设计框图
框图和HDMI彩条显示的框图完全一样,没有改变,只是将之前的HDMI控制模块生产彩条像素信息的内容 改成了显示方块像素的设计:
所以我们只需要修改HDMI控制模块 hdmi_ctrl.v。
引入坐标
这次修改,我们引入了像素坐标和方块坐标,方便定位方块位置。
设计代码
代码里面有非常详实的中文注解:
module hdmi_ctrl ( input wire clk, input wire rst_n, output reg [23:0] hdmi_rgb, output reg hdmi_hs, output reg hdmi_vs, output wire video_de //数据使能 ); //1280*720分辨率时序参数 localparam HS_A = 40; // synchronous pulse, horizontal localparam HS_B = 220; // back porch pulse localparam HS_C = 1280; // display interval localparam HS_D = 110; // Front porch localparam HS_E = 1650; // horizontal cycles localparam VS_A = 5; // synchronous pulse, vertical localparam VS_B = 20; localparam VS_C = 720; localparam VS_D = 5; localparam VS_E = 750; localparam HS_WIDTH = 11; localparam VS_WIDTH = 10; //方块参数定义 localparam SIDE_W = 11'd40; //屏幕边框宽度 localparam BLOCK_W = 11'd40; //方块宽度 localparam BLUE = 24'b00000000_00000000_11111111; //屏幕边框颜色 蓝色 localparam WHITE = 24'b11111111_11111111_11111111; //背景颜色 白色 localparam BLACK = 24'b00000000_00000000_00000000; //方块颜色 黑色 reg [HS_WIDTH - 1:0] cnt_hs; // counter for vertical synchronous signal一行的像素个数计数器 reg [VS_WIDTH - 1:0] cnt_vs; // counter for horizontal synchrous signal行个数计数器 reg [21:0] div_cnt; //时钟分频计数器,用于计数方块移动间隔 reg h_direct; //方块水平移动方向,1:右移,0:左移 reg v_direct; //方块竖直移动方向,1:向下,0:向上 reg [10:0] block_x = SIDE_W ; //方块左上角横坐标 reg [10:0] block_y = SIDE_W ; //方块左上角纵坐标 wire [10:0] pixel_xpos_w ; //HDMI 横坐标 wire [10:0] pixel_ypos_w ; //HDMI 纵坐标 wire en_hs; // dsiplay horizontal enable wire en_vs; // display vertical enable wire move_en; //方块移动使能信号,频率为 100hz //一行像素个数计数 always @ (posedge clk, negedge rst_n) if (!rst_n) cnt_hs <= 0; else if (cnt_hs < HS_E - 1) cnt_hs <= cnt_hs + 1'b1; else cnt_hs <= 0; //一帧中的行的个数计数 always @ (posedge clk, negedge rst_n) if (!rst_n) cnt_vs <= 0; else if (cnt_hs == HS_E - 1) if (cnt_vs < VS_E - 1) cnt_vs <= cnt_vs + 1'b1; else cnt_vs <= 0; else cnt_vs <= cnt_vs; //产生行同步信号输出 always @ (posedge clk, negedge rst_n) if (!rst_n) hdmi_hs <= 1'b1; else if (cnt_hs < HS_A - 1) //同步之前hdmi_hs信号都是低, 同步之后(a)hdmi_hs信号是高 hdmi_hs <= 1'b0; else hdmi_hs <= 1'b1; //产生场同步信号输出 always @ (posedge clk, negedge rst_n) if (!rst_n) hdmi_vs <= 1'b1; else if (cnt_vs < VS_A - 1) //同步之前hdmi_vs 信号都是低, 同步之后(a)hdmi_vs 信号是高 hdmi_vs <= 1'b0; else hdmi_vs <= 1'b1; assign en_hs = (cnt_hs > HS_A + HS_B - 1)&& (cnt_hs < HS_E - HS_D);//en_hs 将有效数据c段标出来了,在有效数据c段en_hs 才为高,否则为低 assign en_vs = (cnt_vs > VS_A + VS_B - 1) && (cnt_vs < VS_E - VS_D);//en_vs 将有效数据q段标出来了,在有效数据q段en_vs 才为高,否则为低 assign video_de = en_hs && en_vs;//将HDMI显示的有效像素点位置全部标注出来了 //产生像素点坐标 assign pixel_xpos_w = video_de ? (cnt_hs - (HS_A + HS_B - 1'b1)) : 10'd0; assign pixel_ypos_w = video_de ? (cnt_vs - (VS_A + VS_B - 1'b1)) : 10'd0; //方块移动使能,每10ms移动一次 assign move_en = (div_cnt == 22'd742500) ? 1'b1 : 1'b0; //通过对 vga 驱动时钟计数,实现时钟分频(实现100M频率,也就是实现10ms计数) always @(posedge clk ) begin if (!rst_n) div_cnt <= 22'd0; else begin if(div_cnt < 22'd742500) div_cnt <= div_cnt + 1'b1; else div_cnt <= 22'd0; //计数达 10ms 后清零 end end //当方块移动到边界时,改变移动方向 always @(posedge clk ) begin if (!rst_n) begin h_direct <= 1'b1; //方块初始水平向右移动 v_direct <= 1'b1; //方块初始竖直向下移动 end else begin if(block_x == SIDE_W - 1'b1) //到达左边界时,水平向右 h_direct <= 1'b1; else //到达右边界时,水平向左 if(block_x == HS_C - SIDE_W - BLOCK_W) h_direct <= 1'b0; else h_direct <= h_direct; if(block_y == SIDE_W - 1'b1) //到达上边界时,竖直向下 v_direct <= 1'b1; else //到达下边界时,竖直向上 if(block_y == VS_C - SIDE_W - BLOCK_W) v_direct <= 1'b0; else v_direct <= v_direct; end end //根据方块移动方向,改变其纵横坐标 always @(posedge clk ) begin if (!rst_n) begin block_x <= SIDE_W; //方块初始位置横坐标 block_y <= SIDE_W; //方块初始位置纵坐标 end else if(move_en) begin if(h_direct) block_x <= block_x + 1'b1; //方块向右移动 else block_x <= block_x - 1'b1; //方块向左移动 if(v_direct) block_y <= block_y + 1'b1; //方块向下移动 else block_y <= block_y - 1'b1; //方块向上移动 end else begin block_x <= block_x; block_y <= block_y; end end //给不同的区域绘制不同的颜色 always @(posedge clk ) begin if (!rst_n) hdmi_rgb <= BLACK; else begin if( (pixel_xpos_w < SIDE_W) || (pixel_xpos_w >= HS_C - SIDE_W) || (pixel_ypos_w < SIDE_W) || (pixel_ypos_w >= VS_C - SIDE_W)) hdmi_rgb <= BLUE; //绘制屏幕边框为蓝色 else if( (pixel_xpos_w >= block_x) && (pixel_xpos_w < block_x + BLOCK_W) && (pixel_ypos_w >= block_y) && (pixel_ypos_w < block_y + BLOCK_W)) hdmi_rgb <= BLACK; //绘制方块为黑色 else hdmi_rgb <= WHITE; //绘制背景为白色 end end endmodule
实验现象
相关阅读:
友晶科技FPGA开发板DE10-Nano的HDMI彩条实验(一)——HDMI简介
友晶科技FPGA开发板DE10-Nano的HDMI彩条实验(二)——TMDS算法
友晶科技FPGA开发板DE10-Nano的HDMI彩条实验(三)——DE10-Nano 的HDMI电路简介
友晶科技FPGA开发板DE10-Nano的HDMI彩条实验(四)——实验源码及现象演示
ADV7513芯片控制解读(中文版)——基于DE10-NANO开发板——C5G 开发板
DE10-NANO 的HDMI显示彩条实验遇到显示器显示“超频”
无