P4. SystemC Tutorial - OR Gate with Testbench
Part 3 introduced one input, one output, one process. This part adds two new ideas: multiple inputs in the sensitivity list, and a directed testbench that walks the truth table. Both translate directly to how UVM monitors and directed tests work later — the OR gate is just the smallest possible vehicle for the pattern.
Implementation
#include "systemc.h"
// OR Gate Module
SC_MODULE(or_gate) {
sc_in<bool> a, b; // Two input ports
sc_out<bool> c; // Output port
void or_gate_p() {
c.write(a.read() | b.read());
}
SC_CTOR(or_gate) {
SC_METHOD(or_gate_p);
sensitive << a << b; // Trigger on either input
}
};
int sc_main(int argc, char* argv[]) {
sc_signal<bool> a, b, c;
or_gate or1("or_gate_or1");
or1.a(a);
or1.b(b);
or1.c(c);
sc_trace_file* tf = sc_create_vcd_trace_file("or_gate");
tf->set_time_unit(1, SC_NS);
sc_trace(tf, a, "a");
sc_trace(tf, b, "b");
sc_trace(tf, c, "c");
// Walk the truth table — each combination held for 1 ns
a = 0; b = 0; sc_start(1.0, SC_NS);
a = 0; b = 1; sc_start(1.0, SC_NS);
a = 1; b = 0; sc_start(1.0, SC_NS);
a = 1; b = 1; sc_start(1.0, SC_NS);
sc_stop();
sc_close_vcd_trace_file(tf);
cout << "Finished at time " << sc_time_stamp() << endl;
return 0;
}
Truth Table
| A | B | C (A|B) |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 1 |
Expected Waveform
Open or_gate.vcd in GTKWave to confirm. c is high whenever either a or b is high.
Why exhaustive testing here?
For a 2-input combinational gate the input space is 4 values — checkable in microseconds. As soon as the design has state or wider buses, exhaustive enumeration explodes. That's where the next layer of techniques comes in:
- Constrained random stimulus (UVM sequences) — let the simulator pick legal inputs
- Functional coverage — measure which combinations you actually hit
- Self-checking testbenches — assert the output instead of eyeballing waveforms
A self-checking version of this OR gate is a one-line addition. Inside sc_main after each sc_start:
sc_assert(c.read() == (a.read() | b.read()));
If the gate is ever wrong, the simulation aborts with a file/line. That's the same idea SystemVerilog assertions and UVM scoreboards generalize to bus protocols.
Viewing the VCD
sudo apt install gtkwave # one-time
gtkwave or_gate.vcd & # opens the GUI
In GTKWave, drag a, b, and c from the SST panel into the Signals pane. You should see four 1ns segments matching the truth table.
Common Pitfalls
- Sensitivity list missing one input. Writing
sensitive << a;alone makes the process oblivious tobchanges — output looks stale half the time. Always list every input the process reads. - Forgetting
sc_stop(). Without it, the simulation runs until the kernel decides nothing more will happen, which can leave the trace file truncated on some platforms. - Using
=onsc_signal. Inside processes, write with.write()and read with.read(). The shorthanda = 0;insc_mainworks only becausesc_signaloverloadsoperator=for the testbench context. - Two zero-width
sc_startcalls back-to-back. Both happen in the same delta cycle — only the last assignment shows up in the trace.
Comments (0)
Leave a Comment