注意
阻塞赋值与非阻塞赋值,只有在时序逻辑中才有
//不是阻塞赋值,也不是非阻塞赋值,因为是组合电路
always@(a,b,c)begin //相当于always@(*)
case({a,b,c})//位拼接,{a,b,c}三位信号
3'b000:out = 8'b0000_0001;
3'b001:out = 8'b0000_0010;
3'b010:out = 8'b0000_0100;
3'b011:out = 8'b0000_1000;
3'b100:out = 8'b0001_0000;
3'b101:out = 8'b0010_0000;//3'd5 :out = 8'b0010_0000
3'b110:out = 8'b0100_0000;
3'b111:out = 8'b1000_0000;
endcase
阻塞赋值
1.阻塞赋值属于顺序执行,即下一条语句执行前,当前语句一定会执行完毕。
2.阻塞赋值语句使用等号 = 作为赋值符。
3.前面的仿真中,initial 里面的赋值语句都是用的阻塞赋值。
1.设计文件
module block_nonblock(clk,reset_n,a,b,c,out
);
input clk;
input reset_n;
input a,b,c;
output reg [1:0] out;
reg [1:0] d;
//阻塞赋值
always@(posedge clk or negedge reset_n)
if(!reset_n)begin
out =2'b0;
d =0;
end
else begin
d =a+b;
out =d+c;
end
endmodule
2.激励文件
`timescale 1ns / 1ns //时间刻度 时间的单位/ 1ns精度
`define clk_period 20
module block_nonblock_tb( );
reg clk;
reg reset_n;
reg a,b,c;
wire [1:0] out;
block_nonblock block_nonblock(
.clk(clk),
.reset_n(reset_n),
.a(a),
.b(b),
.c(c),
.out(out)
);
initial clk=1;
always#(`clk_period/2) clk=~clk;
initial begin
reset_n=1'b0;
a=0;b=0;c=0;
#(`clk_period*200+1);
reset_n=1'b1;
#(`clk_period*200);
a=0;b=0;c=0;
#(`clk_period*200);
a=0;b=0;c=1;
#(`clk_period*200);
a=0;b=1;c=0;
#(`clk_period*200);
a=0;b=1;c=1;
#(`clk_period*200);
a=1;b=0;c=0;
#(`clk_period*200);
a=1;b=0;c=1;
#(`clk_period*200);
a=1;b=1;c=0;
#(`clk_period*200);
a=1;b=1;c=1;
#(`clk_period*200);
$stop;
end
endmodule
3.原理图
4.仿真图
非阻塞赋值
1.非阻塞赋值属于并行执行语句,即下一条语句的执行和当前语句的执行是同时进行的,它不会阻塞位于同一个语句块中后面语句的执行。
2.非阻塞赋值语句使用小于等于号 <= 作为赋值符。
1.设计文件
第一种方法
module block_nonblock(clk,reset_n,a,b,c,out
);
input clk;
input reset_n;
input a,b,c;
output reg [1:0] out;
reg [1:0] d;
//非阻塞赋值
always@(posedge clk or negedge reset_n)
if(!reset_n)begin
out <=2'd0;
d<=0;
end
else begin
d<=a+b;
out<=d+c;
// d<= #2 a+b;//延迟2s,没有实际的电路,综合的时候会忽略,模拟传输延迟方便仿真使用,调试更加方便
// out<= #2 d+c;
// out<=a+b+c;//(数学上相等,电路上不相等)
end
endmodule
第二种方法
module block_nonblock(clk,reset_n,a,b,c,out
);
input clk;
input reset_n;
input a,b,c;
output reg [1:0] out;
reg [1:0] d;
//两个always将out与d分开写
always@(posedge clk or negedge reset_n)
if(!reset_n)begin
out <=2'd0;
end
else begin
out<=d+c;
end
always@(posedge clk or negedge reset_n)
if(!reset_n)begin
d<=0;
end
else begin
d<=a+b;
end
endmodule
2.激励文件
//同阻塞赋值的testbench
3.原理图
生成了d[1:0]和out[1:0]两个寄存器
4.仿真图
对上图中的红色部分放大如下
在非阻塞赋值的情况下,在16,020ns时刻,out[1:0]的值是计算前一个时刻16,000ns的d[1:0]和c值;
16,000ns时刻的d[1:0]等于15,980ns的a+b的值;
非阻塞赋值,均是上一时钟的赋值。
后记:事常与人违,事总在人为。