24位计数器状态机

发布于 2024-12-12 14:54:29 字数 251 浏览 0 评论 0原文

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

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

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

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

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

谢谢

I am trying to create a counter in verilog which counts how many clock cycles there have been and after ten million it will reset and start again.

I have created a twenty four bit adder module along with another module containing twenty four D Flip flops to store the count of the cycles outputted from the adder.

I then want to have a state machine which is in the count state until ten million cycles have passed then it goes to a reset state.

Does this sound right? The problem is I am not sure how to implement the state machine.

Can anyone point me to a website/book which could help me with this?

thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

娇柔作态 2024-12-19 14:54:29

正如 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 输出被整齐地分开)。该链接似乎已关闭,所以这里是 缓存的 Google 结果

As Paul S already mentioned, there is no need for a state machine if you want your counter to keep counting after an overflow. You can do something like this (untested, might contain typos):

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

Of course, normally you'd use parameters so you don't have to make a custom module every time you want an overflowing counter. I'll leave that to you ;).

[Edit] And here are some documents to help you with FSM. I just searched Google for "verilog state machine":

I haven't read the first paper, so I can't comment on that. The 2nd one shows various styles of coding FSMs, among which the 3 always blocks style, which I highly recommend, because it's a lot easier to debug (state transitions and FSM output are neatly separated). The link seems to be down, so here is the cached Google result.

音栖息无 2024-12-19 14:54:29

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

在伪代码中:

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

...或...

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

You don't need a state machine. You already have state in the counter. All you need to do is detect the value you want to wrap at and load 0 into your counter at that point

In pseudo-code:

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

...or...

nextCount  = count + 1;
if count == 10000000 then
  resetCount = 1;
梦萦几度 2024-12-19 14:54:29

状态机并不太棘手。使用 localparam (带有宽度,不要忘记宽度,此处未显示,因为它只是一位)来定义状态的标签。然后创建两个 reg 变量(state_regstate_next)。 _reg 变量是您的实际寄存器。 _next 变量是一个“wire reg”(可以分配到组合always 块内部的连线)。要记住的两件事是在组合always块中执行X_next = X_reg;(然后是组合逻辑的其余部分)和在顺序总是阻塞。您可以考虑特殊情况,但如果您坚持这些简单的规则,那么事情应该会顺利进行。我尽量不将实例化用于非常简单的事情,例如加法器,因为 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

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

State machines are not too tricky. Use localparam (with a width, don't forget the width, not shown here because it is just one bit) to define labels for your states. Then create two reg variables (state_reg, state_next). The _reg variable is your actual register. The _next variable is a "wire reg" (a wire that can be assigned to inside a combinational always block). The two things to remember are to do X_next = X_reg; in the combinational always block (and then the rest of the combinational logic) and X_reg <= X_next; in the sequential always block. You can get fancy for special cases but if you stick to these simple rules then things should just work. I try not to use instantiation for very simple things like adders since Verilog has great support for adders.

Since I work with FPGAs, I assign initial values to my registers and I don't use a reset signal. I'm not sure but for ASIC design I think it is the opposite.

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

I found this book to be very helpful. There is also a VHDL version of the book, so you can use both side-by-side as a Rosetta Stone to learn VHDL.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文