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

Converting finite state machine diagram to Verilog code

我需要将下面的有限状态图转换成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

您似乎试图通过将 in_x 视为二次重置来简化 FSM。我认为这种简化是不正确的,而且无论如何你都想变得太聪明了。只需写出每个案例的所有转换,作为嵌套的 case 语句或作为每个状态下的一系列 if。例如:

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})
    …

您现在的实施实际上存在许多问题:

  1. 你的 state 变量只有一位宽,而它需要是两位:reg state -> reg [1:0] state
  2. 您可能实际上并不想让 out_z 成为一个寄存器,因为它应该遵循同一时钟的状态,而不是之后的一个时钟周期。
  3. 你的reset_b逻辑是倒退的,对于negedge重置,你需要通过!reset_b~reset_b检查断言。
  4. 如前所述,您真的不应该像 reset_bin_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