如何在Verilog中编码一个状态机

不久前,我写了一篇发布关于什么是状态机的帖子.那篇文章将状态机作为一种概念和方法来组织你的思想。如果您希望在FPGA设计中使用状态机,那么如果不知道如何对其编码,这种想法就没有多大帮助。

正如您在上一篇文章中所了解的,状态机由三个组件组成。下一个状态逻辑、状态寄存器和输出逻辑。

我要讲的第一个部分是下一个状态逻辑。这是直接从状态图编写的。

我将把状态图放在这里作为参考。

步进电机控制器状态图。
步进电机控制器状态图。
这段代码创建了状态变量。这样,每个状态都可以通过名称来引用。
这段代码创建了状态变量。这样,每个状态都可以通过名称来引用。
这段代码创建了保存next_state和present_state变量的状态寄存器。这是状态图中,你所在的圆圈。
这段代码创建了保存next_state和present_state变量的状态寄存器。这是你在状态图上的位置。
这是状态逻辑的第一块。它显示,如果您处于sig4状态,根据输入,下一个状态是什么。这封装了状态图上的箭头。
这是状态逻辑的第一块。它显示,如果您处于sig4状态,根据输入,下一个状态是什么。这封装了状态图上的箭头。
这是下一个状态逻辑的第二个部分。它定义了在sig3或sig2中你接下来要去哪里。
这是下一个状态逻辑的第二个部分。它定义了在sig3或sig2中你接下来要去哪里。
这是下一个状态逻辑的第三块。它定义了在sig1或sig0状态下应该做什么。
这是下一个状态逻辑的第三块。它定义了在sig1或sig0状态下应该做什么。
这是输出逻辑。这在状态图中用紫色文本表示。
这是输出逻辑。这在状态图中用紫色文本表示。
这是国家登记册。它将next_state移动到正向时钟边的present_state。这就是状态图中状态之间移动的原因。
这是国家登记册。它将next_state移动到正向时钟边的present_state。这就是状态图中状态之间移动的原因。

有关此状态图和完整代码的更多信息。你可以在上面查看说明用FPGA驱动步进电机

关于凯特林弗朗茨

查看所有由Kaitlyn Franz→的帖子

关于“如何在Verilog中编写状态机代码”的10条评论

    1. 我已经把Kaitlyn的例子翻译成VHDL:

      图书馆IEEE;
      使用IEEE.STD_LOGIC_1164.ALL;

      实体state_machine
      端口(
      CLK:在STD_LOGIC;
      RST:在STD_LOGIC;
      dir:在STD_LOGIC;
      en:在STD_LOGIC;
      输出:out STD_LOGIC_VECTOR(3 downto 0)
      );
      state_machine结束;

      state_machine的行为是

      定义一个新类型来保存状态值
      type state_type is (STATE_0, STATE_1, STATE_2, STATE_3, STATE_4);

      -present状态将变成状态寄存器
      -present状态由时钟边缘的下一个状态驱动
      信号present_state, next_state: state_type;

      开始

      -控制过渡到下一个状态
      state_register_logic:
      过程(CLK RST)开始
      if (RST = ' 1 ') then -reset逻辑
      present_state < = STATE_0;
      elsif (CLK'event and CLK = '1') then -if时钟上升沿
      present_state
      If (dir = ' 0 ' and en = ' 1 ') then
      next_state < = STATE_3;
      else if (dir = '1' and en = '1') then
      next_state < = STATE_1;
      其他的
      next_state
      If (dir = ' 0 ' and en = ' 1 ') then
      next_state < = STATE_2;
      else if (dir = '1' and en = '1') then
      next_state < = STATE_4;
      其他的
      next_state
      If (dir = ' 0 ' and en = ' 1 ') then
      next_state < = STATE_1;
      else if (dir = '1' and en = '1') then
      next_state < = STATE_3;
      其他的
      next_state
      If (dir = ' 0 ' and en = ' 1 ') then
      next_state < = STATE_4;
      else if (dir = '1' and en = '1') then
      next_state < = STATE_2;
      其他的
      next_state
      如果(en = ' 1 ')则
      next_state < = STATE_1;
      其他的
      next_state
      sigout
      sigout
      sigout
      sigout
      sigout < = " 0000 ";
      结束;
      结束过程;

      端行为;

  1. 嘿,

    好文章,谢谢。

    我想知道你是否能提供一篇关于设计一个简单的数字相位调制器的博客文章,我对构建我自己的软件定义无线电感兴趣,应用我的FPGA知识设计无线电的大多数数字组件将是惊人的。

    多问候
    阿卜杜拉

  2. 嗨,阿卜杜拉,
    我自己没有做过任何数字相位调制,但从我简短的互联网搜索看来,它类似于PWM。如果是这种情况,我正在编写一篇关于使用PWM的FPGA使用伺服的指示和博客文章。应该很快就会公布。

    如果没有,在此期间我会在forum.blog.digilentinc.com上发表文章。Digilent论坛的一位成员可能已经做到了这一点,他可能比我更能帮上忙。

    凯特林

  3. 嗨,凯特林,
    这些天我正在学习Verilog和SysVerilog,我用你的博客作为一个测试,只是引用了状态图。请签出我的代码,我目前正在为它编写一个测试平台的过程中。

    //***************************************************************************************
    模块FSM(输入i_enable,输入i_dir,输入i_clk,输入i_rst_n,输出reg [' WIDTH-1:0] o_output);
    //***************************************************************************************
    参数Sig0 = 3'b000;
    参数Sig1 = 3'b001;
    参数Sig2 = 3'b010;
    参数Sig3 = 3'b011;
    参数Sig4 = 3'b100;
    参数Sig5 = 3'b101;/ / NOTUSED
    参数Sig6 = 3'b110;/ / NOTUSED
    参数Sig7 = 3'b111;/ / NOTUSED

    reg [' WIDTH-2:0] curr_state;
    reg [' WIDTH-2:0] next_state;

    //存储当前状态的顺序逻辑
    总是@ (posedge i_clk或negedge i_rst_n)开始
    如果(~ i_rst_n)
    curr_state < = Sig0;
    其他的
    curr_state < = next_state;
    结束

    //下一状态逻辑的组合逻辑
    always @ (curr_state, i_enable, i_dir) begin // Mealy机器的输入和当前状态
    案例(curr_state)
    Sig0:开始
    如果(i_enable)
    next_state < = Sig1;
    其他的
    next_state <= Sig0 //默认值
    结束
    Sig1:开始
    If (i_enable && i_dir)
    next_state < = Sig2;
    Else if (i_enable && !i_dir)
    next_state < = Sig4;
    else if (i_enable !)
    next_state < = Sig0;
    结束
    Sig2:开始
    If (i_enable && i_dir)
    next_state < = Sig3;
    Else if (i_enable && !i_dir)
    next_state < = Sig1;
    else if (i_enable !)
    next_state < = Sig0;
    结束
    Sig3:开始
    If (i_enable && i_dir)
    next_state < = Sig4;
    Else if (i_enable && !i_dir)
    next_state < = Sig2;
    else if (i_enable !)
    next_state < = Sig0;
    结束
    Sig4:开始
    If (i_enable && i_dir)
    next_state < = Sig1;
    Else if (i_enable && !i_dir)
    next_state < = Sig3;
    else if(启用)
    next_sate < = Sig0;
    结束
    endcase / / curr_state
    结束

    总是@ (i_clk)开始
    如果(~ i_rst_n)
    o_output < = {4 {1 'b0}};
    其他的开始
    案例(curr_state)
    Sig0: o_output <= {4{1'b0}};
    Sig1: o_output <= 4'b1000;
    Sig2: o_output <= 4'b0100;
    Sig3: o_output <= 4'b0010;
    Sig4: o_output <= 4'b0001;
    默认值:o_output <= 4'b1000;
    endcase / / curr_state
    结束
    结束

    endmodule / / FSM

    1. 嘿,亚希尔,
      我建议在Forum.blog.digilentinc.com上发表文章。有一整个兴奋的FPGA爱好者社区可以帮助您编写代码。

留下一个回复

您的电子邮件地址将不会被公布。必填字段被标记