1.题目描述
注意:题目中输入d3应该换成饮料选择信号sel
仿真时序:
2.题目分析
注意:分析方法和步骤为fpga设计时序逻辑电路的方法和步骤,电路采用meely型。
(1)确定输入,输出和电路状态
本题已经给出了输入和输出及对应变量,如果题目没有给出就需要自己定义。
输入:
变量 | 说明 |
---|---|
d1 | 投入0.5元 |
d2 | 投入1元 |
sel | 0表示购买1.5元的饮料,1表示购买2.5元饮料 |
输出:
变量 | 说明 |
---|---|
out1 | 输出1.5元饮料 |
out2 | 输出2.5元饮料 |
out3 | 找零0.5元 |
状态定义:
分析:有两种饮料(1.5元,2.5元),币值有两种(0.5元,1元)。当购买2.5元饮料时,已经投入的币有7种状态(0,0.5,1,1.5,2,2.5,3)。(购买2.5元饮料的状态包含了购买两元饮料的所有状态)
状态变量 | 说明 |
---|---|
IDLE | 已经投入0元 |
S1 | 已经投入0.5元 |
S2 | 已经投入1元 |
S3 | 已经投入1.5元 |
S4 | 已经投入2元 |
S5 | 已经投入2.5元 |
S6 | 已经投入3元 |
(2)绘制状态转移图
moore型状态机是不行的
理论上有上述七个状态,对应moore型状态机,但是此电路设计成moore型电路存在问题:在已投入1元状态时,再投入1元后,电路都需要跳转到已投入2元状态,在此状态购买1.5元饮料和2元饮料分别对应两种输出,所以输出不仅仅和当前状态有关,和输入也有关系,所以只能设计为meely状态机。
设计为meely型状态机
(a)在购买1.5元饮料时:
输入大于1时(1.5/2),直接输出饮料1、找零并跳转到初始状态,所以需要的状态为0元,0.5元,1元状态;
(b)在购买2.5元饮料时:
输入大于2时(2.5/3),直接输出饮料2、找零并跳转到初始状态,所以需要的状态为0元,0.5元,1元,1.5元,2元;
所以状态化简为5个状态(0元,0.5元,1元,1.5元,2元)
meely型状态转移图
3.完整代码
(1)两个问题:
题目给的仿真时序,是在时钟上升沿后给脉冲,但是网站检验代码的时候,是在时钟上升沿之前给的脉冲;
因为三段式状态机的第二段状态转移条件判断是在下一个时钟上升沿进行判断,但是代码中脉冲只持续了半个时钟周期;
解决方法:
如果为了通过网站的测试,就将所有输入数据在时钟上升沿打一拍,作为完整的输入数据;
如果为了自己用仿真软件(比如modelsim)仿真并得到正确结果,就将所有时钟,在时钟下降沿打一拍,作为完整的输入数据。
(2)代码
`timescale 1ns/1ns
module seller2(
input wire clk ,
input wire rst ,
input wire d1 ,
input wire d2 ,
input wire sel ,
output reg out1,
output reg out2,
output reg out3
);
//输入数据先打一拍
//sel是否打一拍
reg d1_reg;
reg d2_reg;
reg sel_reg;
always@(posedge clk or negedge rst)begin
if(!rst)begin
d1_reg <= 1'b0;
d2_reg <= 1'b0;
sel_reg <= 1'b0;
end
else begin
d1_reg <= d1;
d2_reg <= d2;
sel_reg <= sel;
end
end
//状态定义
parameter IDLE = 7'b000_0001;
parameter S1 = 7'b000_0010;
parameter S2 = 7'b000_0100;
parameter S3 = 7'b000_1000;
parameter S4 = 7'b001_0000;
//状态存储变量
reg [4:0] current_state;
reg [4:0] next_state;
//三段式状态机第一段
always@(posedge clk or negedge rst)begin
if(!rst)
current_state <= 5'd0;
else
current_state <= next_state;
end
//三段式状态机第二段
always@(*)begin
next_state = IDLE;
case(current_state)
IDLE:begin
case({d1_reg,d2_reg})
{1'b0,1'b0}: next_state = IDLE;
{1'b1,1'b0}: next_state = S1;
{1'b0,1'b1}: next_state = S2;
default: next_state = IDLE;
endcase
end
S1:begin
casex({sel_reg,d1_reg,d2_reg})
{1'bx,1'b0,1'b0}: next_state = S1;
{1'bx,1'b1,1'b0}: next_state = S2;
{1'b0,1'b0,1'b1}: next_state = IDLE;
{1'b1,1'b0,1'b1}: next_state = S3;
default: next_state = IDLE;
endcase
end
S2:begin
casex({sel_reg,d1_reg,d2_reg})
{1'bx,1'b0,1'b0}: next_state = S2;
{1'b0,1'b1,1'b0}: next_state = IDLE;
{1'b0,1'b0,1'b1}: next_state = IDLE;
{1'b1,1'b1,1'b0}: next_state = S3;
{1'b1,1'b0,1'b1}: next_state = S4;
default: next_state = IDLE;
endcase
end
S3:begin
casex({sel_reg,d1_reg,d2_reg})
{1'bx,1'b0,1'b0}: next_state = S3;
{1'b1,1'b1,1'b0}: next_state = S4;
{1'b1,1'b0,1'b1}: next_state = IDLE;
default: next_state = IDLE;
endcase
end
S4:begin
casex({sel_reg,d1_reg,d2_reg})
{1'bx,1'b0,1'b0}: next_state = S4;
{1'b1,1'b1,1'b0}: next_state = IDLE;
{1'b1,1'b0,1'b1}: next_state = IDLE;
default: next_state = IDLE;
endcase
end
default: next_state = IDLE;
endcase
end
//三段式状态机第三段
always@(posedge clk or negedge rst)begin
if(!rst)begin
out1 <= 1'b0;
out2 <= 1'b0;
out3 <= 1'b0;
end
else begin
case(current_state)
IDLE:begin
out1 <= 1'b0;
out2 <= 1'b0;
out3 <= 1'b0;
end
S1:begin
case({sel_reg,d1_reg,d2_reg})
{1'b0,1'b0,1'b1}:begin
out1 <= 1'b1;
out2 <= 1'b0;
out3 <= 1'b0;
end
default:begin
out1 <= 1'b0;
out2 <= 1'b0;
out3 <= 1'b0;
end
endcase
end
S2:begin
case({sel_reg,d1_reg,d2_reg})
{1'b0,1'b1,1'b0}:begin
out1 <= 1'b1;
out2 <= 1'b0;
out3 <= 1'b0;
end
{1'b0,1'b0,1'b1}:begin
out1 <= 1'b1;
out2 <= 1'b0;
out3 <= 1'b1;
end
default:begin
out1 <= 1'b0;
out2 <= 1'b0;
out3 <= 1'b0;
end
endcase
end
S3:begin
case({sel_reg,d1_reg,d2_reg})
{1'b1,1'b0,1'b1}:begin
out1 <= 1'b0;
out2 <= 1'b1;
out3 <= 1'b0;
end
default:begin
out1 <= 1'b0;
out2 <= 1'b0;
out3 <= 1'b0;
end
endcase
end
S4:begin
case({sel_reg,d1_reg,d2_reg})
{1'b1,1'b1,1'b0}:begin
out1 <= 1'b0;
out2 <= 1'b1;
out3 <= 1'b0;
end
{1'b1,1'b0,1'b1}:begin
out1 <= 1'b0;
out2 <= 1'b1;
out3 <= 1'b1;
end
default:begin
out1 <= 1'b0;
out2 <= 1'b0;
out3 <= 1'b0;
end
endcase
end
default:begin
out1 <= 1'b0;
out2 <= 1'b0;
out3 <= 1'b0;
end
endcase
end
end
endmodule