Legend has it that if you can synthesize these cores to run at exactly 88 MHz, they will resonate with the fabric of time and allow your Field Programmable Gate Array to tap into the echoes of gaming's past, conjuring a bygone era where classic games roam free, untethered from the shackles of DRM.
...or at least this is my FPGA playground for now.
- Current & Future Architectures
- Prelude
- PASM - the Prelude ASseMbler
- Prelude - A single cycle 8 bit CPU inspired by the "Overture" architecture from Turing Complete.
- Limb - A single cycle 8 bit CPU inspired by the "LEG" architecture from Turing Complete, which was in turn inspired by the real world "ARM" architecture. Clearly some sort of limb inspired architecture.
- ShinyRock16 - A completely bespoke 16 bit CPU supporting variable length instructions that I originally designed in the game "Turing Complete"
- McFly - A simple as possible single cycle RISC-V 32 bit (RV32I compliant as possible) core
- TBD - Multi cycle 8 bit CPU
- TBD - Multi cycle RISC-V RV32I CPU
LMC - A python emulator for a Little Man Computer LC3 - Possible future design.
Names ideas - Great Scott, Marty, Biff, Brown Byte, Peach
┳┳┓ ┏┓ ┓
┃┃┃ ┏ ┣ ┃ ┓┏
┛ ┗ ┗ ┻ ┗ ┗┫
┛
- Seymour - SIMD vector unit
##### ## ### ##
###### /### ### ##
/# / / ### ## ##
/ / / ### ## ##
/ / ## ## ##
## ## ## ### /### /## ## ## ### ### ## /##
## ## ## ###/ #### / / ### ## ## ### / ######### / ###
/### ## / ## ###/ / ### ## ## ###/ ## #### / ###
/ ### ## / ## ## ### ## ## ## ## ## ## ###
## ######/ ## ######## ## ## ## ## ## ########
## ###### ## ####### ## ## ## ## ## #######
## ## ## ## ## ## ## ## ## ##
## ## ## #### / ## ## /# ## /# #### /
## ## ### ######/ ### / ######/ ## ####/ ######/
## ## ## ### ##### ##/ ##### ## ### #####
### # /
### / Prelude
#####/ ... A tribute to "Overture"
###
Inspired by Overture from the game Turing Complete
- 8 bit single cycle processor
- 8 bit instruction words
- 6 general purpose registers (r0-r5)
- 1 i/o register (r6/rio)
- 1 program counter (pc) register
- 256 bytes of program ROM
TODO:
- optimize signal routing
- connect reset line to register file to reset all registers to 0
possible future upgrades:
10 bit instruction words to allow encode of full 8 bit immediate values. a UART module to send and receive data from a host computer. a RAM interface controlled by an existing register that has no other purpose. shift and/or rotate instructions. a load high and low nibble version of the load immediate instruction. carry select adder for a performance boost over the standard ripple carry. halt instruction to stop the processor. this could be accomplished with a load address of next instruction and branch always as next instruction.
a RAM interface is a bit more LEG than Overture in the game Turing Complete, but it would allow for more complex programs to be run on the system as we are limited to registers with the original overture design.
i think a first go at the RAM interface would be flip flop based SRAM on my Tang Nano 20k but i think it would be interesting to try to implement a DRAM interface but that might be left for the LEG tribute chip.
upper 2 bits | instruction type |
---|---|
00zzzzzz | IMMEDIATE (load lower bits into r0) |
01zzzzzz | CALCULATE (see calc ops) |
10zzzzzz | COPY (see copy ops) |
11zzzzzz | BRANCH |
Set R0 = lower 6 bit of instruction
Lower 6 bits specify ALU operation. R3 = R1 (calc op) R2
ALU Operation Bits | Operation | Notes |
---|---|---|
000000 | OR | R3 = R1 or R2 |
000001 | NAND | R3 = ~(R1 and R2) |
000010 | NOR | R3 = ~(R1 or R2) |
000011 | AND | R3 = R1 and R2 |
000100 | ADD | R3 = R1 + R2 |
000101 | SUB | R3 = R1 - R2 |
000110 | XOR | R3 = R1 ^ R2, Prelude specific |
Copy instructions use the lower 6 bits to specify source and destination registers.
Register Address | Register Name | Description |
---|---|---|
000 | R0 | IMMEDIATE destination, BRANCH destination |
001 | R1 | CALCUATE source 1 |
010 | R2 | CALCUATE source 2 |
011 | R3 | CALCUATE destination, BRANCH comparison value |
100 | R4 | General purpose |
101 | R5 | General purpose |
110 | R6 | General purpose |
111 | R7 | Special I/O register |
Condition bits | Condition | Notes |
---|---|---|
000 | Never | No op, never take branch |
001 | R3 == 0 | |
010 | R3 < 0 | |
011 | R3 <= 0 | |
100 | Always | |
101 | R3 != 0 | |
110 | R3 >= 0 | |
111 | R3 > 0 |
I have written an assembler for Prelude that generates three output targets - a raw binary file, a Turing Complete compatible .txt file and a SystemVerilog Look-Up-Table (LUT)
As of 12/12/2024 all turing complete Overture levels have had solutions assembled and tested in game.
The guide will help you use the Prelude Assembler to convert your Prelude assembly files into binary, Verilog, and Turing Complete ROM images.
- Python 3.x installed on your system
- Basic knowledge of Prelude assembly language
-
Prepare your assembly file: Create a text file with your Prelude assembly code. Ensure the file follows the format described below.
-
Run the assembler: Use the following command to run the assembler:
python3 pasm.py <input_file>
Replace
<input_file>
with the path to your assembly file. -
Output files: The assembler will generate three output files in the same directory as your input file:
<input_file>.bin
: Binary file<input_file>.sv
: Verilog file<input_file>.txt
: Turing Complete ROM image
- Labels: End with a colon (
:
) and are used to mark addresses. - Instructions: Case insensitive and must be on their own lines.
- Constants: Defined using the
CONST
directive (e.g.,CONST MYCONST 42
). - Comments: Begin with a semicolon (
;
) and can be placed at the end of a line.
; full line comment
const five 5
const THREE 3 ; in-line comment
start:
LOAD five ; load 5 into R0
COPY R0 R1 ; R1 = R0 (5)
LOAD tHrEe ; load THREE into R0
COPY R0 R2 ; R2 = R0 (3)
add_more:
ADD ; R3 = R1 + R2
COPY R3 RIO ; RIO = R3
COPY R3 R1 ; R1 = R3
LOAD add_more ; load add_more into R0
BRA ; branch always to address in R0
- The assembler will prompt you to overwrite existing output files if they already exist.
- Ensure that immediate values for the
LOAD
instruction are within the range 0-63.
For more information, visit the GitHub repository.
LOAD <immediate>
: Load an immediate value into R0 (0-63).
OR
: R3 = R1 OR R2NAND
: R3 = R1 NAND R2NOR
: R3 = R1 NOR R2AND
: R3 = R1 AND R2ADD
: R3 = R1 + R2SUB
: R3 = R1 - R2XOR
: R3 = R1 XOR R2SHL
: R3 = R1 << R2
COPY <src> <dst>
: Copy the value from the source register to the destination register.
BRN
: Branch never (NOP)NOP
: No operation (alias for BRN)BZ
: Branch if R3 == 0BLT
: Branch if R3 < 0 (signed)BLE
: Branch if R3 <= 0 (signed)BRA
: Branch alwaysBNZ
: Branch if R3 != 0BGE
: Branch if R3 >= 0 (signed)BGT
: Branch if R3 > 0 (signed)
JZ
: Jump if R3 == 0JLT
: Jump if R3 < 0 (signed)JLE
: Jump if R3 <= 0 (signed)JUMP
: Jump always (alias for BRA)JMP
: Jump always (alias for BRA)JNZ
: Jump if R3 != 0JGE
: Jump if R3 >= 0 (signed)JGT
: Jump if R3 > 0 (signed)
patorjk for the ASCII art