1.1题目描述
题目描述:
设计一个自动贩售机,输入货币有两种,为0.5/1元,饮料价格是1.5/2.5元,要求进行找零,找零只会支付0.5元。
ps:
1、投入的货币会自动经过边沿检测并输出一个在时钟上升沿到1,在下降沿到0的脉冲信号
2、此题忽略出饮料后才能切换饮料的问题
注意rst为低电平复位
信号示意图:
d1 0.5
d2 1
sel 选择饮料
out1 饮料1
out2 饮料2
out3 零钱
波形示意图:
输入描述:
输入信号 clk rst d1 d2 sel
类型 wire
输出描述:
输出信号 out1 out2 out3
类型 reg
2.1状态转换表
input_signal | d1 | d2 |
---|---|---|
state | ||
IDLE | HALF | ONE |
HALF | ONE | ONE_HALF |
ONE | ONE_HALF | TWO |
ONE_HALF | TWO | TWO_HALF |
TWO | TWO_HALF | THREE |
TWO_HALF | NULL | NULL |
THREE | NULL | NULL |
解题思路:sel信号作为选通信号,当不选通时,为饮料1,当选通时切换为饮料2 ,所以根据时序状态来说,第二段组合逻辑判断状态转移条件和第三段时序逻辑进行状态输出应该有两条路径,一个是选通,另一个是不选通,注意此时我们可以将d1 0.5元的输入信号与 1元的输入信号跟它一起组合起来进行输入,注意先定义线性wire类型的input_state ,然后进行拼接,使用case语句时候,从结构设计上更为简洁直观;同时状态机第三段结果输出的时候,也应该结合选通信号来进行输出,out3信号应该结合next_state 来进行选通,图中不同颜色信号代表不同的选通信号时 out3的输出情况。
3.1代码段
`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
);
//*************code***********//
//parameter define
parameter IDLE = 7'b000_000_1,
HALF = 7'b000_001_0,
ONE = 7'b000_010_0,
ONE_HALF = 7'b000_100_0,
TWO = 7'b001_000_0 ,
TWO_HALF = 7'b010_000_0,
THREE = 7'b100_000_0;
//reg define
reg [6 : 0] cur_state ; // 现态
reg [6 : 0] next_state ; //次态
//wire define
wire [1 : 0 ] input_state ;
assign input_state = {d1,d2} ;
//one_motion
always @ (posedge clk or negedge rst) begin
if(!rst) begin
cur_state <= IDLE ; // 初始化状态为零状态
end
else begin
cur_state <= next_state ; // 次态赋值给现态
end
end
//two_motion
always @ (*) begin
if (!sel) begin
case (cur_state)
IDLE : begin
case (input_state)
2'b10 : next_state = HALF ;
2'b01 : next_state = ONE ;
default : next_state = next_state ;
endcase
end
HALF : begin
case (input_state)
2'b10 : next_state = ONE ;
2'b01 : next_state = ONE_HALF ;
default : next_state = next_state ;
endcase
end
ONE : begin
case (input_state)
2'b10 : next_state = ONE_HALF ;
2'b01 : next_state = TWO ;
default : next_state = next_state ;
endcase
end
default : next_state = IDLE ;
endcase
end
else begin
case (cur_state )
IDLE : begin
case (input_state)
2'b10 : next_state = HALF ;
2'b01 : next_state = ONE ;
default : next_state = next_state ;
endcase
end
HALF : begin
case (input_state)
2'b10 : next_state = ONE ;
2'b01 : next_state = ONE_HALF ;
default : next_state = next_state ;
endcase
end
ONE : begin
case (input_state)
2'b10 : next_state = ONE_HALF ;
2'b01 : next_state = TWO ;
default : next_state = next_state ;
endcase
end
ONE_HALF : begin
case (input_state)
2'b10 : next_state = TWO ;
2'b01 : next_state = TWO_HALF ;
default : next_state = next_state ;
endcase
end
TWO : begin
case (input_state)
2'b10 : next_state = TWO_HALF ;
2'b01 : next_state = THREE ;
default : next_state = next_state ;
endcase
end
default : next_state = IDLE ;
endcase
end
end
//THREE_motion
always @ (posedge clk or negedge rst) begin
if (!rst) begin
out1 <= 1'b0 ;
out2 <= 1'b0 ;
out3 <= 1'b0 ; //初始化状态都为闲置状态
end
if(!sel) begin
case( next_state)
ONE_HALF : begin
out1 <= 1'b1 ;
out2 <= 1'b0 ;
out3 <= 1'b0 ;
end
TWO: 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
else if (sel) begin
case (next_state)
TWO_HALF : begin
out1 <= 1'b0 ;
out2 <= 1'b1 ;
out3 <= 1'b0 ;
end
THREE : 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
end
//*************code***********//
endmodule