Close

Designing and Implementing the MicroCode Sequencer

A project log for Homebrew 16-bit CPU

Inspired by The Soul of a New Machine Im designing and building a 16-bit CPU with virtual memory, CPU cache, and rich addressing modes

anthony-fauliseAnthony Faulise 05/06/2025 at 21:210 Comments

It’s time to translate my intent for the MicroCode Sequencer into design decisions.

Narratively, when the CPU executes an instruction:

  1. The Instruction Controller presents the MC Program Counter where execution should start (MC_PC_START) and sets the MC_START bit
  2. The MC Sequencer outputs the control signals from the MC ROM at the address specified by the MC_PC to the ALU and other parts of the CPU
  3. At every clock cycle when an instruction is executing*, the MC Sequencer increments the MC_PC or loads a new value entirely in the event of a Jump or Branch, loop back to 3
  4. At the end of an instruction, the MC ROM sets a signal (MC_DONE) that prevents the MC_PC from loading a new value and instead stops execution and signals the Instruction Controller that the MicroCode Sequencer is done.

*Note (from above): whenever the MicroCode Sequencer requests a memory read or write from the CPU bus controller, it should wait any number of clock cycles until the memory operation completes. So, in the case of memory-wait condition, the MC PC won’t actually advance on every clock cycle.

The inputs to the MicroCode Sequencer will be:

The outputs of the MicroCode Sequencer are:

Let’s address the implementation itself.

We’ll use a simple S-R flip-flop to track whether the MC_Seq is busy or idle.

When the MC_Seq is done with an instruction, we’ll use an S-R flip flop to generate a one-clock-cycle DONE pulse to the Instruction controller.

We’ll use a register to capture the MC_START_ADDRESS on every clock cycle when the MC_Seq is idle, so that when we receive MC_START, the start address is already captured.

We’ll need some logic to examine MC_Seq control signals like ready/busy, branch, jump, done, and RESET to determine which value to load into the MC_PC. Conceptually:

I’ll use a 4-1 multiplexer for the routing of the MC_PC address.

Select mapping for the multiplexer is:

Select

Input

00

0x00

01

MC_ROM output low-bits

10

MC_START_ADDR

11

MC_PC + 1

To implement the logic of selecting which source to use for the next MC_PC, I’ll use this Karnaugh map:

Jump, Branch, CCR Match

000

001

011

010

110

111

101

100

Reset, Busy, Done

000

10

10

10

10

10

10

10

10

001

d/c

d/c

d/c

d/c

d/c

d/c

d/c

d/c

011

d/c

d/c

d/c

d/c

d/c

d/c

d/c

d/c

010

11

11

01

11

n/a

n/a

01

01

110

00

00

00

00

00

00

00

00

111

00

00

00

00

00

00

00

00

101

00

00

00

00

00

00

00

00

100

00

00

00

00

00

00

00

00

n/a - not applicable, condition should not arise

d/c - don’t care

Select_Bit_1 = AND(Not_RESET, Not_Busy) OR AND(Not RESET, Not_Jump, Not_Branch) OR AND(Not_RESET, Branch, Not_Match)

Select_Bit_0 = AND(Not_RESET, Busy, Not_Done)

I’ll route the output of the MC_PC latch to an adder to prepare MC_PC + 1.

I’ll route the output of the MC_PC to the MicroCode ROM, which will be quite wide (I’m expecting 20-40 bits wide).

Except during MicroCode branch operations, I’ll want to route the MC ROM output to the ALU (and other CPU sections), but will want to suppress that output for some of the bits during Jump and Branch instructions, so I’ll use some tri-state output buffers to control when the whole output of the MC ROM is passed to the ALU, etc.

During MicroCode Branch operations, I’ll want to route the condition bits to the ALU CCR section to perform the comparison, so I’ll use some tri-state output buffers to control when the condition select bits are routed to the CCR condition test logic.

Here’s the resulting circuit diagram. If you look in detail, you’ll see that it is currently set up for a 4-bit MC_ROM address space (OK for simulation, not realistic) and a 16-bit MC_ROM output (also OK for simulation, not realistic).

I did a simulation of the circuit and it seems to work OK.  Again, famous last words…

Next, I’ll take on the design of the ALU. That will help me define the ALU control signals I’ll need.

Discussions