最近在做一些经典电路的复现,今天做到了对信号 i 的上升沿检测电路,电路中需要用到延迟一个周期后的中间信号 i_1(对信号 i 打一拍得到 i_1), 实现代码以及其tb如下:
module POS( input clk,
input i,
input rst,
output out
);
reg i_1;//输入打一拍
always @(posedge clk or negedge rst)
begin
if(!rst) i_1 <= 1'd0;
else i_1 <= i;
end
assign out = i & (!i_1);
endmodule
`timescale 1ns/1ps
module POS_TEST;
reg clk;
reg i;
reg rst;
wire out;
initial
begin
clk = 1'd0;
rst = 1'd0;
i = 1'd0;
#40 rst = 1'd1;
#20 i = 1'd1;
#80 i = 1'd0;
end
always #20 clk = ~clk;
POS U1( .clk(clk),
.i(i),
.rst(rst),
.out(out)
);
endmodule
其结果如图:
可以发现 i_1 信号并没有发生一个周期的延迟,个人猜测原因:输入信号 i 的上升与clk的上升沿重合,因为此时仿真为理想情况,信号 i 的上升延迟为0,当always语句被触发时,i 已经完成从 0 到 1 的变化,因此此时 i_1 信号也同步变为1;正常情况下,i由于上升延迟,i_1 信号应该被赋于0才对。
修改方法:将信号 i 的上升与 clk上升沿错开,即将tb中的 i 信号变化时间变为 #21 和 #81,如下
`timescale 1ns/1ps
module POS_TEST;
reg clk;
reg i;
reg rst;
wire out;
initial
begin
clk = 1'd0;
rst = 1'd0;
i = 1'd0;
#40 rst = 1'd1;
#21 i = 1'd1;
#81 i = 1'd0;
end
always #20 clk = ~clk;
POS U1( .clk(clk),
.i(i),
.rst(rst),
.out(out)
);
endmodule
结果如下:
疑问:实际测试是真的就只能通过这种tb的编写方法完成打拍验证吗?但是这种打拍得到的信号其实并不是严格意义上的延迟了一个周期,其实延迟时间会比一个周期略小,这种误差能否改善呢?那这样是否意味着,在写tb的时候所有信号都应该尽量避开clk的上升沿吗?