One thing that the 8259 does is use a command/data interface instead of a full memory mapped interface. This means it takes up 2 locations in memory instead of 4+.
In addition to this, our design requires more and more address space if we want to support more interrupts. For example, right now we require 8 bits for the enable, type, and EOI. If in the future we want to support 16 interrupts, now we need 16 bits for each. Our address space just went from 4 to 7.
Also, the 8259 only takes a single command for EOI. Instead of specifying which interrupt is over.
I think you should consider something like that, as it is more expandable.
If we give it 8 bits of command and 8 bits of data, that would let it be expandable all the way to 256 interrupts while still only occupying 2 addresses in memory.
So instead of having those 4 registers, we could instead have 2, and have multiple commands
Each command should be capable of writing to a register. We need to be able to support 256 interrupts, which is 8 registers. If we allocate 3 bits of the commands to act as an address and then other bits can act as the actual command.
So how about this for the preliminary command set
Byte
Command
Description
0x
IRQ
read only register which provides current interrupt
1x
EN
read/write to the enable register
2x
MODE
read/write to the mode register
3x
EOI
write only register which clears stored interrupts
Worth noting that we only have 3 bits for the command, so the new table looks like this
Byte
Command
Description
0x
IRQ
read only register which provides current interrupt
2x
EN
read/write to the enable register
4x
MODE
read/write to the mode register
FF
EOI
Sends EOI and clears the current IRQ
Because of the way address decoding works, we will waste 32 commands on EOI unless we specifically count them out. I will say that the EOI command has to be FF still for now, but you won't be able to use it for more register reads. Thats okay though cause there are 4 more that you can use.
Also instead of having a data_sel_mux for the data inputs, we can select the write enables instead, and just share the common data bus wires across all the registers.
at the moment, we only support high level triggered interrupts, or rising edge interrupts. This is an FPGA, so just invert the signal if yours is the opposite.
Level triggered is easy: If its 1, then trigger the interrupt
For level triggered, we only trigger it if the previous value is 0. so essentially, the old bit has to be 0, and the new bit has to be 1. We can just invert the old bit and & it with the new bit.
So what we can do is take the old value, invert it, then | it with the type register (where a 1 means level triggered). Then, if it is level triggered the interrupt will always be availabile, but if it is edge triggered then it will only be availabile if the previous value was 0.
This is kind of a moot point anyway since you need to increment the address, which is stored in the command anyway. Just to make it easier, I will say that the command will latch and there will be no state machine or anything. All the command does is control the muxes.
Right now we have a single EOI bit and can therefore only support clearing 1 interrupt as a time. If we want to support e.g. nested interrupts then we will have to keep track of which is the active interrupt, or something like that.
There is a bug in the testbench, the level triggered interrupts still don't work.
The logic is a bit flawed. If we are comparing the new interupt value to the old one, then if we clear the old one it will look like we need a new interrupt. What we need is a shadow register that always stores all the inputs for 1 clock cycle, and only if that is different do we trigger the edge interrupt.
We switched the commands to use 5 bytes for the address instead of 4, but then we still used the upper 4 bits of the command for the command code. So now instead of 0, 1, 2, FF, the command codes are 0, 2, 4, FF.
We want to do a similar thing to the standalone tb, which is make sure IRQs work and we want to make sure that the cpu can actually program the registers and read the IRQ value.