Integrating the Capstone: Compile First, Run Second

A concept-level guide to wiring tiny_calc_top and the compile-first discipline Lesson 7.5 uses.

Updated 2026-07-27

tiny_calc_top instantiates your own Lesson 7.3 tiny_calc_datapath and your own Lesson 7.4 control_fsm directly, unchanged — it does not rebuild either one's internal wiring. Your job is the connections between them: control_fsm's two outputs feed a supplied load-or-compute mux, and that mux's output reaches tiny_calc_datapath's inputs.

Compile first, run second is the habit this lesson is built around. A missing or misspelled port connection is a compile error, not a wrong-output failure — Icarus Verilog reports it before any simulation runs at all. Fixing every compile error first means the checker you eventually run is testing real behavior instead of failing on a typo.

Several supplied wires are worth understanding even though they are not blanked:

  • datapath_write_en and datapath_waddr choose between two sources: a load path (seeding a known register value for the checker) and the controller's own decision.
  • datapath_alu_op chooses between a fixed ADD (while loading) and the controller's requested operation.
  • datapath_raddr_a reads register 0 — which is never written, so it stays zero — while loading, so the "operand + 0" trick that seeds a register works correctly; reading register 1 there instead would corrupt the seed with whatever value register 1 already held.

done proves a write was requested this cycle, not that it has already landed. The register file's actual write completes on the next clock edge after done pulses — the same one-cycle relationship every clocked write has to the control signal that requests it. A checker (or a real caller) that reads the stored value the instant it sees done will read stale data; it must wait one more edge.

Your own passing Lesson 7.3 and 7.4 code is supplied automatically for this lesson — you are not re-typing either one, only wiring the connections that make them work together.