前言
本文笔者将为大家详细的介绍Verilog的三种语句介绍,包括结构语句,赋值语句和条件语句
一、结构语句
1、initial语句
initial语句只执行一次.
常用于测试文件(testbench)的编写,用来产生仿真测试信号的语句(激励信号),或者用于对存储器变量赋初值.
initial
begin
sys_clk <= 1'b0;
sys_rst_n <= 1'b0;
touch_key <= 1'b0;
#20 sys_rst_n <= 1'b1;
#10 touch_key <= 1'b1;
#30 touch_key <= 1'b0;
#110 touch_key <= 1'b1;
#30 touch_key <= 1'b0;
end
2、always 语句
1.一直在不断的重复使用,但只有和一定的时间控制结合在一起才有作用
2.always的时间控制可以是边沿触发,也可以是电平触发;
3.可以是单个信号,也可以是多个信号,多个信号中间要用关键字or连接
4.always语句后紧跟的过程块是否运行,要看他的触发条件是否满足
举例
//计数器对系统时钟计数,计时0.2s
always @(posedge sys_clk or negedge sys_rst_n)//关键字 posedeg上升沿 ,negedge下降沿
begin
if(!sys_rst_n)
counter <= 24'd0;
else if(counter < 24'd1000_0000)
counter <= counter + 1'b1;
else
counter <= 24'd0;
end
5.边沿触发的always块常常描述时序逻辑行为.
6.由关键词or连接的多个事件名或信号名组成的列表为"敏感列表"
7.always和initial语句下的begin–end语句是按顺序执行的,称为过程块
8.电平触发的always块用于描述组合逻辑行为
always @(*)
begin
out1 = a? (b+c) : (d+e);
out2 = f? (g+h) : (p+m);
end
@(*)表示对后面语句块中所有输入变量的变化都是敏感的
二、赋值语句
1.阻塞赋值
(blocking) b=a;
稍微阻塞的概念是,在同一个always块中,后面的赋值语句是在前一句赋值语句结束后才开始赋值的
阻塞赋值可以认为只有一个步骤的操作:两个同时计算
即计算RHS并更新LHS
举例
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
a = 1;
b = 2;
c = 3;
end
else
begin
a = 0;
b = a;
c = b;
end
end
2.非阻塞赋值
(Non_blocking) b<=a;
稍微非阻塞赋值的概念是,在计算非阻塞赋值的RHS以及更新LHS期间,允许其他的非阻塞赋值语句同时计算RHS和更新LHS
非阻塞赋值的操作过程可以看作两个步骤,分步进行计算
1:赋值开始的时候,计算RHS;
2:赋值结束的时候,更新LHS;
举例
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
a <= 1;
b <= 2;
c <= 3;
end
else
begin
a <= 0;
b <= a;
c <= b;
end
end
需要注意的是:
非阻塞赋值只能用于对寄存器类型的变量进行赋值,因此只能用在initial和always块等过程块中
3.总结
读者可能会觉得难以理解,为此,笔者做了一下总结
在描述组合逻辑时–always块用阻塞赋值 “=”
在描述时序逻辑时–always块用非阻塞赋值"<="
注意:
1.在同一个always块不要既用非阻塞赋值,又用阻塞赋值;
2.不允许在多个always块中对用一个变量进行赋值
三、条件语句
1 if_else语句
和c语言类似
if(表达式1)
语句1;
else if(表达式2)
语句2;
else if(表达式3)
语句3;
else
语句4;
条件语句必须在过程块中使用,即在always和initial语句中使用;
注意事项
1.允许缩写
if(a) 等同于 if(a == 1)
2.if 语句对表达式的值进行判断时:
若为 0 x z 则为假
若为 1 则为真
3.if和else后面的操作语句可以用begin–end包含多个语句
4.if语句可以嵌套
2.case 语句
多分支选择语句
注意
1.分支表达式的值互不相同;
2.所有表达式的位宽必须相等;
不能用’bx来代替n’bx
3.casez
比较时,不考虑表达式中的高阻值
4.casex
不考虑高阻值z和不定值x
//根据数码管显示的数值,控制段选信号
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
seg_led <= 8'b0;
else
begin
case(num)
4'h0 : seg_led <= 8'b1100_0000;
4'h1 : seg_led <= 8'b1111_1001;
4'h2 : seg_led <= 8'b1010_0100;
//.....笔者省略了一部分代码,如有需要,可在评论区问我
default : seg_led <= 8'b1100_0000;
endcase
end
end
reg [7:0] sel;//1100_0011
casez(sel)
8'b1100_zzzz;语句1; //执行语句1
8'b1100_xxzz;语句2; //不执行语句2,若将casez改为casex,则需要执行语句2