A D flip-flop copies D to Q at each rising edge and ignores D otherwise. After edge n, Q holds the D value from just before that same edge: Q_after(n) = D_before(n). In RTL the update uses a nonblocking assignment so Q changes just after the edge; in hardware the same update arrives after the clock-to-Q delay.
The waveform comes from simulating the module under Testbench. Inputs change mid-cycle, away from the edge.
Slot 1: d is 0 before the first edge, so q reads 0 just after it.
Slot 2: d is 1 before the second edge, while q observed just after the first edge still reads 0.
Slot 3: q observed just after the edge reads 1, the d value from just before that same edge.
Slot 4: d is 0 before the next edge, while q observed just after the previous edge still reads 1.
Slot 5: q observed just after the edge reads 0, the d value from just before that same edge.
D must be stable around the edge: setup time before it and hold time after it. A change inside that window can capture the wrong value or cause metastability.
Parameter | Meaning | Violated when… | Fixed by |
|---|---|---|---|
t_setup | D must be stable this long before the edge | Logic is too slow | Faster/shorter logic, pipelining, lower clock rate |
t_hold | D must stay stable this long after the edge | Path is too fast (data races through) | Delay padding, usually added by the tools |
t_clk→q | Delay from the edge to Q changing | — | Part of the path delay budget |
Setup violations are cured by slowing the clock; hold violations are not, because they exist at every frequency. That is why hold fixing is done by tools during physical design, and RTL authors mostly worry about setup.
T ≥ 0.15 + 0.9 + 0.1 = 1.15 ns (about 870 MHz), before any clock uncertainty.
The D flip-flop with a testbench that changes D mid-cycle and checks Q after each edge.
module dff (
input logic clk, d,
output logic q
);
always_ff @(posedge clk) q <= d; // sample d at every rising edge
endmodule
module tb_dff;
timeunit 1ns; timeprecision 1ps;
logic clk = 0, d = 0, q;
dff dut (.*);
always #5 clk = ~clk;
int errors = 0;
logic prev_d = 0;
initial begin
// Change d mid-cycle (on the falling edge) so it is stable around the rising edge.
repeat (8) begin
@(negedge clk) d = $urandom_range(0, 1);
@(posedge clk);
prev_d = d; // value present at the edge
#1;
if (q !== prev_d) begin // after the edge q holds what d was AT the edge
errors++;
$display("ERROR time=%0t: q=%b, expected d at the edge=%b", $time, q, prev_d);
end
end
if (errors == 0) $display("PASS: q equals the value d had at the clock edge");
else $fatal(1, "FAIL: D flip-flop check, errors=%0d", errors);
$finish;
end
endmodule