基于Verilog的贪吃蛇小游戏设计(附代码) 您所在的位置:网站首页 贪吃蛇趣味游戏 基于Verilog的贪吃蛇小游戏设计(附代码)

基于Verilog的贪吃蛇小游戏设计(附代码)

2024-07-16 00:54| 来源: 网络整理| 查看: 265

    本文介绍基于verilog语言开发的贪吃蛇小游戏,FPGA板卡至少需要900个LC(文中程序需求1700个LC,可通过删减部分代码得到)、4个独立按键以及1个VGA接口。本文使用的板卡配有50MHz晶振,所配备的程序生成800*600*60Hz驱动信号,采用其它晶振频率的板卡需要对VGA驱动渲染模块(本文中为render)进行相应修改,使得刷新脉冲符合显示屏输入信号要求。

    注意:本文中使用snack代指snake,这是由于最初的错误累积而成,不得已对其进行忽略。

    贪吃蛇工程由7个模块构成,结构层级如图1所示。其中包含1个顶层模块snack、3个功能模块(random_box、render、snack_control)以及3个底层模块(keycheck、random、box_create)。本文设计的结构层次存在一定的瑕疵,其修正方法会在各个模块中提出,但由于本人水平有限,也有部分问题未能解决,欢迎各位能够与我进行探讨。

   

                                                             图1 贪吃蛇工程结构层次

1. 顶层模块snack

    顶层模块主要规定了工程对外的各类接口,以及各个功能模块之间的关系。在本文中,顶层模块调用了三个功能模块(random_box、render、snack_control),作为游戏功能的分区设计。将整个工程所需要实现的功能肢解为随机小盒子(即苹果或被吃物的创建与更新)、VGA驱动脉冲生成与随机小盒子画面渲染、蛇的控制(移动方向、体长、行为检测)。其RTL视图如图2所示。

                                                    图2 顶层模块RTL视图

    在此处,出现了本文的第一个设计瑕疵:功能划分不清。在设计中,将随机小盒子的画面渲染放到render模块中,却将蛇的渲染放置到snack_control模块中,造成了模块的功能混淆。更加理性地办法是将随机小盒子的渲染放到random_box模块中,render模块只负责VGA驱动信号的生成以及画面总体渲染。这样工程模块的划分也更加清晰,任务也更加明确。

顶层设计的代码如下: module snack( input clk, input rst_n, input key_r, input key_l, input key_u, input key_d, output hsync, output vsync, output vga_r, output vga_g, output vga_b ); //贪吃蛇游戏分为:box生成模块、蛇身控制模块、画面渲染模块 //蛇:红色 //box:绿色 //背景:蓝色 //-------------------------------------------------------------------------------- //画面渲染位置 wire [9:0]x_pos; wire [9:0]y_pos; //box坐标传递 wire[9:0]box_x; wire[9:0]box_y; //-------------------------------------------------------------------------------- //蛇身控制模块,蛇是红色的 wire drive; wire snack_r; snack_control u1_snack_control( .clk(clk), .rst_n(rst_n), .key_r(key_r), .key_l(key_l), .key_u(key_u), .key_d(key_d), .box_x(box_x), .box_y(box_y), .x_pos(x_pos), .y_pos(y_pos), .drive(drive), .snack_r(snack_r) ); //-------------------------------------------------------------------------------- //box生成模块 random_box u1_random_box( .clk(clk), .rst_n(rst_n), .drive(drive),//生成驱动信号 .box_x(box_x),//坐标信号 .box_y(box_y) ); //-------------------------------------------------------------------------------- //画面渲染模块 render u1_render( .clk(clk), .rst_n(rst_n), .box_x(box_x), .box_y(box_y), .snack_r(snack_r), .hsync(hsync), .vsync(vsync), .x_pos(x_pos), .y_pos(y_pos), .vga_r(vga_r), .vga_g(vga_g), .vga_b(vga_b) ); endmodule

 

2. random_box模块

    该模块主要负责随机小盒子的生成与更新。盒子的坐标来自于LFSR伪随机码生成器产生的两个相邻数据,为了获取完整的随机坐标,必须等待2个时钟周期。

该模块的代码如下: module random_box( input clk, input rst_n, input drive, output wire[9:0]box_x, output wire[9:0]box_y ); //--------------------------------------------------------------------------------- //随机数生成模块 wire [8:0]rand_num; random U1_random( .clk(clk), .rst_n(rst_n), // .seed(seed), //.load(load), .rand_num(rand_num) ); //随机盒子创建 wire [9:0]rand_x; wire [9:0]rand_y; // wire rand_drive;//随机小方块激励模块 box_create U1_box_create( .clk(clk), .rst_n(rst_n), .rand_num(rand_num), .rand_drive(drive), .rand_x(rand_x), .rand_y(rand_y) ); assign box_x = rand_x; assign box_y = rand_y; endmodule 2.1 random模块

    该模块采用LFSR机制生成伪随机数,其种子已提前预置。本文中采用了9位宽度的设计,使得生成的伪随机数范围小于VGA屏幕的显示范围。如果有需求可为LFSR增加1位长度,并增添额外的代码用于判定取用的伪随机数是否越界。

其代码如下所示: module random( input clk, input rst_n, // input load, // input[8:0] seed, output reg[8:0] rand_num ); //----------------------------------------------------------------------------------- always@(posedge clk or negedge rst_n) if(!rst_n) rand_num


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有