900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 数字逻辑电路与系统 课程设计:基于FPGA的乒乓球游戏

数字逻辑电路与系统 课程设计:基于FPGA的乒乓球游戏

时间:2024-06-07 22:35:25

相关推荐

数字逻辑电路与系统 课程设计:基于FPGA的乒乓球游戏

设计目的

使用FPGA实验班设计一个数字逻辑系统,巩固数字逻辑电路的相关知识,锻炼熟练使用FPGA设计软件和硬件和独立完成项目设计的能力。

二、设计内容

2.1摘要

设计一个乒乓球游戏,实现游戏功能和计分功能。

通过开发板的按键实现左右球拍的击拍和游戏的复位;通过数码管显示游戏的比分;通过led显示乒乓球的运动轨迹。

2.2游戏规则

第一步:按下复位,led不亮,数码管显示比分00–00。

第二步:按下左球拍或者右球拍,发球,游戏开始,发球方向随机。

第三步:乒乓球在左半场/右半场并且靠近左侧/右侧的时候,左球拍/右球拍可以击球。如果在错误的时机击球或未成功接球,判负,对方加一分。

第四步:当有一方积得11分,游戏结束。再次开始游戏需要进行复位。

三、设计思路

3.2流程图

3.2顶层框图

3.3接口说明

名称 类型 封装管脚 说明

clk input PIN_AF14 时钟信号

rst_n input PIN_AA15 全局复位

key_left input PIN_Y16 左球拍

key_right input PIN_AA14 右球拍

Seven_segment output 数码管对应管脚 计分器

led output led对应管脚 运球轨迹

3.4分模块框图

四、代码实现

4.1顶层文件

module play_table_tennis (

inputwireclk,// 50Mhzinputwirerst_n,// low validoutputwire[41:0]seven_segment,// low validoutputwire[9:0]led,// high validinputwirekey_left,// low validinputwirekey_right// low valid

);

wireflag_left;wireflag_right;wire[3:0]left_num;wire[3:0]right_num;key_processor key_processor_inst(.clk(clk),.rst_n(rst_n),.key_left(key_left),.key_right(key_right),.flag_left(flag_left),.flag_right(flag_right));controller controller_inst(.clk(clk),.rst_n(rst_n),.flag_left(flag_left),.flag_right(flag_right),.left_num(left_num),.right_num(right_num),.led(led));seven_tube_drive seven_tube_drive_inst(.clk(clk),.rst_n(rst_n),.left_num(left_num),.right_num(right_num),.seven_segment(seven_segment));

endmodule

4.2按键

module key_processor (

inputwireclk,inputwirerst_n,inputwirekey_left,inputwirekey_right,outputwireflag_left,outputwireflag_right

);

key_filter key_filter_inst_left(.clk(clk),.rst_n(rst_n),.key(key_left),.flag(flag_left));key_filter key_filter_inst_right(.clk(clk),.rst_n(rst_n),.key(key_right),.flag(flag_right));

endmodule

module key_filter (

inputwireclk,inputwirerst_n,inputwirekey,outputregflag

);

parameter T =500_000;reg[18:0]cnt;reg[2:0]state;regkey_r;regkey_rr;always @ (posedge clk, negedge rst_n) beginif (rst_n == 1'b0) beginkey_r <= 1'b1;key_rr <= 1'b1;endelse beginkey_r <= key;key_rr <= key_r;endendalways @ (posedge clk, negedge rst_n) beginif (rst_n == 1'b0) beginstate <= 3'd0;cnt <= 19'd0;flag <= 1'b0;endelse case (state)3'd0:beginstate <= 3'd1;cnt <= 19'd0;flag <= 1'b0;end3'd1:beginif (key_rr == 1'b0)state <= 3'd2;elsestate <= 3'd1;end3'd2:beginif (key_rr == 1'b1) beginstate <= 3'd1;cnt <= 19'd0;endelse if (cnt < T - 1'b1)cnt <= cnt + 1'b1;else begincnt <= 19'd0;state <= 3'd3;flag <= 1'b1;endend3'd3:beginflag <= 1'b0;if (key_rr == 1'b1)state <= 3'd4;elsestate <= 3'd3;end3'd4:beginif (key_rr == 1'b0) beginstate <= 3'd3;cnt <= 19'd0;endelse if (cnt < T - 1'b1)cnt <= cnt + 1'b1;else begincnt <= 19'd0;state <= 3'd0;endenddefault : state <= 3'd0;endcaseend

endmodule

4.3控制器

module controller (

inputwireclk,inputwirerst_n,inputwireflag_left,inputwireflag_right,outputreg[3:0]left_num,outputreg[3:0]right_num,outputreg[9:0]led

);

parameterT=50_000_000;reg[25:0]cnt;wireflag_t;regtime_on;reginit_dir;regdir; // 0 right 1 leftreg[3:0]state;always @ (posedge clk, negedge rst_n) beginif (rst_n == 1'b0)cnt <= 26'd0;elseif (time_on == 1'b0 || flag_left == 1'b1 || flag_right == 1'b1)cnt <= 26'd0;elseif (cnt < T - 1'b1)cnt <= cnt + 1'b1;elsecnt <= 26'd0;endassign flag_t = (cnt == T - 1'b1);always @ (posedge clk, negedge rst_n) beginif (rst_n == 1'b0)init_dir <= 1'b0;elseinit_dir <= ~init_dir;endalways @ (posedge clk, negedge rst_n) beginif (rst_n == 1'b0) beginstate <= 4'd0;dir <= 1'b0;left_num <= 4'd0;right_num <= 4'd0;led <= 10'd0;time_on <= 1'b0;endelsecase (state)4'd0:beginstate <= 4'd1;dir <= 1'b0;left_num <= 4'd0;right_num <= 4'd0;led <= 10'd0;time_on <= 1'b0;end4'd1:beginif (flag_left ==1'b1 || flag_right == 1'b1) beginif (init_dir == 1'b1) begindir <= init_dir;state <= 4'd6;time_on <= 1'b1;endelse begindir <= init_dir;state <= 4'd7;time_on <= 1'b1;endendelse state <= 4'd1;end4'd2:beginled <= 10'b10000_00000;if (flag_right == 1'b1)state <= 4'd12;elseif (flag_left == 1'b1)if (dir == 1'b1) begindir <= ~dir;state <= 4'd3;endelse state <= 4'd13;elseif (flag_t == 1'b1)if (dir == 1'b0)state <= 4'd3;elsestate <= 4'd13;elsestate <= 4'd2;end4'd3:beginled <= 10'b01000_00000;if (flag_right == 1'b1)state <= 4'd12;elseif (flag_left == 1'b1)if (dir == 1'b1) begindir <= ~dir;state <= 4'd4;endelse state <= 4'd13;elseif (flag_t == 1'b1)if (dir == 1'b0)state <= 4'd4;elsestate <= 4'd2;elsestate <= 4'd3;end4'd4:beginled <= 10'b00100_00000;if (flag_right == 1'b1)state <= 4'd12;elseif (flag_left == 1'b1)if (dir == 1'b1) begindir <= ~dir;state <= 4'd5;endelse state <= 4'd13;elseif (flag_t == 1'b1)if (dir == 1'b0)state <= 4'd5;elsestate <= 4'd3;elsestate <= 4'd4;end4'd5:beginled <= 10'b00010_00000;if (flag_right == 1'b1)state <= 4'd12;elseif (flag_left == 1'b1)if (dir == 1'b1) begindir <= ~dir;state <= 4'd6;endelse state <= 4'd13;elseif (flag_t == 1'b1)if (dir == 1'b0)state <= 4'd6;elsestate <= 4'd4;elsestate <= 4'd5;end4'd6:beginled <= 10'b00001_00000;if (flag_right == 1'b1)state <= 4'd12;elseif (flag_left == 1'b1)if (dir == 1'b1) begindir <= ~dir;state <= 4'd7;endelse state <= 4'd13;elseif (flag_t == 1'b1)if (dir == 1'b0)state <= 4'd7;elsestate <= 4'd5;elsestate <= 4'd6;end4'd7:beginled <= 10'b00000_10000;if (flag_left == 1'b1)state <= 4'd13;elseif (flag_right == 1'b1)if (dir == 1'b0) begindir <= ~dir;state <= 4'd6;endelse state <= 4'd12;elseif (flag_t == 1'b1)if (dir == 1'b0)state <= 4'd8;elsestate <= 4'd6;elsestate <= 4'd7;end4'd8:beginled <= 10'b00000_01000;if (flag_left == 1'b1)state <= 4'd13;elseif (flag_right == 1'b1)if (dir == 1'b0) begindir <= ~dir;state <= 4'd7;endelse state <= 4'd12;elseif (flag_t == 1'b1)if (dir == 1'b0)state <= 4'd9;elsestate <= 4'd7;elsestate <= 4'd8;end4'd9:beginled <= 10'b00000_00100;if (flag_left == 1'b1)state <= 4'd13;elseif (flag_right == 1'b1)if (dir == 1'b0) begindir <= ~dir;state <= 4'd8;endelse state <= 4'd12;elseif (flag_t == 1'b1)if (dir == 1'b0)state <= 4'd10;elsestate <= 4'd8;elsestate <= 4'd9;end4'd10:beginled <= 10'b00000_00010;if (flag_left == 1'b1)state <= 4'd13;elseif (flag_right == 1'b1)if (dir == 1'b0) begindir <= ~dir;state <= 4'd9;endelse state <= 4'd12;elseif (flag_t == 1'b1)if (dir == 1'b0)state <= 4'd11;elsestate <= 4'd9;elsestate <= 4'd10;end4'd11:beginled <= 10'b00000_00001;if (flag_left == 1'b1)state <= 4'd13;elseif (flag_right == 1'b1)if (dir == 1'b0) begindir <= ~dir;state <= 4'd10;endelse state <= 4'd12;elseif (flag_t == 1'b1)if (dir == 1'b0)state <= 4'd12;elsestate <= 4'd10;elsestate <= 4'd11;end4'd12:beginled <= 10'd0;time_on <= 1'b0;if (left_num < 4'd10) beginstate <= 4'd1;left_num <= left_num + 1'b1;endelse beginstate <= 4'd14;left_num <= left_num + 1'b1;endend4'd13:beginled <= 10'd0;time_on <= 1'b0;if (right_num < 4'd10) beginstate <= 4'd1;right_num <= right_num + 1'b1;endelse beginstate <= 4'd14;right_num <= right_num + 1'b1;endend4'd14:state <= 4'd14;default : state <= 4'd0;endcaseend

endmodule

4.4数码管显示

module seven_tube_drive (

inputwireclk,inputwirerst_n,inputwire[3:0]left_num,inputwire[3:0]right_num,outputwire[41:0]seven_segment

);

wire[3:0]data_0;wire[3:0]data_1;wire[3:0]data_2;wire[3:0]data_3;wire[3:0]data_4;wire[3:0]data_5;show_data_sel show_data_sel_inst(.clk(clk),.rst_n(rst_n),.left_num(left_num),.right_num(right_num),.data_0(data_0),.data_1(data_1),.data_2(data_2),.data_3(data_3),.data_4(data_4),.data_5(data_5));single_seven_tube_drive single_seven_tube_drive_inst0(.clk(clk),.rst_n(rst_n),.data(data_0),.seven_segment(seven_segment[6:0]));single_seven_tube_drive single_seven_tube_drive_inst1(.clk(clk),.rst_n(rst_n),.data(data_1),.seven_segment(seven_segment[13:7]));single_seven_tube_drive single_seven_tube_drive_inst2(.clk(clk),.rst_n(rst_n),.data(data_2),.seven_segment(seven_segment[20:14]));single_seven_tube_drive single_seven_tube_drive_inst3(.clk(clk),.rst_n(rst_n),.data(data_3),.seven_segment(seven_segment[27:21]));single_seven_tube_drive single_seven_tube_drive_inst4(.clk(clk),.rst_n(rst_n),.data(data_4),.seven_segment(seven_segment[34:28]));single_seven_tube_drive single_seven_tube_drive_inst5(.clk(clk),.rst_n(rst_n),.data(data_5),.seven_segment(seven_segment[41:35]));

endmodule

module single_seven_tube_drive (

inputwireclk,inputwirerst_n,inputwire[3:0]data,outputreg[6:0]seven_segment

);

always @ (posedge clk, negedge rst_n) beginif (rst_n == 1'b0)seven_segment <= 7'h7f;elsecase (data)4'd0:seven_segment <= 7'b100_0000;4'd1:seven_segment <= 7'b111_1001;4'd2:seven_segment <= 7'b010_0100;4'd3:seven_segment <= 7'b011_0000;4'd4:seven_segment <= 7'b001_1001;4'd5:seven_segment <= 7'b001_0010;4'd6:seven_segment <= 7'b000_0010;4'd7:seven_segment <= 7'b111_1000;4'd8:seven_segment <= 7'b000_0000;4'd9:seven_segment <= 7'b001_0000;4'd10:seven_segment <= 7'b011_1111;default:seven_segment <= 7'h7f;endcaseend

endmodule

module show_data_sel (

inputwireclk,inputwirerst_n,inputwire[3:0]left_num,inputwire[3:0]right_num,outputreg[3:0]data_0,outputreg[3:0]data_1,outputwire[3:0]data_2,outputwire[3:0]data_3,outputreg[3:0]data_4,outputreg[3:0]data_5

);

assign data_2 = 4'ha;assign data_3 = 4'ha;always @ (posedge clk, negedge rst_n) beginif (rst_n == 1'b0)data_0 <= 4'hb;elsedata_0 <= right_num%10;endalways @ (posedge clk, negedge rst_n) beginif (rst_n == 1'b0)data_1 <= 4'hb;elsedata_1 <= right_num/10;endalways @ (posedge clk, negedge rst_n) beginif (rst_n == 1'b0)data_4 <= 4'hb;elsedata_4 <= left_num%10;endalways @ (posedge clk, negedge rst_n) beginif (rst_n == 1'b0)data_5 <= 4'hb;elsedata_5 <= left_num/10;end

endmodule

五、顶层仿真

5.1testbench代码

`timescale 1ns/1ps

module play_table_tennis_tb;

regclk;regrst_n;wire[41:0]seven_segment;wire[9:0]led;regkey_left;regkey_right;defparam play_table_tennis_inst.key_processor_inst.key_filter_inst_left.T = 10;defparam play_table_tennis_inst.key_processor_inst.key_filter_inst_right.T = 10;defparam play_table_tennis_inst.controller_inst.T = 100;play_table_tennis play_table_tennis_inst(clk,// 50Mhzrst_n,// low validseven_segment,// low validled,// high validkey_left,// low validkey_right// low valid);initial clk = 1'b0;always # 10 clk = ~clk;initial beginrst_n = 1'b0;key_left = 1'b1;key_right = 1'b1;# 201rst_n = 1'b1;# 200;press_left;press_left;press_left;press_left;press_left;press_left;press_left;press_left;press_left;press_right;press_right;press_right;press_right;press_right;press_right;$stop;endtask press_left;begin@ (posedge clk);# 2;key_left = 1'b0;# 500@ (posedge clk);# 2;key_left = 1'b1;# 5000;endendtasktask press_right;begin@ (posedge clk);# 2;key_right = 1'b0;# 500@ (posedge clk);# 2;key_right = 1'b1;# 5000;endendtask

endmodule

5.2仿真波形

在仿真中,模拟击打左球拍和击打有球拍的情况,从仿真波形中可以看出,当模拟击打球拍时,LED显示出乒乓球运动轨迹,再次击打球拍后,重新发球,数码管计分器数字变化。

六、下板实验

6.1引脚绑定

6.2下板实验

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。