结构语句主要是initial语句和always语句,initial 语句它在模块中只执行一次,而always语句则不断重复执行,以下是一个比较好解释的图:
(图片来源于知乎博主罗成,画的很好很直观!)
initial 语句它在模块中只执行一次。
它常用于测试文件的编写,用来产生仿真测试信号(激励信号),或者用于对存储器变量赋初值。
语法格式:
initial begin
...
endPS:当initial与语句内只有一个执行语句时,可以省略begin..end。
always 语句一直在不断地重复活动,但是只有和一定的时间控制结合在一起才有作用。
语法格式:
(1)满足条件才重复执行
always @ (敏感列表) begin
...
end(2)不用满足条件,执行完一次后立马执行下一次,一直重复执行
always begin
...
end
PS:敏感列表即触发always语句执行的条件,多个触发条件用or连接。同样,当always语句内只有一个执行语句时,可以省略begin..end。
always语句可用于组合逻辑也可用于时序逻辑,电平触发往往是组合逻辑,边沿触发往往是时序逻辑,因此可进一步细分:
(1)电平触发——组合逻辑:
这个程序表示每当信号abcdefghm的值(即电平变化)发生变化时,always块中的所有语句都会被执行 。
如果组合逻辑块语句的输入变量很多,可简写以下形式,@(*)表示对后面语句块中所有输入变量的变化都是敏感的(即所有变量有任何一个变化就执行always语句。)
(2)边沿触发——时序逻辑:
当检测到边沿时,执行always语句,如:
posedge 和 negedge为关键字,分别表示上升沿和下降沿,这个程序表示当 sys_clk为上升沿或者 sys_ret_n为下降沿时,执行always语句。
上一章我们说到Verilog基本程序框架中always和assign都可用来描述逻辑功能,以下说一下两者的区别:
(1) assign使用语法:
由于上面已经详细讲了always语句的语法,这里就只讲assign得语法
assign ...
(...后面为描述逻辑的语句)
(2)区别:
特性 | assign |
always |
---|---|---|
适用范围 | 组合逻辑 | 时序逻辑+组合逻辑 |
信号类型 | 只能用于 wire 类型信号 |
可用于 reg 类型信号 |
工作机制 | 实时赋值,连续赋值 | 依赖敏感度列表,通常与时钟事件相关 |
描述对象 | 组合逻辑电路 | 时序逻辑(如寄存器、触发器)和组合逻辑 |
assign只能用于wire信号,相当于连线,一般是将一个变量的值不间断地赋值给另一个变量,对应的被赋值变量为wire型,只要输入有变化,输出马上有反应。
而always是只有当always@(*)敏感列表发生变化,才执行赋值等操作。
(这两句话大家可以慢慢get一下)。
理解:
initial语句中定义了三个信号,sys_clk,sys_rst_n, touch_key,以sys_rst_n, touch_key为例,波形图对应为第二行和第三行。以下操作只执行了一次。
always语句则不断重复操作,每延迟10ns,sys_clk就取反一次,故波形图上(第一行)对应为产生一个周期信号。
阻塞赋值可以认为只有一个步骤的操作:即计算 RHS 并更新LHS(RHS为式子右边,LHS为式子左边)。
所谓阻塞的概念是指,在同一个always块中:后面的赋值语句是在前一句赋值语句结束后才开始赋值的。
以上例子理解:
当clk信号为上升沿或者rest_n信号处于下降沿时,执行操作。
非阻塞赋值的操作过程可以看作两个步骤:(1)赋值开始的时候,计算RHS;(2)赋值结束的时候,更新LHS
非阻塞赋值可以理解为:第一条非阻塞赋值语句开始时,所有非阻塞语句同时赋值计算好对应的RHS并保存放置一边,全部计算好后,再将各自保存好的RHS传递到对应的LHS中。
非阻寒赋值只能用于对寄存器类型的变量进行赋值:因此只能用在initial块和always块等过程块中。
以上例子与1.1.1中例子只有阻塞赋值与非阻塞赋值的区别:
同理,当clk信号为上升沿或者rest_n信号处于下降沿时,执行操作。
条件语句必须在过程块语句中使用,即是指由initial和always语向引导的块语句。
使用方法类似于C语言。
case (
)
case1 : ... ;
case2: ... ;
case3 : ... ;
case4 : begin
;
end
default:;
endcase
语法解释:
- 其中,case1~case4这些写的是情况1~4,或者说是看
符合case1~case4的哪一种情况,对应进入执行该情况; - default表示如果没有expression没有匹配的 case 情况,执行 default 语句;
- 看case4知,如果情况中有多个执行语句,用begin..end来写。
注意点:
除此之外还有另外两种表达:casez...endcase和casex...endcase。
casez不考虑表达式中的高阻值比较时;casex:不考虑高阻值之和不定值x。
例如:以下例子判定sel的值是否满足以下哪种情况,情况1是8’b1100_zzzz,其中后四位“zzzz”为高阻值不用考虑,即只需要看前4位是否与sel的值相匹配;情况2是8’b1100_xxzz,后两位才是高阻值不用考虑,看前6位是否与sel匹配。sel=1100_0011,可知前4位与情况1匹配,前6位与情况2不匹配,故进入情况1。