Close
0%
0%

Tridora-CPU

a homebrew FPGA CPU with a native Pascal compiler and a simple development environment

Similar projects worth following
Tridora is a homebrew CPU written in Verilog and a matching software environment, including a Pascal compiler and assembler. Everything was created from the ground up (except soldering stuff). Everything is as simple as possible while still being reasonably useful. Everything is open source, so you can read, understand and modify the whole system, hardware and software.

Overview

  • homebrew CPU written in Verilog implemented on an FPGA
  • 32-bit word-oriented stack machine architecture
  • running at 77 MHz on an Arty-A7 board with four clocks per instruction
  • has its own instruction set architecture, compatible with nothing
  • additional IO controllers on FPGA: UART (serial console), SD-Card, VGA
  • Pascal compiler written from zero
  • CPU and compiler were designed together
  • minimal operating system
  • editor, compiler, assembler run natively
  • so you can develop programs directly on the machine
  • small: CPU has ~500 lines of Verilog, compiler ~9000 LoC
  • compiler written in Pascal and can compile itself
  • cross-compiler/-assembler can be compiled with FPC
  • compiler does its own Pascal dialect with some restrictions and some extensions
  • emulator available here

The name comes from a certain fictional monster with three heads. The prefix tri- is greek for three, and the Tridora-CPU has three stacks instead of just one like almost all other CPUs. It also has a strange mixture of features from three different eras of computing:

  • a simple instruction set without integer multiply/divide like an 8-bit CPU
  • speed is like a fast 16-bit CPU, also 16-bit instruction words
  • 32-bit word size from the 32-bit era

It might remind you of the UCSD-P-System and early Turbo-Pascal versions.

Other inspirations were, among others, in no particular order:

  • the Novix 4016 CPU (a stack machine CPU designed for Forth, mainly by Charles Moore)
  • the J1 CPU by James Bowman (which is not entirely unlike the Novix 4016)
  • the Lilith computer by Niklaus Wirth and his team (a stack CPU designed for Modula-2)
  • the PERQ workstation (also a stack CPU designed for Pascal)
  • the Magic-1 by Bill Buzbee
  • the OPC by revaldinho

Source Repository

  Sources are published on Gitlab.

Supported Boards

  • Arty A7-35T (with two PMODs for microSD cards and VGA output)
  • Nexys A7 (planned)

Demo Videos

   See the README on Gitlab or the YouTube channel.

Pascal Language

  • Wirth Pascal
  • no function/procedure pointers
  • arbitrary length strings (2GB)
  • safe strings (runtime information about max/current size)
  • tiny sets (machine word sized), that means no SET OF CHAR
  • array literals with IN-operator, which can replace most uses of SET OF CHAR
  • nested procedures with some limitations
  • 32 bit software floating point with low precision (5-6 digits)
  • break and exit statements, no continue yet
  • static variable initialization for global variables
  • non-standard file i/o (because the standard sucks, obl. XKCD reference)

Standard Library

  • everything from Wirth Pascal
  • some things from TP3.0
  • some graphics functionality (to be expanded in the future)

Operating System

  • not a real operating system, more of a program loader
  • some assembly routines for I/O resident in memory
  • one program image loaded at a time at a fixed address
  • most parts of the operating system are contained in the program image
  • file system is very primitive: only contiguous blocks, no subdirectories
  • simple shell reminiscent of TP3.0, edit, compile, run programs

Building the Compiler

  • you need to have FPC and Python3 installed
  • on Linux, you need make installed
  • in the pcomp directory, run make (or make.bat on Windows)
  • on Linux, you can also run make nativeprogs and make examples

Getting the ROM image

  • there are two formats for the ROM image, one for the emulator (rommon.prog) and one for building the FPGA bitstream (rom.mem)
  • to get the rommon.prog file, either copy it from the tridoraemu package file or build it
  • for rom.mem and rommon.prog, find both files in the lib directory after running make nativeprogs (or make.bat) in the pcomp directory (see above)

Building the FPGA bitstream

  • install Vivado (known to work with 2024.2)
  • install the package for your board in Vivado (Tools -> Vivado Store -> Boards)
  • copy the ROM image (rom.mem) into the tridoracpu directory (see above)
  • start Vivado and open the project file tridoracpu.xpr in the tridoracpu directory
  • run synthesis, implementation and bitstream generation (Flow -> Generate Bitstream)...
Read more »

  • October 2025 Update - Data Cache and Audio

    slederer10/14/2025 at 21:07 0 comments

    The October 2025 Update is here!

    With this update of the logic design, the Tridora-CPU now has a data cache. It is very similar to the instruction cache that was added with the April 2025 update: It caches the 16 bytes that the DRAM controller delivers anyway.

    For decent performance, it had to be implemented as a write-back cache. So when a write to the cached area happens, the cache is not invalidated (as in the simpler write-through cache). Instead, the write is going to RAM and will update the cache. This is because with the stack machine architecture and especially in the code generated by the Pascal compiler, it is very common to read, write and read again the same variable. So a write-through cache would be invalidated quite often and would have a much worse performance.

    Fortunately, the write-back cache was easier to implement than I thought, and the result is really noticable.

    Building the "hello,world" program now takes about 15 seconds instead of 20.

    There were also some minor tweaks for the SD-Card controller so it has a slightly higher transfer rate, and that brings down the build time to about 14 seconds.

    Updated benchmark results are here:

    https://gitlab.com/slederer/Tridora-CPU/-/blob/main/examples/benchmarks.results.text

    In comparison to the version without instruction and data cache, the new version has a three times better performance in the empty loop benchmark. In comparison to the last version with instruction cache, the improvement is factor 1.6.

    The other important thing in the October 2025 is the audio controller. The Tridora-CPU can now make sounds, using a Digilent AMP2 PMOD. At first, I implemented four channels of rectangle waves and a noise generator. Then I scrapped that and went for interrupt-driven sample playback. So now you can play a sample file in the background from your Pascal programs.

    Here is a video of the Tridora-CPU making some noises and playing music: 

  • ECL-Rogue on the Tridora-CPU: A Porting Adventure

    slederer05/27/2025 at 21:59 0 comments

    I have also been working on the software side, fixing bugs in the compiler and assembler that showed up when compiling more complex software.

    The latest result is ECL-Rogue: A variant of the well-known game Rogue that was originally written in C on Unix. This version is written in Pascal, and it was written for the Pascal-Compiler on the PDP-10, a 36-Bit word-oriented mainframe computer from the 1970s.

    It took many small changes to make it compile with Tridora-Pascal (and FreePascal), and there were also parts written in PDP-10 assembly language (e.g. accessing the score file) and system calls to the TOPS-20 operating system that needed to be rewritten.

    Apparently the PDP-10 Pascal compiler was very close to the original Pascal compiler from Niklaus Wirth and his team, and that means: No strings! Just packed array of char, padded with spaces. That required a lot of little changes. I also noticed that Tridora-Pascal is a lot stricter than FreePascal when accessing strings: In FreePascal (and Turbo-Pascal in the good old days), it is not an error to read/write chars beyond the current end of the string. So, more of those little changes.

    But in the end, I got it working while keeping the source code mostly the same, and now you can play ECL-Rogue on the Tridora-CPU. You can also compile it with FreePascal.

    Link to the source repository of the ported version (see the README there for the original version):

    https://gitlab.com/slederer/ecl-rogue-m

    Check out this video of me playing:

    The Tridora emulator image has also been updated to include ECL-Rogue.

  • The Tridora Got an Instruction Cache

    slederer05/27/2025 at 21:40 0 comments

    There have been a few updates to the Tridora-CPU:

    The clock frequency was reduced from 83MHz to 77MHz to allow for some additions to the Verilog code: I have at last implemented an instruction cache.


    Now on the Tridora-CPU, the first 64KB of RAM are static RAM (created from BRAM). The rest is DRAM (256MB on the Arty-A7), and this is accessed via a memory controller generated my MIG, the Memory Interface Generator in Vivado. This memory controller has a latency of 21 cycles and always transfers at least 16 bytes. Good for bursting data to cache lines in modern CPUs, not optimal for my simplicistic design.

    To make matters worse, the CPU uses 32-bit words, but 16-bit instructions. So for an instruction fetch, the CPU reads 32 bits, then throws half of them away to get the instruction. For the next instruction, it will fetch the same 32 bits again, then throw the other half away to get the second instruction in that 32 bit word. This does not matter when executing out of SRAM, but is really bad when executing out of DRAM.

    So an instruction cache was needed. I added a signal from the CPU that indicates an instruction fetch (in contrast to a data read/write), and implemented a simple caching mechanism that just stores the 16 bytes from the last read, and satisfies the read request from that if the read address is in the same 16-byte segment.

    In the optimal case, 8 instructions will now take 53 clock cycles instead of 200.

    I have created a benchmark program in Pascal for some measurements, and in some benchmarks the improvement is about factor two.

    In others, it is less noticable, depending on the amount of data memory accesses which are not cached. Also, some benchmarks exercise operations which are assembly subroutines which reside in SRAM, for example, integer multiplication or all floating point operations.

    Many programs do not run noticably faster though, because they fit inside the first 64KB of RAM. For the benchmark to show any difference, I had to hack the assembly code to move the code above the 64KB boundary.

    The full benchmark results can be seen here: https://gitlab.com/slederer/Tridora-CPU/-/raw/main/examples/benchmarks.results.text

    This is the benchmark source code: https://gitlab.com/slederer/Tridora-CPU/-/raw/main/examples/benchmarks.pas

  • Reduced Compile Times with new Assembler Feature

    slederer11/18/2024 at 00:46 0 comments

    The assembler got a new feature to decrease compile/assembly times.

    It can now import preassembled binaries, which is used for the standard library.

    This is not really a linker, because it cannot do relocation. So it can only import one binary at a fixed address, but that is good enough for now.

    Compiling and assembling "Hello World" now takes 20 seconds instead of 60.

    See the video showing this feature in action:

View all 4 project logs

Enjoy this project?

Share

Discussions

Ed S wrote 10/23/2024 at 06:30 point

Splendid and marvellous!

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates