{"id":34970538,"url":"https://github.com/howerj/subleq-vhdl","last_synced_at":"2026-04-07T14:02:17.683Z","repository":{"id":224138161,"uuid":"753843889","full_name":"howerj/subleq-vhdl","owner":"howerj","description":"SUBLEQ computer written in VHDL for an FPGA that runs Forth","archived":false,"fork":false,"pushed_at":"2024-06-06T17:41:50.000Z","size":1360,"stargazers_count":2,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-06-06T19:35:31.822Z","etag":null,"topics":["16-bit","cpu","eforth","forth","fpga","subleq","uart","vhdl"],"latest_commit_sha":null,"homepage":"","language":"VHDL","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/howerj.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-02-06T22:25:49.000Z","updated_at":"2024-06-06T17:41:54.000Z","dependencies_parsed_at":"2024-06-06T19:18:32.585Z","dependency_job_id":"82ab228b-c573-44d2-9162-7f140df7e52e","html_url":"https://github.com/howerj/subleq-vhdl","commit_stats":null,"previous_names":["howerj/subleq-vhdl"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/howerj/subleq-vhdl","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/howerj%2Fsubleq-vhdl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/howerj%2Fsubleq-vhdl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/howerj%2Fsubleq-vhdl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/howerj%2Fsubleq-vhdl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/howerj","download_url":"https://codeload.github.com/howerj/subleq-vhdl/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/howerj%2Fsubleq-vhdl/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31515151,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-07T03:10:19.677Z","status":"ssl_error","status_checked_at":"2026-04-07T03:10:13.982Z","response_time":105,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["16-bit","cpu","eforth","forth","fpga","subleq","uart","vhdl"],"created_at":"2025-12-26T23:44:31.367Z","updated_at":"2026-04-07T14:02:17.677Z","avatar_url":"https://github.com/howerj.png","language":"VHDL","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 16-bit SUBLEQ CPU written in VHDL with an eForth interpreter\n\n* Author: Richard James Howe\n* License: [The Unlicense](LICENSE) / Public Domain\n* Email: \u003cmailto:howe.r.j.89@gmail.com\u003e\n* Repo: \u003chttps://github.com/howerj/subleq-vhdl\u003e\n\n**This project is a work in progress. The VHDL simulation works, along\nwith the eForth interpreter that runs on it, but the project has not\nbeen tested on an actual FPGA (it does synthesize)**.\n\nThis project contains a 16-bit SUBLEQ CPU written in VHDL that should\nrun on an FPGA (it is unlikely to be tested in actual hardware anytime\nsoon, instead being simulation only). It has be synthesized for a\nSpartan-6 and there is nothing that stands out as indicating that the\ndesign would not work, it has just not actually been run on one (yet).\n\nIf you feel like supporting the project you can buy a book from\nAmazon, available [here](https://www.amazon.com/SUBLEQ-EFORTH-Forth-Metacompilation-Machine-ebook/dp/B0B5VZWXPL)\nthat describes how the eForth interpreter works and how to port a Forth to\na new platform.\n\nIf you are trying the eForth interpreter out on actual hardware note that you\nwill have to leave a roughly 3 millisecond delay, at minimum, between \nsending characters. This is not usually a problem when typing but can be when\nredirecting a file into the UART. This for multiple reasons, firstly the SUBLEQ\neForth is fairly slow, and secondly there is no buffering done on the UART.\n\nA block diagram of the project for those with no imagination (you can\ntell I am a programmer and not a graphic designer):\n\n![SUBLEQ System Diagram](system.png \"SUBLEQ VHDL Block Diagram\")\n\nThe C simulator running (not that characters are echoed back to the user, just\nas they would be when using a UART, this can be disabled in the SUBLEQ image\nor in your terminal):\n\n![C Simulator Running](subleq0.gif \"SUBLEQ C Simulator\")\n\nThe VHDL simulator is capable of *interactive* input and output, however\nas this already long GIF shows the simulator takes a long time to do anything\nand does not run long enough to simulate the input. Only the output is\nsimulated (the Forth interpreter prints \" ok\" followed by a newline).\n\n![Interactive and slow VHDL Simulator](subleq1.gif \"SUBLEQ VHDL Simulator\")\n\nAnd here you can see the FPGA build system running:\n\n![Building the project for an FPGA](subleq2.gif \"SUBLEQ VHDL build process\")\n\nNote that this project, unlike many other SUBLEQ CPUs written for\nFPGAs in *whatever hardware description language* implements the full machine\nwithout any *weird differences*, includes Input/Output, and halting. It\neven reads the \"standard\" format used to describe SUBLEQ programs which\nconsists of spaced delimited ASCII signed decimal values (currently                                                                    \nonly one value is allowed per line, many SUBLEQ programs are stored all                                                                \non one line with only spaces as separators).\n\nWeird/\"non-standard\" things that this implementation *avoids* include:\n\n- Not having a way to halt the CPU.\n- Having different bit widths for various operands.\n- Storing the negation of the input instead of just storing it.\n- Only being 8 bit (with 256 bytes for program storage).\n\nThe pseudo code for a SUBLEQ machine is:\n\n\twhile pc \u003e= 0:\n\t\ta = mem[pc]\n\t\tb = mem[pc + 1]\n\t\tc = mem[pc + 2]\n\t\tpc = pc + 3\n\t\tif a = -1:\n\t\t\tmem[b] = input_byte()\n\t\telse if b = -1:\n\t\t\toutput_byte(mem[a])\n\t\telse\n\t\t\tr = mem[b] - mem[a]\n\t\t\tif r \u003c= 0:\n\t\t\t\tpc = c\n\t\t\tmem[b] = r\n\t\nThis system tries to be as faithful as possible to this.\n\nA (smallish) C program equivalent to this for a 16-bit SUBLEQ\nmachine is (given 16-bit `short` integers that wrap on overflow and \nunderflow):\n\n\t#include \u003cstdint.h\u003e\n\t#include \u003cstdio.h\u003e\n\n\tint main(int argc, char **argv) {\n\t\tshort m[1\u003c\u003c13], pc = 0;\n\t\tfor (long i = 1, d = 0; i \u003c argc; i++) {\n\t\t\tFILE *f = fopen(argv[i], \"r\");\n\t\t\tif (!f)\n\t\t\t\treturn 1;\n\t\t\twhile (fscanf(f, \"%ld,\", \u0026d) \u003e 0)\n\t\t\t\tm[pc++] = d;\n\t\t\tif (fclose(f) \u003c 0)\n\t\t\t\treturn 2;\n\t\t}\n\t\tfor (pc = 0; pc \u003e= 0;) {\n\t\t\tshort a = m[pc++], b = m[pc++], c = m[pc++];\n\t\t\tif (a == -1) {\n\t\t\t\tm[b] = getchar();\n\t\t\t} else if (b == -1) {\n\t\t\t\tif (putchar(m[a]) \u003c 0)\n\t\t\t\t\treturn 3;\n\t\t\t\tif (fflush(stdout) \u003c 0)\n\t\t\t\t\treturn 4;\n\t\t\t} else {\n\t\t\t\tshort r = m[b] - m[a];\n\t\t\t\tif (r \u003c= 0)\n\t\t\t\t\tpc = c;\n\t\t\t\tm[b] = r;\n\t\t\t}\n\t\t}\n\t\treturn 0;\n\t}\n\nThere is a [simulator written in C](subleq.c) that can be used\nto run the [eForth image](subleq.dec).\n\n## Usage\n\nType:\n\n\tmake run\n\nTo run the C simulator on the [subleq.dec][] image. (Requires make\nand a C compiler, alternatively `cc subleq.c -o subleq \u0026\u0026 ./subleq subleq.dec`\nwill work.\n\nType `words` to see a list of defined Forth words.\n\n\t$ make run\n\t./subleq subleq.dec\n\t ok\n\twords\n\tcold quit load evaluate set-input get-input list\n\tblank block buffer empty-buffers flush save-buffers\n\tupdate b/buf at-xy page bell ms [if] [else] [then]\n\tdefined dump see compile-only immediate postpone \\ .(\n\t( abort\" $\" .\" exit rdrop r\u003e \u003er marker does\u003e \u003ebody user\n\tconstant variable create next aft for else repeat while\n\tthen again until if begin recurse ' :noname : ; [char]\n\tchar word definitions +order -order (order) get-order\n\tinterpret compile, literal compile find search-wordlist\n\tcfa nfa compare .s number? \u003enumber . u. u.r sign \u003c# #s #\n\t#\u003e hold parse -trailing query tib expect accept echo /\n\tmod /mod m/mod um/mod * um* d+ dnegate um+ abort throw\n\tcatch space erase fill cmove type +string count c, ,\n\tallot align aligned source 2r\u003e 2\u003er 2@ 2! source-id min\n\tmax c! c@ lshift +! pick set-current get-current cr emit\n\tkey key? ?exit execute cell- cells cell+ cell abs s\u003ed\n\tnegate within u\u003c= u\u003e= u\u003e u\u003c \u003c= \u003e= 0\u003e= 0\u003c \u003e \u003c 0\u003c= 0\u003c\u003e 0\u003e\n\t\u003c\u003e = 2dup 2drop -rot rot r@ ?dup tuck nip [ ] decimal hex\n\trp! rp@ sp! sp@ here bl span \u003ein state hld dpl base scr blk\n\tcontext #vocs pad this root-voc current \u003cok\u003e ! @ 2/ and or\n\txor invert over ) 1- 1+ 2* 0= rshift swap drop dup bye -\n\t+ eforth words only forth system forth-wordlist set-order\n\n\tbye\n\nHitting `ctrl-d` will not quit the interpreter, you must type `bye` (or\nkill with `ctrl-c` if `ctrl-d` has been used to close the input stream\nalready). This has been done for reasons of compatibility with the\nimage running on the hardware.\n\nType:\n\n\tmake\n\nOr:\n\n\tmake simulation\n\nTo run the VHDL simulation under GHDL.\n\n\tmake viewer\n\nCan be used to automatically run GTKWave on the simulation results.\n\nTo make something you can flash to a Spartan-6 FPGA for a Nexys-3 board:\n\n\tmake synthesis implementation bitfile upload\n\nThis requires Xilinx ISE 14.7 which is horrendously out of date by now,\nalong with the fact that the Nexys-3 board is obsolete (I need a new\nFPGA board).\n\nHave fun!\n\n## State machine diagram\n\nThe following shows a state-machine diagram for the SUBLEQ CPU, it is not\noptimal, but it is *simple*. There are some obvious optimizations that could\nbe done (such as going straight from `a` to the `in` state if `a` is `-1`,\nwhich would also perhaps allow us to reuse the `-1` check circuitry), these\nI/O optimizations would not help *much* as most of the time is spent doing\ncomputation. The `store` state could be skipped if the contents of the result\nregister is equal to what is loaded into the `lb` register.\n\n![SUBLEQ State Machine](subleq.png)\n\nThis is the source for the above image, which is [Graphviz][] code, this\ncan be pasted into [GraphvizOnline][].\n\n\tdigraph subleq {\n\t  reset -\u003e a;\n\t  a -\u003e b;\n\t  a -\u003e a [label = \"pause = 1\"];\n\t  a -\u003e halt;\n\t  b -\u003e la;\n\t  b -\u003e in [label = \"a = -1\"];\n\t  la -\u003e lb;\n\t  la -\u003e out [label = \"b = -1\"];\n\t  lb -\u003e store;\n\n\t  store -\u003e jmp [label=\"jmp\\nres \u003c= 0\"];\n\t  store -\u003e njmp;\n\n\t  jmp -\u003e a;\n\t  njmp -\u003e a;\n\n\t  in -\u003e in [label=\"ihav = '0'\"];\n\t  in -\u003e store;\n\n\t  out -\u003e a;\n\t  out -\u003e out [label=\"obsy = '1'\"];\n\n\t  halt -\u003e halt;\n\t}\n\n## Synthesis report\n\nThis is taken from a synthesis report (built using Xilinx ISE version 14.7) and\nedited to remove redundant information so it fits on the screen, this was taken\nfrom commit `28b35357db93a7e50f15f65377a3206afa66e265`.\n\n\t+---------------------------------------------------------------+\n\t| Module     | Slices | Slice Reg | LUTs    | BRAM/FIFO | BUFG  |\n\t+---------------------------------------------------------------+\n\t| top/       | 3/64   | 9/113     | 1/190   | 0/8       | 1/1   |\n\t| +system    | 1/37   | 0/55      | 0/124   | 0/8       | 0/0   |\n\t| ++bram     | 0/0    | 0/0       | 0/0     | 8/8       | 0/0   |\n\t| ++cpu      | 36/36  | 55/55     | 124/124 | 0/0       | 0/0   |\n\t| +uart_rx_0 | 12/12  | 24/24     | 39/39   | 0/0       | 0/0   |\n\t| +uart_tx_0 | 12/12  | 25/25     | 26/26   | 0/0       | 0/0   |\n\t+---------------------------------------------------------------+\n\t* No LUTRAM/DSP48A1/BUFIO/BUFR/DCM/PLL_ADV were used in this design.\n\nAs you can see the system is quite small. However there is still room for\nimprovement in terms of CPU size at least. A similar project,\n\u003chttps://github.com/howerj/bit-serial\u003e, implements a 16-bit bit-serial CPU,\nwhich despite having more instructions is smaller than this already quite tiny\nSUBLEQ CPU. A bit-serial SUBLEQ CPU, perhaps a project for a different time,\nwould be perhaps smaller still (whilst being much slower, glacial even).\n\n## To Do and Wish List\n\n* [x] Do core implementation\n  * [x] Debug application\n* [x] Make small SUBLEQ test programs\n* [x] Get implementation working in simulator with test programs\n  * [x] `hi.dec`\n  * [x] `hello.dec`\n  * [x] `subleq.dec` (eForth interpreter)\n    * [x] Test output\n    * [x] Test input (requires better test bench)\n  * [x] `echo.dec` (optional)\n  * [x] `self.dec` with `hi.dec` (optional)\n* Improve test bench\n  * [x] Add more run time configuration options\n  * [x] Add a UART that can print to STDOUT and read from STDIN (or a FILE)\n* [x] Using Graphviz online, make a state-machine diagram\n* [x] Make a block diagram of the system\n* [x] Use ttygif/ttyrec to record a terminal session showing the simulation, synthesis\n      and running the C simulator.\n* [x] Make cut-down and special SUBLEQ eForth image for the smaller (16KiB) BRAM\n* [x] Improve the SUBLEQ Core and system\n  * [x] Currently there is no way for the SUBLEQ core to signal that it\n        is waiting on I/O. A `paused` line when either the `pause` line\n        is asserted, or when we are waiting for input or output would\n        suffice (we can determine why from other signals).\n  * [x] Instead of loading hexadecimal files, load the original signed decimal \n        files, this would simplify the build process and allow `hex.c` to be\n        removed.\n    * [x] Allow multiple numbers per line (NOTE: Solution does not synthesize,\n          so it has been commented out).\n  * [x] Use the UART from [Nandland](https://nandland.com/) instead of my own, \n        it appears to be smaller and simpler (which would aid in simulation).\n        It is also MIT licensed (or the version I have is).\n  * [x] Optionally generate the UART test benches in the top level component\n        as well as directly intefacing with `system.vhd` (again, optionally)\n  * [x] Optimize number of states needed to execute a SUBLEQ instruction and \n        transitions in CPU (down from 8 to 6).\n  * [x] Hook up `blocked` and `halted` to an LED? (The `blocked` line would\n        need some kind of pulse lengthening to become visible) (will not do)\n  * [x] Find way of interacting with other hardware (A mechanism has been\n        proposed, but not implemented).\n  * [x] Optimize SUBLEQ design for slice area (and speed if possible) (further\n        improvements are always possible...)\n* [ ] Make one big VHDL file containing an initial Forth image and place it in `subleq.vhd`?\n  * [x] Add a component that combines the Block RAM and SUBLEQ into one along\n    with a test bench for it\n  * [x] Merge new module into main system.\n  * [ ] Make a big file with everything in it.\n* [ ] Get implementation working in hardware (need an FPGA board for this)\n\n## Other SUBLEQ projects\n\n* \u003chttps://github.com/howerj/subleq\u003e\n* \u003chttps://github.com/howerj/subleq-forth\u003e\n* \u003chttps://github.com/howerj/subleq-js\u003e\n* \u003chttps://github.com/howerj/subleq-perl\u003e\n* \u003chttps://github.com/howerj/subleq-python\u003e\n* \u003chttps://github.com/pbrochard/subleq-eForthOS\u003e\n\n## References\n\n* \u003chttps://en.wikipedia.org/wiki/Forth_(programming_language)\u003e\n* \u003chttps://en.wikipedia.org/wiki/One-instruction_set_computer\u003e\n* \u003chttps://github.com/howerj/bit-serial\u003e\n* \u003chttps://github.com/howerj/embed\u003e\n* \u003chttps://github.com/howerj/forth-cpu\u003e\n* \u003chttps://rosettacode.org/wiki/Subleq\u003e\n* \u003chttps://stackoverflow.com/questions/2982729\u003e\n* \u003chttps://stackoverflow.com/questions/34120161\u003e\n* \u003chttps://web.ece.ucsb.edu/~parhami/pubs_folder/parh88-ijeee-ultimate-risc.pdf\u003e\n\n[GraphvizOnline]: https://dreampuf.github.io/GraphvizOnline\n[Graphviz]: https://graphviz.org/\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhowerj%2Fsubleq-vhdl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhowerj%2Fsubleq-vhdl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhowerj%2Fsubleq-vhdl/lists"}