Parent epic: #1476
Course id: clocks-and-cdc
Audience: hardware engineers (RTL / FPGA / ASIC).
Prerequisites: Course 1 (FPGA) modules timing and board.
Why this course
Most field failures in FPGA designs are not logic bugs but clocking bugs: a missing synchronizer, a reset released on the wrong edge, a FIFO pointer crossing domains in binary. The repo already has clock_domain, cts, fifo (gray pointers), timing and XDC emission, yet no course explains them. This is the course a hardware hiring manager asks about first.
What already exists in the repo (grounding)
fpga/clock_domain.t27 + testbench/clock_domain_tb.t27 (12 tests, currently fail in the browser runner)
fpga/cts.t27, fpga/fifo.t27 + fifo_tb (18 tests), fpga/timing.t27
pins/emitter_xdc.t27, pins/ir.t27, boards/arty_a7.t27, boards/wukong_v1.t27
tools/trios/tri/clocks.t27, fpga-rxcap.t27 (real captured traffic)
fpga/vcd_trace.t27 for waveforms
Decomposition: 9 modules x 3 lessons
Module 1 -- what-a-clock-is: the clock as a contract
| # |
Lesson id |
What the reader learns |
Spec |
Widget idea |
| 1 |
one-edge-one-world |
why synchronous design works: one edge, one state update |
fpga/clock_domain.t27 |
edge stepper: click an edge, watch every flop update at once |
| 2 |
period-and-jitter |
period, frequency, duty cycle, jitter budget |
tools/trios/tri/clocks.t27 |
jitter eye drawn from a real capture |
| 3 |
where-the-clock-enters |
clock-capable pins, the board oscillator, IBUF to BUFG |
boards/wukong_v1.t27 |
pin-map highlighting the clock-capable balls |
Module 2 -- clock-trees: distributing one edge to every flop
| # |
Lesson id |
What the reader learns |
Spec |
Widget idea |
| 4 |
skew-and-insertion |
skew vs insertion delay, why a tree and not a wire |
fpga/cts.t27 |
tree builder with per-leaf delay |
| 5 |
global-buffers |
BUFG / BUFR / BUFH and clock regions on 7-series |
fpga/cts.t27 |
clock-region map of the XC7A200T |
| 6 |
gated-clock-trap |
why gating a clock in fabric breaks timing; use a clock enable |
fpga/clock_domain.t27 |
side-by-side: gated clock vs CE, glitch shown |
Module 3 -- pll-and-mmcm: making new clocks
| # |
Lesson id |
What the reader learns |
Spec |
Widget idea |
| 7 |
multiply-and-divide |
VCO range, M/D/O dividers, legal settings |
NEW fpga/mmcm.t27 |
MMCM calculator with legality checks as spec tests |
| 8 |
phase-and-lock |
phase shift, LOCKED, holding logic in reset until lock |
NEW fpga/mmcm.t27 |
lock timeline |
| 9 |
related-or-not |
when two clocks are related (same MMCM) vs asynchronous |
fpga/timing.t27 |
relation table derived from the spec |
Module 4 -- resets: starting from a known state
| # |
Lesson id |
What the reader learns |
Spec |
Widget idea |
| 10 |
sync-or-async |
synchronous vs asynchronous reset, cost on 7-series flops |
NEW fpga/reset_sync.t27 |
LUT/FF count from a yosys run, both styles |
| 11 |
reset-release |
async assert, sync deassert; the reset synchronizer |
NEW fpga/reset_sync.t27 |
wave: release near the edge, with and without sync |
| 12 |
reset-fanout |
reset trees, why fewer resets is often better |
fpga/cts.t27 |
fanout histogram from a real netlist |
Module 5 -- metastability: what happens between 0 and 1
| # |
Lesson id |
What the reader learns |
Spec |
Widget idea |
| 13 |
setup-hold-window |
the forbidden window and what a flop does inside it |
fpga/clock_domain.t27 |
window slider: data edge vs clock edge |
| 14 |
mtbf |
MTBF formula, why two flops buy centuries |
NEW fpga/mtbf.t27 (numbers as spec tests) |
MTBF calculator, log scale |
| 15 |
two-flop-sync |
the standard synchronizer and the ASYNC_REG attribute |
fpga/clock_domain.t27 |
netlist view with ASYNC_REG placement |
Module 6 -- crossing-many-bits: when one synchronizer is not enough
| # |
Lesson id |
What the reader learns |
Spec |
Widget idea |
| 16 |
why-binary-fails |
multi-bit skew: binary counter read mid-change |
fpga/fifo.t27 |
glitch sampler showing impossible values |
| 17 |
gray-code |
one bit changes at a time; bin2gray / gray2bin |
fpga/fifo.t27 |
gray counter next to binary counter |
| 18 |
handshakes-and-pulses |
req/ack handshake, pulse synchronizer, toggle sync |
fpga/clock_domain.t27 |
two-domain timeline |
Module 7 -- async-fifo: the workhorse of CDC
| # |
Lesson id |
What the reader learns |
Spec |
Widget idea |
| 19 |
pointers-and-flags |
write/read pointers, full and empty in gray |
fpga/fifo.t27 |
FIFO animation with both pointers |
| 20 |
depth-sizing |
how deep: burst length, rate ratio, latency |
fpga/fifo.t27 |
depth calculator, spec tests as sizing rules |
| 21 |
fifo-testbench |
what fifo_tb checks and what it does not |
fpga/testbench/fifo_tb.t27 |
test-waves of the tb run |
Module 8 -- constraints: telling the tool what you meant
| # |
Lesson id |
What the reader learns |
Spec |
Widget idea |
| 22 |
create-clock |
create_clock, generated clocks, from spec to XDC |
pins/emitter_xdc.t27 |
spec -> XDC diff |
| 23 |
false-path-and-max-delay |
set_false_path vs set_max_delay -datapath_only, clock groups |
fpga/timing.t27 |
constraint picker explaining what each hides |
| 24 |
io-timing |
input/output delays, the RGMII-style source-synchronous case |
pins/emitter_xdc.t27 |
IO timing diagram |
Module 9 -- on-the-board: proof on hardware
| # |
Lesson id |
What the reader learns |
Spec |
Widget idea |
| 25 |
cdc-report |
reading a CDC / timing report from the open flow |
fpga/timing.t27 |
slack-waterfall per clock domain |
| 26 |
capture-a-crossing |
capturing a real crossing on the board |
tools/trios/tri/fpga-rxcap.t27 |
captured trace replay |
| 27 |
capstone |
build a two-clock design with an async FIFO, prove it on the board |
fpga/fifo.t27 + fpga/clock_domain.t27 |
build receipt with both clocks |
Specs that do not exist yet (write in gHashTag/t27 first)
Honesty notes and traps
- MTBF numbers depend on flop parameters that Xilinx publishes only partially; label any constant as an assumption with its source.
- Course 1 already touches timing slack and
cts.t27 (lesson timing-slack points at cts.t27); this course goes deeper and Course 1 should link here instead of duplicating.
Acceptance criteria
Blocked by: #1477 (browser test runner) for every lesson whose spec uses calls, locals or struct fields in tests.
Parent epic: #1476
Course id:
clocks-and-cdcAudience: hardware engineers (RTL / FPGA / ASIC).
Prerequisites: Course 1 (FPGA) modules
timingandboard.Why this course
Most field failures in FPGA designs are not logic bugs but clocking bugs: a missing synchronizer, a reset released on the wrong edge, a FIFO pointer crossing domains in binary. The repo already has
clock_domain,cts,fifo(gray pointers),timingand XDC emission, yet no course explains them. This is the course a hardware hiring manager asks about first.What already exists in the repo (grounding)
fpga/clock_domain.t27+testbench/clock_domain_tb.t27(12 tests, currently fail in the browser runner)fpga/cts.t27,fpga/fifo.t27+fifo_tb(18 tests),fpga/timing.t27pins/emitter_xdc.t27,pins/ir.t27,boards/arty_a7.t27,boards/wukong_v1.t27tools/trios/tri/clocks.t27,fpga-rxcap.t27(real captured traffic)fpga/vcd_trace.t27for waveformsDecomposition: 9 modules x 3 lessons
Module 1 --
what-a-clock-is: the clock as a contractone-edge-one-worldfpga/clock_domain.t27period-and-jittertools/trios/tri/clocks.t27where-the-clock-entersboards/wukong_v1.t27Module 2 --
clock-trees: distributing one edge to every flopskew-and-insertionfpga/cts.t27global-buffersfpga/cts.t27gated-clock-trapfpga/clock_domain.t27Module 3 --
pll-and-mmcm: making new clocksmultiply-and-dividefpga/mmcm.t27phase-and-lockfpga/mmcm.t27related-or-notfpga/timing.t27Module 4 --
resets: starting from a known statesync-or-asyncfpga/reset_sync.t27reset-releasefpga/reset_sync.t27reset-fanoutfpga/cts.t27Module 5 --
metastability: what happens between 0 and 1setup-hold-windowfpga/clock_domain.t27mtbffpga/mtbf.t27(numbers as spec tests)two-flop-syncfpga/clock_domain.t27Module 6 --
crossing-many-bits: when one synchronizer is not enoughwhy-binary-failsfpga/fifo.t27gray-codefpga/fifo.t27handshakes-and-pulsesfpga/clock_domain.t27Module 7 --
async-fifo: the workhorse of CDCpointers-and-flagsfpga/fifo.t27depth-sizingfpga/fifo.t27fifo-testbenchfifo_tbchecks and what it does notfpga/testbench/fifo_tb.t27Module 8 --
constraints: telling the tool what you meantcreate-clockpins/emitter_xdc.t27false-path-and-max-delayfpga/timing.t27io-timingpins/emitter_xdc.t27Module 9 --
on-the-board: proof on hardwarecdc-reportfpga/timing.t27capture-a-crossingtools/trios/tri/fpga-rxcap.t27capstonefpga/fifo.t27+fpga/clock_domain.t27Specs that do not exist yet (write in
gHashTag/t27first)fpga/mmcm.t27-- MMCM/PLL parameter legality (VCO range, dividers) as testsfpga/reset_sync.t27-- reset synchronizerfpga/mtbf.t27-- MTBF model with documented constantsHonesty notes and traps
cts.t27(lessontiming-slackpoints atcts.t27); this course goes deeper and Course 1 should link here instead of duplicating.Acceptance criteria
specs/course/<id>.t27+<id>-ru.t27exist, registered inspecs/course/courses.t27, built bycourse-from-spec.mjs(recipe:specs/course_recipe/course-27.t27).testblocks pass in the reader's browser (blocked by the browser-runner issue), or the lesson says plainly that it is a recordedtricast and links the recording.DATA_SOURCES(yosys / nextpnr / board run / spec test). No invented figures.xc7a200tfgg676vs AX7203xc7a200tfbg484vs Arty A7 / XC7A100T).body+ RUruBody.gHashTag/t27, then copied here).Blocked by: #1477 (browser test runner) for every lesson whose spec uses calls, locals or struct fields in tests.