简体   繁体   中英

Implement testbench on verilog with clock divider and different output

For the following code, wich is a 7-segment 59-seconds counter, I'm trying to implement a testbench. I have two troubles with that: one is that I'm using as an intern clock the term q[24] to make it count approximate seconds, but in the testbench I should be able to see different outputs without implementing thousands of posedge clocks. The other trouble is that I want to see as outputs in the testbench the register [3:0]unidad and [3:0]decena, which are each number on the 7-segment panel, but in the code those aren't used as in or output, but as an intern variable.

How could I implement such a simulation that shows the decena/unidad output in a reasonable time? Thanks.

module cont(
   input clock,
   input reset,
   output reg [6:0]segm,
   output [3:0]an
   );

reg [3:0]unidad; 
reg [3:0]decena; 

reg [24:0] q;

always @(posedge clock or posedge reset)
    begin
        if(reset == 1)
         q <= 0;
        else
            q <= q + 1;
    end

always @ (posedge q[24] or posedge reset)
 begin
  if (reset) begin
   unidad <= 0;
   decena <= 0;
  end
  else if (unidad==4'd9) 
    begin  
    unidad <= 0;
     if (decena==4'd5) 
      decena <= 0;
        else
         decena <= decena + 1;
     end
   else
    unidad <= unidad + 1;
  end

reg [6:0]sseg;
reg [3:0]an_temp;
always @ (*)
 begin
  case(q[13])

   1'b0 : 
    begin
     sseg = unidad;
     an_temp = 4'b1110;
    end

   1'b1 :
    begin
     sseg = decena;
     an_temp = 4'b1101;
    end

  endcase
 end
assign an = an_temp;

always @ (*)
 begin
  case(sseg)
   4'd0 : segm = 7'b1000000; //0
   4'd1 : segm = 7'b1111001; //1
   4'd2 : segm = 7'b0100100; //2
   4'd3 : segm = 7'b0110000; //3
   4'd4 : segm = 7'b0011001; //4
   4'd5 : segm = 7'b0010010; //5
   4'd6 : segm = 7'b0000010; //6
   4'd7 : segm = 7'b1111000; //7
   4'd8 : segm = 7'b0000000; //8
   4'd9 : segm = 7'b0010000; //9
   default : segm = 7'b1111111; 
  endcase
 end

endmodule

You could force the counter closer to the values of interest in your test bench. You could do it via two styles .

1) Force the counter to the value close to your interest and generate some clock cycles.

2) Force the bits of your interest and wait for some clock cycles.

In this case values of 'h1000 and 'h1000000 are of interest or bits 24 and 13 .

// function to set the register - replace <DUT>  
task load_counter ( reg [24:0] val );
#1 <DUT>.q = val ; //delay is to overwrite the main counter
endtask

or

// function to set the counter bit - replace <DUT>
task count_up  ( int count,int loc , bit val);
repeat(count) @(posedge clock ) ;
#1 <DUT>.q[loc] =  val; //delay is to overwrite the main counter
endtask

// toggle bit 24 and in between toggle bit 13 based on counts.
// 100 clock is just a value it can be changes.
task count_24( int count_24,int count_13);
repeat (count_24)
        begin
        repeat(count_13)
        begin
                count_up ( 100,13,1);
                count_up ( 100,13,0);
        end
        count_up ( 1,24,1);
        repeat(count_13)
        begin
                count_up ( 100,13,1);
                count_up ( 100,13,0);
        end
        count_up ( 1,24,0);
end
endtask

in the first approach

load_counter(25'hff0);// load and wait for bit 13 to be set 
repeat(50)  @(posedge clock ) ;
load_counter(25'h1ff0); // load and wait for bit 13 to be re-set. 
repeat(50)  @(posedge clock ) ;
load_counter(25'hf0ff0); //load and wait for bit 13 set ( while other bits > 13 are on )  
repeat(50)  @(posedge clock ) ;
load_counter(25'hfffff0); // bit 24 set 
repeat(50)  @(posedge clock ) ;
// if needed add set/reset for bit 13 code here 
load_counter(25'h1fffff0); // load and wait till bit 24 rolls over 
repeat(50)  @(posedge clock ) ; 
 // repeat the whole process above in a loop to get desired behavior

You could also randomize the number of 13 bit toggles you need to see between each 24 bit toggles and number of clock that needs to be run in between the counter changes.

In scheme 2

the count of 13 and 24 can be determined by the test writer or can also be randomized.

count_24(10,10)

in option 1 we let the counter mechanism do most of the task and hence preferred.

But finally its also better to run the full counter to see the results. probably you can run it on as a weekend regression .

Also you could observe the signals in the TB directly.

wire [3:0] observe_unidad = <DUT>.unidad;
wire [3:0] observe_decena = <DUT>.decena;

Adding full code for a tb here ...

// this code will not synthesize
module tb_cont ;


reg clock_gen ; // To generate a clock
reg reset_gen ; // to generate reset

// Main counter instance
cont  cont_instance (
                .clock(clock_gen),
                .reset ( reset_gen)
                ) ;

// Clock generation block
initial
begin
clock_gen = 0 ;

forever
begin
        #10 clock_gen = 0 ;
        #10 clock_gen = 1 ;
end
end

// Task to write data in the cont- block
task count_up  ( int count,int loc , bit val);
repeat(count) @(posedge clock_gen ) ;
#1  cont_instance.q[loc] =  val; //delay is to overwrite themain counter
endtask

/ toggle bit 24 and in between toggle bit 13 based on counts.
// 100 clock is just a value it can be changed.
task count_24( int count_24,int count_13);
repeat (count_24)
        begin
        repeat(count_13)
        begin
                count_up ( 100,13,1);
                count_up ( 100,13,0);
        end
        count_up ( 1,24,1);
        repeat(count_13)
        begin
                count_up ( 100,13,1);
                count_up ( 100,13,0);
        end
        count_up ( 1,24,0);
end
endtask

// task to load the counter
task load_counter ( reg [24:0] val );
#1 cont_instance.q = val ; //delay is to overwrite themain counter
endtask


initial
begin 
// dump  waveform to observe signals
$dumpvars;

// generate a reset first
reset_gen = 0 ;  
#100 reset_gen = 0 ;
#100 reset_gen = 1 ;
#100 ;
@(posedge clock_gen ) ;
reset_gen = 0 ;
end

// value for the count
int count13 = 100;
int count24=100;

// generate test vector
initial
begin

repeat( 100 ) @ ( posedge clock_gen ) ; // wait for counter
load_counter(25'hff0);
repeat( 100 ) @ ( posedge clock_gen ) ; // wait for counter
load_counter(25'hfffff0); 
repeat( 100 ) @ ( posedge clock_gen ) ; // wait for counter
load_counter(25'h1fffff0);
repeat( 100 ) @ ( posedge clock_gen ) ; // wait for counter

// scheme 2 
count_24(10,10);

$finish ;
end

// both the signal can eb observed 
wire [3:0] observe_unidad = cont_instance.unidad;
wire [3:0] observe_decena = cont_instance.decena;

endmodule

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM