在有限状态机 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 输出。它也能正常工作,但我认为将输出与下一状态逻辑保持在一起对于代码维护和养成良好习惯要容易得多。为一项任务快速破解一些代码是一回事,为一个可能在产品生命周期中多次更新的真实产品开发代码是另一回事,可维护性是必不可少的(这是我在工作中必须学习的,因为没有人在大学里教过它)。
所以我正在尝试实现我的第一个 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 输出。它也能正常工作,但我认为将输出与下一状态逻辑保持在一起对于代码维护和养成良好习惯要容易得多。为一项任务快速破解一些代码是一回事,为一个可能在产品生命周期中多次更新的真实产品开发代码是另一回事,可维护性是必不可少的(这是我在工作中必须学习的,因为没有人在大学里教过它)。