0
\$\begingroup\$

I am working on a MIPS CPU for an FPGA - this is mostly a personal project to understand FPGA's.

I have a 5 stage pipeline CPU implementation working correctly when run on iSim, however when I run it directly on the hardware (Spartan 6) I get a different result.

The test program I have is simple:

load 0x128 into reg[1]   
nop*
load 0x160 into reg[2]
nop*
add reg[1] to reg[2]
assert "finished" flag

when I run this in iSim, I get the correct result in reg[2] (0x288) however, when I run the program on the FPGA I get the result 0x3b0 - it appears that the final instruction is running multiple tiems

The nop instructions are present to force a cache miss during execution, and this is what causes the problem - without these the result is correct.

What I think is happening is that I assert a "stall" flag at the positive edge of the clock cycle - and something else that runs at the positive edge relies on the presence/absence of this flag. iSim by chance runs correctly (due to the arbitrary order in which it executes the simulation of always blocks) however the FPGA fails as the stall change is not available until the negative edge.

I have already scoured my verilog implementation to find where this is - and am still looking. My question is: how can I force iSim to expose this error?

\$\endgroup\$
  • \$\begingroup\$ Ah if only we could always easily force problems we see on the board with the FPGA to happen in simulation :) Things would be much easier. Quick question is this a synchronous design, everything running on one clock cycle? How do you handle reset? Did you check your timing reports after synthesis, after place and route? Have you considered using chipscope or Xilinx's integrated logic analyzer like tools to see what's happening inside your design in the FPGA? Or you could just bring signals out to pins and use a real logic analyzer if you have one. \$\endgroup\$ – Some Hardware Guy Jun 17 '15 at 2:47
  • \$\begingroup\$ @SomeHardwareGuy - I gather from your tone that this is a common problem? For some reason I assumed the software was more advanced :( In regards to synchronous - I believe so, at each stage I read in data (from the previous stage) on the positive edge, and output data at the negative edge. My timing reports show no errors - I have a reasonable margin of error on the frequency (though dont know what else to check there) I can't run simulation after synthesis - there is an issue with the RAM, this doesnt affect the hardware, but in post synth simulation I never get the "calib_done" flag \$\endgroup\$ – Zack Newsham Jun 17 '15 at 2:50
  • \$\begingroup\$ I havent been able to find documentation on how to setup chipscope. I have brought some logic out, I have 3 LED's that show whether execution has a) started (after copying the program to RAM) b) finished (after writing to the "zero" register) and c) the result is correct (result is stored in r2, so I just check that against a constant) I also implemented a basic UART system, right now it just transmits the result on a button press \$\endgroup\$ – Zack Newsham Jun 17 '15 at 2:51
  • \$\begingroup\$ Well really you've got two ways of fighting it, either think of ways your test bench doesn't represent real life and try to change it so it does, or add instrumentation like chipscope and try to catch it on the board. Since you say you're just starting with FPGA's I was tempted to suggest going right to chipscope because I think you might see some things there that maybe you don't realize are happening. Just a guess. Given the choice I'd rather be able to see a problem in simulation though. \$\endgroup\$ – Some Hardware Guy Jun 17 '15 at 2:56
  • \$\begingroup\$ What kind of ram are we talking you mean FPGA internal ram? \$\endgroup\$ – Some Hardware Guy Jun 17 '15 at 2:56
0
\$\begingroup\$

The issue was caused by RAMB16WER reading data on the positive edge. My fetch code was changing these signals on the positive edge too. Moving this code to the negative always block fixed it.

Its odd that it worked up to a certain point on the device, and that it worked fully on iSim, but I guess this is due to the way iSim executes the always blocks.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.