verilog代码如下:
/*
date: 2022/8/31
author: Xingxing Zhou
*/
module auto_selll_drinks(
input wire sys_clk ,
input wire sys_rst_n ,
input wire Ten_Yuan ,
input wire Twenty_Yuan ,
input wire Fifty_Yuan ,
output wire out_drink ,
output reg [7:0] out_money
);
// define states
parameter IDLE = 4'd0 , // No money
S_10 = 4'd1 , // 10 yuan
S_20 = 4'd2 , // 20 yuan
S_30 = 4'd3 , // 30 yuan
S_40 = 4'd4 , // 40 yuan
S_50 = 4'd5 , // 50 yuan
S_60 = 4'd6 , // 60 yuan
S_70 = 4'd7 , // 70 yuan
S_80 = 4'd8 , // 80 yuan
S_90 = 4'd9 , // 90 yuan
S_100 = 4'd10 , // 100 yuan
S_110 = 4'd11 , // 110 yuan
S_120 = 4'd12 ; // 120 yuan
reg [3:0] state ;
reg [3:0] next_state ;
always @(posedge sys_clk or negedge sys_rst_n) begin
if(!sys_rst_n)begin
state <= IDLE;
end
else begin
state <= next_state;
end
end
always @(*) begin
case(state)
IDLE: begin
if(Ten_Yuan)begin
next_state <= S_10;
end
else if(Twenty_Yuan)begin
next_state <= S_20;
end
else if(Fifty_Yuan) begin
next_state <= S_50;
end
else begin
next_state <= IDLE;
end
end
S_10: begin
if(Ten_Yuan)begin
next_state <= S_20;
end
else if(Twenty_Yuan)begin
next_state <= S_30;
end
else if(Fifty_Yuan) begin
next_state <= S_60;
end
else begin
next_state <= S_10;
end
end
S_20: begin
if(Ten_Yuan)begin
next_state <= S_30;
end
else if(Twenty_Yuan)begin
next_state <= S_40;
end
else if(Fifty_Yuan) begin
next_state <= S_70;
end
else begin
next_state <= S_20;
end
end
S_30: begin
if(Ten_Yuan)begin
next_state <= S_40;
end
else if(Twenty_Yuan)begin
next_state <= S_50;
end
else if(Fifty_Yuan) begin
next_state <= S_80;
end
else begin
next_state <= S_30;
end
end
S_40: begin
if(Ten_Yuan)begin
next_state <= S_50;
end
else if(Twenty_Yuan)begin
next_state <= S_60;
end
else if(Fifty_Yuan) begin
next_state <= S_90;
end
else begin
next_state <= S_40;
end
end
S_50: begin
if(Ten_Yuan)begin
next_state <= S_60;
end
else if(Twenty_Yuan)begin
next_state <= S_70;
end
else if(Fifty_Yuan) begin
next_state <= S_100;
end
else begin
next_state <= S_50;
end
end
S_60: next_state <= (Ten_Yuan) ? S_70 : (Twenty_Yuan) ? S_80 : (Fifty_Yuan) ? S_110 : S_60;
S_70: next_state <= (Ten_Yuan) ? S_80 : (Twenty_Yuan) ? S_90 : (Fifty_Yuan) ? S_120 : S_70;
S_80: next_state <= IDLE;
S_90: next_state <= IDLE;
S_100: next_state <= IDLE;
S_110: next_state <= IDLE;
S_120: next_state <= IDLE;
default:next_state <= IDLE;
endcase
end
assign out_drink = ((state == S_80) || (state == S_90) || (state == S_100) || (state == S_110) || (state == S_120));
always @(*) begin
if(state == S_80)begin
out_money <= 8'd0;
end
else if(state == S_90) begin
out_money <= 8'd10;
end
else if(state == S_100) begin
out_money <= 8'd20;
end
else if(state == S_110) begin
out_money <= 8'd30;
end
else if(state == S_120) begin
out_money <= 8'd40;
end
else begin
out_money <= 8'd0;
end
end
endmodule
testbench编写如下:
module tb_auto_sell_drinks;
reg sys_clk ;
reg sys_rst_n ;
reg Ten_Yuan ;
reg Twenty_Yuan ;
reg Fifty_Yuan ;
wire out_drink ;
wire [7:0] out_money ;
integer i;
task buy_drink;
i = $random() % 3;
if(i == 0) begin
Ten_Yuan <= 1'b1;
@(posedge sys_clk);
Ten_Yuan <= 1'b0;
#50;
end
else if(i == 1) begin
Twenty_Yuan <= 1'b1;
@(posedge sys_clk);
Twenty_Yuan <= 1'b0;
#50;
end
else begin
Fifty_Yuan <= 1'b1;
@(posedge sys_clk);
Fifty_Yuan <= 1'b0;
#50;
end
endtask
initial begin
sys_clk = 1'b0;
sys_rst_n = 1'b0;
Ten_Yuan = 1'b0;
Fifty_Yuan = 1'b0;
Twenty_Yuan = 1'b0;
#40
sys_rst_n = 1'b1;
repeat(20) begin
buy_drink();
end
$finish;
end
always #10 sys_clk = ~sys_clk;
auto_selll_drinks u_auto_sell_drinks(
.sys_clk (sys_clk) ,
.sys_rst_n (sys_rst_n) ,
.Ten_Yuan (Ten_Yuan) ,
.Twenty_Yuan(Twenty_Yuan) ,
.Fifty_Yuan (Fifty_Yuan) ,
.out_drink (out_drink) ,
.out_money (out_money)
);
initial begin
$fsdbDumpfile("tb.fsdb");
$fsdbDumpvars;
end
endmodule
仿真波形入下: