Currently trying to simulate a NOEL-V release 2025.1-b4296 core with Modelsim. It works for a good portion of simulation, but then break with the following error:
Failure: X in data going to cache
And the source of it is the process ‘comb’ of iunv.vhd file at the line 13574.
It does appear after a series of communication with RAM and ROM through ‘srctrl’ entity, but those show that they’ve given the AHB bus only actual values with no ‘U‘ stated signals in them. Funny enough, when synthesized with Quartus and loaded into an FPGA it runs smoothly and without errors. Concluding, I’m thinking there’s something going on with data transfer, but I can’t catched it from looking at the top level alone.
I’m already refering to the ‘r‘ register from the ‘iunv’ file to track the changes code does to the core, but I would also love to track ‘xn’ registers values and currently executing opcode in order to debug what’s exactly wrong going on with the simulation. Those that I’ve found are labeled as ‘variable‘ types, so I can’t check out their dynamic values.
What signals and register can I track in Modelsim from ‘iunv‘ or other cpu entities to debug this? Ideally, fields smilliar to what can be pulled out with JTAG would be preferred.
Is it possible that you are reading some register that has not been initialised? Depending on configuration, registers may be in RAM and then not possible to zero at reset. FPGA:s normally do start with RAM initialised to zero, which could be why it works fine then.
Anyway, it should be possible to trace what data is going towards cache in your case. The assert is looking at me_stdata, which comes from data_out in the call to stdata_unit(). As it happens, that procedure only has the r signal as input.
stdata_unit() is responsible for selecting between incoming data from register file read or something that is forwarded from earlier instructions in the pipeline. While it would be possible to look at the r signal in Modelsim to figure out which of the ten or so possible data sources are selected when you get the X, that is probably not the easiest way if you are unfamiliar with our pipeline. Rather, I would suggest that you insert report statements in each branch of the various if-statements.
Since the error apparently happens quickly in your case, the extra debug output should not be too bad. Otherwise, you could in various ways make the reports not start until closer to the expected error. Anyway, the last such report you see before the assert should indicate where from you get the X.
With some luck, the report statements combined with the content of the r signal at assert should point you towards what’s going wrong.
If needed, it would also be possible to have a breakpoint in stdata_unit(), to enable stepping through the code. But you would probably want to start with the report statements mentioned to be able to figure out a good way to do that.
By the way, Modelsim is capable of showing you variables. It just isn’t very obvious how to go about it.
Thanks for your reply and advice. I get to find what was causing the error. But still, struggling to find the solution.
First of all, and I think that’s the funniest thing, switching the assert level from failure to warning didn’t bring any errors and CPU haven’t grind to a halt. I suppose that correlates with synthesized core running okay too. Perhaps there’s errors crawling inside the FPGA too, but it manages to handle them.
Second, what was causing the errors in the first place. They all arise in ‘sw‘ instructions. But not all of them, but in very specific cases. I’m not sure if that’s correct behaviour, but I found that when encountering ‘jr ra‘ instruction in any subprogram, core would still walk 3 additional PC addresses. I assume core needs time to prepare before the jump, but at the same time, branching instructions don’t need those 3 cycles and execute the jump in the very first cycle. I also assume those 3 instructions are ignored, because when landing on ‘sw‘ one, RAM never received any writing signals.
By the looks of thing, errors arises when only when one subprogram ends, PC takes additional 3 steps and lands in the next subprogram that was in memory map (first oscillogram).
Worth noting, that I run an experiment. I was using XPACK GCC code compiler the entire time. I decided to try Gaisler’s edited GCC for compiling. The only difference in code was addition of one more address separating subprograms. That DID resolve most of the problems as PC never landed on ‘sw‘ instruction. Yet, some of the errors remained.
The questions I’m most interested in are:
Can you explain this PC behaviour with ‘jr ra‘ instructions. And do you have any ideas or explanaition why it was causing problems with ‘sw‘ instructions?
Where can I learn more about NOEL’s ALU flow? Haven’t found anything so far
Update: …turns out general purpose registers are not initializerd 0 after reset signal. Loading anything into them at the start of the simulations solved the remaining problems.