3.5.5 · HinglishHDL & Digital Design Flow

Testbenches and simulation

2,634 words12 min readRead in English

3.5.5 · Hardware › HDL & Digital Design Flow


WHY yeh cheez exist karti hai?


WHAT — pieces kya hain?


HOW — scratch se kaise banate hain

Chaliye ek TB ko step by step banate hain ek DUT ke liye, yeh sochte hue ki har line kyun zaruri hai.

Maan lo humara DUT ek 4-bit synchronous counter hai:

module counter(input clk, input rst, output reg [3:0] q);
  always @(posedge clk)
    if (rst) q <= 0; else q <= q + 1;
endmodule

Step 1 — bina ports ka ek module.

module tb;

Kyun? Ek TB hierarchy ka top hota hai; uske upar kuch nahi hota jo ports se wire kiya ja sake.

Step 2 — TB-side signals declare karo.

  reg clk, rst;      // hum inhe DRIVE karte hain → reg
  wire [3:0] q;      // DUT ise drive karta hai → wire

Kyun? clk aur rst TB ke DUT mein jaane wale outputs hain, isliye TB ko unhe hold/assign karna padta hai → reg. q DUT drive karta hai → wire.

Step 3 — DUT instantiate karo (rig ko test wali cheez se connect karo).

  counter dut(.clk(clk), .rst(rst), .q(q));

Kyun? Named port connection (.port(signal)) positional se zyada safe hai — order change hone par silently mis-wire nahi hoga.

Step 4 — clock generate karo.

  initial clk = 0;
  always #5 clk = ~clk;   // period = 10 time units, 100 MHz agar 1 unit = 1 ns

Kyun? Sequential logic ko posedge chahiye. Har 5 units mein toggle karne se 10-unit period milta hai. always hamesha chalta rehta hai, jo ek clock ke liye zarurihai.

Step 5 — stimulus + self-checking.

  integer expected;
  initial begin
    rst = 1; expected = 0;
    @(posedge clk); #1;          // reset ko ek cycle ke liye apply karo
    rst = 0;
    repeat (20) begin
      @(posedge clk); #1;        // flip-flop update hone ka wait karo, phir check karo
      expected = expected + 1;
      if (q !== expected[3:0])
        $error("t=\%0t: q=\%0d expected=\%0d",$time, q, expected[3:0]);
    end
    $display("TEST DONE");
    $finish;                     // (warna infinite) simulation band karo
  end

@(posedge clk) ke baad #1 kyun? Exact clock edge pe flip-flop ki nayi value same delta step mein settle nahi hui hoti — edge ke thodi der baad sampling karna ek race condition se bachata hai aur stable value padhta hai. !== kyun na ki !=? !== x/z (unknown/high-Z) ko bhi pakadta hai, jo != ambiguous maanta hai.

Step 6 — waveform dump (aankho ke liye Dual Coding).

  initial begin
    $dumpfile("wave.vcd");
    $dumpvars(0, tb);   // tb ke neeche sab kuch record karo
  end

Kyun? Jab self-check fail ho, VCD waveform aapko woh timing relationship dikhata hai jo tooti.

Figure — Testbenches and simulation

Event-driven simulation model (asli engine)


Blocking (=) vs non-blocking (<=) — ek testbench trap


Testbenches ke types (yeh names yaad rakho)


Worked example 2 — combinational DUT (ek 2-input AND gate), exhaustive TB

DUT: module and2(input a,b, output y); assign y = a & b; endmodule

module tb;
  reg a, b; wire y;
  and2 dut(.a(a), .b(b), .y(y));
  integer i;
  initial begin
    for (i = 0; i < 4; i = i + 1) begin
      {a, b} = i[1:0];   // Kyun? concatenation dono inputs ko ek counter se drive karta hai
      #10;               // Kyun? check karne se pehle combinational output settle hone do
      if (y !== (a & b))
        $error("a=%b b=%b y=%b", a, b, y);
    end
    $display("AND2 OK"); $finish;
  end
endmodule

Exhaustive kyun? Ek 2-input gate mein sirf input combinations hain — sab ko test karna sasta hai. Generally ek -input combinational block mein cases hote hain; exhaustive testing sirf chhote ke liye feasible hai, isliye bade designs ke liye random/coverage methods exist karte hain.


Worked example 3 — golden reference model use karna

Ek adder test karne ke liye, expected sum TB mein khud compute karo:

reg [7:0] a, b; wire [8:0] sum;
adder8 dut(.a(a), .b(b), .sum(sum));
initial begin
  repeat (1000) begin
    a = $random; b = $random;   // Kyun? constrained-random-ish coverage
    #1;
    if (sum !== (a + b))        // Kyun? TB mein {a+b} golden model hai
      $error("%0d + %0d = %0d", a, b, sum);
  end
  $finish;
end

Yeh kyun kaam karta hai: simulator ka khud ka integer arithmetic humara trusted reference hai; DUT ka gate-level logic woh hai jis par hum trust nahi karte. Dono ko automatically compare karna 1000 random cases mein mismatches dhundh leta hai.


Recall Feynman: ek 12-saal ke bachche ko samjhao

Socho tumne ek toy vending machine banayi. Candy bechne se pehle, tum ek test kit banate ho: ek haath jo buttons order mein dabaata hai, aur ek checklist jo kehti hai "agar main yeh dabaaun, toh mujhe woh milna chahiye." Test kit machine ka hissa nahi hai — woh sirf use pokata hai aur dekhta hai. Computer ke andar yeh poking-and-checking (kuch bhi real banane se pehle) simulation hai, aur test kit testbench hai. Clever part yeh hai: baar baar khud dekhne ki jagah, checklist automatically chilaati hai jab machine galat candy de.


Active recall

What is a testbench?
Ek non-synthesizable HDL module jo DUT ko instantiate karta hai, stimulus drive karta hai, aur outputs check karta hai; iske koi ports nahi hote.
Why is a testbench non-synthesizable?
Yeh simulation-only constructs use karta hai (initial, #delay, $display, $random) jo hardware se map nahi hote; iska kaam test karna hai, build hona nahi.
In a Verilog TB, why must DUT-input signals be reg?
Inhe procedural blocks (initial/always) drive karte hain jinke liye ek aisi variable chahiye jo apni value hold kare; wire ko procedurally assign nahi kar sakte.
In a TB, why must DUT-output signals be wire?
DUT inhe continuously drive karta hai, aur wire apne driver ki value reflect karta hai.
How do you generate a clock in a testbench?
initial clk=0; always #5 clk=~clk; — har 5 units mein toggle karne se 10 units ka period milta hai.
Given a toggle delay d, what is the clock period and frequency?
T = 2d aur f = 1/(2d).
Why sample outputs a small time after @(posedge clk)?
Exact edge pe purani aur nayi values delta cycles mein coexist karti hain (ek race); edge ke baad sampling karna settled value padhta hai.
Difference between != and !== in Verilog?
!== (case inequality) x/z ko exactly distinguish karta hai; != x return karta hai jab operands mein x/z ho, isliye unknown-value bugs miss ho sakte hain.
What is an event-driven simulator?
Ek engine jo time-ordered event queue rakhta hai, signals ko tabhi re-evaluate karta hai jab koi input event aata hai, aur time tabhi aage badhata hai jab current instant mein koi events na bachein.
What are delta cycles?
Zero-time ordered sub-steps ek single simulation time ke andar, jo combinational updates propagate karne aur non-blocking assignments resolve karne ke liye use hote hain.
What is a self-checking testbench?
Woh jo DUT outputs ko code mein golden reference se compare karta hai aur errors automatically report karta hai ($error) haath se waveform inspection ki jagah.
What is a golden reference model?
Ek trusted "sahi jawab" (jaise simulator ka compute kiya a+b) jisse TB DUT ko compare karta hai.
Why use named port connections in DUT instantiation?
Yeh signals ko name se ports se bind karte hain, isliye port-order changes silently design ko mis-wire nahi kar sakti.
Why must a testbench call $finish?
Clock always block hamesha chalta rehta hai, isliye $finish ke bina simulation kabhi terminate nahi hogi.
When is exhaustive testing feasible?
Chhote combinational blocks ke liye jinmein n inputs hain (2^n cases); bade n ke liye constrained-random aur coverage-driven methods use karo.
What is constrained-random verification?
Random-but-legal stimulus generate karna un corner cases ko hit karne ke liye jo engineer ne anticipate nahi kiye, coverage se measure kiya jaata hai.
What does $dumpvars(0, tb) do?
tb ke neeche sare signals (level 0 = sari hierarchy) ko dekhe jaane ke liye ek VCD waveform file mein record karta hai.
Why prefer blocking = for TB stimulus?
Stimulus ko specified time pe immediately change hona chahiye; non-blocking change defer kar deta aur off-by-one-cycle confusion create karta.

Connections

Concept Map

wraps + instantiates

generates

drives inputs into

produces

compares outputs vs

checked against

enables

reports

runs

advances

driven signals must be

observed signals must be

catches bugs before

Testbench non-synthesizable

Device Under Test

Stimulus over time

Outputs

Golden reference model

Self-checking $error

Pass or Fail

Event-driven simulator

Simulation time #10

reg / logic

wire / logic

Synthesis + silicon