Day 4 · Sequential Logic Fundamentals

Flip-Flop Variants

Video 3 of 4 · ~10 minutes

Dr. Mike Borowczak · Electrical & Computer Engineering · CECS · UCF

Clocks & EdgesNonblockingFF VariantsCounters

🌍 Where This Lives

In Industry

Every production flip-flop has at least reset, and usually enable. ARM processor cores? Synchronous-reset D-flops. Intel's Xeon CPUs? Same pattern. The “bare” D-flop from Video 1 exists only in textbooks — real silicon comes with accessories.

In This Course

Every FSM (Day 7) uses reset to enter an initial state. Every counter (Video 4 today) uses reset + enable. Every protocol engine (Days 11-12) uses both. This pattern is now yours, for every remaining lab.

Historical note: The sync/async reset debate has split ASIC teams for 30 years. Modern consensus (post ~2010): synchronous reset is the safer default. We'll use it throughout the course.

⚠️ Missing else? Not a Latch Anymore.

❌ Wrong Model

“Day 3 told me missing else = latch. So I need to add an else to every if in my sequential block too, right?”

✓ Right Model

In always @(posedge clk), a flip-flop is already storage. When a path leaves the output unassigned, the flop simply holds its current value — no new latch gets inferred. “Missing else” means “don't update this cycle,” which is exactly what enables do.

Consequence: The clock enable pattern if (en) q <= d; with no else is idiomatic, correct, and produces an SB_DFFE (D-flop with clock enable) on iCE40. Would be catastrophic in combinational; is the right thing in sequential.

👁️ I Do — D Flip-Flop with Synchronous Reset

always @(posedge i_clk) begin
    if (i_reset)
        r_q <= 1'b0;       // reset on next clock edge
    else
        r_q <= i_d;         // normal capture
end
My thinking: Synchronous reset checks i_reset only on the clock edge. It takes effect at the next rising edge, not immediately. This is the default pattern for iCE40 and most modern FPGA flows. The flop's reset input is tied into the clock domain, which keeps timing analysis tractable.

👁️ I Do — With Clock Enable

always @(posedge i_clk) begin
    if (i_reset)
        r_q <= 1'b0;
    else if (i_enable)      // only update when enabled
        r_q <= i_d;
    // else: r_q holds — no latch! (this is sequential)
end
The missing else is NOT a latch in sequential logic. Flip-flops inherently hold their value. Only always @(*) has the latch problem.
iCE40 primitive: this synthesizes to SB_DFFE — D-flop with built-in clock enable. Same silicon cost as a plain SB_DFF; the enable is “free” on this FPGA family.

🤝 We Do — Sync vs Async Reset

Synchronous (preferred)

always @(posedge clk)
  if (reset) q <= 0;
  else       q <= d;

Clean timing. Works well with iCE40. Reset acts only on clock edges.

Asynchronous

always @(posedge clk
         or posedge reset)
  if (reset) q <= 0;
  else       q <= d;

Resets immediately on reset assertion. Used in some ASIC flows.

Trade-off: Async reset is instant — useful for powering up safely before clocks are stable. But deassertion needs to be synchronized to avoid metastability. Sync reset needs a running clock to take effect. Pick sync unless you have a specific reason not to.

🧪 You Do — Build the Flop

Write a 4-bit register with: synchronous reset to 4'b0, clock enable on en, input d, output q.

Answer:
reg [3:0] r_q;
always @(posedge clk) begin
    if (reset)
        r_q <= 4'b0;
    else if (en)
        r_q <= d;
end
assign q = r_q;
Synthesis target:SB_DFFE cells (one per bit). Zero LUTs. Total area: 0.3% of iCE40 HX1K. This is the workhorse pattern you'll use constantly.
▶ LIVE DEMO

Reset + Enable Register in Action

~4 minutes

▸ COMMANDS

cd labs/week1_day04/ex3_reg_with_rst_en/
make sim
make wave
make stat   # count SB_DFFE vs SB_DFF

▸ EXPECTED STDOUT

PASS: reset → q=0
PASS: en=0, d=X → q unchanged
PASS: en=1, d=5 → q=5
PASS: en=1, d=9 → q=9
PASS: reset → q=0 again
=== 12 passed, 0 failed ===

▸ GTKWAVE

Signals: clk · reset · en · d[3:0] · q[3:0]. Set d and q to hex. Toggle en to see q freeze; toggle reset to see q snap to 0. The shape of the q waveform — stairsteps when en=1, plateaus when en=0 — is the clock-enable signature.

🔧 What Did the Tool Build?

$ yosys -p "read_verilog reg_4bit_rst_en.v; synth_ice40; stat" -q

=== reg_4bit_rst_en ===
   Number of wires:                  8
   Number of cells:                  4
     SB_DFFESR                       4    ← 4 flops with Enable + Sync Reset
     SB_LUT4                         0    ← zero LUTs — built-in!
Zero LUTs. The iCE40 DFFESR primitive has built-in enable and synchronous reset inputs. The whole “if reset, clear; else if en, update” pattern fits in the flop itself — no extra gates needed. This is why Yosys prefers this coding pattern.
iCE40 flop variants available: SB_DFF, SB_DFFE (w/ enable), SB_DFFR (async reset), SB_DFFSR (sync reset), SB_DFFER, SB_DFFESR... and their “set” variants. The tool picks the right one based on your code.

🤖 Check the Machine

Ask AI: “Why is this OK in always @(posedge clk) but NOT in always @(*)?”

if (en) q <= d;   // no else

TASK

Ask AI about the sequential vs combinational distinction.

BEFORE

Predict: flop already stores, so missing else means “hold current value” — fine.

AFTER

Good AI distinguishes: in sequential, “hold” maps to existing flop; in combinational, it maps to a new latch.

TAKEAWAY

The Day 3 “no missing else” rule does NOT apply in sequential blocks. Context matters.

Key Takeaways

 Basic D-FF: always @(posedge clk) r_q <= r_d;

 Sync reset: if (reset) r_q <= 0; else r_q <= r_d;

 Enable: adds another condition — else if (en)

 Prefer synchronous, active-high reset on iCE40.

Flops hold by default. “Missing else” in sequential = “don't update this cycle.”

🔗 Transfer

Counters & Clock Division

Video 4 of 4 · ~14 minutes

▸ WHY THIS MATTERS NEXT

Combine today's flip-flop pattern with a simple increment and you have a counter — the most-used sequential building block. And the first practical use: turning 25 MHz into a 1 Hz LED blink you can see. Video 4 builds it end-to-end, and flashes it to the Go Board.