需求:
1、生成蛇头的初始坐标
2、蛇头坐标根据蛇运动方向做改变
思路:
1、使用VGA-640480分辨率显示,以2020个像素为一格,所以xpos为1-32(640/20=32),ypos为1-24(480/24=20)。
2、定义4个方向:LEFT,RIGHT,UP,DOWN。
方向为LEFT时,xpos每个时钟周期减1,ypos不变
方向为RIGHT时,xpos每个时钟周期加1,ypos不变
方向为UP时,ypos每个时钟周期减1,xpos不变
方向为DOWN时,ypos每个时钟周期加1,xpos不变
3、键盘值输入,定义4个方向按键:KEY_UP,KEY_DOWN,KEY_LEFT,KEY_RIGHT
蛇头方向根据按键方向改变,除了运动方向与按键操作方向正好相反的情况
4、分频出一个时钟,作为蛇头位置改变的时钟。这儿用了0.5s的时钟,也就是说蛇运动速度是固定的,实现基本功能后可以加入变速的功能。
`define SIM
module snake_dri (
input clk ,
input rst_n ,
//====================snake_dri_interface===================
input [3:0] key_val ,
input key_trig ,
output [5:0] x_pos ,
output [5:0] y_pos ,
output [1:0] direction ,
input flag_go
);
//==============Time_Parameter define====================
`ifndef SIM
localparam CNT_DIV_05S = 12500000 ;
`else
localparam CNT_DIV_05S = 5 ;
`endif
//==============directiton Parameter define====================
localparam DIR_LEFT = 2'd0 ;
localparam DIR_RIGHT = 2'd1 ;
localparam DIR_UP = 2'd2 ;
localparam DIR_DOWN = 2'd3 ;
//==============key_val Parameter define====================
localparam KEY_UP = 2'd0 ;
localparam KEY_DOWN = 2'd1 ;
localparam KEY_LEFT = 2'd2 ;
localparam KEY_RIGHT = 2'd3 ;
//=================System Reg define===================
reg [23:0] cnt_div_clk ;
reg div_clk ;
reg [5:0] x_pos_reg ;
reg [5:0] y_pos_reg ;
reg [1:0] directiton_reg ;
reg [3:0] key_val_reg ;
//key_trig_reg
reg key_trig_t0 ;
reg key_trig_t1 ;
reg key_trig_t2 ;
//====================System Wire define=====================
wire key_trig_pedge0 ;
wire key_trig_pedge1 ;
//====================inteface Wire =====================
assign x_pos = x_pos_reg ;
assign y_pos = y_pos_reg ;
assign direction = directiton_reg ;
//=============================================================================
//**************************** Main Code *******************************
//=============================================================================
//cnt_div_clk logic
always @ (posedge clk or negedge rst_n) begin
if(rst_n == 1'b0)
cnt_div_clk <= 24'd0;
else if(cnt_div_clk==CNT_DIV_05S)
cnt_div_clk <= 24'd0;
else
cnt_div_clk <= cnt_div_clk + 1'b1;
end
//div_clk logic
always @ (posedge clk or negedge rst_n) begin
if(rst_n == 1'b0)
div_clk <= 1'b0;
else if(cnt_div_clk==CNT_DIV_05S)
div_clk <= ~div_clk;
end
//x_pos_reg logic
always @ (posedge div_clk or negedge rst_n) begin
if(rst_n == 1'b0)
x_pos_reg <= 6'd4;
else if(flag_go==1'b1)
case (directiton_reg)
DIR_DOWN:begin
x_pos_reg <= x_pos_reg;
end
DIR_UP:begin
x_pos_reg <= x_pos_reg;
end
DIR_LEFT:begin
if(x_pos_reg==6'd1)
x_pos_reg <= 6'd1;
else
x_pos_reg <= x_pos_reg - 1'b1;
end
DIR_RIGHT:begin
if(x_pos_reg==6'd32)
x_pos_reg <= 6'd32;
else
x_pos_reg <= x_pos_reg + 1'b1;
end
default:x_pos_reg <= x_pos_reg;
endcase
else
x_pos_reg <= 6'd4;
end
//y_pos_reg logic
always @ (posedge div_clk or negedge rst_n) begin
if(rst_n == 1'b0)
y_pos_reg <= 6'd4;
else if(flag_go==1'b1)
case (directiton_reg)
DIR_DOWN:begin
if(y_pos_reg==6'd24)
y_pos_reg <= 6'd24;
else
y_pos_reg <= y_pos_reg + 1'b1;
end
DIR_UP:begin
if(y_pos_reg==6'd1)
y_pos_reg <= 6'd1;
else
y_pos_reg <= y_pos_reg - 1'b1;
end
DIR_LEFT:begin
y_pos_reg <= y_pos_reg;
end
DIR_RIGHT:begin
y_pos_reg <= y_pos_reg;
end
default:y_pos_reg <= y_pos_reg;
endcase
else
y_pos_reg <= 6'd4;
end
//key_trig_temp_logic
always @ (posedge clk) begin
key_trig_t0 <= key_trig;
key_trig_t1 <= key_trig_t0;
key_trig_t2 <= key_trig_t1;
end
//key_trig_pedge logic
assign key_trig_pedge0 = key_trig_t0&~key_trig_t1;
assign key_trig_pedge1 = key_trig_t1&~key_trig_t2;
//direction reg logic
always @ (posedge clk or negedge rst_n) begin
if(rst_n == 1'b0)
directiton_reg <= DIR_RIGHT;
else if(key_trig_pedge1==1'b1)
case (key_val_reg)
KEY_RIGHT:begin
case (directiton_reg)
DIR_LEFT:directiton_reg <= DIR_LEFT;
default:directiton_reg <= DIR_RIGHT;
endcase
end
KEY_LEFT:begin
case (directiton_reg)
DIR_RIGHT:directiton_reg <= DIR_RIGHT;
default:directiton_reg <= DIR_LEFT;
endcase
end
KEY_UP:begin
case (directiton_reg)
DIR_DOWN:directiton_reg <= DIR_DOWN;
default:directiton_reg <= DIR_UP;
endcase
end
KEY_DOWN:begin
case (directiton_reg)
DIR_UP:directiton_reg <= DIR_UP;
default:directiton_reg <= DIR_DOWN;
endcase
end
default:directiton_reg <= directiton_reg;
endcase
else
directiton_reg <= directiton_reg;
end
//key_val_reg logic
always @ (posedge clk or negedge rst_n) begin
if(rst_n == 1'b0)
key_val_reg <= KEY_RIGHT;
else if(key_trig_pedge0==1'b1)
key_val_reg <= key_val;
end
endmodule
`define clock_period 20
`timescale 1ns/1ns
module tb_food_gene_dri;
//=================System Signals===================
reg clk;
reg rst_n;
//=================module_signals===================
reg flag_go ;
wire [5:0] food_xpos ;
wire [5:0] food_ypos ;
reg flag_food_get ;
//==============internal signal===================
integer i = 0 ;
food_gene_dri food_gene_dri(
.clk (clk) ,
.rst_n (rst_n) ,
//====================food_gene_dri_interface===================
.flag_go (flag_go) ,
.food_xpos (food_xpos) ,
.food_ypos (food_ypos) ,
.flag_food_get (flag_food_get)
);
//=================System clock logic===============
initial begin
clk = 1;
end
always #(`clock_period/2)clk = ~clk;
//=================System Rst_n logic===============
initial begin
rst_n = 0;
#(`clock_period*20);
rst_n = 1;
end
//=================Test Signal logic================
initial begin
flag_go = 0;
flag_food_get = 0;
#(`clock_period*20);
flag_go = 1;
#(`clock_period*500);
for (i = 0;i <= 20; i = i + 1)begin
flag_food_get = 1;
#(`clock_period)flag_food_get = 0;
#(`clock_period*500);
end
end
endmodule