PicoCPU

From ATI public wiki
Revision as of 15:04, 24 November 2015 by Karljans (Talk)

Jump to: navigation, search

The picoCPU was built as a course work during the Digital Systems Modelling and Synthesis course. Its goal is to provide very simple and minimal, but still functional, general purpose CPU design for educational purposes.

Architecture

Architecture of picoCPU

PicoCPU is divided into four main components (seen in the figure on the right):

  • Control Unit (CU): Reads the instructions, advances the program counter and controls the work of the rest of the CPU
  • Data Path Unit (DPU): Does all the calculations and other data manipulation operations
  • Program Memory (PM): A ROM that contains the program data. In picoCPU, it is emulated by the testbench.
  • Data memory (DM): The data memory is implemented as a RAM. It contains the temporary data that are needed by the currently running program.

PicoCPU is designed to have a generic design and it's bitwidth is scalable to satisfy the user's preference, being 8-bit by default. All the data are always treated as signed values.

Control Unit

Diagram of the control unit for picoCPU

The most important part of the CU is the control FSM, that has four states:

  1. Fetch: fetches the data from the program memory and stores it in the instruction register.
  2. Decode: Seperates operand from instruction
  3. Execute: Executes the instruction
  4. Write back: Writes execution result to the destination register or memory address, advances the program counter.

The program counter (PC) is a pointer to the program memory address of the currently executed instruction. The program counter's value directly specifies the memory address for reading the program memory. Usually, the program counter is increased by one after the current instruction is loaded (next address of the program memory is chosen). However, it is also possible to change the PC's value to an arbitrary one, for example to implement branching in the code.

Data Path Unit

Diagram of the DPU's architecture for the picoCPU

ALU

The central part of the DPU is the Arithmetic and Logic Unit (ALU). ALU's task is to execute all the arithmetical and logical calculations. It has many functions and the correct one is chosen by the CU, based on the currently executed instruction. Every calculation result always ends up in the accumulator register. The first input of the ALU can be multiplexed between a register and the operand from the operand from the program memory and the contents of a register (the multiplexer can be controlled be specific instructions). The second input is always the contents of the accumulator.

Memory operations

Writing to and reading from the data memory always involves the accumulator - all data read from the memory always ends up in the accumulator. It is also only possible to write into the memory data that is stored in the accumulator.

For writing into the register, the file data to be written has to be already in the accumulator. Then, a special instruction is used for doing the writing. Reading from the register can be done only through the ALU, using the regular ALU-related instructions, just the MUX has to be configured to take its input from the register. Due to the fact that it is possible to access the register only through the ALU, the value of the register can only be retrieved by running an arithmetic or logic operation on it. If just retreaving of the value is desired, a neutral operation, that does not change the value can be performed, like adding or subtracting 0 to/from the register or AND-ing the value with 1-s.

Flags

The picoCPU features two flags: zero (Z) and overflow(OV)

The zero flag indicates that the value in the accumulator is equal to 0 and OV flag indicates that the last operation caused an overflow in the accumulator. User can access the values of these flags using some conditional branching functions (BranchIfZero, etc.). The flags are only held up as long as the condition for a flag is true (i.e. the accumulator is zero) and are, thus, usually available only to the next isntruction (except some neutral instructions like NOP, that are not data-related).

Impementation

Diagram showing implementation of picoCPU

Each main component of picoCPU is implemented as a separate entity. The structure of the connections can be seen in the figure on the right.

In case of picoCPU, the program memory is emulated be the testbench. Its contents are read from a text file. This enables easy reprogramming of picoCPU for simulation purposes.

Program Memory Data format

Description of the instruction format for picoCPU

As it can be seen in the figure on the right, each instruction for the picoCPU consists of 16 bits. The three highest bits are reserved and not currently used, so they should be given the values '0'. The next 5 bits (bits 12 - 8) specify the opcode. Finally the lowest 8 bits (bits 7-0) specify the operand. It has to be noted, that picoCPU accepts only one operand in an instruction. In case no operand is needed for the instruction, the operand bits are ignored.

Program memory file format

As mentioned above, the program memory in picoCPU is emulated by the tesbench and its contents are read from a text file. The format of the text file is quite simple: each line represents one memory address, line 1 mapping to memory address 0x0, line 2 to address 0x1 and so on. Each line contains 16 bits in a format mentioned above.

The execution of the program starts from memory address 0x0 and the address is normally increased by one after executing of every line, except branching instructions, that can cause the program execution to jump to other addresses.

Instruction set

Opcode Instruction Description Register Transfer Language Description
00000 ADD Add the operand to the AC, no carry in AC ← AC + OP
00001 SUB Subtract the operand from the AC, no carry in AC ← AC – OP
00010 INC Increment the AC by one, no carry in AC ← AC + 1
00011 DEC Decrement the AC by one, no carry in AC ← AC -1
00100 SLL Logical shift the AC value to the left AC ← SLL(AC)
00101 SRL Logical shift the AC value to the right AC ← SRL(AC)
00110 SLA Arithmetical shift the AC value to the left AC ← SLA(AC)
00111 SRA Arithmetical shift the AC value the right AC ← SRA(AC)
01000 AND AND the operand with the AC AC ← AC AND OP
01001 OR OR the operand with the AC AC ← AC OR OP
01010 XOR XOR the operand with the AC AC ← AC XOR OP
01011 INV Invert the AC value AC ← INV(AC)
01100 NEG Calculate the opposite-signed value of the AC value (pos → neg, neg → pos) AC ← INV(AC)+1
01101 LOADN Load the number in operand into the AC AC ← OP
01110 LOADV Load the value of the address specified in the operand into the AC AC ← M(OP)
01111 STORE Store the contents of the AC into the address in the operand M[OP] ← AC
10000 JMP Set the program counter to the value in the operand PC ← OP
10001 BIZ If 0 flag is set, set PC to address in operand, else by increase it by 1 if (Z == 1) then PC ← OP, else PC ← PC +1
10010 BINE Subtract the operand from the AC. if 0 flag set, PC=PC+1( instruction PC+1 has to contain jump command to branch), else PC=PC+2 AC ← AC – OP; if (Z != 1) then PC ← PC + 1, else PC ← PC + 2
10011 BIOF If OV flag is set, set PC to address in operand, else by increase it by 1 if (OV == 1) then PC ← OP, else PC ← PC +1
10100 SETR Copy the value in the AC into the register R ← AC
10101 CLRR Clear the register R ← 0
10110 SETF Set the flag described in operand F[OP] ← 1
10111 CLRF Clear the flag in operand F[OP] ← 0
11000 MUXR Set the ALU input to the register After executing that instruction, all operands in all instructions will be replaced by the contents of the chosen register until MUXOP is executed OP ← R
11001 MUXOP Set the ALU input to operand in. The operand in this command is ignored OP ← OP
11010 LOADA Load the value from a memory cell specified in the AC into the AC AC ← M(AC)
11011 STOREA Stores the value in the register to address in AC M(AC) ← R
11100 HALT Halt the CPU PC ← PC
11101 NOP No operation PC ← PC + 1
11110 NOP All unused instructions are treated as NOP
11111 NOP All unused instructions are treated as NOP