三段式状态机训练例子:
softdrinkFSM-----饮料自动投币售卖机控制电路设计
softdrinkFSM.v设计代码:
module softdrinkFSM(
input clk,
input rst_n,
input reg op_start, //开始1/结束标志
input reg cancel_flag, //取消1标志
input reg [1:0] coin_val, //收到币值,2’b01—0.5yuan,2’b10—1yuan
output reg hold_ind, //空闲1/繁忙标志
output reg charge_ind, //找零/退币标志1
output reg [2:0] charge_val,//退币/找零币值 3’b001—0.5yuan,依次递推。
output reg drinktk_ind, //出饮料1
output reg [2:0] currentstate,
output reg [2:0] nextstate
);
parameter S0=3’b000;
parameter S1=3’b001;
parameter S2=3’b010;
parameter S3=3’b011;
parameter S4=3’b100;
parameter S5=3’b101;
parameter S6=3’b110;
//1段:同步状态转移,次态迁移到现态 时序逻辑
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
currentstate <= S0;
else
currentstate <= nextstate;
end
//2段:状态跳转,当前状态判断接下来的状态 组合逻辑
always @(currentstate or coin_val or cancel_flag or op_start or rst_n)
begin
if (!rst_n)
nextstate = S0;
else
case(currentstate)
S0:
if(op_start)
if(coin_val == 2’b01) nextstate = S1;
else if(coin_val == 2’b10) nextstate = S2;
// else nextstate = S0;
S1:
if(cancel_flag) nextstate = S0;
else if(coin_val == 2’b01) nextstate = S2;
else if(coin_val == 2’b10) nextstate = S3;
S2:
if(cancel_flag) nextstate = S0;
else if(coin_val == 2’b01) nextstate = S3;
else if(coin_val == 2’b10) nextstate = S4;
S3:
if(cancel_flag) nextstate = S0;
else if(coin_val == 2’b01) nextstate = S4;
else if(coin_val == 2’b10) nextstate = S5;
S4:
if(cancel_flag) nextstate = S0;
else if(coin_val == 2’b01) nextstate = S5;
else if(coin_val == 2’b10) nextstate = S6;
S5:
nextstate = S0;
S6:
nextstate = S0;
default:
nextstate = S0;
endcase
end
//3段:次态描述输出。时序逻辑
always @(currentstate)
begin
if(currentstate==S0)hold_ind=1’b1;
else hold_ind=1’b0;
end
always @(currentstate)
begin
if((currentstate == S5) || (currentstate == S6)) drinktk_ind=1’b1;
else drinktk_ind=1’b0;
end
always @(currentstate or cancel_flag)
begin
if(currentstate == S0) charge_ind = 1’b0;
else if(currentstate == S6) charge_ind=1’b1;
else if(cancel_flag) charge_ind=1’b1;
else charge_ind=1’b0;
end
always @(currentstate or cancel_flag)
if(currentstate == S0) charge_val=3’b000;
else if(currentstate == S6) charge_val=3’b001;
else if(cancel_flag==1)
begin
case(currentstate)
S1:charge_val=3’b001;
S2:charge_val=3’b010;
S3:charge_val=3’b011;
S4:charge_val=3’b100;
default :charge_val=3’b000;
endcase
end
else charge_val=3’b000;
endmodule
softdrinkFSM_tb.v仿真测试文件:
仿真效果是:点击开始,先投币0.5元,再投币1元,再投币0.5元,点击取消,点击结束。
注意:由于是仿真,投币1元结束后(也就是信号持续1个周期后)立即将取消信号拉高。
仿真文件编程步骤:
大的方面就三个:1.监测目标文件的输出;2.给目标文件输入;3.例化。
细节化:
1、timescale—>2、module xxx();—>3、接口信号定义—>4、输出时钟,编写输出信号—>5、例化。—>endmodule
`timescale 1ns/1ps
module softdrinkFSM_tb();
reg clk;
reg rst_n;
reg op_start;
reg cancel_flag;
reg [1:0] coin_val;
wire hold_ind;
wire charge_ind;
wire drinktk_ind;
wire [2:0] charge_val;
wire [2:0] currentstate;
wire [2:0] nextstate;
always #25 clk = ~clk;
initial begin
clk=1’b0;
rst_n=1’b1;
op_start=1’b0;
cancel_flag=1’b0;
coin_val=2’b00;
#50 rst_n = 1’b0;
#50 rst_n = 1’b1;
#50 op_start = 1’b1;//
#75 coin_val= 2’b01;
#50 coin_val= 2’b10;
#50 coin_val= 2’b01;
#50 cancel_flag =1’b1;
#50 op_start = 1’b0;
#1000 $stop;//仿真2000ns后停止。
end
softdrinkFSM u1(
.clk(clk),
.rst_n(rst_n),
.op_start(op_start), //开始1/结束标志
.cancel_flag(cancel_flag), //取消1标志
.hold_ind(hold_ind), //空闲1/繁忙标志
.charge_ind(charge_ind), //找零/退币标志1
.coin_val(coin_val),
.charge_val(charge_val),
.drinktk_ind(drinktk_ind),
.currentstate(currentstate),
.nextstate(nextstate)
);
endmodule
仿真波形:
总结:经过反复仿真测试,表明:三段式状态机的第三段应该用currentstate做状态判断条件。
(参考资料:《verilog数字系统设计教程》第四版 夏宇闻著)