第一步:看要求
编写一个自动售货机,功能如下:
1)共有三种纸币入口,分别支持10元,20元,50元;
2)货物售价为80元;
3)需要支持找钱功能(注意,找钱有四种种情况)。
RTL编码,完成testbench编码,用QuestaSim仿真波形通过。
答题
第一步画出状态转移图
有7种状态,状态图从s0到s7如下图
第二步:辨别情况,设置输入输出及s0~s7的状态
(1)输入与输出状态
设置投钱10元为:in10,
设置投钱20元为:in20,
设置投钱50元为:in50
设置出货为:out,
设置找钱10元为: return_10,
设置找钱20元为: return_20,
设置找钱30元为: return_30,
设置找钱40元为: return_40。
(2)s0~s7的状态定义如下
parameter [2:0] s0 = 3’b000,
s1 = 3’b001,
s2 = 3’b010,
s3 = 3’b011,
s4 = 3’b100,
s5 = 3’b101,
s6 = 3’b110,
s7 = 3’b111。
第三步:写RTL如下
module sell(
output out,
output return_10,
output return_20,
output return_30,
output return_40,
input clk,
input reset,
input in10,
input in20,
input in50
);
parameter [2:0] s0 = 3'b000,
s1 = 3'b001,
s2 = 3'b010,
s3 = 3'b011,
s4 = 3'b100,
s5 = 3'b101,
s6 = 3'b110,
s7 = 3'b111;
reg [2:0] curr_state; //Temporary variables are defined
reg [2:0] next_state;
//First segment: state transfer(state transitions are clock-dependent)
always@(posedge clk, negedge reset)
begin
if (!reset)
curr_state <= s0;
else
curr_state <= #1 next_state;
end
//Second segment: transfer condition(condition are state-dependent)
always@(curr_state, in10, in20, in50)
begin
case(curr_state) //curr_state have many conditions
s0: begin
if (in10) next_state = s1;
else if (in20) next_state = s2;
else if (in50) next_state = s5;
else next_state = s0;
end
s1: begin
if (in10) next_state = s2;
else if (in20) next_state = s3;
else if (in50) next_state = s6;
else next_state = s1;
end
s2: begin
if (in10) next_state = s3;
else if (in20) next_state = s4;
else if (in50) next_state = s7;
else next_state = s2;
end
s3: begin
if (in10) next_state = s4;
else if (in20) next_state = s5;
else if (in50) next_state = s0;
else next_state = s3;
end
s4: begin
if (in10) next_state = s5;
else if (in20) next_state = s5;
else if (in50) next_state = s0;
else next_state = s4;
end
s5: begin
if (in10) next_state = s6;
else if (in20) next_state = s7;
else if (in50) next_state = s0;
else next_state = s5;
end
s6: begin
if (in10) next_state = s7;
else if (in20) next_state = s0;
else if (in50) next_state = s0;
else next_state = s6;
end
s7: begin
if (in10) next_state = s0;
else if (in20) next_state = s0;
else if (in50) next_state = s0;
else next_state = s7;
end
default: next_state = s0;
endcase
end
//Third sement: state ouput
//mealy type FSM
assign out = ((curr_state == s7) & (in10 | in20 | in50)) ? 1 :
((curr_state == s6) & (in20 | in50)) ? 1 :
((curr_state == s5) & (in50)) ? 1 :
((curr_state == s4) & (in50)) ? 1 :
((curr_state == s3) & (in50)) ? 1 : 0;
assign return_40 = ((curr_state == s7) & (in50)) ? 1 : 0;
assign return_30 = ((curr_state == s6) & (in50)) ? 1 : 0;
assign return_20 = ((curr_state == s5) & (in50)) ? 1 : 0;
assign return_10 = ((curr_state == s7) & (in20)) ? 1 :
((curr_state == s4) & (in50)) ? 1 : 0;
endmodule
第四步:写Testbench如下(这个可以自己随便写的)
module sell_tb();
wire out;
wire return_10;
wire return_20;
wire return_30;
wire return_40;
reg in10;
reg in20;
reg in50;
reg clk;
reg reset;
initial
begin
clk = 0;
reset = 0;
#20
reset = 1;
end
always #20 clk = ~clk;
initial
begin
in10 = 0;
in20 = 0;
in50 = 0;
#100
repeat (8) //after repeat 8 times was spend time of 8*20ns=160ns
begin
@(posedge clk) in10 = 1;
@(posedge clk) in20 = 0;
@(posedge clk) in50 = 0;
end
#200
repeat (4)
begin
@(posedge clk) in10 = 0;
@(posedge clk) in20 = 1;
@(posedge clk) in50 = 0;
end
#200
repeat (3)
begin
@(posedge clk) in10 = 1;
@(posedge clk) in20 = 1;
@(posedge clk) in50 = 0;
end
#200
repeat (2)
begin
@(posedge clk) in10 = 0;
@(posedge clk) in20 = 0;
@(posedge clk) in50 = 1;
end
#200
$finish;
end
sell u0_sell(
.out (out),
.return_10 (return_10),
.return_20 (return_20),
.return_30 (return_30),
.return_40 (return_40),
.in10 (in10),
.in20 (in20),
.in50 (in50),
.clk (clk),
.reset (reset)
);
endmodule
观察波形,看看自己的tb输入和波形的情况
波形图如下