Goal: Understand the specification → RTL design flow, design methodology, and why we verify.
[← Previous: N/A (First Module)] | Next: Module 2: Methodology (Part 2) →
This module focuses on methodology only (no UVM, no protocol-specific content).
- Module doc: module1/README.md
- Example: module1/examples/spec_to_rtl/ — tiny spec → RTL → simulation
For beginners: To learn how to understand a specification and translate it into RTL, read in order: UNDERSTANDING_THE_SPEC.md → SPEC_TO_RTL_GUIDE.md → spec_to_rtl WALKTHROUGH.md.
Quick run (from repo root):
cd module1/examples/spec_to_rtl
make runOr use the module script:
./scripts/module1.sh --runModule 1 establishes the design and verification mindset you will use for UART, SPI, and I²C in later modules:
- Specification → RTL: Start from a written spec (interface, behavior, timing) and implement it in RTL.
- Design methodology: How to structure a small block (spec document, RTL, testbench).
- Intro to verification: What we verify (correctness vs spec, corner cases) and why (bugs are cheaper to fix before tape-out).
- Spec-to-RTL flow: From SPEC.md (or equivalent) to synthesizable Verilog/SystemVerilog.
- Why verify: The cost of bugs, and how directed tests (and later UVM) reduce risk.
- Minimal toolchain: Verilator + Make + C++ harness for RTL simulation (no UVM in this module).
- Linux/macOS/WSL2 with a terminal
- Verilator (5.x recommended)
- GNU Make
- C++ compiler (GCC or Clang)
UVM is not required for Module 1.
- Specification: Document interface (ports, widths, direction), behavior (reset, enable, state transitions), and timing (sync/async).
- RTL: Implement the spec in Verilog/SystemVerilog; each requirement in the spec should map to clear RTL (e.g., reset logic, enable gating, counter width).
- Traceability: Being able to point from a line in the spec to the RTL that implements it (and vice versa).
- Single block: One spec, one (or a few) RTL files, one testbench.
- Reuse: The same flow (spec → RTL → testbench) scales to protocol blocks (UART, SPI, I²C) in Modules 3–8.
- Documentation: Keep SPEC.md (or similar) next to the RTL so that reviewers and verification can check against it.
- What we verify: That the RTL matches the specification (correct function, reset, enable, boundaries like count wrap).
- Why we verify: Finding bugs in RTL is far cheaper than finding them in silicon or in system integration; directed tests (and later UVM) give repeatable, automated checks.
- Directed test: A simple test that drives specific inputs (e.g., reset, then 10 enabled cycles) and checks expected outputs (e.g., count == 10). The spec_to_rtl example is a minimal directed test.
Beginners can use these guides in order:
- module1/UNDERSTANDING_THE_SPEC.md — How to read a specification: what to look for (interface, behavior, timing, edge cases), questions to answer, and a simple checklist before writing RTL.
- module1/SPEC_TO_RTL_GUIDE.md — How to translate a spec into RTL: interface → ports, timing → always block, reset → first branch, normal behavior → remaining branches, edge cases, and traceability (spec ↔ RTL).
- module1/examples/spec_to_rtl/WALKTHROUGH.md — Concrete walkthrough: the counter spec read section-by-section and each requirement mapped to the exact line in dut/counter.v.
The example in module1/examples/spec_to_rtl/ demonstrates:
| Step | Artifact | Description |
|---|---|---|
| Spec | SPEC.md | 8-bit up-counter: clk, rst_n, enable, count; behavior and timing. |
| RTL | dut/counter.v | Verilog implementation of that spec. |
| Top | top.v | Wrapper that instantiates the counter; C++ drives pins. |
| Test | sim_main.cpp | C++ harness: clock, reset, enable for 10 cycles; check count == 10. |
Run it:
cd module1/examples/spec_to_rtl
make runOptional: make run TRACE=1 to generate a VCD for waveform viewing.
verilator --version
make --versioncd module1/examples/spec_to_rtl
make run./scripts/module1.sh --check # Environment only
./scripts/module1.sh --run # Run spec_to_rtl
./scripts/module1.sh --help # OptionsBy the end of Module 1, you should be able to:
- Describe the specification → RTL flow and why a written spec matters.
- Explain what we verify (RTL vs spec) and why (cost of bugs, repeatability).
- Run the spec_to_rtl example (make run) and relate SPEC.md, counter.v, and sim_main.cpp.
- Be ready for Module 2: basic testbench patterns and UVM+SV (agents, sequences, drivers, monitors, scoreboards) and toolchain (Verilator, UVM_HOME, Make).
-
Read the spec and RTL
- Open module1/examples/spec_to_rtl/SPEC.md and dut/counter.v. Map each requirement in the spec to the corresponding RTL.
-
Run and extend the test
- Run
make runand confirm PASS. Change the test in sim_main.cpp (e.g., enable for 20 cycles and check count == 20, or test wrap from 255 to 0) and re-run.
- Run
-
Optional: Trace
- Run
make run TRACE=1and open the generated VCD in a waveform viewer. Identify clk, rst_n, enable, and count and confirm they match the spec.
- Run
- Can explain the spec → RTL flow and the role of a written specification.
- Can explain what we verify (RTL vs spec) and why verification is done.
- Can run the spec_to_rtl example and describe what SPEC.md, counter.v, and sim_main.cpp do.
- Ready to move to Module 2 (basic TB, UVM+SV, toolchain).
After completing this module, proceed to Module 2: Design & Verification Methodology (Part 2) — basic testbench (directed tests, pin wiggling), evolution to UVM+SV (agents, sequences, drivers, monitors, scoreboards), and toolchain (Verilator, UVM_HOME, Make).