Aliyar Attaran
Aliyar Attaran

Reputation: 41

Why is the counter output always x?

I am having problem with this counter. The output is all xxxxxxxx. I know I should set the initial value of count and overflow to 0, but it gives an error that way.

module counter (in, start, count, clk, overflow);    
input [3:0] in;
input clk;
input start;
output reg [7:0] count;
output reg overflow;
//reg count;
//count =0;
//overflow=0;
always @ (posedge clk)
  begin
    if (start) begin
      count <= 8'b0;
      overflow <= 1'b0;
    end
    
    else if (in == 4'b0101) begin
      count <= count+1;
    end
    if (count == 4'b1111) begin
      overflow <=1'b1;
    end
  end
endmodule

This is the testbench:

module tb();      
  reg [3:0] in;
  reg clk,start;
  wire [7:0] count;
  reg overflow = 1'b0;
  
  initial begin
    
    $display ("time\t clk start in count overflow");
    $monitor ("%g\t %b %b %b %b", $time, clk, start, in, count, overflow);
    
    clk=0;
    in=0;
    start=0;
   // overflow=0;
   // count=0;
    
    #5 in=4'd1;
    #5 in=4'd5;
    #5 in=4'd4;
    #5 in=5'd5;
    #5 in=4'd1;
    #5 in=4'd5;
    #5 in=4'd4;
    #5 in=5'd5;
    #5 in=4'd1;
    #5 in=4'd5;
    #5 in=4'd4;
    #5 in=5'd5;
    #5 in=4'd1;
    #5 in=4'd5;
    #5 in=4'd4;
    #5 in=5'd5;
    #50 $finish;
  end
  
    always #5 clk=~clk;

  counter u0(.*);
endmodule

Upvotes: 1

Views: 12379

Answers (1)

Rahul Menon
Rahul Menon

Reputation: 792

There are two issues that need to be fixed.

1) Coincidently in=5 is set only during the neg edge of clock. This is because clk cycle is #10 and the tb code changes "in" value every #5 .As the counter checks the value of in at posedge it misses the in = 5. The in time period needs to #10 or the TB can wait for a posedge of clk before setting signal "in".

2) the start needs to be set for the counter to reset , else the value of count = x (unknown) and count+1 => x+1 which equals x. Hence the counter will not increment and continue to remain x throughout.

Updated tb is below .

module tb();

  reg [3:0] in;
  reg clk,start;
  wire [7:0] count;
  reg overflow = 1'b0;

  initial begin

    $display ("time\t clk start in count overflow");
    $monitor ("%g\t %b %b %b %b", $time, clk, start, in, count, overflow);

    clk=0;
    in=0;
    start=0;
   // overflow=0;
   // count=0;

    #10 start = 1'b1; // reset counter 
    #10 start = 1'b0;
    #10 in=4'd1;
    #10 in=4'd5;
    #10 in=4'd4;
    #10 in=5'd5;
    #10 in=4'd1;
    #10 in=4'd5;
    #10 in=4'd4;
    #10 in=5'd5;
    #10 in=4'd1;
    #10 in=4'd5;
    #10 in=4'd4;
    #10 in=5'd5;
    #10 in=4'd1;
    #10 in=4'd5;
    #10 in=4'd4;
    #10 in=5'd5;
    #50 $finish;

  end

    always #5 clk=~clk;

  counter u0(.*);

initial  // Dump waveform for debug 
$dumpvars;

endmodule

You can dump waveform using $dumpvars command to debug.

Alternative code ( using posedge event to drive data in test bench )

// Code your testbench here
// or browse Examples
module tb();

  reg [3:0] in;
  reg clk,start;
  wire [7:0] count;
  reg overflow = 1'b0;

  initial begin

    $display ("time\t clk start in count overflow");
    $monitor ("%g\t %b %b %b %b", $time, clk, start, in, count, overflow);

    clk=0;
    in=0;
    start=0;
   // overflow=0;
   // count=0;

    @(posedge clk )   start = 1'b1;// reset counter 
    @(posedge clk )   start = 1'b0;
    @(posedge clk )   in=4'd1;
    @(posedge clk )   in=4'd5;
    @(posedge clk )   in=4'd4;
    @(posedge clk )   in=5'd5;
    @(posedge clk )   in=4'd1;
    @(posedge clk )   in=4'd5;
    @(posedge clk )   in=4'd4;
    @(posedge clk )   in=5'd5;
    @(posedge clk )   in=4'd1;
    @(posedge clk )   in=4'd5;
    @(posedge clk )   in=4'd4;
    @(posedge clk )   in=5'd5;
    @(posedge clk )   in=4'd1;
    @(posedge clk )   in=4'd5;
    @(posedge clk )   in=4'd4;
    @(posedge clk )   in=5'd5;
    #50 $finish;

  end

    always #5 clk=~clk;

  counter u0(.*);

initial
$dumpvars;

endmodule

Upvotes: 1

Related Questions