24位计数器状态机

时间:2011-10-28 16:02:03

标签: verilog fpga

我正在尝试在verilog中创建一个计数器,该计数器计算已经有多少个时钟周期,一千万个时钟周期后它将重置并重新启动。

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

然后我希望有一个处于计数状态的状态机,直到超过一千万个周期,然后它进入复位状态。

这听起来不错吗?问题是我不知道如何实现状态机。

有人能指出我可以帮助我的网站/书吗?

感谢

3 个答案:

答案 0 :(得分:4)

正如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的文档。我刚搜索谷歌的“verilog状态机”:

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

答案 1 :(得分:3)

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

在伪代码中:

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

...或...

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

答案 2 :(得分:2)

状态机并不太棘手。使用localparam(宽度,不要忘记宽度,这里没有显示,因为它只是一位)来定义状态的标签。然后创建两个注册变量(state_regstate_next)。 _reg变量是您的实际注册。 _next变量是“wire reg”(可以分配到组合内部的线路始终阻止)。要记住的两件事是在组合中始终X_next = X_reg;阻塞(然后是组合逻辑的其余部分)和X_reg <= 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。