When we simulate (VHDL) RTL designs in a simulation tool like ModelSim or ActiveHDL e.t.c, we can have a complete visibility of all signals and variables in the design. This goes a great deal in aiding debug in simulation. Certain things like function calls and procedure calls are not easy to debug though, we would have to set breakpoints for that.

Now assume I have a soft-processor inside the design like a Nios II processor or something else which has a program written in high level language. This program will have its own variables and state-machine code implemented in a high level programming language like C. If I carry out RTL simulation, I would be able to see what is happening at the interface of the processor. However, if I want to be able to debug the system, I should be able to see into the software of the processor in real-time as the simulation progresses.

How is this problem handled in the real world? How would such systems be debugged? If I want to fix an error in the code, I would have to have a command-line method to compile the code, generate hex and put it in a place where the simulation tool can access it everytime.

  • 1
    \$\begingroup\$ Hardware-in-the-loop/Software-in-the-loop are your terms. \$\endgroup\$ – Eugene Sh. Oct 7 '20 at 16:06
  • \$\begingroup\$ Please elaborate, I have not had to simulate a mixed system of this type yet but will have to do it soon it seems. \$\endgroup\$ – Quantum0xE7 Oct 7 '20 at 16:22
  • \$\begingroup\$ this is just an observation from a non-expert point of view ... maybe you need to treat the soft-processor as a component, basically a black box with specified inputs, outputs and behavior ... if the actual behavior, or some input/output, does not match the specification, then debug the soft-processor separately to bring it in line with the specification \$\endgroup\$ – jsotola Oct 7 '20 at 16:28
  • \$\begingroup\$ The soft-processor needs stimulus from outside it to complete its tasks. It will be easier to find what the actual problem is if the stimulus can be applied onto it in real-time in simulation, and we can observe how the code execution proceeds. One problem here is that the code gets complete into machine language which will not easily tally with the high level programming language code. I mean, we might for example be able to see where the address counter is, and what the state of the registers of the processor is, but this may not be very helpful. \$\endgroup\$ – Quantum0xE7 Oct 7 '20 at 16:38
  • \$\begingroup\$ ironic how often C is called a "high level" language and VHDL isn't. The reverse is true despite the low level purposes VHDL is used for. Vivado offers "cosimulation" but not for NIOS. In practice I tend to prove the hardware in simulation, then debug the software on actual known-(mostly)-good hardware, post synthesis. There are approaches using hardware simulation and C running on the simulation host (using VHPI, or VHPIdirect). This is probably easiest when the same compiler is used for both VHDL and C, for example GHDL using gcc or LLVM. \$\endgroup\$ – Brian Drummond Oct 7 '20 at 17:16

There is no concept of hardware software co-simulation on a general purpose, average CPU, since the CPU does not have the processing power to emulate hardware real-time in a fashion that is timing-accurate. You want to emulate hardware in a fashion that is timing-accurate since you want the software to run on the hardware and be able to debug it a timing-accurate fashion.

A more appropriate term would be Hardware-Software Co-Verification to describe the process of verifying that the software correctly runs on the hardware.

In practice, 3 options are used for hardware-software co-verification:

  1. Emulation: Specialised hardware called an emulator or emulation-box is used. The software runs on the hardware using an emulation box. Emulators usually provide high visibility of the system, so you can step through the C program and debug it.

  2. Hardware co-simulation using an FPGA: This is also known as Hardware in the loop simulation. It is supported by some FPGA vendors like Xilinx. The basic idea is that instead of simulating hardware, you synthesize it on an FPGA. The debugging of the system can be done by connecting the FPGA to a CPU using PCIe. The FPGA communicates with the CPU in real time.

  3. Use a Transaction-Level or functional Model: The idea is "Things which are equal to the same thing are equal to one another." A transaction-level model is at a higher abstraction than RTL, so it can be simulated on a CPU much faster than RTL. A transaction level model can be functional, cycle-accurate etc. To do hardware software co-verification, first verify the working of the software by running it on the Transaction-Level model. This can be done on a CPU, since it is not timing accurate. Then verify the validity of the transaction-level model by co-simulating it with the HDL simulator, using DPI for SystemVerilog or VHPI for VHDL. The transaction-level model can be written in C, C++ or SystemC. Alternatively gem5 or QEMU can also be used to co-simulate with the RTL model.


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.