【问题标题】:24 bit counter state machine24位计数器状态机
【发布时间】:2011-10-28 16:02:03
【问题描述】:

我正在尝试在 verilog 中创建一个计数器,用于计算已经存在多少个时钟周期,并在一千万后重置并重新开始。

我创建了一个 24 位加法器模块以及另一个包含 24 个 D 触发器的模块,以存储从加法器输出的周期计数。

然后我想要一个处于计数状态的状态机,直到经过一千万个周期然后它进入重置状态。

这听起来对吗?问题是我不确定如何实现状态机。

谁能给我指出一个可以帮助我解决这个问题的网站/书籍?

谢谢

【问题讨论】:

    标签: verilog fpga


    【解决方案1】:

    正如 Paul S 已经提到的,如果您希望计数器在溢出后继续计数,则不需要状态机。您可以这样做(未经测试,可能包含拼写错误):

    module overflow_counter (
      clk,
      reset,
      enable,
      ctr_out
    );
    
    // Port definitions
    input clk, reset, enable;
    output [23:0] ctr_out;
    
    // Register definitions
    reg [23:0] reg_ctr;
    
    // Assignments
    assign ctr_out = reg_ctr;
    
    // Counter behaviour - Asynchronous active-high reset
    initial reg_ctr <= 0;
    always @ (posedge clk or posedge reset)
    begin
      if (reset)                 reg_ctr <= 0;
      else if (enable)
      begin
        if (reg_ctr == 10000000) reg_ctr <= 0;
        else                     reg_ctr <= reg_ctr + 1;
      end
    end
    
    endmodule
    

    当然,通常您会使用参数,这样您就不必在每次需要溢出计数器时都创建自定义模块。我会把它留给你;)。

    [编辑]这里有一些文档可以帮助您进行 FSM。我刚刚在 Google 上搜索了“verilog 状态机”:

    我还没有读过第一篇论文,所以我不能对此发表评论。第二个展示了各种编码 FSM 的风格,其中 3 种总是阻塞风格,我强烈推荐,因为它更容易调试(状态转换和 FSM 输出被整齐地分开)。链接好像挂了,所以这里是the cached Google result

    【讨论】:

      【解决方案2】:

      您不需要状态机。您已经在柜台中有状态。您需要做的就是检测您想要包装的值并将 0 加载到您的计数器中

      在伪代码中:

      if count == 10000000 then
        nextCount = 0;
      else
        nextCount = count + 1;
      

      ...或...

      nextCount  = count + 1;
      if count == 10000000 then
        resetCount = 1;
      

      【讨论】:

        【解决方案3】:

        状态机并不太复杂。使用 localparam (带有宽度,不要忘记宽度,这里没有显示,因为它只是一位)为您的状态定义标签。然后创建两个 reg 变量(state_regstate_next)。 _reg 变量是您的实际寄存器。 _next 变量是一个“wire reg”(可以分配给组合 always 块内部的线)。要记住的两件事是在组合 always 块中执行 X_next = X_reg;(然后是其余的组合逻辑)和在顺序 always 块中执行 X_reg &lt;= X_next;。您可能会喜欢特殊情况,但如果您坚持这些简单的规则,那么事情应该会奏效。因为 Verilog 对加法器有很好的支持,所以我尽量不要对加法器等非常简单的事情使用实例化。

        由于我使用 FPGA,我为我的寄存器分配了初始值,我不使用复位信号。我不确定,但对于 ASIC 设计,我认为情况正好相反。

        localparam STATE_RESET = 1'b0, STATE_COUNT = 1'b1;
        
        reg [23:0] cntr_reg = 24'd0, cntr_next;
        reg state_reg = STATE_COUNT, state_next;
        
        always @* begin
            cntr_next = cntr_reg; // statement not required since we handle all cases
            if (cntr_reg == 24'd10_000_000)
                cntr_next = 24'd0;
            else
                cntr_next = cntr_reg + 24'd1;
            state_next = state_reg; // statement required since we don't handle all cases
            case (state_reg)
                STATE_COUNT: if (cntr_reg == 24'd10_000_000) state_next = STATE_RESET;
            endcase
        end
        
        always @(posedge clk) begin
            cntr_reg <= cntr_next;
            state_reg <= state_next;
        end
        

        我发现this book 很有帮助。这本书还有一个VHDL版本,因此您可以将两者并排用作Rosetta Stone来学习VHDL。

        【讨论】:

        • 我看不到状态在您的示例中完成了什么。没有什么取决于它。如果将该代码放在 FPGA 中的哪个位置,则合成器会将与状态相关的代码优化掉。
        • 我在回答原来的问题。
        猜你喜欢
        • 1970-01-01
        • 2014-10-20
        • 2011-01-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多