Computer Architecture Lab/Winter2006/PoettschacherRosenblattlWolf/iMISC

iMISC - invertable Minimized Instruction Set Computer
The basic idea is to design a microprocessor that is able to perform all mandatory operations while reducing the usually rather rich RISC instruction set to a minimum.

Features

 * CPU Architecture: RISC
 * Memory Architecture: Harvard
 * Number of Opcodes: 14
 * Number of Commands: 21
 * Pipeline Stages: 4 + Writeback
 * Branch Delay: 1 Cycle
 * Command execution: 1 Tick
 * Data Width: 16 bit
 * Registers: 32 16-bit Registers (29 for general purpose)
 * Addressable object size: 16-bit word
 * Ram address width: 16 bit
 * Ram size: up to 128 kb
 * Rom address width: 16 bit
 * Rom size: up to 128 kb

Specifications on Target (Altera Cyclone EP1C12Q240C8):
 * Logic Cells: about 1100 (with UART, depending on ROM size)
 * Total Memory Bits: 8704 + Rom
 * f_max: about 84 MHz (with most optimizations, depending on ROM size)

Design Decisions
To minimize the instruction set we decided to use only three bits for the opcode, limiting them to eight different opcodes. To keep the overall design simple, we have chosen to implement a load/store harvard architecture. Currently, the design specifies a 16 bit cpu with 16 bit address space and 32 16 bit registers, 29 of them are general purpose. Another simplification is the lack of a program status word which normally holds some flags like the carry flag or an overflow flag. Also, there is no dedicated stack pointer. Jumps are performed by writing to the program counter which is a special register.

Registers
The registers are numbered consecutively with a leading R character. The first register is R00. The three special registers are: They have the mnemonics ZERO, IP and PIP.
 * R29 ... Zero register (ZERO)
 * R30 ... Instruction Pointer (IP)
 * R31 ... Previous Instruction Pointer (PIP)

Instruction Set
For the given design, the following instructions are mandatory: also, some form of conditional operation is needed, like
 * MV ... copys the value of one register to another register
 * LD ... loads a value from the given address to the given register
 * ST ... stores a value from a given register to the given address
 * AND, OR, NAND or NOR ... performs a logical (N)AND/(N)OR operation on the two given registers and store the value to a given register
 * ADD or SUB ... adds/subtracts the value of the second register to/from the first register
 * LSL ... performs a left shift on a register
 * LSR ... performs a right shift on a register
 * SKIP ... skips next operation

Although this are just 7 different instructions, we need some more instructions by several reasons. First, we use a harvard architecture, thus we want to separate access to the program memory (FLASH) from access to the data memory (SRAM). To simplify the load/store instructions, we limit them to the data memory, thus we need some way to get constants into a register as the data memory is not initialized. Therefore, we also need an instruction as
 * LDI ... loads a constant to a given register.

Another design decision is that we want to fit every instruction into 16 bit. As three bit are taken by the opcode, 13 bits are left for the parameters. We use 32 registers, thus we need 5 bits per register. This limits the number of parameters to 2, if both parameters of an instruction are register numbers. So instruction like NAND write the result to one of the given source registers. Additionally the LDI instructions cant load a 16 bit constant, so we decided to limit the size of the constant parameter to 8 bit and added a high byte/low byte flag. This leaves only 4 bits left for the register number, so constants can only be loaded into the lower 16 registers. To speed up execution, the AND, OR and NOR instructions are a good idea, although they could be done by software using NAND operations.

Memory-mapped I/O
We implemented access to peripherals as the LED or the UART memory-mapped in the address range from 0x0200 to 0x0203, with the following special addresses:


 * 0x0200: The LED. If the bit 0 of this word is set, the LED goes on, otherwise, it goes off. A read has no effect.
 * 0x0201: UART read. If a byte is received by the UART hardware, it is read at this address in the low byte, with the high byte set to 0x01. If no byte is available, this is always read as 0x0000. A write has no effect.
 * 0x0202: UART write. If the UART write queue is not full, the lower byte of the word written here is transmitted. A read has no effect.
 * 0x0203: UART status. Bit 0 signals the possiblity to write to the UART, bit 1 signals if a byte is ready to be received.

invertability
Finally, and not just to do something different than other designs, we enabled to invert instructions. This just means that by setting the inverted flag (by the SINV instruction), an opposite operation to the next instructions is performed, if possible. This enables to reduce the number of opcodes and enables further optimization within the pipeline. For example, the opposite operation of the LD instruction is the ST instruction. If the inverted flag is not set, only LD is possible, therefore no write back interferance within the pipeline is possible. If the iverted flag is set by the SINV instruction, all following LD instructions become ST instructions, therefore only write back operations may be possible.

Instruction Set of the iMISC architecture
As the mnemonics are used as the following:
 * 0 ... one bit with value zero
 * 1 ... one bit with value one
 * C ... one bit of constant
 * Rs ... one bit of the number of the source register
 * Rd ... one bit of the number of the destination register
 * H/L ... one bit signaling if high or low byte, H is equivalent to 1 and L to 0

Diagram
The following Diagram shows the actual architecture: imisc_architecture.gif

Assembler
The Assembler is the basic instrument to feed the iMISC architecture with machinecode. It is able to output text, binary or vhdl rom code. Also, it performs basic checks on the code. When using a C-Precompiler, assembler code becomes more readable as the iMISC-Assembler was not made to make code looking nice...

Language
The assembler language is mostly comparable to the structure of the binary code, although there are some differences. Mainly, the assembler uses what it gets from the input file and converts it to the binary codeword which is written to the output. As the semantic of a codeword depends on the state of the InvertedFlag, it does not depend which of its representations is used. The basic syntax of an assembler command is as follows: CMD SRC, DST Here, CMD is the command name, SRC is the source may be a register or constant, depending on the command and DST is the destination and therefore again a register. Constants may be in decimal or hexadecimal format (either with leading 0x or h). The registers are named R00 to R31. The use of the special registers may be restricted depending on their meaning. R29 (ZERO) and R31 (PIP) must not be the destination register. R30, the instruction pointer register, may only be written through a move command where the source register is R00. Labels can be placed at the begin of a line and are delimited by a colon. They can be treated like constants (they are converted to 16-bit-addresses). The commands are as follows:

File Structure
A very basic assembler file may look like that: final: LDI HIGH(final), R00 LDI LOW(final), R00 MV R00,R30 This is a simple endless loop which should be placed at the end of every assembler file to prevent the processor to execute unwanted code.

As usual, semicolon can be used for comments. When using a C-Precompiler, some defines may be useful:


 * Convenience defines
 * Convenience defines


 * 1) define ZERO r29
 * 2) define JMP MV R00,R30

final: LDI HIGH(final), R00 LDI LOW(final), R00 JMP

Usage
$ ./as-iMISC.exe --help iMISC assembler, reads from stdin, writes to stdout switches: -t --text  ... create human readable assembler output from input -b --binary ... create binary text from input -v --vhdl  ... create VHDL output from input (default) To run the C preprocessor before assembling (recommended): gcc -x c -E -C -P | ./as-iMISC

Files
All files related to this project are available at http://stud4.tuwien.ac.at/~e0325880/iMISC/. As there are:
 * assembler