本教程要求对数字电路中的寄存器(边沿D触发器)具有一定的了解,并熟悉基本的verilog语法。
首先利用非阻塞赋值编写一个异步寄存器:
module blocking
(
input wire sys_clk ,
input wire sys_rst_n ,
input wire [1:0] in ,
output reg [1:0] out
);
reg [1:0] in_reg ;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n==1'b0)
begin
in_reg<=sys_rst_n;
out<=in_reg;
end
else
begin
in_reg<=in;
out<=in_reg;
end
endmodule
编写仿真代码:
`timescale 1ns/1ns
module tb_blocking();
reg sys_clk ;
reg sys_rst_n ;
reg [1:0] in ;
wire [1:0] out ;
initial
begin
sys_clk=1'b1;
sys_rst_n<=1'b0;
in<=2'b00;
#20
sys_rst_n<=1'b1;
end
always #10 sys_clk=~sys_clk;
always #20 in<={$random}%4;
initial
begin
$timeformat(-9,0,"ns",6);
$monitor("@time %t sys_clk=%b sys_rst_n=%b in=%b out=%b",
$time,sys_clk,sys_rst_n,in,out);
end
blocking blocking_inst
(
.sys_clk (sys_clk) ,
.sys_rst_n (sys_rst_n) ,
.in (in) ,
.out (out)
);
endmodule
运行该代码进行仿真得到波形:
从图中可以看出输出out相对于输入in延迟了两个时钟周期。从而说明<=非阻塞赋值在begin end中是并行执行。其rtl视图如下,从图中可以看出对于每一个bit分别由两组寄存器组成,故进行了两个时钟周期的延迟。
对于阻塞赋值将<=改为=即可,仿真代码不变:
module blocking
(
input wire sys_clk ,
input wire sys_rst_n ,
input wire [1:0] in ,
output reg [1:0] out
);
reg [1:0] in_reg ;
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n==1'b0)
begin
in_reg=sys_rst_n;
out=in_reg;
end
else
begin
in_reg=in;
out=in_reg;
end
endmodule
对应的波形和rtl视图如下,从图中可以看出输出out相对于输入in只有一个时钟周期延迟,reg_in和out是同步的,从而说明阻塞赋值在begin end中是顺序执行的。