- SystemVerilog 51.3%
- Python 40.4%
- Assembly 6.4%
- Makefile 1.5%
- Dockerfile 0.4%
|
|
||
|---|---|---|
| .devcontainer | ||
| .vscode | ||
| docs | ||
| rtl | ||
| src | ||
| sw | ||
| tb | ||
| tools | ||
| .gitignore | ||
| .rules.verible_lint | ||
| .verible-verilog-format | ||
| AGENTS.md | ||
| info.yaml | ||
| LICENSE | ||
| Makefile | ||
| PLAN.md | ||
| README.md | ||
| TODO.md | ||
TPSM
TPSM is a general-purpose protocol emulator for a Tiny Tapeout IHP submission. The name stands for Transport-Programmed State Machine. A transport-triggered core generates and captures serial protocol waveforms. A host loads programs and data over SPI or QSPI. The design is not a copy of the RP2040 PIO. It has one instruction type, so every operation is a transport from a source port to a destination port.
The target process is IHP SG13G2 at 130 nm with the CMOS5L metal stack. The core clock is 50 MHz. The competition grants a 6 by 4 grid of 24 tiles. The design targets 12.
Status
The specification, the assembler, the instruction set simulator, and the core RTL are written. The SystemVerilog unit testbenches pass under Verilator. make cosim and make cosim-random compare the RTL with the Python model for directed programs and for random programs.
The cocotb suite in tb/cocotb/ runs the host, UART, and SPI tests on the two-bus core, and make cocotb passes. The full-duplex UART, an I2C master with clock stretching, PS/2 transmit and receive, a JTAG master, an SWD master, and CAN transmit and receive are written and tested, and each fits the 32-bundle memory. Low-Speed USB and the formal proofs for the main modules are written, and the 32-bundle design is hardened in 12 tiles. Open work is the 48 and 64 bundle area probe, gate-level simulation, and the rest of the formal properties. TODO.md holds the full list.
Protocol scope
Stage v1 covers UART, SPI, I2C, and PS/2. Stage v2 adds JTAG, SWD, and CAN. Stage v3 adds Low-Speed USB. Everything except USB is written and tested. 10BASE-T is a simulation target, because the Tiny Tapeout clock pin cannot reach 100 MHz.
Architecture at a glance
- One core with one program counter and one architectural state.
- 32-bit bundles. Each bundle holds two 16-bit transport slots, and both slots commit in the same cycle.
- 32 bundles of instruction memory.
- 8-bit transport bus and 8-bit ALU.
- Eight 8-bit registers, R0 to R7. R7 is the
PC_LOOPcounter. - Eight 8-bit constants, loaded by the host.
- 32-bit OSR and ISR, with 32-bit TX and RX FIFOs that never stall the core.
- A shift unit with independent TX and RX bit counters and bit order.
- A Line Coder for NRZI, bit stuffing, CAN arbitration, differential mode, and an oversampling receiver that tracks a start edge on its own.
- Optional extra cores, set by the
CORESparameter, that share the host bus and the pins. - A 16-bit CRC unit with separate transmit and receive contexts.
- A shared 24-bit clock divider.
- A host bus with 1-bit SPI and 4-bit QSPI modes, and burst commands.
The full specification is in docs/arch.md. The protocol programs are in docs/protocols.md. The invariants and proofs are in docs/verification.md. The goal, the settled decisions, and the platform rules are in PLAN.md. The ordered work list is in TODO.md.
Repository layout
| Path | Contents |
|---|---|
docs/ |
Architecture and protocol specifications, and the verification claims |
rtl/ |
Synthesizable SystemVerilog, one module or package per file |
tb/ |
Verilator testbenches and the shared check header |
tb/cocotb/ |
cocotb system tests and the SPI host model |
sw/ |
Assembly programs. cosim.s is the directed lockstep program |
tools/ |
Python assembler, instruction set simulator, and random lockstep |
build/ |
Generated output, not tracked |
Build and test
The build system is a Makefile.
| Target | Action |
|---|---|
make asm |
Assemble every program in sw/ |
make hex |
Alias for make asm |
make test-tools |
Run the Python tests for the assembler |
make test |
Run the Python tests and every SystemVerilog testbench |
make run-<tb> |
Run one SystemVerilog testbench, for example make run-core_loop |
make lint |
Run Verible lint |
make vlt-lint |
Run Verilator lint with all warnings |
make format |
Format the SystemVerilog with Verible |
make format-check |
Fail when a file needs formatting |
make cosim |
Compare the RTL with the ISS on the directed program |
make cosim-random |
Compare the RTL with the ISS on random programs |
make cocotb |
Run the cocotb system tests in tb/cocotb/ |
make test-all |
Run make test, make cocotb, and make cosim-random |
make formal |
Run the SymbiYosys proofs in tb/formal/ in the LibreLane image |
make formal-mutants |
Break each module on purpose and check that its proof fails |
make area |
Report the synthesized cell area with Yosys |
make clean |
Remove build/ |
Dev container and LibreLane
.devcontainer/ builds the Tiny Tapeout IHP environment. It has Verilator 5.052, Verible, uv, tt-support-tools, and LibreLane 3.0.0.dev44, and it runs the hardening tools through docker-in-docker. Open the repo in VS Code and reopen it in the container. make setup runs after creation and prepares tt/ and the cocotb environment.
| Target | Action |
|---|---|
make tt-config |
Write src/user_config.json and src/config_merged.json from info.yaml |
make synth |
Run LibreLane through Yosys synthesis only. No placement or routing. It reports the cell area in runs/synth/06-yosys-synthesis/reports/stat.rpt |
make harden |
Run the full RTL to GDS flow. This takes hours |
src/ holds symlinks to rtl/. tools/tt_config.py replaces tt_tool.py --create-user-config because the Tiny Tapeout port check cannot parse SystemVerilog packages. src/config.json sets USE_SLANG so LibreLane reads the sources with the slang frontend.
Requirements
- Verilator 5.x. The status above was checked with Verilator 5.052.
- Verible for
make lintandmake format. - Python 3 for the assembler, the ISS, and the random lockstep.
- uv for the cocotb environment in
tb/cocotb/. - Yosys for
make area. - SymbiYosys for the formal checks, when they are written.
- LibreLane for hardening and static timing analysis, when the flow is set up.
Verification
The ladder runs from lint to unit tests, then the assembler and ISS tests, then lockstep comparison against the Python model, then the cocotb system tests, then formal proofs, then hardening at 50 MHz. docs/verification.md holds the claims that each layer checks. TODO.md holds the status of each layer.
License
Licensed under the Apache License, Version 2.0. See LICENSE.
Copyright 2026 Dragos Bajanica.