FPGA学习篇——Verilog学习4

1.1 结构语句

结构语句主要是initial语句和always语句, initial 语句它在模块中只执行一次,而always语句则不断重复执行,以下是一个比较好解释的图:

(图片来源于知乎博主罗成,画的很好很直观!)

1.1.1 initial语句

initial 语句它在模块中只执行一次

它常用于测试文件的编写,用来产生仿真测试信号(激励信号),或者用于对存储器变量赋初值。

语法格式:

initial begin ...
end

PS:当initial与语句内只有一个执行语句时,可以省略begin..end。

1.1.2 always语句

always 语句一直在不断地重复活动,但是只有和一定的时间控制结合在一起才有作用。

语法格式:

always @ ( 敏感列表**) begin
...
end**


PS:敏感列表即触发always语句执行的条件,多个触发条件用or连接。同样,当always语句内只有一个执行语句时,可以省略begin..end。


always语句可用于组合逻辑也可用于时序逻辑,电平触发往往是组合逻辑,边沿触发往往是时序逻辑,因此可进一步细分:

(1)电平触发------组合逻辑:

这个程序表示每当信号abcdefghm的值(即电平变化)发生变化时,always块中的所有语句都会被执行 。

如果组合逻辑块语句的输入变量很多,可简写以下形式,@(*)表示对后面语句块中所有输入变量的变化都是敏感的(即所有变量有任何一个变化就执行always语句。)

(2)边沿触发------时序逻辑:

当检测到边沿时,执行always语句,如:

posedge 和 negedge为关键字,分别表示上升沿和下降沿,这个程序表示当 sys_clk为上升沿或者 sys_ret_n为下降沿时,执行always语句。

1.1.3 实例理解

理解:

initial语句中定义了三个信号,sys_clk,sys_rst_n, touch_key,以sys_rst_n, touch_key为例,波形图对应为第二行和第三行。以下操作只执行了一次。

  • 首先sys_rst_n, touch_key均赋值为0(程序从注释开始算第3行和第5行);
  • 代码第6行,延迟20ns后,sys_rst_n赋值为1,对应于波形图中红色线(20ns时刻)时sys_rst_n信号由低电平跳变至高电平。
  • 代码第7行,又延迟10ns后,即30ns处(蓝色线),touch_key赋值为1
  • 代码第8~10行,touch_key类似操作。

always语句则不断重复操作,每延迟10ns,sys_clk就取反一次,故波形图上(第一行)对应为产生一个周期信号。

1.2 赋值语句

1.2.1 阻塞赋值 " = "

阻塞赋值可以认为只有一个步骤的操作:即计算 RHS 并更新LHS(RHS为式子右边,LHS为式子左边)。

所谓阻塞的概念是指,在同一个always块中:后面的赋值语句是在前一句赋值语句结束后才开始赋值的。

以上例子理解:

当clk信号为上升沿或者rest_n信号处于下降沿时,执行操作。

  • 在波形图部分,从-6时刻开始,直接clk信号上升沿,且满足rest_n为低电平,执行if语句,故abc分别赋值为1,2,3。
  • 然后 -6 ~ 0时刻,rest_n恒为低电平,每到clk信号上升沿,执行操作中if语句,故-6 ~ 0时刻abc值恒为1,2,3。
  • 0时刻时,rest_n跳变为高电平,是上升沿不是下降沿,故不执行操作。
  • 0时刻后,rest_n恒为高电平,clk信号第一个上升沿为2时刻,执行操作,此时不满足if语句(rest_n为高电平),则执行else语句。由于赋值语句是在前一句赋值语句结束后才开始赋值的,故a=0执行完后,b = a = 0执行完, 在执行c = b = 0;
  • 2时刻后rest_n恒为高电平,每到clk信号上升沿,执行操作中else语句,故此后abc值都为0。

1.2.2 非阻塞赋值 " <="

非阻塞赋值的操作过程可以看作两个步骤:(1)赋值开始的时候,计算RHS;(2)赋值结束的时候,更新LHS

非阻塞赋值可以理解为:第一条非阻塞赋值语句开始时,所有非阻塞语句同时赋值计算好对应的RHS并保存放置一边,全部计算好后,再将各自保存好的RHS传递到对应的LHS中。

非阻寒赋值只能用于对寄存器类型的变量进行赋值:因此只能用在initial块和always块等过程块中。

以上例子与1.1.1中例子只有阻塞赋值与非阻塞赋值的区别:

同理,当clk信号为上升沿或者rest_n信号处于下降沿时,执行操作。

  • 在波形图部分,从-6时刻开始,直接clk信号上升沿,且满足rest_n为低电平,执行if语句,赋值语句右边为1,2,3然后对应赋值到abc上。
  • 然后 -6 ~ 0时刻,rest_n恒为低电平,每到clk信号上升沿,执行操作中if语句,故-6 ~ 0时刻abc值恒为1,2,3。
  • 0时刻时,rest_n跳变为高电平,是上升沿不是下降沿,故不执行操作。
  • 0时刻后,rest_n恒为高电平,clk信号第一个上升沿为2时刻,执行操作,此时不满足if语句(rest_n为高电平),则执行else语句。赋值语句右边0,a(值为1),b(值为2)【由于此时ab值为临近2时刻的值】,则对应将其赋值到abc上得到a=0,b=1,c=2**。**
  • 2时刻后rest_n恒为高电平,4时刻又到了clk信号上升沿,执行操作中else语句,。赋值语句右边0,a(值为0),b(值为1)【由于此时ab值为临近4时刻的值】,则对应将其赋值到abc上得到a=0,b=0,c=1;
  • 2时刻后rest_n恒为高电平,6时刻又到了clk信号上升沿,执行操作中else语句。赋值语句右边0,a(值为0),b(值为0)【由于此时ab值为临近6时刻的值】,则对应将其赋值到abc上得到a=0,b=0,c=0;
  • 此后,abc都为0,按照非阻塞也为0了。

1.3 条件语句

条件语句必须在过程块语句中使用,即是指由initial和always语向引导的块语句。

1.3.1 if语句

使用方法类似于C语言。

  • 允许一定形式的简写, if(a) 等同于 if(a==1);if(!a) 等同于 if(a!=1)
  • if语句对表达式的值进行判断,若为0,x,z则按假处理:若为1,按真处理:
  • if和else后面的操作语句可以用begin和end包含多个语句。
  • 允许if语句的嵌套。

1.3.2 case语句

case (<expression>)

case1 : ...

case2: ...

case3 : ...

case4 : begin

<multiple statements>

end

default: <statement>
endcase


语法解释:

  • 其中,case1~case4这些写的是情况1~4,或者说是看<expression>符合case1~case4的哪一种情况,对应进入执行该情况;
  • default表示如果没有expression没有匹配的 case 情况,执行 default 语句;
  • 看case4知,如果情况中有多个执行语句,用begin..end来写。

注意点:

  • 分支表达式的值互不相同(即每种情况应不同,不然编译会出现矛盾)
  • 所有表达式的位宽必须相等不能用:bx 来代替:n'bx

除此之外还有另外两种表达: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。

相关推荐
西岸行者4 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
ZPC82104 天前
docker 镜像备份
人工智能·算法·fpga开发·机器人
ZPC82104 天前
docker 使用GUI ROS2
人工智能·算法·fpga开发·机器人
悠哉悠哉愿意4 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码4 天前
嵌入式学习路线
学习
毛小茛4 天前
计算机系统概论——校验码
学习
babe小鑫4 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms4 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下4 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。4 天前
2026.2.25监控学习
学习