Verilog HDL基本语法
1、变量类型
wire,reg
wire 线型,用于数据传输,两信号的连接,用assign赋值。
reg 存储器型,用于寄存器、锁存器、查找表。用always initial赋值。
2、时序电路与组合电路的区别
时序电路:
赋值符号 <= 非阻塞赋值,解释:不受信号延时的影响,输出的结果不受输入信号延时的影响,只根据时钟上升沿或者下降沿变化。
组合电路:
赋值符号 = 阻塞赋值,解释:输出的结果受输入信号延时的影响。
3、时序电路时钟
时序电路,在时钟的上升沿或者下降沿到来时,将触发器D端的数据传输到Q端。
时钟的占空比通常为50%。
4、内部信号上电的默认值定义
例如:reg[7:0] counter = 8'd255;
解释:FPGA一上电,将counter信号赋初始值为8位的十进制数255。
只有reg信号且是寄存器才可以赋初始值。
wire变量不可以,而且reg组合逻辑也不可以赋初始值。
一个信号若不指定位宽,则默认位宽为32位的十进制数。
5、信号位宽的参数化
例如:parameter W = 8;
reg[W-1: 0] counter;
6、赋值语句
用在可综合的:always、assign(功能文件)
用在非可综合的:initial(testbench)
7、组合逻辑与时序逻辑的区别
组合逻辑:不需要时钟,生成组合电路
时序逻辑:有时序节拍,根据时钟延变化,受寄存器节拍控制。
8、运算符
(+、-、*、/、%)加减乘除和取余。
(+、-)可以直接使用
(*、/)调用IP核,%求余数偶尔用一下,这三个符合直接用的话会占用很多的逻辑资源。
!a 等价于 a == 0
reg[1:0] a = 2'b10; 则:&a = a[1] & a[0] = 1 & 0 = 0;
reg[2:0] b = 3'b110; 则:&b = b[2] & b[1] = b[0] = 1 & 1 & 0 = 0;
9、三目运算符(既可用于assign语句,也可用于always语句)
assign a = (b > 6)? 1'b1: 1'b0;
可嵌套:assign a = (b > 6)? 1'b1 : (b < 5)? 1'b1: 1'b0;
10、移位运算符:
>> 右移运算符 每次右移一位,数据高位补0
<< 左移运算符 每次左移一位,数据低位补0
例如:
reg [3:0] a = 4'b0110;
b <= (a >> 1'b1); 则 b 的值为4'b0011;
c <= (a << 1'b1); 则 c 的值为4'b1100;
11、左移位循环可以用以下两种方式实现
(1)用位拼接实现
(2)左移位+判断条件
12、条件判断语句
(1)if...else 最好不大于8级,在模块中顺序执行,上面条件满足则不再执行下面的语句,组合逻辑中最好使用else结束,否则会生成锁存器。
(2)case...endcase 并行执行,最好带有一个default语句,避免有些条件没有列出来。
两个寄存器之间延时较大,容易产生时序违例,时序违例是指:由于延时较大,上一时刻发送的数据,下一时刻采集不到,导致出错。
时序电路不会产生锁存器,组合电路才可能产生锁存器。
13、补充知识:
(1)8位 0~255 激励数据产生的方法:{$random}%256.
(2)如下左图所示,如果敏感列表中触发电平不全,会导致产生锁存器。保险起见,如果用always语句产生组合电路,敏感列表中的信号用*代替,如下右图所示。
(3)xilinx 建议使用同步的高电平复位,altera建议使用异步的低电平复位