Features:
- Formal verification: TEC30 was formally verified using SymbiYosys, providing strong assurance of correct operation when implemented on a functioning board.
- Vendor-specific optimization: TEC30 includes an X7 version specifically tailored
for Xilinx commercial 7-series boards, reducing the amount of the layout left to Vivado's heuristics.
- Small footprint: At just 160 LUTs, only 40 more than SERV, TEC30 provides a C-programmable core with improved CPI.
- Modularity: TEC30 was designed with a modular architecture. Users can customize which peripherals
the final SoC includes by changing a parameter in the Verilog instantiation.
- Customizable memory model: TEC30 can be connected to BRAM in a pure Harvard configuration,
or adapted to a modified or hybrid Harvard configuration for operating-system support.
- Open source: TEC30 is distributed under the CERN-OHL-S-2.0 license and may be redistributed
according to its terms.
- Simplicity: TEC30's compact design makes its implementation easy to inspect and reason about,
including at the cycle-by-cycle level.
- Performance: The maximum clock frequency of the bare TEC30 core is well above 200 MHz.
Downloads
TEC30 can be cloned from its repo, by running this command:
git clone https://github.com/LoPalma/tec30
The repo includes an assembler, verification suite, tests, and synthesizable RTL files.
As for the C toolchain, it hasn't been published yet. For updates on its publishing you
can refer to my blogposts (scroll to the bottom of the page).
Quickstart
Once you cloned the repo, embedding TEC30 is a matter of seconds.
Specifically, by copying this verilog down here, you'll be embedding a fully ready tiny SoC known as TEC30X7U:
tec30_x7u #(
.ALU_IMPL(0) // change to 1 if you're not using a Xilinx 7 series FPGA
.MEM_MODEL(0) // 0 = pure harvard, 1 = modified/hybrid harvard
) u_board (
// of course ensure you have declared the signals before plugging them here
.clk(clk),
.btn(rst_btn),
.rx(uart_rx),
.tx(uart_tx)
)
If you wish to build your own SoC, you can do that using the tec30_soc toplevel, as follows:
logic rst;
tec30_reset u_rst (.clk(clk), .btn(rst_btn), .rst(rst));
tec30_soc #(
.ALU_IMPL(0) // change to 1 if you're not using a Xilinx 7 series FPGA
.MEM_MODEL(0) // 0 = pure harvard, 1 = modified/hybrid harvard
.CODE_WORDS(16384) // to set instruction memory
.DATA_WORDS(65535) // to set data memory
.CODE_HEX("path/to/code.hex")
.DATA_LO_HEX("path/to/data_lo.hex")
.DATA_HI_HEX("path/to/data_hi.hex")
.HAS_UART(1)
// and so on so forth for every peripheral you (don't) want
)
That code instantiated TEC30X7U, just in extra steps to demonstrate the composability of TEC30.
You can also work with TEC30's bare core directly, without using tec30_soc's abstractions.
This is by far the most verbose way to start using TEC30:
tec30 #(.ALU_IMPL(0)) cpu (
.clk(clk),
.rst(rst),
.ibus_adr(ibus_adr),
.ibus_rdy(ibus_rdy),
.ibus_data(ibus_data),
.ibus_vld(ibus_vld),
.ibus_eom(ibus_eom),
.dbus_adr(dbus_adr),
.dbus_rdy(dbus_rdy),
.dbus_we(dbus_we),
.dbus_wdata(dbus_wdata),
.dbus_data(dbus_data),
.dbus_vld(dbus_vld),
.dbus_eom(dbus_eom),
.dbg_MP(), .dbg_PC(), .dbg_C_flag(), .dbg_Z_flag(),
.dbg_opA(), .dbg_opB(), .dbg_state(), .dbg_instr()
);
With that, you interface directly with the Q-bus master and gain access to debug signals.
Happy hacking!
Development
TEC30 is developed on github by me.
You can read about my shenanigans and various "adventures" in which I learn just how nice it would be to have a teacher
at the bottom of this page. Just click on one of those links and enjoy.