4位反击使用verilog不递增

时间:2016-11-07 06:57:13

标签: verilog counter

爵士

我使用verilog做了一个4位向上的计数器。但是在模拟过程中没有增加。分频器电路用于为计数器提供必要的时钟。请帮我解决这个问题。代码如下:

module my_upcount(
    input clk,
    input clr,
    output [3:0] y
    );

 reg [26:0] temp1;
 wire clk_1;

always @(posedge clk or posedge clr)
    begin
      temp1 <= ( (clr) ? 4'b0 : temp1 + 1'b1 );
    end 
assign clk_1 = temp1[26];


reg [3:0] temp;

always @(posedge clk_1 or posedge clr)
    begin
       temp <= ( (clr) ? 4'b0 : temp + 1'b1 );
    end 
assign y = temp;    
endmodule

1 个答案:

答案 0 :(得分:1)

您是否至少在(2^27) / 2 + 1次迭代中运行了模拟?如果没有,那么你的clk_1信号永远不会升至1,你的计数器永远不会增加。尝试使用4位作为除数计数器,这样您就不必长时间运行模拟。此外,clk_1信号应在除数计数器达到其最大值时激活,而不是在MSB位为1时激活。

除此之外,您的代码还有其他几个问题:

  • 使用单个时钟驱动所有寄存器 - 在单个硬件模块中使用不同的时钟是一个非常糟糕的主意,因为它违反了同步设计的原则。所有寄存器都应该由相同的时钟信号驱动,否则你会遇到麻烦。
  • 分隔当前和下一个寄存器值 - 最好将当前寄存器值与下一个寄存器值分开。然后,下一个寄存器值将分配在电路的组合部分(不由时钟驱动),并在下一个时钟周期开始时存储在寄存器中(例如,下面的检查代码)。这使得代码更加清晰易懂,并最大限度地降低了竞争条件和不需要的推断内存的可能性。
  • 定义模块开头的所有信号 - 所有信号都应在模块的开头定义。这有助于保持模块逻辑尽可能干净。

这是根据我的建议重写的例子:

module my_counter
(
    input wire clk, clr,
    output [3:0] y
);

    reg [3:0] dvsr_reg, counter_reg;
    wire [3:0] dvsr_next, counter_next;
    wire dvsr_tick;

    always @(posedge clk, posedge clr)
        if (clr)
        begin
            counter_reg <= 4'b0000;
            dvsr_reg <= 4'b0000;
        end
        else
        begin
            counter_reg <= counter_next;
            dvsr_reg <= dvsr_next;
        end

    /// Combinational next-state logic
    assign dvsr_next = dvsr_reg + 4'b0001;
    assign counter_next = (dvsr_reg == 4'b1111) ? counter_reg + 4'b0001 : counter_reg;

    /// Set the output signals
    assign y = counter_reg;

endmodule

这是验证其操作的简单测试平台:

module my_counter_tb;

    localparam
        T = 20;

    reg clk, clr;
    wire [3:0] y;

    my_counter uut(.clk(clk), .clr(clr), .y(y));

    always
    begin

        clk = 1'b1;
        #(T/2);
        clk = 1'b0;
        #(T/2);

    end

    initial
    begin

        clr = 1'b1;
        @(negedge clk);

        clr = 1'b0;
        repeat(50) @(negedge clk);

        $stop;

    end
endmodule