一、方块移动原理
二、实验任务
使用FPGA开发板上的HDMI接口在显示器上显示一个不停移动的方块,要求方块移动到边界处时能够改变移动方向。显示分辨率为800*480,刷新速率为90hz。(480p分辨率为800*480,像素时钟频率Vga_clk = 800x480x90 = 33264000 ≈33.3Mhz(误差忽略不计))
三、程序设计
1、video_display框图:
Haskell
`timescale 1ns / 1ps
module video_display(
input pixel_clk ,//驱动时钟
input sys_rst_n ,//复位信号
input [10:0] pixel_xpos ,//像素点横坐标
input [10:0] pixel_ypos ,//像素点纵坐标
output reg [23:0] pixel_data //像素点数据
);
parameter H_DISP = 11'd800 ; //分辨率 行
parameter V_DISP = 11'd480 ; //分辨率 列
parameter DIV_CNT = 22'd750000 ; //分辨率计数器
localparam SIDE_W = 11'd40 ; //屏幕边框宽度
localparam BLOCK_W = 11'd20 ; //方块宽度
localparam BLUE = 24'h0000ff ; //屏幕边框颜色 蓝色
localparam WHITE = 24'hffffff ; //背景颜色 白色
localparam BLACK = 24'h000000 ; //方块颜色 黑色
reg [10:0] block_x = SIDE_W ; //方块左上角横坐标
reg [10:0] block_y = SIDE_W ; //方块左上角纵坐标
reg [21:0] div_cnt ; //时钟分频计数器
reg h_direct ; //方块水平位移方向 1:右移 0:左移
reg v_direct ; //方块竖直位移方向 1:向下 0:向上
wire move_en ; //方块移动使能信号 频率100hz
assign move_en = (div_cnt == DIV_CNT - 1'd1) ? 1'd1 : 1'd0;
//时钟计数器,实现时钟分频
always @(posedge pixel_clk or negedge sys_rst_n ) begin
if (!sys_rst_n) begin
div_cnt <= 22'd0;
end
else begin
if (div_cnt < DIV_CNT - 1'd1) begin
div_cnt <= div_cnt + 1'd1;
end
else begin
div_cnt <= 22'd0; //技术到10ms清零
end
end
end
//当方块移动到边界时,改变移动方向
always @(posedge pixel_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
h_direct <= 1'b1; //方块初始水平向右移动
v_direct <= 1'b1; //方块初始竖直向下移动
end
else begin
if (block_x == SIDE_W + 1'b1) begin //到达左边界,水平向右
h_direct <= 1'b1;
end
else begin //到达有边界,水平向左
if(block_x == H_DISP - SIDE_W - BLOCK_W + 1'd1)begin
h_direct <= 1'b0;
end
else begin
h_direct <= h_direct;
end
end
if (block_y == SIDE_W + 1'b1) begin //到达上边界,竖直向下
v_direct <= 1'b1;
end
else begin //到达下边界,竖直向上
if(block_y == V_DISP - SIDE_W - BLOCK_W + 1'b1)begin
v_direct <= 1'b0;
end
else begin
v_direct <= v_direct;
end
end
end
end
//根据方块移动方向,改变横纵坐标
always @(posedge pixel_clk or negedge sys_rst_n ) begin
if (!sys_rst_n) begin
block_x <= SIDE_W + 1'b1; //方块初始位置横坐标
block_y <= SIDE_W + 1'b1; //方块初始位置纵坐标
end
else if(move_en == 1'b1)begin
if (h_direct == 1'b1) begin
block_x <= block_x + 1'b1; //方块向右移动
end
else begin
block_x <= block_x -1'b1; //方块向左移动
end
if (v_direct == 1'b1) begin
block_y <= block_y + 1'b1; //方块向下移动
end
else begin
block_y <= block_y -1'b1; //方块向上移动
end
end
else begin
block_x <= block_x;
block_y <= block_y;
end
end
//对区域给出颜色数据
always @(posedge pixel_clk or negedge sys_rst_n ) begin
if (!sys_rst_n) begin
pixel_data <= BLACK;
end
else begin
if ((pixel_xpos < SIDE_W) || (pixel_xpos >= H_DISP - SIDE_W) ||
(pixel_ypos <= SIDE_W) || (pixel_ypos > V_DISP - SIDE_W)) begin
pixel_data <= BLUE;
end
else begin
if ((pixel_xpos >= block_x -1'b1) && (pixel_xpos < block_x + BLOCK_W - 1'b1) &&
(pixel_ypos >= block_y) && (pixel_ypos < block_y + BLOCK_W - 1'b1)) begin
pixel_data <= BLACK;
end
else begin
pixel_data <= WHITE;
end
end
end
end
endmodule
其他部分完全延用上一章代码
HDMI彩条显示------FPGA学习笔记12-CSDN博客
2、整体代码框架
3、bug更正
上一章中该部分表述错误
实际应为800*480*90 = 34560000约等于33.3Mhz