SystemVerilog/Verilog labs building up to a working single-cycle MIPS processor — an independent, from-skeleton implementation of 252-0028 — Digital Design and Computer Architecture (DDCA) (ETH Zürich, SAFARI group, Prof. Onur Mutlu), part of a csdiy.wiki full-catalog build.
DDCA teaches digital design bottom-up: combinational logic → sequential logic → finite-state machines → the MIPS ALU → a complete MIPS processor, using Verilog and (in the course) the Basys 3 FPGA board with Xilinx Vivado. This repository implements the simulatable portion of every lab as clean, synthesizable SystemVerilog with self-checking testbenches, and verifies each one with the open-source Icarus Verilog simulator (plus Verilator lint as a second, stricter check).
The capstone (Labs 7–9) is a full single-cycle MIPS processor following Harris &
Harris Digital Design and Computer Architecture §7.6 (the course's primary text): it
runs the canonical mipstest program and the test2 program, and its RTL is verified
cycle-by-cycle against the textbook's reference trace.
Every testbench prints Simulation succeeded only when all its checks pass. Raw logs
are in results/; the regression is reproduced by scripts/run_all.sh.
| Lab | What it implements | Verification (measured) |
|---|---|---|
| 1 — Basic circuits | 1-bit & 4-bit comparators (gate-level) | 260/260 cases pass (exhaustive) |
| 2 — Adder / FPGA | 4-bit ripple-carry adder (structural) + Basys 3 top & XDC | 512/512 cases pass (exhaustive) |
| 3 — Combinational Verilog | hex→7-segment decoder + 4-digit scan driver | 16/16 hex digits correct |
| 4 — FSM | Thunderbird tail-light Moore FSM | full L & R turn sequences correct |
| 5 — ALU | 32-bit MIPS ALU (AND/OR/ADD/SUB/SLT + andnot/ornot) | all ops correct, Verilator-clean |
| 6 — Testing the ALU | golden-model testbench (directed + 4000 random) | passes on good ALU, catches both injected bugs on buggy ALU (1503 mismatches) |
| 7 — Assembly | hand-written MIPS program (Σ 1..10) + assembler | processor computes 55 → mem[80] |
| 8 — MIPS single-cycle | full processor (controller + datapath + memories) | mipstest writes 7 → addr 84, "Simulation succeeded" |
| 9 — Performance / new instrs | processor extended with ori & bne |
test2 writes 0xFFFF7F02 → addr 84 |
The processor's execution matches the Harris & Harris reference table exactly
(full trace in results/lab8_mips_trace.log; waveform in
results/mips_singlecycle.vcd):
cyc rst pc instr aluout writedata mw readdata
2 0 00000000 20020005 00000005 00000005 0 xxxxxxxx addi $2,$0,5
3 0 00000004 2003000c 0000000c ........ 0 xxxxxxxx addi $3,$0,12
4 0 00000008 2067fff7 00000003 ........ 0 xxxxxxxx addi $7,$3,-9
5 0 0000000c 00e22025 00000007 00000005 0 xxxxxxxx or $4,$7,$2 = 7
...
14 0 00000034 ac670044 00000050 00000007 1 xxxxxxxx sw $7,68($3): mem[80]=7
15 0 00000038 8c020050 00000050 00000005 0 00000007 lw $2,80($0) = 7
17 0 00000050 ac020054 00000054 00000007 1 xxxxxxxx sw $2,84($0): mem[84]=7
The only surviving store is mem[84] = 7, which is the textbook success criterion.
- Lab 1 — Drawing Basic Circuits — 4-bit equality comparator, 1-bit magnitude comparator
- Lab 2 — Mapping Your Circuit to an FPGA — structural 4-bit adder, Basys 3 wrapper + XDC
- Lab 3 — Verilog for Combinational Circuits — hex-to-seven-segment display decoder + scan driver
- Lab 4 — Finite-State Machines — 1965 Ford Thunderbird tail-light FSM
- Lab 5 — Implementing an ALU — 32-bit MIPS ALU
- Lab 6 — Testing the ALU — self-checking testbench + buggy-ALU debug
- Lab 7 — Writing Assembly Code — MIPS test program running on the processor
- Lab 8 — Full System Integration — single-cycle MIPS processor (simulation core)
- Lab 9 — The Performance of MIPS — processor extended with
oriandbne
See PARTIAL.md for the FPGA-board-only portions (Vivado synthesis, the "snake" hardware demo) that require a Basys 3 board and are documented rather than run.
ethz-ddca/
├── lab1-comparators/ comparators.sv, tb_comparators.sv
├── lab2-adder/ adder.sv, top_basys3.sv, basys3_lab2.xdc, tb_adder.sv
├── lab3-seven-segment/ seven_seg.sv, tb_seven_seg.sv
├── lab4-fsm-thunderbird/ thunderbird_fsm.sv, tb_thunderbird.sv
├── lab5-alu/ alu.sv, top_basys3.sv, basys3_lab5.xdc, tb_alu.sv
├── lab6-alu-testbench/ alu_buggy.sv, tb_alu_golden.sv
├── lab7-assembly/ sum.asm, sum.dat, tb_asmtest.sv
├── lab8-mips-processor/ mips.sv, mips_parts.sv, top.sv, mipstest.asm,
│ memfile.dat, tb_mips.sv, tb_mips_trace.sv, tb_mips_wave.sv
├── lab9-performance/ mips2.sv, top2.sv, test2.asm, test2.dat, tb_mips2.sv
├── scripts/ run_all.sh, capture_results.sh, masm.py (MIPS assembler)
└── results/ per-lab logs, cycle trace, VCD waveform
The simulators run in a Linux environment (WSL2 Ubuntu here):
sudo apt-get install -y iverilog verilator gtkwave
# Run every lab's self-checking testbench and print a pass/fail summary:
bash scripts/run_all.sh
# Re-generate all logs + the processor trace and VCD under results/:
bash scripts/capture_results.sh
# Run one lab manually, e.g. the single-cycle processor:
cd lab8-mips-processor
iverilog -g2012 -o mips.vvp -s tb_mips \
mips.sv mips_parts.sv top.sv tb_mips.sv ../lab5-alu/alu.sv
vvp mips.vvp # -> "Simulation succeeded: wrote 7 to address 84."
# View the processor waveform:
gtkwave results/mips_singlecycle.vcdThe MIPS assembler (scripts/masm.py, pure Python) turns any supported .asm into a
$readmemh memfile:
python scripts/masm.py lab7-assembly/sum.asm lab7-assembly/sum.dat- Icarus Verilog 12.0 compiles (
iverilog -g2012 -Wall) and simulates every testbench; each printsSimulation succeeded(seeresults/*.log). - Verilator 5.020 lints the ALU and both processor cores with
-Walland exits cleanly (0 warnings) — a stricter, independent check that the RTL is well-formed. - Lab 6 is a negative test on purpose: the same golden-model testbench that passes
on the correct ALU reports 1503 mismatches on the deliberately buggy ALU
(
results/lab6_buggy_alu_caught.log), demonstrating that the verification actually catches the injected OR→XOR and subtract-carry bugs. - Lab 8 is validated cycle-by-cycle against the Harris & Harris reference trace; the
first three cycles (
20020005,2003000c,2067fff7→ aluout 5, C, 3) match the lab manual's Table 1 exactly.
SystemVerilog (IEEE 1800-2012), Icarus Verilog, Verilator, GTKWave; MIPS32 assembly; a small Python MIPS assembler. Target board for the synthesis labs: Digilent Basys 3 (Xilinx Artix-7), Vivado.
- Building a datapath + controller from primitives: the single-cycle MIPS splits neatly
into
maindec(opcode → control) +aludec(aluop+funct → ALU control) + a datapath of muxes, a register file, sign-extension, and the ALU. - The MIPS ALU's elegant subtract/SLT trick: invert B and set carry-in via
alucontrol[2], so ADD/SUB/SLT share one adder; SLT is just the sign bit ofA−B. - Adding instructions end-to-end (
ori,bne) touches every layer — a new opcode row, an ALU-decoder case, a zero-extend vs sign-extend control, and the branch logic (pcsrc = branch·zero | bne·¬zero). - Real functional verification means self-checking testbenches with a golden model and exhaustive/randomized stimulus — and proving they fail on a known-bad design.
Based on the labs of 252-0028 Digital Design and Computer Architecture (DDCA) by Prof. Onur Mutlu and the SAFARI Research Group at ETH Zürich, whose lab structure builds on Harris & Harris, Digital Design and Computer Architecture (MIPS Edition). This repository is an independent educational reimplementation; all course materials, lab manuals, and the textbook belong to their original authors. Original code here is released under the MIT License.
Course site: https://safari.ethz.ch/ddca/ · csdiy entry: https://csdiy.wiki/体系结构/DDCA/