又懒得写了,激励文件补了,写的好乱,唐完了,有大佬有见解的话请斧正,
module vending #(
parameter REST = 2'b00, //待机
parameter GET = 2'b01, //收钱
parameter RETURN = 2'b10 //找零
)(
input CLK, //外部时钟
input RSTN, //复位,低位为复位请求
input GET_END, //表示位被挂起时,表示没有其他的钱币了
input [7:0] MONEY, //目标金额,在收钱时用于输入主机识别的钱币金额,8'h01是1块,8'h02是5块,8'h04是10块,其他的不识别
output reg [2:0] CHANGE, //找零输出
output reg SHELL); //结束请求,告诉主机,找零流程完成
reg [1:0] state;
reg [7:0] target;
reg [7:0] total;
initial begin //初始化
state = 2'b00;
total = 8'h00;
target = 8'h00;
CHANGE = 'bz;
SHELL = 1'b1;
end
always @(posedge CLK or negedge RSTN) begin
if (!RSTN) begin //复位,不过可能有丢失投入金钱的可能,懒得修了
state <= REST;
total <= 8'h00;
target <= 8'h00;
CHANGE <= 'bz;
SHELL <= 1'b1;
end
else begin
case(state)
REST : begin //待机状态
if(MONEY != 0) begin
target <= MONEY;
state <= GET;
SHELL <= 1'b0;
end else SHELL <= 1'b1;
end
GET : begin //收钱状态
case(MONEY)
8'h01 : total = total + 1;
8'h02 : total = total + 5;
8'h04 : total = total + 10;
default: ;
endcase
if(GET_END) begin
state <= RETURN;
total <= total - target;
end
end
RETURN : begin //吐钱状态,每次吐前检验钱的数量,为零则结算,并重置变量
if(total >= 8'h0a) begin
total <= total - 10;
CHANGE <= 3'b100;
end
else if(total >= 8'h05) begin
total <= total - 5;
CHANGE <= 3'b010;
end
else if(total > 0) begin
total <= total - 1;
CHANGE <= 3'b001;
end
else if(!total) begin
CHANGE <= 'bz;
total <= 0;
target <= 0;
SHELL <= 1'b1;
state <= REST;
end
end
endcase
end
end
endmodule
下面是激励和仿真图
`timescale 1 ns/ 1 ns
module test;
reg clk;
reg rstn;
reg get_end;
reg [7:0] money;
wire [2:0] change;
wire shell;
reg [7:0] money_reg [3:0] ; //模拟主机向模块发送目标金额
reg [7:0] coin [3:0] [3:0]; //模拟主机向模块逐个发送硬币面额
integer i,j; //两个数组下标
initial begin
forever begin //标准时钟
clk = 1;
#10;
clk = 0;
#10;
end
end
initial begin
i=0; //一些数据的初始化
j=0;
money <= 8'h00;
rstn <= 1;
get_end <= 0;
money_reg[0] <= 2;
money_reg[1] <= 4;
money_reg[2] <= 7;
money_reg[3] <= 11;
coin[0][0] <= 8'h01;
coin[0][1] <= 8'h02;
coin[0][2] <= 8'h00;
coin[1][0] <= 8'h01;
coin[1][1] <= 8'h04;
coin[1][2] <= 8'h00;
coin[2][0] <= 8'h01;
coin[2][1] <= 8'h02;
coin[2][2] <= 8'h04;
coin[2][3] <= 8'h00;
coin[3][0] <= 8'h01;
coin[3][1] <= 8'h02;
coin[3][2] <= 8'h02;
coin[3][3] <= 8'h00;
end
always @(negedge clk)begin
if(i<4) begin
if(shell) begin //模块是否在空闲,是则发送目标金额,同时开启硬币接收
money <= money_reg[i];
get_end <=0;
end
else if(!get_end) begin //模块不空闲,且硬币接收状态,当目前硬币为0面额,则关闭硬币接收
money <= coin[i][j];
if(!coin[i][j]) begin
j <=0;
get_end <= 1;
i <=i+1;
end else begin
j <= j+1;
end
end
end
end
vending My_vending(
.CLK(clk),
.RSTN(rstn),
.GET_END(get_end),
.MONEY(money),
.CHANGE(change),
.SHELL(shell));
initial begin
forever begin
#100;
if($time >= 1000) $finish;
end
end
endmodule