Verilog基础语法——阻塞赋值与非阻塞赋值、组合逻辑与时序逻辑
写在前面
阻塞赋值“<=”与非阻塞赋值“=”两者之间的不同之处要从时序波形与逻辑电路上来分析。而要讲清楚两者之间的区别,就避不开组合逻辑与时序逻辑。本文
一、基本概念
1.1 阻塞赋值与非阻塞赋值
阻塞赋值的运算符为“=”,非阻塞赋值的运算符为“<=”。无论是阻塞赋值还是非阻塞赋值,其本质都是赋值操作,即将RHS的运算结果赋值给LHS。这一操作可以细分为两个部分:(1)RHS运算操作;(2)将RHS运算结果赋值给LHS。 那么阻塞赋值与非阻塞赋值两者最本质的区别在哪里?两者最本质的区别在于操作(1)与操作(2)是并行执行的还是串行执行的。
具体而言,阻塞赋值的步骤如下:
Step 1 :执行RHS的运算,同时 将RHS的运算结果赋值给LHS;
非阻塞赋值的步骤如下:
Step 1 :先 执行将RHS的运算;
Step 2 :再 将RHS的运算结果赋值给LHS;
可以这么理解,阻塞赋值中 “RHS运算操作” 与 “将RHS运算结果赋值给LHS” 是并行执行的,即RHS中运算结果一旦发生变化就立马赋值给LHS,LHS立马随之变化。而在非阻塞赋值中,“RHS运算操作” 与 “将RHS运算结果赋值给LHS” 是串行执行的,即先执行“RHS运算操作” ,得到RHS运算结果,再“将RHS运算结果赋值给LHS” ,那么LHS变化的时间会滞后于RHS变化一段时间(具体滞后了多久?可以说是无穷小,但不等于没有)。
1.2 组合逻辑与时序逻辑
组合逻辑的特点是任意时刻的输出仅仅取决于该时刻的输入,与电路原本的状态无关,逻辑中不牵涉跳变沿信号的处理。即组合逻辑电路输出的变化发生在敏感信号发生改变时。而时序逻辑的特点是任意时刻的输出不仅取决于该时刻的输入,而且还和电路原来的状态有关(PS:这段描述和状态机的描述相似,注意甄别)。即时序逻辑电路的变化仅在敏感信号的边沿处。
那么对于组合逻辑,有两种描述方法:一种是在always块中进行阻塞赋值;一种采用连续赋值(连续赋值语句只能搭配阻塞赋值进行使用)。如下:
(1)在always块中进行阻塞赋值
reg [DW-1:0] RHS;
always @(*) begin
LHS = RHS;
end
(2)连续赋值
wire [DW-1:0] RHS;
assign LHS = RHS;
而时序逻辑的描述方法如下:
reg [DW-1:0] RHS;
always @(边沿信号) begin
LHS <= RHS;
end
组合逻辑与时序逻辑是互斥的关系吗?答案:不是。两者应该属于包含的关系,即组合逻辑 ⊂ \subset ⊂ 时序逻辑。
二、区别
上述分析了阻塞赋值与非阻塞赋值、组合逻辑与时序逻辑的基本概念与语法,其中组合逻辑搭配阻塞赋值使用,时序逻辑搭配非阻塞赋值进行使用,那么如果组合逻辑搭配非阻塞赋值、时序逻辑搭配阻塞赋值进行使用,为什么不推荐使用?会造成哪些问题?
为了分析四种不同方案之间的区别,最主要是从时序波形以及逻辑电路上进行分析。在这给出4种不同组合的代码如下:
module top(
input wire clk ,
input wire din1 ,
input wire din2 ,
output reg dout1,
output reg dout2,
output reg dout3,
output reg dout4
);
// 组合逻辑+阻塞赋值
always @(*) dout1 = din1+din2;
// 组合逻辑+非阻塞赋值
always @(*) dout2 <= din1+din2;
// 时序逻辑+阻塞赋值
always @(posedge clk) dout3 = din1+din2;
// 时序逻辑+非阻塞赋值
always @(posedge clk) dout4 <= din1+din2;
endmodule
2.1 逻辑电路区别
对上述RTL代码进行综合,综合电路如下图所示。可以看到无论是组合逻辑还是时序逻辑,搭配阻塞赋值与非阻塞赋值综合出来的电路是一致的。
2.2 时序波形区别
为了分析4种不同搭配之间的时序波形差异,TestBench代码如下:
`timescale 1ns/1ns
module TestBench();
reg clk;
reg din1,din2;
wire dout1,dout2,dout3,dout4;
initial begin
clk = 1'b1;
din1 <= 1'b0;
din2 <= 1'b0;
#40
din1 <= 1'b0;
din2 <= 1'b1;
end
always #10 clk = ~clk;
top top_inst(
.clk (clk ),
.din1 (din1 ),
.din2 (din2 ),
.dout1(dout1),
.dout2(dout2),
.dout3(dout3),
.dout4(dout4)
);
endmodule
仿真结果如下。其中dout1与dout2分别为组合逻辑搭配阻塞赋值与非阻塞赋值的结果,dout3与dout4分别为时序逻辑搭配阻塞赋值与非阻塞赋值的结果。
可以看到无论是组合逻辑还是时序逻辑,搭配阻塞赋值与非阻塞赋值的时序波形是一致的。那么,为什么对于“组合逻辑+非阻塞赋值”与“时序逻辑+非阻塞赋值”的描述风格,不推荐呢?从夏宇闻老师的《Verilog数字系统设计教程》一书中可以得知:“组合逻辑+非阻塞赋值”与“时序逻辑+非阻塞赋值”两种描述风格虽然仿真正确,但是风格混乱,在大规模电路设计中时序上容易出问题,不推荐。
写在后面
在本文中,我们学习了组合逻辑与时序逻辑、阻塞赋值与非阻塞赋值的基本概念、语法和区别,并对4种不同的电路描述方式进行介绍。
🧐:以上为个人学习笔记,如有疑问,欢迎评论区交流探讨 !!!