Line 1... |
Line 1... |
# Forth computing system
|
# Forth computing system
|
|
|
| Project | Forth SoC written in VHDL |
|
| Project | Forth SoC written in VHDL |
|
| --------- | ------------------------- |
|
| --------- | ------------------------- |
|
| Author | Richard James Howe |
|
| Author | Richard James Howe |
|
| Copyright | 2013-2017 Richard Howe |
|
| Copyright | 2013-2019 Richard Howe |
|
| License | MIT/LGPL |
|
| License | MIT/LGPL |
|
| Email | howe.r.j.89@gmail.com |
|
| Email | howe.r.j.89@gmail.com |
|
|
|
![H2 build status](https://travis-ci.org/howerj/forth-cpu.svg?branch=master "Build status of the H2 Assembler")
|
![H2 build status](https://travis-ci.org/howerj/forth-cpu.svg?branch=master "Build status of the H2 Assembler")
|
|
|
Line 20... |
Line 20... |
* Create a working version of [J1][] processor (called the H2).
|
* Create a working version of [J1][] processor (called the H2).
|
* Make a working toolchain for the processor.
|
* Make a working toolchain for the processor.
|
* Create a [FORTH][] for the processor which can take its input either from a
|
* Create a [FORTH][] for the processor which can take its input either from a
|
[UART][] or a USB keyboard and a [VGA][] adapter.
|
[UART][] or a USB keyboard and a [VGA][] adapter.
|
|
|
|
All three of which have been completed.
|
|
|
The H2 processor, like the [J1][], is a stack based processor that executes an
|
The H2 processor, like the [J1][], is a stack based processor that executes an
|
instruction set especially suited for [FORTH][].
|
instruction set especially suited for [FORTH][].
|
|
|
The current target is the [Nexys3][] board, with a [Xilinx][] Spartan-6 XC6LX16-CS324
|
The current target is the [Nexys3][] board, with a [Xilinx][] Spartan-6 XC6LX16-CS324
|
[FPGA][], new boards will be targeted in the future as this board is reaching it's
|
[FPGA][], new boards will be targeted in the future as this board is reaching it's
|
Line 43... |
Line 45... |
|
|
![GUI Simulator](https://raw.githubusercontent.com/howerj/howerj.github.io/master/h2/sim2.gif)
|
![GUI Simulator](https://raw.githubusercontent.com/howerj/howerj.github.io/master/h2/sim2.gif)
|
|
|
The System Architecture is as follows:
|
The System Architecture is as follows:
|
|
|
![System Architecture](https://raw.githubusercontent.com/howerj/howerj.github.io/master/h2/system.svg)
|
|
![System Architecture](https://raw.githubusercontent.com/howerj/howerj.github.io/master/h2/system.png)
|
![System Architecture](https://raw.githubusercontent.com/howerj/howerj.github.io/master/h2/system.png)
|
|
|
# License
|
# License
|
|
|
The licenses used by the project are mixed and are on a per file basis. For my
|
The licenses used by the project are mixed and are on a per file basis. For my
|
code I use the [MIT][] license - so feel free to use it as you wish. The other
|
code I use the [MIT][] license - so feel free to use it as you wish. The other
|
licenses used are the [LGPL][], they are confined to single modules so could be
|
licenses used are the [LGPL][] and the [Apache 2.0][] license, they are confined
|
removed if you have some aversion to [LGPL][] code.
|
to single modules so could be removed if you have some aversion to [LGPL][] code.
|
|
|
# Target Board
|
# Target Board
|
|
|
The only target board available at the moment is the [Nexys3][], this should
|
The only target board available at the moment is the [Nexys3][], this should
|
change in the future as the board is currently at it's End Of Life. The next
|
change in the future as the board is currently at it's End Of Life. The next
|
Line 81... |
Line 82... |
* [pandoc][] for building the documentation
|
* [pandoc][] for building the documentation
|
* [picocom][] (or an alternative terminal client)
|
* [picocom][] (or an alternative terminal client)
|
|
|
Hardware:
|
Hardware:
|
|
|
* VGA Monitor
|
* VGA Monitor, and cable (Optional)
|
* USB Keyboard (plugs into the Nexys3 USB to PS/2 bridge)
|
* USB Keyboard (Optional) (plugs into the Nexys3 USB to PS/2 bridge)
|
* [Nexys3][] development board
|
* [Nexys3][] development board (if communication via UART only is
|
|
desired, the VGA Monitor and USB and Keyboard are not needed).
|
|
* USB Cables!
|
|
|
[Xilinx ISE][] can (or could be) downloaded for free, but requires
|
[Xilinx ISE][] can (or could be) downloaded for free, but requires
|
registration. ISE needs to be on your path:
|
registration. ISE needs to be on your path:
|
|
|
PATH=$PATH:/opt/Xilinx/14.7/ISE_DS/ISE/bin/lin64;
|
PATH=$PATH:/opt/Xilinx/14.7/ISE_DS/ISE/bin/lin64;
|
Line 95... |
Line 98... |
|
|
# Building and Running
|
# Building and Running
|
|
|
To make the [C][] based toolchain:
|
To make the [C][] based toolchain:
|
|
|
make h2
|
make embed.hex
|
|
|
To make a bit file that can be flashed to the target board:
|
To make a bit file that can be flashed to the target board:
|
|
|
make simulation synthesis implementation bitfile
|
make simulation synthesis implementation bitfile
|
|
|
Line 113... |
Line 116... |
|
|
The [C][] based CLI simulator can be invoked with:
|
The [C][] based CLI simulator can be invoked with:
|
|
|
make run
|
make run
|
|
|
Which will assemble the H2 Forth source file [h2.fth][], and run the assembled
|
Which will assemble the H2 Forth source file [embed.fth][], and run the assembled
|
object file under the H2 simulator with the debugger activated. A graphical
|
object file under the H2 simulator with the debugger activated. A graphical
|
simulator can be run with:
|
simulator can be run with:
|
|
|
make gui-run
|
make gui-run
|
|
|
Line 134... |
Line 137... |
compilation to the [J1][] core). It also provides a simulator for the system
|
compilation to the [J1][] core). It also provides a simulator for the system
|
written in [C][].
|
written in [C][].
|
|
|
*
|
*
|
|
|
|
The eForth interpreter which the meta-compiler is built on can be found at:
|
|
|
|
*
|
|
|
# Manual
|
# Manual
|
|
|
The H2 processor and associated peripherals are subject to change, so the code
|
The H2 processor and associated peripherals are now quite stable, however the
|
is the definitive source what instructions are available, the register map, and
|
source is always the definitive guide as to how instructions and peripherals
|
how the peripherals behave.
|
behave, as well as the register map.
|
|
|
There are a few modifications to the [J1][] CPU which include:
|
There are a few modifications to the [J1][] CPU which include:
|
|
|
* New instructions
|
* New instructions
|
* A CPU hold line which keeps the processor in the same state so long as it is
|
* A CPU hold line which keeps the processor in the same state so long as it is
|
high.
|
high.
|
* Interrupt Service Routines have been added.
|
* Interrupt Service Routines have been added.
|
* Larger return and data stacks
|
* Larger (adjustable at time of synthesis) return and data stacks
|
|
|
The Interrupt Service Routines (ISR) have not been throughly tested and will be
|
|
subject to the most change.
|
|
|
|
### H2 CPU
|
### H2 CPU
|
|
|
The H2 CPU behaves very similarly to the [J1][] CPU, and the [J1 PDF][] can be
|
The H2 CPU behaves very similarly to the [J1][] CPU, and the [J1 PDF][] can be
|
read in order to better understand this processor. The processor is 16-bit with
|
read in order to better understand this processor. The processor is 16-bit with
|
Line 167... |
Line 170... |
* A 64 deep return stack (up from 32 in the original [J1][])
|
* A 64 deep return stack (up from 32 in the original [J1][])
|
* A 65 deep variable stack (up from 33 in the original [J1][])
|
* A 65 deep variable stack (up from 33 in the original [J1][])
|
* A program counter
|
* A program counter
|
* An interrupt enable and interrupt request bit
|
* An interrupt enable and interrupt request bit
|
* An interrupt address register
|
* An interrupt address register
|
|
* Registers to delay and hold the latest IRQ and hold-line values
|
|
|
Loads and stores into the block RAM that holds the H2 program discard the
|
Loads and stores into the block RAM that holds the H2 program discard the
|
lowest bit, every other memory operation uses the lower bit (such as jumps
|
lowest bit, every other memory operation uses the lower bit (such as jumps
|
and loads and stores to Input/Output peripherals). This is so applications can
|
and loads and stores to Input/Output peripherals). This is so applications can
|
use the lowest bit for character operations when accessing the program RAM.
|
use the lowest bit for character operations when accessing the program RAM.
|
Line 231... |
Line 235... |
| 11 | R | Top of return stack |
|
| 11 | R | Top of return stack |
|
| 12 | [T] | Load from address |
|
| 12 | [T] | Load from address |
|
| 13 | N << T | Logical Left Shift |
|
| 13 | N << T | Logical Left Shift |
|
| 14 | depth | Depth of stack |
|
| 14 | depth | Depth of stack |
|
| 15 | N u< T | Unsigned comparison |
|
| 15 | N u< T | Unsigned comparison |
|
| 16 | set interrupts | Enable interrupts |
|
| 16 | Set CPU State | Enable interrupts |
|
| 17 | interrupts on? | Are interrupts on? |
|
| 17 | Get CPU State | Are interrupts on? |
|
| 18 | rdepth | Depth of return stk |
|
| 18 | rdepth | Depth of return stk |
|
| 19 | 0= | T == 0? |
|
| 19 | 0= | T == 0? |
|
| 20 | CPU ID | CPU Identifier |
|
| 20 | CPU ID | CPU Identifier |
|
|
| 21 | LITERAL | Internal Instruction |
|
|
|
|
|
### Peripherals and registers
|
### Peripherals and registers
|
|
|
Registers marked prefixed with an 'o' are output registers, those with an 'i'
|
Registers marked prefixed with an 'o' are output registers, those with an 'i'
|
prefix are input registers. Registers are divided into an input and output
|
prefix are input registers. Registers are divided into an input and output
|
section of registers and the addresses of the input and output registers do not
|
section of registers and the addresses of the input and output registers do not
|
correspond to each other in all cases. Unlike for RAM reads, the I/O registers
|
correspond to each other in all cases.
|
are indexed by word aligned addresses, without the lowest bit being discarded
|
|
(this should be fixed at a later date).
|
|
|
|
The following peripherals have been implemented in the [VHDL][] SoC to
|
The following peripherals have been implemented in the [VHDL][] SoC to
|
interface with devices on the [Nexys3][] board:
|
interface with devices on the [Nexys3][] board:
|
|
|
* [VGA][] output device, text mode only, 80 by 40 characters from
|
* [VGA][] output device, text mode only, 80 by 40 characters from
|
|
. This has
|
* Timer
|
been heavily modified from the original, which now implements most of a
|
* [UART][] (Rx/Tx) with a [FIFO][]
|
[VT100][] terminal emulator. This has two fonts available to it:
|
from
|
- [Terminus][]/[KOI8-R][] (Default)
|
|
- Latin [ISO-8859-15][] (Secondary Font) from
|
|
|
|
* [Timer][] in [timer.vhd][].
|
|
* [UART][] (Rx/Tx) in [uart.vhd][].
|
* [PS/2][] Keyboard
|
* [PS/2][] Keyboard
|
from
|
from
|
* [LED][] next to a bank of switches
|
* [LED][] next to a bank of switches
|
* An [8 Segment LED Display][] driver (a 7 segment display with a decimal point)
|
* A [7 Segment LED Display][] driver (a 7 segment display with a decimal point)
|
|
|
The SoC also features a limited set of interrupts that can be enabled or
|
The SoC also features a limited set of interrupts that can be enabled or
|
disabled.
|
disabled.
|
|
|
The output register map:
|
The output register map:
|
Line 274... |
Line 281... |
| oLeds | 0x4004 | LED outputs |
|
| oLeds | 0x4004 | LED outputs |
|
| oTimerCtrl | 0x4006 | Timer control |
|
| oTimerCtrl | 0x4006 | Timer control |
|
| oMemDout | 0x4008 | Memory Data Output |
|
| oMemDout | 0x4008 | Memory Data Output |
|
| oMemControl | 0x400A | Memory Control / Hi Address |
|
| oMemControl | 0x400A | Memory Control / Hi Address |
|
| oMemAddrLow | 0x400C | Memory Lo Address |
|
| oMemAddrLow | 0x400C | Memory Lo Address |
|
| o7SegLED | 0x400E | 4 x LED 8 Segment display |
|
| o7SegLED | 0x400E | 4 x LED 7 Segment display |
|
| oIrcMask | 0x4010 | CPU Interrupt Mask |
|
| oIrcMask | 0x4010 | CPU Interrupt Mask |
|
|
| oUartBaudTx | 0x4012 | UART Tx Baud Clock Setting |
|
|
| oUartBaudRx | 0x4014 | UART Rx Baud Clock Setting |
|
|
|
|
|
The input registers:
|
The input registers:
|
|
|
| Register | Address | Description |
|
| Register | Address | Description |
|
Line 392... |
Line 401... |
| X | X | X | X | X | X | X | X | IMSK |
|
| X | X | X | X | X | X | X | X | IMSK |
|
+-------------------------------------------------------------------------------+
|
+-------------------------------------------------------------------------------+
|
|
|
IMSK: Interrupt Mask
|
IMSK: Interrupt Mask
|
|
|
|
#### oUartBaudTx
|
|
|
|
This register is used to set the baud and sample clock frequency for
|
|
transmission only.
|
|
|
|
+-------------------------------------------------------------------------------+
|
|
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|
|
+-------------------------------------------------------------------------------+
|
|
| BTXC |
|
|
+-------------------------------------------------------------------------------+
|
|
|
|
BTXC: Baud Clock Settings
|
|
|
|
#### oUartBaudRx
|
|
|
|
This register is used to set the baud and sample clock frequency for
|
|
reception only.
|
|
|
|
+-------------------------------------------------------------------------------+
|
|
| 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|
|
+-------------------------------------------------------------------------------+
|
|
| BRXC |
|
|
+-------------------------------------------------------------------------------+
|
|
|
|
BRXC: Baud Clock Settings
|
|
|
|
|
#### oMemDout
|
#### oMemDout
|
|
|
Data to be output to selected address when write enable (WE) issued in
|
Data to be output to selected address when write enable (WE) issued in
|
oMemControl.
|
oMemControl.
|
|
|
Line 442... |
Line 478... |
| Address Lo |
|
| Address Lo |
|
+-------------------------------------------------------------------------------+
|
+-------------------------------------------------------------------------------+
|
|
|
#### o7SegLED
|
#### o7SegLED
|
|
|
On the [Nexys3][] board there is a bank of 7 segment displays, with a dot
|
On the [Nexys3][] board there is a bank of 7 segment displays, with a decimal
|
(8-segment really), which can be used for numeric output. The LED segments
|
point (8-segment really), which can be used for numeric output. The LED segments
|
cannot be directly addressed. Instead the value stored in L8SD is mapped
|
cannot be directly addressed. Instead the value stored in L8SD is mapped
|
to a hexadecimal display value (or a BCD value, but this requires regeneration
|
to a hexadecimal display value (or a BCD value, but this requires regeneration
|
of the SoC and modification of a generic in the VHDL).
|
of the SoC and modification of a generic in the VHDL).
|
|
|
The value '0' corresponds to a zero displayed on the LED segment, '15' to an
|
The value '0' corresponds to a zero displayed on the LED segment, '15' to an
|
Line 583... |
Line 619... |
Interrupts are lost when an interrupt with the same number occurs that has not
|
Interrupts are lost when an interrupt with the same number occurs that has not
|
been processed.
|
been processed.
|
|
|
# The Toolchain
|
# The Toolchain
|
|
|
The Assembler, Disassembler and [C][] based simulator for the H2 is in a single
|
The Disassembler and [C][] based simulator for the H2 is in a single
|
program (see [h2.c][]). This simulator complements the [VHDL][] test bench
|
program (see [h2.c][]). This simulator complements the [VHDL][] test bench
|
[tb.vhd][] and is not a replacement for it.
|
[tb.vhd][] and is not a replacement for it. The meta-compiler runs on top of an
|
|
eForth interpreter and it contained within the files [embed.c][] and
|
|
[embed.blk][]. The meta-compiler (Forth parlance for a cross-compiler) is a
|
|
Forth program which is used to create the eForth image that runs on the target.
|
|
|
|
The toolchain is currently in flux, going forward there is liable to more
|
|
integration between [h2.c][] and [embed.c][], along with changing the Embed
|
|
Virtual Machine into one that more closely resembles the H2 CPU with the long
|
|
term goal of creating a self hosting system.
|
|
|
To build it a [C][] compiler is needed, the build target "h2" will build the
|
To build both, a [C][] compiler is needed, the build target "h2" will build the
|
executable:
|
executable, h2, and "embed" will build the meta-compiler:
|
|
|
make h2
|
make h2 embed
|
|
|
And it can be run on the source file [h2.fth][] with the make target:
|
And it can be run on the source file [embed.fth][] with the make target:
|
|
|
make run
|
make run
|
|
|
The make file is not needed:
|
The make file is not needed:
|
|
|
Linux:
|
Linux:
|
|
|
cc -std=c99 h2.c -o h2 # To build the h2 executable
|
cc -std=c99 h2.c -o h2 # To build the h2 executable
|
|
cc -std=c99 embed.c -o embed # To build the embed VM executable
|
|
./embed embed.blk embed.hex embed.fth # Create the target eForth image
|
./h2 -h # For a list of options
|
./h2 -h # For a list of options
|
./h2 -T -R h2.fth # Assemble h2.fth and run it
|
./h2 -r embed.hex # Run the assembled file
|
|
|
Windows:
|
Windows:
|
|
|
gcc -std=c99 h2.c -o h2.exe # Builds the h2.exe executable
|
gcc -std=c99 h2.c -o h2.exe # Builds the h2.exe executable
|
|
gcc -std=c99 embed.c -o embed.exe # Builds the embed.exe executable
|
|
embed.exe embed.blk embed.hex embed.fth # Create the target eForth iamge
|
h2.exe -h # For a list of options
|
h2.exe -h # For a list of options
|
h2.exe -T -R h2.fth # Assemble h2.fth and run it
|
h2.exe -r embed.hex # Run the assembled file
|
|
|
A list of command line options available:
|
A list of command line options available:
|
|
|
- stop processing options, following arguments are files
|
- stop processing options, following arguments are files
|
-h print a help message and exit
|
-h print a help message and exit
|
-v increase logging level
|
-v increase logging level
|
-d disassemble input files (default)
|
-d disassemble input files (default)
|
-D full disassembly of input files
|
-D full disassembly of input files
|
-T Enter debug mode when running simulation
|
-T Enter debug mode when running simulation
|
-a assemble file
|
|
-r run hex file
|
-r run hex file
|
-R assemble file then run it
|
|
-L # load symbol file
|
-L # load symbol file
|
-S # save symbols to file
|
|
-s # number of steps to run simulation (0 = forever)
|
-s # number of steps to run simulation (0 = forever)
|
-n # specify NVRAM block file (default is nvram.blk)
|
-n # specify NVRAM block file (default is nvram.blk)
|
file* file to process
|
file* file to process
|
|
|
This program is released under the [MIT][] license, feel free to use it and
|
This program is released under the [MIT][] license, feel free to use it and
|
modify it as you please. With minimal modification it should be able to
|
modify it as you please. With minimal modification it should be able to
|
assemble programs for the original [J1][] core.
|
assemble programs for the original [J1][] core.
|
|
|
## Assembler
|
## Meta-Compiler
|
|
|
The assembler is actually a compiler for a pseudo Forth like language with a
|
The meta-compiler runs on top of the [embed][] virtual machine, it is a 16-bit
|
fixed grammar. It is a much more restricted language than Forth and cannot be
|
virtual machine that originally descended from the H2 CPU. The project includes
|
extended within itself like Forth can.
|
a meta-compilation scheme that allows an eForth image to generate a new eForth
|
|
image with modifications. That system has been adapted for use with the H2,
|
The main program can be found in [h2.fth][], which is still currently in
|
which replaced the cross compiler written in C, which allowed the first image
|
testing.
|
for the H2 to be created.
|
|
|
The assembler/compiler reads in a text file containing a program and produces a
|
The meta-compiler is an ordinary Forth program, it is contained within
|
hex file which can be read in by the simulator, disassembler, the VHDL test
|
[embed.fth][]. The meta-compiler Forth program is then used to build up an
|
bench or read in by the [Xilinx ISE][] toolchain when it generates the bit file
|
eForth image capable of running on the H2 target.
|
for the [Spartan 6][] on the [Nexys3][] board.
|
|
|
For more information about meta-compilation in Forth, see:
|
A rough [EBNF][] grammar for the language is as follows:
|
|
|
*
|
Program := Statement* EOF
|
*
|
Statement := Label | Branch | 0Branch | Call | Literal | Instruction
|
*
|
| Identifier | Constant | Variable | Location | Definition | If
|
|
| Begin | Char | Set | Pc | Pwd | Break | Mode | String | BuiltIn
|
|
Label := Identifier ";"
|
|
Branch := "branch" ( Identifier | Literal )
|
|
0Branch := "0branch" ( Identifier | Literal )
|
|
Call := "call" ( Identifier | Literal )
|
|
Set := ".set" ( Identifier | Literal | String ) ( Identifier | Literal | String )
|
|
Pc := ".pc" ( Identifier | Literal )
|
|
Pwd := ".pwd" ( Identifier | Literal )
|
|
Break := ".break"
|
|
BuiltIn := ".built-in"
|
|
Mode := ".mode" Literal
|
|
Allocate := ".allocate" ( Identifier | Literal )
|
|
Constant := "constant" Identifier Literal "hidden"?
|
|
Variable := "variable" Identifier ( Literal | String ) "hidden"?
|
|
Location := "Location" Identifier ( Literal | String )
|
|
Instruction := "@" | "store" | "exit" | ...
|
|
Definition := ":" ( Identifier | String) Statement* ";" ( "hidden" | "immediate" | "inline")
|
|
If := "if" Statement* [ "else" ] Statement* "then"
|
|
Begin := "begin" Statement* ("until" | "again" | "while" Statement* "repeat")
|
|
For := "for" Statement* ("aft" Statement* "then" Statement* | "next")
|
|
Literal := [ "-" ] Number
|
|
String := '"' SChar* '"'
|
|
Char := "[char]" ASCII ","
|
|
Number := Hex | Decimal
|
|
Decimal := "0" ... "9" ("0" ... "9")*
|
|
Hex := "$" HexDigit HexDigit*
|
|
HexDigit := ( "a" ... "f" | "A" ... "F" )
|
|
SChar := Any character except quote
|
|
|
|
Literals have higher priority than Identifiers, and comments are '\'
|
|
until a new line is encountered, or '(' until a ')' is encountered.
|
|
|
|
The grammar allows for nested word definitions, however state is held in the
|
|
lexer to prevent this.
|
|
|
|
The assembler the following directives:
|
|
|
|
.pc Set the program counter
|
|
.pwd Set the previous word pointer
|
|
.allocate Increment the program counter
|
|
.set Set location in memory
|
|
.mode Change compiler mode
|
|
.built-in Assemble built words here
|
|
|
|
|
|
There are several optimizations that can be performed, the ".mode" directive
|
|
controls whether they are active, along with controlling whether word
|
|
definitions are compiled with their headers or not. Optimizations performed
|
|
include merging a call to exit with the previous instruction if it is possible
|
|
to do so and performing tail call optimization where possible.
|
|
|
|
The built in words, with their instruction encodings:
|
|
|
|
|
|
| Word | 0 | 1 | 1 | ALU OPERATION |T2N|T2R|N2A|R2P| RSTACK| DSTACK|
|
|
|--------|---|---|---|-------------------|---|---|---|---|-------|-------|
|
|
| dup | 0 | 1 | 1 | T | X | | | | | +1 |
|
|
| over | 0 | 1 | 1 | N | X | | | | | +1 |
|
|
| invert | 0 | 1 | 1 | ~ T | | | | | | |
|
|
| + | 0 | 1 | 1 | T + N | | | | | | -1 |
|
|
| swap | 0 | 1 | 1 | N | X | | | | | |
|
|
| nip | 0 | 1 | 1 | T | | | | | | -1 |
|
|
| drop | 0 | 1 | 1 | N | | | | | | -1 |
|
|
| exit | 0 | 1 | 1 | T | | | | X | -1 | |
|
|
| >r | 0 | 1 | 1 | N | | X | | | +1 | -1 |
|
|
| r> | 0 | 1 | 1 | R | X | | | | -1 | +1 |
|
|
| r@ | 0 | 1 | 1 | R | X | | | | | +1 |
|
|
| @ | 0 | 1 | 1 | [T] | | | | | | |
|
|
| store | 0 | 1 | 1 | N | | | X | | | -1 |
|
|
| rshift | 0 | 1 | 1 | N >> T | | | | | | -1 |
|
|
| lshift | 0 | 1 | 1 | N << T | | | | | | -1 |
|
|
| = | 0 | 1 | 1 | N = T | | | | | | -1 |
|
|
| u< | 0 | 1 | 1 | N u< T | | | | | | -1 |
|
|
| < | 0 | 1 | 1 | N < T | | | | | | -1 |
|
|
| and | 0 | 1 | 1 | T & N | | | | | | -1 |
|
|
| xor | 0 | 1 | 1 | T ^ N | | | | | | -1 |
|
|
| or | 0 | 1 | 1 | T or N | | | | | | -1 |
|
|
| depth | 0 | 1 | 1 | depth | | | | | | +1 |
|
|
| 1- | 0 | 1 | 1 | T - 1 | | | | | | |
|
|
| seti | 0 | 1 | 1 | set interrupts | | | | | | -1 |
|
|
| iset? | 0 | 1 | 1 | interrupts on? | | | | | | +1 |
|
|
| rdepth | 0 | 1 | 1 | rdepth | | | | | | +1 |
|
|
| 0= | 0 | 1 | 1 | 0= | | | | | | |
|
|
| up1 | 0 | 1 | 1 | T | | | | | | +1 |
|
|
| nop | 0 | 1 | 1 | T | | | | | | |
|
|
| cpu-id | 0 | 1 | 1 | CPU ID | | | | | | +1 |
|
|
| rdrop | 0 | 1 | 1 | T | | | | | -1 | |
|
|
|
|
|
|
The language used in the assembler is Forth like, the best example of how to
|
|
use it is in the file "h2.fth", which contains a working Forth interpreter and
|
|
many Forth definitions. New words can be defined in the usual manner:
|
|
|
|
: 2+ 2 + ;
|
|
: ?dup dup if dup then ;
|
|
|
|
Control structure mismatches cause the parser to terminate with an error
|
|
condition as they are handled with a parser, each ":" must have a corresponding
|
|
";", an "if" must have either an "else" and then "then", or just "then",
|
|
etcetera.
|
|
|
|
Variables and constants can also be defined, but the grammar is slightly
|
|
different to how it works in a normal Forth:
|
|
|
|
variable x 55
|
|
constant y 20
|
|
|
|
Constants take up no space unless they are used, whereas variables are
|
|
allocated a location and set to an initial value. The above example creates a
|
|
variable 'x' and sets the variable to '55'. It also adds a constant 'y' to the
|
|
current symbol table, which can be used in other function definitions.
|
|
|
|
Code that does not appear within a word definition is assembled at that
|
|
location.
|
|
|
|
The following control structures are available:
|
|
|
|
T = value to consume off the top of the stack
|
|
A = First clause
|
|
B = Second clause
|
|
C = Third clause
|
|
|
|
T if A else B then If T != 0 execute A else execute B
|
|
T if A then If T != 0 execute A
|
|
begin A T until Execute T until T != 0
|
|
begin A again Inifinite loop, execute A
|
|
begin A T while B repeat Execute A, if T = 0 exit loop, else execute B
|
|
T for A next Execute loop T times (stores
|
|
loop parameter on the return stack)
|
|
T for A aft B then C next Execute loop T times, skip B on first loop
|
|
label: A branch label Branch to label
|
|
label: A T 0branch label Branch to label if T = 0
|
|
|
|
Unlike in a normal Forth environment these control structures can be called
|
|
from outside functions definitions. They must also matched up correctly,
|
|
otherwise a syntax error will be raised.
|
|
|
|
## Disassembler
|
## Disassembler
|
|
|
The disassembler takes a text file containing the assembled program, which
|
The disassembler takes a text file containing the assembled program, which
|
consists of 16-bit hexadecimal numbers. It then attempts to disassemble the
|
consists of 16-bit hexadecimal numbers. It then attempts to disassemble the
|
Line 806... |
Line 714... |
The purple trace shows the disassembled instructions.
|
The purple trace shows the disassembled instructions.
|
|
|
## Simulator
|
## Simulator
|
|
|
The simulator in C implements the H2 core and most of the SoC. The IO for the
|
The simulator in C implements the H2 core and most of the SoC. The IO for the
|
simulator is not cycle accurate (and most likely will never be), but can be
|
simulator is not cycle accurate, but can be used for running and debugging
|
used for running and debugging programs with results that are very similar to
|
programs with results that are very similar to how the hardware behaves.
|
how the hardware behaves. This is much faster than rebuilding the bit file used
|
This is much faster than rebuilding the bit file used to flash the [FPGA][].
|
to flash the [FPGA][].
|
|
|
|
## Debugger
|
## Debugger
|
|
|
The simulator also includes a debugger, which is designed to be similar to the
|
The simulator also includes a debugger, which is designed to be similar to the
|
[DEBUG.COM][] program available in [DOS][]. The debugger can be used to
|
[DEBUG.COM][] program available in [DOS][]. The debugger can be used to
|
Line 823... |
Line 730... |
|
|
To run the debugger either a hex file or a source file must be given:
|
To run the debugger either a hex file or a source file must be given:
|
|
|
# -T turns debugging mode on
|
# -T turns debugging mode on
|
./h2 -T -r file.hex # Run simulator
|
./h2 -T -r file.hex # Run simulator
|
./h2 -T -R file.fth # Assemble and run some code
|
|
|
|
Both modes of operation can be augmented with a symbols file, which lists where
|
Both modes of operation can be augmented with a symbols file, which lists where
|
variables, labels and functions are located with the assembled core.
|
variables, labels and functions are located with the assembled core.
|
|
|
When the "-T" option is given debug mode will be entered before the simulation
|
When the "-T" option is given debug mode will be entered before the simulation
|
Line 932... |
Line 838... |
This simulates the [Nexys3][] board peripherals that the SoC interfaces with,
|
This simulates the [Nexys3][] board peripherals that the SoC interfaces with,
|
but provides a graphical environment, unlike the command line utility. It is easier
|
but provides a graphical environment, unlike the command line utility. It is easier
|
to interact with the device and see what it is doing, but the debugging sessions
|
to interact with the device and see what it is doing, but the debugging sessions
|
are a less controlled. It requires [free glut][].
|
are a less controlled. It requires [free glut][].
|
|
|
* VGA output works
|
* VGA shown on screen.
|
* UART or PS/2 input (selectable by pressing F11) comes from typing in the screen,
|
* UART or PS/2 input (selectable by pressing F11) comes from typing in the screen,
|
and in the case of the UART this is buffered with a FIFO.
|
and in the case of the UART this is buffered with a FIFO.
|
* UART output gets written to a display box.
|
* UART output gets written to a display box.
|
* There are four 7-Segment displays as on the original board.
|
* There are four 7-Segment displays as on the original board.
|
* The switches and push buttons can take their input from either keyboard keys
|
* The switches and push buttons can take their input from either keyboard keys
|
Line 993... |
Line 899... |
|
|
| File | License | Author | Description |
|
| File | License | Author | Description |
|
| -------- | ---------- | --------------- | ----------------------------------- |
|
| -------- | ---------- | --------------- | ----------------------------------- |
|
| util.vhd | MIT | Richard J Howe | A collection of generic components |
|
| util.vhd | MIT | Richard J Howe | A collection of generic components |
|
| h2.vhd | MIT | Richard J Howe | H2 Forth CPU Core |
|
| h2.vhd | MIT | Richard J Howe | H2 Forth CPU Core |
|
|
| uart.vhd | MIT | Richard J Howe | UART TX/RX (Run time customizable) |
|
| vga.vhd | LGPL 3.0 | Javier V GarcÃa | Text Mode VGA 80x40 Display |
|
| vga.vhd | LGPL 3.0 | Javier V GarcÃa | Text Mode VGA 80x40 Display |
|
| uart.vhd | Apache 2.0 | Peter A Bennett | UART, modified from original |
|
| | | Richard J Howe | (and VT100 terminal emulator) |
|
| kbd.vhd | ??? | Scott Larson | PS/2 Keyboard |
|
| kbd.vhd | ??? | Scott Larson | PS/2 Keyboard |
|
| led.vhd | MIT | Richard J Howe | LED 7-Segment + Dot Display Driver |
|
|
|
|
|
|
# eForth on the H2
|
# eForth on the H2
|
|
|
The pseudo Forth like language used as an assembler is described above, the
|
The pseudo Forth like language used as an assembler is described above, the
|
application that actually runs on the Forth core is in itself a Forth
|
application that actually runs on the Forth core is in itself a Forth
|
interpreter. This section describes the Forth interpreter that runs on H2 Core,
|
interpreter. This section describes the Forth interpreter that runs on H2 Core,
|
it is contained within [h2.fth][].
|
it is contained within [embed.fth][].
|
|
|
TODO:
|
TODO:
|
- Fully implement the Forth interpreter
|
* Describe the Forth environment running on the H2 CPU.
|
- Describe and show its operation on here including memory layout, list of
|
|
words, word layout, ...
|
|
|
|
# Using Forth as a bootloader
|
|
|
|
A running Forth environment can be quite easily used as a bootloader with no
|
|
further modification, a simple protocol for sending data and verification of it
|
|
can be built using only Forth primitives - although it is not the most
|
|
efficient use of bandwidth.
|
|
|
|
The sender can interrogate the running Forth environment over the serial link
|
|
to determine the amount of space left in memory, and then populate it with an
|
|
assembled binary.
|
|
|
|
The Forth words needed are:
|
|
|
|
|
|
| Word | Description |
|
|
| ------- | --------------------- |
|
|
| .free | show free space |
|
|
| cp | compile pointer |
|
|
| pwd | previous word pointer |
|
|
| @ | load |
|
|
| ! | store |
|
|
| cr | print new line |
|
|
| execute | execute |
|
|
| decimal | set decimal output |
|
|
| cells | size of cell |
|
|
| . | print number |
|
|
|
|
|
|
And of course numeric input, all of which are provided by this interpreter. The
|
|
protocol is line oriented, the host with the program to transfer to the H2
|
|
(called PC) sends a line of text and expects a reply from the H2 board (called
|
|
H2),
|
|
|
|
PC: decimal ( set the H2 core to a known numeric output )
|
|
PC: .free cp @ . cr ( query how much space is left, and where to put it )
|
|
H2: ADDR ADDR ( H2 replies with both addresses )
|
|
PC: 1 cells . cr ( PC queries size of cells )
|
|
H2: 2 ( H2 responds, PC now knows to increment ADDR )
|
|
PC: NUM ADDR ! ( PC write NUM to ADDR )
|
|
PC: ADDR @ . cr ( optionally PC checks value )
|
|
H2: NUM ( H2 responds with value stored at ADDR )
|
|
... ( PC and H2 do this as often as necessary )
|
|
PC: ADDR pwd ! ( PC optionally updates previous word register )
|
|
PC ADDR cp ! ( PC optionally updated compile poiinter )
|
|
PC: ADDR execute ( Begin execution of word )
|
|
|
|
The advantage of this "protocol" is that is human readable, and includes a
|
|
debugger for the microcontroller it is operating on.
|
|
|
|
# A simple Forth block editor
|
|
|
|
TODO:
|
|
- Add an SPI master with Rx/Tx Fifos to the SoC, which can then be use
|
|
communicate with the memory on the [Nexys3][], this can then be used in
|
|
conjunction with a simple block editor for a full Forth experience.
|
|
- Talk about implementing a simple block editor in a few words of Forth.
|
|
|
|
|
|
|
|
# Coding standards
|
# Coding standards
|
|
|
There are several languages used throughout this project, all of which are
|
There are several languages used throughout this project, all of which are
|
radically different from each other and require their own set of coding
|
radically different from each other and require their own set of coding
|
Line 1159... |
Line 1004... |
width register:
|
width register:
|
|
|
-- Lots of comments about what the unit does should go
|
-- Lots of comments about what the unit does should go
|
-- here. Describe the waveforms, states and use ASCII
|
-- here. Describe the waveforms, states and use ASCII
|
-- art where possible.
|
-- art where possible.
|
library ieee;
|
library ieee, work;
|
use ieee.std_logic_1164.all;
|
use ieee.std_logic_1164.all;
|
use ieee.numeric_std.all; -- numeric_std not std_logic_arith
|
use ieee.numeric_std.all; -- numeric_std not std_logic_arith
|
|
|
entity reg is -- generic and port indented one tab, their parameters two
|
entity reg is -- generic and port indented one tab, their parameters two
|
generic(
|
generic(
|
Line 1201... |
Line 1046... |
|
|
|
|
## C
|
## C
|
|
|
There is quite a lot of [C][] code used within this project, used to make a
|
There is quite a lot of [C][] code used within this project, used to make a
|
tool chain for the H2 core and to simulate the system. It follows a fairly
|
tool chain for the H2 core and to simulate the system.
|
strict coding style.
|
|
|
|
|
* Usage of assertions for any pre or post condition, or invariant, are encouraged.
|
* Tabs are to be used instead of spaces, a tab width of 8 was used when coding
|
* Tabs are to be used instead of spaces, a tab width of 8 was used when coding
|
the C, if this causes any code to go off screen then there is a problem with
|
the C, if this causes any code to go off screen then there is a problem with
|
the code and not the tab length.
|
the code and not the tab length.
|
* Generally the [K&R][] style is followed.
|
* Generally the [K&R][] style is followed.
|
* Line lengths should ideally be limited to 80 characters, but this is
|
* Line lengths should ideally be limited to 80 characters, but this is
|
Line 1229... |
Line 1074... |
mapping then the entire statement should occupy only a single line, for
|
mapping then the entire statement should occupy only a single line, for
|
example:
|
example:
|
|
|
|
|
|
|
static const char *alu_op_to_string(uint16_t instruction)
|
static const char *alu_op_to_string(uint16_t instruction) {
|
{
|
|
/* notice also that the 'case' clauses are inline with the
|
/* notice also that the 'case' clauses are inline with the
|
* switch selector */
|
* switch selector */
|
switch(ALU_OP(instruction)) {
|
switch(ALU_OP(instruction)) {
|
case ALU_OP_T: return "T";
|
case ALU_OP_T: return "T";
|
case ALU_OP_N: return "N";
|
case ALU_OP_N: return "N";
|
Line 1271... |
Line 1115... |
baz();
|
baz();
|
|
|
* "goto" can be used - it can be misused, but using it does not instantly make
|
* "goto" can be used - it can be misused, but using it does not instantly make
|
code inscrutable contrary to popular belief.
|
code inscrutable contrary to popular belief.
|
|
|
## FORTH
|
|
|
|
The Forth in [h2.fth][] used to build an actual Forth system for the target
|
|
core is not a proper Forth, but a compiler for a Forth like language, this
|
|
idiosyncratic language has its own way of doing things. The workings of the
|
|
language will not be described in this section, only the coding standards and
|
|
style guide.
|
|
|
|
Either type of comment can be used, although "( )" comments are preferred,
|
|
single line words should be short at only a few words, multi line words
|
|
should be indented properly
|
|
|
|
: 1+ 1 + ;
|
|
: negate invert 1+ ;
|
|
: dnegate not >r not 1 um+ r> + ; ( d -- d )
|
|
|
|
Tabs should be used for indentation and a stack comment present for long or
|
|
complex words.
|
|
|
|
: ?rx ( -- c -1 | 0 : read in a character of input from UART )
|
|
iUart @ 0x0100 and 0= ( the value to test goes on one line )
|
|
if ( the 'if' on another line )
|
|
0x0400 oUart ! iUart @ 0xff and -1
|
|
else
|
|
0
|
|
then ; ( ';' is part of the final statement )
|
|
|
|
\ This word is too long for the stack comment and to be on a
|
|
\ single line
|
|
: parse ( c -- b u ; )
|
|
>r tib >in @ + #tib @ >in @ - r> parser >in +! ;
|
|
|
|
Space is seriously limited on the target device at only 8192 cells (16KiB), so
|
|
words kept as short as possible, and programs highly factored. Speed is not so
|
|
much of an issue as the board and core runs at 100MHz.
|
|
|
|
Stack comments describe what values and Forth word takes and returns, it is
|
|
good practice to make words that accept and return a fixed number of parameters
|
|
but in certain circumstances it is advantages to return a variable number of
|
|
arguments. The comments also describe the type of the arguments word accepts,
|
|
the Forth kernel will do no checking on the data it gets however.
|
|
|
|
Stack comments should be added with the following scheme:
|
|
|
|
| Comment | Meaning |
|
|
|----------------|-------------------------------------|
|
|
| a | cell address |
|
|
| n | signed number |
|
|
| u | unsigned number |
|
|
| b | string address |
|
|
| c | single character |
|
|
| d | double width number (2 Cells) |
|
|
| f | boolean flag (-1 = true, 0 = false) |
|
|
| k | block number |
|
|
| cfa | code field address of a word |
|
|
| nfa | name field address of a word |
|
|
| pwd | previous word address of a word |
|
|
| <string> | a parsing word |
|
|
|
|
Stack comments have the following format:
|
|
|
|
Variable Stack Effects Return stack Effects Parsing Description
|
|
( arguments -- returns; R: arguments -- returns; : comment )
|
|
|
|
Examples of words and their stack comments:
|
|
|
|
dup ( n -- n n : duplicate a number )
|
|
>r ( n -- ; R: -- n : move a number to the return stack )
|
|
r> ( -- n ; R: n -- : move a number from the return stack )
|
|
parse ( c -- b u; : parse a word delimted by 'c' )
|
|
over ( n1 n2 -- n1 n2 n1 : duplicate next on stack over top )
|
|
|
|
Words can have their arguments numbered to make it clearer what the effects
|
|
are.
|
|
|
|
# To Do
|
# To Do
|
|
|
* My [embed][] project, which was derived from the simulator and Forth for this
|
* Even better than using the [embed][] project directly, would be to port the
|
project, has an improved version of Forth which could be reintegrated with
|
[embed][] project so the meta-compiler runs directly on the hardware. The
|
this project. The [embed][] project features a metacompiler suitable for 16-bit
|
simulator could then be used to assemble new images, making the system (much
|
systems like this one, it could be used in lieu of the Pseudo-Forth compiler.
|
more) self-hosting. Input/Output would be a problem, a possible solution is to
|
* Guide to reusing the VHDL in this project, and component listing
|
use one of the UARTs for reading the meta-compiler and meta-compiled eForth
|
* Turn the [h2.fth][] into a literate program file, describing how to build up
|
program, and writing status/error messages. A second UART could be used to
|
a Forth system like in "The Zen of eForth by C. H. Ting".
|
dump the binary as a stream of hexadecimal numbers, the simulator could
|
* Make a bootloader/program loader as a single, simple program
|
redirect the second UART output to a file.
|
* Make diagrams of the SoC layout, take GIFs and pictures of the simulators and
|
* Create a cut down version of the project; remove nearly everything apart from
|
the running board.
|
the H2 Core, Block RAM and timer components. The interrupt handler could be
|
* Make a javascript based simulator for the H2, perhaps with [emscripten][]
|
simplified as well. The UART could be handed in the H2 Core
|
* Move this file to "h2.md" and make a simpler "readme.md" with a short
|
* The GUI simulator could be written to be built against [SDL][], and include
|
description and flashy GIFs
|
proper textures for the buttons and displays, instead of the current simulator
|
|
which looks like an early 90s test application for OpenGL.
|
|
* Prepare more documentation. Specifically about the eForth interpreter that
|
|
runs on the target and the online help stored within the non-volatile storage
|
|
on the board.
|
|
* An IDE for resetting/uploading the image to the target board and then sending
|
|
a text buffer to it would help in developing code for the platform.
|
|
* A [Super Optimizer][] could be made for the H2.
|
|
* More instructions can be combined
|
|
* It might be possible to add a conditional exit instruction. Other
|
|
instructions which would be useful are: Add with Carry, Bit Count, Leading
|
|
Zeroes Count, Sign Extend, Arithmetic Right Shift, Rotate Left/Right, ...
|
* Add notes about picocom, and setting up the hardware:
|
* Add notes about picocom, and setting up the hardware:
|
* Add a [Wishbone interface][] for each component
|
|
* Put the project up on [opencores][]
|
|
* It should be possible to turn [h2.c][] into a Forth interpreter usable in
|
|
a hosted environment. Some of the remaining instructions could be used for
|
|
function calls and floating point operations and the "uint16\_t" would have to
|
|
be changed to "uintptr\_t". As the interpreter is so small a Forth to "C"
|
|
compiler could just spit out a copy of the interpreter. It should make for
|
|
a very compact system.
|
|
* Spin off the VT100 VHDL code into a separate project, and the C code in the
|
|
simulator into a simple terminal emulator for Unixen.
|
|
* Add some example games, any of the following: Space Invaders, Tetris, Pong,
|
|
Minesweeper, Sokoban, Sudoku, Hack, 2048, Breakout, Brain F\*ck, Conway's
|
|
Game of Life, and other terminal based games could be added, see
|
|
for a
|
|
minimal version of Nethack, and for a
|
|
cool 1 dimensional game.
|
|
* Other programs like a compressor, decompressor, ARC4, data base function based
|
|
around blocks, and a meta compiler (removing the need for the C assembler),
|
|
could be added.
|
|
|
|
|
|
|
|
|
|
|
|
picocom --omap delbs -b 115200 -e b /dev/ttyUSB1
|
picocom --omap delbs -b 115200 -e b /dev/ttyUSB1
|
|
|
Line 1399... |
Line 1158... |
*
|
*
|
*
|
*
|
*
|
*
|
*
|
*
|
|
|
|
[j1eforth]: https://github.com/samawati/j1eforth
|
[javascript]: https://www.javascript.com/
|
[javascript]: https://www.javascript.com/
|
[emscripten]: https://github.com/kripken/emscripten
|
[emscripten]: https://github.com/kripken/emscripten
|
[DEBUG.COM]: https://en.wikipedia.org/wiki/Debug_%28command%29
|
[DEBUG.COM]: https://en.wikipedia.org/wiki/Debug_%28command%29
|
[DOS]: https://en.wikipedia.org/wiki/DOS
|
[DOS]: https://en.wikipedia.org/wiki/DOS
|
[h2.c]: h2.c
|
[h2.c]: h2.c
|
[h2.fth]: h2.fth
|
[embed.fth]: embed.fth
|
|
[embed.c]: embed.c
|
|
[embed.blk]: embed.blk
|
[tb.vhd]: tb.vhd
|
[tb.vhd]: tb.vhd
|
[uart.vhd]: uart.vhd
|
[uart.vhd]: uart.vhd
|
|
[timer.vhd]: timer.vhd
|
[top.ucf]: top.ucf
|
[top.ucf]: top.ucf
|
[font.bin]: font.bin
|
[font.bin]: font.bin
|
[text.bin]: text.bin
|
[text.bin]: text.bin
|
[J1]: http://www.excamera.com/sphinx/fpga-j1.html
|
[J1]: http://www.excamera.com/sphinx/fpga-j1.html
|
[J1 PDF]: http://excamera.com/files/j1.pdf
|
[J1 PDF]: http://excamera.com/files/j1.pdf
|
Line 1438... |
Line 1201... |
[D-Pad]: https://en.wikipedia.org/wiki/D-pad
|
[D-Pad]: https://en.wikipedia.org/wiki/D-pad
|
[FIFO]: https://en.wikipedia.org/wiki/FIFO_%28computing_and_electronics%29
|
[FIFO]: https://en.wikipedia.org/wiki/FIFO_%28computing_and_electronics%29
|
[VGA]: https://en.wikipedia.org/wiki/Video_Graphics_Array
|
[VGA]: https://en.wikipedia.org/wiki/Video_Graphics_Array
|
[PS/2]: https://en.wikipedia.org/wiki/PS/2_port
|
[PS/2]: https://en.wikipedia.org/wiki/PS/2_port
|
[LED]: https://en.wikipedia.org/wiki/Light-emitting_diode
|
[LED]: https://en.wikipedia.org/wiki/Light-emitting_diode
|
[8 Segment LED Display]: https://en.wikipedia.org/wiki/Seven-segment_display
|
[7 Segment LED Display]: https://en.wikipedia.org/wiki/Seven-segment_display
|
[ISO 8859-1 (Latin-1)]: https://cs.stanford.edu/people/miles/iso8859.html
|
[ISO 8859-1 (Latin-1)]: https://cs.stanford.edu/people/miles/iso8859.html
|
[Spartan 6]: https://www.xilinx.com/products/silicon-devices/fpga/spartan-6.html
|
[Spartan 6]: https://www.xilinx.com/products/silicon-devices/fpga/spartan-6.html
|
[FPGA]: https://en.wikipedia.org/wiki/Field-programmable_gate_array
|
[FPGA]: https://en.wikipedia.org/wiki/Field-programmable_gate_array
|
[ASCII]: https://en.wikipedia.org/wiki/ASCII
|
[ASCII]: https://en.wikipedia.org/wiki/ASCII
|
[free glut]: http://freeglut.sourceforge.net/
|
[free glut]: http://freeglut.sourceforge.net/
|
Line 1457... |
Line 1220... |
[picocom]: https://github.com/npat-efault/picocom
|
[picocom]: https://github.com/npat-efault/picocom
|
[Gforth]: https://www.gnu.org/software/gforth/
|
[Gforth]: https://www.gnu.org/software/gforth/
|
[opencores]: https://opencores.org
|
[opencores]: https://opencores.org
|
[VT100]: https://en.wikipedia.org/wiki/VT100
|
[VT100]: https://en.wikipedia.org/wiki/VT100
|
[embed]: https://github.com/howerj/embed
|
[embed]: https://github.com/howerj/embed
|
|
[SDL]: https://www.libsdl.org/
|
|
[Apache 2.0]: https://www.apache.org/licenses/LICENSE-2.0.html
|
|
[KOI8-R]: https://en.wikipedia.org/wiki/KOI8-R
|
|
[Terminus]: http://terminus-font.sourceforge.net/
|
|
[ISO-8859-15]: https://en.wikipedia.org/wiki/ISO/IEC_8859-15
|
|
[Super Optimizer]: https://en.wikipedia.org/wiki/Superoptimization
|
|
|
|
|
https://www.w3schools.com/css/css_table.asp
|
https://www.w3schools.com/css/css_table.asp
|
http://adis.ca/entry/2011/pretty-code-block-in-css/
|
http://adis.ca/entry/2011/pretty-code-block-in-css/
|
https://www.w3.org/Style/Examples/007/center.en.html
|
https://www.w3.org/Style/Examples/007/center.en.html
|
https://css-tricks.com/centering-css-complete-guide/
|
https://css-tricks.com/centering-css-complete-guide/
|
-->
|
-->
|
|
|
|
|
|
![System Architecture](https://raw.githubusercontent.com/howerj/howerj.github.io/master/h2/system.svg)
|
|
-->
|
|
|