Skip to content

Example: Debug Probes

Julian Kemmerer edited this page Feb 20, 2025 · 8 revisions

wave

Say you are describing some hardware an ethernet demo or maybe an old DDR3 mem test...you have a state machine and some related signals (ex. state, address, data) you want to probe for debug in hardware testing.

Your existing option is something like a MARK_DEBUG attribute in your HDL + going through your manufacturer specific 'chipscope/signal tap' flow - which I have not had much fun with personally - annoying every time I need to use it.

Otherwise, doing this without manufacturer support, maybe you are lucky enough to have set up some kind of debug structs/record ports where you easily can route debug signals around your design hierarchy for some existing debug ports you've planned up. Or worse you are adding new ports and connections all over your design hierarchy to get to these signals - boo.

Here is why this is easy in PipelineC:

To start, look to the ability to connect point-to-point wires from one point in the design hierarchy to other. With a single line of code, a design can connect a point to point wire from the signal you want to capture to some debug probe module/port (the compiler wires up and down across whatever design hierarchy exists for you).

my_debug_probe = test_data;

This lets you write a stand alone 'library module' for capture of debug probes. Each probe is exposed as a global point to point wire from the probes module in uart_probes.c to wherever the user uses it. Here is how to 'use the library':

  1. Define a struct data type to use for the probe. Ex. my_debug_probe_t in a header file and include it in your PipelineC code.
  2. Include uart_probes.c in the hardware you want to debug.
    // Name and specify probe number
    #define probe0 my_debug_probe
    #include "debug_probes/uart_probes.c"
  3. Assign to the my_debug_probe debug probe signal as desired to capture your intended data.
  4. Include #define probe0 my_debug_probe and your my_debug_probe_t header in the software debug_probes.c program and recompile.
  5. Run debug_probes and/or plot_probes.py programs to view your debug probe values.

So what does this uart_probes.c library module do for you? It samples your debug probe and streams out the data to a host pc (over UART for now). Here is a high level diagram of whats going on:

diagram

Ok so this lets you get a one time capture of my_debug_probe_t of data. Thats neat. But combined with a bit more logic it's pretty powerful:

Say your my_debug_probe_t is defined like so:

#define DEBUG_SAMPLES 32
typedef struct my_debug_probe_t
{
  mem_test_state_t state[DEBUG_SAMPLES];
  uint32_t test_addr[DEBUG_SAMPLES];
  uint8_t test_data[DEBUG_SAMPLES];
}my_debug_probe_t;

A small FSM is used to shift new data into those arrays inside the my_debug_probe_t reg each clock cycle, you can capture samples over time (32 clocks here), and then all at once sample that entire debug probe.

static my_debug_probe_t debug_shift_reg;
// shift new data into arrays each cycle
// ... 
// then connect to probe
probe0 = debug_shift_reg;

PipelineC comes with code generation support so the packing of my_debug_probe_t to and from bytes is handled for you. That makes writing the supporting software very easy: write to the device to select the probe to read, and then read back the probe bytes. Conversion to and from structs is handled for you by generated code.

The simple debug_probes.c is such a little C program and plot_probes.py is a helper script that takes the probes printout and starts up GTKWave to view the probe data (see image at top of post). Let's you do a one liner capture and show waveforms:

./debug_probes 0 | plot_probes.py

A final note is that this 'capture logic' of shifting sampled data into registers over time - it can be whatever you want. Want to capture data only when your FSM changes state? Every 3rd cycle? Into block ram / fifos instead of shift regs? 'Advanced trigger and capture settings' you might configure in a manufacturer tool are just whatever logic you describe to store samples.

Clone this wiki locally