为什么定时器输出未知?

Why is the timer output unknown?

我刚开始在 Verilog 中构建递增计数定时器,但输出一直未知。

我在代码中使用 50MHz 振荡器和这些变量:

分钟:秒:1/100 秒

a b : c d : ef

例如,我希望定时器为:

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

<测试台>

`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

假设您在测试台中将 f 声明为 wire 并将其连接到 timerf 输出,我的模拟器在这一行给我一个编译错误:

f = 1'b0;

用程序分配驱动电线是非法的。

你的直觉是正确的;您需要初始化 f。在timer里面声明为reg,也就是说初始化为X.

这通常是通过向您从测试台驱动的设计添加复位输入信号来完成的。在前几个时钟周期置位复位,然后释放它。您可能应该重置设计中的所有寄存器。

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 

这些是有效的 Verilog 代码。 感谢您的帮助!

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

<我错过的事情>

  1. Flip Flop的初始值只有在有reset输入时才需要设置
  2. 在测试台中,计数器应该是
// count signal 
always begin
count = 0;
forever #(clk_period/5)count = count + 19'b0000000000000000001;
end
  1. 初始块只执行一次,不作为硬件综合。