Verilog HDL数据流建模与运算符
数据流建模使用的连续赋值语句由关键词assign
开始,一般用法如下:
wire [位宽说明]变量名1, 变量名2, ..., 变量名n;
assign 变量名 = 表达式;
只要等号右边的值发生变化,则立即更新等号左边的值。
注意,连续赋值语句只能对wire
型变量进行赋值,所以等号左边必须是wire
型。
把2线-4线译码器用数据流描述风格的代码写出来就是:
module Decoder2x4_gates(
input [1:0]A,
input En,
output [3:0]Y);
assign Y[0] = ~(~A[1] & ~A[0] & En);
assign Y[1] = ~(~A[1] & A[0] & En);
assign Y[2] = ~(A[1] & ~A[0] & En);
assign Y[3] = ~(A[1] & A[0] & En);
endmodule
然后就是介绍数据流风格中设计的运算符了。
1.算数运算符+ - * / %(取余) **(指数)
(1)进行算数运算符时,如果某个操作数中某一位是x
或者z
,那么整个表达式运算结果也是x
,例如`b101x + `b0111 = `bxxxx。
(2)取余后,余数的符号与第一个操作数的符号相同。例如:-7%2 = -1
,7%-2=+1
,8%4=0
。
2.关系运算符< > <= >=
(1)结果为真1或者假0。
(2)如果操作数中有一个为x
或者z
,那么结果为x
。
(3)两个有符号数进行比较时,如果操作数位宽不同,那么用符号位将位数较小操作数的位数补齐。例如:
4'sb1011 <= 8'sh1A //等价于8'sb1111_1011 <= 8'sh1A = 8'sb0001_1010,结果为1.
(4)如果表达式有一个操作数为无符号数,则该表达式的其余操作数均被当作无符号处理。例如:
(4'sd9 * 4'd2) < 4 //18 < 4, 结果为假0。
(4'sd9 * 2) < 4 //-7 * 2 < 4,结果为真1.
3.相等运算符==(逻辑相等), !=(逻辑不等), ===(条件全等), !==(条件不全等)
(1)对于==
和!=
,会逐位比较两个操作数相应位的值是否相等,如果都相等则相等关系成立,如果有一位是x
或z
,那么结果为x
。
(2)而===
和!==
,允许操作数某些位为x
或z
,例如:
0 === x为0
0 === z为0
1 === x为0
1 === z为0
x === x为0
x === z为0
z === z为0
z === x为0
4.逻辑运算符!, &&, ||
需要注意的是,如果操作数中有一位是x
或者z
,那么运算结果为x
,而仿真器一般将其作为假处理。其他都与C语言一样。
5.按位运算符~, &, |, ^, ^~(同或)
(1)如果两个操作数位宽不相等,仿真软件自动将短操作数的左端高位部分以0补足,如果最高位为x,那么补x。
(2)如果操作数中的某一位是x
或者z
,那么结果的那一位为x
。
6.缩位运算符&, ~&(缩位与非), |, ~|(缩位或非), ^, ^~
都只有一个操作数,操作数从右边位一次往左边每一位运算,例如reg [3:0]A
,那么运算规则为A[1]与A[0],然后这个结果再与A[2],然后再与A[3]运算,最后得到的结果为1位。
7.移位运算符<<(左移), >>(右移), <<<(算数左移), >>>(算数右移)
。
(1)逻辑移位,当移位后,所产生的空余位总是0填充。
(2)算数移位,向左移动时,空余位用0补充;向右移动时,如果是无符号数,那么用0补充,否则用符号位补充。
8.条件运算符,用法如下:
condition_expr ? true_expr : false_expr;
9.拼接和复制运算符
拼接运算符{}
,要求每个操作数必须有确定位宽。
reg A;
reg [1:0]B, C;
A=1'b1, B=2'b00, C=2'b10;
Y={B,C};
Y={A,B[0],C[1],1'b1};
Z={A,B,5}; //非法,5的位宽不确定。
如果需要多次拼接,直接再{}
前加一个数,就是拼接几次。
reg A;
reg [1:0]B, C;
A=1'b1, B=2'b00, C=2'b10;
Y={4{A}}; //把A复制4次
Y={2{A},2{B},C}; //把A复制2次,把B复制2次,然后与C拼接一起
重复的次数可以参数化,例如:
parameter LENGTH=8;
Y = {LENGTH{1'B0}};
10.运算符优先级
感觉没太有必要记,加括号就完事了。。。