大三的实验,给出代码,仅供参考:
基本功能:
1、在屏幕上显示3种商品,及其单价
2、按键实现投币,购买,找零等
3、不同按键代表不同的金钱数
1、分频模块:
modulefenpin(
input CLK,
input RSTn,
output reg CLK_25M
);
always @ (posedge CLK or negedge RSTn )
if( !RSTn )
CLK_25M <= 0;
else
CLK_25M<=~CLK_25M;
Endmodule
2、按键消抖模块:
modulekey_delay(
input CLK,
input RSTn,
input [3:0] button_in,
output reg [3:0] button_out
);
reg [1:0]next_state;
reg [3:0]button_reg;
reg time_20ms;
reg is_cnt;
reg [19:0] cnt;
always @ ( posedge CLK or negedge RSTn )
if( !RSTn )
begin
button_reg <= 4'b0000;
next_state <= 2'd0;
is_cnt <= 1'b0;
button_out <= 4'b0000;
end
else
begin
case(next_state)
2'd0:
if(button_in!=4'b0000)//有按键输入
begin
next_state<= 2'd1;
is_cnt <= 1'b1;//开始计数
button_reg<= button_in;
end
else
begin
next_state<= 2'd0;
button_reg<= 4'b0000;
is_cnt <= 1'b0;
end
2'd1:
if(time_20ms==1'b1 )//按键维持了20ms
begin
is_cnt <= 1'b0;//结束计数
next_state<= 2'd2;
end
else
begin
button_reg<= button_in;
if(button_in!=button_reg)
begin
is_cnt<=1'b0;
next_state<= 2'd0;
end
else
begin
next_state<= 2'd1;
is_cnt <= 1'b1;//开始计数
end
end
2'd2:
if(button_in!=button_reg || button_in==4'b0000)//按键松开
begin
button_out<= button_reg;
next_state<= 2'd3;
end
else
begin
button_out<= 4'b0000;
next_state<= 2'd2;
end
2'd3:
begin
next_state<= 2'd0;
button_out<= 4'b0000;
end
default:
next_state<= 2'd0;
endcase
end
always @ ( posedge CLK or negedge RSTn )
if(!RSTn)
begin
time_20ms<=1'b0;
cnt<=20'd0;
end
else if(is_cnt==1'b1)
if(cnt==20'd1000000)
begin
time_20ms<=1'b1;
cnt <=20'd0;
end
else
begin
time_20ms<=1'b0;
cnt<=cnt+1'd1;
end
else
begin
time_20ms<=1'b0;
cnt<=20'd0;
end
endmodule
3、VGA控制模块:
modulesync_module(
CLK, RSTn,
VSYNC_Sig,
HSYNC_Sig,
Ready_Sig,
Column_Addr_Sig,
Row_Addr_Sig
);
input CLK;
input RSTn;
output VSYNC_Sig;
output HSYNC_Sig;
output Ready_Sig;
output [10:0]Column_Addr_Sig;
output [10:0]Row_Addr_Sig;
reg [10:0]Count_H;
always @ ( posedge CLK or negedge RSTn )
if( !RSTn )
Count_H <= 11'd0;
else if( Count_H == 11'd799 )
Count_H <= 11'd0;
else
Count_H <= Count_H +1'b1;
reg [10:0]Count_V;
always @ ( posedge CLK or negedge RSTn )
if( !RSTn )
Count_V <= 11'd0;
else if( Count_V == 11'd524 )
Count_V <= 11'd0;
else if( Count_H == 11'd799 )
Count_V <= Count_V +1'b1;
reg isReady;
always @ ( posedge CLK or negedge RSTn )
if( !RSTn )
isReady <= 1'b0;
else if( ( Count_H > 11'd144&& Count_H < 11'd785 ) &&
(Count_V >11'd34 && Count_V < 11'd515 ) )
isReady <= 1'b1;
else
isReady <= 1'b0;
assign VSYNC_Sig = ( Count_V < 11'd3 )? 1'b0 : 1'b1;
assign HSYNC_Sig = ( Count_H < 11'd97) ? 1'b0 : 1'b1;
assign Ready_Sig = isReady;
assign Column_Addr_Sig = isReady ?Count_H - 11'd145 : 11'd0;
assign Row_Addr_Sig = isReady ? Count_V -11'd35 : 11'd0;
endmodule
4、VGA显示模块:
modulevga_control_module(
input CLK,
input RSTn,
input Ready_Sig,
input [10:0] lie,
input [10:0] hang,
input [7:0] pic_Data,
output reg [14:0] pic_Addr,
input [31:0] char_Data,
output reg [7:0] char_Addr,
input [15:0] num_Data,
output reg [8:0] num_Addr,
input [2:0] wupin,
output reg [7:0] rgb,
input error, //错误信号
input [3:0] tb1,
input [3:0] tb2,
input [3:0] hf1,
input [3:0] hf2,
input [3:0] hf3,
input [3:0] zl1,
input [3:0] zl2,
input [3:0] zl3
);
/**************3个框****************/
wire k1,k2,k3,k4,k5,k6; //框1、2、3
assign k1=(((160<=lie &&lie<165)||(229<=lie && lie<234))&&(120<=hang&& hang<258))?1'b1:1'b0;
assign k2=(((250<=lie &&lie<255)||(319<=lie && lie<324))&&(120<=hang&& hang<258))?1'b1:1'b0;
assign k3=(((340<=lie &&lie<345)||(409<=lie && lie<414))&&(120<=hang&& hang<258))?1'b1:1'b0;
assign k4=((165<=lie &&lie<229)&&((120<=hang && hang<125)||(253<=hang&& hang<258)))?1'b1:1'b0;
assign k5=((255<=lie &&lie<319)&&((120<=hang && hang<125)||(253<=hang&& hang<258)))?1'b1:1'b0;
assign k6=((345<=lie &&lie<409)&&((120<=hang && hang<125)||(253<=hang&& hang<258)))?1'b1:1'b0;
/**************3个图片****************/
wire pic1,pic2,pic3; //图片1、2、3
wire pich; //图片的行
assign pich=(125<=hang &&hang<253)?1'b1:1'b0;
assign pic1=((165<=lie &&lie<229)&&(pich==1'b1))?1'b1:1'b0;
assign pic2=((255<=lie &&lie<319)&&(pich==1'b1))?1'b1:1'b0;
assign pic3=((345<=lie &&lie<409)&&(pich==1'b1))?1'b1:1'b0;
/**************3个单价****************/
wire [2:0]dj1,dj2,dj3;//单价1、2、3
wire dah; //单价的行
assign dah=(270<=hang &&hang<302)?1'b1:1'b0;
assign dj1[0]=((170<=lie &&lie<186)&&(dah==1'b1))?1'b1:1'b0;
assign dj1[1]=((186<=lie &&lie<202)&&(dah==1'b1))?1'b1:1'b0;//这一位存小数点
assign dj1[2]=((202<=lie &&lie<218)&&(dah==1'b1))?1'b1:1'b0;
assign dj2[0]=((260<=lie &&lie<276)&&(dah==1'b1))?1'b1:1'b0;
assign dj2[1]=((276<=lie &&lie<292)&&(dah==1'b1))?1'b1:1'b0;
assign dj2[2]=((292<=lie &&lie<308)&&(dah==1'b1))?1'b1:1'b0;
assign dj3[0]=((350<=lie &&lie<366)&&(dah==1'b1))?1'b1:1'b0;
assign dj3[1]=((366<=lie &&lie<382)&&(dah==1'b1))?1'b1:1'b0;
assign dj3[2]=((382<=lie &&lie<398)&&(dah==1'b1))?1'b1:1'b0;
/**************17个字符****************投币,花费,找零,和3个元,8个钱的输入*/
wire t,b,h,f,z,l; //投币,花费,找零
wire [2:0]y; //3个"元"
wire [7:0]q; //8个钱
wire [1:0]xsd; //2个小数点
assign t =(165<=lie && lie <197 && 320<=hang &&hang<352 )?1'b1:1'b0;
assign b =(197<=lie && lie <229 && 320<=hang &&hang<352 )?1'b1:1'b0;
assign q[0] =( 255<=lie && lie <271 && 320<=hang&& hang<352 )?1'b1:1'b0;
assign q[1] =( 271<=lie && lie <287 && 320<=hang&& hang<352 )?1'b1:1'b0;
assign y[0] =( 350<=lie && lie <382 && 320<=hang&& hang<352 )?1'b1:1'b0;
assign h =(165<=lie && lie <197 && 360<=hang &&hang<392 )?1'b1:1'b0;
assign f =(197<=lie && lie <229 && 360<=hang &&hang<392 )?1'b1:1'b0;
assign q[2] =( 255<=lie && lie <271 && 360<=hang&& hang<392 )?1'b1:1'b0;
assign q[3] =( 271<=lie && lie <287 && 360<=hang&& hang<392 )?1'b1:1'b0;
assign xsd[0]=( 287<=lie &&lie <303 && 360<=hang && hang<392 )?1'b1:1'b0;
assign q[4] =( 303<=lie && lie <319 && 360<=hang&& hang<392 )?1'b1:1'b0;
assign y[1] =( 350<=lie && lie <382 && 360<=hang&& hang<392 )?1'b1:1'b0;
assign z =(165<=lie && lie <197 && 400<=hang &&hang<432 )?1'b1:1'b0;
assign l =(197<=lie && lie <229 && 400<=hang &&hang<432 )?1'b1:1'b0;
assign q[5] =( 255<=lie && lie <271 && 400<=hang&& hang<432 )?1'b1:1'b0;
assign q[6] =( 271<=lie && lie <287 && 400<=hang&& hang<432 )?1'b1:1'b0;
assign xsd[1]=( 287<=lie &&lie <303 && 400<=hang && hang<432 )?1'b1:1'b0;
assign q[7] =( 303<=lie && lie <319 && 400<=hang&& hang<432 )?1'b1:1'b0;
assign y[2] =( 350<=lie && lie <382 && 400<=hang&& hang<432 )?1'b1:1'b0;
assign err =( 350<=lie && lie <382 && 400<=hang&& hang<432 )?1'b1:1'b0;
wire [3:0] zl1_reg,zl2_reg,zl3_reg;
assign zl1_reg = (error==1)?4'd10:zl1;
assign zl2_reg = (error==1)?4'd10:zl2;
assign zl3_reg = (error==1)?4'd10:zl3;
always @ ( posedge CLK or negedge RSTn )
if(!RSTn)
begin
rgb<=8'h00;
end
else if(Ready_Sig)
begin
if(k1|k4)//框1
if(wupin[0])
rgb<=8'b11100000;
else
rgb<=8'b11111111;
else if(k2|k5)//框2
if(wupin[1])
rgb<=8'b11100000;
else
rgb<=8'b11111111;
else if(k3|k6)//框3
if(wupin[2])
rgb<=8'b11100000;
else
rgb<=8'b11111111;
else if(pic1|pic2|pic3)
begin
case({pic1,pic2,pic3})
3'b001:beginpic_Addr=(hang-125)*64+(lie-165);rgb<=pic_Data;end//阿萨姆
3'b010:beginpic_Addr=128*64+(hang-125)*64+(lie-255);rgb<=pic_Data;end//冰红茶
3'b100:beginpic_Addr=2*128*64+(hang-125)*64+(lie-345);rgb<=pic_Data;end//康师傅
default:beginpic_Addr=0;rgb<=8'b01101101;end
endcase
end
elseif(dj1[0]|dj1[1]|dj1[2])
begin
case(dj1)
9'b001:beginnum_Addr=4*32+(hang-270);rgb<={8{num_Data[lie-170]}};end
9'b010:beginnum_Addr=10*32+(hang-270);rgb<={8{num_Data[lie-186]}};end
9'b100:beginnum_Addr=0*32+(hang-270);rgb<={8{num_Data[lie-202]}};end
default:beginnum_Addr=0;rgb<=8'b11100011;end
endcase
end
elseif(dj2[0]|dj2[1]|dj2[2])
begin
case(dj2)
9'b001:beginnum_Addr=2*32+(hang-270);rgb<={8{num_Data[lie-260]}};end
9'b010:beginnum_Addr=10*32+(hang-270);rgb<={8{num_Data[lie-276]}};end
9'b100:beginnum_Addr=5*32+(hang-270);rgb<={8{num_Data[lie-292]}};end
default:beginnum_Addr=0;rgb<=8'b11100011;end
endcase
end
elseif(dj3[0]|dj3[1]|dj3[2])
begin
case(dj3)
9'b001:beginnum_Addr=1*32+(hang-270);rgb<={8{num_Data[lie-350]}};end
9'b010:beginnum_Addr=10*32+(hang-270);rgb<={8{num_Data[lie-366]}};end
9'b100:beginnum_Addr=0*32+(hang-270);rgb<={8{num_Data[lie-382]}};end
default:beginnum_Addr=0;rgb<=8'b11100011;end
endcase
end
else if(t|h|z)
begin
case({t,h,z})
3'b100:beginchar_Addr=0*32+(hang-320);rgb<={8{char_Data[lie-165]}};end
3'b010:beginchar_Addr=2*32+(hang-360);rgb<={8{char_Data[lie-165]}};end
3'b001:beginchar_Addr=4*32+(hang-400);rgb<={8{char_Data[lie-165]}};end
default:beginchar_Addr=0;rgb<=8'b00011100;end
endcase
end
else if(b|f|l)
begin
case({b,f,l})
3'b100:beginchar_Addr=1*32+(hang-320);rgb<={8{char_Data[lie-197]}};end
3'b010:beginchar_Addr=3*32+(hang-360);rgb<={8{char_Data[lie-197]}};end
3'b001:beginchar_Addr=5*32+(hang-400);rgb<={8{char_Data[lie-197]}};end
default:beginchar_Addr=0;rgb<=8'b00011111;end
endcase
end
else if(y[0]|y[1]|y[2])
begin
case(y)
3'b001:beginchar_Addr=6*32+(hang-320);rgb<={8{char_Data[lie-350]}};end
3'b010:beginchar_Addr=6*32+(hang-360);rgb<={8{char_Data[lie-350]}};end
3'b100:beginchar_Addr=6*32+(hang-400);rgb<={8{char_Data[lie-350]}};end
default:beginchar_Addr=0;rgb<=8'b11111100;end
endcase
end
elseif(q[0]|q[1]|q[2]|q[3]|q[4]|q[5]|q[6]|q[7])
begin
case(q)
8'b000_000_01:beginnum_Addr=tb1*32+(hang-320);rgb<={8{num_Data[lie-255]}};end
8'b000_000_10:beginnum_Addr=tb2*32+(hang-320);rgb<={8{num_Data[lie-271]}};end
8'b000_001_00:beginnum_Addr=hf1*32+(hang-360);rgb<={8{num_Data[lie-255]}};end
8'b000_010_00:beginnum_Addr=hf2*32+(hang-360);rgb<={8{num_Data[lie-271]}};end
8'b000_100_00:beginnum_Addr=hf3*32+(hang-360);rgb<={8{num_Data[lie-303]}};end
8'b001_000_00:beginnum_Addr=zl1_reg*32+(hang-400);rgb<={8{num_Data[lie-255]}};end
8'b010_000_00:beginnum_Addr=zl2_reg*32+(hang-400);rgb<={8{num_Data[lie-271]}};end
8'b100_000_00:beginnum_Addr=zl3_reg*32+(hang-400);rgb<={8{num_Data[lie-303]}};end
default:beginnum_Addr=0;rgb<=8'b10101010;end
endcase
end
else if(xsd[0]|xsd[1])
begin
case(xsd)
2'b01:beginnum_Addr=10*32+(hang-360);rgb<={8{num_Data[lie-287]}}; end
2'b10:beginnum_Addr=10*32+(hang-400);rgb<={8{num_Data[lie-287]}}; end
endcase
end
else
rgb<=8'h00;
end
endmodule
5、销售模块:
module main(
input CLK,
input RSTn,
input [3:0]button,
input [2:0]wupin,
output reg error,
output reg [3:0]a,b,c,d,e,f,g,h
);
reg[9:0] tb,hf;
always @ ( posedge CLK or negedge RSTn )
if(!RSTn)
begin
a<=0;
b<=0;
error<=0;
tb<=0;
end
else
begin
tb<=(a*10+b)*10;
if(b>=10)
begin
b<=b-10;
a<=a+1;
end
if(a>=10)
begin
a<=9;
b<=9;
error<=1;
end
case(button)
4'b1000://一块
b<=b+1;
4'b0100://五块
b<=b+5;
4'b0010://十块
a<=a+1;
4'b0001:
begin
a<=0;
b<=0;
if(tb<hf)
error<=1;
else
begin
error<=0;
if(e>0)
begin
h<=10-e;
if(b>0)
if(b-1<d)
begin
g<=10+(b-1)-d;
f<=a-1-c;
end
else
begin
g<=b-1-d;
f<=a-c;
end
else
begin
g<=9-d;
f<=a-1-c;
end
end
else
begin
h<=0;
if(b<d)
begin
g<=10+b-d;
f<=a-1-c;
end
else
begin
g<=b-d;
f<=a-c;
end
end
end
end
endcase
end
/****************拨码开关的消抖*****************/
reg [2:0]wupin_reg;
reg [2:0]wupin_out,wupin_out_r;
reg time_20ms;
reg is_cnt;
reg [19:0] cnt;
always @ ( posedge CLK or negedge RSTn )
if(!RSTn)
begin
wupin_out<=3'b000;
wupin_reg<=3'b000;
end
else
begin
wupin_out<=wupin_reg^wupin;//当wupin有变化时,wupin_out产生一个时钟的高电平
wupin_reg<=wupin;
end
always @ ( posedge CLK or negedge RSTn )
if(!RSTn)
begin
is_cnt <=1'b0;
wupin_out_r<=4'b0000;
end
else
if(wupin_out!=3'b000)
begin
is_cnt <=1'b1;
wupin_out_r<=wupin_out;
end
else if(time_20ms)
is_cnt <=1'b0;
always @ ( posedge CLK or negedge RSTn )
if(!RSTn)
begin
time_20ms<=1'b0;
cnt<=20'd0;
end
else if(is_cnt==1'b1)
if(cnt==20'd1000000)
begin
time_20ms<=1'b1;
cnt <=20'd0;
end
else
begin
time_20ms<=1'b0;
cnt<=cnt+1'd1;
end
else
begin
time_20ms<=1'b0;
cnt<=20'd0;
end
always @ ( posedge CLK or negedge RSTn )
if(!RSTn)
begin
d<=0;
c<=0;
e<=0;
hf<=0;
end
else
begin
hf<=c*100+d*10+e;
if(time_20ms)
case(wupin_out_r)
4'b001://4块
if(wupin[0])
d<=d+4;
else
d<=d-4;
4'b010://2.5块
if(wupin[1])
begin
d<=d+2;
e<=e+5;
end
else
begin
d<=d-2;
e<=e-5;
end
4'b100://1块
if(wupin[2])
d<=d+1;
else
d<=d-1;
endcase
end
endmodule
6、顶层模块:
module top( CLK,
RSTn,
button, //按键
wupin, //物品
v,
h,
rgb
);
input CLK,RSTn;
input [3:0]button;
input [2:0]wupin;
output v;
output h;
output [7:0]rgb;
wire CLK_25M;
wire Ready_Sig;
wire [10:0] Column_Addr_Sig;
wire [10:0] Row_Addr_Sig;
wire [3:0] button_out;
wire [14:0] pic_add;
wire [7:0] pic_data;
wire [7:0] char_add;
wire [31:0] char_data;
wire [8:0] num_add;
wire [15:0] num_data;
wire error;
wire [3:0]tb1,tb2,hf1,hf2,hf3,zl1,zl2,zl3;
fenpin U0
( CLK,
RSTn,
CLK_25M
);
key_delay U1
( CLK,
RSTn,
button,
button_out
);
sync_module U2
( CLK_25M,
RSTn,
v,
h,
Ready_Sig,
Column_Addr_Sig,
Row_Addr_Sig
);
vga_control_module U3
( CLK_25M,
RSTn,
Ready_Sig,
Column_Addr_Sig,
Row_Addr_Sig,
pic_data,
pic_add,
char_data,
char_add,
num_data,
num_add,
wupin,
rgb,
error,
tb1,tb2,hf1,hf2,hf3,zl1,zl2,zl3
);
pic U4
( CLK,
pic_add,
pic_data
);
char U5
( CLK,
char_add,
char_data
);
num U6
( CLK,
num_add,
num_data
);
main u7
( CLK,
RSTn,
button_out,
wupin,
error,
tb1,tb2,hf1,hf2,hf3,zl1,zl2,zl3
);
Endmodule
FPGA开发板截图:
(1)、初始界面:
(2)、投币:
(3)、选购物品(被选中的会显示一个红框,同是在花费中算出总的花费):
(4)、购买并找零(此时投币会清空):
(5)、如果投币不够就购买,找零出会显示”….”,投币也会清空: