青岛做英文网站的公司,在哪可以做网站,怎样查后缀vc域名网站,网站关键技术FPGA教程学习
第十四章 HDMI 输出实验 文章目录 FPGA教程学习前言实验原理实验过程程序设计时钟模块#xff08;video_pll#xff09;彩条产生模块#xff08;color_bar)配置数据查找表模块#xff08;lut_adv7511#xff09;I2C Master 寄存器配置模块#xff08;i2c_c…FPGA教程学习
第十四章 HDMI 输出实验 文章目录 FPGA教程学习前言实验原理实验过程程序设计时钟模块video_pll彩条产生模块color_bar)配置数据查找表模块lut_adv7511I2C Master 寄存器配置模块i2c_config TODO总结参考 前言
FPGA通过HDMI编码芯片输出彩条。 实验原理
开发板有一个HDMI编码芯片ADV7511将 24 位 RGB 编码输出 TMDS 差分信号。 本实验使用其将RGB24视频数据显示出来。 硬件原理图如下 结合前面从原理图或者看手册这里只是大致分析一下上可以分析出
编码输入是24位的数据本实验是RGB编码输出时TMDS 差分信号编码芯片的配置接口是I2CHDMI接口上有I2C
实验过程
程序设计 时钟模块video_pll
负责产生一个100Mhz的时钟和一个1080P的148.5Mhz的像素时钟。 生成时钟 IP 的方法是点击 Project Manager目录下的 IP Catalog,再选择 FPGA Features and Design-Clocking-Clocking Wizard 图标。然后进行设置即可。
彩条产生模块color_bar)
是产生 8 种颜色的 VGA 格式的彩条彩条分别为白、黄、青、绿、紫、红、蓝和黑。产生分辨率为 1920x1080 刷新率为 60Hz 的彩条,也就是所谓的 1080P 的高清视频图像。
视频时序图
模块要根据这个视频时序去看用了几个寄存器来计数行场信号。 模块接口参数比较少输入只有时钟和复位其他都是输出。这里输出的时序是给编码芯片的。
module color_bar(input clk, //像素时钟输入1280x72060P的像素时钟为74.25input rst, //复位,高有效output hs, //行同步、高有效output vs, //场同步、高有效output de, //数据有效output[7:0] rgb_r, //像素数据、红色分量output[7:0] rgb_g, //像素数据、绿色分量output[7:0] rgb_b //像素数据、蓝色分量
);//*************************************************************************\
//
// Description:
// 彩条发生模块
//
// Revision History:
// Date By Revision Change Description
//--------------------------------------------------------------------------
//2013/5/7 1.2 remove some warning
//2013/4/18 1.1 vs timing
//2013/4/16 1.0 Original
//*************************************************************************/
module color_bar(input clk, //像素时钟输入1280x72060P的像素时钟为74.25input rst, //复位,高有效output hs, //行同步、高有效output vs, //场同步、高有效output de, //数据有效output[7:0] rgb_r, //像素数据、红色分量output[7:0] rgb_g, //像素数据、绿色分量output[7:0] rgb_b //像素数据、蓝色分量
);
/*********视频时序参数定义******************************************/
//parameter H_ACTIVE 16d1280; //行有效长度像素时钟周期个数
//parameter H_FP 16d110; //行同步前肩长度
//parameter H_SYNC 16d40; //行同步长度
//parameter H_BP 16d220; //行同步后肩长度
//parameter V_ACTIVE 16d720; //场有效长度行的个数
//parameter V_FP 16d5; //场同步前肩长度
//parameter V_SYNC 16d5; //场同步长度
//parameter V_BP 16d20; //场同步后肩长度parameter H_ACTIVE 16d1920;
parameter H_FP 16d88;
parameter H_SYNC 16d44;
parameter H_BP 16d148;
parameter V_ACTIVE 16d1080;
parameter V_FP 16d4;
parameter V_SYNC 16d5;
parameter V_BP 16d36;
parameter H_TOTAL H_ACTIVE H_FP H_SYNC H_BP;//行总长度
parameter V_TOTAL V_ACTIVE V_FP V_SYNC V_BP;//场总长度
/*********彩条RGB color bar颜色参数定义*****************************/
parameter WHITE_R 8hff;
parameter WHITE_G 8hff;
parameter WHITE_B 8hff;
parameter YELLOW_R 8hff;
parameter YELLOW_G 8hff;
parameter YELLOW_B 8h00;
parameter CYAN_R 8h00;
parameter CYAN_G 8hff;
parameter CYAN_B 8hff;
parameter GREEN_R 8h00;
parameter GREEN_G 8hff;
parameter GREEN_B 8h00;
parameter MAGENTA_R 8hff;
parameter MAGENTA_G 8h00;
parameter MAGENTA_B 8hff;
parameter RED_R 8hff;
parameter RED_G 8h00;
parameter RED_B 8h00;
parameter BLUE_R 8h00;
parameter BLUE_G 8h00;
parameter BLUE_B 8hff;
parameter BLACK_R 8h00;
parameter BLACK_G 8h00;
parameter BLACK_B 8h00;
reg hs_reg;//定义一个寄存器,用于行同步
reg vs_reg;//定义一个寄存器,用户场同步
reg hs_reg_d0;//hs_reg一个时钟的延迟//所有以_d0、d1、d2等为后缀的均为某个寄存器的延迟
reg vs_reg_d0;//vs_reg一个时钟的延迟
reg[11:0] h_cnt;//用于行的计数器
reg[11:0] v_cnt;//用于场帧的计数器
reg[11:0] active_x;//有效图像的的坐标x
reg[11:0] active_y;//有效图像的坐标y
reg[7:0] rgb_r_reg;//像素数据r分量
reg[7:0] rgb_g_reg;//像素数据g分量
reg[7:0] rgb_b_reg;//像素数据b分量
reg h_active;//行图像有效
reg v_active;//场图像有效
wire video_active;//一帧内图像的有效区域h_active v_active
reg video_active_d0;
assign hs hs_reg_d0;
assign vs vs_reg_d0;
assign video_active h_active v_active;
assign de video_active_d0;
assign rgb_r rgb_r_reg;
assign rgb_g rgb_g_reg;
assign rgb_b rgb_b_reg;always(posedge clk or posedge rst)
beginif(rst)beginhs_reg_d0 1b0;vs_reg_d0 1b0;video_active_d0 1b0;endelsebegin // 这个地方左侧的寄存器是hsvsde的输出hs_reg和vs_reg有关系hs_reg_d0 hs_reg;vs_reg_d0 vs_reg;video_active_d0 video_active;end
end// 行计数每次记一行的时钟个数也就是一行的第几个时钟
always(posedge clk or posedge rst)
beginif(rst)h_cnt 12d0;else if(h_cnt H_TOTAL - 1)//行计数器到最大值清零h_cnt 12d0;elseh_cnt h_cnt 12d1;
end// x坐标像素坐标当前肩同步后肩结束时输出有效像素x用来计数有效的图像数据或者说是x的坐标
always(posedge clk or posedge rst)
beginif(rst)active_x 12d0;else if(h_cnt H_FP H_SYNC H_BP - 1)//计算图像的x坐标active_x h_cnt - (H_FP[11:0] H_SYNC[11:0] H_BP[11:0] - 12d1);elseactive_x active_x;
end// 场计数或者说是行数计数用来计数多少行每当一行的前肩开始时就进行计数到达最大进行清零
always(posedge clk or posedge rst)
beginif(rst)v_cnt 12d0;else if(h_cnt H_FP - 1)//在行数计算器为H_FP - 1的时候场计数器1或清零if(v_cnt V_TOTAL - 1)//场计数器到最大值了清零v_cnt 12d0;elsev_cnt v_cnt 12d1;//没到最大值1elsev_cnt v_cnt;
end// 行同步信号的输出从前肩开始有效到达设定的值时结束
always(posedge clk or posedge rst)
beginif(rst)hs_reg 1b0;else if(h_cnt H_FP - 1)//行同步开始了...hs_reg 1b1;else if(h_cnt H_FP H_SYNC - 1)//行同步这时候要结束了hs_reg 1b0;elsehs_reg hs_reg;
end// 行数据有效信号在一行前肩同步后肩内为低图像数据有效时为高
always(posedge clk or posedge rst)
beginif(rst)h_active 1b0;else if(h_cnt H_FP H_SYNC H_BP - 1)h_active 1b1;else if(h_cnt H_TOTAL - 1)h_active 1b0;elseh_active h_active;
end// 场同步信号和行同步信号类似从前肩开始有效到达设定的值时结束
always(posedge clk or posedge rst)
beginif(rst)vs_reg 1d0;else if((v_cnt V_FP - 1) (h_cnt H_FP - 1))vs_reg 1b1;else if((v_cnt V_FP V_SYNC - 1) (h_cnt H_FP - 1))vs_reg 1b0; elsevs_reg vs_reg;
end// 场数据有效信号在前肩同步后肩内为低图像数据有效时为高h_active和v_active共同用来指示数据是否有效作为数据使能信号DE
always(posedge clk or posedge rst)
beginif(rst)v_active 1d0;else if((v_cnt V_FP V_SYNC V_BP - 1) (h_cnt H_FP - 1))v_active 1b1;else if((v_cnt V_TOTAL - 1) (h_cnt H_FP - 1))v_active 1b0; elsev_active v_active;
end// 根据行坐标输出特定的像素值
always(posedge clk or posedge rst)
beginif(rst)beginrgb_r_reg 8h00;rgb_g_reg 8h00;rgb_b_reg 8h00;endelse if(video_active)if(active_x 12d0)beginrgb_r_reg WHITE_R;rgb_g_reg WHITE_G;rgb_b_reg WHITE_B;endelse if(active_x (H_ACTIVE/8) * 1)beginrgb_r_reg YELLOW_R;rgb_g_reg YELLOW_G;rgb_b_reg YELLOW_B;end else if(active_x (H_ACTIVE/8) * 2)beginrgb_r_reg CYAN_R;rgb_g_reg CYAN_G;rgb_b_reg CYAN_B;endelse if(active_x (H_ACTIVE/8) * 3)beginrgb_r_reg GREEN_R;rgb_g_reg GREEN_G;rgb_b_reg GREEN_B;endelse if(active_x (H_ACTIVE/8) * 4)beginrgb_r_reg MAGENTA_R;rgb_g_reg MAGENTA_G;rgb_b_reg MAGENTA_B;endelse if(active_x (H_ACTIVE/8) * 5)beginrgb_r_reg RED_R;rgb_g_reg RED_G;rgb_b_reg RED_B;endelse if(active_x (H_ACTIVE/8) * 6)beginrgb_r_reg BLUE_R;rgb_g_reg BLUE_G;rgb_b_reg BLUE_B;end else if(active_x (H_ACTIVE/8) * 7)beginrgb_r_reg BLACK_R;rgb_g_reg BLACK_G;rgb_b_reg BLACK_B;endelsebeginrgb_r_reg rgb_r_reg;rgb_g_reg rgb_g_reg;rgb_b_reg rgb_b_reg;end elsebeginrgb_r_reg 8h00;rgb_g_reg 8h00;rgb_b_reg 8h00;end
endendmodule 配置数据查找表模块lut_adv7511
这个模块就是根据输入的下标输出设定好的值。 module lut_adv7511(input[9:0] lut_index, // Look-up table index addressoutput reg[31:0] lut_data // I2C device address register address register data
);always(*)
begincase(lut_index)//To be compatible with the 16bit register address, add 8h008d0 : lut_data {8h72,24h004100}; //16h4110; 8d1 : lut_data {8h72,24h00d6c0}; 8d2 : lut_data {8h72,24h005512}; 8d3 : lut_data {8h72,24h001500}; //input id 0x0 0000 24 bit RGB 4:4:4 or YCbCr 4:4:4 (separate syncs)8d4 : lut_data {8h72,24h00d03c};8d5 : lut_data {8h72,24h00af04}; 8d6 : lut_data {8h72,24h004c04}; 8d7 : lut_data {8h72,24h004000}; 8d8 : lut_data {8h72,24h009803};8d9 : lut_data {8h72,24h009ae0}; 8d10 : lut_data {8h72,24h009c30}; 8d11 : lut_data {8h72,24h009d61}; 8d12 : lut_data {8h72,24h00a2a4}; 8d13 : lut_data {8h72,24h00a3a4}; 8d14 : lut_data {8h72,24h00e0d0}; 8d15 : lut_data {8h72,24h00f900};default:lut_data {8hff,16hffff,8hff};endcase
endendmodule I2C Master 寄存器配置模块i2c_config
这个模块使用了查找表模块输出对应的下标将查找的数据作为输入。然后这里还有一大堆使用I2C读写的代码以后再看。
module i2c_config(input rst,input clk,input[15:0] clk_div_cnt,input i2c_addr_2byte,output reg[9:0] lut_index,input[7:0] lut_dev_addr,input[15:0] lut_reg_addr,input[7:0] lut_reg_data,output reg error,output done,inout i2c_scl,inout i2c_sda
);TODO
分析I2C读写代码了解视频时序查看编码芯片数据手册
总结
本实验通过使用I2C配置编码芯片构建模拟图像输出视频时序模块完成了使用HDMI输出模拟图像彩条的功能。通过本次实验了解了HDMI输出、视频时序、I2C读写的一些知识点。HDMI输出的是差分信号芯片输出是可能需要编码芯片进行编码不能够直接输出。视频时序中有前肩、后肩、同步等术语行场信号是一个重要的知识点要熟悉行场信号的构造。I2C是一个常用的配置接口实验中的编码芯片由I2C进行配置HDMI接口上也有一个。
参考
8k,4k,2k视频时序参数分享HDMI中的视频时序分析基于FPGA的视频时序生成