tag 标签: verilog教程

相关博文
  • 热度 18
    2012-11-4 03:04
    4059 次阅读|
    0 个评论
    wire 和reg才是精干 虽说变量数据类型可以变出很多,但是领导群雄的只有两大门派,一个是wire型,另一个就是reg型,他们才是精干,和他们打交道的机会也是最多的。任何时候,结识一个群体的核心是比较重要的。接下我们就着重就说说这两大门派。 wire型 我该如何声明wire型 wire型数据该如何表示呢?wire型信号的声明是有一定的格式的。 其格式为: 数据类型标示符(wire)  位宽   数据名列表; 如果一次定义多个数据,数据名之间用逗号隔开,声明语句最后要用分号表示语句结束。例如:          wire a,b,c;   或者          wire a,b,c; //定义了三个n位宽的信号a,b,c wire是wire型数据的标示符; 和 代表该数据的位宽n;a,b,c是数据的名字。 若信号声明时为位宽缺省,其位宽默认为1位。如: wire  a;           //定义了一个1位的wire型数据a 该如何使用wire型 1.wire型信号可以用于任何方程式的输入,也可作为用做“assign“语句的或者实例元件(如门)的输出;如                    wire         ain;                    wire          bout;                    reg      cout;                    assign  bout = ~ ain;// bout作为“assign“语句输出,ain作为输入                    always @(posedge clk)                    begin                             cout= bout+ ain;    // ain 和bout求和方程式的输入                    end          又如:                    wire         ain;                    wire          bout;                             not   uuu(bout,ain);// bout作为非门元件的输出,ain作为输入 2.在verilog HDL程序模块中,输入信号须定义为wire型,同时输入,输出信号若未定义,则默认定义为 wire 类型。   reg型 我该如何声明reg型数据          reg型的变量与wire的声明格式很相似的,可以一次定义多个reg型数据,格式如下:                    数据类型标示符(reg)  位宽   数据名列表;          比如:                    reg a,b,c; //定义了3个名为a,b,c的reg型数据;   “always“的常客 reg型数据常用来表示“always“模块内的制定信号,常代表触发器,同时在“always“模块中被赋值的每一个信号都必须定义成reg型,他是“always“模块中的常客。如 module  sum(ain,bin,cout,dout) input          ain,bin; output   cout; reg bout; always @( ain or bin or  cout) begin          cout= ain+bin;  // bout必须定义成reg型          dout= cout+ ain; //reg型数据(如 cout)也可以作为运算式的输入 end endmodule 从例子可以知道,reg型在“always“模块可以作为运算式的输入,也可作为运算式的输出,但运算式的输出(即等号左边)必须为reg型。 reg型的赋值问题 reg型数据可以赋正值,也可赋负值,但是当reg型作为一个表达式中操作数时,其内部数值会被作为无符号数(也就是正值)处理。如何进行转化呢?reg型变量的数值的进行取反,再加1。比如 reg           b= -5; 那么b中的无符号数值为多少呢?按照上面的方法,5对应的四位宽的二进制数为0101,将其取反就是1010,再加1,就是1011,也就是10进制的11。 另外,reg型数据的缺省的初始值为不定值x。在顶层测试仿真文件中,初始的信号要定义成reg型,比如:clk,rst。模块间的连接信号和模块的输出信号要定义为wire型。 不要以为reg我就是触发器 reg型信号常常是寄存器或触发器的输出,但不能以为reg我就是触发器; 比如: module or_test(          ain,          bin,          cout          ); input ain,bin; output cout; reg cout; always @ (ain or bin or cout) begin          cout = ain | bin; end endmodule 综合后的RTL级电路如下:     这是用“always”块实现的or门电路的模块,reg型cout信号并不是触发器的输出。     memory其实也是reg memory型可以看做reg型变量的数组,是二维的reg,可以用来描述RAM型或ROM型的存储器。memory型数据类型是通过扩展reg型数据的地址范围来生成的。 我该怎么声明memory型变量? memory型有特定的表示格式: reg     存储器名    ; reg  定义了存储器中每一个单元的大小,也就是存储单元的位宽; 定义了存储器中有多少个存储单元,地址范围从0到m-1。地址索引的表达式必须为常数表达式,表达式中可以含有参数常量。如: parameter      memorysize; reg    memory_a ; 例子中定义了名字为memory_a,有memorysize个16位宽的存储单元的存储器。地址从0到memorysize-1。 memory型和reg型数据可以在一起定义,如 reg    memory_a ,reg_b,reg_c; 我该怎么对memory型变量赋值? 对memory型数据不能像reg型数据一样在一条赋值语句里赋值。如 reg reg_a, memory_b ; reg_a=0;   //合法赋值 memory_b=0;  //非法赋值 要想对一个memory型的数据赋值或者进行读写操作,必须通过指定数据变量的地址分别对每个存储单元进行操作。如: memory_b =0; //将memory_b地址为5的存储单元赋值为0 我们应该如何对一个memory型变量所有的单元进行访问或操作?那么我们可以通过访问memory型变量的地址索引来访问该变量的每个单元。 例如: module test_memory_assignment;          reg clk;                                 //时钟          reg  mema ;    //memory型变量          reg add_mema; //地址索引寄存器          reg over; //赋值结束信号 always #1 clk=~clk;           //产生仿真时钟 //地址控制模块 always @(posedge clk) begin          if(add_mema==7over==0)                    begin                             mema =0;                    end          else if(over==0)                    begin                             add_mema=add_mema+1;                              mema =0;                    end          else ; end            initial begin                    //初始化                    clk  = 1;                    over = 0;                    add_mema =0;                             #20;        $stop; //仿真结束函数          end       endmodule   仿真结果如下:   上面的仿真是通过地址索引对memory型变量的单元依次进行初始化。 inout该怎么定义类型 第六章已经讲过模块的端口定义分为input,output和inout是三类。那么inout型的如何使用呢,该怎么定义变量数据类型?前面讲过input只能定义为net型数据, inout型端口也可以作为输入,也同样只能定义为net型数据,一般定义为wire型。 因为inout型变量是输入又是输出,那我们可以用“assign“语句作为inout型变量的驱动源,通过定义一个寄存器io_link作为选择inout口方向,若将io_link置1,则代表为output,若io_link置为0则代表input口。 还是举个例子吧:          inout io_data;      //inout口          reg out_data;     //需要输出的数据          reg io_link;               //inout口方向控制,1为输出,0为输入          assign  io_data = io_link ? out_data:1'bz;   //这个是关键,没用是一定要拉三态 切记:在没有作为输出时,一定要把它置为高阻态z,别“占着茅坑不拉屎”,只有这样才可以把inout口当作平常的input口用了。