Micro16 - A Simple 16 Bit VHDL CPU
Micro16 is an extension or derivative of the Micro8 CPUs. Addressing modes have been reduced to extend the adressing range. Rather than supporting an index register the Micro16 uses indirect addressing. The Micro16 does not support byte addressing. addresses are word addresses. The idea of the Micro16 was to provide a very simple micro controller, originally intened as an I/O processor for a Compact Flash reader.
The Micro16 features:
Bits 15 to 13 form the Opcode.
- 8 Instructions
- Direct & Indirect Addressing
- 4KWord Direct Addressing Range (Program & Data)
- 64K Word Indirect Addressing Range (Data Only)
- 8 Level Hardware Stack
- 1 Interrupt Input
Bit 12 is the Indirect bit. If set the opcode reads / writes from the address pointed to by the address field.
Bits 11 to 0 form the Direct address. Stored Program code can only reside in the Direct Address Space.
15
14
13
12
11
10
9
8
7
6
5
4
3
2
1
0
Opcode
I
Address
B15
B14
B13
Instruction
0
0
0
ADD Add Accumulator
0
0
1
NOR Nor Accumulator
0
1
0
STO Store Accumulator
0
1
1
JSR Jump to Subroutine
1
0
0
JNZ Jump if Non Zero (Clears ZFlag)
1
0
1
JNC Jump if No Carry (Clears Carry Flag)
1
1
0
RTI Return From Interrupt
1
1
1
RTS Return From Subroutine
I had an enquiry today about porting this design to other FPGA platforms namely the XESS XSB-300E. The thing to note is that SysClk has been set up for 4.9152 MHz. The baud rate divisor in the UART for the RX sample clock defaults to 128. The TX baud rate is one quarter of this 4.915200/128/4 = 9600 Baud. I am not sure what the maximum clock rate is for Micro16 but if you use SysClk = 25 MHz and 115200 Baud then you need to set BRDIVISOR = 25,000,000/115,200/4 = approx 54. I have not tested this so you may need to experiment a bit.
Micro16b replaces the hardware stack with a memory stack. The stack pointer is 8 bits and works down from word address #00FF. There are no provisions for modifying the stack pointer, so all subroutine must be exited with a return from subroutine instruction (RTS).
I have added 3 interrupt inputs. These are prioritised so that the highest interrupt masks lower interrupt. The interrupts should push the return address, the accumulator and the condition codes onto the stack. The return from interrupt instruction (RTI) should pull these registers off the stack. Interrupts have not been tested yet.
I have parameterised the address and data bus widths, although in practice the data bus width is determined by the block ram and the address width can be scaled from 9 bits to 16 bits. I have set the address width to 10 bits in this design to save space. The design uses 3 4Kbit block RAMs, because this is all that is available on the Pluto board. One block RAM is used for RAM and Stack in page 0 and two Block RAMs are used for the monitor ROM in pages 2 and 3. The design has been implemented on a 200K gate Spartan 3 starter board so the ROMs can be upgraded to 16K Bits. It has not been determined though if this design will fit in the ACEX1K10 used on the smallest Pluto board.
#0000 - #00FF - Page 0 - Ram (stack works down from #00FF)The directory structure in the zip folder stores the program source files in the "src" folder, the VHDL designs in"rtl", and the utilities in "bin". The "src" folder include folders for "u16test" used in the test bench, "u16mon" a stripped down monitor program with Memory modify, dump and jump to commands and "u16load" which is an untested loader for smal32.
Micro16b
src
lib - Common library macros
u16test - Test code for test bench ROMs
u16mon - striped down monitor program
u16load - Smal32 loader (untested)
rtl
Spartan2 - 4K bit roms
Micro16_Digilent_3S200 - top level project files
Testbench - Test Bench code
VHDL - vhdl library files
bin - assembler (smal) and ROM formatter (epedit)