See it move
The idea
A D flip-flop captures its input at one instant, the clock edge, then holds that value until the next edge. It is the basic memory element of synchronous design, and it is usually built from two latches.
Two latches, opposite phases
For a rising-edge flop:
- Clock low: the first (master) is open and follows D. The second latch (slave) is closed and keeps Q steady.
- Clock high: the master closes and freezes what D was at the moment of the edge. The slave opens and passes that frozen value to Q.
At no point is there a transparent path from D to Q, because the two latches are never open together. That is why the flop appears edge-triggered although each part is level-sensitive. Step through the animation to watch this happen.
always_ff @(posedge clk)
q <= d;Clock-to-Q delay
Q doesn't change instantly. Clock-to-Q (Tcq) is the time from the edge until the new value appears at the output, and it's part of every timing path.
Why synchronous design works
Each flop samples just once per cycle, so any glitches or slow settling between flops don't matter, as long as the logic has settled by the next edge. This turns a messy analog reality into something you can reason about one cycle at a time.
Common mistake
Expecting Q to take the new value in the same cycle. If q <= d, then during this cycle q shows what d was at the previous edge. Each flop in a path adds exactly one cycle of . Off-by-one mistakes here are among the most common RTL bugs.
Key ideas
- Master and slave latches are transparent on opposite clock phases.
- Q updates only at the active edge.
- Clock-to-Q is the delay before the new value appears.
Lab: Setup and hold lab
Your exercise
Find the bug
This code has one deliberate bug. Read the symptom, then click the line you think is wrong.
The fix
always @(posedge clk)
Why it failed
The specification asks for a rising-edge flop, and this block waits for the falling edge. Each output then appears half a cycle late, cutting the time available to the next stage. A waveform shows it immediately if you check where Q moves relative to the clock.
Interview questions
coreHow do you make a flop from latches?
A negative-level latch feeding a positive-level latch forms a rising-edge flop.
basicWhat does the Q output of a rising-edge D flip-flop do between two clock edges, even if D changes many times?
It holds the value that was captured at the last rising edge. The flop only samples D at the edge, so changes to D in between have no effect on Q. The next value appears just after the following rising edge.
basicThree rising-edge flops are chained, d to f1 to f2 to f3. D changes from 0 to 1 a little before rising edge number 1. After which edge does f3 first show 1?
always @(posedge clk) begin f1 <= d; f2 <= f1; f3 <= f2; end
After edge 3. Each flop adds exactly one cycle: f1 takes the new value at edge 1, f2 at edge 2 and f3 at edge 3. Counting flops in a path gives its latency in cycles.
coreIn a master-slave rising-edge flop, what does each latch do while the clock is low, and while it is high? Why is there never a straight path from D to Q?
While the clock is low, the master is open and follows D, and the slave is closed and keeps Q steady. When the clock rises, the master closes and freezes the value D had at the edge, and the slave opens and passes that frozen value to Q. The two latches are open on opposite phases, so D can never run through both at once, which is what makes the pair act on the edge.
coreThis code models a flop with two latches. Which clock edge does it capture on, and how would you change it to capture on the falling edge?
always @(*) if (!clk) m = d; // master always @(*) if (clk) q = m; // slave
It captures on the rising edge. The master m follows d while clk is low and freezes when clk rises; the slave then copies m to q while clk is high. For a falling-edge flop, swap the phases: let the master follow d while clk is high and the slave copy while clk is low. In simulation, this model matched a plain always @(posedge clk) q <= d; when d changed away from the edge.
coreAt a rising edge, flop A's output changes. Flop B, on the same clock, takes A's output as its D. Why does B capture A's old value rather than the new one?
A's new value only appears a clock-to-Q delay after the edge. By then, B has already sampled its input at that same edge, and as long as the clock-to-Q plus any logic delay is longer than B's hold time, B sees the old value. That is the basis of synchronous design: every flop reads values from before the edge and writes values that appear after it.
coreThis was meant to be a rising-edge flop, but in simulation q sometimes changes on the falling edge of the clock. What is wrong?
always @(clk) q <= d;
The event list is the clock level, so the block runs on every change of clk, both rising and falling. If d changes while the clock is high, q picks it up at the falling edge, which a real rising-edge flop would not do. Writing always @(posedge clk) makes it sample only on the rising edge.
advancedCombinational logic between flops often glitches before it settles. Why is that usually harmless, and in which cases does a glitch become a real bug?
A flop only samples its D around the clock edge, so a glitch that settles before the next edge, with setup time to spare, is never seen. Glitches matter when the signal is used in a way that reacts at any instant: as a clock, as an asynchronous set or reset, as a latch enable, when it leaves the chip, or when another clock domain samples it at an arbitrary time. Those signals should come straight from a flop.
advancedA master-slave flop is driven by a clock and an inverted copy of it. If the inverter is slow, both latches can be open at the same time for a short moment around the edge. What can go wrong?
During the overlap there is a transparent path through both latches, so a D change that arrives in that moment can run straight through to Q. The flop then behaves partly like a latch, which can break hold timing because new data races into the stage it was not meant to reach until the next edge. Real flop designs keep the phases non-overlapping, or short enough that the data cannot pass both latches in time.