eris2206

Documentation: http://frombelow.net/projects/eris2206/
Clone: git clone https://git.frombelow.net/eris2206.git
Log | Files | Refs | Submodules | README | LICENSE

README.md (13340B)


      1 Eris 2206
      2 ---------
      3 
      4 1. Introduction
      5 2. Operating Eris 2206
      6 3. Programming
      7 3.1 Memory
      8 3.2 Assembler
      9 3.3 Example
     10 3.4 I/O and UART
     11 3. Hardware
     12 3.1 SOC
     13 3.2 CPU
     14 3.4 LED Matrix Monitor
     15 4. Case and Electronics
     16 4.1 Case
     17 4.2 Electronics
     18 5. License
     19 
     20 
     21 Introduction
     22 ============
     23 
     24 [Watch the video!](https://frombelow.net/projects/eris2206/images/eris2206_demo.mp4)
     25 
     26 Eris 2206 is a front-panel programmable 8 bit computer with lots of
     27 Blinkenlights, implemented on an FPGA. It is not directly based on an
     28 existing computer design (contemporary or historic), but it takes
     29 inspiration from minicomputers and early microcomputers. The most
     30 prominent feature of Eris 2206 is its 16x16 LED display, which shows
     31 the internal state of the CPU and the first 24 memory addresses. The
     32 main mode of programming Eris 2206 is by directly writing to its 128
     33 bytes of RAM via front-panel switches. The 125 bytes ROM contain a
     34 small bootloader to load programs and data via a serial connection.
     35 
     36 
     37 Operating Eris 2206
     38 ===================
     39 
     40 Eris 2206 knows three operation modes: run mode, step mode, and memory
     41 set mode. The mode is chosen by a three way switch. In run mode,
     42 execution speed is set by the speed dial next to the mode switch,
     43 while in step mode the step button triggers execution of the next
     44 micro instruction.
     45 
     46 Eris 2206 powers on when connected to a USB power supply. On power up
     47 in run or step mode, it starts executing the program located at the
     48 first ROM address, $80, which computes Fibonacci numbers.
     49 
     50 The 16x16 LED matrix shows the internal state of the CPU and the first
     51 RAM cells:
     52 
     53  Row | Left Side         | Right Side
     54 ----:|:-----------------:|:------------------:
     55 0    | Micro Instruction | Micro Instruction
     56 1    | Address Bus       | Data Bus
     57 2    | Accumulator       | ALU
     58 3    | Program Counter   | Data Pointer
     59 4-15 | RAM               | RAM
     60 
     61 
     62 Programming
     63 ===========
     64 
     65 The main mode of programming Eris 2206 is by front panel switches. For
     66 this, the mode switch has to be set to memory set mode. Pushing the
     67 reset button sets the memory address to the first address, $00. Now
     68 the data bus can be set via switches. Pushing the step button writes
     69 the current value on the data bus to the current memory address and
     70 advances the memory pointer. Pushing the skip button advances the
     71 memory pointer without writing to memory. When program and data have
     72 been written to memory, execution is started by setting the mode
     73 button to step mode and pushing the reset button. Now the program is
     74 executed by pushing the step button repeatedly or by switching to run
     75 mode.
     76 
     77 Alternatively, programs can be uploaded via the serial UART provided
     78 by the USB interface. For this, a minimal first-stage boot loader has
     79 to be programmed and executed via the front panel. This first-stage
     80 boot loader jumps to the second stage serial boot loader at ROM
     81 address $C0. The host program for serial upload is located in
     82 directory `src/tools/send_serial.py`. It expects hex code input.
     83 
     84 
     85 Memory
     86 ------
     87 
     88 Since we have an 8 bit address bus, a total of 256 memory addresses
     89 are available. The lower 128 bytes are RAM. The upper 125 bytes are
     90 RAM. The uppermost three bytes provide memory mapped access
     91 to I/O and the UART.
     92 
     93 Address | Assignment
     94 :-------|:--------------------
     95 $FF     | UART - Clear/Status
     96 $FE     | UART - Send/Receive
     97 $FD     | I/O (0..5: LEDs)
     98 $C0-$FC | ROM (Serial boot loader)
     99 $80-$BF | ROM (Fibonacci numbers)
    100 $00-$7F | RAM
    101 
    102 
    103 Assembler
    104 ---------
    105 
    106 `src/tools/eras.pl` provides a macro assembler using CPP for macro
    107 processing. The directory also contains a number of example programs.
    108 
    109 The CPU knows four addressing modes:
    110 
    111 - Implicit
    112 
    113 The argument is given implicitly, e.g. INC, which adds one to the
    114 accumulator.
    115 
    116 - Immediate
    117 
    118 The argument is the actual value. This mode is indicated by a
    119 "#". Example: LDA #$5C loads the value $5C into the accumulator.
    120 
    121 - Direct
    122 
    123 The argument is the memory location of the actual value. Example: LDA
    124 $5C loads the value stored at memory address $5C into the accumulator.
    125 
    126 - Indirect
    127 
    128 The argument is the memory address where the memory address of the
    129 actual value is located. This mode is indicated by "()". Example: If
    130 memory address $5C contains value $3B, and memory address $3B contains
    131 value $67, LDA ($5C) loads $67 into the accumulator.
    132 
    133 Op. | Imp. | Imm. | Dir. | Ind. | Description
    134 ----|------|------|------|------|:------------------------------------
    135 NOP |  $00 |      |      |      | No operation
    136 LDA |      |  $08 |  $02 |  $0B | Load accumulator
    137 STA |      |      |  $12 |  $17 | Store accumulator
    138 JMP |      |      |  $1D |      | Jump to address
    139 JNZ |      |      |  $21 |      | Jump if accumulator != 0
    140 JZE |      |      |  $25 |      | Jump if accumulator == 0
    141 ADD |      |  $38 |  $29 |  $30 | Add value to accumulator
    142 SUB |      |  $4B |  $3C |  $43 | Subtract value from accumulator
    143 AND |      |  $5E |  $4F |  $56 | Logical AND of accumulator and value
    144 ORA |      |  $71 |  $62 |  $69 | Logical OR of accumulator and value
    145 XOR |      |  $84 |  $75 |  $7C | Logical XOR of accumulator and value
    146 INC |  $88 |      |      |      | Increment accumulator
    147 DEC |  $8A |      |      |      | Decrement accumulator
    148 ROL |  $8C |      |      |      | Rotate accumulator 1 bit left
    149 ROR |  $8E |      |      |      | Rotate accumulator 1 bit right
    150 INV |  $90 |      |      |      | Invert accumulator
    151 
    152 
    153 Example
    154 -------
    155 
    156 We write a program that adds $05 and $06:
    157 
    158 ```
    159 start:
    160 	LDA #$05
    161 	ADD #$06
    162 	STA :result
    163 	JMP :start
    164 result:
    165 ```
    166 
    167 The assembler generates the following machine code for this:
    168 
    169 ```
    170 08 05
    171 38 06
    172 12 08
    173 1D 00
    174 ```
    175 
    176 In order to enter the machine code, we set the mode switch to "set",
    177 and push the reset button. Now we enter each byte, followed by pushing
    178 "step". Once we are done, we set the mode switch to step, push reset,
    179 and set the mode switch to run. After a number of steps, the result is
    180 shown memory address $08.
    181 
    182 If we want to add different numbers, we set the mode to set again,
    183 push reset, push skip once in order to advance to memory address $01
    184 without overwriting the LDA instruction, set the first new number, push
    185 step, push skip in order to advance to memory address $03, set the
    186 second new number, and set the mode switch to run.
    187 
    188 
    189 I/O and UART
    190 ------------ 
    191 
    192 The I/O register simply maps the lowest 5 bits to the LEDs on the
    193 iCEstick (which are not visible, since the iCEstick is in the
    194 case).
    195 
    196 The UART utilizes two addresses: One address for sending and receiving
    197 data, and a second address for status information and to clear the
    198 input buffer.
    199 
    200 The byte written to address $FE is send. While the bit is transmitted,
    201 bit 0 of $FF is 1 (tx_busy). In order to receive a byte, the receiver
    202 buffer must be cleared by writing any value to $FF. Once a byte is
    203 received, bit 1 of $FF is 1 (recv_buffer_full). Now the byte can be
    204 read from $FE. In order to receive the next byte, the receive buffer
    205 has to be cleared again. See `src/roms/rom_uart.asm` for an example.
    206 
    207 
    208 Hardware
    209 ========
    210 
    211 Eris2206 is implemented on an iCEstick FPGA Evaluation Kit. It is
    212 synthesized using the free tools of project
    213 [IceStorm](https://clifford.at/icestorm).
    214 
    215 The GPIO pins of the FPGA connect to the 16x16 (WS2811) matrix display
    216 and the buttons/switches. Beside some pull-down resistors, the only
    217 additional hardware is an NE555 multivibrator circuit providing the
    218 bus clock. The speed dial changes the frequency of the multivibrator.
    219 
    220 
    221 SOC
    222 ---
    223 
    224 See `doc/schematic.dia` for an overview of the SOC. Besides the CPU core,
    225 the main peripherals are memory (RAM and ROM), the UART, and a system
    226 monitor providing output to a matrix of WS2811 LEDs.
    227 
    228 
    229 CPU
    230 ---
    231 
    232 The following description of the internal works of the CPU should help
    233 you to understand the implementation in `src/ecpu.v`. It is not
    234 necessary to operate Eris 2206.
    235 
    236 An instance of module control_logic orchestras the components of the
    237 CPU. (These control lines are not shown in the schematic.) Microcode
    238 implementations of the opcodes govern the operation of the control
    239 logic. The microcode for the assembler opcodes is defined in and
    240 generated by `src/tools/mc_compiler.py`.
    241 
    242 The CPU has two counters and three registers:
    243 
    244 The program counter (PC) points to the next instruction/argument to
    245 be processed. The micro instruction pointer (MIP) points to the next
    246 micro instruction to be executed. These counters can be set or
    247 incremented.
    248 
    249 The three registers are the data pointer (DP), the accumulator, and
    250 the output of the arithmetic-logic unit (ALU).
    251 
    252 The accumulator is the only register visible to the user. It reads
    253 from and writes to external memory (and memory mapped I/O modules) via
    254 the data bus. In addition to read and write operations, the
    255 accumulator can be incremented, decremented, rotated (left and right),
    256 and inverted.
    257 
    258 The ALU operates on the current value of the accumulator and the
    259 current value on the data base, and writes back to the data bus.
    260 
    261 Like the PC, the DP does not write to the data bus, but to the address
    262 bus. It is used to dereference addresses in direct and indirect
    263 addressing mode.
    264 
    265 A zero flag, i.e. a wire indicating whether the register value is
    266 zero, is available for the accumulator. This flag is used by the
    267 comparator in order to implement the conditional jump on (not) zero
    268 instructions.
    269 
    270 A little bit of glue logic multiplexes the data and address line:
    271 Only the active component may write to the buses.
    272 
    273 Micro instructions consist of 15 bits:
    274 
    275   Bit | Operation
    276 -----:|:---------------------------------------------------------------------
    277     0 | Write data bus to PC
    278     1 | Write data bus to PC if zero flag 1
    279     2 | Write data bus to PC if zero flag 1
    280     3 | Increment PC
    281     4 | Write data bus to DP
    282     5 | Write DP to address bus (write PC to address bus if bit 5 = 0)
    283     6 | Set memory address on address bus to value on data bus
    284     7 | Write accumulator to data bus
    285  8-10 | Set/increment/decrement/rotate/invert accumulator
    286    11 | Set MIP to value on data bus (increment MIP if bit 11 = 0)
    287 12-14 | Add/subtract/and/or/xor data bus to accumulator and write to data bus
    288 
    289 The implementation of the opcodes as micro instructions is given in
    290 `src/tools/mc_compiler.py`. `mc_compiler.py` compiles a ROM file of
    291 the micro instruction implementations of all opcodes. The machine code
    292 (= byte value) of an opcodes is the entry points for the microcode of
    293 its implementation in this ROM file. Therefore in order to decode an
    294 opcode, its byte code is read from the data bus and written into the
    295 MIP.
    296 
    297 On negative edges of the clock, the next micro instruction is set,
    298 i.e. components are turned on/off according to the micro
    299 instruction. The components operate on positive clock edges.
    300 
    301 There is a separate clock port for the UART, because the UART must be
    302 run at 12 MHz for timing reasons, while the rest of the SOC may run at
    303 a lower speed.
    304 
    305 
    306 LED Matrix Monitor
    307 ------------------
    308 
    309 A 16x16 LED matrix provides a monitor view into the internals of the
    310 SOC. The LEDs are driven by WS2811 controllers. The control logic is
    311 implemented in `src/ws2811.v`. On each iteration of the internal (12
    312 MHz) clock of the FPGA, one 8 bit element of the monitor is updated,
    313 i.e. it takes 32 cycles to update the complete LED matrix. The WS2811
    314 driver allows to set the three color channels of each LED on or
    315 off. The intensity is fixed for all LEDs and color channels.
    316 
    317 
    318 Case and Electronics
    319 ====================
    320 
    321 Case
    322 ----
    323 
    324 The case has been designed in OpenSCAD. The main design file is
    325 `case/case.scad`. Most elements of the case can be cut from 6 mm ply
    326 wood with a laser cutter. Running make in directory case generates
    327 cutouts for a laser cutter in `case/dst/svg/`. Three elements are not
    328 only cut, but also engraved. Engravings have been added manually using
    329 Inkscape. These files for laser cutting are located in
    330 `case/dst/labeled`. Note that for
    331 `case/dst/labeled/top_plate/acryl_top_plate.svg` not 6 mm plywood, but
    332 an acryl plate should be cutted.
    333 
    334 The holders for the iCEstick and the circuit board are 3D printed.
    335 After running make in directory case/, the 3D print files are located
    336 in directory case/dst/stl.
    337 
    338 The case is partly glued and partly held together by M4 screws. Most
    339 M4 screws have nuts as counterparts, except the four screws in the
    340 bottom. These are held by claw nuts.
    341 
    342 Electronics
    343 -----------
    344 
    345 The NE555 multivibrator is housed on a small circuit board, together
    346 with a bunch of pull-down resistors for the switches. A Fritzing
    347 design file is given in board/circuit.fzz. See src/ecpu.pcf for how to
    348 connect the hardware components to the GPIO I/O pins.
    349 
    350 License
    351 =======
    352 
    353 See case/lasercut/LICENSE for author, copyright, and licensing
    354 information of the lasercut library.
    355 
    356 Everything else:
    357 
    358 Copyright © 2022 Gerd Beuster <gerd@frombelow.net>
    359 
    360 This project is free soft- and hardware: you can redistribute it
    361 and/or modify it under the terms of the GNU General Public License as
    362 published by the Free Software Foundation, either version 3 of the
    363 License, or (at your option) any later version.
    364 
    365 This project is distributed in the hope that it will be useful, but
    366 WITHOUT ANY WARRANTY; without even the implied warranty of
    367 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    368 General Public License for more details.
    369 
    370 You should have received a copy of the GNU General Public License
    371 along with this project.  If not, see <http://www.gnu.org/licenses/>.