IRQ - Hold and reset Circuit.
2-Zons wrote 01/03/2019 at 06:26 • 0 pointsWorking on my 8 bit TTL CPU. I've got a version of IRQ working. When IRQ is pulled low, it loads the IRQ instruction (FF) into the instruction register after the current instruction is finished.
I am trying to figure out the simplest way of preventing repeat IRQ instructions. The solution I'm currently working with is a 2 bit state machine with 3 states, 2 Inputs (IRQ, and IRQ ack), and one output (IRQ out, which loads the IRQ instruction). This will work but I'm thinking there has to be simpler solution.
I need to be able to hold an IRQ signal long enough for an instruction to finish, Once it has loaded the instruction (IRQ ack), it needs to ignore the IRQ signal until it goes hi and then low again (a new IRQ request). I'm thinking there might be a simple way to do this with one or two D flip flops? I can't think of it though.
I've been putting a lot on the stack lately. This community has been just great for getting answers.
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.
I obviously put this in the wrong place —- it’s in response to your earlier question regarding differentiating between IRQ and RESET. Cheers.
The interrupt-pending flags carry the state information you need. Where you end up will of course depend on the requirements of your design (and your own personal preference), but I can see a couple of ways to handle it: (1) you can have shared microcode and use combinatorial logic to tailor each interrupt as needed, or (2) you can synthesize a different opcode based on the flags that are active at the onset of the interrupt and have distinct microcode for each. My bias would be towards option 1 if the processing is similar, as it seems to be in this case. Initializing the program counter is just a jump to a defined address (no different than other interrupts really). That leaves initializing the stack. Maybe you can direct an active-low RESET-PENDING flag into the /CLR input of a 74HC273 stack pointer, which will then be “initialized” to 0 on RESET but not otherwise. Anyway, you get the idea. But take a close look at what you actually *need* to initialize. It’s often the case that you can leave things be and it simplifies the logic immensely.
Are you sure? yes | no
I used to program on the Commodore Vic-20 and 64 back in the day, but my memory is a little rusty. ;^) From memory, the 6502 used an interrupt disable flag in its status register to stop IRQs from triggering. This is set by default, so an IRQ won't trigger until the program has set up an IRQ handler and then reset the disable bit. When the handler is called, it first sets the disable bit, to stop further triggering, and when the handler is finished is resets the disable bit. I'm sure there's a better way of doing things, but this is how I remember the 6502 dealing with interrupts.
Are you sure? yes | no
Using an IRQ mask might be an option. I don't know if it's the best one. My state machine is giving me the behavior I want, but it's a lot of logic to implement. I'm trying to figure out if there's a more efficient way to get the same behavior.
Are you sure? yes | no
Amos is right regarding the 6502’s I-flag. This interrupt structure is fairly efficient in TTL, so you might look at it. Here’s one possible approach:
IRQ is level-sensitive. You can sample the input pin mid-cycle (run it into the D input of an “IRQ-PENDING” flip-flop clocked by the falling-edge of the clock). On every FetchOpcode, if an IRQ is pending AND interrupts are enabled (the I-Flag is low), then replace the opcode with a $00 (BRK), and place it in the IR as usual. (This is conveniently done if your IR register is a 74HC273 with a /CLR input. You will also want to inhibit the normal Increment-PC, so the replaced opcode will be re-read once the interrupt completes). The BRK instruction then executes: it saves state, sets the I-Flag, clears the IRQ-pending flip-flop, and jumps through the interrupt vector. That’s it.
If you are using microcode, IRQ only needs two flip-flops (one to sample IRQ and one for the I-Flag). NMI is edge-sensitives so you can run it directly into the CLK input of a flip-flop to record an NMI-PENDING (although you might also want to sample it on the clock edge, in which case you need two flip-flops). RESET is the same, except that you invert the input pin. The same BRK instruction is executed for all interrupts. It simply selects the low-byte of the jump vector based on which interrupts are pending. Hope that helps.
Are you sure? yes | no
@Drass , that is very helpful, and gives me a lot to think about. I am using 00 as reset. Since all my reset inputs for my registers counters are tied to it. In your example how do you differentiate between a reset and a IRQ. My reset routine initializes the stack pointer and program counter.
Are you sure? yes | no
You can differentiate between various sources by setting the address bits of the jump appropriately. For each interrupt source, allocate 8 or 16 bytes of code in an array. Thus set PC to <IRQnr> followed by 3 or 4 cleared bits.
The few bytes give enough time to act immediately on the source of interruption and eventually jump to appropriate less urgent handling code.
Are you sure? yes | no