课程设计实验报告基于spartan3an的贪吃蛇游戏设计

上传人:仙*** 文档编号:37530622 上传时间:2021-11-03 格式:DOC 页数:29 大小:191KB
返回 下载 相关 举报
课程设计实验报告基于spartan3an的贪吃蛇游戏设计_第1页
第1页 / 共29页
课程设计实验报告基于spartan3an的贪吃蛇游戏设计_第2页
第2页 / 共29页
课程设计实验报告基于spartan3an的贪吃蛇游戏设计_第3页
第3页 / 共29页
点击查看更多>>
资源描述
贪吃蛇游戏设计基于Xilinx Spartan-3anFPGA开发板专业:电子科学与技术学号:姓名: 贪吃蛇游戏设计基于Xilinx Spartan-3anFPGA开发板一、实验要求设计一款贪吃蛇游戏。设计平台为xilinx的spartan3an FPGA开发板。通过VGA接口控制液晶显示器,在液晶显示器上实现该游戏。具体要求为,在液晶显示器上有一移动的”蛇”,通过开发板上的拨码开关实现“蛇”上下左右移动。并且要求“蛇”只能在显示器一定范围内运动,若碰到坐标区域的边缘或者“蛇”的身体,则游戏结束。同时会在屏幕有效区域随机出现“苹果”,“蛇”每吃到一次苹果则表示一次成功操作,得分加1,并在数码管上显示得分。本实验刚开始的蛇身长度定位3。为了便于书写程序,我们设定蛇的最大长度为16。二、实验原理 (1)VGA接口 本开发板提供VGA接口。对硬件进行编程,输出标准的VGA信号(红、绿、蓝三色信号和行、帧同步信号),通过15针VGA接口输出至显示器,可驱动显示器显示图像信号。如下图所示: 在实验中只需使用其中的五个引脚,如上图所示。VGA接口信号基本时序图如下图所示:符号含义垂直同步水平同步时间时钟线数时间时钟TS同步脉冲时间16.7ms41680052132us800TDISP显示时间15.36ms38400048025.6us640TPWVsync脉冲宽度64us160023.84us96TFP前沿320us800010640ns16TBP后沿928us23200291.92us48表1 640*480模式下的VGA时序图信号FPGA管教约束VGA_RT13VGA_GV13VGA_BU13H_SYNCW13V_SYNCY13表2 VGA引脚配置(2)拨码开关 本游戏通过开发板下方的四个拨码开关来实现上下左右控制。4拨码开关直接接入FPGA管脚,用户可自行配置。拨码开关拨到“ON”位置时,其状态为“0”,否则状态为“1”;按键连接原理图如下:信号FPGA管脚约束SW1_1J4SW1_2H3SW1_3J3SW1_4J2表3 4码开关FPGA引脚配置(3)LED数码管此开发板提供4个LED数码管,可显示数字,直接与FPGA相连,其控制方法为扫描式,如图所示,此数码管内部接线为共阴方式,即低电平亮。所以若要控制左边第一个七节灯管输出2的字型,可以先输出“0010010”到CADP,然后输出“0111”到A1A4即可。 信号FPGA管教约束LED_BIT1M2LED_BIT2M3LED_BIT3M4LED_BIT4M5LED_CAN1LED_CBN2LED_CCN3LED_CDN4LED_CET1LED_CFT2LED_CGT3LED_DPR4表4 7段数码管FPGA引脚配置三、实验代码1. 由于本实验涉及的模块较多,我们采用小模块化设计的思想。本设计含有六个子模块,分别是: Game_ctrl_unit Snake_eating_apple Snake Key VGA_control Seg_display顶层模块代码如下:module Greedy_Snake (input clk,input reset,input left,input right,input up,input down,output h_sync,output v_sync,output 2:0 color_out,output 7:0 seg_out,output 3:0 sel);wire left_key_press,right_key_press, up_key_press, down_key_press;wire 1:0 snake;wire 9:0 x_pos;wire 9:0 y_pos;wire 5:0 apple_x;wire 4:0 apple_y;wire 5:0 head_x;wire 5:0 head_y;wire add_cube;wire 1:0 game_status;wire hit_wall;wire hit_body;wire die_flash;wire restart;wire 6:0 cube_num;Game_ctrl_unit game_ctrl_unit1( .clk(clk),.reset(reset),.key1_press(left_key_press),.key2_press(right_key_press),.key3_press(up_key_press),.key4_press(down_key_press),.game_status(game_status),.hit_wall(hit_wall),.hit_body(hit_body),.die_flash(die_flash),.restart(restart) ); Snake_eating_apple snake_eating_apple1( .clk(clk),.reset(reset),.apple_x(apple_x),.apple_y(apple_y),.head_x(head_x),.head_y(head_y),.add_cube(add_cube) );Snake snake(.clk(clk),reset(reset),.left_press(left_key_press),.right_press(right_key_press),.up_press(up_key_press),.down_press(down_key_press),.snake(snake),.x_pos(x_pos),.y_pos(y_pos),.head_x(head_x),.head_y(head_y),.add_cube(add_cube),.game_status(game_status),.cube_num(cube_num),.hit_body(hit_body),.hit_wall(hit_wall),.die_flash(die_flash) );VGA_control vga_control(.clk(clk),.reset(reset),.h_sync(h_sync), .v_sync(v_sync), .snake(snake),.color_out(color_out),.x_pos(x_pos), .y_pos(y_pos),.apple_x(apple_x),.apple_y(apple_y) );Key key1( .clk(clk),.reset(reset),.left(left),.right(right),.up(up),.down(down),.left_key_press(left_key_press), .right_key_press(right_key_press),.up_key_press(up_key_press),.down_key_press(down_key_press) ); Seg_display Seg_display1( .clk(clk),.reset(reset),.add_cube(add_cube),.seg_out(seg_out),.sel(sel) );endmodule2.每个子模块的实现方法及要求 2.1 Game_ctrl_unit本模块从其他模块接受信号,决定游戏状态(ready、play、die),并且产生其他模块的控制信号。在ready的状态下,只要有键按下(上下左右),则蛇就会自动向右运动,从而进入play的状态。在play状态下,本模块等待hit_wall或者hit_body的信号,如果这两个信号发生,则进入die状态,即游戏结束。在die状态下,屏幕会闪烁一段时间,最后进入ready状态。此子模块代码如下:module Game_ctrl_unit(input clk,input reset,input key1_press,input key2_press,input key3_press,input key4_press,input hit_wall,input hit_body,output reg 1:0 game_status,output reg die_flash,output reg restart);localparam RESTART = 2b00;localparam START = 2b01;localparam PLAY = 2b10;localparam DIE = 2b11;reg 31:0 clk_cnt;always ( posedge clk ) begin if( !reset ) begin game_status = START; clk_cnt = 0; die_flash = 1; restart = 0; endelse begin case( game_status ) RESTART:begin if( clk_cnt = 5 ) begin clk_cnt = clk_cnt + 1; restart = 1; end else begin game_status = START; clk_cnt = 0; restart = 0; endend START: begin if( key1_press | key2_press | key3_press | key4_press ) begingame_status = PLAY; end end PLAY: begin if( hit_wall | hit_body ) game_status = DIE;end DIE: begin if( clk_cnt = 200000000 ) begin clk_cnt = clk_cnt + 1; if( clk_cnt = 25000000 ) die_flash = 0; else if( clk_cnt = 50000000 ) die_flash = 1; else if( clk_cnt = 75000000 )die_flash = 0; else if( clk_cnt = 100000000 )die_flash = 1; else if( clk_cnt = 125000000 )die_flash = 0; else if( clk_cnt = 150000000 )die_flash = 1; end else begin die_flash = 1; clk_cnt = 0; game_status = RESTART; end end endcaseendendendmodule2.2 Snake 这是本次试验最复杂的部分,此模块需要完成四项任务:(1)保持蛇的运动 (2)根据按下的键改变蛇的运动方向 (3)判断蛇是否碰撞墙或者自己的身体 (4)在液晶显示器上显示根据VGA_control模块此子模块代码如下:module Snake (input clk,input reset,input left_press,input right_press,input up_press,input down_press,input 9:0 x_pos,input 9:0 y_pos,input add_cube,input 1:0 game_status,input die_flash,output reg 1:0 snake,output reg 6:0 cube_num,output 5:0 head_x,output 5:0 head_y,output reg hit_body,output reg hit_wall);localparam UP = 2b00;localparam DOWN = 2b01;localparam LEFT = 2b10;localparam RIGHT = 2b11;localparam NONE = 2b00;localparam HEAD = 2b01;localparam BODY = 2b10;localparam WALL = 2b11;localparam PLAY = 2b10;reg 31:0 cnt;wire 1:0 direct; reg 1:0 direct_r;assign direct=direct_r;reg 1:0 direct_next;reg change_to_left;reg change_to_right;reg change_to_up;reg change_to_down; reg 5:0 cube_x15:0;reg 5:0 cube_y15:0;reg 15:0 is_exist;reg 2:0 color;assign head_x = cube_x0;assign head_y = cube_y0;always ( posedge clk ) /初始化刚开始时我们设定蛇向右运动if( !reset)direct_r=RIGHT ;elsedirect_r=direct_next;always ( posedge clk )beginif(!reset ) begin /设定初始化后刚开始三个蛇块的位置cnt = 0;cube_x0 = 10;cube_y0 = 5;cube_x1 = 9;cube_y1 = 5;cube_x2 = 8;cube_y2 = 5;hit_wall = 0;hit_body = 0; endelse begincnt = cnt + 1;if( cnt = 12500000 ) begincnt = 0;if( game_status = PLAY ) begin /在play过程中判断是否hit_wallif( ( direct = UP & cube_y0 = 1 ) | ( direct = DOWN & cube_y0 = 28 )| ( direct = LEFT & cube_x0 = 1 )| ( direct = RIGHT & cube_x0 = 38 ) )hit_wall = 1;/下边判断是否hit_dodyelse if( ( cube_y0 = cube_y1 & cube_x0 = cube_x1 & is_exist1 = 1 )| ( cube_y0 = cube_y2 & cube_x0 = cube_x2 & is_exist2 = 1 )| ( cube_y0 = cube_y3 & cube_x0 = cube_x3 & is_exist3 = 1 )| ( cube_y0 = cube_y4 & cube_x0 = cube_x4 & is_exist4 = 1 )| ( cube_y0 = cube_y5 & cube_x0 = cube_x5 & is_exist5 = 1 )| ( cube_y0 = cube_y6 & cube_x0 = cube_x6 & is_exist6 = 1 )| ( cube_y0 = cube_y7 & cube_x0 = cube_x7 & is_exist7 = 1 )| ( cube_y0 = cube_y8 & cube_x0 = cube_x8 & is_exist8 = 1 )| ( cube_y0 = cube_y9 & cube_x0 = cube_x9 & is_exist9 = 1 )| ( cube_y0 = cube_y10 & cube_x0 = cube_x10 & is_exist10 = 1 )| ( cube_y0 = cube_y11 & cube_x0 = cube_x11 & is_exist11 = 1 )| ( cube_y0 = cube_y12 & cube_x0 = cube_x12 & is_exist12 = 1 )| ( cube_y0 = cube_y13 & cube_x0 = cube_x13 & is_exist13 = 1 )| ( cube_y0 = cube_y14 & cube_x0 = cube_x14 & is_exist14 = 1 )| ( cube_y0 = cube_y15 & cube_x0 = cube_x15 & is_exist15 = 1 ) ) hit_body=1;else /蛇运动过程中相邻模块之间坐标存在联系,依次代替 begincube_x1 = cube_x0;cube_y1 = cube_y0;cube_x2 = cube_x1;cube_y2 = cube_y1;cube_x3 = cube_x2;cube_y3 = cube_y2;cube_x4 = cube_x3;cube_y4 = cube_y3;cube_x5 = cube_x4;cube_y5 = cube_y4;cube_x6 = cube_x5;cube_y6 = cube_y5;cube_x7 = cube_x6;cube_y7 = cube_y6;cube_x8 = cube_x7;cube_y8 = cube_y7;cube_x9 = cube_x8;cube_y9 = cube_y8;cube_x10 = cube_x9;cube_y10 = cube_y9;cube_x11 = cube_x10;cube_y11 = cube_y10;cube_x12 = cube_x11;cube_y12 = cube_y11;cube_x13 = cube_x12;cube_y13 = cube_y12;cube_x14 = cube_x13;cube_y14 = cube_y13;cube_x15 = cube_x14;cube_y15 = cube_y14;case( direct ) /根据运动方向来决定蛇头的坐标UP:beginif( cube_y0 = 1 )hit_wall = 1;else cube_y0 = cube_y0 1;endDOWN: beginif( cube_y0 = 28 )hit_wall = 1;elsecube_y0 = cube_y0 + 1;endLEFT:beginif( cube_x0 = 1 )hit_wall = 1;else cube_x0 = cube_x0 1;endRIGHT: beginif( cube_x0 = 38 )hit_wall = 1;elsecube_x0 = cube_x0 + 1;endendcaseendendendendendalways ( * ) begindirect_next = direct;case( direct )UP: beginif( change_to_left )direct_next = LEFT;else if( change_to_right )direct_next = RIGHT;else direct_next = UP;endDOWN : beginif( change_to_left )direct_next = LEFT;else if( change_to_right )direct_next = RIGHT;else direct_next = DOWN;endLEFT : beginif( change_to_up )direct_next = UP;else if( change_to_down )direct_next = DOWN;else direct_next = LEFT;endRIGHT : beginif( change_to_up )direct_next = UP;else if( change_to_down )direct_next = DOWN;else direct_next = RIGHT;endendcaseendalways ( posedge clk ) beginif( left_press = 1 ) beginchange_to_left = 1;endelse if( right_press = 1 ) beginchange_to_right = 1;endelse if( up_press = 1 ) beginchange_to_up = 1;endelse if( down_press = 1 ) beginchange_to_down = 1;endelse beginchange_to_left = 0;change_to_right = 0;change_to_up = 0;change_to_down = 0;endendreg addcube_state;always ( posedge clk ) beginif( reset = 0 ) beginis_exist = 16b0000000000000111;cube_num = 3;addcube_state = 0;endelse begincase( addcube_state )0: beginif( add_cube ) begincube_num = cube_num + 1;is_existcube_num = 1;addcube_state = 1;endend1: beginif(!add_cube)addcube_state = 0 & x_pos = 0 & y_pos 480 ) beginif( ( x_pos9:4 = 0 | y_pos9:4 = 0 | x_pos9:4 = 39 | y_pos9:4 = 29 ) )snake = WALL;else if( x_pos9:4 = cube_x0 & y_pos9:4 = cube_y0 & is_exist0 = 1 ) beginsnake = ( die_flash = 1 ) ? HEAD : NONE;endelse if( ( x_pos9:4 = cube_x1 & y_pos9:4 = cube_y1 & is_exist1 = 1 )| ( x_pos9:4 = cube_x2 & y_pos9:4 = cube_y2 & is_exist2 = 1 )| ( x_pos9:4 = cube_x3 & y_pos9:4 = cube_y3 & is_exist3 = 1 )| ( x_pos9:4 = cube_x4 & y_pos9:4 = cube_y4 & is_exist4 = 1 )| ( x_pos9:4 = cube_x5 & y_pos9:4 = cube_y5 & is_exist5 = 1 )| ( x_pos9:4 = cube_x6 & y_pos9:4 = cube_y6 & is_exist6 = 1 )| ( x_pos9:4 = cube_x7 & y_pos9:4 = cube_y7 & is_exist7 = 1 )| ( x_pos9:4 = cube_x8 & y_pos9:4 = cube_y8 & is_exist8 = 1 )| ( x_pos9:4 = cube_x9 & y_pos9:4 = cube_y9 & is_exist9 = 1 )| ( x_pos9:4 = cube_x10 & y_pos9:4 = cube_y10 & is_exist10 = 1 )| ( x_pos9:4 = cube_x11 & y_pos9:4 = cube_y11 & is_exist11 = 1 )| ( x_pos9:4 = cube_x12 & y_pos9:4 = cube_y12 & is_exist12 = 1 )| ( x_pos9:4 = cube_x13 & y_pos9:4 = cube_y13 & is_exist13 = 1 )| ( x_pos9:4 = cube_x14 & y_pos9:4 = cube_y14 & is_exist14 = 1 )| ( x_pos9:4 = cube_x15 & y_pos9:4 = cube_y15 & is_exist15 = 1 )snake = ( die_flash = 1 ) ? BODY : NONE;elsesnake = NONE;endend endmodule2.3Snake_eating_apple此模块需要在液晶显示器有效区域内随机产生一个苹果,而且需要判断蛇是否已吃下苹果。此子模块代码如下:module Snake_eating_apple (input clk,input reset,input 5:0 head_x,input 5:0 head_y,output reg 5:0 apple_x,output reg 4:0 apple_y,output reg add_cube);reg 31:0 clk_cnt;reg 10:0 random_num;always ( posedge clk )random_num = random_num + 927; always ( posedge clk ) beginif( reset = 0 ) beginclk_cnt = 0;apple_x = 24;apple_y = 10;add_cube = 0;endelse beginclk_cnt = clk_cnt + 1;if( clk_cnt = 250000 ) beginclk_cnt = 0;if( apple_x = head_x & apple_y = head_y ) begin add_cube = 1;apple_x 38 ) ? ( random_num10:5 - 25 ) :( random_num10:5 = 0 ) ? 1:random_num10:5;apple_y 28 ) ? ( random_num4:0 - 3 ) :( random_num4:0 = 0 ) ? 1 : random_num4:0; endelse add_cube = 0;endendendendmodule2.4VGA_control此模块直接控制液晶屏的显示。产生五个信号:红、绿、蓝三色信号和行帧同步信号。此子模块代码如下:module VGA_control (input clk,input reset,input 1:0 snake,input 5:0 apple_x,input 4:0 apple_y,output reg 9:0 x_pos,output reg 9:0 y_pos,output reg h_sync,output reg v_sync,output reg 2:0 color_out);reg 19:0 clk_cnt;reg 9:0 line_cnt;reg clk_25M;localparam NONE = 2b00;localparam HEAD = 2b01;localparam BODY = 2b10;localparam WALL = 2b11;localparam HEAD_COLOR = 3b010;localparam BODY_COLOR = 3b011;reg 3:0 lox;reg 3:0 loy;always ( posedge clk ) beginclk_25M = clk_25M;end/ generate display signalalways ( posedge clk_25M ) beginif( reset = 0) begin clk_cnt = 0;line_cnt = 0;h_sync = 1;v_sync = 1;endelse beginx_pos = clk_cnt 144;y_pos = line_cnt 33;/产生水平控制信号if( clk_cnt = 0 ) beginh_sync = 0;clk_cnt = clk_cnt + 1;endelse if( clk_cnt = 96 ) beginh_sync = 1;clk_cnt = clk_cnt + 1;endelse if( clk_cnt = 799 ) beginclk_cnt = 0;line_cnt = line_cnt + 1;endelse clk_cnt = clk_cnt + 1;/ 产生垂直控制信号if( line_cnt = 0 ) beginv_sync = 0;endelse if( line_cnt = 2 ) beginv_sync = 1;endelse if( line_cnt = 521 ) beginline_cnt = 0;v_sync = 0 & x_pos = 0 & y_pos 480 ) beginlox = x_pos3:0;loy = y_pos3:0;if( x_pos9:4 = apple_x & y_pos9:4 = apple_y )case( loy, lox )8b0000_0000: color_out = 3b000; Default:color_out = 3b001; endcaseelse if( snake = NONE )color_out = 3b000;else if( snake = WALL )color_out = 3b101;else if( snake = HEAD | snake = BODY ) begincase( lox, loy )8b0000_0000: color_out = 3b000;Default:color_out = ( snake = HEAD ) ? HEAD_COLOR : BODY_COLOR;endcaseendendelse color_out = 3b000;endend endmodule2.5Key 本模块根据拨码开关的高低电平,来产生left、right、up和down的信号,从而控制蛇的运动方向。此子模块代码如下:module Key (input clk,input reset,input left,input right,input up,input down,output reg left_key_press,output reg right_key_press,output reg up_key_press,output reg down_key_press);reg 31:0 clk_cnt;reg left_key_last;reg right_key_last;reg up_key_last;reg down_key_last;always ( posedge clk ) beginif( !reset ) beginclk_cnt = 0;left_key_press = 0;right_key_press = 0;up_key_press = 0;down_key_press = 0;left_key_last = 0;right_key_last = 0;up_key_last = 0;right_key_last = 0;endelse beginif( clk_cnt = 50000 ) beginclk_cnt = 0;left_key_last = left;right_key_last = right;up_key_last = up;down_key_last = down;if( left_key_last = 0 & left = 1 ) beginleft_key_press = 1;endif( right_key_last = 0 & right = 1 ) beginright_key_press = 1;endif( up_key_last = 0 & up = 1 ) beginup_key_press = 1;endif( down_key_last = 0 & down = 1 ) begindown_key_press = 1;endendelse beginclk_cnt = clk_cnt + 1;left_key_press = 0;right_key_press = 0;up_key_press = 0;down_key_press = 0;endendendendmodule2.6 Seg_display 此模块非常简单,类似之前数字秒表实验的设计。此子模块代码如下:module Seg_display(input clk,input reset,input add_cube,output reg 7:0 seg_out,output reg 3:0 sel);reg 15:0 point;reg 31:0 clk_cnt;always ( posedge clk ) beginif( !reset ) beginseg_out = 0; clk_cnt = 0;sel = 0;endelse beginif( clk_cnt = 200000 ) beginclk_cnt = clk_cnt + 1;if( clk_cnt = 50000 ) beginsel = 4b1110;case( point3:0 )4b0000:seg_out = 8b00000011;4b0001:seg_out = 8b10011111;4b0010:seg_out = 8b00100101;4b0011:seg_out = 8b00001101;4b0100:seg_out = 8b10011001;4b0101:seg_out = 8b01001001;4b0110:seg_out = 8b01000001;4b0111:seg_out = 8b00011111;4b1000:seg_out = 8b00000001;4b1001:seg_out = 8b00001001;default:;endcase endelse if( clk_cnt = 100000 ) beginsel = 4b1101;case( point7:4 )4b0000:seg_out =
展开阅读全文
相关资源
相关搜索

最新文档


当前位置:首页 > 压缩资料 > 基础医学


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!