Verilog HDL语法

  1. 算数运算符:+ – * / %(取模)
  2. 赋值运算符 =(堵塞) <=(非堵塞)
  3. 关系运算符 > ,< , >= , <= , ==:逻辑相等, !=:逻辑不等,===:全等;!==:不全等 “===”和”!==”可以比较含有x和z的操作数,在模块的功能仿真中有着广泛的应用。
  4. 逻辑运算符: && || !
  5. 位运算符: 按位 & | !~ ,^按位异或 ,^~ 按位同或
  6. 条件运算符: ?: r=s?t:u
  7. 移位运算符: << >>
  8. 拼接运算符: {信号1的某几位,信号2的某几位,信号3的某几位….} 2{信号的某几位} 表示{}中的信号重复2次
  9. 缩减运算符: 单目运算符 &,|,~ : c= &b 指的是b的前一位&后一位,知道最终只剩下一个bit

Vector:

type [upper:lower] vector_name;

如果声明vector时候指定了vector方向 [8:0] 高到低,那么在使用该vector时,也要从高到低指定:[3:0] [4:1]

向量的字节顺序(或非正式地称为“方向”)是指最低有效位是具有较低的索引(较小的字节序,例如[3:0])还是具有较高的索引(较大的字节序,例如[[ 0:3])。在Verilog中,一旦以特定的字节序声明了向量,就必须始终以相同的方式使用它。例如,声明vec[0:3]时写是非法的。与字节序一致是一种好习惯,因为如果将不同字节序的向量一起分配或使用,则会发生奇怪的错误。

wire [7:0] w;         // 8-bit wire
reg  [4:1] x;         // 4-bit reg
output reg [0:0] y;   // 1-bit reg that is also an output port (this is still a vector)
input wire [3:-2] z;  // 6-bit wire input (negative ranges are allowed)
output [3:0] a;       // 4-bit output wire. Type is 'wire' unless specified otherwise.
wire [0:7] b;         // 8-bit wire where b[0] is the most-significant bit.
wire [2:0] a, c;   // Two vectors
assign a = 3'b101;  // a = 101
assign b = a;       // b =   1  implicitly-created wire
assign c = b;       // c = 001  <-- bug
my_module i1 (d,e); // d and e are implicitly one-bit wide if not declared.
                    // This could be a bug if the port was intended to be a vector.

Adding `default_nettype none would make the second line of code an error, which makes the bug more visible.
assign w = a;
takes the entire 4-bit vector a and assigns it to the entire 8-bit vector w (declarations are taken from above). If the lengths of the right and left sides don't match, it is zero-extended or truncated as appropriate.

wire 和 reg 的区别和使用:

wire表示直通,即输入有变化,输出马上无条件地反映(如与、非门的简单连接)。

reg表示一定要有触发,输出才会反映输入的状态。

reg相当于存储单元,wire相当于物理连线。reg表示一定要有触发,没有输入的时候可以保持原来的值,但不直接实际的硬件电路对应。

      两者的区别是:寄存器型数据保持最后一次的赋值,而线型数据需要持续的驱动。wire使用在连续赋值语句中,而reg使用在过程赋值语句(initial ,always)中。wire若无驱动器连接,其值为z,reg默认初始值为不定值 x 。

     在连续赋值语句中,表达式右侧的计算结果可以立即更新表达式的左侧。在理解上,相当于一个逻辑之后直接连了一条线,这个逻辑对应于表达式的右侧,而这条线就对应于wire。在过程赋值语句中,表达式右侧的计算结果在某种条件的触发下放到一个变量当中,而这个变量可以声明成reg类型的。根据触发条件的不同,过程赋值语句可以建模不同的硬件结构:如果这个条件是时钟的上升沿或下降沿,那么这个硬件模型就是一个触发器;如果这个条件是某一信号的高电平或低电平,那么这个硬件模型就是一个锁存器;如果这个条件是赋值语句右侧任意操作数的变化,那么这个硬件模型就是一个组合逻辑。

      对组合逻辑输出变量,可以直接用assign。即如果不指定为reg类型,那么就默认为1位wire类型,故无需指定1位wire类型的变量。当然专门指定出wire类型,可能是多位或为使程序易读。wire只能被assign连续赋值,reg只能在initial和always中赋值。

      输入端口可以由wire/reg驱动,但输入端口只能是wire;输出端口可以是wire/reg类型,输出端口只能驱动wire;若输出端口在过程块中赋值则为reg型,若在过程块外赋值则为net型(wire/tri)。用关键词inout声明一个双向端口, inout端口不能声明为reg类型,只能是wire类型。

      默认信号是wire类型,reg类型要申明。这里所说的默认是指输出信号申明成output时为wire。如果是模块内部信号,必须申明成wire或者reg.

      对于always语句而言,赋值要申明成reg,连续赋值assign的时候要用wire。

模块调用时 信号类型确定方法总结如下:

•信号可以分为端口信号和内部信号。出现在端口列表中的信号是端口信号,其它的信号为内部信号。

•对于端口信号,输入端口只能是net类型。输出端口可以是net类型,也可以是register类型。若输出端口在过程块中赋值则为register类型;若在过程块外赋值(包括实例化语句),则为net类型。

•内部信号类型与输出端口相同,可以是net或register类型。判断方法也与输出端口相同。若在过程块中赋值,则为register类型;若在过程块外赋值,则为net类型。

•若信号既需要在过程块中赋值,又需要在过程块外赋值。这种情况是有可能出现的,如决断信号。这时需要一个中间信号转换。

下面所列是常出的错误及相应的错误信息(error message)

•用过程语句给一个net类型的或忘记声明类型的信号赋值。

           信息:illegal …… assignment.

•将实例的输出连接到声明为register类型的信号上。

           信息:<name> has illegal output port specification.

•将模块的输入信号声明为register类型。

case 、casex和casez的区别

用法:

case(in)
 2'b00:out = 0;
 2'b01:out = 1;
 2'b10:out = 2;
 2'b11:out = 3;
endcase

casex: 该语句不考虑高阻值z以及不定值x,即在表达式进行 比较时,不会比较x、z所在位的状态:in = 001 c = xx1 那么 in在case语句中等于c,因为不考虑x位,只需要比较最后一位 1=1


//要实现 如果in的第一个1出现的位置 in == 000 则out = 0  in = 101则out =1  in =111  则out仍是1
case(in)
 2'bxx1:out = 3;
 2'bx1x:out = 2;
 2'b1xx:out = 1;
 2'b000:out = 0
endcase

同理 casez 该语句不考虑高阻值z , 即在表达式进行 比较时,不会比较z所在位的状态

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注