目录
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)begin
if(!rst)
curr_state <= s0;
else
curr_state <= next_state;
end
//第二段 转移状况
always @(*)begin
case(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?
end
s1:begin
if(d1) next_state = s2;
else if(d2) next_state = s4;
else if(d3) next_state = s5;
else next_state = next_state;
end
s2:begin
if(d1) next_state = s4;
else if(d2) next_state = s3;
else if(d3) next_state = s6;
else next_state = next_state;
end
s3,s4,s5,s6:begin next_state = s0;end
default: begin next_state = s0;end
endcase
end
//第三段 状态输出 moore FSM
always @(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; //出货标志
else
out1 <= 0;
end
always @(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;
else
out2 <= 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 begin
clk = 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)begin
if(!rst)
curr_state <= s0;
else
curr_state <= next_state;
end
//第二段 转移状况
always @(*)begin
case(curr_state)
s0: begin
if(d1) next_state = s1;
else if(d2) next_state = s2;
else next_state = next_state;
end
s1: begin
if(d1) next_state = s2;
else if(d2) next_state = s3;
else next_state = next_state;
end
s2: begin
if(d1) next_state = s3;
else if(d2) next_state = s4;
else next_state = next_state;
end
s3: 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;
end
end
s4: 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;
end
end
s5: begin next_state = s0; end
s6: begin next_state = s0; end
default: begin next_state = s0;end
endcase
end
/********* 第三段 状态输出 moore FSM ************/
//出货标志
always @(posedge clk or negedge rst)begin
if(!rst)begin
out1 <= 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 begin
out1 <= 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
else
out3 <= 2'b0;
end
//*************code***********//
endmodule
仿真文件
仿真图如下:
3、状态机基本知识
以上是mealy和moore型状态机的实现区别,注意在代码里理解!