【附源码】基于fpga的自动售货机(三段式状态机)
目录
1、VL38 自动贩售机1
题目介绍
思路分析
代码实现
仿真文件
2、VL39 自动贩售机2
题目介绍:
题目分析
代码实现
仿真文件
3、状态机基本知识
1、VL38 自动贩售机1
题目介绍
设计一个自动贩售机,输入货币有三种,为0.5/1/2元,饮料价格是1.5元,要求进行找零,找零只会支付0.5元。
ps:
1、投入的货币会自动经过边沿检测并输出一个在时钟上升沿到1,在下降沿到0的脉冲信号
2、注意rst为低电平复位
信号示意图:

波形示意图:

思路分析

代码实现
module seller1(input wire clk ,input wire rst ,input wire d1 , //0.5元input wire d2 , //1.0元input wire d3 , //2.0元output reg out1, //饮料output reg [1:0]out2 //零钱
);
//*************code***********//parameter [2:0] s0 = 3'b000,s1 = 3'b001, s2 = 3'b010,s3 = 3'b011,s4 = 3'b100, s5 = 3'b101,s6 = 3'b110;reg [2:0] curr_state;
reg [2:0] next_state;//第一段 状态转移
always @(posedge clk or negedge rst)beginif(!rst)curr_state <= s0;elsecurr_state <= next_state;end//第二段 转移状况
always @(*)begincase(curr_state)s0:begin if(d1) next_state = s1;else if(d2) next_state = s2;else if(d3) next_state = s3;else next_state = next_state; //为什么保持原值next_state,而不是s0?ends1:begin if(d1) next_state = s2;else if(d2) next_state = s4;else if(d3) next_state = s5;else next_state = next_state;ends2:begin if(d1) next_state = s4;else if(d2) next_state = s3;else if(d3) next_state = s6;else next_state = next_state;ends3,s4,s5,s6:begin next_state = s0;end default: begin next_state = s0;endendcase
end//第三段 状态输出 moore FSMalways @(posedge clk or negedge rst)begin //为什么用时序电路,而不是组合电路?if(!rst)out1 <= 0;else if( next_state == s3 || next_state == s4 || next_state == s5 || next_state == s6)out1 <= 1; //出货标志elseout1 <= 0; endalways @(posedge clk or negedge rst)begin //为什么用时序电路,而不是组合电路?if(!rst)out2 <= 0;else if(next_state == s3)out2 <= 2'd1; //找零5毛的数量 else if(next_state == s5)out2 <= 2'd2; else if(next_state == s6)out2 <= 2'd3; elseout2 <= 2'b0; end//*************code***********//
endmodule
针对代码中的问题“为什么保持原值next_state,而不是s0?”
答:如下图所示,如果保持s0,因为是组合逻辑,且输入信号d1为半个时钟周期,那么就会导致next_state在s1和s0之间翻转,而不是保持正确的状态s1。
参考这个回答:
仿真文件
仿真图:

仿真代码:
module tb_seller1;reg clk;reg rst;reg d1,d2,d3; wire out1;wire [1:0] out2; //1、初始化
initial beginclk = 0;rst = 0;d1 = 0;d2 = 0;d3 = 0;
end //2、产生激励
always #5 clk = ~clk;initial begin#10;rst = 1'b1;#20;@(posedge clk); {d1,d2,d3}=3'b100; //0.5@(posedge clk); {d1,d2,d3}=3'b000; #50; @(posedge clk); {d1,d2,d3}=3'b010; //1.5@(posedge clk); {d1,d2,d3}=3'b000; #30; @(posedge clk); {d1,d2,d3}=3'b100; //0.5@(posedge clk); {d1,d2,d3}=3'b000; #60; @(posedge clk); {d1,d2,d3}=3'b100; //1@(posedge clk); {d1,d2,d3}=3'b000; #50; @(posedge clk); {d1,d2,d3}=3'b001; //3@(posedge clk); {d1,d2,d3}=3'b000; #50; @(posedge clk); {d1,d2,d3}=3'b001; //2@(posedge clk); {d1,d2,d3}=3'b000; #30; @(posedge clk); {d1,d2,d3}=3'b100; //0.5@(posedge clk); {d1,d2,d3}=3'b000; #60; @(posedge clk); {d1,d2,d3}=3'b001; //2.5@(posedge clk); {d1,d2,d3}=3'b000; #50; @(posedge clk); {d1,d2,d3}=3'b010; //1@(posedge clk); {d1,d2,d3}=3'b000; #60; @(posedge clk); {d1,d2,d3}=3'b010; //2@(posedge clk); {d1,d2,d3}=3'b000;
end //3、仿真暂停
initial begin#1000 $finish();
end //4、实例化
seller1 u1_seller1(.clk(clk),.rst(rst),.d1 (d1), //0.5元.d2 (d2), //1.0元.d3 (d3), //2.0元.out1(out1), //饮料.out2(out2) //零钱
);endmodule
2、VL39 自动贩售机2
题目介绍:
设计一个自动贩售机,输入货币有两种,为0.5/1元,饮料价格是1.5/2.5元,要求进行找零,找零只会支付0.5元。
ps:
1、投入的货币会自动经过边沿检测并输出一个在时钟上升沿到1,在下降沿到0的脉冲信号
2、此题忽略出饮料后才能切换饮料的问题
注意rst为低电平复位
波形示意图:

题目分析

代码实现
module seller2(input wire clk ,input wire rst ,input wire d1 , //0.5元input wire d2 , //1.0元input wire sel , //0选择1.5元、1选择2.5元output reg out1, //饮料1(1.5元)output reg out2, //饮料2(2.5元)output reg [1:0]out3 //零钱);
//*************code***********//parameter [2:0] s0 = 3'b000,s1 = 3'b001, s2 = 3'b010,s3 = 3'b011,s4 = 3'b100, s5 = 3'b101,s6 = 3'b110;reg [2:0] curr_state;
reg [2:0] next_state;//第一段 状态转移
always @(posedge clk or negedge rst)beginif(!rst)curr_state <= s0;elsecurr_state <= next_state;end//第二段 转移状况
always @(*)begincase(curr_state)s0: beginif(d1) next_state = s1;else if(d2) next_state = s2;else next_state = next_state; ends1: begin if(d1) next_state = s2;else if(d2) next_state = s3;else next_state = next_state; ends2: beginif(d1) next_state = s3;else if(d2) next_state = s4;else next_state = next_state; ends3: begin if(!sel) //选择饮料是1.5元还是2元begin next_state = s0; end else begin if(d1) next_state = s4;else if(d2) next_state = s5;else next_state = next_state;endends4: begin if(!sel) begin next_state = s0; end else begin if(d1) next_state = s5;else if(d2) next_state = s6;else next_state = next_state;endend s5: begin next_state = s0; ends6: begin next_state = s0; end default: begin next_state = s0;endendcase
end/********* 第三段 状态输出 moore FSM ************///出货标志
always @(posedge clk or negedge rst)begin if(!rst)beginout1 <= 0;out2 <= 0;end else if(sel==0 && (next_state == s3 || next_state == s4) )out1 <= 1; //饮料1 else if(sel==1 && (next_state == s5 || next_state == s6) )out2 <= 1; //饮料2 else beginout1 <= 0;out2 <= 0;end
end//找零数量
always @(posedge clk or negedge rst)begin if(!rst)out3 <= 0; else if(sel==0 && (next_state == s4) )out3 <= 2'd1; //饮料1 else if(sel==1 && (next_state == s6) )out3 <= 2'd1; //饮料2 elseout3 <= 2'b0;
end//*************code***********//
endmodule
仿真文件
仿真图如下:

3、状态机基本知识







以上是mealy和moore型状态机的实现区别,注意在代码里理解!
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!


