Programmable Devices
CPLDs, FPGAs, SoC FPGAs, Configuration, and Transceivers
21017 Discussions

Why is my nios custom instruction executing twice?

JLiew
Beginner
768 Views

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.

0 Kudos
4 Replies
Ahmed_H_Intel1
Employee
536 Views

Hi,

I see the VHDL code is totally correct. But I am wondering how you are using this C-code function:  Can you please send to me more details about this function?

unsigned com_bus_simple(unsigned dataa, unsigned datab)

{

unsigned readdata;

readdata = (unsigned)ALT_CI_NIOS_FPGA_COM_0(dataa, datab);

return readdata;

}

 

 

Plus, Can you please share more details about the connection to/from NIOS II?

Regards,

 

0 Kudos
JLiew
Beginner
536 Views

Hello,

To be honest, I have since rewritten a completely new custom instruction (now an extended one) with the express purpose to not do a double send, and now it is working.

I'll append both the old and new VHDL files and old and new examples of drivers that use it. Because, while I have a working instruction now, I still have no clue why the old one didn't work.

I've put them in a zip, because, apparently I can only add one file per post?

 

What would you want to know about the connection to and from the NIOS II? You mean how it is implemented in a FPGA entity?

 

Thank you

0 Kudos
Ahmed_H_Intel1
Employee
536 Views

Thanks for the shared files, I will check them and will let you know.

0 Kudos
Ahmed_H_Intel1
Employee
536 Views

Hi,

I've opened an internal ticket for this issue, BTW the shared files don't show the main cause, any way I shared this with our the engineering team. The code in the post looks simple and clear (no issue I see).

Regards,

 

 

0 Kudos
Reply