记录翀翀🥺学习数字逻辑与数字系统的核心笔记与思考,由于这门课程和计算机系统基础的知识点联系性较强,可以作为408机组原理的补充学习。这里分享一段话:要么出众,要么出局,乾坤未定,你我皆是黑马,同是寒窗苦读,怎愿甘拜下风。
行为建模
在SystemVerilog HDL中,行为建模是指将数字逻辑电路的功能以较高的抽象形式描述出来,他通过输入和输出之间的因果关系直接建立电路模型,行为建模包括两种描述风格:
- 基于持续赋值语句(assign)的建模
- 基于过程块(always和initial)的建模
基于过程块语句的建模相比基于持续赋值语句的建模具有更高的抽象层次,编程也更加便捷。
基于持续赋值语句的建模
基于持续赋值语句的建模是指根据信号量之间的逻辑关系,采用持续赋值语句(assign)描述数字逻辑电路的方式,也称为数据流建模,其使用方法如下:
1 | assign <#延迟量> 信号名=逻辑表达式//<#延迟量>可以缺省 |
比如:
1 | logic [3:0]out1,out2,A,B; |
我们注意到行为建模语句主要是基于已经定义的变量,来定义输入变量和输出变量之间的某种关系,即为行为建模。基于持续赋值语句的建模的特点是只要“=”右侧表达式中的任意变量发生变化,那么这个表达式就会立即重新计算并赋值给左边的变量。如果定义了延迟量,那么赋值将在相应的单位时间内(默认为纳秒,ns)后再完成。
一定要注意延迟量主要用于仿真,是不可以综合的。
并且持续赋值语句左侧可以是变量类型(如logic)的信号,也可以是线网类型(如tri)信号,也可以是信号的拼接形式。对于持续赋值语句,任何输入的变化都会立即影响输出结果,体现了组合逻辑电路的特征,即变化瞬时性,因此,基于持续赋值语句的建模只能用来描绘组合逻辑电路。而且基于持续赋值语句的建模方式提供了使用逻辑表达式描述电路的一种方式,不必考虑电路的组成结构以及元组之间的连接。
刚刚上面我们已经给出了基于持续赋值语句的建模例子了,建模语句主要是用来描述信号之间的行为关系,下面我们给出基于持续赋值语句的建模模板:
1 | module 模块名 (端口列表); |
下面我们以一道例题来讲解如何进行基于赋值语句的建模,我们这里以译码器为例,我们前面学习过译码器是根据接收的信号所组成的编号,从而让特定的输出信号输出高电平真值。比如2线-4线译码器:
我们可以根据真值表列出不同信号取真值的表达式(简单的当然也可以使用卡诺图进行简化),然后定义译码器模块来进行建模:
1 | module dec2to4(input EN,A,output Y); |
当然我们还可以通过这个方法来实现机组原理中讲到的一位全加器:
他的建模语言代码如下:
1 | module fulladder(A,B,cin,sum,cout); |
如果我们在基于持续赋值建模中的代码中使用了延迟量,那么虽然最后得到的电路完全相同,但是在仿真综合时是会出现不同的结果的,我们前面学习了最终仿真综合平台的结果会以脉冲的形式显示在图上,那么当增加了延迟后,脉冲出现的时间就会发生改变,如下:
未加延迟量的结果:
增加了延迟量的结果:
基于过程块的建模
前面我们介绍了基于持续赋值语句的建模方式,接下来我们来学习一下另一种建模方式—基于过程块的建模。基于过程块的建模关注数字逻辑电路输入输出的因果关系(行为特性),即在何种输入条件下,产生何种输出(即完成什么操作),并不关注电路的内部结构细节。这种建模适用于规模庞大、复杂的电路设计,配合EDA工具,构成了现代超大规模集成电路(VISI)的设计基础。
基于过程块的建模使用关键字initial和always定义,通过块标识符begin…end(相当于大括号)包围起来的过程块对电路进行描述。initial主要用于仿真验证,always则主要用于电路建模,也可以用于仿真。always过程块是一个无限循环,每一个always块描述了一个独立的电路功能。
always过程块分为三中类型:always_comb(描述组合逻辑),always_ff和always_latch(描述时序逻辑)。这里我们主要关注always_comb。他的代码模板如下:
1 | module 模块名 (端口列表); |
基于过程块的建模最重要的就是一定记住块标识符类型的声明以及begin…end包裹。这里我们给出二路选择器的建模板子:
我们发现上面的代码中是使用条件语句结构推动描述某几个信号之间的因果关系来进行行为建模的,但是仅仅使用条件语句明显是无法完成建模行为描述的,他也可以像基于持续赋值语句建模一样使用过程赋值语句即对某些变量信号进行赋值,但是他不需要使用assign声明,并且“=”左边的信号必须是变量类型(如logic类型),并且不能是线网类型,“=”右边的信号的类型无限制。如下:
1 | module adder(input a,b,cin,output[1:0] out); |