一、项目原理
在always 块语句中,使用阻塞赋值,完成组合逻辑的电路结构;使用非阻塞赋值,综合成时序逻辑电路结构。
以下将RHS做等号右边的表达式或者变量;
LHS做等号左边的表达式或者变量;
1、阻塞赋值:在赋值操作进行时,先计算RHS的值,此时,赋值语句不会受到别的语句的干扰,知道RHS赋值给LHS结束的时刻,才允许别的语句执行。在概念上,同一always 块语句中,后一赋值语句的执行是在前一赋值语句结束后才进行操作的。即有延迟。
如果上一赋值语句的RHS变量作为下一赋值语句的LHS变量,并且两个赋值语句是用同一时钟沿触发,如果阻塞赋值的顺序没有安排好,即会出现竞争的情况,执行顺序无法确定。
example:
输入 a,b,c;
寄存器:sum
输出:out
举例:sum = a+b;
out = sum +c;
生成的电路图如下:
2、非阻塞赋值:赋值操作开始时,即计算RHS,赋值操作结束后,才更新LHS的值;此时在同一always 块语句中,其他赋值语句可对 RHS或者LHS进行更新。
非阻塞赋值只用于对寄存器类型变量进行操作,常用于 initial块 或者always块中;不允许进行连续赋值操作。
(1)sum <= a+b;
out <= sum +c;
产生的电路图如下:
(2)out <= a+b+c;
产生的电路图如下:
二、实验代码
//项目文件
module block_noblock(clk,rst_n,a,b,c,out);
input clk;
input rst_n;
input a;
input b;
input c;
output reg [1:0]out;
//reg [1:0]sum;
always@(posedge clk or negedge rst_n)
if(!rst_n)
out <= 2'b0;
else
begin
out <= a+b+c;
end
endmodule
//测试文件
`timescale 1ps/1ps
`define delay_period 20
module block_noblock_tb;
reg clk;
reg rst_n;
reg a;
reg b;
reg c;
wire [1:0]out;
block_noblock block_noblock0(clk,rst_n,a,b,c,out);
initial clk = 1;
always#(`delay_period /2 )clk = ~clk;
initial begin
rst_n = 1'b0;
a = 0;b = 0;c = 0;
#(`delay_period *200+1);
rst_n = 1'b1;
a = 0;b = 0;c = 0;
#(`delay_period *200);
a = 0;b = 0;c = 1;
#(`delay_period *200);
a = 0;b = 1;c = 0;
#(`delay_period *200);
a = 0;b = 1;c = 1;
#(`delay_period *200);
a = 1;b = 0;c = 0;
#(`delay_period *200);
a = 1;b = 0;c = 1;
#(`delay_period *200);
a = 1;b = 1;c = 0;
#(`delay_period *200);
a = 1;b = 1;c = 1;
#(`delay_period *200);
$stop;
end
endmodule
三、项目总结
通过逻辑仿真、时序仿真来看,此种赋值方式,产生了滞后赋值,每个D触发器都会产生一定延时,在实际电路中会有影响。