前不久一位朋友发来一道验证题,虽然题目不是很复杂,但是琢磨了下感觉其中需要掌握的内容还是很多的,正所谓麻雀虽小五脏俱全。下面将对此题涉及的一些内容进行挖掘和示例,与大家分享下。
【问题描述】
如下一段Verilog代码,请根据代码的描述,并结合已知的clk和rst的波形图,画出对应信号的波形。
通过仿真工具得到对应的仿真波形如下。
【仿真波形】
【知识点挖掘】
0.reg和wire都采用的四值逻辑
reg变量在未进行赋值时,其默认值为x,wire默认为z,上图中cnt_nxt之所以仿真开始时为不定态,主要是因为它是由cnt进行运算后得到的,而cnt刚开始就是个x。
1.变量和线网声明时初始化
线网在声明的同时进行赋值操作实际上完成的是一种隐含的连续赋值操作(implicit continuous assignment),即相当于该线网从声明的时候就开始采用了连续赋值操作,此时如果有其他对于该线网的赋值操作,将会导致多驱动;与之相对应的是变量在声明时的初始化,实际上仅仅完成了对于该变量真正的初始化操作,后续对该变量的赋值操作将会覆盖声明时初始化的值。
示例详见《硅芯思见:【173】隐藏的初始化》
2.缩减操作符
操作符 | 作用 |
&(缩减与) | 操作数中只要有任意一位的值为0,则操作的结果就为0;操作数中只要有任意一位的值为x或者z,则操作的结果就为x;否则结果为1 |
~&(缩减与非) | 上述结果取反即可 |
|(缩减或) | 操作数中只要有任意一位的值为1,则操作的结果就为1;操作数中只要有任意一位的值为x或者z,则操作的结果就为x;否则结果为0 |
~|(缩减或非) | 上述结果取反即可 |
^(缩减异或) | 操作数中只要有任意一位的值为x或者z,则操作的结果就为x;若操作数中有偶数个1,则操作结果为0;否则其操作结果为1 |
~^(缩减同或) | 上述结果取反即可 |
3.阻塞赋值与非阻塞赋值区别
详见《Verilog系列:【17】阻塞赋值与非阻塞赋值》
阻塞赋值(blocking assignment) | 非阻塞赋值(non-blocking assignment) |
格式:“LHS”=“RHS” | 格式:“LHS”<= “RHS” |
阻塞赋值RHS会延迟指定延迟(如果没有指定就是0延迟,如果指定了非零延迟,那么就延迟非零延迟,关于延迟位置不同结果不同可参见topic“阻塞赋值中的延迟”)后立即更新至LHS | 非阻塞赋值LHS会在当前仿真时间槽(time-slot)最后被更新,即RHS变化后不会立即反应在LHS上 |
当多条阻塞赋值语句顺序出现在同一个进程中时,所有的语句按顺序执行,即后续的语句必须在当前赋值操作完成后才能进行 | 同一个进程中的非阻塞赋值在同一个时间槽中是同时执行的,即不会互相阻塞 |
建议在组合逻辑的结构中使用 | 建议在时序逻辑进程中使用 |
可以在过程性赋值和连续性赋值中使用 | 建议在时序进程中使用 |
当阻塞赋值中的变量同时出现在不同的进程中时,可能会出现竞争的情况 | 非阻塞赋值LHS更新在仿真时间槽的最后,可以在一定程度上避免竞争的出现 |
【示例】 initial begin temp_1 = #5 2'b10; temp_2 = #1 2'b01; end 从仿真0时刻开始,temp_1在时刻5被赋值为2'b10,temp_2在时刻6(5+1)被赋值为2'b01,即temp_2更新发生在temp_1之后,即两次赋值有先后顺序 |
【示例】 initial begin temp_1 <= #5 2'b10; temp_2 <= #1 2'b01; end 从仿真0时刻开始,temp_1在时刻5被赋值为2'b10,temp_2在时刻1被赋值为2'b01,即temp_2更新发生在temp_1之前,即两次赋值从同一时刻同时开始 |
4.+:和-:位选操作
如果base_expr和width_expr经过位选后超过d本身的位宽,那么读取超出部分将获得不定态表示。其中base_expr是可以在仿真运行过程中按照需要变化的,但是width_expr是必须是确定的。
【示例】
【仿真结果】
5.wire和reg分别在什么时候使用
wire常用于连续赋值语句(连续赋值语句左侧信号)、模块端口(input、output、inout,其中注意output默认为wire),reg常用于过程性赋值语句(当然也可以位于连续赋值语句的右侧),关于连续赋值语句和过程性赋值语句的关系可以参看《Verilog系列:【32】Verilog中的几种赋值语句》
6.异步复位、同步复位和异步复位同步撤销
复位主要用于将数字电路中的触发器置为一个确定的初始值上,例如可以是状态机工作于初始状态。而触发器一般情况下分为两种:一种是有复位引脚的,一种是没有复位引脚的,带有复位的触发器占用的面积比没有复位引脚的触发器大一些。一般情况下,处于数据路径上的触发器的初始值无关紧要,此时可以使用不带复位引脚的触发器,以降低芯片的面积。两者之间的优缺点如下。
【同步复位】
l抗干扰性强,可以容忍一定的毛刺,但是前提是这个毛刺不要出现在setup和hold违例区间;
l利于后端人员进行STA分析;
l触发器的复位信号完全同步于时钟源,确保时钟和复位作用下的逻辑电路的一致性;
l复位信号要确保大于时钟周期,避免没有被采样到;
l因为触发器本身不带复位引脚,综合后会增加很多其他的逻辑资源;
l如果时钟信号出现问题,可能会影响到复位;
【异步复位】
相较于同步复位,异步复位有以下特点。
l复位信号不依赖于时钟;
l大多数库提供的触发器都是自带异步复位的触发器;
l异步复位不管产生或撤销复位信号,都是一个异步过程,但是撤销时就出现了问题,如果异步复位在触发器时钟有效沿附近释放,触发器的输出就会进入亚稳态,因此导致复位状态丢失;
l毛刺容易对电路造成干扰,导致不期望的复位产生;
l异步复位需要满足时序要求(recover time、remove time,类似于setup和hold);
为了综合两种复位的优缺点,提出了一种异步复位同步释放的方式,就是指在复位信号到来的时候不受时钟信号的同步,而是在复位信号释放的时候受到时钟信号的同步,即用一个同步器来将异步复位信号转换为同步的复位信号,从而确保复位操作的可控性和稳定性。。其典型结构图如下。
其操作过程如下为当复位信号rst_async_n有效时,第一个D触发器的输出是低电平,第二个D触发器的输出rst_sync_n也为低电平,此时驱动后级方框中的异步复位端口有效,其输出被复位。复位撤销时,rst_async_n经过两级触发器同步后得到的rst_sync_n是与时钟同步的,从而可以实现复位的同步撤销。假设rst_async_n在clk的上升沿时撤除,那么第一个大黄框中的第一级触发器处于亚稳态,但是由于两级触发器的同步作用,第二级触发器的输入为clk到来前第一级触发器的输出,即为低电平。因此,此时第二级触发器的输出一定是稳定的低电平,方框左中触发器此时还处于复位状态。在第二个clk到来时,第一级触发器的输出已经是稳定的高电平了,故rst_sync_n已经是稳定的高电平,此时复位释放,也就是同步释放。
7.~和!区别
首先条件判断语句根据根据判断其关键字后的条件判断表达式结果的真假(非零的结果被认为"真",零的结果对应为"假")来选择不同的条件分支,即可以将条件表达式分为两步来实现:第一步计算条件表达式,第二步判断条件表达式结果;其次,在Verilog中"!"的意思为逻辑非,"~"为按位操作符, "!"主要是对操作数进行逻辑非操作,其预算结果只能为"0"(假)或者"1"(真),"~"主要是对操作数进行按位运算,即对操作数的每一位进行取反操作.但是这里需要注意的是对于一位数据来说,两种操作的结果是一样的,但是如果操作数为多位数据,那么两个操作的运算结果将会不一样.使用逻辑操作符"!",在进行位运算时使用按位运算符"
【示例】
【仿真结果】
从上例仿真结果可以观测到,代码10行没有执行,13行执行。代码中9行的条件判断语句"if(!sig_1)"中的"!sig_1"计算结果为"0",条件表达式对应的分支不会执行,所以仿真过程中并没有显示对应的消息;12行的"if(~sig_2)"中的"~sig_2"计算结果为"2'b10",为非零值,即条件表达式判断的条件为真,所以对应的分支被有效执行;17和20行两个条件表达式都为真,所以对应的分支都被有效执行,但是这时需要注意两个条件表达式的具体计算结果并不相同,17行"!sig_1"计算结果为"1",而20行"~sig_2"计算结果为"2'b11",两者的相同点是均为非零值,所以对于条件语句来说都是为真的条件,所以对应的分支会被执行.在具体使用这两种操作符的时候,一般情况下推荐进行逻辑判断时~"。
审核编辑:汤梓红
-
仿真
+关注
关注
50文章
4070浏览量
133552 -
信号
+关注
关注
11文章
2789浏览量
76730 -
Verilog
+关注
关注
28文章
1351浏览量
110074 -
波形图
+关注
关注
1文章
34浏览量
14932 -
代码
+关注
关注
30文章
4779浏览量
68524
原文标题:一道设计&验证“麻雀”题
文章出处:【微信号:处芯积律,微信公众号:处芯积律】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
评论