Introduction

This project will aid new FPGA designers to tackle a real project using VHDL and Verilog and later Matlab HDL generator. The idea is to develop a full 16 bit SOC (System on a chip) system that will be used in or Hexapod project. Also we're going improve our HDL coding design. This project will be largelly based on xsoc xr16 project and my magic-1 fpga port aka as "fpga-magic-1". This processor should be very simple and easy to read, so I will supress MMU, Instruction set, addressing modes, etc.. to keep it simple.

Processor main characteristics

This processor will be a RISC non pipeline 16 bit big endian processor (By means of non pipeline we mean that our processor will execute one instruction at a time). As xr16 this processor will be designed to run integer-only C programs. After we develop our processor we will also develop a simple assembly compiler and retarget lcc to generate code to our processor.

Other important characteristic of our architecture is that our processor is Von Neumann. Wich means that our program and the data will be placed in the same memory storage.

Data Format

With this 16 bit processor we're going to define our data types like this:

typedef unsigned char Byte; // 8 bits

typedef unsigned Word; // 16 bits

typedef unsigned long Long; // 32 bits

Program Counter and addressing modes

Our PC register will have 16 bits wich means that we're going to address 65K of memory, on reset PC will be set to address 0, and each normal instruction it will be added by 2. The branch instructions may add different values in the case of displacements, the jump instructions will directly load a value.

Other point... Each instruction is 16-bit wide, so, we will encode our opcodes in 16-bits...

Register file

We're going to have 16 registers each one with the following meaning:

Register description table

Register

Use

r0 General register
r1=RAcc Reserved for assembler (Accumulator)
r2 General register
r3-r5 Routine parameters (Fast mode)
r6-r9 General register
r10-r12 Register variables (Fast mode)
r13 Stack pointer

System Flags

Some instructions will set some hardware flags, used to check conditions and stuff, in our processor we will be using these.

Flags description table
Flag Description
Zero Result of ALU operation is Zero
Sign Flag set when we have negative result
Carry Indicate an arithmetic carry or borrow has been generated out of the most significant ALU bit (Unsigned overflow)
Overflow Indicate when an arithmetic overflow has occurred in an operation. 127+127=-2 (Overflow)

Instruction set and description

Now one of the most important part of a CPU design, the instruction set ... our CPU will have 32 instructions so they can be encoded with 5 bits. The table bellow show this encoding format.

Instruction Format
15-11 10-7 6-3 2-0
opcode 0000 0000 000
opcode r(destiny) 0000 000
opcode imm10-7 imm6-3 imm2-0
opcode r(destiny) r(source) 000

 

Data Movement instructions
Instruction Encoding Operation Desctiption Sample
mov 00001 rrrr rrrr 000 r(1) = r(2) Move the content of some register to another mov r1,r2
movi 00010 imm11 000 RAcc = imm11 Move the imediate 11 bit value to Accumulator mov r1,0xFF
ldm 00011 rrrr rrrr 000 r(1) = mem(r(2)) Load some value from memory pointed by r(1) and place in some register ldm r1,r2
stm 00100 rrrr rrrr 000 mem(r(1)) = r(2) Place in memory pointed by r(1) the value in r(2) stm r1,r2

 

Arithimetic and logical instructions
Instruction Encoding Operation Desctiption Sample
and 00101 rrrr rrrr 000 RAcc = r(1) and r(2) Move the content of some register to another mov r1,r2
or 00110 rrrr rrrr 000 RAcc = r(1) or r(2) Move the imediate 8 bit value to some register mov r1,0xFF
not 00111 rrrr 0000000 RAcc = NOT r(1) Invert all values of r(1) register not r2
inc 01000 rrrr 0000000 r(1) = r(1) + 1 Increment register content inc r3
dec 01001 rrrr 0000000 r(1) = r(1) - 1 Decrement register content dec r2
add 01010 rrrr rrrr 000 RAcc = r(1) + r(2) Add r(1) and r(2) and place result in R accumulator add r4,r5
sub 01011 rrrr rrrr 000 RAcc = r(1) - r(2) Subtract r(1) and r(2) and place result in R accumulator sub r4,r5
shfl 01100 rrrr 0000000 r(1) = r(1) << 1 Shift left shfl r5
shfr 01101 rrrr 0000000 r(1) = r(1) >> 1 Shift right shfr r5
rotr 01110 rrrr rrrr 000 r(1) = r(1) ror 1 Rotate right rotr r5

 

Jump instructions
Instruction Encoding Operation Desctiption Sample
jmp 01111 rrrr 0000000 PC = r(1) Jump absolute to some position pointed by some register jmp r4
jmpr 10000 s imm10

if (s imm10 != 0) then

if s = 0 then PC = PC + imm10

else PC = PC - imm10

Jump relative if s=0 increment PC by imm10 if s=1 decrement PC by imm10 jmpr 3
jz 10001 rrrr 0000000

if (ZeroFlag) then PC = r(1)

Jump if zero absolute jz r1
jzr 10010 s imm10

if (ZeroFlag) then

if s = 0 then PC = PC + imm10

else PC = PC - imm10

Jump if zero relative if s=0 increment PC by imm10 if s=1 decrement PC by imm10 jzr 3
jnz 10011 rrrr 0000000 if (!ZeroFlag) then PC = r(1) Jump if not zero absolute jnz r4
jnzr 10100 s imm10

if (!ZeroFlag) then

if s = 0 then PC = PC + imm10

else PC = PC - imm10

Jump if not zero relative (Comes back in jnzr 10
jp 10101 rrrr 0000000 if (SignFlag) then PC = r(1) Jump absolute if positive jp r3
jpr 10110 s imm10

if (SignFlag) then

if s = 0 then PC = PC + imm10

else PC = PC - imm10

Jump if positive relative if s=0 increment PC by imm10 if s=1 decrement PC by imm10 jpr 3
call 10111 rrrr 0000000 PC = r(1) , r2 = PC (current) Go to routine in adress pointed by r(1) call r1
ret 11000 00000000000 PC = r2 Return from routine to the point of calling ret

 

Input output and miscellaneous
Instruction Encoding Operation Desctiption Sample
in 11001 rrrr 0000000 r(1) = External Receive something from external 16 bits port in r1
out 11010 rrrr 0000000 External = r(1) Send something to external 16 bits port out r1
halt 11011 00000000000 HALT Halt the system halt
nop 11100 00000000000 no operation Does nothing just increment PC nop

 

Stack operations
Instruction Encoding Operation Desctiption Sample
push 11101 rrrr 0000000

mem(r13)=r(1)

r13 = r13 + 1

Push a value from r(1) in memory at address in r13

push r2

pop 11110 rrrr 0000000

r(1) = mem(r13)

r13 = r13 - 1

Get a value from memory at r13 and put in r(1) pop r2

 

One point to observe... the RAcc (the accumulator registe) is just the r1 register. By sacrificing one register we can simplify a little bit the instruction opcode size.

Project source code and instructions definitions

Next topic:

Now that we defined all the important aspects of our CPU we're going to define it's datapath that will be controled by the control unit.

Datapath