1.问题
设计一个自动贩卖机,设商品售价2.5元,可使用5角和一元硬币,有找零功能。
2.功能框图和接口定义
clk: 时钟输入;reset:复位信号;half:投入五角硬币;one:投入一元硬币;out:机器弹出商品;cout:机器找零。
3.状态转换图(基于摩尔型状态机)
4.RTL代码编写
module sell (
input one,
input half,
input clk,
input rst_n,
output reg out,
output reg cout
);
reg [2:0] curr_state, next_state;
parameter S0=3'd0,
S1=3'd1,
S2=3'd2,
S3=3'd3,
S4=3'd4,
S5=3'd5,
S6=3'd6;
always @(posedge clk or negedge rst_n) begin
if(!rst_n)
curr_state<=S0;
else
curr_state<=next_state;
end
always @(*) begin
case (curr_state)
S0:begin
if(half)
next_state=S1;
else if (one)
next_state=S2;
else
next_state=curr_state;
end
S1:begin
if(half)
next_state=S2;
else if (one)
next_state=S3;
else
next_state=curr_state;
end
S2:begin
if(half)
next_state=S3;
else if (one)
next_state=S4;
else
next_state=curr_state;
end
S3:begin
if(half)
next_state=S4;
else if (one)
next_state=S5;
else
next_state=curr_state;
end
S4:begin
if(half)
next_state=S5;
else if (one)
next_state=S6;
else
next_state=curr_state;
end
S5: next_state=S0;
S6: next_state=S0;
default: next_state=S0;
endcase
end
always @(*) begin
if(!rst_n)begin
out<=0;
cout<=0;
end
else if(curr_state==S5) begin
out<=1;
cout<=0;
end
else if(curr_state==S6) begin
out<=1;
cout<=1;
end
else begin
out<=0;
cout<=0;
end
end
endmodule
5.测试代码编写
本测试仅仿真了两个购买情景
测试情景1:S0→S2→S4→S6;即连续投了三次一元钱,机器弹出饮料并找零(out=1,cout=1)。
测试情景2:S0→S1→S3→S5;即先投了五角钱,然后又投了一元钱,最后又投了一元钱,机器弹出饮料不找零(out=1,cout=0)。
module sell_tb();
logic one,half,clk,rst_n;
logic cout,out;
sell u1(.clk(clk),.rst_n(rst_n),.half(half),.one(one),.cout(cout),.out(out) );
initial begin
clk=0;
rst_n<=0;
#40;
rst_n<=1;
end
always #10 clk=~clk;
initial begin
half<=0;
one<=0;
#50;
half<=0;
one<=1;
#20;
half<=0;
one<=1;
#20;
half<=0;
one<=1;
#20;//测试场景1cout=1,out=1
half<=0;
one<=0;
#50;
half<=1;
one<=0;
#20;
half<=0;
one<=1;
#20;
half<=0;
one<=1;
#50; //测试场景2cout=0,out=1;
$finish;
end
initial
begin
$fsdbDumpfile("test.fsdb");
$fsdbDumpvars(0,sell_tb);
end
endmodule
6.仿真波形
仿真工具:VCS、Verdi