有限状态机FSM (自动售货机Verilog实现) ) ) ) ) ) ) ) ) )。
FSM
状态机是一种可以描述具有逻辑顺序和时间顺序的事件的方法。
状态机有两种类型: Mealy型和Moore型。
Moore型状态机的输出只与当前状态有关,但Mealy型状态机的输出不仅由当前状态控制,还由输入直接控制,可能与状态无关。
使用Verilog编写简单的状态机设计时,必须将状态机状态中的组合逻辑与状态机控制器的控制分开。
通过隔离功能,可以在逻辑部分的代码中使用块赋值语句
状态更新逻辑包含状态寄存器,不能被外围设备读取。 逻辑将输入和当前状态值组合为输出赋值,以更改状态机的下一个状态。
同步时序电路的设计方法
逻辑抽象,得到电路的状态转移图或状态转移表
简化状态
状态分配(状态代码:Binary,Gray,One-Hot ) ) ) ) ) ) ) )。
Verilog根据最简单的状态转移图编程,检查设计的电路是否能自行启动
四个要素
当前输入
现在的状态
下一个状态
当前输出值
代码样式
一段式
当前的状态、下一个状态、当前的输出值都写入一个always块
两段式
当前状态、下一个状态和当前输出值将写入两个always块中
注意:有三种这样的组合方法和写这两个always块的三种方法。
三段式法
当前状态、下一状态和当前输出值写入每个always块,这需要三个always块。
自动售货机Verilog的实现
设计说明
设计简单的数字电路用于电子售报机的老虎机。
把报纸的价格定为15分。
投币器只能接受5分和1角的硬币。
必须提供适当数量的零钱,老虎机不找钱。
合法硬币组合包括一枚五分硬币、一枚一角硬币、三枚五分硬币、一枚一角硬币和一枚五分硬币。 2个1角的硬币是合法的,但是老虎机不给找零。
电路说明
投入硬币后,1、2位的信号coin[1:0]将被发送到数字电路。 该信号在全局clock信号的下一个下降沿取值,总是正确地保持一定的周期。
数字电路的输出为1位。 每当投入硬币总数达到15点以上时,输出信号newspaper就会成为高电平,维持1个时钟周期。 售货机的门也被打开。
reset信号可以重置有限状态机。 设为同步复位。
有限状态机FSM
该数字电路的功能可以用有限状态机表示。
输入: 2位,coin[1:0]。 如果没有硬币,则x0=2'b00; 有5分硬币时,x5=2'b01; 如果有1角硬币,则x10=2'b10。
输出: 1位,newspaper。 newspaper=1'b1时,打开门。
状态:四种状态。 s0=0分,s5=5分,s10=10分,s15=15分。
状态机转换图
状态
钱的数量
输入
硬币[1:0]
s0
0分
x0
2'b00
s5
五分
x5
2'b01
s10
十分
x10
2'b10
s15
十五分
_
没关系
验证日志说明
设计代码
module vend (
input [1:0] coin,
输入时钟、
输入重置,
输出新空间
);
//声明有限状态机的内部状态
wire [1:0] NEXT_STATE;
reg [1:0] PRES_STATE;
//状态代码
参数s0=2' b00;
参数S5=2' b01;
参数S10=2' b10;
参数s15=2' b11;
//同步复位,在时钟正转沿触发的状态触发器
always@(posedge clock )
比根
if(reset==1'B1 ) ) ) )。
PRES_STATE=s0;
else
PRES_STATE=NEXT_STATE;
结束
//组合逻辑
函数[ 2:0 ] FSM; //状态变化和输出的组合逻辑
辑input [1:0] fsm_coin;
input [1:0] fsm_PRES_STATE;
reg fsm_newspaper;
reg [1:0] fsm_NEXT_STATE;
begin
case(fsm_PRES_STATE)
s0: //状态为s0
begin
if(fsm_coin == 2'b10)
begin
fsm_newspaper = 1'b0;
fsm_NEXT_STATE = s10;
end
else if(fsm_coin == 2'b01)
begin
fsm_newspaper = 1'b0;
fsm_NEXT_STATE = s5;
end
else
begin
fsm_newspaper = 1'b0;
fsm_NEXT_STATE = s0;
end
end
s5: //状态为s5
begin
if(fsm_coin == 2'b10)
begin
fsm_newspaper = 1'b0;
fsm_NEXT_STATE = s15;
end
else if(fsm_coin == 2'b01)
begin
fsm_newspaper = 1'b0;
fsm_NEXT_STATE = s10;
end
else
begin
fsm_newspaper = 1'b0;
fsm_NEXT_STATE = s5;
end
end
s10: //状态为s10
begin
if(fsm_coin == 2'b10)
begin
fsm_newspaper = 1'b0;
fsm_NEXT_STATE = s15;
end
else if(fsm_coin == 2'b01)
begin
fsm_newspaper = 1'b0;
fsm_NEXT_STATE = s15;
end
else
begin
fsm_newspaper = 1'b0;
fsm_NEXT_STATE = s10;
end
end
s15: //状态为s15
begin
fsm_newspaper = 1'b1;
fsm_NEXT_STATE = s0;
end
endcase
fsm = {fsm_newspaper,fsm_NEXT_STATE};
end
endfunction
//每当硬币放入或当前状态改变时,组合逻辑动作
assign {newspaper,NEXT_STATE} = fsm(coin,PRES_STATE);
endmodule
testbench
module vend_tb;
reg clock;
reg reset;
reg [1:0] coin;
wire newspaper;
always #20 clock = ~clock;
initial
begin
clock = 0;
reset = 1;
#100;
reset = 0;
@(posedge clock) coin[1:0] = 2'b00;
@(posedge clock);
@(posedge clock) coin[1:0] = 2'b01;
@(posedge clock);
@(posedge clock) coin[1:0] = 2'b10;
@(posedge clock);
@(posedge clock) coin[1:0] = 2'b10;
@(posedge clock);
@(posedge clock) coin[1:0] = 2'b10;
@(posedge clock);
@(posedge clock) coin[1:0] = 2'b00;
@(posedge clock);
@(posedge clock) coin[1:0] = 2'b01;
@(posedge clock);
@(posedge clock) coin[1:0] = 2'b01;
@(posedge clock);
@(posedge clock) coin[1:0] = 2'b01;
#200 $finish;
end
initial begin
$fsdbDumpfile("test.fsdb");
$fsdbDumpvars();
end
vend u_vend(
.coin(coin),
.clock(clock),
.reset(reset),
.newspaper(newspaper)
);
endmodule
仿真结果
参考资料
[1]. Verilog HDL数字设计与综合(第二版) [美]Simir Palnitkar 著 夏宇闻 等译
[2]. Verilog 数字VLSI设计教程 [美] John Willianms 著 pcdqd 等译
[3]. 有限状态机 FSM 设计
[4]. 有限狀態機FSM coding style整理 (SOC) (Verilog)