Video 1 of 4 · ~12 minutes
Dr. Mike Borowczak · Electrical & Computer Engineering · CECS · UCF
Every digital chip built since 1970 runs on clocks. Your phone's SoC has 50+ clock domains running at frequencies from 32 kHz to 3 GHz. Clock distribution is a whole specialty — PLLs, clock trees, skew analysis. Today is your first formal introduction to the concept that governs all modern digital design: Register Transfer Level.
Every sequential lab from here uses a clock. Topic 4 counter. Topic 5 debouncer. Topic 6 testbench stimulus. Topic 7 FSM. Topic 11 UART. Topic 14 assertions. Get the clock mental model right today and everything downstream falls into place.
“The clock is like a loop counter. Every time the clock ticks, the always @(posedge clk) block runs once, statement by statement.”
The clock is a capture signal. On each rising edge, every flip-flop simultaneously snapshots its D input. Between edges, combinational logic churns continuously — settling on what will become the next D values. The code describes the structure; the clock just says “snapshot now.”
always @(posedge clk) block doesn't take 100× longer to “run” than a 1-line one. All flops capture in parallel. The length of the block affects routing and area, not time.
On each positive edge, every flip-flop captures its input. Between edges, combinational logic computes next values.
This is Register Transfer Level (RTL) — the fundamental abstraction of synchronous design.
Frequency: 25 MHz crystal oscillator (pin 15)
Period: 1 / 25,000,000 = 40 ns
Problem: 25 MHz is far too fast for human eyes (persistence of vision kicks in around 24-60 Hz).
Solution: Clock divider — your first real sequential design!
always @(posedge clk).
// Divide-by-N: toggle o_clk_div every N cycles of i_clk
// (small N = 4 here so the waveform below is readable;
// on the Go Board, N = 12_500_000 gives 1 Hz toggle = 1 s period)
reg [2:0] r_count = 3'd0;
reg r_clk_div = 1'b0;
always @(posedge i_clk) begin
if (r_count == 3'd3) begin
r_count <= 3'd0;
r_clk_div <= ~r_clk_div; // toggle on terminal count
end else begin
r_count <= r_count + 1'b1;
end
end
assign o_clk_div = r_clk_div;
~3 minutes · one clock, one counter, one toggle
▸ COMMANDS
cd lecture_examples/week1_day04/d04_s1_ex4/
make sim # iverilog testbench (10 checks)
make stat # yosys synth_ice40 (1 counter + 1 flop)
make prog # full flow → flash the Go Board
▸ EXPECTED ON HARDWARE
LED1: 1 s ON, 1 s OFF (period 2 s)
LED2: OFF
LED3: OFF
LED4: OFF
driven by ONE 25 MHz clock
▸ THE IDEA
▸ TAKEAWAY
One clock, one counter, one terminal value → one LED you can see blink at human speed. Same always @(posedge i_clk) pattern with T = CLK_HZ - 1. The other three LEDs are tied to 1'b0 — pure visual focus on the single divider before we generalize the math in segment 4.
always @(posedge i_clk) begin
r_q <= r_d; // D flip-flop: capture on rising edge
end
On every rising edge, r_q captures r_d. Between edges, r_q holds.
A D flip-flop — the 1-bit memory element of synchronous design. On iCE40: an SB_DFF primitive.
posedge clk in the sensitivity list, reg-declared LHS, <= for the assignment. Miss any of the three and you've written something that isn't a synchronous flip-flop.
// Three attempts at a D flip-flop. Which work?
// Attempt 1:
always @(posedge clk) q = d;
// Attempt 2:
always @(clk) q <= d;
// Attempt 3:
always @(*) q <= d;
= — OK for a single register, but catastrophic if the block grows. Don't write this.
(2) Triggers on any transition of clk (both edges) — synthesis warns, behavior unpredictable. Wrong.
(3) Combinational sensitivity with nonblocking — pointless and produces a latch. Very wrong.
Given d toggles at 10 MHz and clk is 25 MHz, sketch q:
q updates on each posedge clk, capturing whatever d was a few picoseconds before the edge. Here d rises and falls cleanly between edges, so q tracks one cycle later. When d changes near an edge, the sample becomes unpredictable — a metastability hazard covered on Topic 5.
~4 minutes
▸ COMMANDS
cd lecture_examples/week1_day04/d04_s3_ex2/
make sim # iverilog testbench
make wave # GTKWave
make stat # yosys synth_ice40
▸ EXPECTED STDOUT
PASS: d=1 → q=1 after edge
PASS: d=0 → q=0 after edge
PASS: q stays through many
cycles when d stable
=== 8 passed, 0 failed ===
▸ CIRCUIT
▸ GTKWAVE
Add clk · d · q. Look for: q transitions happen right after each posedge of clk, never between edges. The step-function shape is the visual signature of synchronous design.
$ make stat # yosys synth_ice40 on day04_ex01_d_flip_flop.v
=== d_flip_flop ===
Number of wires: 4
Number of cells: 1
SB_DFF 1 ← one flip-flop, finally!
SB_LUT4 0
SB_DFFs. Now we have one. This is the first hardware primitive that remembers — the building block of every sequential design you'll write.
SB_DFF is a positive-edge-triggered D flip-flop with synchronous set/reset capability. There are ~1200 of them on the HX1K. That's your “state budget” for any design.
Ask AI: “In Verilog, why does always @(posedge clk) q <= d; create a flip-flop, but always @(*) q <= d; does not?”
TASK
Ask AI: why the sensitivity list determines the storage.
BEFORE
Predict: posedge = edge-triggered storage = flop. @(*) = level-sensitive = combinational or latch.
AFTER
Strong AI mentions edge-trigger semantics explicitly. Weak AI says “because of the clock” without explaining why.
TAKEAWAY
The sensitivity list is structural: it describes the kind of hardware to build.
① Clock edges define when state changes — always @(posedge clk).
② Between edges, combinational logic computes next values.
③ Go Board: 25 MHz. To make visible events, divide the clock.
④ This is RTL — the design abstraction used everywhere.
🔗 Transfer
Video 2 of 4 · ~12 minutes
▸ WHY THIS MATTERS NEXT
You used <= in the D-flop example without really understanding why. Video 2 makes it rigorous with a side-by-side waveform demo: same shift-register code, one with = and one with <=, and you'll see the blocking version collapse.