由于本人偷懒一直没有按时去做这个大作业,导致在验收前一天才开始去动手去做,感到十分痛苦。 建议每个人都自己提前去尝试完成,如果实在是像我一样没时间了,可以参考一下这个做法。
1.我使用的是vivado2021.2版本,第一步create project,这一步一定要按照学校发的实验指导书把开发板的型号输入,咱们学校应该用的都是xc7a35tcsg324-3,如果开发板不一样后续管教约束的时候会出现错误。2.create design sources这里我们把文件命名为pingpong1.v,然后把代码替换进去,再create constraints,文件名为pingpong.xdc,再把管脚约束代码替换进去,保存,这样代码部分就全部完成了,不需要仿真代码,直接烧板子就可以了。
module pingpong1(
input clk, //时钟
input rst, //复位键
input [0:4] key, //按键输入
output [0:7] seg_cs, //数码管位选
output [0:7] seg_data0, //前四个数码管
output ring,
output [0:15] led, //LED灯
output [0:7] seg_data1 //后四个数码管
);
reg beep = 1'b0; //蜂鸣器
reg [0:7] smg; //数码管段码
reg [0:7] wz; //数码管位选
reg [0:1] cnt_wz; //数码管状态
reg [0:17] cnt_500Hz; //500Hz扫描
reg [0:20] cnt_xd = 0; //消抖计时
reg [0:26] speed; //球的运动计时
reg [0:25] sound; //蜂鸣器计时
reg [0:26] sd = 27'd25000000; //球的运动速度,如果觉得游戏速度过慢,可以修改程序里其的数值
reg [0:6] player1 = 0; //玩家1的得分
reg [0:6] player2 = 0; //玩家2的得分
reg [0:3] num; //中间变量
reg [0:1] key_out = 0; //按键
reg [0:15] light = 16'h8000; //LED的过渡寄存器
reg state = 1'b0; //游戏运行状态,0是发球状态,1是击球状态
reg pos = 1'b0; //球的运动方向,0是向右,1是向左
reg DIR = 1'b0; //500Hz分频
reg DIR1 = 1'b0; //0.5s分频
reg DIR2 = 1'b0; //1s分频
parameter xd = 21'd1000000; //计时_10ms
always@(posedge clk) begin //消抖计时
if(key == 5'b00000) //抖动即重新开始
cnt_xd <= 0;
else if(cnt_xd == xd)
cnt_xd <= xd;
else
cnt_xd <= cnt_xd + 1;
end
always@(posedge clk) begin
if(cnt_xd == 0)
key_out <= 0;
else if(cnt_xd == (xd - 21'b1)) //产生1个时间单位的按键信号
case(key) //根据键入得到对应的值
5'b10000: key_out <= 1;
5'b00010: key_out <= 2;
endcase
else
key_out <= 0; //0表示无按键按下
end
always @(posedge clk) begin //球的运动计时模块
if(state == 1)
begin
if(speed >= sd)
begin
speed <= 0;
DIR1 <= 1'b1;
end
else
begin
speed <= speed + 1;
DIR1 <= 1'b0;
end
end
else
begin
if(speed >= 27'd100000000) //1s
begin
speed <= 0;
DIR2 <= 1'b1;
end
else
begin
speed <= speed + 1;
DIR2 <= 1'b0;
end
end
end
always @(posedge clk) begin //游戏的核心逻辑模块
if(!rst)
begin
player1 <= 0;
player2 <= 0;
end
else if(key_out == 1)
begin
if(state == 1'b0 & light == 16'h0001)
begin
state <= 1'b1;
pos <= 1'b1;
sd <= 27'd25000000;
end
else if(light == 16'h0002)
begin
pos <= 1'b1;
if(speed >= sd / 2)
sd <= 27'd25000000;
else if(speed >= sd / 4)
sd <= 27'd20000000;
else if(speed >= sd / 8)
sd <= 27'd15000000;
else
sd <= 27'd10000000;
end
else
begin
pos <= pos;
state <= state;
end
end
else if(key_out == 2)
begin
if(state == 1'b0 & light == 16'h8000)
begin
state <= 1'b1;
pos <= 1'b0;
sd <= 27'd25000000;
end
else if(light == 16'h4000)
begin
pos <= 1'b0;
if(speed >= sd / 2)
sd <= 27'd25000000;
else if(speed >= sd / 4)
sd <= 27'd20000000;
else if(speed >= sd / 8)
sd <= 27'd15000000;
else
sd <= 27'd10000000;
end
else
begin
pos <= pos;
state <= state;
end
end
else if(light <= 16'h0000)
begin
state <= 0;
if(DIR2 == 1'b1)
case (pos)
1'b0 : player1 <= player1 + 1;
1'b1 : player2 <= player2 + 1;
endcase
end
else
begin
state <= state;
pos <= pos;
player1 <= player1;
player2 <= player2;
end
end
always @(posedge clk) begin //蜂鸣器输出模块
if(key_out == 2 & light == 16'h4000)
beep <= 1'b1;
else if(key_out == 1 & light == 16'h0002)
beep <= 1'b1;
else if(beep == 1)
begin
if(sound >= 26'd50000000) //0.5s
begin
sound <= 0;
beep <= 0;
end
else
sound <= sound + 1;
end
else
beep <= beep;
end
always @(posedge clk) begin //LED灯状态输出模块
if(DIR1 == 1'b1)
case (pos)
1'b0 : light <= light >> 1;
1'b1 : light <= light << 1;
default: light <= 0;
endcase
else if(light <= 16'h0000 & DIR2 == 1'b1)
case (pos)
1'b0 : light <= 16'h0001;
1'b1 : light <= 16'h8000;
default: light <= 0;
endcase
else
light <= light;
end
always@(posedge clk) begin //数码管扫描计时
if(cnt_500Hz >= 18'd200000) //500Hz
begin
cnt_500Hz <= 0;
DIR <= 1'b1; //产生一个上升沿
end
else
begin
cnt_500Hz <= cnt_500Hz +1;
DIR <= 1'b0;
end
end
always@(posedge DIR) begin
if(cnt_wz == 3)
cnt_wz <= 0;
else
cnt_wz <= cnt_wz + 1; //cnt_wz表示不同数码管的状态
end
always @(posedge clk) begin
case(cnt_wz)
2'd0 : wz <= 8'b10000000;
2'd1 : wz <= 8'b01000000;
2'd2 : wz <= 8'b00000010;
2'd3 : wz <= 8'b00000001;
default : wz <= 8'b00000000;
endcase
end
always @(posedge clk) begin
case (cnt_wz)
2'd0 : num <= player1 / 10;
2'd1 : num <= player1 % 10;
2'd2 : num <= player2 / 10;
2'd3 : num <= player2 % 10;
default: num <= 0;
endcase
end
always @(posedge clk) begin
case (num)
4'd0: smg <= 8'b11111100;
4'd1: smg <= 8'b01100000;
4'd2: smg <= 8'b11011010;
4'd3: smg <= 8'b11110010;
4'd4: smg <= 8'b01100110;
4'd5: smg <= 8'b10110110;
4'd6: smg <= 8'b10111110;
4'd7: smg <= 8'b11100000;
4'd8: smg <= 8'b11111110;
4'd9: smg <= 8'b11110110;
default: smg <= 8'b00000000;
endcase
end
assign ring = beep;
assign seg_data0 = smg; //段码输送
assign seg_data1 = smg;
assign seg_cs = wz; //位选输送
assign led = light; //LED输送
endmodule
set_property -dict {PACKAGE_PIN P17 IOSTANDARD LVCMOS33} [get_ports clk]
set_property -dict {PACKAGE_PIN P15 IOSTANDARD LVCMOS33} [get_ports rst]
set_property -dict {PACKAGE_PIN M6 IOSTANDARD LVCMOS33} [get_ports {ring} ]
#数码管位选
set_property -dict {PACKAGE_PIN G2 IOSTANDARD LVCMOS33} [get_ports {seg_cs[0]}]
set_property -dict {PACKAGE_PIN C2 IOSTANDARD LVCMOS33} [get_ports {seg_cs[1]}]
set_property -dict {PACKAGE_PIN C1 IOSTANDARD LVCMOS33} [get_ports {seg_cs[2]}]
set_property -dict {PACKAGE_PIN H1 IOSTANDARD LVCMOS33} [get_ports {seg_cs[3]}]
set_property -dict {PACKAGE_PIN G1 IOSTANDARD LVCMOS33} [get_ports {seg_cs[4]}]
set_property -dict {PACKAGE_PIN F1 IOSTANDARD LVCMOS33} [get_ports {seg_cs[5]}]
set_property -dict {PACKAGE_PIN E1 IOSTANDARD LVCMOS33} [get_ports {seg_cs[6]}]
set_property -dict {PACKAGE_PIN G6 IOSTANDARD LVCMOS33} [get_ports {seg_cs[7]}]
#数码管段选
set_property -dict {PACKAGE_PIN B4 IOSTANDARD LVCMOS33} [get_ports {seg_data0[0]}]
set_property -dict {PACKAGE_PIN A4 IOSTANDARD LVCMOS33} [get_ports {seg_data0[1]}]
set_property -dict {PACKAGE_PIN A3 IOSTANDARD LVCMOS33} [get_ports {seg_data0[2]}]
set_property -dict {PACKAGE_PIN B1 IOSTANDARD LVCMOS33} [get_ports {seg_data0[3]}]
set_property -dict {PACKAGE_PIN A1 IOSTANDARD LVCMOS33} [get_ports {seg_data0[4]}]
set_property -dict {PACKAGE_PIN B3 IOSTANDARD LVCMOS33} [get_ports {seg_data0[5]}]
set_property -dict {PACKAGE_PIN B2 IOSTANDARD LVCMOS33} [get_ports {seg_data0[6]}]
set_property -dict {PACKAGE_PIN D5 IOSTANDARD LVCMOS33} [get_ports {seg_data0[7]}]
#另一组数码管段选
set_property -dict {PACKAGE_PIN D4 IOSTANDARD LVCMOS33} [get_ports {seg_data1[0]}]
set_property -dict {PACKAGE_PIN E3 IOSTANDARD LVCMOS33} [get_ports {seg_data1[1]}]
set_property -dict {PACKAGE_PIN D3 IOSTANDARD LVCMOS33} [get_ports {seg_data1[2]}]
set_property -dict {PACKAGE_PIN F4 IOSTANDARD LVCMOS33} [get_ports {seg_data1[3]}]
set_property -dict {PACKAGE_PIN F3 IOSTANDARD LVCMOS33} [get_ports {seg_data1[4]}]
set_property -dict {PACKAGE_PIN E2 IOSTANDARD LVCMOS33} [get_ports {seg_data1[5]}]
set_property -dict {PACKAGE_PIN D2 IOSTANDARD LVCMOS33} [get_ports {seg_data1[6]}]
set_property -dict {PACKAGE_PIN H2 IOSTANDARD LVCMOS33} [get_ports {seg_data1[7]}]
#八个LED
set_property -dict {PACKAGE_PIN F6 IOSTANDARD LVCMOS33} [get_ports {led[0]}]
set_property -dict {PACKAGE_PIN G4 IOSTANDARD LVCMOS33} [get_ports {led[1]}]
set_property -dict {PACKAGE_PIN G3 IOSTANDARD LVCMOS33} [get_ports {led[2]}]
set_property -dict {PACKAGE_PIN J4 IOSTANDARD LVCMOS33} [get_ports {led[3]}]
set_property -dict {PACKAGE_PIN H4 IOSTANDARD LVCMOS33} [get_ports {led[4]}]
set_property -dict {PACKAGE_PIN J3 IOSTANDARD LVCMOS33} [get_ports {led[5]}]
set_property -dict {PACKAGE_PIN J2 IOSTANDARD LVCMOS33} [get_ports {led[6]}]
set_property -dict {PACKAGE_PIN K2 IOSTANDARD LVCMOS33} [get_ports {led[7]}]
set_property -dict {PACKAGE_PIN K1 IOSTANDARD LVCMOS33} [get_ports {led[8]}]
set_property -dict {PACKAGE_PIN H6 IOSTANDARD LVCMOS33} [get_ports {led[9]}]
set_property -dict {PACKAGE_PIN H5 IOSTANDARD LVCMOS33} [get_ports {led[10]}]
set_property -dict {PACKAGE_PIN J5 IOSTANDARD LVCMOS33} [get_ports {led[11]}]
set_property -dict {PACKAGE_PIN K6 IOSTANDARD LVCMOS33} [get_ports {led[12]}]
set_property -dict {PACKAGE_PIN L1 IOSTANDARD LVCMOS33} [get_ports {led[13]}]
set_property -dict {PACKAGE_PIN M1 IOSTANDARD LVCMOS33} [get_ports {led[14]}]
set_property -dict {PACKAGE_PIN K3 IOSTANDARD LVCMOS33} [get_ports {led[15]}]
#五个按键
set_property -dict {PACKAGE_PIN R11 IOSTANDARD LVCMOS33} [get_ports {key[0]}]
set_property -dict {PACKAGE_PIN R17 IOSTANDARD LVCMOS33} [get_ports {key[1]}]
set_property -dict {PACKAGE_PIN R15 IOSTANDARD LVCMOS33} [get_ports {key[2]}]
set_property -dict {PACKAGE_PIN V1 IOSTANDARD LVCMOS33} [get_ports {key[3]}]
set_property -dict {PACKAGE_PIN U4 IOSTANDARD LVCMOS33} [get_ports {key[4]}]
3.连接开发板,这里我们按照实验指导书的教学一步步跟着走即可,我们先把开发板和电脑用线连接上 然后在vivado进行如下操作1.选择Run Synthesis 2.在弹出窗口选择 Run Implementation 点击OK 3. 等待一会完成之后,在弹出窗口再选择 Open Implemented Design 4.选择 Generate Bitstream,下载比特流文件 5.下载完成后选择 Open Hardware Manager 6.auto connect 7.在页面上面的program divice 里点击program
这样就连接上开发板,可以进行实操检验了。 上面的两个数字是双方得分,下面是乒乓球运动区域,具体讲解可以参考b站,这里右很多FPGA实例,这个代码也是从这个视频中学到的。主要是有开发板操作的讲解,代码讲解较为粗糙,需要自己理解并写实验报告。FPGA | 密码锁、饮料机、数字时钟和呼吸灯等设计分享与讲解(附程序代码)_哔哩哔哩_bilibili