不想错过我的推送,记得右上角-查看公众号-设为星标,摘下星星送给我
笔试、面试中,有很多大家很容易迷惑的知识点,其中就有
阻塞与非阻塞
相关的问题。熟悉Verilog语言的同学都知道一个规范:
在always块中描述组合逻辑电路时使用阻塞(=)赋值的方式,在always块中描述时序逻辑电路时使用非阻塞(<=)赋值的方式
。但是出题人往往喜欢考不按照这个规范写出的代码会出现什么情况,其RTL视图又是怎样的。接下来让我们来看几个例子。
我们之前讲过跨时钟域相关的问题,知道单比特信号从慢速时钟域跨到快速时钟域需要进行打两拍的操作,那我们就以此为例,看看下面的这8种打两拍的代码,其RTL代码如下所示:
//—————————————–
001`define CASE1
002
003
module
test
(
004
input
wire
sclk
,
005
input
wire
rst_n
,
006
input
wire
in
,
007
008
output
reg
out
009
);
010
011
reg
temp
;
012
013//第1种情况:使用一个always块,并使用非阻塞赋值方式
014`ifdef CASE1
015
always
@(
posedge
sclk
or
negedge
rst_n
)
016
if
(
rst_n
==
1’b0
)
begin
017 temp
<=
1’b0
;
018 out
<=
1’b0
;
019
end
020
else begin
021 temp
<=
in
;
022 out
<=
temp
;
023
end
024`endif
025
026//第2种情况:使用一个always块,并使用阻塞赋值方式
027`ifdef CASE2
028
always
@(
posedge
sclk
or
negedge
rst_n
)
029
if
(
rst_n
==
1’b0
)
begin
030 temp
=
1’b0
;
031 out
=
1’b0
;
032
end
033
else begin
034 temp
=
in
;
035 out
=
temp
;
036
end
037`endif
038
039//第3种情况:使用一个always块,并使用非阻塞赋值方式,且输出信号和中间变量的赋值顺序进行了调换
040`ifdef CASE3
041
always
@(
posedge
sclk
or
negedge
rst_n
)
042
if
(
rst_n
==
1’b0
)
begin
043 temp
<=
1’b0
;
044 out
<=
1’b0
;
045
end
046
else begin
047 out
<=
temp
;
048 temp
<=
in
;
049
end
050`endif
051
052//第4种情况:使用一个always块,并使用阻塞赋值方式,且输出信号和中间变量的赋值顺序进行了调换
053`ifdef CASE4
054
always
@(
posedge
sclk
or
negedge
rst_n
)
055
if
(
rst_n
==
1’b0
)
begin
056 temp
=
1’b0
;
057 out
=
1’b0
;
058
end
059
else begin
060 out
=
temp
;
061 temp
=
in
;
062
end
063`endif
064
065//第5种情况:使用两个always块,并使用非阻塞赋值方式
066`ifdef CASE5
067
always
@(
posedge
sclk
or
negedge
rst_n
)
068
if
(
rst_n
==
1’b0
)
069 temp
<=
1’b0
;
070
else
071 temp
<=
in
;
072
073
always
@(
posedge
sclk
or
negedge
rst_n
)
074
if
(
rst_n
==
1’b0
)
075 out
<=
1’b0
;
076
else
077 out
<=
temp
;
078`endif
079
080//第6种情况:使用两个always块,并使用阻塞赋值方式
081`ifdef CASE6
082
always
@(
posedge
sclk
or
negedge
rst_n
)
083
if
(
rst_n
==
1’b0
)
084 temp
=
1’b0
;
085
else
086 temp
=
in
;
087
088
always
@(
posedge
sclk
or
negedge
rst_n
)
089
if
(
rst_n
==
1’b0
)
090 out
=
1’b0
;
091
else
092 out
=
temp
;
093 `endif
094
095//第7种情况:使用一个always块,并使用非阻塞赋值方式,且使用位拼接的方式
096`ifdef CASE7
097
always
@(
posedge
sclk
or
negedge
rst_n
)
098
if
(
rst_n
==
1’b0
)
099
{
out
,
temp
}
<=
2’b0
;
100
else
101
{
out
,
temp
}
<=
{
temp
,
in
};
102 `endif
103
104//第8种情况:使用一个always块,并使用阻塞赋值方式,且使用位拼接的方式
105`ifdef CASE8
106
always
@(
posedge
sclk
or
negedge
rst_n
)
107
if
(
rst_n
==
1’b0
)
108
{
out
,
temp
}
=
2’b0
;
109
else
110
{
out
,
temp
}
=
{
temp
,
in
};
111 `endif
112
113
endmodule
//————————
如果不先看我们综合与仿真的结果就能够把上面8种情况综合的RTL视图和仿真波形正确画出的同学,说明你对阻塞和非阻塞这块的了解已经很透彻了。
我们分别使用Quartus_13.0和Vivado_19.1工具来查看综合结果,使用Modelism_10.5SE和Vivado_19.1 Simulator工具来查看仿真波形图。下面就让我们依次查看以上8种情况的RTL视图与仿真波形图。
CASE1:
根据下图可以看出无论是RTL视图还是仿真波形图都是我们预想的常规打两拍的结果。
CASE2:
根据下图可以看出无论是RTL视图还是仿真波形图都不是我们预想的常规打两拍的结果,显然是出现了错误。
CASE3、
CASE4、
CASE5
,都
与CASE1结果完全相同。
CASE6:
根据下图可以看出RTL视图是我们预想的常规打两拍的方式,而仿真的波形图因仿真工具的不同,而产生了不同的效果,这是及其危险的情况,在设计中如果出现了该问题很难排查错误的原因。
CASE7、CASE8
:与CASE1结果完全相同。
我们根据实验的结果列出如下表格进行对比:
情况 |
RTL视图 |
仿真波形图 |
CASE1 |
正确 |
正确 |
CASE2 |
错误 |
错误 |
CASE3 |
正确 |
正确 |
CASE4 |
正确 |
正确 |
CASE5 |
正确 |
正确 |
CASE6 |
正确 |
错误 |
CASE7 |
正确 |
正确 |
CASE8 |
正确 |
正确 |
出问题的两种情况都是在always块描述时序逻辑的时候使用了阻塞赋值的方式,虽然CASE4和CASE8也使用了阻塞赋值方式而没有出现问题,但是绝对不能有这种侥幸心理,这也是为什么一直强调在编写Verilog代码的时候一定要按照规范来写的原因,否则在某些情况下连这种简单的打拍都会出现不可预测的错误,更不用说大型复杂的设计了。
另外再给大家看一个相似的例子,RTL代码如下所示:
//————————-
01
module
test
(
02
input
wire
sclk
,
03
input
wire
rst_n
,
04
input
wire
in1
,
05
input
wire
in2
,
06
input
wire
in3
,
07
08
output
reg
out
09
);
10
11
always
@(
posedge
sclk
or
negedge
rst_n
)
12
if
(
rst_n
==
1’b0
)
begin
13
out
<=
1’b0
;
14
out
<=
1’b0
;
15
out
<=
1’b0
;
16
end
17
else
begin
18
out
<=
in1
;
19
out
<=
in2
;
20
out
<=
in3
;
21
end
22
23
endmodule
//————————–
看到RTL视图我们就知道结果了,直接等于最后赋值的结果。有人会说如果分成三个always来写是什么情况呢?大家不要忘记多个always块是并行执行的,同一个变量在多个always块中赋值,综合工具会报出现多驱动的报错。
最后考察一下大家的掌握情况,留个题目大家做一做。
假设初始值a=1,b=2,c=3,请问下一个时间,A,B模块代码中a,b,c的值分别为多少?
A 1,1,1;1,1,1
B 1,1,1;3,1,2
C 3,1,2;1,1,1
D 3,1,2;3,1,2
END
目前,
我们正在通过大疆硬件岗和FPGA逻辑岗的题目,为大家带来笔试题的解析,以及知识的补充。如果有想要解析的题目,可以发给达尔闻安排。
同时,
欢迎加入达尔闻求职技术交流群,进群方式:
添加妮姐微信(459888529),并备注求职,即可邀请进群
。
达尔闻求职系列:
华为海思校招机考范围
求职攻略| 运放压摆率&三运放仪表放大电路分析,含仿真文件
磁珠的用法、PCB布线3W规则
单比特信号跨时钟域问题详解
如何搞定状态机问题
电容击穿表现为短路?
MOS管导通损耗和什么有关?
毛刺滤除的代码应该如何写
资深工程师总结减小串扰的7种方法
二进制数11.101对应的十进制数是多少
FGPA时序分析看这篇就够了
逻辑电路24种表达式
芯片工艺28nm的28是指什么
FPGA设计中的时序收敛准则
华为硬件逻辑岗(FPGA)
紫光展锐数字IC岗(编程题)
从无人机爱好者到获得DJI大疆Offer
offer拿到手软,最后选华为!
IO的时序约束该如何设置
典型FPGA器件常用资源
死活清除不了的亚稳态,怎么减少出现概率?
典型5级流水线RSIC结构中的5大功能
三步优化FPGA时序设计
噪声还分颜色?粉红、白噪声解析
电源拓扑别再傻傻搞不清楚
开关电源中的MOS功耗来源
晶体管的静态工作点一步快速搞定!
老司机也复习功率二极管、三相半波可控整流电路
2021年校招提前批第一枪(vivo芯片设计岗)
建立时间VS保持时间,竞争VS冒险(紫光展锐IC笔试题)
RAM的大小为520*8bit,其地址需要多少位
有符号4位二进制数运算0101+1000,还会计算吗
错综复杂的建立保持时间路径你能搞明白吗
关于稳压二极管的坑,你一定要知道
学会分频,“为所欲为”
一网打尽状态机的套路