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:
  • 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
Bits 15 to 13 form the Opcode.
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

Micro16-18sep03.zip  Pre-release

This version does not work ... I'm putting it up here for safe keeping. I've included the smal32 macro assembler with macros for the micro16 and the source to a monitor program included in the blockrom VHDL code. I've also included the source to "epedit" that allows you to generate the initialisation code for the 16 bit block RAM.

Micro16-27sep03.zip - Runs with umon16 monitor program.

The Micro16 now runs a simple monitor program that allows you to read and modify memory locations. The "M" key allows you to examine a 16 bit memory location. 64KWords may be accessed, but care should be taken to ensure that you only access valid memory, or the CPU will hang indefinitely, due to the wishbone handshaking protocol.

There is also a loader for the Smal32 macro assembler, but it has not been tested as yet. It will only load 64 Kbytes, even though the macro assembler is designed for 32 bit addressing. In the loader I simply ignore the top 16 bits of 32 bit addresses.

Modifications made to Micro16:
1. The opcode is initialised to a JNZ instruction so that on reset the Z bit is cleared and a JNZ instruction can be used to jump around the interrupt vector location.
2. Condition codes were onlt testing 8 bits of the ALU result. This is because the code was a carry over from the micro8.
3. The program counter is now 16 bits. Direct jumps jump within a 4KWord Page, but you can jump into other pages using an indirect jump.

The memory map is as follows

#0000 - #00FF - ROM0 - 256 x 16 bits
#0100 - #01FF - ROM1 - 256 x 16 bits
#0E00 - #0EFF - RAM2 - 256 x 16 bits
#0F00 - #0FDF - RAM3 - 224 x 16 bits
#0FE0 - #0FEF - Compact Flash Interface
#0FF0 - #0FFF - MiniUART

umon16-27sep03.zip - Monitor program for the Micro16

This uses two Xlinx RAMB4_S16 Block ROMs. You need to use the EPEDIT C program also included, to load the object file generated by the Smal32 macro assembler and you need to save it as a 16 bit vhdl hex file. Since I have upgraded my operating system, I can no longer run cygwin, which is what the C code was compiled under. I will have to produce a  windows version of the eprom loader at some stage.

The instruction macros are included in the "micro16.inc" file.

Note the following work arounds:
1. The macro assembler is designed for 8 bit addressing where as I have used 16 bit addressing, so all the addresses along the side of the listing need to be divided by two. The correct code is generated, but the addresses are mis leading.
2. The "SUB" macro actually Negates the accumulator and adds it to the memory location. this means it is actually Memory - Accumulator, however the condition codes are actually in reverse, because you are doing an ADD and not a true SUB in the macro.

Smal32.zip - Macro assembler

SMAL is a macro assembler By Douglas W. Jones of THE UNIVERSITY OF IOWA Department of Computer Science

Micro16-30sep03.zip - Integrates the latest version of umon16

No major changes here .... except the iocs16 signal is an output from the CF, not an input. I have removed it. I have used 4 Block RAMs for ROM to cater for the increased size, and relocated the RAM. Also, I am now using WebPack ISE 6.1i.

#0000 - #00FF Rom0
#0100 - #01FF Rom1
#0200 - #02FF Rom2
#0300 - #03FF  Rom3
#0D00 - #0DFF RamD (can be used for compact flash sector buffer)
#0E00 - #0EFF RamE (Monitor variables)
#0FE0 - #0FEF Compact Flash
#0FF0 - #0FFF MiniUart

uMon16-30sep03.zip - Extra Comands

I've added a number of extra commands:

M - Memory examine and modify
L - Load smal binary (not tested)
D - Dump memory
R - Read sector (not working 100%)
W - Write sector (not working 100%)
I - Initialise / reset Compact Flash

Be careful not to access undecoded memory as the cpu will hang because there is no decode acknowledgement. Note that the addresses used by umon are WORD addresses, not the BYTE addresses used in the smal macro assembler.

To generate ROMs using EPDIT:

compile and run epedit.c, at the prompt enter the following commands
:
type o
load umon16.o
type w
save rom0.xxx 0 1ff
save rom1.xxx 200 3ff
save rom3.xxx 400 5ff
save rom4.xxx 600 7ff
quit
y

This will produce the initialization block for 4 x 16 bit Block ROMs that must be manually inserted into the ROM VHDL code. Note that the addresses are BYTE Addresses, and not WORD addresses

30 September 2006

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.

 

Back to FPGA Page