RTL Design #2 · 2026-09-25 · Clock crossing · Medium · about 15 min
A counter that skips across clocks
A 4-bit event counter runs in clk_a and is read in the unrelated clk_b domain. The word you send across, cross_a, comes back to you as cross_b after a two-flop synchronizer on every bit.
The design in design.sv sends the binary count. Now and then cnt_b shows values the counter never held, for example 0111 → 1111 → 1000.
Fix it so every value of cnt_b is a count the counter really reached. cnt_b may lag the counter by a few cycles, but it must never jump or run ahead, and it must catch up once events stop.
Simulators have no metastability, so the testbench models the synchronizer: each bit that changed just before a clk_b edge may land on that edge or the next, the way real flops resolve. Run shows what that does to the current design.
Write and run your answer in the browser. The hidden tests check it, and it’s free.