最近做了一个自动售货机,有几个问题请教一下。。
时间:10-02
整理:3721RD
点击:
顶层文件:
module auto_machine(clk,clk1,reset,one_rmb,half_rmb,call,half_out,out,state,sel,disply);
input clk,clk1,reset;//clk为自动售货机的基准时钟,clk1为数码管显示扫描时钟
input one_rmb,half_rmb; //代表1元和5角
output reg call,half_out,out; //提示取物,找零和输出物品
output reg[2:0]state; //各种投币情况
output reg[6:0]disply; //数码管的七段数据
output reg sel; //选择数码管
parameter idle = 0, //idle空闲状态
half =1, //half投入硬币总钱数为5角状态
one =2, //one投入硬币总钱数为1元状态
one_half =3, //one_half投入硬币总钱数为1.5元状态
two =4; //two投入硬币总钱数为2元状态
always @(posedge clk) begin
if(reset) begin
state =idle;out=0;
half_out=0;call=0;
end
case (state)
idle :
if(half_rmb) state = half;
else if(one_rmb) state = one;
half:
if(half_rmb) state =one;
else if(one_rmb) state =one_half;
one:
if(half_rmb) state= one_half;
else if(one_rmb) state =two;
one_half:
if(half_rmb) state= two;
else if(one_rmb) begin
out =1; //售出物品
call=1; //提示取物
state=idle;
end
two:
if(half_rmb) begin
out=1;
call=1;
state=idle;
end
else if(one_rmb) begin
state =idle ;
out =1; //售出物品
call=1; //提示取物
half_out=1; //找零
end
endcase
end
reg [3:0] disply0,disply1; //总价钱的高,低2个BCD数据
reg [4:0] sum; //统计投币的总价钱
always @(posedge clk) begin
if(half_rmb) sum=sum+5; //统计投币总钱数
else if(one_rmb) sum=sum+10;
else sum=sum;
if(sum>=30) begin //将总钱数转换成2个BCD码
disply0 =0;
disply1 =3;
end
else if(sum>=20) begin
disply0 =sum-20;
disply1 =2;
end
else if(sum>=10) begin
disply0 <=sum-10;
disply1 <=1;
end
else begin
disply0 =sum;
disply1 =0;
end
end
reg [3:0] d; //将总价钱分为2个BCD码的寄存器
always @(posedge clk1) begin
if(sel<1) sel =sel+1; //扫描数码管,即选择数码管
else sel =0;
case (sel) //将显示数码传给相应的数码管
0:d=disply1;
1:d=disply0;
default:d=4'bx;
endcase
end
always @(d) begin //译码
case(d)
0:disply =7'b1111110; //7E
1:disply =7'b0110000; //30
2:disply =7'b1101101; //6D
3:disply =7'b1111001; //79
4:disply =7'b0110011; //33
5:disply =7'b1011011; //5B
6:disply =7'b1011111; //5F
7:disply =7'b1110000; //70
8:disply =7'b1111111; //7F
9:disply =7'b1111011; //7B
default:disply =7'bx;
endcase
end
endmodule
testbench:
`timescale 1ns/1ps
module auto_machine_tb();
reg clk;//clk为自动售货机的基准时钟
reg clk1;//clk1为数码管显示扫描时钟
reg reset;
reg one_rmb;//代表1元
reg half_rmb;//代表5角
wire call;
wire half_out;
wire out;
wire [2:0]state;
wire [6:0]disply;
wire sel;
auto_machine i1(.clk(clk),
.clk1(clk1),
.reset(reset),
.one_rmb(one_rmb),
.half_rmb(half_rmb),
.call(call),
.half_out(half_out),
.out(out),
.state(state),
.sel(sel),
.disply(disply)
);
initial clk =0; //clk
always #10 clk =~clk;
initial clk1 =0; //clk1
always #40 clk1 =~clk1;
initial begin //reset
reset =1;
#100;
reset=0;
#400;
reset=1;
#100;
reset=0;
#275;
reset=1;
#100;
reset=0;
#300;
reset=1;
#100;
reset=0;
#400;
$stop;
end
initial begin //half_rmb
half_rmb=0;
#100;
half_rmb=1;
#200;
half_rmb=0;
#100;
half_rmb=1;
#100;
half_rmb=0;
#100;
half_rmb=1;
#75;
half_rmb=0;
#700;
half_rmb=1;
#200;
half_rmb=0;
#200;
$stop;
end
initial begin //one_rmb
one_rmb=0;
#300;
one_rmb=1;
#100;
one_rmb=0;
#275;
one_rmb=1;
#200;
one_rmb=0;
#100;
one_rmb=1;
#300;
one_rmb=0;
#300;
one_rmb=1;
#200;
$stop;
end
endmodule
问题:1.
波形图:
disply就是数码管显示,有红色线?但是实际中不是这样的。
2.状态视图不能出来,就是一片空白。不知原因所在,求讲解。
你说的两个问题,都是你跨时钟域产生的,而且出现modelsim中红色的送不定值,不建议送不定值,给高组值也比这个要好得多的;建议从新规划一下代码,别按照C风格来搞
我发现这是一个神奇的器件
你好,有问题和你讨论,方便的话加我qq176426425
学习了。。