数字系统设计复习笔记:第二篇
赋值语句
我说这个必考,因为真会考。
阻塞赋值
使用=
进行。
- 赋值语句执行完后,块才结束;
- b 的值在赋值语句执行完后立刻就改变的;
- 在时序逻辑中使用时,可能会产生意想不到的结果。
1 | reg b,c; |
有的仿真器可以综合成D触发器,但是不推荐。
在 三段式状态机 中,描述次态逻辑和输出逻辑的电路必须使用阻塞赋值,表明为组合电路。
非阻塞赋值
使用<=
进行赋值。
- 在语句块中,上面语句所赋的变量值不能立即就为下面的语句所用;
- 块结束后才能完成这次赋值操作,而所赋的变量值是上次赋值得到的;
- 在编写可综合的时序逻辑模块时,这是最常用的赋值方法。
例:下面代码会发生什么?
1 | always @(posedge clk) |
答案
这俩会交换位置。因为:
- 在时钟沿到来前,两个表达式并行运算,已经确定好结果;
- 时钟沿到来时,a和b被赋值。
块语句
顺序块
使用begin...end
的块是顺序块,通常用来标识顺序执行的语句。
- 块内的语句是按顺序执行的,即只有上面一条语句执行完后下面的语句才能执行。
- 每条语句的延迟时间是相对于前一条语句的仿真时间而言的。
- 直到最后一条语句执行完,程序流程控制才跳出该语句块。
1 | begin [:block_id |
如果在块内用到了临时变量,则必须填写block_id!
并行块
- 块内语句是同时执行的,即程序流程控制一进入到该并行块,块内语句则开始同时并行地执行。
- 块内每条语句的延迟时间是相对于程序流程控制进入到块内的仿真时间的。
- 延迟时间是用来给赋值语句提供执行时序的。
- 当按时间时序排序在最后的语句执行完后或一个 disable 语句执行时,程序流程控制跳出该程序块。
1 | fork [:block_id |
生成块
这一块很少用到,考的话就是冷门点。留个概念就行,平时写代码也可以强迫自己刻意去用(虽然印象中确实用不到)
generate/endgenerate
生成语句可以动态地生成 Verilog 代码。这一声明语句方便了参数化模块的生成。当对矢量中的多个位进行重复操作时,或者当进行多个模块的实例引用的重复操作时,或者在根据参数的定义来确定程序中是否应该包括某段 Verilog 代码的时候,使用生成语句能够大大简化程序的编写过程。
生成实例可以是以下的一个或多种类型:
- 模块
- 用户定义原语
- 门级原语
- 连续赋值语句
- initial 和 always 块
不允许出现在生成范围之中的模块项声明:
- 参数、局部参数
- 输入、输出和输入/输出声明
- 指定块
举个栗子
1 | //本模块生成两条N位总线变量的按位异或 |
生成块用的时候,记得给begin块起名字!
生成块的本质是使用循环内的一条语句来代替多条重复的 Verilog 语句,简化用户的编程。
关键词genvar
用于声明生成变量,生成变量只能用在生成块之中;在确立后的仿真代码中,生成变量是不存在的。
和if..else还有case的连携
1 | /本模块生成N位的加法器 |
块语句的特点
嵌套:块可以嵌套使用, 顺序块和并行块能够混合在一起使用
1 | initial |
命名块:块可以具有自己的名字
禁用块
1 | //从矢量标志寄存器的低有效位开始查找第一个值为1的位 |
为什么要加块名?
- 可以在块内定义局部变量,即只在块内使用的变量。
- 可以允许块被其他语句调用,如 disable 语句。
- 在 Verilog 语言里,所有的变量都是静态的,即所有的变量都只有一个唯一的存储地址,因此进入或跳出块并不影响存储在变量内的值。基于以上原因,块名就提供了一个在任何仿真时刻确认变量值的方法。
条件语句
if...else
没啥好说的,记得带上()
和begin...end
就行。
只能写在过程块里!
如果嵌套使用,必须带上begin...end
!
case
记得写default
,不写可以,多写了不行。多个default语句是非法的。
同样只能用于过程块。
- 每一个 case 分项的分支表达式的值必须互不相同,否则就会出现问题,即对表达式的同一个值,将出现多种执行方案,产生矛盾。
- 执行完 case 分项后的语句,则跳出该 case 语句结构,终止 case 语句的执行。
- 在用 case 语句表达式进行比较的过程中,只有当信号的对应位的值能明确进行比较时,比较才能成功。因此,要注意详细说明 case 分项的分支表达式的值。
- case 语句的所有表达式值的位宽必须相等,只有这样,控制表达式和分支表达式才能进行对应位的比较。一个经常犯的错误是用
ˈbx
,ˈbz
来替代nˈbx
,nˈbz
,这样写是不对的,因为信号 x , z 的默认宽度是机器的字节宽度,通常是 32 位(此处 n 是 case 控制表达式的位宽)。
循环语句
在 VerilogHDL 中存在着 4 种类型的循环语句,用来控制执行语句的执行次数。
- forever 语句:连续的执行语句
- repeat 语句:连续执行一条语句 n 次
- while 语句:执行一条语句直到某个条件不满足。如果一开始条件即不满足(为假),则语句一次也不能被执行
- for 语句:通过以下 3 个步骤来决定语句的循环执行
- 给控制循环次数的变量赋初值
- 判定控制循环的表达式的值,如为假,则跳出循环语句;如为真,则执行指定的语句后,转到下一步
- 执行一条赋值语句来修正控制循环变量次数的变量值,然后返回上一步
forever
forever
必须和时间控制一起使用!否则会陷入无法逃脱的死循环.....
1 | // 生成周期为20的时钟 |
repeat
1 | // 乘法器 |
while
1 | // 对rega中有多少个1进行统计 |
for
1 | // 上面用 repeat 实现的乘法器,用 for 也可以 |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Esing的小站!
评论
WalineGitalk