Level 44: Control Unit

Task

Implement an instruction decoder (Control Unit) — the key component of a processor that converts an operation code (opcode) into control signals.

The ControlUnit module accepts a 4-bit opcode and produces 4 control signals:

  • RegWrite — register write enable (ADD, AND).
  • MemWrite — memory write (STA).
  • ALUSel — ALU operation select: 0=add, 1=AND.
  • Branch — branch signal (JMP).

Recognized opcodes (mini-ISA):

opcodeInstructionRegWriteMemWriteALUSelBranch
0 (0000)ADD1000
1 (0001)AND1010
2 (0010)STA0100
3 (0011)JMP0001
4–15NOP0000

Use only AND, OR, NOT gates (structural approach). assign, if, case, always are forbidden.

Related materials

Solution

The decoder is built as detection trees for each opcode. Algorithm:

  1. Invert all opcode bits: n0 = NOT opcode[0], …, n3 = NOT opcode[3].
  2. Detect each opcode with an AND-tree of inverted/direct bits.
  3. Combine signals via OR for outputs active on multiple opcodes.
module ControlUnit(
    input wire [3:0] opcode,
    output wire RegWrite,
    output wire MemWrite,
    output wire ALUSel,
    output wire Branch
);
  wire n0, n1, n2, n3;
  not g0(n0, opcode[0]);
  not g1(n1, opcode[1]);
  not g2(n2, opcode[2]);
  not g3(n3, opcode[3]);

  // opcode=0 (ADD): all bits 0
  wire add_t1, add_t2, op_add;
  and ga1(add_t1, n0, n1);
  and ga2(add_t2, n2, n3);
  and ga3(op_add, add_t1, add_t2);

  // opcode=1 (AND): opcode[0]=1, rest 0
  wire and_t1, and_t2, op_and;
  and gb1(and_t1, opcode[0], n1);
  and gb2(and_t2, n2, n3);
  and gb3(op_and, and_t1, and_t2);

  // opcode=2 (STA): opcode[1]=1, rest 0
  wire sta_t1, sta_t2, op_sta;
  and gc1(sta_t1, n0, opcode[1]);
  and gc2(sta_t2, n2, n3);
  and gc3(op_sta, sta_t1, sta_t2);

  // opcode=3 (JMP): opcode[0]=1, opcode[1]=1
  wire jmp_t1, jmp_t2, op_jmp;
  and gd1(jmp_t1, opcode[0], opcode[1]);
  and gd2(jmp_t2, n2, n3);
  and gd3(op_jmp, jmp_t1, jmp_t2);

  // Outputs: OR combines opcodes
  or grw(RegWrite, op_add, op_and);
  or galusel(ALUSel, op_and, op_and);
  or gmem(MemWrite, op_sta, op_sta);
  or gbr(Branch, op_jmp, op_jmp);
endmodule

Total: 4×NOT, 12×AND, 4×OR. Each opcode is detected by three ANDs: two ANDs combine bit pairs, the third combines the results. Opcodes 4–15 activate no detector → all outputs = 0 (NOP).