JuanGg wrote:
As I ran out of address lines on the microcode ROMs, I have turned reset and interrupts into regular instructions. When IRQ goes low, next opcode to be executed is forced to be 0x0, the BRK instruction.
This statement appears to indicate that you were running the RST and IRQ signals into your microcode ROMs. I think that this is an inefficient use of the address lines to your microcode ROM. First, RST should have an independent effect on some of your internal registers, such as your program / instruction counter (PC), your microprogram / microinstruction counter (uPC), and your Memory Address Register (MAR). When RST is asserted, these registers / counters should be forced to a known state.
In the case of the PC and the MAR, they should point to the reset vector location: 0xFFFC. In my implementation, I don't actually set the PC explicitly when RST is asserted. Instead, I either increment it, i.e. PC <= PC + 1, or I load it with the address I'm presenting on the memory address bus, i.e. the value assigned to MAR. Therefore, on RST, I force the memory address to 0xFFFC, and capture that address into the PC at the completion of the first read cycle of the reset sequence. The uPC is force to 0x00 (8-/9-bit microprogram address bus), and I proceed from there.
To handle interrupts, I conditionally test the internal INT signal, i.e. INT = FE(NMI) | IRQ & IE, and load the MAR as required with either the NMI vector address or the IRQ vector address. (Note: FE(NMI) is a function that latches until serviced when a falling edge on the external nNMI signal is detected.)
This approach may make the implementation a bit slower since it places logic in the address path, but it allows the microcode ROM to be populated with microcode sequences as required by the instructions and addressing modes. In other words, the microcode ROM does not need four different microinstructions for each instruction sequence element to account for RST or INT being asserted. In the case of RST, it is not a conditional signal, and in the case of INT, as defined above, the current instruction sequence is completed and the INT sequence is only performed at the boundary between instructions.
Just curiosity, but are you using a microprogram sequencer or just a loadable counter. If you're using just a loadable counter, you may consider using a simple microprogram sequencer like the Fairchild 9408. You can find a description of this obsolete microprogram sequencer in the 1976 Fairchild Macrologic manual (page 86) archived on bitsavers.org
here. (Note: big PDF) Alternatively, you can view a derivative of this particular microprogram sequencer written in Verilog
here.