D触发器是在时钟上升沿采样输出数据。
在做HDLbit的题目时,发现在D触发器那一块仿真波形发现和modelsim的不一样,感觉很迷惑。
HDLBIT里的仿真图是这样的。
会发现输出q与输入d并不是同步的,输出q似乎延时了一个周期。这个是这样理解的,在时钟上升沿采样数据时,数据还没有完全完成从0到1的变化,因此在输入第一次变化时,触发器采样的值是0.
然后我去modelsim中试了试,因为modelsim中的波形是理想化的,就想试试当输入是立刻变化时,输出是采样时钟前的值还是立刻变化的值。modelsim的波形是这样的:
输出q与输入d是同步变化的。这似乎是采样立刻变化后的值,当时这就觉得很奇怪。
后面发现其实是modelsim中的测试文件写的有些问题。
module tb();
reg clk;
reg [3:0] d;
wire [3:0] q;
edgetect inst(.clk(clk),
.d(d),
.q(q));
initial begin
clk = 0;
d = 0;
#50 d = 1;
#50 d = 2;
#50 d = 3;
#50 d = 4;
#50 d = 5;
end
always #50 clk = ~clk;
当时是这么写的。后面问了一些大佬,好像是说输入激励也应该用clk产生,或者使用非阻塞赋值。
改了之后,波形如下。
此时输出q采样的为上升沿前输入d的值。与HDLBit一样啦。
以上的原因后面发现还是和激励赋值采用的是阻塞还是非阻塞方式。采用非阻塞赋值则触发器取样的是输入上周期的值。
后面还遇到另一种情况:即某个寄存器的输出需要在某个寄存器的边沿检测值,那么此时检测的值为哪个呢?
如图,dout在时钟上升沿时需要判断dout是否为0,为0则加1,从图中可看出,仿真此时在dout的边沿判断为0,即为前一时钟的数据。
后续:两个同样判断条件的信号,一个dout1采用组合逻辑(assign),一个采用时序逻辑dout2,
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2022/02/23 21:22:44
// Design Name:
// Module Name: test
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module test(
input clk,
input din,
output reg dout,
output dout1,
output reg dout2
);
always@(posedge clk)begin
dout <= din;
end
assign dout1 = (dout == 0);
always@(posedge clk)begin
if(dout == 0)
dout2 <= 1;
else
dout2 <= 0;
end
endmodule
二者仿真时序差一个时钟周期,因此在时序逻辑内判断输出会延时一个周期,assign判断是同步输出。