Forum Discussion
Integrating a custom component in SOPC [+IRQ]
Hello i made a custom component and integrated it on SOPC, my problem is the IRQ signal... i am using Linux in my NIOS2 and i need to make a device driver to control my custom component, however i have no control signals like :
-enable_irq -irq_reg signal to clear when a irq happens and etc. The PIO has more signals than the IRQ Avalon interface... When i export my IRQ as a conduit in my custom component and then import it as an input std_logic port /PIO to the NIOS2 i have all these control registers... any suggestions?12 Replies
- Altera_Forum
Honored Contributor
Those functionalities (IRQ enable and clear) need to be done in your custom component, using additional registers. What I usually do in a custom component is to create two registers: a status register and a mask register.
Each bit in the status register represents an event that can trigger an interrupt. When the corresponding event occurs, the bit is set to '1' inside the component. The software can then read this status register to know what happened, and clear the status bits to say it has handled the event (write '1' to a bit to clear it). The mask register can be used to enable/disable the IRQ, and decide what events should trigger an interrupt. What I do is an AND between the mask and the status register, and activate the IRQ signal to the CPU if the result is non-zero. This is a pretty standard way of handling interrupts, but it needs to be done in each individual custom component. - Altera_Forum
Honored Contributor
Thanks for your help Daixiwen.
- Altera_Forum
Honored Contributor
As i mentioned in a private msg to you.
Does anybody have a template to do this? My read_en signal happens when
do i need a irq_en signal too, that says when i can send an irq?read_en <= '1' when ((chipselect = '1') and (read = '1') and (byteenable = "1111")) else '0'; - Altera_Forum
Honored Contributor
I don't know how well it would integrate in your code but this is my general template for an Avalon memory mapped slave with IRQ:
And outside the process (but it could be inside too, it would add one cycle delay)--! Main process Main: process(csi_Mem_Reset, csi_Mem_Clk) is begin if(csi_Mem_Reset = '1') then -- Initialize signals StatusRegister <= (others => '0'); StatusInterruptMask <= (others => '0'); elsif(rising_edge(csi_Mem_Clk)) then -- Avalon bus read if (avs_Conf_Read = '1') then case avs_Conf_Address is when AddressStatus => ConfigReadData <= StatusRegister; when AddressInterruptMask => ConfigReadData <= StatusInterruptMask; when others => report "Bad address for read operation" severity error; end case; -- address end if; -- read -- Avalon bus write if (avs_Conf_Write = '1') then case avs_Conf_Address is when AddressStatus => -- clear selected bits in the status register StatusRegister <= StatusRegister and (not avs_Conf_WriteData); when AddressInterruptMask => StatusInterruptMask <= avs_Conf_WriteData; when others => report "Bad address for write operation" severity error; end case; -- address end if; -- write -- update the status register when an event is detected if (something) then StatusRegister(n) <= '1'; end if; end if; -- clock cycle end process;
I hope this helps-- IRQ generation ins_Interrupt_Irq <= '0' when (unsigned(StatusRegister and StatusInterruptMask) = 0) else '1'; - Altera_Forum
Honored Contributor
Thank you so much
if (avs_Conf_Read = '1') referes to which avalon signal? also those others avs signals... since you are not using the normal nomenclature of the avalon interface i am kinda lost hehehe :P The avalon interface is the follow
also dont you need to let the IRQ on 1 by X cycles of clock for NIOS2 to see it? I would like to know X numberclk : in std_logic; reset_n : in std_logic; address : in std_logic_vector(3 downto 0); byteenable : in std_logic_vector(3 downto 0); writedata : in std_logic_vector(31 downto 0); write : in std_logic; readdata : out std_logic_vector(31 downto 0); irq : out std_logic; read : in std_logic; chipselect : in std_logic; - Altera_Forum
Honored Contributor
This is the read signal, and I'm using the nomenclature defined by Altera in the sopc manual (http://www.altera.com/literature/ug/ug_sopc_builder.pdf) (page 6-4). The only exception is the signal ConfigReadData which is connected to avs_Conf_ReadData outside the process.
Yes you need to keep IRQ on until the ISR routine treats the interrupt and clears it. With this architecture the IRQ signal will stay to 1 until the StatusRegister vector is cleared by software. - Altera_Forum
Honored Contributor
Okay but my Linux recieves an IRQ from my SOPC custom component only when a pulse is detected right? If i keep my signal (irq) at one my linux won't see it.. am i wrong?
- Altera_Forum
Honored Contributor
The way this works is: [list][*]The software runs normaly[*]A hardware component detects an event that should trigger an interrupt and raise the IRQ line[*]The CPU finishes processing the current instruction, and jumps to the ISR[*]The ISR reads the hardware status, acts accordingly, and returns[*]The CPU continues executing the application[/list]
I'm simplifying a bit here, assuming you use the standard interrupt controller included in the Nios, and am not talking about the context save, but the essential is here. There are two requirements for the IRQ signal:[list][*]It must be at '1' long enough for the CPU to see it, especially if it is executing a long instruction. I don't know how the Nios II processes the IRQ signal and during what cycle it reads it, but to be sure the IRQ signal should be at '1' at least until the CPU enters the ISR[*]It must be put back at '0' before the CPU exits the ISR, or else it will enter the interrupt mode again and re-execune the ISR[/list] An easy way to do this is to hold the IRQ signal at '1' until you are sure that the software acknowledged it, by using a register it must write to from the ISR in order to clear the IRQ status. - Altera_Forum
Honored Contributor
Daixiwen i understand now, thank you so much for your help and your detailed explanation.
Just a final question.. in this part of the code
status register is never going to be one right? Only if it resets at one, does it?when AddressStatus => -- clear selected bits in the status register StatusRegister <= StatusRegister and (not avs_Conf_WriteData); - Altera_Forum
Honored Contributor
Daixiwen i understand now, thank you so much for your help and your detailed explanation.
Just a final question.. in this part of the code ;;;;;;;;;;; never mind, i already saw where you assigned stats register to one