We are using a Stratix processor with NIOS2 (Altera University Program DE4 development board with a Stratix Ep4SGX230KF40C1 processor). We have been plagued with problems where small changes in code will suddenly make the code lock up or not work in some fairly unpredictable way. Sometimes the same code will only work half of the time (we have to re-download the .sof file and it will then work). We are using the NIOS2 terminal to download both .sof and .elf files, and thus we do not have many ways to debug or understand what is going on.So our main question is: when code works erratically, what are the most likely explanations? Our next question is: how does one debug code on this level, when multiple components are talking to each other and the results are inconsistent? (The first question is probably less vague) TimeQuest tells us there are unconstrained paths, but otherwise gives us no warnings or errors. More details on our code: We are writing code to send data from the FPGA to the NIOS2 processor and then through high speed Ethernet.
How many unconstrained paths? Because if you end up with entire unconstrained clock domains, it's possible that a big part of your design isn't analysed by Timequest at all, and you could have timing problems. Timing problems are one of the most common causes of erratic behaviours.At least try to constrain all your I/O and clocks, and check in Timequest's clocks report that they are all there, with the correct frequencies.
To follow up on this, we found that we had been using the NIOS2/f processor when we were instructed to use the NIOS2/s. The NIOS2/f has a Data Master Data Cache, and the presence of this seemed to be causing memory issues. We are not entirely sure what was going on, but no issues have presented themselves since removing this cache.
Do you use the standard drivers from Altera for Ethernet or do you use your own? Do you have any other DMA in your system, or another hardware component that can access memory directly? In that case care must be taken when you have a data cache. You must flush the data cache before a component reads the memory, and you must invalidate after a component writes to it. The Altera TSE drivers do this.