This functional single cycle (non-pipelined) processor is capable of performing basic arithmetic, logic and data operations. It is based on the ARM 64-bit architecture, with 32 registers each 64-bits wide with instruction lengths of 32-bits.
Basic assembly instructions: LDUR
, STUR
, ADD
, SUB
, ORR
, AND
, CBZ
, B
, and NOP
are supported by the CPU, with LDUR
and STUR
supporting immediate values when performing certain operations to the registers module.
During development, the group wrote a sample program (in ARMv7 assembly) and tested it on a Cypress PSoC 5LP and recorded its registers after each instruction. The group then verified this custom CPU with the state of the registers from the Cypress PSoC 5LP.
When working with the unconditional branch, instead of a written label the tested instruction use immediate values to where the location of memory where the program counter will branch to.
Since the ARM CPU is little endian, the instruction memory in this project is designed to have 64 8-bits for each index.
The Data Memory is made up of 31 64-bit values to show that the values could be accessed and stored via the CPU.
With the instruction memory, data memory and registers located outside the CPU itself, the project could be incrementally tested and treated as independent components on a physical board.
The examples below use the following 'variables' to show off the functionaility for each instruction:
r#
: Register # in the CPU (From 0 to 31)RAM
: Random Access Memory (RAM) or Data MemoryPC
: Program Counter
Example 1: LDUR r2, [r10]
- Sudo-C code:
r2 = RAM[r10]
- Explanation: Retrieve the value in memory at location
r10
and put that value into registerr2
Example 2: LDUR r3, [r10, #1]
- Sudo-C code:
r3 = RAM[r10 + 1]
- Explanation: Retrieve the value in memory at the location
r10 + immediate (1)
and put that value into registerr3
Example 1: STUR r1, [r9]
- Sudo-C code:
RAM[r9] = r1
- Explanation: Store the value of
r1
into memory at the locationr9
Example 2: STUR r4, [r7, #1]
- Sudo-C code:
RAM[r7 + 1] = r4
- Explanation: Store the value of
r4
into memory at the locationr7 + immediate (1)
Example: ADD r5, r3, r2
- Sudo-C code:
r5 = r3 + r2
- Explanation: Add the values of
r3
andr2
then put the result intor5
Note: This does not support immediate values. Only values within the registers!
Example: SUB r4, r3, r2
- Sudo-C code:
r4 = r3 - r2
- Explanation: Subtract the values of
r3
andr2
then put the result intor4
Note: This does not support immediate values. Only values within the registers!
Example: ORR r6, r2, r3
- Sudo-C code:
r6 = r2 | r3
- Explanation: Bit-wise OR the values of
r2
andr3
then put the result intor6
Note: This does not support immediate values. Only values within the registers!
Example: AND r4, r3, r2
- Sudo-C code:
r4 = r3 & r2
- Explanation: Bit-wise AND the values of
r3
andr2
and put the result intor4
Note: This does not support immediate values. Only values within the registers!
Example: CBZ r1, #2
- Sudo-C code:
if (r1 == 0) { PC = 2 } else { PC++ }
- Explanation: If the value of
r1
is zero then jump to instruction 2, otherwise, continue executingPC++
Example: B #2
- Sudo-C:
PC = 2
- Explanation: Jump to instruction 2
Example: NOP
- Sudo-C:
;
- Explanation: An instruction that makes the processor wait one clock cycle.
The thirteen instructions as shown in the table below is the test program used to test the functionality of the CPU.
Line # | ARM Assembly | Machine Code | Hexadecimal |
---|---|---|---|
1 | LDUR r2, [r10] |
1111 1000 0100 0000 0000 0001 0100 0010 | 0xF8400142 |
2 | LDUR r3, [r10, #1] |
1111 1000 0100 0000 0001 0001 0100 0011 | 0xF8401143 |
3 | SUB r4, r3, r2 |
1100 1011 0000 0010 0000 0000 0110 0100 | 0xCB020064 |
4 | ADD r5, r3, r2 |
1000 1011 0000 0010 0000 0000 0110 0101 | 0x8B020065 |
5 | CBZ r1, #2 |
1011 0100 0000 0000 0000 0000 0100 0001 | 0xB4000041 |
6 | CBZ r0, #2 |
1011 0100 0000 0000 0000 0000 0100 0000 | 0xB4000040 |
7 | LDUR r2, [r10] |
1111 1000 0100 0000 0000 0001 0100 0010 | 0xF8400142 |
8 | ORR r6, r2, r3 |
1010 1010 0000 0011 0000 0000 0100 0110 | 0xAA030046 |
9 | AND r7, r2, r3 |
1000 1010 0000 0011 0000 0000 0100 0111 | 0x8A030047 |
10 | STUR r4, [r7, #1] |
1111 1000 0000 0000 0001 0000 1110 0100 | 0xF80010E4 |
11 | B #2 |
0001 0100 0000 0000 0000 0000 0000 0011 | 0x14000003 |
12 | LDUR r3, [r10, #1] |
1111 1000 0100 0000 0001 0001 0100 0011 | 0xF8401143 |
13 | ADD r8, r0, r1 |
1000 1011 0000 0001 0000 0000 0000 1000 | 0x8B010008 |
The instructions were entered into the instruction memory itself to properly show its functionality while simulated.
The Registers were initialized with values from 0-30 with register 31 defined set to 0 as stated in the reference sheet for LEGv8.
The Data Memory was initialized with values starting from 0-3100 with each content of memory being 100 more than the previous index with an exception of index 10 and 11 with the contents 1540 and 2117 respectively.
-
ARM LEGv8 CPU Module - ARM_CPU.v
-
ARM LEGv8 Testbench - CPU_TEST.v