Why is the timer output unknown?

Viewed 84

I just started building up-count timer in Verilog, and I keep getting unknown as output.

I'm using 50MHz osciliator and these variables for the code:

min : sec : 1/100 sec

a b : c d : e f

For example, I want the timer to be:

00:00:99 > 00:01:00
...
00:59:99 > 1:00:00
module timer    (clk,
        a,
        b,
        c,
        d,
        e,
        f,
        count);


input clk;
input [18:0]count;


output reg[3:0]a;
output reg[3:0]b;
output reg[3:0]c;
output reg[3:0]d;
output reg[3:0]e;
output reg[3:0]f;


always@(posedge clk) 
begin
    if (f == 4'b1010)       f = 4'b0000;
    else if (count == 19'd500000)   f = f+4'b0001;
end 

always@(posedge clk) 
begin
    if (e == 4'b1010)       e = 4'b0000;
    else if (f == 4'b1010)      e = e +4'b0001;
end 

always@(posedge clk) 
begin
    if (d == 4'b1010)       d = 4'b0000;
    else if (e == 4'b1010)       d = d +4'b0001;
end 

always@(posedge clk) 
begin
    if (c == 4'b1010)       c = 4'b0000;
    else if (d == 4'b1010)       c = c +4'b0001;
end 

always@(posedge clk) 
begin
    if (b == 4'b1010)       b = 4'b0000;
    else if (c == 4'b0101)      b = b +4'b0001;
end 

always@(posedge clk) 
begin
    if (a == 4'b1010)       a = 4'b0000;
    else if (c == 4'b1010)      a = a +4'b0001;
end 

endmodule

< test bench >

`timescale 1ns / 1ps

module tb_timer();

parameter clk_period = 10;
parameter N = 19;

reg clk; 
reg [N-1:0]count;

wire [3:0]a;
wire [3:0]b;
wire [3:0]c;
wire [3:0]d;
wire [3:0]e;
wire [3:0]f;

//instatiate the module 
timer U0(
    .count(count),
    .clk(clk),
    .a(a),
    .b(b),
    .c(c),
    .d(d),
    .e(e),
    .f(f));



// clk signal
always begin
 clk =0;
 forever #(clk_period/2)clk = ~clk;
end

// count signal 
always begin
f = 1'b0
count = 1'b0;
forever #clk_period count = ~count;
end

//reset signal
initial begin
reset = 1;
#12 reset = 0;
#(clk_period) reset = 0;
end

endmodule
2 Answers

Assuming you declared f as wire in the testbench and connected it to the f output of timer, my simulator gives me a compile error on this line:

f = 1'b0;

It is illegal to drive a wire with a procedural assignment.

Your instinct is correct; you need to initialize f. It is declared as reg inside timer, which means that it initializes to X.

This is typically done by adding a reset input signal to your design which you drive from your testbench. Assert the reset for the first few clock cycles, then release it. You should probably reset all your registers in the design.

always@(posedge clk or posedge reset) 
begin
    if (reset) f = 4'b0000;
    else if (f == 4'b1010)       f = 4'b0000;
    else if (count == 19'd500000)   f = f+4'b0001;
end 

These are the Verilog code that worked. Thank you for the help!

module timer    (clk,
         reset,
             a,
             b,
             c,
             d,
             e,
             f,
             count);

input clk;
input reset;
input [18:0]count;

output reg[3:0]a;
output reg[3:0]b;
output reg[3:0]c;
output reg[3:0]d;
output reg[3:0]e;
output reg[3:0]f;


always@(posedge clk or negedge reset) 
begin
    if (~reset)             f <= 4'b0000;
    else if (f == 4'b1010)          f <= 4'b0000;
    else if (count == 19'd500000)   f <= f + 4'b0001;
end 

always@(posedge clk or negedge reset) 
begin   
    if (~reset)             e <= 4'b0000; 
    else if (e == 4'b1010)          e <= 4'b0000;
    else if (f == 4'b1010)          e <= e +4'b0001;
end 

always@(posedge clk or negedge reset) 
begin
    if (~reset)             d <= 4'b0000;
    else if (d == 4'b1010)          d <= 4'b0000;
    else if (e == 4'b1010)          d <= d +4'b0001;
end 

always@(posedge clk or negedge reset) 
begin
    if (~reset)             c <= 4'b0000;
    else if (c == 4'b1010)          c <= 4'b0000;
    else if (d == 4'b1010)          c <= c +4'b0001;
end 

always@(posedge clk or negedge reset) 
begin
    if (~reset)             b <= 4'b0000;
    if (b == 4'b1010)               b <= 4'b0000;
    else if (c == 4'b0101)          b <= b +4'b0001;
end 

always@(posedge clk or negedge reset) 
begin
    if (~reset)             a <= 4'b0000;
    if (a == 4'b1010)           a <= 4'b0000;
    else if (b == 4'b1010)          a <= a +4'b0001;
end 

endmodule
// <test bench>


`timescale 1ns / 1ps

module tb_timer();

parameter clk_period = 10;
parameter N = 19;

reg clk; 
reg [N-1:0]count;
reg reset;

wire [3:0]a;
wire [3:0]b;
wire [3:0]c;
wire [3:0]d;
wire [3:0]e;
wire [3:0]f;

//instatiate the module 
timer U0(
    .reset(reset),
    .count(count),
    .clk(clk),
    .a(a),
    .b(b),
    .c(c),
    .d(d),
    .e(e),
    .f(f));


//reset signal 
initial begin 
reset = 1;
#13 reset = 0;
#(clk_period)reset =1;
end

// clk signal
always begin
 clk =0;
 forever #(clk_period/2)clk = ~clk;
end

// count signal 
always begin
count = 0;
forever #(clk_period/5)count = count + 19'b0000000000000000001;
end

//reset signal
initial begin
reset = 1;
#12 reset = 0;
#(clk_period) reset = 0;
end

endmodule

< Things that I've missed >

  1. The initial value of Flip Flop must be set only when there is reset input.
  2. In testbench, counter should be
// count signal 
always begin
count = 0;
forever #(clk_period/5)count = count + 19'b0000000000000000001;
end
  1. The initial block is only executed once and it doesn't synthesis as hardware.
Related