在有限状态机 verilog 中处理大量输出

Dealing with lots of outputs in a finite state machine verilog

所以我正在尝试实现我的第一个 FSM,但我感到非常困惑。

代码有点长,总结一下: 我从声明输入和输出开始 然后声明声明(我有五个加三个占位符) 然后Current state赋值,是sequential

always @(posedge clk)
begin
    if (rst == 1'b1)
        Current_State <= MainGreen;
    else
        Current_State <= Next_state;
end

然后……我迷路了。我最初只有一个分配 next_state 和输出的大型 ol' 时序电路,但这很混乱/可能有很多错误。

我现在只有 next_state 逻辑,但与输出无关:

always @*
begin
    Next_state = Current_State;
    case (Current_State)

        MainGreen:
        begin
            if (count && expired)
            begin
                Next_state = MainYel;
            end
        end

        MainYel:
        begin
            if (WR && expired)
                Next_state = AllRed;
            else if (expired)
                Next_state = SideGreen;
        end

        AllRed:
        begin
            if (expired)
                Next_state = SideGreen;
        end

        SideGreen:
        begin
            if(sensor && expired)
                Next_state = SideYel;
        end

        SideYel:
        begin
            if(expired)
                Next_state = MainGreen;
        end
    endcase
    end

我有大约八个仅基于状态的输出和四个基于状态和输入的输出。我应该如何分配它们?

你已经完成了 90%。有两种方法可以继续(可能不止这些,但我会给你我认为最好的两个选择):

首先,您是否有很多输出只针对一小部分州进行断言?如果是这样,我会在你的组合总是块中推荐这样的东西:

always @*
begin
  // default output values
  output1 = 1'b0;
  output2 = 1'b0;
  output3 = 1'b0;
  ....
  case (Current_State)
    STATE1: 
    begin
      output2 = 1'b1;
      // calculate next state
      ...
    end

    STATE2: 
    begin
      output4 = 1'b1;
      // calculate next state
      ...
    end
    ...
  endcase
end 

这可能是对状态机进行编码的最有效方式,因为您不需要定义每个状态的每个输出。现在,如果您让每个输出在许多不同的状态下处于活动状态,那么您可能更容易在 case 语句中定义每个状态下的这些输出。

我不推荐的最后一种方法是在单独的赋值语句中派生 sm 输出。它也能正常工作,但我认为将输出与下一状态逻辑保持在一起对于代码维护和养成良好习惯要容易得多。为一项任务快速破解一些代码是一回事,为一个可能在产品生命周期中多次更新的真实产品开发代码是另一回事,可维护性是必不可少的(这是我在工作中必须学习的,因为没有人在大学里教过它)。