Why is my nios custom instruction executing twice?
I have a NIOS2 custom instruction written in VHDL to communicate with my self-made FPGA components. It takes dataa and datab from the custom instruction and turns it into a communication bus of sorts with an address and a data line. Both are high for exactly 1 clock cycle, and the result is read back from the read 2 cycles later. Up to now, this has worked very well, both reading and writing data with this bus worked fine. However, I now have a entity that needs to be written to an exact number of times. (it needs a specific number of data bytes) Here things go very wrong. Somehow, each write action is processed twice, so the data get's all messed up.
When simulating the custom instruction with a testbench in modelsim, it does exactly what I expect it to do. Same when I use the custom instruction as part of a larger testbench system. I've written the testbench such that the waveform of the data into the custom instruction matches exactly with the waveform in the NIOS2 custom instruction manual.
However, I've confirmed with tests in system that each write action is somehow active for 2 clock cycles. I've done this by creating a adder that adds 1 to a register each clock cycle it's address matches. That is linked to the LEDs. This shows that with each write actions the register goes up by 2.
I can't find an explanation.
elsif rising_edge(clk) then
COM_Address <= (others => '0'); --default
COM_CPU_WRITE_DATA <= (others => '0'); --default
if clk_en = '1' then
case state is
when s_idle =>
if start = '1' then -- if the cpu says to start, immediately send address and data, else keep idle.
result <= (others => '0');
done <= '0';
COM_Address <= dataa(15 downto 0); -- send out the address and data provided by the cpu
COM_CPU_WRITE_DATA <= datab;
state <= s_wait_one;
else
state <= s_idle;
result <= (others => '0');
done <= '0';
COM_Address <= (others => '0');
COM_CPU_WRITE_DATA <= (others => '0');
end if;
when s_wait_one => -- wait one tick, to allow the slave to put data on the read lines.
result <= (others => '0');
done <= '0';
COM_Address <= (others => '0'); --Address and data can be put back to zeros. Only wait for reading, writing is done by now.
COM_CPU_WRITE_DATA <= (others => '0');
state <= s_reading_done;
This is part of the VHDL code from the nios custom instruction. As you can see, the COM_Address and COM_CPU_WRITE_DATA lines are only high for a single clock cycle. I've even pulled them to 0's as the default each clock cycle.
unsigned com_bus_simple(unsigned dataa, unsigned datab)
{
unsigned readdata;
readdata = (unsigned)ALT_CI_NIOS_FPGA_COM_0(dataa, datab);
return readdata;
}
This is the function used to do the write (and or read) actions. This is wrapped in multiple layers of functions for each entity driver, but at the basics, this the what writes to the communication bus in the FPGA
There are no error messages, it compiles and simulates just fine, except that while I expect (and simulate) the address line to be high for 1 clock cycle, it's high for two, somehow.