示例 自动售货机
设定:投币口只能投一枚五角或一枚一元硬币,投入一元五角后售货机自动给出一瓶饮料,投入两元则找零五角并给出饮料,投币只能一枚一枚投。
状态确定:
idel——不投币
half——投币五角
one——投币一元
输入 | 输出 |
---|---|
一枚一元 一枚五角 | 饮料一瓶 找零五角 |
one_dollar half_dollar | dispense half_out |
0 0 | 0 0 |
01 | 10 |
01 | 10 |
10 | 11 |
/*
clk:时钟输入
reset:系统复位信号
half_dollar:1 代表投入5角硬币
one_dollar:1 代表投入1元硬币
half_out:1 代表售货机找回一枚5角硬币信号
dispense:1 代表机器售出一瓶饮料
collect:1 提示投币者取走饮料信号
Collect half_out dispense
| | |
| | |
+---------------------+
| |
clk | machine |
------> _______ |
| |
+---------------------+
| | |
| | |
reset one_dollar half_dollar
*/
module machine(one_dollar, half_dollar,collect,half_out,dispense,reset,clk);
//状态确定 idle:不投币 half:投币五角 one:投币一元
parameter idle=2'b00,half=2'b01,one=2'b10;//2位宽二进制数
input one_dollar,half_dollar,reset,clk;
output collect,half_out,dispense;
reg collect,half_out,dispense;
reg[1:0] D;
always @(posedge clk)
begin
if(reset)//系统复位
begin
dispense=0; collect=0;
half_out=0; D=idle;//初始为idle状态
end
else
case(D)
idle:
if(half_dollar)
begin
dispense=0;collect=0;
half_out=0;D=half;//投入half_dollar 进入half状态
end
else if(one_dollar)
begin
dispense = 0;collect=0;
half_out = 0;D=one;//投入one_dollar 进入one状态
end
else
begin
dispense = 0;collect=0;
half_out = 0;D=idle;
end
half:
if(half_dollar)
begin
dispense=0;collect=0;
half_out=0;D=one;//投入half_dollar 累加进入one状态
end
else if(one_dollar)
begin
dispense = 1;
collect=1;
half_out = 0;D=idle;//投入one_dollar 累加给出一瓶饮料 进入idle状态
end
else
begin
dispense = 0;collect=0;
half_out = 0;D=half;
end
one:
if(half_dollar)
begin
dispense=1;collect=1;
half_out=0;D=idle;//投入one_dollar 累加给出一瓶饮料 进入idle状态
end
else if(one_dollar)
begin
dispense = 1;collect=1;
half_out = 1;D=idle;//投入one_dollar 累加给出一瓶饮料找零五角 进入idle状态
end
else
begin
dispense = 0;collect=0;
half_out = 0;D=one;
end
default:
begin
dispense=0;collect=0;
half_out=0;D=idle;
end
endcase
end
endmodule
仿真波形图显示:half_dollar连续3个时钟脉冲即3个五角后,输出饮料一瓶加提醒;one_dollar连续2个时钟脉冲即2个一元,则输出饮料一瓶加提醒并找零五角。
改进
改进投币信号检测模块,投币一次输出一个时钟周期的高电平
/*
clk:时钟输入
reset:系统复位信号
half_dollar:1 代表投入5角硬币
one_dollar:1 代表投入1元硬币
half_out:1 代表售货机找回一枚5角硬币信号
dispense:1 代表机器售出一瓶饮料
collect:1 提示投币者取走饮料信号
Collect half_out dispense
| | |
| | |
+---------------------+
| |
clk | machine |
------> _______ |
| |
+---------------------+
| | |
| | |
reset one_dollar half_dollar
*/
module machine(one_dollar, half_dollar,collect,half_out,dispense,reset,clk);
//状态确定 idle:不投币 half:投币五角 one:投币一元
parameter idle=2'b00,half=2'b01,one=2'b10;
input one_dollar,half_dollar,reset,clk;
output collect,half_out,dispense;
reg collect,half_out,dispense;
reg[1:0] D;
//改进项-投币一次输出一个时钟周期
reg half_in0;
reg half_in1;
wire half_test;//投币五角检测脉冲
reg one_in0;
reg one_in1;
wire one_test;//投币一元检测脉冲
always @(posedge clk or posedge reset)
begin
if(reset)
begin
half_in0 <=0;
half_in1 <=0;
one_in0 <=0;
one_in1 <=0;
end
else
begin
half_in0 <=half_in1;
half_in1 <=half_dollar;
one_in0 <=one_in1;
one_in1 <=one_dollar;
end
end
assign half_test = ~half_in0 & half_in1;
assign one_test = ~one_in0 & one_in1;
always @(posedge clk or posedge reset)
begin
if(reset)//系统复位
begin
dispense=0; collect=0;
half_out=0; D=idle;
end
else
case(D)
idle:
if(half_test)
begin
dispense=0;collect=0;
half_out=0;D=half;
end
else if(one_test)
begin
dispense = 0;collect=0;
half_out = 0;D=one;
end
else
begin
dispense = 0;collect=0;
half_out = 0;D=idle;
end
half:
if(half_test)
begin
dispense=0;collect=0;
half_out=0;D=one;
end
else if(one_test)
begin
dispense = 1;
collect=1;
half_out = 0;D=idle;
end
else
begin
dispense = 0;collect=0;
half_out = 0;D=half;
end
one:
if(half_test)
begin
dispense=1;collect=1;
half_out=0;D=idle;
end
else if(one_test)
begin
dispense = 1;collect=1;
half_out = 1;D=idle;
end
else
begin
dispense = 0;collect=0;
half_out = 0;D=one;
end
default:
begin
dispense=0;collect=0;
half_out=0;D=idle;
end
endcase
end
endmodule
仿真波形:
仿真波形说明,分别投入五角+五角+一元,检测到3个投币投币信号,输出饮料和找零。