Lê Hòa
Lê Hòa

Reputation: 45

Verilog test bench code

Can anyone help me in writing verilog test bench code for the following code ! I have try but it's doesn't work !

module top(clock_in, Reset, Hold, up_down, Led_Out, f);     
  input clock_in, Reset, Hold, up_down;
  output      [6:0] Led_Out;        
  output wire [3:0] f;

  wire pulse;

  clock_design temp0(clock_in, pulse);
  up_down_counter temp1(pulse, Reset, Hold, up_down, f);
  led7 temp2(Led_Out, f);
endmodule

led7 :

module led7(iOut, iQ);
  output reg [6:0] iOut;
  input      [3:0] iQ;

  always @(iQ)
    case (iQ)
      4'b0000: iOut = 7'b0000001; //0
      4'b0001: iOut = 7'b1001111; //1
      4'b0010: iOut = 7'b0010010; //2
      4'b0011: iOut = 7'b0000110; //3
      4'b0100: iOut = 7'b1001100; //4
      4'b0101: iOut = 7'b0100100; //5
      4'b0110: iOut = 7'b0100000; //6
      4'b0111: iOut = 7'b0001111; //7
      4'b1000: iOut = 7'b0000000; //8
      4'b1001: iOut = 7'b0000100; //9
      default: iOut = 7'b0000000; //default
    endcase  
  endmodule

up_down_counter :

 module up_down_counter (Clock,Reset,Hold,up_down,Q);
   input Clock,Reset,Hold,up_down;
   output reg [3:0] Q;
   integer direction;


    always @(posedge Clock)
    begin
      if(up_down)
        direction = 1;
      else
        direction = -1;

     if (!Reset && direction == 1)
        Q <= 0;
      else if(!Reset && direction == -1)
        Q <= 1001;
      else if (!Hold)           
        Q <= Q + direction; 

      if (direction==1  && Q[0]==1 && Q[1]==0 &&Q[1]==0 && Q[3]==1)
        Q <= 0; 
      else if (direction==-1 && Q[0]==0 && Q[1]==0 &&Q[2]==0 && Q[3]==0)
        Q <= 1001;
      end
    endmodule

clock_design :

module clock_design (clock_in,clock_out);
  input clock_in;
  output clock_out;
  parameter which_clock=1;
  reg [31:0] divided_clocks=0;

  always @(posedge clock_in)
    divided_clocks = divided_clocks +1;

  assign clock_out = divided_clocks[which_clock];
endmodule

My Test-bench code

module counter_tb;
  reg  [6:0] Led_Out_tb;
  wire [3:0] f_tb;
  reg  clock_in_tb, Reset_tb, Hold_tb, up_down_tb;

  top dut(clock_in_tb, Reset_tb,Hold_tb, up_down_tb, Led_Out_tb, f_tb);

  initial begin
    #10 clock_in_tb = 1;Hold_tb = 0;Reset_tb = 1; up_down_tb = 1;
    #10 clock_in_tb = 0;Hold_tb = 0;Reset_tb = 1; up_down_tb = 1;
    #10 clock_in_tb = 1;Hold_tb = 0;Reset_tb = 1; up_down_tb = 1;
    #10 clock_in_tb = 0;Hold_tb = 0;Reset_tb = 1; up_down_tb = 1;
    #10 clock_in_tb = 1;Hold_tb = 0;Reset_tb = 1; up_down_tb = 1;
    #10 clock_in_tb = 0;Hold_tb = 0;Reset_tb = 1; up_down_tb = 1;
    #10 clock_in_tb = 1;Hold_tb = 0;Reset_tb = 1; up_down_tb = 1;
    #10 clock_in_tb = 0;Hold_tb = 0;Reset_tb = 1; up_down_tb = 1;
    #10 clock_in_tb = 1;Hold_tb = 0;Reset_tb = 1; up_down_tb = 1;
    #10 clock_in_tb = 0;Hold_tb = 0;Reset_tb = 1; up_down_tb = 1;
    #10 clock_in_tb = 1;Hold_tb = 0;Reset_tb = 1; up_down_tb = 1;
    #10 clock_in_tb = 0;Hold_tb = 0;Reset_tb = 1; up_down_tb = 1;
    #10 clock_in_tb = 1;Hold_tb = 0;Reset_tb = 1; up_down_tb = 1;
    #10 clock_in_tb = 0;Hold_tb = 0;Reset_tb = 1; up_down_tb = 1;
    #10 clock_in_tb = 1;Hold_tb = 0;Reset_tb = 1; up_down_tb = 1;
    #10 clock_in_tb = 0;Hold_tb = 0;Reset_tb = 1; up_down_tb = 1;
    #10 clock_in_tb = 1;Hold_tb = 0;Reset_tb = 1; up_down_tb = 1;
    #10 clock_in_tb = 0;Hold_tb = 0;Reset_tb = 1; up_down_tb = 1;
    #10 clock_in_tb = 1;Hold_tb = 0;Reset_tb = 1; up_down_tb = 1;
    #10 clock_in_tb = 0;Hold_tb = 0;Reset_tb = 1; up_down_tb = 1;
    #10 clock_in_tb = 1;Hold_tb = 0;Reset_tb = 1; up_down_tb = 1;
    #10 clock_in_tb = 0;Hold_tb = 0;Reset_tb = 1; up_down_tb = 1;
    #10 clock_in_tb = 1;Hold_tb = 0;Reset_tb = 1; up_down_tb = 1;
    #10 clock_in_tb = 0;Hold_tb = 0;Reset_tb = 1; up_down_tb = 1;
    #10 clock_in_tb = 1;Hold_tb = 0;Reset_tb = 1; up_down_tb = 1;
    #10 clock_in_tb = 0;Hold_tb = 0;Reset_tb = 1; up_down_tb = 1;
    #10 clock_in_tb = 1;Hold_tb = 0;Reset_tb = 1; up_down_tb = 0;
    #10 clock_in_tb = 0;Hold_tb = 0;Reset_tb = 1; up_down_tb = 0;
    #10 clock_in_tb = 1;Hold_tb = 0;Reset_tb = 1; up_down_tb = 0;
    #10 clock_in_tb = 0;Hold_tb = 0;Reset_tb = 1; up_down_tb = 0;
    #10 clock_in_tb = 1;Hold_tb = 0;Reset_tb = 1; up_down_tb = 0;
    #10 clock_in_tb = 0;Hold_tb = 0;Reset_tb = 1; up_down_tb = 0;
    #10 clock_in_tb = 1;Hold_tb = 0;Reset_tb = 1; up_down_tb = 0;
    #10 clock_in_tb = 0;Hold_tb = 0;Reset_tb = 1; up_down_tb = 0;
    #10 clock_in_tb = 1;Hold_tb = 0;Reset_tb = 1; up_down_tb = 0;
    #10 clock_in_tb = 0;Hold_tb = 0;Reset_tb = 1; up_down_tb = 0;
    #10 clock_in_tb = 1;Hold_tb = 0;Reset_tb = 1; up_down_tb = 0;
    #10 clock_in_tb = 0;Hold_tb = 0;Reset_tb = 1; up_down_tb = 0;
    #10 clock_in_tb = 1;Hold_tb = 0;Reset_tb = 1; up_down_tb = 0;
    #10 clock_in_tb = 0;Hold_tb = 0;Reset_tb = 1; up_down_tb = 0;
    #10 clock_in_tb = 1;Hold_tb = 0;Reset_tb = 1; up_down_tb = 0;
    #10 clock_in_tb = 0;Hold_tb = 0;Reset_tb = 1; up_down_tb = 0;
    #10 clock_in_tb = 1;Hold_tb = 0;Reset_tb = 1; up_down_tb = 0;
    #10 clock_in_tb = 0;Hold_tb = 0;Reset_tb = 1; up_down_tb = 0;
    #10 clock_in_tb = 1;Hold_tb = 0;Reset_tb = 1; up_down_tb = 0;
    #10 clock_in_tb = 0;Hold_tb = 0;Reset_tb = 1; up_down_tb = 0;
    #10 clock_in_tb = 1;Hold_tb = 0;Reset_tb = 1; up_down_tb = 0;
    #10 clock_in_tb = 0;Hold_tb = 0;Reset_tb = 1; up_down_tb = 0;
    #10 clock_in_tb = 1;Hold_tb = 0;Reset_tb = 1; up_down_tb = 0;
    #10 clock_in_tb = 0;Hold_tb = 0;Reset_tb = 1; up_down_tb = 0;
  end
endmodule

Upvotes: 0

Views: 20561

Answers (1)

Morgan
Morgan

Reputation: 20514

Testbench wise I would set up a clock and reset like this :

reg clk ; //Rising edge every 10 timesteps
initial begin
  clk = 0;
  #5; 
  forever begin
    #5 clk = ~clk;
  end
end

// TB Reset_tb
reg Reset_tb
initial begin
  Reset_tb = 0;
  @(posedge clk);
  @(posedge clk);
  Reset_tb = 1;
end

And for the actual test something like :

//The actual test
initial begin
  Hold_tb    = 0;
  up_down_tb = 1;
  repeat (50) begin
    @(posedge clk);
  end
  up_down_tb = 1;
  repeat (50) begin
    @(posedge clk);
  end
  $finish();
end

About the Code

You have a section of what looks like it should be combinatorial logic in an always @(posedge clk) block.

always @(posedge Clock)
begin
  if(up_down)
    direction = 1;
  else
    direction = -1;

I think this should be :

 always @* begin
   if(up_down)begin
     direction = 1;
   end
   else begin
     direction = -1;
   end
 end

If you do not include begin end the if statements only apply to the next line. I would use begin ends much more frequently so your code is explicitly shows your intent.

You have the following section of code :

  if (!Reset && direction == 1)
    Q <= 0;
  else if(!Reset && direction == -1)
    Q <= 1001;
  else if (!Hold)           
    Q <= Q + direction; 

  if (direction==1  && Q[0]==1 && Q[1]==0 &&Q[1]==0 && Q[3]==1)
    Q <= 0; 
  else if (direction==-1 && Q[0]==0 && Q[1]==0 &&Q[2]==0 && Q[3]==0)
    Q <= 1001;

Is there a missing else on the 4th if? if (direction==1 && Q[0]==1 && Q[1]==0 &&Q[1]==0 && Q[3]==1)

I would avoid the use of integer types in RTL as the are often overkill, especially here were you are just storing 1 or -1 that really only needs a 1 bit value. Regs and wires can be signed :

reg signed signed_reg ;
reg signed [7:0] signed_reg8;

You can also declare constant as signed :

reg_signed = 1'sd-1 ; //1Bit Signed Decimal value -1

I find it bad practise to use mixed case signal names, I always use lower case. Constants like parameters and localparams are all upper case. This makes typos a bit less likely, you could spend ages trying to workout why something is not working then you realise one of the connection was using a lower case instead of upper case first character.

Upvotes: 8

Related Questions