Index

CPU (CISC)

The following is a design for a simple 16-bit central processing unit (CPU) which can be seen as an example of a microprogrammed programmable control unit. The implementation described is similar to the CPU shown here. The major difference is that this implementation has several addressing modes and a more flexible microprogramming scheme.

Instruction Set Architecture

The CPU's instruction set architecture (instructions, addressing modes, programmer visible registers, and interrupt handling) is detailed in this section.

Registers

There are 16 register addresses but only 15 registers, and of these only 7 are available to the programmer. Each register is 16-bits wide. Register 0 is always read as zero and it cannot be loaded. Registers 1 to 7 are available to the programmer to use as he/she wishes. The registers 8 to 15 are used internally by the CPU and are not available to the programmer.

Instructions

For each instruction the following is given:

The symbols used are as follows:

Generic Format

151413121110 9876543210
Opcode Mode S SRC DST
Data Word

Zero Operand

This class of instruction covers a group of instructions which have no common theme other than they take no operands.

151413121110 9876543210
00XXXX

One Operand

This class of instruction covers the stack and shifter operations. If the mode is 000 or 001 then the data word is not present.

151413121110 9876543210
01XXXX Mode S SHA DST
Data Word

Two Operand

This class of instruction covers the arithmetic and logic operations and data movement. If the mode is 000 or 001 then the data word is not present.

151413121110 9876543210
10XXXX Mode S SRC DST
Data Word

Branch

This class of instructions covers branching and procedure call. If the mode is 000 or 001 then the data word is not present.

151413121110 9876543210
11XXXX Mode DST
Data Word

Mode

The table below enumerates all of the addressing modes. The three bit instruction field Mode is used as a selector, DST and SRC are three bit register addresses found in the instruction. The value W is the data word that follows the instruction in memory.

Two Operand
Mode Name One Operand/Branch S=0 S=1
000 Register PUSH REG[DST] ADD REG[DST], REG[SRC] ADD REG[DST], REG[SRC]
001 Register Indirect PUSH MEMORY[REG[DST]] ADD REG[DST], MEMORY[REG[SRC]] ADD MEMORY[REG[DST]], REG[SRC]
010 Immediate PUSH W ADD REG[DST], W ADD W, REG[SRC]
011 Direct PUSH MEMORY[W] ADD REG[DST], MEMORY[W] ADD MEMORY[W], REG[SRC]
100 Indexed PUSH MEMORY[REG[DST]+W] ADD REG[DST], MEMORY[REG[SRC]+W] ADD MEMORY[REG[DST]+W], REG[SRC]
101 Indexed Indirect PUSH MEMORY[MEMORY[REG[DST]+W]] ADD REG[DST], MEMORY[MEMORY[REG[SRC]+W]] ADD MEMORY[MEMORY[REG[DST]+W]], REG[SRC]
110 Relative PUSH MEMORY[PC+W]] ADD REG[DST], MEMORY[PC+W]] ADD MEMORY[PC+W]], REG[SRC]
111 Relative Indirect PUSH MEMORY[MEMORY[PC+W]]] ADD REG[DST], MEMORY[MEMORY[PC+W]]] ADD MEMORY[MEMORY[PC+W]]], REG[SRC]

Instruction List

The list of instructions is now given.

ADD

Addition.

151413121110 9876543210
100010

REG[DST] ⇐ REG[DST] + REG[SRC]

Flags: C, N, V, and Z.

ADDC

Addition with carry.

151413121110 9876543210
100011

REG[DST] ⇐ REG[DST] + REG[SRC] + C

Flags: C, N, V, and Z.

AND

Bitwise conjunction.

151413121110 9876543210
101001

REG[DST] ⇐ REG[DST] & REG[SRC]

Flags: N, and Z.

ASL

Arithmetic shift left.

151413121110 9876543210
011001

REG[DST] ⇐ REG[DST] << REG[SHA]

Flags: C, N, V, and Z.

ASR

Arithmetic shift right.

151413121110 9876543210
011000

REG[DST] ⇐ REG[DST] >> REG[SHA]

Flags: C, N, V, and Z.

CALL

Subroutine call.

151413121110 9876543210
110001

SP ⇐ SP - 1
MEMORY[SP] ⇐ PC
PC ⇐ MEMORY[REG[DST]]

Flags: None.

BC

Branch if carry.

151413121110 9876543210
110001

if(C == 1)
  PC ⇐ MEMORY[REG[DST]]

Flags: None.

BN

Branch if negative.

151413121110 9876543210
110100

if(N == 1)
  PC ⇐ MEMORY[REG[DST]]

Flags: None.

BNC

Branch if not carry.

151413121110 9876543210
110011

if(C == 0)
  PC ⇐ MEMORY[REG[DST]]

Flags: None.

BNN

Branch if negative.

151413121110 9876543210
110101

if(N == 0)
  PC ⇐ MEMORY[REG[DST]]

Flags: None.

BNV

Branch if not overflow.

151413121110 9876543210
110111

if(V == 0)
  PC ⇐ MEMORY[REG[DST]]

Flags: None.

BNZ

Branch if not zero.

151413121110 9876543210
111001

if(Z == 0)
  PC ⇐ MEMORY[REG[DST]]

Flags: None.

BV

Branch if overflow.

151413121110 9876543210
110110

if(V == 1)
  PC ⇐ MEMORY[REG[DST]]

Flags: None.

BZ

Branch if zero.

151413121110 9876543210
111000

if(Z == 1)
  PC ⇐ MEMORY[REG[DST]]

Flags: None.

CMP

Compare. Two values are subtracted for their side effects on the PSR status bits only.

151413121110 9876543210
101000

REG[DST] - REG[SRC]

Flags: C, N, V, and Z.

DEC

Decrement.

151413121110 9876543210
010011

REG[DST] ⇐ REG[DST] - 1

Flags: C, N, V, and Z.

INC

Increment.

151413121110 9876543210
010010

REG[DST] ⇐ REG[DST] + 1

Flags: C, N, V, and Z.

JMP

Unconditional branch.

151413121110 9876543210
110000

PC ⇐ MEMORY[REG[DST]]

Flags: None.

MOV

Move data.

151413121110 9876543210
100000

REG[DST] ⇐ REG[SRC]

Flags: None.

MVS

Move a byte string of a given length from one location to another. The length is taken from REG[3] which is interpreted as a signed integer, the source address is taken from REG[1], and the destination address is taken from REG[2].

151413121110 9876543210
000011

REG[8] ⇐ REG[1]
REG[9] ⇐ REG[2]
REG[10] ⇐ REG[3]
loop:
REG[10] ⇐ REG[10] - 1
if(REG[10] >= 0)
  REG[11] ⇐ MEMORY[REG[8]]
  MEMORY[REG[9]] ⇐ REG[11]
  REG[8] ⇐ REG[8] + 1
  REG[9] ⇐ REG[9] + 1
  goto loop

Flags: None.

NEG

Negate.

151413121110 9876543210
010100

REG[DST] ⇐ -REG[DST]

Flags: C, N, V, and Z.

NOP

No operation.

151413121110 9876543210
000000

Flags: None.

NOT

Not (complement).

151413121110 9876543210
010101

REG[DST] ⇐ ~REG[DST]

Flags: C, N, V, and Z.

OR

Bitwise disjunction.

151413121110 9876543210
101010

REG[DST] ⇐ REG[DST] | REG[SRC]

Flags: N, and Z.

POPR

Pop the registers from the stack.

151413121110 9876543210
000010

REG[1] ⇐ MEMORY[SP]
SP ⇐ SP + 1
REG[2] ⇐ MEMORY[SP]
SP ⇐ SP + 1
REG[3] ⇐ MEMORY[SP]
SP ⇐ SP + 1
REG[4] ⇐ MEMORY[SP]
SP ⇐ SP + 1
REG[5] ⇐ MEMORY[SP]
SP ⇐ SP + 1
REG[6] ⇐ MEMORY[SP]
SP ⇐ SP + 1
REG[7] ⇐ MEMORY[SP]
SP ⇐ SP + 1

Flags: None.

POP

Pop a value from the stack.

151413121110 9876543210
010001

REG[DST] ⇐ MEMORY[SP]
SP ⇐ SP + 1

Flags: None.

PUSH

Push a value onto the stack.

151413121110 9876543210
010000

SP ⇐ SP - 1
MEMORY[SP] ⇐ REG[DST]

Flags: None.

PSHR

Push the registers onto the stack.

151413121110 9876543210
000001

SP ⇐ SP - 1
MEMORY[SP] ⇐ REG[1]
SP ⇐ SP - 1
MEMORY[SP] ⇐ REG[2]
SP ⇐ SP - 1
MEMORY[SP] ⇐ REG[3]
SP ⇐ SP - 1
MEMORY[SP] ⇐ REG[4]
SP ⇐ SP - 1
MEMORY[SP] ⇐ REG[5]
SP ⇐ SP - 1
MEMORY[SP] ⇐ REG[6]
SP ⇐ SP - 1
MEMORY[SP] ⇐ REG[7]

Flags: None.

RET

Return from subroutine.

151413121110 9876543210
000100

PC ⇐ MEMORY[SP]
SP ⇐ SP + 1

Flags: None.

ROL

Rotate left.

151413121110 9876543210
011011

REG[DST] ⇐ REG[DST] << REG[SHA]

Flags: C, and Z.

ROLC

Rotate left through carry.

151413121110 9876543210
011101

REG[DST] ⇐ REG[DST] << REG[SHA]

Flags: C, and Z.

ROR

Rotate right.

151413121110 9876543210
011010

REG[DST] ⇐ REG[DST] >> REG[SHA]

Flags: C, and Z.

RORC

Rotate right through carry.

151413121110 9876543210
011100

REG[DST] ⇐ REG[DST] >> REG[SHA]

Flags: C, and Z.

RTI

Return from interrupt.

151413121110 9876543210
000101

PSR ⇐ MEMORY[SP]
SP ⇐ SP + 1
PC ⇐ MEMORY[SP]
SP ⇐ SP + 1

Flags: None.

SHL

Logical shift left.

151413121110 9876543210
010111

REG[DST] ⇐ REG[DST] << REG[SHA]

Flags: C, and Z.

SHR

Logical shift right.

151413121110 9876543210
010110

REG[DST] ⇐ REG[DST] >> REG[SHA]

Flags: C, and Z.

SUB

Subtraction.

151413121110 9876543210
100100

REG[DST] ⇐ REG[DST] - REG[SRC]

Flags: C, N, V, and Z.

SUBB

Subtraction with borrow.

151413121110 9876543210
100101

REG[DST] ⇐ REG[DST] - REG[SRC] - C

Flags: C, N, V, and Z.

XCHG

Move data

151413121110 9876543210
100001

REG[15] ⇐ REG[DST]
REG[DST] ⇐ REG[SRC]
REG[SRC] ⇐ REG[15]

Flags: None.

XOR

Bitwise exclusive disjunction.

151413121110 9876543210
101011

REG[DST] ⇐ REG[DST] ^ REG[SRC]

Flags: N, and Z.

Interrupt Handling

The INTS input line to the CPU is used to signal an interrupt (active high). The CPU will poll this input as the final stage of instruction execution. If the input is active then the CPU will branch to address zero. Before branching the current contents of the PC and PSR registers are pushed onto the stack. To resume execution the RTI instruction should be executed. Currently interrupts are not actually disabled via the EI status bit. This was omitted to save time.

CPU Top-level

The top-level module merely connects the control unit and the datapath.

	
module cpu (MEMA, MEMD, MWR, INTS, RESETn, CLK);
   output [15:0] MEMA;   // Memory Address.
   output [15:0] MEMD;   // Memory Data out.
   output 	 MWR;    // Memory WRite.
   input 	 INTS;   // INTerrupt Signal.   
   input 	 RESETn; // System reset.
   input 	 CLK;    // System clock.

   wire [15:0] 	 SHA;  // SHift Amount.   
   wire [4:0] 	 FS;   // Function unit Selector.
   wire [3:0] 	 MO;   // Misc. Operation.
   wire [3:0] 	 DST;  // DST register address.
   wire [4:0] 	 DSA;  // D and A register address.
   wire [3:0] 	 SRC;  // SRC register address.
   wire [4:0] 	 SB;   // B register address.
   wire [1:0] 	 MA;   // Multipexer A selector.
   wire [1:0] 	 MB;   // Multipexer B selector.
   wire 	 MD;   // Multipexer D selector.
   wire [15:0] 	 PC;   // Program Counter.
   wire [15:0] 	 SP;   // Stack Pointer.
   wire [15:0] 	 DBUS; // Bus D.
   wire 	 RL;   // Register file Load.  
   wire 	 MSC;  // MicroStatus Carry bit.
   wire 	 MSN;  // MicroStatus Negative bit.
   wire 	 MSV;  // MicroStatus oVerflow bit.
   wire 	 MSZ;  // MicroStatus Zero bit.
   wire 	 C;    // ISA Carry status bit.
   wire 	 N;    // ISA Negative status bit.
   wire 	 V;    // ISA oVerflow status bit.
   wire 	 Z;    // ISA Zero status bit.
   wire 	 EI;   // ISA Enable Interrupts status bit.
   
   control_unit cu0(SHA, MWR, FS, MO, DST, DSA, SRC, SB, MA, MB, MD, PC, SP, RL, DBUS, INTS, MSC, MSN, MSV, MSZ, C, N, V, Z, EI, RESETn, CLK);
   datapath d0(MEMA, MEMD, DBUS, EI, C, N, V, Z, MSC, MSN, MSV, MSZ, FS, MO, PC, SP, RL, DST, DSA, SRC, SB, MA, MB, MD, SHA, RESETn, CLK);
endmodule // cpu
	
      

Datapath

The top-level datapath module is just a container for the register file, the function unit, and the status registers.

	
module datapath(MEMA, MEMD,
		DBUS,
		EI, Cout, Nout, Vout, Zout,
		MCout, MNout, MVout, MZout,
		Op,
		MO,
		PC, SP, RL, DST, DSA, SRC, SB, MAS, MBS, MDS, SHA, RESETn, CLK);
   output [15:0] MEMA;	 // Memory Address.
   inout [15:0]	 MEMD;	 // Memory Data.
   output [15:0] DBUS;	 // D BUS.   
   output	 EI;	 // Processor Enable Interrupts status bit.   
   output	 Cout;	 // Processor Carry status bit.	  
   output	 Nout;	 // Processor Minus status bit.	  
   output	 Vout;	 // Processor oVerflow status bit.   
   output	 Zout;	 // Processor Zero status bit.	 
   output	 MCout;	 // Microstatus Carry status bit.   
   output	 MNout;	 // Microstatus Negative status bit.   
   output	 MVout;	 // Microstatus oVerflow status bit.   
   output	 MZout;	 // Microstatus Zero status bit.   
   input [15:0]	 PC;	 // Program Counter contents.
   input [15:0]	 SP;	 // Stack Pointer contents.
   input [4:0]	 Op;	 // Function unit operation.
   input [3:0]	 MO;	 // Misc. Operation.
   input	 RL;	 // Register Load.
   input [3:0]	 DST;	 // Address of D reg and A reg from instruction with prepended 0 bit. 
   input [4:0]	 DSA;	 // Address of D reg and A reg from microinstruction.
   input [3:0]	 SRC;	 // Address of A reg from instruction with prepended 0 bit.
   input [4:0]	 SB;	 // Address of B reg from microinstruction.
   input [1:0]	 MAS;	 // Mux A select.
   input [1:0]	 MBS;	 // Mux B select.
   input	 MDS;	 // Mux D select.
   input [15:0]	 SHA;	 // SHift Amount.
   input	 RESETn; // System reset.    
   input	 CLK;	 // System clock.
   
   wire [15:0]	 CST; // Constant from micro instruction via zero fill.
   wire [15:0]	 PSR; // 16-bit version of PSR bits.
   wire [15:0]	 RFA; // Connections to the register file for bus A.
   wire [15:0]	 RFB; // Connections to the register file for bus B.
   wire [15:0]	 A;   // Bus A.
   wire [15:0]	 B;   // Bus B.
   wire [15:0]	 Y;   // ALU output.
   
   assign MEMA = A;			    // Address bus (bus A).
   assign MEMD = (MDS == 1'b0) ? B : 16'bz; // Bus D input or output.
   
   zero_fill zf1(CST, SB);						      // CST goes into muxB.
   zero_fill zf2(PSR, {EI, Cout, Nout, Vout, Zout});			      // PSR goes into muxB.   
   register_file rf(RFA, RFB, DBUS, DST, DSA, SRC, SB, RL, CLK);	      // RFA goes into muxA, RFB goes into muxB.
   multiplexer_4_1 muxA(A, RFA, PC, SP, RFB, MAS[1], MAS[0]);		      // Bus A. This goes to MEM/IO as MEMA and into fu.
   multiplexer_4_1 muxB(B, RFB, PSR, CST, SHA, MBS[1], MBS[0]);		      // Bus B. This goes to MEM/IO as MEMD and into fu.
   function_unit fu(Y, C, V, N, Z, A, B, Cout, Op, MO);			      // Y goes to muxD.
   psr regPSR(EI, Cout, Nout, Vout, Zout, DBUS, C, N, V, Z, MO, RESETn, CLK); // Status bits go to the control unit, function unit, and into zf2.
   msts regMSTS(MCout, MNout, MVout, MZout, C, N, V, Z, MO, RESETn, CLK);     // Microstatus bits go to the control unit.
   multiplexer_2_1 muxD(DBUS, Y, MEMD, MDS);				      // Bus D. This goes to the register file and the control unit.
endmodule // datapath
	
      

PSR

The PSR is the Processor Status Register. It contains the status bits from the ALU: C, N, V, and Z, along with the EI status bit which Enables Interrupts (currently unused). The MO (Misc. Operation) input determines which status bits are updated.

MOMeaning
0000 NOP
0001 INACK = 1 (Acknowledge interrupt)
0010 Memory write (prevent write to register file)
0011 Load PC (prevent write to register file)
0100 Load IR and increment PC (prevent write to register file)
0101 Increment PC
0110 Load PSR (prevent write to register file)
0111 Load SP (prevent write to register file)
1000 Decrement SP
1001 Decrement SP and memory write (prevent write to register file)
1010 Increment SP
1011 Select C as Cin for ALU and update PSR bits CNVZ as below
1100 Update PSR bits CNVZ
1101 Update PSR bits CZ
1110 Update PSR bits NZ
1111 Update MSTS bits CNVZ
	
module psr(EI, Cout, Nout, Vout, Zout, D, C, N, V, Z, MO, RESETn, CLK);
   output EI;           // Enable Interrupt status bit output.
   output Cout;         // Carry status bit output.
   output Nout;         // Negative status bit output.
   output Vout;         // oVerflow status bit output.
   output Zout;         // Zero status bit output.
   input [15:0] D;      // Data from bus D.
   input 	C;      // Carry status bit from ALU.
   input 	N;      // Negative status bit from ALU.
   input 	V;      // oVerflow status bit from ALU.
   input 	Z;      // Zero status bit from ALU.
   input [3:0] 	MO;     // Misc. Operation.
   input 	RESETn; // Reset active low.
   input 	CLK;    // System clock.

   wire [15:0] 	Q;
   wire [15:0] 	RD;
   wire [15:0] 	RDMO;
   wire [15:0] 	QCNVZ, QCZ, QNZ;
   
   assign EI = Q[4];
   assign Zout = Q[3];
   assign Vout = Q[2];
   assign Nout = Q[1];
   assign Cout = Q[0];

   assign QCNVZ = (Q & 16'hfff0) | {Z,    V,    N,    C}; 
   assign QCZ   = (Q & 16'hfff6) | {Z, 1'b0, 1'b0,    C};
   assign QNZ   = (Q & 16'hfff5) | {Z, 1'b0,    N, 1'b0};
   
   multiplexer_16_1 mRD0(RDMO, Q, Q, Q, Q, Q, Q, D, Q, Q, Q, Q, QCNVZ, QCNVZ, QCZ, QNZ, Q, MO);
   multiplexer_2_1 mRD1(RD, 16'h0000, RDMO, RESETn); // Handle resets.  
   register_parallel_load r(Q, RD, 1'b1, CLK);   
endmodule // psr
	
      

MSTS

The MSTS register is the Microprogram STatuS. Essentially this register holds the C, N, V, and Z status bits from the ALU, and it is updated when the microcode executes ALU operations. With two registers, MSTS and PSR, we are free to use the ALU in our microprograms without interfering with the PSR. The MO (Misc. Operation) determines if the bits are to be updated or not.

MOMeaning
0000 NOP
0001 INACK = 1 (Acknowledge interrupt)
0010 Memory write (prevent write to register file)
0011 Load PC (prevent write to register file)
0100 Load IR and increment PC (prevent write to register file)
0101 Increment PC
0110 Load PSR (prevent write to register file)
0111 Load SP (prevent write to register file)
1000 Decrement SP
1001 Decrement SP and memory write (prevent write to register file)
1010 Increment SP
1011 Select C as Cin for ALU and update PSR bits CNVZ as below
1100 Update PSR bits CNVZ
1101 Update PSR bits CZ
1110 Update PSR bits NZ
1111 Update MSTS bits CNVZ
	
module msts(Cout, Nout, Vout, Zout, C, N, V, Z, MO, RESETn, CLK);
   output Cout;         // Carry status bit output.
   output Nout;         // Negative status bit output.
   output Vout;         // oVerflow status bit output.
   output Zout;         // Zero status bit output.
   input 	C;      // Carry status bit from ALU.
   input 	N;      // Negative status bit from ALU.
   input 	V;      // oVerflow status bit from ALU.
   input 	Z;      // Zero status bit from ALU.
   input [3:0] 	MO;     // Misc. Operation.
   input 	RESETn; // Reset active low.
   input 	CLK;    // System clock.

   wire [15:0] 	Q;
   wire [15:0] 	RD;
   wire [15:0] 	RDMO;
   wire [15:0] 	QCNVZ;
   wire 	S;
   
   assign Zout = Q[3];
   assign Vout = Q[2];
   assign Nout = Q[1];
   assign Cout = Q[0];
   assign QCNVZ = (Q & 16'hfff0) | {Z, V, N, C}; 
   and(S, MO[3], MO[2], MO[1], MO[0]);  // Update when MO = 4'b1111
   
   multiplexer_2_1 mRD0(RDMO, Q, QCNVZ, S);
   multiplexer_2_1 mRD1(RD, 16'h0000, RDMO, RESETn);  // Handle resets. 
   register_parallel_load r(Q, RD, 1'b1, CLK);   
endmodule // msts
	
      

Zero Fill

The zero fill module is used to zero extend the immediate data constant from the control unit and the PSR register contents to 16 bits so that they can be injected into the datapath.

	
module zero_fill(Y, A);   
   output [15:0] Y; // Result value zero filled.
   input [4:0] 	 A; // Value to fill.

   assign Y[0] = A[0];
   assign Y[1] = A[1];
   assign Y[2] = A[2];
   assign Y[3] = A[3];
   assign Y[4] = A[4];
   assign Y[15:5] = 11'b00000000000;
endmodule // zero_fill
	
      

Register File

The register file comprises 16 registers. Register 0 is always zero so it isn't really a register. DST and SRC are fields in the instruction used to address registers. These fields are 3 bits wide so the instruction can address the first 8 registers. However, when passed to the register file, these addresses have a 0 bit prepended to them to make the address 4 bits. DSA and SB are fields of the microinstruction. Bit 4 of these fields select between the microinstruction register or the instruction register (see muxda and muxb). Only one of DSA or SB can have bit 4 set. The one that has bit 4 set uses bit 3 to make the instruction field DST or SRC the destination or source (see muxs and muxaddr). DAA is the A and D bus register addresses. BA is the B bus register address.

DSA[4] DSA[3] SB[4] SB[3] DAA BA
0000DSA[3:0]SB[3:0]
0001DSA[3:0]SB[3:0]
0010DSA[3:0]DST
0011DSA[3:0]SRC
0100DSA[3:0]SB[3:0]
0101DSA[3:0]SB[3:0]
0110DSA[3:0]DST
0111DSA[3:0]SRC
1000DSTSB[3:0]
1001DSTSB[3:0]
1010XXXXXX
1011XXXXXX
1100SRCSB[3:0]
1101SRCSB[3:0]
1110XXXXXX
1111XXXXXX
	
module register_file(A, B, D, DST, DSA, SRC, SB, Load, CLK);
   output [15:0] A;     // Data contents of A reg.
   output [15:0] B;     // Data contents of B reg.
   input [15:0]  D;     // Data to load into D reg from bus D.
   input [3:0] 	 DST;   // Address of D reg and A reg from instruction with prepended 0 bit. 
   input [4:0] 	 DSA;   // Address of D reg and A reg from microinstruction.
   input [3:0] 	 SRC;   // Address of A reg from instruction with prepended 0 bit.
   input [4:0] 	 SB;    // Address of B reg from microinstruction.
   input 	 Load;  // Enable loading of D reg - active high.
   input 	 CLK;   // Clock.

   wire [3:0] 	 DAA;   // Address of A reg and D reg.
   wire [3:0] 	 BA;    // Address of B reg.
   wire [3:0] 	 ADDR;  // Address of either A reg and D reg, or of B reg.
   wire 	 SADDR; // Selector for muxaddr.
   
   registers reggies(A, B, D, DAA, BA, DAA, Load, CLK);
   multiplexer_2_1 #(1)muxS(SADDR, DSA[3], SB[3], SB[4]);
   multiplexer_2_1 #(4)muxAddr(ADDR, DST, SRC, SADDR);
   multiplexer_2_1 #(4)muxdA(DAA, DSA[3:0], ADDR, DSA[4]);
   multiplexer_2_1 #(4)muxB(BA, SB[3:0], ADDR, SB[4]);
   
endmodule // register_file

/*
 * 16 x 16-bit registers with register 0 always containing zero.
 */
module registers(A, B, D, AA, BA, DA, Load, CLK);
   output [15:0] A;     // Data contents of A reg.
   output [15:0] B;     // Data contents of B reg.
   input [15:0]  D;     // Data to load into D reg.
   input [3:0] 	 AA;    // Address of A reg.
   input [3:0] 	 BA;    // Address of B reg.
   input [3:0] 	 DA;    // Address of D reg.
   input 	 Load;  // Enable loading of D reg - active high.
   input 	 CLK;   // Clock.
   
   wire [15:0] 	 Q1, Q2, Q3, Q4, Q5, Q6, Q7;
   wire [15:0] 	 Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15;
   wire 	 dr0, dr1, dr2, dr3, dr4, dr5, dr6, dr7;
   wire 	 dr8, dr9, dr10, dr11, dr12, dr13, dr14, dr15;
   wire 	 load1, load2, load3, load4, load5, load6, load7;
   wire 	 load8, load9, load10, load11, load12, load13, load14, load15;
	 
   multiplexer_16_1 muxa(A, 16'h0000, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15, AA);
   multiplexer_16_1 muxb(B, 16'h0000, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, Q10, Q11, Q12, Q13, Q14, Q15, BA);

   // Note: dr0 is unused.
   hex_decoder decd(dr0, dr1, dr2, dr3, dr4, dr5, dr6, dr7, dr8, dr9, dr10, dr11, dr12, dr13, dr14, dr15, DA[3], DA[2], DA[1], DA[0], 1'b1);

   and(load1, dr1, Load);
   and(load2, dr2, Load);
   and(load3, dr3, Load);
   and(load4, dr4, Load);
   and(load5, dr5, Load);
   and(load6, dr6, Load);
   and(load7, dr7, Load);
   and(load8, dr8, Load);
   and(load9, dr9, Load);
   and(load10, dr10, Load);
   and(load11, dr11, Load);
   and(load12, dr12, Load);
   and(load13, dr13, Load);
   and(load14, dr14, Load);
   and(load15, dr15, Load);
   
   register_parallel_load r1(Q1, D, load1, CLK);
   register_parallel_load r2(Q2, D, load2, CLK);
   register_parallel_load r3(Q3, D, load3, CLK);
   register_parallel_load r4(Q4, D, load4, CLK);
   register_parallel_load r5(Q5, D, load5, CLK);
   register_parallel_load r6(Q6, D, load6, CLK);
   register_parallel_load r7(Q7, D, load7, CLK);
   register_parallel_load r8(Q8, D, load8, CLK);
   register_parallel_load r9(Q9, D, load9, CLK);
   register_parallel_load r10(Q10, D, load10, CLK);
   register_parallel_load r11(Q11, D, load11, CLK);
   register_parallel_load r12(Q12, D, load12, CLK);
   register_parallel_load r13(Q13, D, load13, CLK);
   register_parallel_load r14(Q14, D, load14, CLK);
   register_parallel_load r15(Q15, D, load15, CLK);
endmodule // registers

module register_parallel_load(Q, D, Load, CLK);
   output [15:0] Q;
   input [15:0]  D;
   input 	 Load;
   input 	 CLK;
   
   wire 	 Loadn;
   wire 	 w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12;           // Connecting wires.
   wire 	 w13, w14, w15, w16, w17, w18, w19, w20, w21, w22, w23, w24;  // Connecting wires.
   wire 	 w25, w26, w27, w28, w29, w30, w31, w32, w33, w34, w35, w36;  // Connecting wires.
   wire 	 w37, w38, w39, w40, w41, w42, w43, w44, w45, w46, w47, w48;  // Connecting wires.
   wire [15:0] 	 Qn;   // Unused.
   
   not(Loadn, Load);

   and(w1, Q[0], Loadn);
   and(w2, D[0], Load);
   or(w3, w2, w1);

   and(w4, Q[1], Loadn);
   and(w5, D[1], Load);
   or(w6, w5, w4);

   and(w7, Q[2], Loadn);
   and(w8, D[2], Load);
   or(w9, w8, w7);

   and(w10, Q[3], Loadn);
   and(w11, D[3], Load);
   or(w12, w11, w10);

   and(w13, Q[4], Loadn);
   and(w14, D[4], Load);
   or(w15, w14, w13);

   and(w16, Q[5], Loadn);
   and(w17, D[5], Load);
   or(w18, w17, w16);

   and(w19, Q[6], Loadn);
   and(w20, D[6], Load);
   or(w21, w20, w19);

   and(w22, Q[7], Loadn);
   and(w23, D[7], Load);
   or(w24, w23, w22);

   and(w25, Q[8], Loadn);
   and(w26, D[8], Load);
   or(w27, w26, w25);

   and(w28, Q[9], Loadn);
   and(w29, D[9], Load);
   or(w30, w29, w28);

   and(w31, Q[10], Loadn);
   and(w32, D[10], Load);
   or(w33, w32, w31);

   and(w34, Q[11], Loadn);
   and(w35, D[11], Load);
   or(w36, w35, w34);

   and(w37, Q[12], Loadn);
   and(w38, D[12], Load);
   or(w39, w38, w37);

   and(w40, Q[13], Loadn);
   and(w41, D[13], Load);
   or(w42, w41, w40);

   and(w43, Q[14], Loadn);
   and(w44, D[14], Load);
   or(w45, w44, w43);

   and(w46, Q[15], Loadn);
   and(w47, D[15], Load);
   or(w48, w47, w46);
   
   d_flip_flop_edge_triggered dff0(Q[0], Qn[0], CLK, w3);
   d_flip_flop_edge_triggered dff1(Q[1], Qn[1], CLK, w6);
   d_flip_flop_edge_triggered dff2(Q[2], Qn[2], CLK, w9);
   d_flip_flop_edge_triggered dff3(Q[3], Qn[3], CLK, w12);
   d_flip_flop_edge_triggered dff4(Q[4], Qn[4], CLK, w15);
   d_flip_flop_edge_triggered dff5(Q[5], Qn[5], CLK, w18);
   d_flip_flop_edge_triggered dff6(Q[6], Qn[6], CLK, w21);
   d_flip_flop_edge_triggered dff7(Q[7], Qn[7], CLK, w24);
   d_flip_flop_edge_triggered dff8(Q[8], Qn[8], CLK, w27);
   d_flip_flop_edge_triggered dff9(Q[9], Qn[9], CLK, w30);
   d_flip_flop_edge_triggered dff10(Q[10], Qn[10], CLK, w33);
   d_flip_flop_edge_triggered dff11(Q[11], Qn[11], CLK, w36);
   d_flip_flop_edge_triggered dff12(Q[12], Qn[12], CLK, w39);
   d_flip_flop_edge_triggered dff13(Q[13], Qn[13], CLK, w42);
   d_flip_flop_edge_triggered dff14(Q[14], Qn[14], CLK, w45);
   d_flip_flop_edge_triggered dff15(Q[15], Qn[15], CLK, w48);
   
endmodule // register_parallel_load

module d_flip_flop_edge_triggered(Q, Qn, C, D);
   output Q;
   output Qn;
   input  C;
   input  D;

   wire   Cn;   // Control input to the D latch.
   wire   Cnn;  // Control input to the SR latch.
   wire   DQ;   // Output from the D latch, inputs to the gated SR latch.
   wire   DQn;  // Output from the D latch, inputs to the gated SR latch.
   
   not(Cn, C);
   not(Cnn, Cn);   
   d_latch dl(DQ, DQn, Cn, D);
   sr_latch_gated sr(Q, Qn, Cnn, DQ, DQn);   
endmodule // d_flip_flop_edge_triggered

module d_latch(Q, Qn, G, D);
   output Q;
   output Qn;
   input  G;   
   input  D;

   wire   Dn; 
   wire   D1;
   wire   Dn1;

   not(Dn, D);   
   and(D1, G, D);
   and(Dn1, G, Dn);   
   nor(Qn, D1, Q);
   nor(Q, Dn1, Qn);
endmodule // d_latch

module sr_latch_gated(Q, Qn, G, S, R);
   output Q;
   output Qn;
   input  G;   
   input  S;
   input  R;

   wire   S1;
   wire   R1;
   
   and(S1, G, S);
   and(R1, G, R);   
   nor(Qn, S1, Q);
   nor(Q, R1, Qn);
endmodule // sr_latch_gated

module hex_decoder(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, A3, A2, A1, A0, E);
   output X0; // Minterm 0
   output X1; // Minterm 1
   output X2; // Minterm 2
   output X3; // Minterm 3
   output X4; // Minterm 4
   output X5; // Minterm 5
   output X6; // Minterm 6
   output X7; // Minterm 7
   output X8; // Minterm 8
   output X9; // Minterm 9
   output X10; // Minterm 10
   output X11; // Minterm 11
   output X12; // Minterm 12
   output X13; // Minterm 13
   output X14; // Minterm 14
   output X15; // Minterm 15
   
   input  A3;  // Input binary code most significant bit
   input  A2;
   input  A1;  
   input  A0;  // Input binary code least significant bit

   input  E;   // Enable signal

   wire   A3n; // A3 negated
   wire   A2n; // A2 negated
   wire   A1n; // A1 negated
   wire   A0n; // A0 negated

   not(A3n, A3);
   not(A2n, A2);
   not(A1n, A1);
   not(A0n, A0);
   
   and(X0, A3n, A2n, A1n, A0n, E);  // Minterm 0: 0000
   and(X1, A3n, A2n, A1n, A0, E);   // Minterm 1: 0001
   and(X2, A3n, A2n, A1, A0n, E);   // Minterm 2: 0010
   and(X3, A3n, A2n, A1, A0, E);    // Minterm 3: 0011
   and(X4, A3n, A2, A1n, A0n, E);   // Minterm 4: 0100
   and(X5, A3n, A2, A1n, A0, E);    // Minterm 5: 0101
   and(X6, A3n, A2, A1, A0n, E);    // Minterm 6: 0110
   and(X7, A3n, A2, A1, A0, E);     // Minterm 7: 0111
   and(X8, A3, A2n, A1n, A0n, E);   // Minterm 8: 1000
   and(X9, A3, A2n, A1n, A0, E);    // Minterm 9: 1001
   and(X10, A3, A2n, A1, A0n, E);   // Minterm 10: 1010
   and(X11, A3, A2n, A1, A0, E);    // Minterm 11: 1011
   and(X12, A3, A2, A1n, A0n, E);   // Minterm 12: 1100
   and(X13, A3, A2, A1n, A0, E);    // Minterm 13: 1101
   and(X14, A3, A2, A1, A0n, E);    // Minterm 14: 1110
   and(X15, A3, A2, A1, A0, E);     // Minterm 15: 1111
endmodule // octal_decoder
	
      

Function Unit

This unit is similar to the one described in the function unit notes. The table shows all of the operations where A and B are inputs and Y is the output.

OpFunction
00000Addition
00001Subtraction
00010Increment
00011Decrement
00100Bitwise AND
00101Bitwise OR
00110Bitwise XOR
00111Bitwise NOT
10000Y = A
11000Logical shift left
10100Logical shift right
11001Arithmetic shift left
10101Arithmetic shift right
11010Rotate left
10110Rotate right
11011Rotate left with carry
10111Rotate right with carry
111XXY = B

The MO (Misc. Operation) input determines if the Cin (Carry input) bit is to be used.

MOMeaning
0000 NOP
0001 INACK = 1 (Acknowledge interrupt)
0010 Memory write (prevent write to register file)
0011 Load PC (prevent write to register file)
0100 Load IR and increment PC (prevent write to register file)
0101 Increment PC
0110 Load PSR (prevent write to register file)
0111 Load SP (prevent write to register file)
1000 Decrement SP
1001 Decrement SP and memory write (prevent write to register file)
1010 Increment SP
1011 Select C as Cin for ALU and update PSR bits CNVZ as below
1100 Update PSR bits CNVZ
1101 Update PSR bits CZ
1110 Update PSR bits NZ
1111 Update MSTS bits CNVZ
	
module function_unit(Y, C, V, N, Z, A, B, Cin, Op, MO);
   output [15:0] Y;   // Bus D result.
   output 	 C;   // Carry output.
   output 	 N;   // Negative.
   output 	 V;   // Overflow.
   output 	 Z;   // Zero.
   input [15:0]  A;   // Bus A operand.
   input [15:0]  B;   // Bus B operand.
   input 	 Cin; // Carry input.
   input [4:0] 	 Op;  // Operation.
   input [3:0] 	 MO;  // Misc. Operation.   

   wire [15:0] 	 Ya;  // ALU result output.
   wire [15:0] 	 Ys;  // Shifter result output.
   wire 	 Ca;  // Carry out from the ALU.
   wire 	 Cs;  // Carry out from the shifter.
   wire 	 Va;  // oVerflow out from the ALU.
   wire 	 Vs;  // oVerflow out from the shifter.

   // MO = 4'b1011 then select C status bit as Cin for ALU.
   wire 	 CB;   // ALU carry/borrow input
   wire 	 MO2n; // not(MO[2])
   not(MO2n, MO[2]);   
   and(CB, MO[3], MO2n, MO[1], MO[0], Cin);

   alu aluf(Ya, Ca, Va, A, B, CB, {Op[2], Op[1], Op[0]});   
   shifter shifterf(Ys, Cs, Vs, A, {Op[3], Op[2], Op[1], Op[0]}, Cin, B);
   multiplexer_2_1 muxf(Y, Ya, Ys, Op[4]);
   multiplexer_2_1 #(1) muxc(C, Ca, Vs, Op[3]);
   multiplexer_2_1 #(1) muxv(V, Ca, Vs, Op[3]);
   
   assign N = Y[15];       // Most significant bit is the sign bit in 2's complement.   
   zero z(Z, Y);           // Zero status bit.
endmodule // function_unit

module zero(Z, A);
   output Z;        // Result. 
   input [15:0]  A; // Operand.

   wire [15:0] 	 Y; // Temp result.
   
   xnor(Y[0], A[0], 1'b0);
   xnor(Y[1], A[1], 1'b0);
   xnor(Y[2], A[2], 1'b0);
   xnor(Y[3], A[3], 1'b0);
   xnor(Y[4], A[4], 1'b0);
   xnor(Y[5], A[5], 1'b0);
   xnor(Y[6], A[6], 1'b0);
   xnor(Y[7], A[7], 1'b0);
   xnor(Y[8], A[8], 1'b0);
   xnor(Y[9], A[9], 1'b0);
   xnor(Y[10], A[10], 1'b0);
   xnor(Y[11], A[11], 1'b0);
   xnor(Y[12], A[12], 1'b0);
   xnor(Y[13], A[13], 1'b0);
   xnor(Y[14], A[14], 1'b0);
   xnor(Y[15], A[15], 1'b0);
   and(Z, Y[0], Y[1], Y[2], Y[3], Y[4],
       Y[5], Y[6], Y[7], Y[8],
       Y[9], Y[10], Y[11], Y[12],
       Y[13], Y[14], Y[15]);
endmodule // zero
	
      

ALU

This unit is similar to the one described in the ALU notes. The table shows all of the operations.

SOperation
000Addition
001Subtraction
010Increment
011Decrement
100Bitwise AND
101Bitwise OR
110Bitwise XOR
111Bitwise NOT
	
module alu(Y, C, V, A, B, CB, Op);
   output [15:0] Y;  // Bus D result.
   output 	 C;  // Carry.
   output 	 V;  // oVerflow.
   input [15:0]  A;  // Bus A operand.
   input [15:0]  B;  // Bus B operand.
   input 	 CB; // Carry/borrow.
   input [2:0] 	 Op; // Operation.

   wire [15:0] 	 AS, Inc, Dec, And, Or, Xor, Not;
   wire 	 s; 
   wire 	 Varith, Vas, Vinc, Vdec;
   wire 	 Carith, Cas, Cinc, Cdec;
   
   // The operations
   carry_select_adder_subtractor addsub(AS, Cas, Vas, A, B, CB, Op[0]);         // Op == 3'b000, 3'b001
   carry_select_adder_subtractor inc(Inc, Cinc, Vinc, A, 16'h0001, 1'b0, 1'b0); // Op == 3'b010
   carry_select_adder_subtractor dec(Dec, Cdec, Vdec, A, 16'h0001, 1'b0, 1'b1); // Op == 3'b011
   andop aluand(And, A, B);                                                     // Op == 3'b100
   orop aluor(Or, A, B);                                                        // Op == 3'b101
   xorop aluxor(Xor, A, B);                                                     // Op == 3'b110
   notop alunot(Not, A);                                                        // Op == 3'b111
   multiplexer_8_1 muxy(Y, AS, AS, Inc, Dec, And, Or, Xor, Not, Op);            // Select the result.
   multiplexer_4_1 #(1)muxc(C, Cas, Cas, Cinc, Cdec, Op[1], Op[0]);             // Select the carry.
   multiplexer_4_1 #(1)muxv(V, Vas, Vas, Vinc, Vdec, Op[1], Op[0]);             // Select the carry.   
endmodule // alu

module andop(Y, A, B);
   output [15:0] Y;  // Result.
   input [15:0]  A;  // Operand.
   input [15:0]  B;  // Operand.

   and(Y[0], A[0], B[0]);
   and(Y[1], A[1], B[1]);
   and(Y[2], A[2], B[2]);
   and(Y[3], A[3], B[3]);
   and(Y[4], A[4], B[4]);
   and(Y[5], A[5], B[5]);
   and(Y[6], A[6], B[6]);
   and(Y[7], A[7], B[7]);
   and(Y[8], A[8], B[8]);
   and(Y[9], A[9], B[9]);
   and(Y[10], A[10], B[10]);
   and(Y[11], A[11], B[11]);
   and(Y[12], A[12], B[12]);
   and(Y[13], A[13], B[13]);
   and(Y[14], A[14], B[14]);
   and(Y[15], A[15], B[15]);
endmodule // andop

module orop(Y, A, B);
   output [15:0] Y; // Result.
   input [15:0]  A; // Operand.
   input [15:0]  B; // Operand.

   or(Y[0], A[0], B[0]);
   or(Y[1], A[1], B[1]);
   or(Y[2], A[2], B[2]);
   or(Y[3], A[3], B[3]);
   or(Y[4], A[4], B[4]);
   or(Y[5], A[5], B[5]);
   or(Y[6], A[6], B[6]);
   or(Y[7], A[7], B[7]);
   or(Y[8], A[8], B[8]);
   or(Y[9], A[9], B[9]);
   or(Y[10], A[10], B[10]);
   or(Y[11], A[11], B[11]);
   or(Y[12], A[12], B[12]);
   or(Y[13], A[13], B[13]);
   or(Y[14], A[14], B[14]);
   or(Y[15], A[15], B[15]);
endmodule // orop

module xorop(Y, A, B);
   output [15:0] Y; // Result.
   input [15:0]  A; // Operand.
   input [15:0]  B; // Operand.

   xor(Y[0], A[0], B[0]);
   xor(Y[1], A[1], B[1]);
   xor(Y[2], A[2], B[2]);
   xor(Y[3], A[3], B[3]);
   xor(Y[4], A[4], B[4]);
   xor(Y[5], A[5], B[5]);
   xor(Y[6], A[6], B[6]);
   xor(Y[7], A[7], B[7]);
   xor(Y[8], A[8], B[8]);
   xor(Y[9], A[9], B[9]);
   xor(Y[10], A[10], B[10]);
   xor(Y[11], A[11], B[11]);
   xor(Y[12], A[12], B[12]);
   xor(Y[13], A[13], B[13]);
   xor(Y[14], A[14], B[14]);
   xor(Y[15], A[15], B[15]);
endmodule // xorop

module notop(Y, A);
   output [15:0] Y; // Result.
   input [15:0]  A; // Operand.

   not(Y[0], A[0]);
   not(Y[1], A[1]);
   not(Y[2], A[2]);
   not(Y[3], A[3]);
   not(Y[4], A[4]);
   not(Y[5], A[5]);
   not(Y[6], A[6]);
   not(Y[7], A[7]);
   not(Y[8], A[8]);
   not(Y[9], A[9]);
   not(Y[10], A[10]);
   not(Y[11], A[11]);
   not(Y[12], A[12]);
   not(Y[13], A[13]);
   not(Y[14], A[14]);
   not(Y[15], A[15]);
endmodule // notop

      
module carry_select_adder_subtractor(S, C, V, A, B, CB, Op);
   output [15:0] S;   // The 16-bit sum/difference.
   output 	 C;   // The 1-bit carry/borrow status.
   output 	 V;   // The 1-bit overflow status.
   input 	 CB;  // The carry/borrow input.
   input [15:0]  A;   // The 16-bit augend/minuend.
   input [15:0]  B;   // The 16-bit addend/subtrahend.
   input 	 Op;  // The operation: 0 => Add, 1=>Subtract.
   
   wire 	 C15; // The carry out bit of adder/subtractor, used to generate final carry/borrrow.   
   wire [15:0] 	 Bx;
   wire 	 CBx;
   
   // Looking at the truth table for not we see that  
   // B xor 0 = B, and
   // B xor 1 = not(B).
   // So, if Op==1 means we are subtracting, then
   // adding A and B xor Op alog with setting the first
   // carry bit to Op, will give us a result of
   // A+B when Op==0, and A+not(B)+1 when Op==1.
   // Note that not(B)+1 is the 2's complement of B, so
   // this gives us subtraction.     
   xor(Bx[0], B[0], Op);
   xor(Bx[1], B[1], Op);
   xor(Bx[2], B[2], Op);
   xor(Bx[3], B[3], Op);
   xor(Bx[4], B[4], Op);
   xor(Bx[5], B[5], Op);
   xor(Bx[6], B[6], Op);
   xor(Bx[7], B[7], Op);
   xor(Bx[8], B[8], Op);
   xor(Bx[9], B[9], Op);
   xor(Bx[10], B[10], Op);
   xor(Bx[11], B[11], Op);
   xor(Bx[12], B[12], Op);
   xor(Bx[13], B[13], Op);
   xor(Bx[14], B[14], Op);
   xor(Bx[15], B[15], Op);
   xor(C, C15, Op);            // Carry = C15 for addition, Carry = not(C15) for subtraction.
   xor(CBx, CB, Op); 
   carry_select_adder csa(S, C15, V, A, Bx, CBx);   
endmodule // carry_select_adder_subtractor

module carry_select_adder(S, C, V, A, B, Cin);
   output [15:0] S;   // The 16-bit sum.
   output 	 C;   // The 1-bit carry.
   output 	 V;   // The 1-bit overflow status.
   input [15:0]  A;   // The 16-bit augend.
   input [15:0]  B;   // The 16-bit addend.
   input 	 Cin; // The initial carry in.

   wire [3:0] 	S1_0;   // Nibble 1 sum output with carry input 0.
   wire [3:0] 	S1_1;   // Nibble 1 sum output with carry input 1.
   wire [3:0] 	S2_0;   // Nibble 2 sum output with carry input 0.
   wire [3:0] 	S2_1;   // Nibble 2 sum output with carry input 1.
   wire [3:0] 	S3_0;   // Nibble 3 sum output with carry input 0.
   wire [3:0] 	S3_1;   // Nibble 3 sum output with carry input 1.
   wire 	C1_0;   // Nibble 1 carry output with carry input 0.
   wire 	C1_1;   // Nibble 1 carry output with carry input 1.
   wire 	C2_0;   // Nibble 2 carry output with carry input 0.
   wire 	C2_1;   // Nibble 2 carry output with carry input 1.
   wire 	C3_0;   // Nibble 3 carry output with carry input 0.
   wire 	C3_1;   // Nibble 3 carry output with carry input 1.
   wire 	C0;     // Nibble 0 carry output used to select multiplexer output.
   wire 	C1;     // Nibble 1 carry output used to select multiplexer output.
   wire 	C2;     // Nibble 2 carry output used to select multiplexer output.
   wire         V0;     // Nibble 0 overflow output.
   wire 	V1_0;   // Nibble 1 overflow output with carry input 0.
   wire 	V1_1;   // Nibble 1 overflow output with carry input 1.
   wire 	V2_0;   // Nibble 2 overflow output with carry input 0.
   wire 	V2_1;   // Nibble 2 overflow output with carry input 1.
   wire 	V3_0;   // Nibble 3 overflow output with carry input 0.
   wire 	V3_1;   // Nibble 3 overflow output with carry input 1.
   
   ripple_carry_adder rc_nibble_0(S[3:0], C0, V0, A[3:0], B[3:0], Cin);          // Calculate S nibble 0.
   ripple_carry_adder rc_nibble_1_carry_0(S1_0, C1_0, V1_0, A[7:4], B[7:4], 1'b0);      // Calculate S nibble 1 with carry input 0.
   ripple_carry_adder rc_nibble_1_carry_1(S1_1, C1_1, V1_1, A[7:4], B[7:4], 1'b1);      // Calculate S nibble 1 with carry input 1.
   ripple_carry_adder rc_nibble_2_carry_0(S2_0, C2_0, V2_0, A[11:8], B[11:8], 1'b0);    // Calculate S nibble 2 with carry input 0.
   ripple_carry_adder rc_nibble_2_carry_1(S2_1, C2_1, V2_1, A[11:8], B[11:8], 1'b1);    // Calculate S nibble 2 with carry input 1.
   ripple_carry_adder rc_nibble_3_carry_0(S3_0, C3_0, V3_0, A[15:12], B[15:12], 1'b0);  // Calculate S nibble 3 with carry input 0.
   ripple_carry_adder rc_nibble_3_carry_1(S3_1, C3_1, V3_1, A[15:12], B[15:12], 1'b1);  // Calculate S nibble 3 with carry input 1.

   multiplexer_2_1 #(1) muxc1(C1, C1_0, C1_1, C0); // C0 selects the carry output for nibble 1.
   multiplexer_2_1 #(1) muxc2(C2, C2_0, C2_1, C1); // C1 selects the carry output for nibble 2.
   multiplexer_2_1 #(1) muxc(C, C3_0, C3_1, C2);   // C2 selects the carry output for nibble 3 which is the global carry output.
   multiplexer_2_1 #(1) muxv(V, V3_0, V3_1, C2);   // C2 selects the overflow output for nibble 3 which is the global overflow output.
   
   multiplexer_2_1 #(4) muxs1(S[7:4], S1_0, S1_1, C0);    // C0 selects the result for nibble 1.
   multiplexer_2_1 #(4) muxs2(S[11:8], S2_0, S2_1, C1);   // C1 selects the result for nibble 2.
   multiplexer_2_1 #(4) muxs3(S[15:12], S3_0, S3_1, C2);  // C2 selects the result for nibble 3.
endmodule // carry_select_adder

module ripple_carry_adder(S, C, V, A, B, Cin);
   output [3:0] S;   // The 4-bit sum.
   output 	C;   // The 1-bit carry.
   output       V;   // The 1-bit overflow status.   
   input [3:0] 	A;   // The 4-bit augend.
   input [3:0] 	B;   // The 4-bit addend.
   input 	Cin; // The carry input.
 	
   wire 	C0; // The carry out bit of fa0, the carry in bit of fa1.
   wire 	C1; // The carry out bit of fa1, the carry in bit of fa2.
   wire 	C2; // The carry out bit of fa2, the carry in bit of fa3.
	
   full_adder fa0(S[0], C0, A[0], B[0], Cin);    // Least significant bit.
   full_adder fa1(S[1], C1, A[1], B[1], C0);
   full_adder fa2(S[2], C2, A[2], B[2], C1);
   full_adder fa3(S[3], C, A[3], B[3], C2);    // Most significant bit.
   xor(V, C, C2);  // Overflow   
endmodule // ripple_carry_adder

module full_adder(S, Cout, A, B, Cin);
   output S;
   output Cout;
   input  A;
   input  B;
   input  Cin;
   
   wire   w1;
   wire   w2;
   wire   w3;
   wire   w4;
   
   xor(w1, A, B);
   xor(S, Cin, w1);
   and(w2, A, B);   
   and(w3, A, Cin);
   and(w4, B, Cin);   
   or(Cout, w2, w3, w4);
endmodule // full_adder
	
      

Shifter

The shifter is a basic design which shifts/rotates only one place. The functions are given in the following table:

SFunction
0000Y = A
1000logical shift left
0100logical shift right
1001arithmetic shift left
0101arithmetic shift right
1010rotate left
0110rotate right
1011rotate left with carry
0111rotate right with carry
11XXY = B
	
module shifter(Y, Cout, V, A, S, Cin, B);   
   output [15:0] Y;     // The bus D result.
   output 	 Cout;  // The carry result.
   output 	 V;     // The oVerflow result.
   input [15:0]  A;     // The value to be shifted from bus A.
   input [3:0] 	 S;     // The shift function.
   input 	 Cin;   // The carry input.
   input [15:0]  B;     // The input value from bus B. (passed through in a register to register move).
   
   wire 	 L; // The bit to shift in to the LSB when shifting left.
   wire 	 R; // The bit to shift in to the MSB when shifting right.
   
   multiplexer_4_1 #(1) muxL(L, 1'b0, 1'b0, A[15], Cin, S[1], S[0]);
   multiplexer_4_1 #(1) muxR(R, 1'b0, A[15], A[0], Cin, S[1], S[0]);
   multiplexer_2_1 #(1) muxC(Cout, A[0], A[15], S[3]);   // Chose the Cout bit depending on direction.
   shifter_16 basic_shifter(Y, A, S[3:2], L, R, B);          
   xor(V, Y[15], A[15]);                                 // oVerflow if the sign bits are different.
endmodule

module shifter_16(Y, A, S, L, R, B);
   output [15:0] Y;  // The shifted result.
   input [15:0]  A;  // The value to be shifted.
   input [1:0] 	 S;  // The direction of the shift.
   input 	 L;  // The bit to shift in to the LSB when shifting left.
   input 	 R;  // The bit to shift in to the MSB when shifting right.
   input [15:0]  B;  // The input value from bus B. (passed through in a register to register move).
   
   multiplexer_4_1 #(1) mux0(Y[0], A[0], A[1], L, B[0], S[1], S[0]);
   multiplexer_4_1 #(1) mux1(Y[1], A[1], A[2], A[0], B[1], S[1], S[0]);
   multiplexer_4_1 #(1) mux2(Y[2], A[2], A[3], A[1], B[2], S[1], S[0]);
   multiplexer_4_1 #(1) mux3(Y[3], A[3], A[4], A[2], B[3], S[1], S[0]);
   multiplexer_4_1 #(1) mux4(Y[4], A[4], A[5], A[3], B[4], S[1], S[0]);
   multiplexer_4_1 #(1) mux5(Y[5], A[5], A[6], A[4], B[5], S[1], S[0]);
   multiplexer_4_1 #(1) mux6(Y[6], A[6], A[7], A[5], B[6], S[1], S[0]);
   multiplexer_4_1 #(1) mux7(Y[7], A[7], A[8], A[6], B[7], S[1], S[0]);
   multiplexer_4_1 #(1) mux8(Y[8], A[8], A[9], A[7], B[8], S[1], S[0]);
   multiplexer_4_1 #(1) mux9(Y[9], A[9], A[10], A[8], B[9], S[1], S[0]);
   multiplexer_4_1 #(1) mux10(Y[10], A[10], A[11], A[9], B[10], S[1], S[0]);
   multiplexer_4_1 #(1) mux11(Y[11], A[11], A[12], A[10], B[11], S[1], S[0]);
   multiplexer_4_1 #(1) mux12(Y[12], A[12], A[13], A[11], B[12], S[1], S[0]);
   multiplexer_4_1 #(1) mux13(Y[13], A[13], A[14], A[12], B[13], S[1], S[0]);
   multiplexer_4_1 #(1) mux14(Y[14], A[14], A[15], A[13], B[14], S[1], S[0]);
   multiplexer_4_1 #(1) mux15(Y[15], A[15], R, A[14], B[15], S[1], S[0]);
endmodule // shifter_16
	
      

Control Unit

The control unit is the most complicated part of the CPU. This particular control unit is microprogrammed and there is some decoding performed in this module. The microinstructions have the following format:

Microinstrucion
MC3029282726252423222120191817161514131211109876543210
00,01,10MCMMMRDSASB MAMBMDFSMO
11MCLSPSMSNAMO

The generation of the MWR (Memory WRite) and RL (Register Load) output signals depends upon the MO (Misc. Operation) field of the microinstruction.

MOMeaning
0000 NOP
0001 INACK = 1 (Acknowledge interrupt)
0010 Memory write (prevent write to register file)
0011 Load PC (prevent write to register file)
0100 Load IR and increment PC (prevent write to register file)
0101 Increment PC
0110 Load PSR (prevent write to register file)
0111 Load SP (prevent write to register file)
1000 Decrement SP
1001 Decrement SP and memory write (prevent write to register file)
1010 Increment SP
1011 Select C as Cin for ALU and update PSR bits CNVZ as below
1100 Update PSR bits CNVZ
1101 Update PSR bits CZ
1110 Update PSR bits NZ
1111 Update MSTS bits CNVZ

Instructions are also decoded in the control unit. The instructions have the following format:

Instruction
Type1514131211109876543210
Generic formatOpcodeModeSSRCDST
Zero operands00XXXX
One operand01XXXXModeSSHADST
Two operands10XXXXModeSSRCDST
Branch11XXXXModeSDST
	
module control_unit(SHA, MWR, FS, MO, DST, DSA, SRC, SB, MA, MB, MD, PC, SP, RL, DBUS, INTS, MSC, MSN, MSV, MSZ, C, N, V, Z, EI, RESETn, CLK);
   output [15:0] SHA;    // SHift Amount.
   output 	 MWR;    // Memory WRite.
   output [4:0]  FS;     // Function unit Selector.
   output [3:0]  MO;     // Misc. Operation.
   output [3:0]  DST;    // DST register address.
   output [4:0]  DSA;    // D and A register address.
   output [3:0]  SRC;    // SRC register address.
   output [4:0]  SB;     // B register address.
   output [1:0]  MA;     // Multipexer A selector.
   output [1:0]  MB;     // Multipexer B selector.
   output 	 MD;     // Multipexer D selector.
   output [15:0] PC;     // Program Counter.
   output [15:0] SP;     // Stack Pointer.
   output 	 RL;     // Register file Load.  
   input [15:0]  DBUS;   // Datapath D bus input. 
   input 	 INTS;   // INTerrupt Signal.
   input 	 MSC;    // MicroStatus Carry bit.
   input 	 MSN;    // MicroStatus Negative bit.
   input 	 MSV;    // MicroStatus oVerflow bit.
   input 	 MSZ;    // MicroStatus Zero bit.
   input 	 C;      // ISA Carry status bit.
   input 	 N;      // ISA Negative status bit.
   input 	 V;      // ISA oVerflow status bit.
   input 	 Z;      // ISA Zero status bit.
   input 	 EI;     // ISA Enable Interrupts status bit.
   input 	 RESETn; // System reset.
   input 	 CLK;    // System clock.
   
   wire [7:0] MROMA;  // Mapping ROM Address.
   wire [7:0] CROMA;  // Control ROM Address.
   
   wire [15:0] Instruction;
   wire [30:0] Microinstruction;

   // Control unit specific microinstruction fields.
   wire [1:0] MC; 
   wire [1:0] MM;
   wire [2:0] MR;
   wire       LS;
   wire       PS;
   wire [3:0] MS;
   wire [7:0] NA;

   // The microsequencer can disable loads for branching instructions.
   wire       MSRL;
   
   
   pc pc0(PC, DBUS, MO, RESETn, CLK);
   ir ir0(Instruction, DBUS, MO, RESETn, CLK);
   sp sp0(SP, DBUS, MO, RESETn, CLK);
   instruction_decoder id0(MROMA, MR, MM, Instruction);
   microsequencer m0(CROMA, MSRL, INTS, MSC, MSN, MSV, MSZ, C, N, V, Z, EI, NA, MS, PS, LS, MC, MROMA, RESETn, CLK);
   control_rom cr0(Microinstruction, CROMA);

    
   assign MC = Microinstruction[30:29];
   assign MM = Microinstruction[28:27];
   assign MR = Microinstruction[26:24];
   assign DSA = Microinstruction[23:19];
   assign SB = Microinstruction[18:14];
   assign MA = Microinstruction[13:12];
   assign MB = Microinstruction[11:10];
   assign MD = Microinstruction[9];
   assign FS = Microinstruction[8:4];
   assign MO = Microinstruction[3:0];
   assign LS = Microinstruction[28];
   assign PS = Microinstruction[27];
   assign MS = Microinstruction[26:23];
   assign NA = Microinstruction[11:4];

   assign SRC = {1'b0, Instruction[5:3]};  // Prepend a 0 bit.
   assign DST = {1'b0, Instruction[2:0]};  // Prepend a 0 bit.
   assign SHA = {1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0,Instruction[5:3]};  // Prepend a 12 0-bits.
   
   /*
    * Generate the MWR and RL signals.
    */
   assign MWR = (MO == 4'b0010) || (MO == 4'b1001);   
   assign RL = MSRL && (MO != 4'b0010) && (MO != 4'b0010) && (MO != 4'b0011) && (MO != 4'b0100) && (MO != 4'b0110) && (MO != 4'b0111) && (MO != 4'b1001);
endmodule // control_unit
	
      

Program Counter

The program counter (PC) holds the address of the next instruction to be fetched from memory. The MO (Misc. Operation) input determines if the PC is to be loaded or incremented.

MOMeaning
0000 NOP
0001 INACK = 1 (Acknowledge interrupt)
0010 Memory write (prevent write to register file)
0011 Load PC (prevent write to register file)
0100 Load IR and increment PC (prevent write to register file)
0101 Increment PC
0110 Load PSR (prevent write to register file)
0111 Load SP (prevent write to register file)
1000 Decrement SP
1001 Decrement SP and memory write (prevent write to register file)
1010 Increment SP
1011 Select C as Cin for ALU and update PSR bits CNVZ as below
1100 Update PSR bits CNVZ
1101 Update PSR bits CZ
1110 Update PSR bits NZ
1111 Update MSTS bits CNVZ
	
module pc(Q, Din, MO, RESETn, CLK);
   output [15:0] Q;      // Contents of the PC
   input [15:0]	 Din;    // New contents upon loading.
   input [3:0] 	 MO;     // Misc. Operation.
   input 	 RESETn; // System reset.   
   input 	 CLK;    // System clock.

   wire [15:0] 	 D0, D1;   
   wire [15:0] 	 Dinc;   // Incremented PC.
   wire 	 Cinc;   // Carry for increment operation.
   wire 	 Vinc;   // oVerflow for increment operation.
   
   carry_select_adder_subtractor inc(Dinc, Cinc, Vinc, Q, 16'h0001, 1'b0, 1'b0);
   multiplexer_16_1 mux0(D0, Q, 16'h0000, Q, Din, Dinc, Dinc, Q, Q, Q, Q, Q, Q, Q, Q, Q, Q, MO); // 16'h0000 is the interrupt vector
   multiplexer_2_1 mux1(D1, 16'h0000, D0, RESETn);  // Handle resets. 
   register_parallel_load r1(Q, D1, 1'b1, CLK);
endmodule // pc
	
      

Instruction Register

The Instruction Register (IR) holds the instruction that is currently being executed. The MO (Misc. Operation) input determines when the IR is loaded.

MOMeaning
0000 NOP
0001 INACK = 1 (Acknowledge interrupt)
0010 Memory write (prevent write to register file)
0011 Load PC (prevent write to register file)
0100 Load IR and increment PC (prevent write to register file)
0101 Increment PC
0110 Load PSR (prevent write to register file)
0111 Load SP (prevent write to register file)
1000 Decrement SP
1001 Decrement SP and memory write (prevent write to register file)
1010 Increment SP
1011 Select C as Cin for ALU and update PSR bits CNVZ as below
1100 Update PSR bits CNVZ
1101 Update PSR bits CZ
1110 Update PSR bits NZ
1111 Update MSTS bits CNVZ
	
module ir(Q, Din, MO, RESETn, CLK);
   output [15:0] Q;      // Contents of the IR
   input [15:0]	 Din;    // New contents upon loading.
   input [3:0] 	 MO;     // Misc. Operation.
   input 	 RESETn; // System reset.   
   input 	 CLK;    // System clock.

   wire [15:0] 	 D0, D1;
   wire 	 Load;
   wire 	 M03n, MO1n, MO0n;

   not(MO3n, MO[3]);
   not(MO1n, MO[1]);
   not(MO0n, MO[0]);
   and(Load, MO3n, MO[2], MO1n, MO0n);
   
   multiplexer_2_1 mux1(D0, Q, Din, Load);   
   multiplexer_2_1 mux2(D1, 16'h0000, D0, RESETn);  // Handle resets. 
   register_parallel_load r1(Q, D1, 1'b1, CLK);
endmodule // ir
	
      

Stack Pointer

The Stack Pointer (SP) is a counter which holds the address of the top of the processor stack. The MO (Misc. Operation) input determines the stack operation.

MOMeaning
0000 NOP
0001 INACK = 1 (Acknowledge interrupt)
0010 Memory write (prevent write to register file)
0011 Load PC (prevent write to register file)
0100 Load IR and increment PC (prevent write to register file)
0101 Increment PC
0110 Load PSR (prevent write to register file)
0111 Load SP (prevent write to register file)
1000 Decrement SP
1001 Decrement SP and memory write (prevent write to register file)
1010 Increment SP
1011 Select C as Cin for ALU and update PSR bits CNVZ as below
1100 Update PSR bits CNVZ
1101 Update PSR bits CZ
1110 Update PSR bits NZ
1111 Update MSTS bits CNVZ
	
module sp(Q, Din, MO, RESETn, CLK);
   output [15:0] Q;      // Contents of the SP
   input [15:0]	 Din;    // New contents upon loading from bus D.
   input [3:0] 	 MO;     // Misc. Operation.
   input 	 RESETn; // System reset.   
   input 	 CLK;    // System clock.

   wire [15:0] 	 D0, D1;   
   wire [15:0] 	 Dinc;   // Incremented SP.
   wire 	 Cinc;   // Carry for increment operation (ignored).
   wire 	 Vinc;   // oVerflow for increment operation (ignored).
   wire [15:0] 	 Ddec;   // Decremented SP.
   wire 	 Cdec;   // Carry for decrement operation (ignored).
   wire 	 Vdec;   // oVerflow for decrement operation (ignored).
   
   carry_select_adder_subtractor inc(Dinc, Cinc, Vinc, Q, 16'h0001, 1'b0, 1'b0);
   carry_select_adder_subtractor dec(Ddec, Cdec, Vdec, Q, 16'h0001, 1'b0, 1'b1);
   multiplexer_16_1 mux0(D0, Q, Q, Q, Q, Q, Q, Q, Din, Ddec, Ddec, Dinc, Q, Q, Q, Q, Q, MO);
   multiplexer_2_1 mux1(D1, 16'hffff, D0, RESETn);  // Handle resets.
   register_parallel_load r1(Q, D1, 1'b1, CLK);
endmodule // sp
	
      

Instruction Decoder

The generic form of the instruction along with the four different types of instruction is given in the table below.

Instruction
Type1514131211109876543210
Generic formatOpcodeModeSSRCDST
Zero operands00XXXX
One operand01XXXXModeSSHADST
Two operands10XXXXModeSSRCDST
Branch11XXXXModeSDST

The most significant two bits of the opcode give us the number of operands/type.

OPCODE[5:4]Type
000 operand
011 operand
102 operand
11branch

The opcodes are as follows:

OPCODE[5:0]Mnemonic
000000NOP
000001PSHR
000010POPR
000011MVS
000100RET
000101RTI
......
010000PUSH
010001POP
010010INC
010011DEC
010100NEG
010101NOT
010110SHR
010111SHL
011000ASR
011001ASL
011010ROR
011011ROL
011100RORC
011101ROLC
......
100000MOV
100001XCHG
100010ADD
100011ADDC
100100SUB
100101SUBB
100110MUL
100111DIV
101000CMP
101001AND
101010OR
101011XOR
......
110000JMP
110001CALL
110010BC
110011BNC
110100BN
110101BNN
110110BV
110111BNV
111000BZ
111001BNZ
......

The MODE field is decoded as follows:

MODEAddressing mode
000Register
001Register indirect
010Immediate
011Direct
100Indexed
101Indexed Indirect
110Relative
111Relative indirect

The S field determines which of the two fields, SRC or DST, are subject to the addressing mode determined by MODE.

SMeaning
0SRC is subject to addressing mode.
1DST is subject to addressing mode.
	 
module instruction_decoder(A, MR, MM, Instruction);
   output [7:0] A;           // ROM output.
   input [2:0] 	MR;          // ROM address bits.
   input [1:0] 	MM;          // The muxM selector.
   input [15:0] Instruction; // The instruction to be decoded.

   wire [3:0] 	M0; // The muxM output.
   
   multiplexer_4_1 #(4) muxM(M0, {Instruction[15:14], 1'b0, 1'b0}, Instruction[13:10], Instruction[9:6], Instruction[9:6], MM[1], MM[0]);
   mapping_rom rom0(A, {MM, MR, M0});   
endmodule // instruction_decoder
	
      

Microsequencer

The microsequencer is driven by the microinstruction fields, the CAR register, and the MSTS register. The MS field of the microinstruction is used when branching.

MSMeaning
0000 Unconditional branch.
0001 Branch if C status bit set.
0010 Branch if N status bit set.
0011 Branch if V status bit set.
0100 Branch if Z status bit set.
0101 Branch if EI status bit set.
0110 Branch if C microstatus bit set.
0111 Branch if N microstatus bit set.
1000 Branch if V microstatus bit set.
1001 Branch if Z microstatus bit set.
1010 Branch if interrupt.
1011 Unused.
1100 Unused.
1101 Unused.
1110 Unused.
1111 Unused.

The PS field of the microinstruction determines how we check for a branch condition. If PS==0 then the status bit is passed unchanged, otherwise, when PS==1, the status bit is complemented. The wire ST has the following meaning where NA is a microinstruction field meaning Next Address.

ST Meaning
0 No branch so continue at A+1.
1 Branch to NA.

The MC microinstruction field is interpreted as follows:

MC Meaning
00 Increment CAR.
01 Return from subroutine.
10 Map instruction into CAR.
11 Branch or call.
	
module microsequencer(A, RL, INTS, MSC, MSN, MSV, MSZ, C, N, V, Z, EI, NA, MS, PS, LS, MC, MROMA, RESETn, CLK);
   output [7:0] A;      // Address of next microinstruction.
   output 	RL;     // Register Load signal for the register file.
   input 	INTS;   // Interrupt signal.
   input 	MSC;    // Microstatus Carry bit.
   input 	MSN;    // Microstatus Negative bit.
   input 	MSV;    // Microstatus oVerflow bit.
   input 	MSZ;    // Microstatus Zero bit.
   input 	C;      // ISA Carry bit.
   input 	N;      // ISA Negative bit.
   input 	V;      // ISA oVerflow bit.
   input 	Z;      // ISA Zero bit.
   input 	EI;     // ISA Enable Interrupts bit.
   input [7:0] 	NA;     // Next address.
   input [3:0] 	MS;     // MuxS selector.
   input 	PS;     // Pass Status bit. 0 => status bit unchanged, 1 => status bit complemented.   
   input 	LS;     // Load SBR.
   input [1:0] 	MC;     // MuxC selector.
   input [7:0] 	MROMA;  // Mapping ROM Address.   
   input 	RESETn; // System clock.
   input 	CLK;    // System reset.

   wire [7:0] 	C0;      // Output from muxC.
   wire [7:0]	R0;      // Output from muxR.
   wire 	SO;      // Output from muxS.
   wire 	ST;      // Processed status bit. This is the muxR selector.
   wire [7:0] 	Ainc;    // The incremented address output.
   wire [7:0] 	SBR;     // Output of the SRB register.
   wire 	SBRLoad; // The load SBR signal.

   multiplexer_16_1 #(1) muxS(S0, 1'b1, C, N, V, Z, EI, MSC, MSN, MSV, MSZ, INTS, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, MS);

   /*    
    * Complement the status bit if necessary. ST == 1 => status condition met.
    */
   xor(ST, S0, PS); 

   /*
    * Increment the output address (A).
    */
   incrementer_8 inc(Ainc, A); 

   multiplexer_2_1 #(8) muxR(R0, Ainc, NA, ST);
   
   multiplexer_4_1 #(8) muxC(C0, Ainc, SBR, MROMA, R0, MC[1], MC[0]);

   /*
    * Save the incremented output address (A) in the SBR 
    * if we are calling a subroutine.
    * We load the SBR when MC[1] & MC[0] & LS & ST 
    */
   sbr sbr0(SBR, Ainc, SBRLoad, CLK); 
   and(SBRLoad, MC[1], MC[0], LS, ST);
   
   /*
    * The CAR holds the output address.
    */ 
   car car0(A, C0, RESETn, CLK);

   /*
    * We output the RL (Register Load) signal to the register 
    * file when not(MC[1] & MC[0]).
    */   
   nand(RL, MC[1], MC[0]);
endmodule // microsequencer
	
      

Control Address Register

The Control Address Register (CAR) hold the address of the next microinstrcution.

	
module car(Q, D, RESETn, CLK);
   output [7:0] Q;      // Current contents of the CAR.
   input [7:0] 	D;      // New contents to load.
   input 	RESETn; // System rest.   
   input 	CLK;    // System clock.

   wire [7:0]	D1;
   
   multiplexer_2_1 #(8) mux1(D1, 8'h00, D, RESETn); // Handle resets.
   register_parallel_load_8 r1(Q, D1, 1'b1, CLK);
endmodule // car
	
      

Microcode Subroutine Return Address

The microcode SuBroutine Return address register (SBR) holds the address that the microcode can return to. This gives us the opportunity to write microsubroutines, however, there is only one such register so microsubroutines cannot be nested.

	
module sbr(Q, D, Load, CLK);
   output [7:0] Q;    // Contents of the SBR.
   input [7:0] 	D;    // New contents to load.
   input 	Load; // Load the new contents of the SBR.
   input 	CLK;  // System clock.
   
   register_parallel_load_8 r1(Q, D, Load, CLK);
endmodule // sbr
	
      

Mapping ROM

The mapping ROM is used to hold the addresses of microinstruction routines in the control ROM. Each mapping ROM address is a 9-bit value which comprises three fields:

876543210
MMMRINSTR

The fields MM and MR come from the microinstruction. The field INSTR is extracted from the instruction depending on the value of MM as seen in the table below.

MMINSTR
00OPCODE[5:3]
01OPCODE[3:0]
10MODE|S
11MODE|S

This scheme gives us a sort of jump table. When MM==00 we can jump to a different routine for each type of instruction (zero operand, one operand, ...), when MM==01 we can jump to a different routine for each instruction (push, pop, ret, ....), and when MM==1X we can jump to a different routine for each addressing mode. The MR field gives us eight different addresses for each of these different routines.

	
module mapping_rom(D, A);
   input [8:0] A;
   output [7:0] D;

   assign D = (A == 9'b00_000_0000)   ? 8'h02   // 0EX
	      : (A == 9'b00_000_0001) ? 8'h02   // 0EX
	      : (A == 9'b00_000_0010) ? 8'h02   // 0EX   
	      : (A == 9'b00_000_0011) ? 8'h02   // 0EX
	      : (A == 9'b00_000_0100) ? 8'h30   // 1OF
	      : (A == 9'b00_000_0101) ? 8'h30   // 1OF
	      : (A == 9'b00_000_0110) ? 8'hab   // 2OF
	      : (A == 9'b00_000_0111) ? 8'hab   // 2OF
	      : (A == 9'b00_000_1000) ? 8'hab   // 2OF
	      : (A == 9'b00_000_1001) ? 8'hab   // 2OF
	      : (A == 9'b00_000_1010) ? 8'hab   // 2OF
	      : (A == 9'b00_000_1011) ? 8'h80   // BAF
	      : (A == 9'b00_000_1100) ? 8'h80   // BAF

	      : (A == 9'b00_001_0000) ? 8'h45   // 1EX
	      : (A == 9'b00_001_0001) ? 8'h45   // 1EX
	      : (A == 9'b00_001_0010) ? 8'h45   // 1EX
	      : (A == 9'b00_001_0011) ? 8'h45   // 1EX
	      : (A == 9'b00_001_0100) ? 8'h45   // 1EX
	      : (A == 9'b00_001_0101) ? 8'h45   // 1EX
	      : (A == 9'b00_001_0110) ? 8'h45   // 1EX
	      : (A == 9'b00_001_0111) ? 8'h45   // 1EX
	      : (A == 9'b00_001_1000) ? 8'h45   // 1EX
	      : (A == 9'b00_001_1001) ? 8'h45   // 1EX
	      : (A == 9'b00_001_1010) ? 8'h45   // 1EX
	      : (A == 9'b00_001_1011) ? 8'h45   // 1EX
	      : (A == 9'b00_001_1100) ? 8'h45   // 1EX    
	      : (A == 9'b00_001_1101) ? 8'h45   // 1EX    
	      : (A == 9'b00_001_1110) ? 8'h45   // 1EX
	      : (A == 9'b00_001_1111) ? 8'h45   // 1EX    

	      : (A == 9'b00_010_0000) ? 8'he4   // 2EX
	      : (A == 9'b00_010_0001) ? 8'he4   // 2EX
	      : (A == 9'b00_010_0010) ? 8'he4   // 2EX
	      : (A == 9'b00_010_0011) ? 8'he4   // 2EX
	      : (A == 9'b00_010_0100) ? 8'he4   // 2EX
	      : (A == 9'b00_010_0101) ? 8'he4   // 2EX
	      : (A == 9'b00_010_0110) ? 8'h45   // 1EX
	      : (A == 9'b00_010_0111) ? 8'he4   // 2EX
	      : (A == 9'b00_010_1000) ? 8'he4   // 2EX
	      : (A == 9'b00_010_1001) ? 8'he4   // 2EX
	      : (A == 9'b00_010_1010) ? 8'he4   // 2EX
	      : (A == 9'b00_010_1011) ? 8'he4   // 2EX
	      : (A == 9'b00_010_1100) ? 8'he4   // 2EX    
	      : (A == 9'b00_010_1101) ? 8'he4   // 2EX    
	      : (A == 9'b00_010_1110) ? 8'he4   // 2EX
	      : (A == 9'b00_010_1111) ? 8'he4   // 2EX    

	      : (A == 9'b00_011_0000) ? 8'h93   // BEX
	      : (A == 9'b00_011_0001) ? 8'h93   // BEX
      	      : (A == 9'b00_011_0010) ? 8'h93   // BEX
      	      : (A == 9'b00_011_0011) ? 8'h93   // BEX
      	      : (A == 9'b00_011_0100) ? 8'h93   // BEX
      	      : (A == 9'b00_011_0101) ? 8'h93   // BEX
      	      : (A == 9'b00_011_0110) ? 8'h93   // BEX
      	      : (A == 9'b00_011_0111) ? 8'h93   // BEX
      	      : (A == 9'b00_011_1000) ? 8'h93   // BEX
      	      : (A == 9'b00_011_1001) ? 8'h93   // BEX
      	      : (A == 9'b00_011_1010) ? 8'h93   // BEX
      	      : (A == 9'b00_011_1011) ? 8'h93   // BEX
      	      : (A == 9'b00_011_1100) ? 8'h93   // BEX
      	      : (A == 9'b00_011_1101) ? 8'h93   // BEX
      	      : (A == 9'b00_011_1110) ? 8'h93   // BEX
      	      : (A == 9'b00_011_1111) ? 8'h93   // BEX

	      : (A == 9'b01_000_0000) ? 8'h03   // NOP0
	      : (A == 9'b01_000_0001) ? 8'h04   // PSHR0
	      : (A == 9'b01_000_0010) ? 8'h0c   // POPR0	 	
	      : (A == 9'b01_000_0011) ? 8'h13   // MVS0
	      : (A == 9'b01_000_0100) ? 8'h1d   // RET0
	      : (A == 9'b01_000_0101) ? 8'h1f   // RTI0

	      : (A == 9'b01_001_0000) ? 8'h46   // PUSH0
	      : (A == 9'b01_001_0001) ? 8'h49   // POP
	      : (A == 9'b01_001_0010) ? 8'h4a   // INC
	      : (A == 9'b01_001_0011) ? 8'h4b   // DEC
	      : (A == 9'b01_001_0100) ? 8'h4c   // NEG0
	      : (A == 9'b01_001_0101) ? 8'h4e   // NOT
	      : (A == 9'b01_001_0110) ? 8'hff   // INVALID
	      : (A == 9'b01_001_0111) ? 8'hff   // INVALID    
	      : (A == 9'b01_001_1000) ? 8'h4f   // SHR0
	      : (A == 9'b01_001_1001) ? 8'h55   // SHL0
	      : (A == 9'b01_001_1010) ? 8'h5b   // ASR0
	      : (A == 9'b01_001_1011) ? 8'h61   // ASL0
	      : (A == 9'b01_001_1100) ? 8'h67   // ROR0
	      : (A == 9'b01_001_1101) ? 8'h6d   // ROL0
	      : (A == 9'b01_001_1110) ? 8'h73   // RORC0
	      : (A == 9'b01_001_1111) ? 8'h79   // ROLC0

	      : (A == 9'b01_010_0000) ? 8'he5   // MOV
	      : (A == 9'b01_010_0001) ? 8'he6   // XCHG0
	      : (A == 9'b01_010_0010) ? 8'heb   // ADD
	      : (A == 9'b01_010_0011) ? 8'hec   // ADDC
	      : (A == 9'b01_010_0100) ? 8'hed   // SUB
	      : (A == 9'b01_010_0101) ? 8'hee   // SUBB
	      : (A == 9'b01_010_0110) ? 8'hff   // MUL
	      : (A == 9'b01_010_0111) ? 8'hff   // DIV
	      : (A == 9'b01_010_1000) ? 8'hef   // CMP
	      : (A == 9'b01_010_1001) ? 8'hf0   // AND
	      : (A == 9'b01_010_1010) ? 8'hf1   // OR
	      : (A == 9'b01_010_1011) ? 8'hf2   // XOR
	      : (A == 9'b01_010_1100) ? 8'hff   // INVALID    
	      : (A == 9'b01_010_1101) ? 8'hff   // INVALID    
	      : (A == 9'b01_010_1110) ? 8'hff   // INVALID
	      : (A == 9'b01_010_1111) ? 8'hff   // INVALID    

	      : (A == 9'b01_011_0000) ? 8'h94   // JMP
	      : (A == 9'b01_011_0001) ? 8'h95   // CALL0
	      : (A == 9'b01_011_0010) ? 8'h99   // BC0
	      : (A == 9'b01_011_0011) ? 8'h9b   // BNC0
	      : (A == 9'b01_011_0100) ? 8'h9d   // BN0
	      : (A == 9'b01_011_0101) ? 8'h9f   // BNN0
	      : (A == 9'b01_011_0110) ? 8'ha2   // BV0
	      : (A == 9'b01_011_0111) ? 8'ha4   // BNV0
	      : (A == 9'b01_011_1000) ? 8'ha6   // BZ0
	      : (A == 9'b01_011_1001) ? 8'ha8   // BNZ0
	      : (A == 9'b01_011_1010) ? 8'hff   // INVALID
	      : (A == 9'b01_011_1011) ? 8'hff   // INVALID
	      : (A == 9'b01_011_1100) ? 8'hff   // INVALID
	      : (A == 9'b01_011_1101) ? 8'hff   // INVALID
	      : (A == 9'b01_011_1110) ? 8'hff   // INVALID
	      : (A == 9'b01_011_1111) ? 8'hff   // INVALID    

	      : (A == 9'b01_100_0000) ? 8'hf5   // WB0
	      : (A == 9'b01_100_0001) ? 8'hf5   // WB0
	      : (A == 9'b01_100_0010) ? 8'hf5   // WB0
	      : (A == 9'b01_100_0011) ? 8'hf5   // WB0
	      : (A == 9'b01_100_0100) ? 8'hf5   // WB0
	      : (A == 9'b01_100_0101) ? 8'hf5   // WB0
	      : (A == 9'b01_100_0110) ? 8'hf5   // WB0
	      : (A == 9'b01_100_0111) ? 8'hf5   // WB0
	      : (A == 9'b01_100_1000) ? 8'hf5   // WB0
	      : (A == 9'b01_100_1001) ? 8'hf5   // WB0
	      : (A == 9'b01_100_1010) ? 8'hf5   // WB0
	      : (A == 9'b01_100_1011) ? 8'hf5   // WB0
	      : (A == 9'b01_100_1100) ? 8'hf5   // WB0
	      : (A == 9'b01_100_1101) ? 8'hf5   // WB0
	      : (A == 9'b01_100_1110) ? 8'hf5   // WB0
	      : (A == 9'b01_100_1111) ? 8'hf5   // WB0	      

	      : (A == 9'b01_101_0000) ? 8'hf8   // INT0
	      : (A == 9'b01_101_0001) ? 8'hf8   // INT0
	      : (A == 9'b01_101_0010) ? 8'hf8   // INT0
	      : (A == 9'b01_101_0011) ? 8'hf8   // INT0
	      : (A == 9'b01_101_0100) ? 8'hf8   // INT0
	      : (A == 9'b01_101_0101) ? 8'hf8   // INT0
	      : (A == 9'b01_101_0110) ? 8'hf8   // INT0
	      : (A == 9'b01_101_0111) ? 8'hf8   // INT0
	      : (A == 9'b01_101_1000) ? 8'hf8   // INT0
	      : (A == 9'b01_101_1001) ? 8'hf8   // INT0
	      : (A == 9'b01_101_1010) ? 8'hf8   // INT0
	      : (A == 9'b01_101_1011) ? 8'hf8   // INT0
	      : (A == 9'b01_101_1100) ? 8'hf8   // INT0
	      : (A == 9'b01_101_1101) ? 8'hf8   // INT0
	      : (A == 9'b01_101_1110) ? 8'hf8   // INT0
	      : (A == 9'b01_101_1111) ? 8'hf8   // INT0	      

	      : (A == 9'b10_001_0000) ? 8'h31   // 1RG
	      : (A == 9'b10_001_0001) ? 8'h31   // 1RG
	      : (A == 9'b10_001_0010) ? 8'h32   // 1RGI0
	      : (A == 9'b10_001_0011) ? 8'h32   // 1RGI0
	      : (A == 9'b10_001_0100) ? 8'h34   // 1IM
	      : (A == 9'b10_001_0101) ? 8'h34   // 1IM
	      : (A == 9'b10_001_0110) ? 8'h35   // 1DR0
	      : (A == 9'b10_001_0111) ? 8'h35   // 1DR0
	      : (A == 9'b10_001_1000) ? 8'h37   // 1ID0
	      : (A == 9'b10_001_1001) ? 8'h37   // 1ID0
	      : (A == 9'b10_001_1010) ? 8'h3a   // 1IDI0
	      : (A == 9'b10_001_1011) ? 8'h3a   // 1IDI0
	      : (A == 9'b10_001_1100) ? 8'h3e   // 1RL0
	      : (A == 9'b10_001_1101) ? 8'h3e   // 1RL0
	      : (A == 9'b10_001_1110) ? 8'h41   // 1RLI0
	      : (A == 9'b10_001_1111) ? 8'h41   // 1RLI0

	      : (A == 9'b10_010_0000) ? 8'hac   // 2RG0
	      : (A == 9'b10_010_0001) ? 8'hae   // 2RGS0
	      : (A == 9'b10_010_0010) ? 8'hb0   // 2RGI00
	      : (A == 9'b10_010_0011) ? 8'hb3   // 2RGI0S0
	      : (A == 9'b10_010_0100) ? 8'hb6   // 2IM0
	      : (A == 9'b10_010_0101) ? 8'hb8   // 2IMS0
	      : (A == 9'b10_010_0110) ? 8'hba   // 2DR00
	      : (A == 9'b10_010_0111) ? 8'hbd   // 2DR0S0
	      : (A == 9'b10_010_1000) ? 8'hc0   // 2ID00
	      : (A == 9'b10_010_1001) ? 8'hc4   // 2ID0
	      : (A == 9'b10_010_1010) ? 8'hc8   // 2IDI00
	      : (A == 9'b10_010_1011) ? 8'hcd   // 2IDIS0
	      : (A == 9'b10_010_1100) ? 8'hd2   // 2RL0
	      : (A == 9'b10_010_1101) ? 8'hd6   // 2RLS0
	      : (A == 9'b10_010_1110) ? 8'hda   // 2RLI00
	      : (A == 9'b10_010_1111) ? 8'hdf   // 2RLIS0

	      : (A == 9'b10_011_0000) ? 8'hff   // INVALID
	      : (A == 9'b10_011_0001) ? 8'hff   // INVALID
	      : (A == 9'b10_011_0010) ? 8'h81   // BRGI0
	      : (A == 9'b10_011_0011) ? 8'h81   // BRGI0
	      : (A == 9'b10_011_0100) ? 8'h83   // BIM
	      : (A == 9'b10_011_0101) ? 8'h83   // BIM
	      : (A == 9'b10_011_0110) ? 8'h84   // BDR0
	      : (A == 9'b10_011_0111) ? 8'h84   // BDR0
	      : (A == 9'b10_011_1000) ? 8'h85   // BID0
	      : (A == 9'b10_011_1001) ? 8'h85   // BID0
	      : (A == 9'b10_011_1010) ? 8'h88   // BIDI0
	      : (A == 9'b10_011_1011) ? 8'h88   // BIDI0
	      : (A == 9'b10_011_1100) ? 8'h8c   // BRL0
	      : (A == 9'b10_011_1101) ? 8'h8c   // BRL0
	      : (A == 9'b10_011_1110) ? 8'h8f   // BRLI0
	      : (A == 9'b10_011_1111) ? 8'h8f   // BRLI0

	      : (A == 9'b10_100_0000) ? 8'he9   // XCH3
	      : (A == 9'b10_100_0001) ? 8'he9   // XCH3
	      : (A == 9'b10_100_0010) ? 8'hea   // XCH4
	      : (A == 9'b10_100_0011) ? 8'he9   // XCH3
	      : (A == 9'b10_100_0100) ? 8'hea   // XCH4
	      : (A == 9'b10_100_0101) ? 8'he9   // XCH3
	      : (A == 9'b10_100_0110) ? 8'hea   // XCH4
	      : (A == 9'b10_100_0111) ? 8'he9   // XCH3
	      : (A == 9'b10_100_1000) ? 8'hea   // XCH4
	      : (A == 9'b10_100_1001) ? 8'he9   // XCH3
	      : (A == 9'b10_100_1010) ? 8'hea   // XCH4
	      : (A == 9'b10_100_1011) ? 8'he9   // XCH3
	      : (A == 9'b10_100_1100) ? 8'hea   // XCH4
	      : (A == 9'b10_100_1101) ? 8'he9   // XCH3
	      : (A == 9'b10_100_1110) ? 8'hea   // XCH4
	      : (A == 9'b10_100_1111) ? 8'he9   // XCH3
	      
	      : (A == 9'b11_000_0000) ? 8'hf6   // WB1
	      : (A == 9'b11_000_0001) ? 8'hf6   // WB1
	      : (A == 9'b11_000_0010) ? 8'hf6   // WB1
	      : (A == 9'b11_000_0011) ? 8'hf7   // WB2
	      : (A == 9'b11_000_0100) ? 8'hf6   // WB1
	      : (A == 9'b11_000_0101) ? 8'hf7   // WB2	      
	      : (A == 9'b11_000_0110) ? 8'hf6   // WB1
	      : (A == 9'b11_000_0111) ? 8'hf7   // WB2	      
	      : (A == 9'b11_000_1000) ? 8'hf6   // WB1
	      : (A == 9'b11_000_1001) ? 8'hf7   // WB2
	      : (A == 9'b11_000_1010) ? 8'hf6   // WB1
	      : (A == 9'b11_000_1011) ? 8'hf7   // WB2
	      : (A == 9'b11_000_1100) ? 8'hf6   // WB1 	      
	      : (A == 9'b11_000_1101) ? 8'hf7   // WB2
	      : (A == 9'b11_000_1110) ? 8'hf6   // WB1
	      : (A == 9'b11_000_1111) ? 8'hf7   // WB2

	      : (A == 9'b11_001_0000) ? 8'hf8   // INT0
	      : (A == 9'b11_001_0001) ? 8'hf8   // INT0
	      : (A == 9'b11_001_0010) ? 8'hf8   // INT0
	      : (A == 9'b11_001_0011) ? 8'hf8   // INT0
	      : (A == 9'b11_001_0100) ? 8'hf8   // INT0
	      : (A == 9'b11_001_0101) ? 8'hf8   // INT0
	      : (A == 9'b11_001_0110) ? 8'hf8   // INT0
	      : (A == 9'b11_001_0111) ? 8'hf8   // INT0
	      : (A == 9'b11_001_1000) ? 8'hf8   // INT0
	      : (A == 9'b11_001_1001) ? 8'hf8   // INT0
	      : (A == 9'b11_001_1010) ? 8'hf8   // INT0
	      : (A == 9'b11_001_1011) ? 8'hf8   // INT0
	      : (A == 9'b11_001_1100) ? 8'hf8   // INT0
	      : (A == 9'b11_001_1101) ? 8'hf8   // INT0
	      : (A == 9'b11_001_1110) ? 8'hf8   // INT0
	      : (A == 9'b11_001_1111) ? 8'hf8   // INT0	      

	      : (A == 9'b11_010_0000) ? 8'h00   // IF0
	      : (A == 9'b11_010_0001) ? 8'h00   // IF0
	      : (A == 9'b11_010_0010) ? 8'h00   // IF0
	      : (A == 9'b11_010_0011) ? 8'h00   // IF0
	      : (A == 9'b11_010_0100) ? 8'h00   // IF0
	      : (A == 9'b11_010_0101) ? 8'h00   // IF0
	      : (A == 9'b11_010_0110) ? 8'h00   // IF0
	      : (A == 9'b11_010_0111) ? 8'h00   // IF0
	      : (A == 9'b11_010_1000) ? 8'h00   // IF0
	      : (A == 9'b11_010_1001) ? 8'h00   // IF0
	      : (A == 9'b11_010_1010) ? 8'h00   // IF0
	      : (A == 9'b11_010_1011) ? 8'h00   // IF0
	      : (A == 9'b11_010_1100) ? 8'h00   // IF0
	      : (A == 9'b11_010_1101) ? 8'h00   // IF0
	      : (A == 9'b11_010_1110) ? 8'h00   // IF0
	      : (A == 9'b11_010_1111) ? 8'h00   // IF0	      

	      : 8'hff;   
endmodule // mapping_rom
	
      

Control ROM

The control ROM holds all of the microcode instructions. The microinstructions use the mapping ROM when branching, so both need to be designed at the same time. The format of a microinstruction is shown in the table below.

Microinstrucion
MC3029282726252423222120191817161514131211109876543210
00,01,10MCMMMRDSASB MAMBMDFSMO
11MCLSPSMSNAMO

Address zero is hard-coded to be the first address of the instruction fetch routine (IF0). Control is then passed to either the zero operand routine (0EX), the one operand routine (1EX), the two operand routine (2EX), or the branch routine (BEX). A branch is then made on addressing mode, followed by a branch to the instruction routine. When the instruction routine has executed, there is either a branch to the write-back routine (WB0) followed by a branch to the interrupt handling routine (INT0), or, if there are no values to write back to memory/registers, the write-back routine is skipped and there is a branch direct to the interrupt handling routine (INT0). The cycle then continues back at the instruction fetch routine (IF0).

	
module control_rom(D, A);
   input [7:0] A;
   output [30:0] D;
   assign D = (A == 8'h00)   ? 31'b00_00_000_00000_00000_01_00_1_00000_0100 // IF0: IR<=M[PC], PC<=PC+1
	      : (A == 8'h01) ? 31'b10_00_000_00000_00000_00_00_0_00000_0000 // IF1: CAR<=ROM[2'b00000||OPCODE[5:4]||2'b00]
	      
	      : (A == 8'h02) ? 31'b10_01_000_00000_00000_00_00_0_00000_0000 // 0EX: CAR<=ROM[2'b10000||MODE||S]

	      : (A == 8'h03) ? 31'b10_01_101_00000_00000_00_00_0_00000_0000 // NOP0: CAR<=INT0(ROM)

	      : (A == 8'h04) ? 31'b00_00_000_00000_00000_00_00_0_00000_1000 // PSHR0: SP<=SP-1
	      : (A == 8'h05) ? 31'b00_00_000_00000_00001_10_00_0_00000_1001 // PSHR1: M[SP]<=R1, SP<=SP-1
	      : (A == 8'h06) ? 31'b00_00_000_00000_00010_10_00_0_00000_1001 // PSHR2: M[SP]<=R2, SP<=SP-1
	      : (A == 8'h07) ? 31'b00_00_000_00000_00011_10_00_0_00000_1001 // PSHR3: M[SP]<=R3, SP<=SP-1
	      : (A == 8'h08) ? 31'b00_00_000_00000_00100_10_00_0_00000_1001 // PSHR4: M[SP]<=R4, SP<=SP-1
	      : (A == 8'h09) ? 31'b00_00_000_00000_00101_10_00_0_00000_1001 // PSHR5: M[SP]<=R5, SP<=SP-1
	      : (A == 8'h0a) ? 31'b00_00_000_00000_00110_10_00_0_00000_1001 // PSHR6: M[SP]<=R6, SP<=SP-1
	      : (A == 8'h0b) ? 31'b10_01_101_00000_00111_10_00_0_00000_0010 // PSHR7: M[SP]<=R7, CAR<=INT0(ROM)

	      : (A == 8'h0c) ? 31'b00_00_000_00111_00000_10_00_1_00000_1010 // POPR0: R7<=M[SP], SP<=SP+1
	      : (A == 8'h0d) ? 31'b00_00_000_00110_00000_10_00_1_00000_1010 // POPR1: R6<=M[SP], SP<=SP+1
	      : (A == 8'h0e) ? 31'b00_00_000_00101_00000_10_00_1_00000_1010 // POPR2: R5<=M[SP], SP<=SP+1
	      : (A == 8'h0f) ? 31'b00_00_000_00100_00000_10_00_1_00000_1010 // POPR3: R4<=M[SP], SP<=SP+1
	      : (A == 8'h10) ? 31'b00_00_000_00011_00000_10_00_1_00000_1010 // POPR4: R3<=M[SP], SP<=SP+1
	      : (A == 8'h11) ? 31'b00_00_000_00010_00000_10_00_1_00000_1010 // POPR5: R2<=M[SP], SP<=SP+1
	      : (A == 8'h12) ? 31'b10_01_101_00001_00000_10_00_1_00000_1010 // POPR6: R1<=M[SP], SP<=SP+1, CAR<=INT0(ROM)

	      : (A == 8'h13) ? 31'b00_00_000_01000_00001_00_00_0_11100_0000 // MVS0: R8<=R1
	      : (A == 8'h14) ? 31'b00_00_000_01001_00010_00_00_0_11100_0000 // MVS1: R9<=R2
	      : (A == 8'h15) ? 31'b00_00_000_01010_00011_00_00_0_11100_0000 // MVS2: R10<=R3
	      : (A == 8'h16) ? 31'b00_00_000_01010_00001_00_10_0_00001_1111 // MVS3: R10<=R10-1
	      : (A == 8'h17) ? 31'b11_0_0_0111_00000000000_00000000_0000    // MVS4: n:CAR<=IF0
	      : (A == 8'h18) ? 31'b00_00_000_01011_01000_11_00_1_00000_0000 // MVS5: R11<=M[R8]
	      : (A == 8'h19) ? 31'b00_00_000_01001_01011_00_00_0_00000_0010 // MVS6: M[R9]<=R11
	      : (A == 8'h1a) ? 31'b00_00_000_01000_00001_00_10_0_00000_0000 // MVS7: R8<=R8+1
	      : (A == 8'h1b) ? 31'b00_00_000_01001_00001_00_10_0_00000_0000 // MVS7: R9<=R9+1
	      : (A == 8'h1c) ? 31'b11_0_0_0000_00000000000_00010110_0000    // MVS4: CAR<=MVS3

	      : (A == 8'h1d) ? 31'b00_00_000_00000_00000_10_00_1_00000_0011 // RET0: PC<=M[SP]
	      : (A == 8'h1e) ? 31'b10_01_101_00000_00000_10_00_0_00000_1010 // RET1: SP<=SP+1, CAR<=INT0(ROM)

	      : (A == 8'h1f) ? 31'b00_00_000_00000_00000_10_00_1_00000_0110 // RTI0: PSR<=M[SP]
	      : (A == 8'h20) ? 31'b00_00_000_00010_00000_00_00_0_00000_1010 // RTI1: SP<=SP+1
	      : (A == 8'h21) ? 31'b00_00_000_00000_00000_10_00_1_00000_0011 // RTI2: PC<=M[SP]
	      : (A == 8'h21) ? 31'b10_01_101_00000_00000_10_00_0_00000_1010 // RTI1: SP<=SP+1, CAR<=INT0(ROM)

	      : (A == 8'h30) ? 31'b10_10_001_00000_00000_00_00_0_00000_0000 // 1OF: CAR<=ROM[2'b10001||MODE||S]
	     
	      : (A == 8'h31) ? 31'b10_00_001_01111_10000_00_00_0_11100_0000 // 1RG: DD<=R[DST], CAR<=1EX(ROM)
	      
	      : (A == 8'h32) ? 31'b00_00_000_01110_10000_00_00_0_11000_1000 // 1RGI0: DA<=R[DST]
	      : (A == 8'h33) ? 31'b10_00_001_01111_00000_00_00_1_00000_0000 // 1RGI1: DD<=M[DA], CAR<=1EX(ROM)

	      : (A == 8'h34) ? 31'b10_00_001_01111_00000_01_00_1_00000_0101 // 1IM: DD<=M[PC], PC<=PC+1, CAR<=1EX(ROM)

	      : (A == 8'h35) ? 31'b00_00_000_01110_00000_01_00_1_00000_0101 // 1DR0: DA<=M[PC], PC<=PC+1
	      : (A == 8'h36) ? 31'b10_00_001_01111_01110_00_00_1_00000_0000 // 1DR0: DD<=M[DA], CAR<=1EX(ROM)

	      : (A == 8'h37) ? 31'b00_00_000_01110_00000_01_00_1_00000_0101 // 1ID0: DA<=M[PC], PC<=PC+1
	      : (A == 8'h38) ? 31'b00_00_000_01110_10000_00_00_0_00000_0000 // 1ID1: DA<=DA+R[DST]
	      : (A == 8'h39) ? 31'b10_00_001_01111_01110_00_00_1_00000_0000 // 1ID2: DD<=M[DA], CAR<=1EX(ROM)

	      : (A == 8'h3a) ? 31'b00_00_000_01110_00000_01_00_1_00000_0101 // 1IDI0: DA<=M[PC], PC<=PC+1
	      : (A == 8'h3b) ? 31'b00_00_000_01110_10000_00_00_0_00000_0000 // 1IDI1: DA<=DA+R[DST]
	      : (A == 8'h3c) ? 31'b00_00_000_01111_00000_00_00_1_00000_0000 // 1IDI2: DA<=M[DA]
	      : (A == 8'h3d) ? 31'b10_00_001_01111_01110_00_00_1_00000_0000 // 1IDI3: DD<=M[DA], CAR<=1EX(ROM)
	      
	      : (A == 8'h3e) ? 31'b00_00_000_01110_00000_01_00_1_00000_0101 // 1RL0: DA<=M[PC], PC<=PC+1
	      : (A == 8'h3f) ? 31'b00_00_000_01110_00000_01_00_0_00000_0000 // 1RL1: DA<=DA+PC
	      : (A == 8'h40) ? 31'b10_00_001_01111_01110_00_00_1_00000_0000 // 1RL2: DD<=M[DA]+PC, CAR<=1EX(ROM) 

	      : (A == 8'h41) ? 31'b00_00_000_01110_00000_01_00_1_00000_0101 // 1RLI0: DA<=M[PC], PC<=PC+1
	      : (A == 8'h42) ? 31'b00_00_000_01110_00000_01_00_0_00000_0000 // 1RLI1: DA<=DA+PC
	      : (A == 8'h43) ? 31'b00_00_000_01111_00000_00_00_1_00000_0000 // 1RLI2: DA<=M[DA]	      
	      : (A == 8'h44) ? 31'b10_00_001_01111_01110_00_00_1_00000_0000 // 1RLI3: DD<=M[DA]+PC, CAR<=1EX(ROM) 

	      : (A == 8'h45) ? 31'b10_01_001_00000_00000_00_00_0_00000_0000 // 1EX: CAR<=ROM[1'b01001||OPCODE[3:0]]
	      
	      : (A == 8'h46) ? 31'b00_00_000_00000_00000_00_00_0_00000_1000 // PUSH0: SP<=SP-1
	      : (A == 8'h47) ? 31'b00_00_000_00000_01111_10_00_0_00000_0010 // PUSH1: M[SP]<=DD, SP<=SP-1
	      : (A == 8'h48) ? 31'b10_01_100_00000_00000_00_00_0_00000_0000 // PUSH2: CAR<=WB0(ROM)

	      : (A == 8'h49) ? 31'b10_01_100_01111_00000_10_00_1_00000_1010 // POP: DD<=M[SP], SP<=SP+1, CAR<=WB0(ROM)
	      
	      : (A == 8'h4a) ? 31'b10_01_100_01111_00001_00_10_0_00000_1100 // INC: DD<=DD+1, CAR<=WB0(ROM)

	      : (A == 8'h4b) ? 31'b10_01_100_01111_00001_00_10_0_00001_1100 // DEC: DD<=DD-1, CAR<=WB0(ROM)

	      : (A == 8'h4c) ? 31'b00_00_000_01111_00000_00_10_0_00111_0000 // NEG0: DD<=~DD
	      : (A == 8'h4d) ? 31'b10_01_100_01111_00001_00_10_0_00000_1100 // NEG1: DD<=DD+1, CAR<=WB0(ROM)

	      : (A == 8'h4e) ? 31'b10_01_100_01111_00001_00_10_0_00111_1110 // NOT: DD<=~DD, CAR<=WB0(ROM)

	      : (A == 8'h4f) ? 31'b00_00_000_01001_00000_00_11_0_11100_1111 // SHR0: R9<=SHA
	      : (A == 8'h50) ? 31'b11_0_0_1001_00000000000_11111000_0000    // SHR1: z:CAR<=INT0
	      : (A == 8'h51) ? 31'b00_00_000_01001_00001_00_10_0_00001_1111 // SHR2: R9<=R9-1
	      : (A == 8'h52) ? 31'b00_00_000_01111_00001_00_00_0_10100_1101 // SHR2: DD<=SHR(DD)
	      : (A == 8'h53) ? 31'b11_0_1_1001_00000000000_01010001_0000    // SHR3: ~z:CAR<=SHR2
	      : (A == 8'h54) ? 31'b10_01_100_00000_00000_00_00_0_00000_0000 // SHR4: CAR<=WB0(ROM)

	      : (A == 8'h55) ? 31'b00_00_000_01001_00000_00_11_0_11100_1111 // SHL0: R9<=SHA
	      : (A == 8'h56) ? 31'b11_0_0_1001_00000000000_11111000_0000    // SHL1: z:CAR<=INT0
	      : (A == 8'h57) ? 31'b00_00_000_01001_00001_00_10_0_00001_1111 // SHL2: R9<=R9-1
	      : (A == 8'h58) ? 31'b00_00_000_01111_00001_00_00_0_11000_1101 // SHL2: DD<=SHL(DD)
	      : (A == 8'h59) ? 31'b11_0_1_1001_00000000000_01010111_0000    // SHL3: ~z:CAR<=SHL2
	      : (A == 8'h5a) ? 31'b10_01_100_00000_00000_00_00_0_00000_0000 // SHL4: CAR<=WB0(ROM)

	      : (A == 8'h5b) ? 31'b00_00_000_01001_00000_00_11_0_11100_1111 // ASR0: R9<=SHA
	      : (A == 8'h5c) ? 31'b11_0_0_1001_00000000000_11111000_0000    // ASR1: z:CAR<=INT0
	      : (A == 8'h5d) ? 31'b00_00_000_01001_00001_00_10_0_00001_1111 // ASR2: R9<=R9-1
	      : (A == 8'h5e) ? 31'b00_00_000_01111_00001_00_00_0_10101_1100 // ASR2: DD<=ASR(DD)
	      : (A == 8'h5f) ? 31'b11_0_1_1001_00000000000_01011101_0000    // ASR3: ~z:CAR<=ASR2
	      : (A == 8'h60) ? 31'b10_01_100_00000_00000_00_00_0_00000_0000 // ASR4: CAR<=WB0(ROM)

	      : (A == 8'h61) ? 31'b00_00_000_01001_00000_00_11_0_11100_1111 // ASL0: R9<=SHA
	      : (A == 8'h62) ? 31'b11_0_0_1001_00000000000_11111000_0000    // ASL1: z:CAR<=INT0
	      : (A == 8'h63) ? 31'b00_00_000_01001_00001_00_10_0_00001_1111 // ASL2: R9<=R9-1
	      : (A == 8'h64) ? 31'b00_00_000_01111_00001_00_00_0_11001_1100 // ASL2: DD<=ASL(DD)
	      : (A == 8'h65) ? 31'b11_0_1_1001_00000000000_01100011_0000    // ASL3: ~z:CAR<=ASL2
	      : (A == 8'h66) ? 31'b10_01_100_00000_00000_00_00_0_00000_0000 // ASL4: CAR<=WB0(ROM)
	      
	      : (A == 8'h67) ? 31'b00_00_000_01001_00000_00_11_0_11100_1111 // ROR0: R9<=SHA
	      : (A == 8'h68) ? 31'b11_0_0_1001_00000000000_11111000_0000    // ROR1: z:CAR<=INT0
	      : (A == 8'h69) ? 31'b00_00_000_01001_00001_00_10_0_00001_1111 // ROR2: R9<=R9-1
	      : (A == 8'h6a) ? 31'b00_00_000_01111_00001_00_00_0_10110_1101 // ROR2: DD<=ROR(DD)
	      : (A == 8'h6b) ? 31'b11_0_1_1001_00000000000_01101001_0000    // ROR3: ~z:CAR<=ROR2
	      : (A == 8'h6c) ? 31'b10_01_100_00000_00000_00_00_0_00000_0000 // ROR4: CAR<=WB0(ROM)

	      : (A == 8'h6d) ? 31'b00_00_000_01001_00000_00_11_0_11100_1111 // ROL0: R9<=SHA
	      : (A == 8'h6e) ? 31'b11_0_0_1001_00000000000_11111000_0000    // ROL1: z:CAR<=INT0
	      : (A == 8'h6f) ? 31'b00_00_000_01001_00001_00_10_0_00001_1111 // ROL2: R9<=R9-1
	      : (A == 8'h70) ? 31'b00_00_000_01111_00001_00_00_0_11010_1101 // ROL2: DD<=ROL(DD)
	      : (A == 8'h71) ? 31'b11_0_1_1001_00000000000_01101111_0000    // ROL3: ~z:CAR<=ROL2
	      : (A == 8'h72) ? 31'b10_01_100_00000_00000_00_00_0_00000_0000 // ROL4: CAR<=WB0(ROM)

	      : (A == 8'h73) ? 31'b00_00_000_01001_00000_00_11_0_11100_1111 // RORC0: R9<=SHA
	      : (A == 8'h74) ? 31'b11_0_0_1001_00000000000_11111000_0000    // RORC1: z:CAR<=INT0
	      : (A == 8'h75) ? 31'b00_00_000_01001_00001_00_10_0_00001_1111 // RORC2: R9<=R9-1
	      : (A == 8'h76) ? 31'b00_00_000_01111_00001_00_00_0_10111_1101 // RORC2: DD<=RORC(DD)
	      : (A == 8'h77) ? 31'b11_0_1_1001_00000000000_01110101_0000    // RORC3: ~z:CAR<=RORC2
	      : (A == 8'h78) ? 31'b10_01_100_00000_00000_00_00_0_00000_0000 // RORC4: CAR<=WB0(ROM)

	      : (A == 8'h79) ? 31'b00_00_000_01001_00000_00_11_0_11100_1111 // ROLC0: R9<=SHA
	      : (A == 8'h7a) ? 31'b11_0_0_1001_00000000000_11111000_0000    // ROLC1: z:CAR<=INT0
	      : (A == 8'h7b) ? 31'b00_00_000_01001_00001_00_10_0_00001_1111 // ROLC2: R9<=R9-1
	      : (A == 8'h7c) ? 31'b00_00_000_01111_00001_00_00_0_11011_1101 // ROLC2: DD<=ROLC(DD)
	      : (A == 8'h7d) ? 31'b11_0_1_1001_00000000000_01111011_0000    // ROLC3: ~z:CAR<=ROLC2
	      : (A == 8'h7e) ? 31'b10_01_100_00000_00000_00_00_0_00000_0000 // ROLC4: CAR<=WB0(ROM)

	      : (A == 8'h80) ? 31'b10_10_011_00000_00000_00_00_0_00000_0000 // BAF: CAR<=ROM[2'b1011||MODE||S]
	      
	      : (A == 8'h81) ? 31'b00_00_000_01110_10000_00_00_0_11000_1000 // BRGI0: DA<=R[DST]
	      : (A == 8'h82) ? 31'b10_00_011_01111_00000_00_00_1_00000_0000 // BRGI1: DD<=M[DA], CAR<=BEX(ROM)

	      : (A == 8'h83) ? 31'b10_00_011_01110_00000_01_00_1_00000_0101 // BIM: DA<=M[PC], PC<=PC+1, CAR<=BEX(ROM) 

	      : (A == 8'h84) ? 31'b10_00_011_01110_00000_00_01_1_00000_0101 // BDR0: DA<=M[PC], PC<=PC+1, CAR<=BEX(ROM)

	      : (A == 8'h85) ? 31'b00_00_000_01110_00000_01_00_1_00000_0101 // BID0: DA<=M[PC], PC<=PC+1
	      : (A == 8'h86) ? 31'b00_00_000_01110_10000_00_00_0_00000_0000 // BID1: DA<=DA+R[DST]
	      : (A == 8'h87) ? 31'b10_00_011_01110_01110_00_00_1_00000_0000 // BID2: DA<=M[DA], CAR<=BEX(ROM)

	      : (A == 8'h88) ? 31'b00_00_000_01110_00000_01_00_1_00000_0101 // BIDI0: DA<=M[PC], PC<=PC+1
	      : (A == 8'h89) ? 31'b00_00_000_01110_10000_00_00_0_00000_0000 // BIDI1: DA<=DA+R[DST]
	      : (A == 8'h8a) ? 31'b00_00_000_01110_00000_00_00_1_00000_0000 // BIDI2: DA<=M[DA]
	      : (A == 8'h8b) ? 31'b10_00_011_01110_01110_00_00_1_00000_0000 // BIDI3: DA<=M[DA], CAR<=BEX(ROM)
	      
	      : (A == 8'h8c) ? 31'b00_00_000_01110_00000_01_00_1_00000_0101 // BRL0: DA<=M[PC], PC<=PC+1
	      : (A == 8'h8d) ? 31'b00_00_000_01110_01110_01_00_0_00000_0000 // BRL1: DA<=DA+PC
	      : (A == 8'h8e) ? 31'b10_00_011_01110_01110_00_00_1_00000_0000 // BRL2: DA<=M[DA], CAR<=BEX(ROM) 

	      : (A == 8'h8f) ? 31'b00_00_000_01110_00000_01_00_1_00000_0101 // BRLI0: DA<=M[PC], PC<=PC+1
	      : (A == 8'h90) ? 31'b00_00_000_01110_01110_01_00_0_00000_0000 // BRLI1: DA<=DA+PC
	      : (A == 8'h91) ? 31'b00_00_000_01110_00000_00_00_1_00000_0000 // BRLI2: DA<=M[DA]	      
	      : (A == 8'h92) ? 31'b10_00_011_01110_01110_00_00_1_00000_0000 // BRLI3: DA<=M[DA], CAR<=BEX(ROM) 

	      : (A == 8'h93) ? 31'b10_01_011_00000_00000_00_00_0_00000_0000 // BEX: CAR<=ROM[2'b01011||OPCODE[3:0]]

	      : (A == 8'h94) ? 31'b10_01_101_01110_00000_00_00_0_00000_0011 // JMP: PC<=DA, CAR<=INT0(ROM)

	      : (A == 8'h95) ? 31'b00_00_000_01000_00000_01_00_0_10000_0000 // CALL0: R8<=PC
	      : (A == 8'h96) ? 31'b00_00_000_01000_00000_00_00_0_00000_1000 // CALL1: SP<=SP-1
	      : (A == 8'h97) ? 31'b00_00_000_00000_01000_10_00_0_00000_0010 // CALL2: M[SP]<=R8
	      : (A == 8'h98) ? 31'b10_01_101_01110_00000_00_00_0_00000_0011 // CALL3: PC<=DA, CAR<=INT0(ROM)

	      : (A == 8'h99) ? 31'b11_0_0_0001_00000000000_10101010_0000    // BC0: C:CAR<=BRA
	      : (A == 8'h9a) ? 31'b10_01_101_00000_00000_00_00_0_00000_0000 // BC1: CAR<=INT0(ROM)

	      : (A == 8'h9b) ? 31'b11_0_1_0001_00000000000_10101010_0000    // BNC0: ~C:CAR<=BRA
	      : (A == 8'h9c) ? 31'b10_01_101_00000_00000_00_00_0_00000_0000 // BNC1: CAR<=INT0(ROM)

	      : (A == 8'h9d) ? 31'b11_0_0_0010_00000000000_10101010_0000    // BN0: N:CAR<=BRA
	      : (A == 8'h9e) ? 31'b10_01_101_00000_00000_00_00_0_00000_0000 // BN1: CAR<=INT0(ROM)

	      : (A == 8'h9f) ? 31'b11_0_1_0010_00000000000_10101010_0000    // BNN0: ~N:CAR<=BRA
	      : (A == 8'ha1) ? 31'b10_01_101_00000_00000_00_00_0_00000_0000 // BNN1: CAR<=INT0(ROM)

	      : (A == 8'ha2) ? 31'b11_0_0_0011_00000000000_10101010_0000    // BV0: V:CAR<=BRA
	      : (A == 8'ha3) ? 31'b10_01_101_00000_00000_00_00_0_00000_0000 // BV1: CAR<=INT0(ROM)

	      : (A == 8'ha4) ? 31'b11_0_1_0011_00000000000_10101010_0000    // BNV0: ~V:CAR<=BRA
	      : (A == 8'ha5) ? 31'b10_01_101_00000_00000_00_00_0_00000_0000 // BNV1: CAR<=INT0(ROM)

	      : (A == 8'ha6) ? 31'b11_0_0_0100_00000000000_10101010_0000    // BZ0: Z:CAR<=BRA
	      : (A == 8'ha7) ? 31'b10_01_101_00000_00000_00_00_0_00000_0000 // BZ1: CAR<=INT0(ROM)

	      : (A == 8'ha8) ? 31'b11_0_1_0100_00000000000_10101010_0000    // BNZ0: ~Z:CAR<=BRA
	      : (A == 8'ha9) ? 31'b10_01_101_00000_00000_00_00_0_00000_0000 // BNZ1: CAR<=INT0(ROM)

	      : (A == 8'haa) ? 31'b10_01_101_01110_00000_00_00_0_00000_0011 // BRA: PC<=DA, CAR<=INT0(ROM)

	      : (A == 8'hab) ? 31'b10_10_010_00000_00000_00_00_0_00000_0000 // 2OF: CAR<=ROM[2'b10010||MODE||S]	      

	      : (A == 8'hac) ? 31'b00_00_000_01101_11000_00_00_0_11100_0000 // 2RG0: SD<=R[SRC]
	      : (A == 8'had) ? 31'b10_00_010_01111_10000_00_00_0_11100_0000 // 2RG1: DD<=R[DST], CAR<=2EX(ROM)
	      : (A == 8'hae) ? 31'b00_00_000_01101_10000_00_00_0_11100_0000 // 2RGS0: SD<=R[DST]
	      : (A == 8'haf) ? 31'b10_00_010_01111_11000_00_00_0_11100_0000 // 2RGS1: DD<=R[SRC], CAR<=2EX(ROM)
	      
	      : (A == 8'hb0) ? 31'b00_00_000_01100_11000_00_00_0_11100_0000 // 2RGI0: SA<=R[SRC]
	      : (A == 8'hb1) ? 31'b00_00_000_01101_01100_11_00_1_00000_0000 // 2RGI1: SD<=M[SA]
	      : (A == 8'hb2) ? 31'b10_00_010_01111_10000_00_00_0_11100_0000 // 2RGI2: DD<=R[DST], CAR<=2EX(ROM)
	      : (A == 8'hb3) ? 31'b00_00_000_01110_10000_00_00_0_11100_0000 // 2RGIS0: DA<=R[DST]
	      : (A == 8'hb4) ? 31'b00_00_000_01111_01110_11_00_1_00000_0000 // 2RGIS1: DD<=M[DA]
	      : (A == 8'hb5) ? 31'b10_00_010_01101_11000_00_00_0_11100_0000 // 2RGIS2: SD<=R[SRC], CAR<=2EX(ROM)

	      : (A == 8'hb6) ? 31'b00_00_000_01101_00000_01_00_1_00000_0101 // 2IM0: SD<=M[PC], PC<=PC+1
	      : (A == 8'hb7) ? 31'b10_00_010_01111_10000_00_00_0_11100_0000 // 2IM1: DD<=R[DST], CAR<=2EX(ROM)
	      : (A == 8'hb8) ? 31'b00_00_000_01101_00000_01_00_1_00000_0101 // 2IMS0: SD<=M[PC], PC<=PC+1
	      : (A == 8'hb9) ? 31'b10_00_010_01111_11000_00_00_0_11100_0000 // 2IMS1: DD<=R[SRC], CAR<=2EX(ROM)
	      
	      : (A == 8'hba) ? 31'b00_00_000_01100_00000_01_00_1_00000_0101 // 2DR0: SA<=M[PC], PC<=PC+1
	      : (A == 8'hbb) ? 31'b00_00_000_01101_01100_11_00_1_00000_0000 // 2DR1: SD<=M[SA]
	      : (A == 8'hbc) ? 31'b10_00_010_01111_10000_00_00_0_11100_0000 // 2DR2: DD<=R[DST], CAR<=2EX(ROM)
	      : (A == 8'hbd) ? 31'b00_00_000_01110_00000_01_00_1_00000_0101 // 2DRS0: DA<=M[PC], PC<=PC+1
	      : (A == 8'hbe) ? 31'b00_00_000_01111_01110_11_00_1_00000_0000 // 2DRS1: DD<=M[DA]
	      : (A == 8'hbf) ? 31'b10_00_010_01101_11000_00_00_0_11100_0000 // 2DRS2: SD<=R[SRC], CAR<=2EX(ROM)

	      : (A == 8'hc0) ? 31'b00_00_000_01001_10000_00_00_0_11100_0000 // 2ID0: SD<=R[DST], 
	      : (A == 8'hc1) ? 31'b00_00_000_01110_00000_01_00_1_00000_0101 // 2ID1: DA<=M[PC], PC<=PC+1
	      : (A == 8'hc2) ? 31'b00_00_000_01110_11000_00_00_0_00000_0000 // 2ID2: DA<=DA+R[SRC]
	      : (A == 8'hc3) ? 31'b10_00_010_01111_01110_00_00_1_00000_0000 // 2ID3: DD<=M[DA], CAR<=2EX(ROM)
	      : (A == 8'hc4) ? 31'b00_00_000_01101_11000_00_00_0_11100_0000 // 2IDS0: SD<=R[SRC], 
	      : (A == 8'hc5) ? 31'b00_00_000_01110_00000_01_00_1_00000_0101 // 2IDS1: DA<=M[PC], PC<=PC+1
	      : (A == 8'hc6) ? 31'b00_00_000_01110_10000_00_00_0_00000_0000 // 2IDS2: DA<=DA+R[DST]
	      : (A == 8'hc7) ? 31'b10_00_010_01111_01110_00_00_1_00000_0000 // 2IDS3: DD<=M[DA], CAR<=2EX(ROM)

	      : (A == 8'hc8) ? 31'b00_00_000_01001_10000_00_00_0_11100_0000 // 2IDI0: SD<=R[DST], 
	      : (A == 8'hc9) ? 31'b00_00_000_01110_00000_01_00_1_00000_0101 // 2IDI1: DA<=M[PC], PC<=PC+1
	      : (A == 8'hca) ? 31'b00_00_000_01110_11000_00_00_0_00000_0000 // 2IDI2: DA<=DA+R[SRC]
	      : (A == 8'hcb) ? 31'b00_00_000_01111_00000_00_00_1_00000_0000 // 2IDI3: DA<=M[DA]
	      : (A == 8'hcc) ? 31'b10_00_010_01111_01110_00_00_1_00000_0000 // 2IDI4: DD<=M[DA], CAR<=2EX(ROM)
	      : (A == 8'hcd) ? 31'b00_00_000_01001_11000_00_00_0_11100_0000 // 2IDIS0: SD<=R[SRC], 
	      : (A == 8'hce) ? 31'b00_00_000_01110_00000_01_00_1_00000_0101 // 2IDIS1: DA<=M[PC], PC<=PC+1
	      : (A == 8'hcf) ? 31'b00_00_000_01110_10000_00_00_0_00000_0000 // 2IDIS2: DA<=DA+R[DST]
	      : (A == 8'hd0) ? 31'b00_00_000_01111_00000_00_00_1_00000_0000 // 2IDIS3: DA<=M[DA]
	      : (A == 8'hd1) ? 31'b10_00_010_01111_01110_00_00_1_00000_0000 // 2IDIS4: DD<=M[DA], CAR<=2EX(ROM)
	      
	      : (A == 8'hd2) ? 31'b00_00_000_01101_10000_00_00_0_11100_0000 // 2RL0: SD<=R[DST], 
	      : (A == 8'hd3) ? 31'b00_00_000_01100_00000_01_00_1_00000_0101 // 2RL1: SA<=M[PC], PC<=PC+1
	      : (A == 8'hd4) ? 31'b00_00_000_01100_01100_01_00_0_00000_0000 // 2RL2: SA<=SA+PC
	      : (A == 8'hd5) ? 31'b10_00_010_01101_01100_11_00_1_00000_0000 // 2RL3: SD<=M[SA], CAR<=2EX(ROM) 
	      : (A == 8'hd6) ? 31'b00_00_000_01101_11000_00_00_0_11100_0000 // 2RLS0: SD<=R[SRC], 
	      : (A == 8'hd7) ? 31'b00_00_000_01110_01110_01_00_1_00000_0101 // 2RLS1: DA<=M[PC], PC<=PC+1
	      : (A == 8'hd8) ? 31'b00_00_000_01110_01110_01_00_0_00000_0000 // 2RLS2: DA<=DA+PC
	      : (A == 8'hd9) ? 31'b10_00_010_01111_01110_11_00_1_00000_0000 // 2RLS3: DD<=M[DA], CAR<=2EX(ROM) 

	      : (A == 8'hda) ? 31'b00_00_000_01101_10000_00_00_0_11100_0000 // 2RLI0: SD<=R[DST], 
	      : (A == 8'hdb) ? 31'b00_00_000_01100_00000_01_00_1_00000_0101 // 2RLI1: SA<=M[PC], PC<=PC+1
	      : (A == 8'hdc) ? 31'b00_00_000_01100_01100_01_00_0_00000_0000 // 2RLI2: SA<=SA+PC
	      : (A == 8'hdd) ? 31'b00_00_000_01100_00000_00_00_1_00000_0000 // 2RLI3: SA<=M[SA]	      
	      : (A == 8'hde) ? 31'b10_00_010_01101_01100_11_00_1_00000_0000 // 2RLI4: SD<=M[SA], CAR<=2EX(ROM) 
	      : (A == 8'hdf) ? 31'b00_00_000_01101_11000_00_00_0_11100_0000 // 2RLIS0: SD<=R[SRC], 
	      : (A == 8'he0) ? 31'b00_00_000_01110_00000_01_00_1_00000_0101 // 2RLIS1: DA<=M[PC], PC<=PC+1
	      : (A == 8'he1) ? 31'b00_00_000_01110_01110_01_00_0_00000_0000 // 2RLIS2: DA<=DA+PC
	      : (A == 8'he2) ? 31'b00_00_000_01111_00000_00_00_1_00000_0000 // 2RLIS3: DA<=M[DA]	      
	      : (A == 8'he3) ? 31'b10_00_010_01101_01110_11_00_1_00000_0000 // 2RLIS4: SD<=M[DA], CAR<=2EX(ROM) 

	      : (A == 8'he4) ? 31'b10_01_010_00000_00000_00_00_0_00000_0000 // 2EX: CAR<=ROM[2'b01010||OPCODE[3:0]]

	      : (A == 8'he5) ? 31'b10_01_100_01111_01101_00_00_0_11100_0000 // MOV: DD<=SD, CAR<=WB0(ROM)

	      : (A == 8'he6) ? 31'b00_00_000_01001_01101_00_00_0_11100_0000 // XCH0: R9<=SD
	      : (A == 8'he7) ? 31'b00_00_000_01101_01111_00_00_0_11100_0000 // XCH1: SD<=DD
	      : (A == 8'he8) ? 31'b10_10_100_01111_01001_00_00_0_11100_0000 // XCH2: DD<=R9, CAR<=ROM[2'b10100||MODE||S]
	      : (A == 8'he9) ? 31'b10_01_100_10000_01101_00_00_0_11100_0000 // XCH3: R[SRC]<=SD, CAR<=WB0(ROM)
	      : (A == 8'hea) ? 31'b10_01_100_11000_01101_00_00_0_00000_0010 // XCH4: M[SA]<=SD, CAR<=WB0(ROM)

	      : (A == 8'heb) ? 31'b10_01_100_01111_01101_00_00_0_00000_1100 // ADD: DD<=DD+SD, CAR<=WB0(ROM)

	      : (A == 8'hec) ? 31'b10_01_100_01111_01101_00_00_0_00000_1011 // ADDC: DD<=DD+SD+C, CAR<=WB0(ROM)

	      : (A == 8'hed) ? 31'b10_01_100_01111_01101_00_00_0_00001_1100 // SUB: DD<=DD-SD, CAR<=WB0(ROM)

	      : (A == 8'hee) ? 31'b10_01_100_01111_01101_00_00_0_00001_1011 // SUBB: DD<=DD-(SD+C), CAR<=WB0(ROM)

	      /*
	       * MUL & DIV MISSING. These are not implemented to save time.
	       */
	      
	      : (A == 8'hef) ? 31'b10_01_101_01111_01101_00_00_0_00001_1100 // CMP: DD<=DD-SD, CAR<=INT0(ROM)

	      : (A == 8'hf0) ? 31'b10_01_100_01111_01101_00_00_0_00010_1100 // AND: DD<=DD&SD, CAR<=WB0(ROM)

	      : (A == 8'hf1) ? 31'b10_01_100_01111_01101_00_00_0_00011_1100 // OR: DD<=DD|SD, CAR<=WB0(ROM)

	      : (A == 8'hf2) ? 31'b10_01_100_01111_01101_00_00_0_00100_1100 // XOR: DD<=DD^SD, CAR<=WB0(ROM)

	      : (A == 8'hf5) ? 31'b10_11_000_00000_00000_00_00_0_00000_0000 // WB0: CAR<=ROM[2'b11000||MODE||S]
	      : (A == 8'hf6) ? 31'b10_01_101_10000_01111_00_00_0_11100_0000 // WB1: R[DST]<=DD, CAR<=INT0(ROM)
	      : (A == 8'hf7) ? 31'b10_01_101_01110_01111_00_00_0_00000_0010 // WB2: M[DA]<=DD, CAR<=INT0(ROM)
	      
	      : (A == 8'hf8) ? 31'b11_0_1_1010_00000000000000_00000_0000    // INT0: ~INTS:CAR<=IF0
	      : (A == 8'hf9) ? 31'b00_00_000_01000_00000_01_00_0_00000_0000 // INT1: R8<=PC
	      : (A == 8'hfa) ? 31'b00_00_000_00000_00000_00_00_0_00000_1000 // INT2: SP<=SP-1
	      : (A == 8'hfb) ? 31'b00_00_000_00000_01000_10_00_0_00000_1001 // INT3: M[SP]<=R8, SP<=SP-1
	      : (A == 8'hfc) ? 31'b00_00_000_00000_00000_10_01_0_00000_1001 // INT4: M[SP]<=PSR
	      : (A == 8'hfd) ? 31'b00_00_000_00000_00000_00_00_0_00000_0110 // INT5: PSR<=0
	      : (A == 8'hfe) ? 31'b00_00_000_00000_00000_00_00_0_00000_0001 // INT6: INACK<=1 (PC is loaded with 16'h0000)
	      : (A == 8'hff) ? 31'b10_11_010_00000_00000_00_00_1_00000_0000 // INT7: CAR<=IF0(ROM)
	      : 31'b00_00_000_00000_00000_00_00_0_00000_0000;   
endmodule // control_rom
	
      

Eight-bit Incrementer

The eight-bit incrementer is used by the microsequencer to increment the contents of the CAR.

	
module incrementer_8(S, A);
   output [7:0] S;   // The 8-bit sum.
   output 	C;   // The 1-bit carry.
   output 	V;   // The 1-bit overflow status.
   input [7:0] 	A;   // The 8-bit augend.
   input [7:0] 	B;   // The 8-bit addend.
   input 	Cin; // The initial carry in.
   
   wire [3:0] 	S1_0;   // Nibble 1 sum output with carry input 0.
   wire [3:0] 	S1_1;   // Nibble 1 sum output with carry input 1.
   wire 	C1_0;   // Nibble 1 carry output with carry input 0 (unused).
   wire 	C1_1;   // Nibble 1 carry output with carry input 1 (unused).
   wire 	C0;     // Nibble 0 carry output used to select multiplexer output.
   wire         V0;     // Nibble 0 overflow output (unused).
   wire 	V1_0;   // Nibble 1 overflow output with carry input 0 (unused).
   wire 	V1_1;   // Nibble 1 overflow output with carry input 1 (unused).
   
   ripple_carry_adder rc_nibble_0(S[3:0], C0, V0, A[3:0], 4'b0001, 1'b0);           // Calculate S nibble 0.
   ripple_carry_adder rc_nibble_1_carry_0(S1_0, C1_0, V1_0, A[7:4], 4'b0000, 1'b0); // Calculate S nibble 1 with carry input 0.
   ripple_carry_adder rc_nibble_1_carry_1(S1_1, C1_1, V1_1, A[7:4], 4'b0000, 1'b1); // Calculate S nibble 1 with carry input 1.
   
   multiplexer_2_1 #(4) muxs1(S[7:4], S1_0, S1_1, C0);    // C0 selects the result for nibble 1.
endmodule 
	
      

Eight-bit Register

The eight-bit register is used to implement the CAR and the SBR.

	
module register_parallel_load_8(Q, D, Load, CLK);
   output [7:0] Q;    // Contents of the register.
   input [7:0] 	D;    // Data to load into the register.
   input 	Load; // Signal to load contents.
   input 	CLK;  // System clock.
   
   wire 	Loadn;
   wire 	w1, w2, w3, w4, w5, w6, w7, w8, w9, w10, w11, w12;           // Connecting wires.
   wire 	w13, w14, w15, w16, w17, w18, w19, w20, w21, w22, w23, w24;  // Connecting wires.
   wire [7:0] 	Qn;   // Unused.
   
   not(Loadn, Load);
   
   and(w1, Q[0], Loadn);
   and(w2, D[0], Load);
   or(w3, w2, w1);

   and(w4, Q[1], Loadn);
   and(w5, D[1], Load);
   or(w6, w5, w4);

   and(w7, Q[2], Loadn);
   and(w8, D[2], Load);
   or(w9, w8, w7);

   and(w10, Q[3], Loadn);
   and(w11, D[3], Load);
   or(w12, w11, w10);

   and(w13, Q[4], Loadn);
   and(w14, D[4], Load);
   or(w15, w14, w13);

   and(w16, Q[5], Loadn);
   and(w17, D[5], Load);
   or(w18, w17, w16);

   and(w19, Q[6], Loadn);
   and(w20, D[6], Load);
   or(w21, w20, w19);

   and(w22, Q[7], Loadn);
   and(w23, D[7], Load);
   or(w24, w23, w22);

   d_flip_flop_edge_triggered dff0(Q[0], Qn[0], CLK, w3);
   d_flip_flop_edge_triggered dff1(Q[1], Qn[1], CLK, w6);
   d_flip_flop_edge_triggered dff2(Q[2], Qn[2], CLK, w9);
   d_flip_flop_edge_triggered dff3(Q[3], Qn[3], CLK, w12);
   d_flip_flop_edge_triggered dff4(Q[4], Qn[4], CLK, w15);
   d_flip_flop_edge_triggered dff5(Q[5], Qn[5], CLK, w18);
   d_flip_flop_edge_triggered dff6(Q[6], Qn[6], CLK, w21);
   d_flip_flop_edge_triggered dff7(Q[7], Qn[7], CLK, w24);
   
endmodule // register_parallel_load_8
	
      

Misc.

Multiplexers are found almost everywhere in the CPU design. The code for all types are given below.

	
module multiplexer_2_1(X, A0, A1, S);
   parameter WIDTH=16;     // How many bits wide are the lines

   output [WIDTH-1:0] X;   // The output line

   input [WIDTH-1:0]  A1;  // Input line with id 1'b1
   input [WIDTH-1:0]  A0;  // Input line with id 1'b0
   input 	      S;  // Selection bit
   
   assign X = (S == 1'b0) ? A0 : A1;
endmodule // multiplexer_2_1

module multiplexer_4_1(X, A0, A1, A2, A3, S1, S0);
   parameter WIDTH=16;     // How many bits wide are the lines

   output [WIDTH-1:0] X;   // The output line

   input [WIDTH-1:0]  A3;  // Input line with id 2'b11
   input [WIDTH-1:0]  A2;  // Input line with id 2'b10
   input [WIDTH-1:0]  A1;  // Input line with id 2'b01
   input [WIDTH-1:0]  A0;  // Input line with id 2'b00
   input 	      S0;  // Least significant selection bit
   input 	      S1;  // Most significant selection bit

   assign X = (S1 == 0 
	       ? (S0 == 0 
		  ? A0       // {S1,S0} = 2'b00
		  : A1)      // {S1,S0} = 2'b01
	       : (S0 == 0 
		  ? A2       // {S1,S0} = 2'b10
		  : A3));    // {S1,S0} = 2'b11		  
endmodule // multiplexer_4_1

module multiplexer_8_1(X, A0, A1, A2, A3, A4, A5, A6, A7, S);
   parameter WIDTH=16;     // How many bits wide are the lines

   output [WIDTH-1:0] X;   // The output line

   input [WIDTH-1:0]  A7;  // Input line with id 3'b111
   input [WIDTH-1:0]  A6;  // Input line with id 3'b110
   input [WIDTH-1:0]  A5;  // Input line with id 3'b101
   input [WIDTH-1:0]  A4;  // Input line with id 3'b100
   input [WIDTH-1:0]  A3;  // Input line with id 3'b011
   input [WIDTH-1:0]  A2;  // Input line with id 3'b010
   input [WIDTH-1:0]  A1;  // Input line with id 3'b001
   input [WIDTH-1:0]  A0;  // Input line with id 3'b000
   input [2:0]	      S;   

   assign X = (S[2] == 0 
	       ? (S[1] == 0 
		  ? (S[0] == 0 
		     ? A0       // {S2,S1,S0} = 3'b000
		     : A1)      // {S2,S1,S0} = 3'b001
		  : (S[0] == 0 
		     ? A2       // {S2,S1,S0} = 3'b010
		     : A3))     // {S2,S1,S0} = 3'b011
	       : (S[1] == 0 
		  ? (S[0] == 0 
		     ? A4       // {S2,S1,S0} = 3'b100
		     : A5)      // {S2,S1,S0} = 3'b101
		  : (S[0] == 0 
		     ? A6       // {S2,S1,S0} = 3'b110
		     : A7)));   // {S2,S1,S0} = 3'b111
endmodule // multiplexer_8_1

module multiplexer_16_1(X, A0, A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, A13, A14, A15, S);
   parameter WIDTH=16;     // How many bits wide are the lines

   output [WIDTH-1:0] X;   // The output line
   
   input [WIDTH-1:0]  A15;  // Input line with id 4'b1111
   input [WIDTH-1:0]  A14;  // Input line with id 4'b1110
   input [WIDTH-1:0]  A13;  // Input line with id 4'b1101
   input [WIDTH-1:0]  A12;  // Input line with id 4'b1100
   input [WIDTH-1:0]  A11;  // Input line with id 4'b1011
   input [WIDTH-1:0]  A10;  // Input line with id 4'b1010
   input [WIDTH-1:0]  A9;  // Input line with id 4'b1001
   input [WIDTH-1:0]  A8;  // Input line with id 4'b1000
   input [WIDTH-1:0]  A7;  // Input line with id 4'b0111
   input [WIDTH-1:0]  A6;  // Input line with id 4'b0110
   input [WIDTH-1:0]  A5;  // Input line with id 4'b0101
   input [WIDTH-1:0]  A4;  // Input line with id 4'b0100
   input [WIDTH-1:0]  A3;  // Input line with id 4'b0011
   input [WIDTH-1:0]  A2;  // Input line with id 4'b0010
   input [WIDTH-1:0]  A1;  // Input line with id 4'b0001
   input [WIDTH-1:0]  A0;  // Input line with id 4'b0000
   input [3:0]	      S;   

   assign X = (S[3] == 0 
	       ? (S[2] == 0 
		  ? (S[1] == 0 
		     ? (S[0] == 0 
			? A0       // {S3, S2,S1,S0} = 4'b0000
			: A1)      // {S3, S2,S1,S0} = 4'b0001
		     : (S[0] == 0 
			? A2       // {S3, S2,S1,S0} = 4'b0010
			: A3))     // {S3, S2,S1,S0} = 4'b0011
		  : (S[1] == 0 
		     ? (S[0] == 0 
			? A4       // {S3, S2,S1,S0} = 4'b0100
			: A5)      // {S3, S2,S1,S0} = 4'b0101
		     : (S[0] == 0 
			? A6       // {S3, S2,S1,S0} = 4'b0110
			: A7)))    // {S3, S2,S1,S0} = 4'b0111
	       : (S[2] == 0 
		  ? (S[1] == 0 
		     ? (S[0] == 0 
			? A8       // {S3, S2,S1,S0} = 4'b1000
			: A9)      // {S3, S2,S1,S0} = 4'b1001
		     : (S[0] == 0 
			? A10      // {S3, S2,S1,S0} = 4'b1010
			: A11))    // {S3, S2,S1,S0} = 4'b1011
		  : (S[1] == 0 
		     ? (S[0] == 0 
			? A12      // {S3, S2,S1,S0} = 4'b1100
			: A13)     // {S3, S2,S1,S0} = 4'b1101
		     : (S[0] == 0 
			? A14      // {S3, S2,S1,S0} = 4'b1110
			: A15)))); // {S3, S2,S1,S0} = 4'b1111
endmodule // multiplexer_16_1
	
      

References

Mano, M. Morris, and Kime, Charles R. Logic and Computer Design Fundamentals. 2nd Edition. Prentice Hall, 2000.

Index