将有限状态机图转换为Verilog代码

将有限状态机图转换为Verilog代码,verilog,finite-automata,state-machine,Verilog,Finite Automata,State Machine,我需要将下面的有限状态图转换为Verilog代码。 我已经在下面介绍了我编写的代码。在我看来,我已经正确地实现了所有逻辑,并且代码适用于前几个输入组合。然而,它最终失败了,我似乎不明白为什么 module FiniteStateMachine(output reg out_z, input in_x, in_y, clk, reset_b); parameter S0 = 2'b00, S1 = 2'b01, S2 = 2'b10, S3 = 2'b11; reg

我需要将下面的有限状态图转换为Verilog代码。

我已经在下面介绍了我编写的代码。在我看来,我已经正确地实现了所有逻辑,并且代码适用于前几个输入组合。然而,它最终失败了,我似乎不明白为什么

module FiniteStateMachine(output reg out_z, input in_x, in_y, clk, reset_b);

    parameter   S0 = 2'b00, S1 = 2'b01, S2 = 2'b10, S3 = 2'b11;
    reg         state;

    always @(posedge clk, negedge reset_b) begin

        // set state
        if (reset_b || !in_x) state <= S0;
        else
            case (state)
                S0: state <= (in_y == 1) ? S1 : S3;
                S1: state <= S2;
                S2: state <= S3;
                S3: state <= S3;
            endcase

        // set output
        out_z <= (state == S2 || state == S3) ? 1 : 0;

    end

endmodule
模块FiniteTestMachine(输出reg out_z、输入in_x、in_y、clk、复位_b);
参数S0=2'b00,S1=2'b01,S2=2'b10,S3=2'b11;
注册州;
始终@(posedge clk,NEGDEDGE reset_b)开始
//设定状态

如果(reset_b | | | |!in_x)状态看起来您试图通过将in_x中的
视为二次重置来简化FSM。我不认为这种简化是正确的,不管怎样,你试图变得太聪明。只需写出每种情况下的所有转换,要么作为嵌套的
case
语句,要么作为每个状态下的一系列
if
s。例如:

case (state)
  S0: case ({in_x, in_y})
    2'b00: state <= S0;
    2'b01: state <= S0;
    2'b10: state <= S3;
    2'b11: state <= S1;
  endcase
  S2: case ({in_x, in_y})
    …
案例(状态)
S0:大小写({in_x,in_y})

2'b00:state看起来您试图通过将
在_x
中作为辅助重置来简化FSM。我不认为这种简化是正确的,不管怎样,你试图变得太聪明。只需写出每种情况下的所有转换,要么作为嵌套的
case
语句,要么作为每个状态下的一系列
if
s。例如:

case (state)
  S0: case ({in_x, in_y})
    2'b00: state <= S0;
    2'b01: state <= S0;
    2'b10: state <= S3;
    2'b11: state <= S1;
  endcase
  S2: case ({in_x, in_y})
    …
案例(状态)
S0:大小写({in_x,in_y})

2'b00:state实际上,您的实现目前存在许多问题:

  • 当您的
    state
    变量需要为两位时,它只有一位宽:
    reg state
    ->
    reg[1:0]state
  • 很可能您实际上不想让
    out_z
    成为寄存器,因为它应该跟随同一时钟上的状态,而不是之后的时钟周期
  • 您的
    reset_b
    逻辑是向后的,对于negedge重置,您需要通过
    检查断言!重置\u b
    ~重置\u b
  • 如前所述,您确实不应该将异步重置与任何同步输入相结合,甚至不应该将同步重置与
    reset\u b
    in\u x
    相结合。虽然这在模拟中可以很好地工作,但大多数合成工具可能无法正确处理它。在学习Verilog时,我犯了同样的错误,花了好几天时间才发现并纠正
  • 下面是一个更清晰的代码版本,其中实施并注释了此修复程序,因此您可以看到以下4点:

    module FiniteStateMachine(output reg out_z, input in_x, in_y, clk, reset_b);
    
      parameter S0 = 2'b00, S1 = 2'b01, S2 = 2'b10, S3 = 2'b11;
      reg [1:0] state; // Fix state variable
    
      // Set output combinationally (no need for turning operator)
      always @(*) begin
        out_z = (state == S2 || state == S3);
      end
    
      always @(posedge clk, negedge reset_b) begin
        // Invert the logic for reset and keep it separate
        if (!reset_b) begin
          state <= S0;
        end
        else begin
          // You can case on inputs as was suggested, but I think casing on state is fine
          // I include only logic for changing state
          case (state)
            S0: begin
              if (in_x && in_y) begin
                state <= S1;
              end
              else if (in_x && !in_y) begin
                state <= S3;
              end
            end
            S1: begin
              if (in_x) begin
                state <= S2;
              end
              else begin
                state <= S0;
              end
            end
            S2:  begin
              if (in_x) begin
                state <= S3;
              end
              else begin
                state <= S0;
              end
            end
            S3: begin
              if (!in_x) begin
                state <= S0;
              end
            end
          endcase
        end
      end
    
    endmodule
    
    模块FiniteTestMachine(输出reg out_z、输入in_x、in_y、clk、复位_b);
    参数S0=2'b00,S1=2'b01,S2=2'b10,S3=2'b11;
    注册[1:0]状态;//固定状态变量
    //组合设置输出(无需转动操作器)
    始终@(*)开始
    out_z=(状态==S2 | |状态==S3);
    结束
    始终@(posedge clk,NEGDEDGE reset_b)开始
    //反转复位逻辑,并将其分开
    如果(!reset_b)开始
    
    state实际上,您的实现目前存在许多问题:

  • 当您的
    state
    变量需要为两位时,它只有一位宽:
    reg state
    ->
    reg[1:0]state
  • 很可能您实际上不想让
    out_z
    成为寄存器,因为它应该跟随同一时钟上的状态,而不是之后的时钟周期
  • 您的
    reset_b
    逻辑是向后的,对于negedge重置,您需要通过
    检查断言!重置\u b
    ~重置\u b
  • 如前所述,您确实不应该将异步重置与任何同步输入相结合,甚至不应该将同步重置与
    reset\u b
    in\u x
    相结合。虽然这在模拟中可以很好地工作,但大多数合成工具可能无法正确处理它。在学习Verilog时,我犯了同样的错误,花了好几天时间才发现并纠正
  • 下面是一个更清晰的代码版本,其中实施并注释了此修复程序,因此您可以看到以下4点:

    module FiniteStateMachine(output reg out_z, input in_x, in_y, clk, reset_b);
    
      parameter S0 = 2'b00, S1 = 2'b01, S2 = 2'b10, S3 = 2'b11;
      reg [1:0] state; // Fix state variable
    
      // Set output combinationally (no need for turning operator)
      always @(*) begin
        out_z = (state == S2 || state == S3);
      end
    
      always @(posedge clk, negedge reset_b) begin
        // Invert the logic for reset and keep it separate
        if (!reset_b) begin
          state <= S0;
        end
        else begin
          // You can case on inputs as was suggested, but I think casing on state is fine
          // I include only logic for changing state
          case (state)
            S0: begin
              if (in_x && in_y) begin
                state <= S1;
              end
              else if (in_x && !in_y) begin
                state <= S3;
              end
            end
            S1: begin
              if (in_x) begin
                state <= S2;
              end
              else begin
                state <= S0;
              end
            end
            S2:  begin
              if (in_x) begin
                state <= S3;
              end
              else begin
                state <= S0;
              end
            end
            S3: begin
              if (!in_x) begin
                state <= S0;
              end
            end
          endcase
        end
      end
    
    endmodule
    
    模块FiniteTestMachine(输出reg out_z、输入in_x、in_y、clk、复位_b);
    参数S0=2'b00,S1=2'b01,S2=2'b10,S3=2'b11;
    注册[1:0]状态;//固定状态变量
    //组合设置输出(无需转动操作器)
    始终@(*)开始
    out_z=(状态==S2 | |状态==S3);
    结束
    始终@(posedge clk,NEGDEDGE reset_b)开始
    //反转复位逻辑,并将其分开
    如果(!reset_b)开始
    
    状态解释你所说的“工作”和“失败”是什么意思。哪个信号应该切换状态<代码>案例(状态)
    不正确。我想你应该使用类似于
    的case({in_x,in_y})
    来代替。另外,我建议对状态和条件使用不同的名称。@dave_59为测试它而编写的测试台记录了不正确的输出。@Serge该状态应在时钟上升沿更改,或在重置下降沿重置为状态0。请解释“工作”和“失败”的含义.哪个信号应该切换状态<代码>案例(状态)
    不正确。我想你应该使用类似于
    的case({in_x,in_y})
    来代替。我还建议对状态和条件使用不同的名称。@dave_59为测试它而编写的测试台记录了不正确的输出。@Serge状态应该在时钟上升沿改变,或者在重置的下降沿重置为状态0。我实现了此逻辑并再次测试了代码,但我的代码的问题似乎与out_z设置为的值有关。我实现了此逻辑并再次测试了代码,但我的代码的问题似乎与out_z设置为的值有关。