0
votes

First day struggling with verilog, here is a simple module:

module example4_23 (x, f);
  input [0:6] x;
  output f;

  assign f = x[0] & x[1] & x[2] & x[3] & x[4] & x[5] & x[6];
endmodule

Then I want to write a testbench for it. Firstly, I used 7bit register for x (no array) - everything worked, but now i want to run it with several test patterns, so I announce an array and want to loop over it and run the module with new input every time.

module test;
  reg [0:6] arr [0:1] = {7'b0011111,7'b1100000}; // all patterns
  reg [0:1] arr_size;                            // number of patterns
  wire [0:6] x;                                  // current pattern
  wire f;                                        // output

  initial begin
    $write("| TIME | x0 | x1 | x2 | x3 | x4 | x5 | x6 |   f   |"); // header
    $display;
    arr_size = $size(arr);                                         // 2
  end

// go through all test patterns, assign it to x and run the module   
  genvar i;  
  generate
    for (i=0; i<2; i=i+1)         // if use 'i<arr_size' gives an error
    begin
      assign x = arr[i];  // change to '..= arr[1]' or '..= arr[0]' successfully makes one test
      example4_23 dut (x,f);
    end
  endgenerate

// anytime there is a change - output on the screen   
  always @(x,f)
  begin
    $strobe("%6d %4d %4d %4d %4d %4d %4d %4d %5d", $time, x[0],x[1],x[2],x[3],x[4],x[5],x[6], f);
  end

endmodule 

Currently after compiling I only see the header line. Except an obvious question, why it doesnt work, I also dont understand the following:

  1. What should I use for x - wire or register?
  2. Can I get without the 'generate'\'for' cycle? Probably there is a way to simplify the code.
  3. Is it possible to use a variable arr_size in FOR cycle instead of a number?

Thanks in advance.

1

1 Answers

0
votes

I'm surprised you don't get an error about assigning multiple values to f.

Remember that verilog (or any other HDL) creates physical circuits, and a generate block creates multiple versions of a given circuit. In this case, you're creating two instances of your example4_23 module and have both driving the same output. Generate loops operate in a spatial manner, while for loops in an always block are temporal when you add delays.

To answer your questions: 1) use a reg, and assign the value in an always block with a delay; 2) Yes! (see below example); 3) Yes! Use a parameter!

So, here's some changes you could make:

  • replace wire arr_size with a localparam ARR_SIZE = 2 (or as appropriate)
  • change reg [0:6] arr [0:1] to reg [0:6] arr [0:ARR_SIZE1-]
  • replace the generate loop with a basic for loop in an initial block
  • The array of test vectors could be a parameter instead of a wire or reg
  • Add in delays. Right now, your test bench doesn't vary with time, only in space. Delays are noted using a # (see below)
  • Use always @(*) instead of always @(x,f)

Here's what I would implement:

module test;
  localparam ARR_SIZE = 2;                            // number of patterns
  localparam [0:6] arr [0:ARR_SIZE-1] = {7'b0011111,7'b1100000}; // all patterns
  reg[0:6] x;                                  // current pattern
  wire f;                                        // output
  integer i;

  example4_23 dut (x,f);  

  initial begin
    $write("| TIME | x0 | x1 | x2 | x3 | x4 | x5 | x6 |   f   |"); // header
    $display;
    for (i=0; i< ARR_SIZE; i=i+1) begin
      x = arr[i];
      #5;    // delay 5 timesteps
    end
  end

// anytime there is a change - output on the screen   
  always @(*)
  begin
    $strobe("%6d %4d %4d %4d %4d %4d %4d %4d %5d", $time, x[0],x[1],x[2],x[3],x[4],x[5],x[6], f);
  end

endmodule