Microinstruction

Microinstructions are stored in the control store and are fetched with the address stode at MPC (Microprogram Counter).

A Vondel microinstruction has 62 bits the following format:

NEXTJAMALUC BUSMEMABIMMEDIATE
9 bits3 bits9 bits20 bits3 bits5 bits5 bits8 bits

You can find a more detailed version of this diagram here

NEXT

The NEXT field stores the next microinstruction address. In other words, the NEXT field stores the next value to be stored at MPC.

JAM

The JAM field stores in which conditions the program should jump. A Jump is a change in the natural flow of the microprogram that represents that the next instruction should be changed is some way.

We have 3 possible condition to jump: if the value returned by ALU is 0 (JAMZ), if is negative (JAMN) and if we want to change the next instruction using something stored at MBR (JMPC). The first bit (MSB) from JAM is JMPC, the second is JAMN and the last is JAMZ.

On JAMN and JAMZ a jump is, in fact, a OR operation on the most sigficant bit of MPC and the condition. In other words, if the condition is true, which happens when its bit is 1, that 1 is bitwise ORed with the MSB of MPC, so if the value of MPC is 000001010 the jump position is 100001010. But on JMPC, a jump is a bitwise or with MBR and the 8 LSB's from MPC.

ALU

The ALU field actually controls 2 devices: the ALU itself and the shifter connected to its autput.

The ALU has two input, A and B (that come from the A and B bus, respectively) and it's controled by the 6 LSB's from the ALU field, they are:

  • F0, F1 and F2 (Controls the ALU function)
  • ENA and ENB (Enables the input from A and B bus respectively)
  • INVA (Inverts the bits of A)
  • INC (Increments 1 to the ALU result)

from MSB to LSB. The logic and arithmetic functions that ALU can operate are managed by F0, F1 and F2 like this:

F0F1F2Function
000A AND B
001A OR B
010NOT B
011A + B
100A XOR B
101A * B
110A / B
111A % B

Where AND, OR and XOR are bitwise operations and +, *, / and % are the addition, multiplication, division and remainder arithmetic operations respectively.

Some useful combinations of ALU signal can be found below:

F0F1F2ENAENBINVAINCFunction
0011000A
0010100B
0011010not A
0101100not B
0111100A + B
0111101A + B + 1
0111001A + 1
0110101B + 1
0111111B − A
0110110B − 1
0111011−A
0001100A AND B
0011100A OR B
00100000
01100011
0110010−1
1001100A XOR B
1011100A * B
1101100A / B
1111100A % B

The shifter has 2 inputs: The value of the ALU operation (let's call it X) and the operation opcode that are which are the 2 MSB's from the ALU field. The operations and its opcode are as following:

OpcodeOperationOutput
0b00NoneX
0b01Shift Right 1 bitX >> 1
0b10Shift Left 8 bitsX << 8
0b11Shift Left 1 bitX << 1

C BUS

The C BUS field represents which registers gonna be writen with the value of the C BUS (which is the shifter output). This field has 20 bits because there are 20 registers connected to the C bus, each bit 1 represents that the register represented by that bit should be writen by the C BUS.

The relation between a bit n and which register it's represents is shown below (from MSB to LSB):

BitRegister
1MDR
2MAR
3PC
4LV
5R0
6R1
7R2
8R3
9R4
10R5
11R6
12R7
13R8
14R9
15R10
16R11
17R12
18R13
19R14
20R15

MEM

The memory field represents which memory operations gonna happen in the cycle. The bit 1 (MSB), 2 and 3 represents the operations of WRITE, READ and FETCH respectively.

Each bit 1 in the field informs that the memory operation related to that field will be executed. What is actually done in operations can be found below:

  • READ: Reads the memory word (32 bit) of the address stored in MAR into MDR.
  • WRITE: Writes the memory word stored in MDR into the memory address stored in MAR.
  • FETCH: Reads the memory word of the address stored in PC into MBR (8-bit) and MBR2 (16-bit).

The FETCH operation uses the IFU to store the remainder bytes in cache to only access memory when needed.

A and B

A and B are fields that control which register writes to the A and B bus respectively, but, since the A and B bus are connected directly to the A and B inputs of the ALU, they can also be viewed as which register goes as a entry to the ALU operation.

The values of A and B and which register they enable (NONE, represents that none of them writes to the respective BUS, so the value of the bus is 0) is shown below:

Output to BUS A:

IDBINRegister
000000MDR
100001PC
200010MBR
300011MBRU
400100MBR2
500101MBR2U
600110LV
700111CPP
801000IMMEDIATE
901001R0
1001010R1
1101011R2
1201100R3
1301101R4
1401110R5
1501111R6
1610000R7
1710001R8
1810010R9
1910011R10
2010100R11
2110101R12
2210110R13
2310111R14
2411000R15
.....NONE

Output to BUS B:

IDBINRegister
000000MDR
100001LV
200010CPP
300011IMMEDIATE
400100R0
500101R1
600110R2
700111R3
801000R4
901001R5
1001010R6
1101011R7
1201100R8
1301101R9
1401110R10
1501111R11
1610000R12
1710001R13
1810010R14
1910011R15
.....NONE

IMMEDIATE

The immediate field allows us to send a arbitrary 8 bit number to the A or B bus, i.e if we set 0x08 in the IMMEDIATE field and enable the immediate input on the A and/or B bus, that 0x08 gonna be loaded in the corresponding bus.

Assembly

Some details about the relation between the assembly code and the microarchitecture.

Register nomeclature

In the assembly code the general purpose registers were renamed for convenience in when writing code, the rename table is as following:

RegisterAssembly Name
R0Ra
R1T0
R2T1
R3T2
R4T3
R5S0
R6S1
R7S2
R8S3
R9S4
R10S5
R11S6
R12A0
R13A1
R14A2
R15A3

WARNING: The registers T0 - T3 can be used in instructions like mul to store temporary values, so the value of those can be changed in the instruction implementations, therefore they are not guaranteed to have the value that you expect using instruction like lui or read.

Assembly Implementations

You can find some implementatinos examples of assembly code into the microarchitecture in the next chapter.