Zedboard—实验三阻塞非阻塞
本节包括对阻塞与非阻塞这一个重要概念的讨论和进一步的仿真。
阻塞和非阻塞
在上节的FPGA设计中有这样的赋值语句:
always@(posedge clk) led = switch;
在上一节中的测试文件中,对开关信号的复制语句:
always@(posedge clk) switch = $random;
问题来了,上述这两句赋值语句都是当时钟信号上升沿到来时进行赋值,那么究竟是哪一句会先执行?
在实际硬件中,他们有可能同时发生。但在仿真器中是不可能的。究竟哪个语句先完成赋值,是不确定的,而且谁先执行会影响到仿真结果。
修改上节中top.v和bench.v文件,将阻塞语句修改为非阻塞语句:
top.v:
`timescale 1ns / 1ns
module top
(
input clk,
input [7:0] switch,
output reg [7:0] led
);
always @(posedge clk) led <= switch;
endmodule
bench.v:
`timescale 1ns / 1ns
module bench;
reg clk = 1;
always #5 clk = ~clk;
reg [7:0] switch;
wire [7:0] led;
top top
(
.clk(clk),
.switch(switch),
.led(led)
);
always @(posedge clk)
switch <= $random;
initial
begin
repeat (1000) @(posedge clk);
$finish;
end
endmodule
优化Test Bench
下图为修改为非阻塞式赋值语句的仿真波形图:
对比阻塞式赋值语句的仿真波形图:
LED值滞后Switch一个时钟周期,因为当时钟上升沿到达了时,触发器捕获LED的值。
接下来添加检测LED输出是否与期望值相等。首先是生成期望结果。即,Switch信号延时一个时钟周期:
reg [7:0] expected_led;
always @(posedge clk)
expected_led <= switch;
将期望结果与实际输出结果对比,这里声明了两个整型变量num_checks和num_errors初始化为0.整型变量是有符号的32位reg值。然后,每个时钟沿对结果进行比较,如果实际输出记结果与期望输出结果不等,errors值加一。
integer num_checks = 0;
integer num_errors = 0;
always @(posedge clk)
begin
num_checks = num_checks+1;
if (expected_led != led)
begin
$display("ERROR: led value %0x does not match expected value %0x at time %0fns",
led,expected_led,$realtime);
num_errors = num_errors+1;
end
end
运行仿真结果如下:
参考原文连接