Electronic – Verilog Testbench with Pipelined Modules

verilog

First I'm very new to verilog.. and test benches are driving me crazy. I have a pipelined multiplier and I'm trying to write a test bench to auto-check it. My problem is that I apply stimulus to the input, but the correct answer doesn't come out until 5 cycles later. So in the test bench I'm calculating the answer when the stimulus hits, which will never match the output. I figure there must be an easy solution to this but have yet to figure it out.

Code of my test bench is below. The module is a 32bit multiplier with pipelines.

Result is calculated after i_Aj & i_Ak are set, however the module does not produce an answer in o_Ai for five cycles. That's the gist of the problem.

module scalar_multiply_tb;

 reg [31:0] i_Aj, i_Ak;
 reg clk;
 wire [31:0] o_Ai;
 reg [32:0] count1, count2;

 initial
 begin
  clk <= 1'b0;
  i_Aj <= 32'b0;
  i_Ak <= 32'b0;

  repeat (50) @(posedge clk);
  //check all possible input
   for(count1 = 1; count1 <= 32'hffffffff; count1 = count1 + 1)  //Aj max 2^32
   begin
     for(count2 = 1; count2 <= 32'hffffffff; count2 = count2 + 1) //Ak max 2^32
      begin
       i_Aj = count1;
       i_Ak = count2;
       @(posedge clk);
      end
    end
  end

  always #10 clk <= ~clk;

  scalar_multiply u_scalar_multiply (i_Ak, i_Aj, clk, o_Ai);
   reg [63:0] Aj_d, Ak_d;
   reg [63:0] result;

   always@(posedge clk) 
    begin
     Aj_d <= i_Aj;
     Ak_d <= i_Ak;
    end

    always@(Aj_d or Ak_d) 
    begin
      result <= Aj_d*Ak_d;
    end  

   always@(result) 
    begin
     $display("CLK=%t,Aj=%d,Ak=%d,result=%d,actual=%d", $time,Aj_d,Ak_d,result,o_Ai);
     if(result != o_Ai)
      $display("ERROR: %t,sj=%d,sk=%d,result=%d,actual=%d", $time,Aj_d,Ak_d,result,o_Ai);
     end
    initial begin
     $dumpfile("dump.vcd");
     $dumpvars;
     #32000 $finish;
    end
endmodule

Best Answer

Create a pipeline for the results in your testbench:

   parameter PIPE = 5;
   reg [63:0] result [1:PIPE];

   always@(posedge clk) 
    begin
     Aj_d <= i_Aj;
     Ak_d <= i_Ak;
    end

    always@(Aj_d or Ak_d) 
    begin
      result[1] <= Aj_d*Ak_d;
      for (int i=2; i<=PIPE; i++) result[i] <= result[i-1];
    end  

   always@(result[PIPE]) 
    begin
     $display("CLK=%t,Aj=%d,Ak=%d,result=%d,actual=%d", $time,Aj_d,Ak_d,result[PIPE],o_Ai);
     if(result[PIPE] !== o_Ai)
      $display("ERROR: %t,sj=%d,sk=%d,result=%d,actual=%d", $time,Aj_d,Ak_d,result[PIPE],o_Ai);
     end