当前位置: 首页> 教育> 就业 > HDMI彩条显示——FPGA学习笔记12

HDMI彩条显示——FPGA学习笔记12

时间:2025/7/12 6:07:53来源:https://blog.csdn.net/m0_69082048/article/details/142031271 浏览次数:0次

                                                                                                                               素材来自原子哥

一、HDMI简介

        英文全称是High-Definition Multimedia Interface,即高清多媒体接口。 

 

HDMI引脚解析(A型)

HDMI工作连接图

 HDMI工作原理

DVI编码输出示意图

二、TMDS编码(最小化差分传输)

TMDS编码框图

TMDS参数表 

编码过程

三、并转串、单端转差分原语介绍

        原语:英文名称Primitive,是Xilinx针对其器件特征开发的一系列常用模块名称,涵盖了FPGA开发过程中的常用领域,方便用户直接调用FPGA的底层组件。

        原语可以看作是库函数,可以直接例化调用,使用方便,功能全面,可以有效提高开发效率。

IO端口组件原语;

IO组件

IOB

OSERDESE2(双沿)

        并行转串行原语,可以调用Xilinx 7系列FPGAIO逻辑资源,其主要功能是将并行数据转换成串行数据。

OSERDESE2级联示意图

OSERDESE2工作时序图(8:1)

OSERDESE2三态时序图(4:1)

OSERDESE2原语调用(并转串)

OSERDESE2 #(.DATA_RATE_OQ(“DDR”),          // DDR, SDR.DATA_RATE_TQ(“DDR”),           // DDR, BUF, SDR.DATA_WIDTH(4),                       // Parallel data width (2-8,10,14).INIT_OQ(1‘b0),                          // Initial value of OQ output (1'b0,1'b1).INIT_TQ(1‘b0),                           // Initial value of TQ output (1'b0,1'b1).SERDES_MODE(“MASTER”),    // MASTER, SLAVE.SRVAL_OQ(1‘b0),                      // OQ output value when SR is used (1'b0,1'b1).SRVAL_TQ(1‘b0),                       // TQ output value when SR is used (1'b0,1'b1).TBYTE_CTL(“FALSE”),                // Enable tristate byte operation (FALSE, TRUE).TBYTE_SRC(“FALSE”),                // Tristate byte source (FALSE, TRUE).TRISTATE_WIDTH(4)                 // 3-state converter width (1,4))
OSERDESE2_inst (.OFB(OFB),                         // 1-bit output: Feedback path for data.OQ(OQ),                            // 1-bit output: Data path output// SHIFTOUT1 / SHIFTOUT2: 1-bit (each) output: Data output expansion (1-bit each).SHIFTOUT1(SHIFTOUT1),.SHIFTOUT2(SHIFTOUT2),.TBYTEOUT(TBYTEOUT),   // 1-bit output: Byte group tristate.TFB(TFB),                           // 1-bit output: 3-state control.TQ(TQ),                              // 1-bit output: 3-state control.CLK(CLK),                           // 1-bit input: High speed clock.CLKDIV(CLKDIV),              // 1-bit input: Divided clock// D1 - D8: 1-bit (each) input: Parallel data inputs (1-bit each).D1(D1),.D2(D2),.D3(D3),.D4(D4),.D5(D5),.D6(D6),.D7(D7),.D8(D8),.OCE(OCE),                    // 1-bit input: Output data clock enable.RST(RST),                      // 1-bit input: Reset// SHIFTIN1 / SHIFTIN2: 1-bit (each) input: Data input expansion (1-bit each).SHIFTIN1(SHIFTIN1),.SHIFTIN2(SHIFTIN2),// T1 - T4: 1-bit (each) input: Parallel 3-state inputs.T1(T1),.T2(T2),.T3(T3),.T4(T4),.TBYTEIN(TBYTEIN),     // 1-bit input: Byte group tristate.TCE(TCE)                      // 1-bit input: 3-state clock enable);

OSERDESE2原语属性配置表

OBUFDS原语(差分)

OBUFDS OBUFDS_inst (.O(O),      // 1-bit output: Diff_p output (connect directly to top-level port).OB(OB), // 1-bit output: Diff_n output (connect directly to top-level port).I(I)          // 1-bit input: Buffer input);

四、硬件设计

五、试验任务

        本章的实验任务是驱动FPGA开发板上的HDMI接口,在显示器上显示480p彩条图案(480p分辨率为800*480,像素时钟频率Vga_clk = 1056x525x60 = 33264000 ≈33.3hz(误差忽略不计))。

六、程序设计

1、整体框架

 

2、dvi_encoder:编码模块

//
//
//  Xilinx, Inc. 2008                 www.xilinx.com
//
//
//
//  File name :       dvi_encoder.v
//
//  Description :     TMDS encoder  
//
//  Date - revision : Jan. 2008 - v 1.0
//
//  Author :          Bob Feng
//
//  Copyright 2006 Xilinx, Inc.
//  All rights reserved
//
//  
`timescale 1 ps / 1psmodule dvi_encoder (input            clkin,    // pixel clock inputinput            rstin,    // async. reset input (active high)input      [7:0] din,      // data inputs: expect registeredinput            c0,       // c0 inputinput            c1,       // c1 inputinput            de,       // de inputoutput reg [9:0] dout      // data outputs
);// Counting number of 1s and 0s for each incoming pixel// component. Pipe line the result.// Register Data Input so it matches the pipe lined adder// outputreg [3:0] n1d; //number of 1s in dinreg [7:0] din_q;//计算像素数据中“1”的个数always @ (posedge clkin) beginn1d <=#1 din[0] + din[1] + din[2] + din[3] + din[4] + din[5] + din[6] + din[7];din_q <=#1 din;end///// Stage 1: 8 bit -> 9 bit// Refer to DVI 1.0 Specification, page 29, Figure 3-5///wire decision1;assign decision1 = (n1d > 4'h4) | ((n1d == 4'h4) & (din_q[0] == 1'b0));wire [8:0] q_m;assign q_m[0] = din_q[0];assign q_m[1] = (decision1) ? (q_m[0] ^~ din_q[1]) : (q_m[0] ^ din_q[1]);assign q_m[2] = (decision1) ? (q_m[1] ^~ din_q[2]) : (q_m[1] ^ din_q[2]);assign q_m[3] = (decision1) ? (q_m[2] ^~ din_q[3]) : (q_m[2] ^ din_q[3]);assign q_m[4] = (decision1) ? (q_m[3] ^~ din_q[4]) : (q_m[3] ^ din_q[4]);assign q_m[5] = (decision1) ? (q_m[4] ^~ din_q[5]) : (q_m[4] ^ din_q[5]);assign q_m[6] = (decision1) ? (q_m[5] ^~ din_q[6]) : (q_m[5] ^ din_q[6]);assign q_m[7] = (decision1) ? (q_m[6] ^~ din_q[7]) : (q_m[6] ^ din_q[7]);assign q_m[8] = (decision1) ? 1'b0 : 1'b1;/// Stage 2: 9 bit -> 10 bit// Refer to DVI 1.0 Specification, page 29, Figure 3-5/reg [3:0] n1q_m, n0q_m; // number of 1s and 0s for q_malways @ (posedge clkin) beginn1q_m  <=#1 q_m[0] + q_m[1] + q_m[2] + q_m[3] + q_m[4] + q_m[5] + q_m[6] + q_m[7];n0q_m  <=#1 4'h8 - (q_m[0] + q_m[1] + q_m[2] + q_m[3] + q_m[4] + q_m[5] + q_m[6] + q_m[7]);endparameter CTRLTOKEN0 = 10'b1101010100;parameter CTRLTOKEN1 = 10'b0010101011;parameter CTRLTOKEN2 = 10'b0101010100;parameter CTRLTOKEN3 = 10'b1010101011;reg [4:0] cnt; //disparity counter, MSB is the sign bitwire decision2, decision3;assign decision2 = (cnt == 5'h0) | (n1q_m == n0q_m);/// [(cnt > 0) and (N1q_m > N0q_m)] or [(cnt < 0) and (N0q_m > N1q_m)]/assign decision3 = (~cnt[4] & (n1q_m > n0q_m)) | (cnt[4] & (n0q_m > n1q_m));// pipe line alignmentreg       de_q, de_reg;reg       c0_q, c1_q;reg       c0_reg, c1_reg;reg [8:0] q_m_reg;always @ (posedge clkin) beginde_q    <=#1 de;de_reg  <=#1 de_q;c0_q    <=#1 c0;c0_reg  <=#1 c0_q;c1_q    <=#1 c1;c1_reg  <=#1 c1_q;q_m_reg <=#1 q_m;end///// 10-bit out// disparity counter///always @ (posedge clkin or posedge rstin) beginif(rstin) begindout <= 10'h0;cnt <= 5'h0;end else beginif (de_reg) beginif(decision2) begindout[9]   <=#1 ~q_m_reg[8]; dout[8]   <=#1 q_m_reg[8]; dout[7:0] <=#1 (q_m_reg[8]) ? q_m_reg[7:0] : ~q_m_reg[7:0];cnt <=#1 (~q_m_reg[8]) ? (cnt + n0q_m - n1q_m) : (cnt + n1q_m - n0q_m);end else beginif(decision3) begindout[9]   <=#1 1'b1;dout[8]   <=#1 q_m_reg[8];dout[7:0] <=#1 ~q_m_reg[7:0];cnt <=#1 cnt + {q_m_reg[8], 1'b0} + (n0q_m - n1q_m);end else begindout[9]   <=#1 1'b0;dout[8]   <=#1 q_m_reg[8];dout[7:0] <=#1 q_m_reg[7:0];cnt <=#1 cnt - {~q_m_reg[8], 1'b0} + (n1q_m - n0q_m);endendend else begincase ({c1_reg, c0_reg})2'b00:   dout <=#1 CTRLTOKEN0;2'b01:   dout <=#1 CTRLTOKEN1;2'b10:   dout <=#1 CTRLTOKEN2;default: dout <=#1 CTRLTOKEN3;endcasecnt <=#1 5'h0;endendendendmodule 

3、video_driver:(参考LCD模块框图)

`timescale 1ns / 1psmodule video_driver(
input               pixel_clk       ,
input               sys_rst_n       ,//RGB接口
output              video_hs        ,   //行同步信号
output              video_vs        ,   //场同步信号
output              video_de        ,   //数据使能
output      [23:0]  video_rgb       ,   //RGB888颜色数据
output  reg         data_req        ,   //数据请求input       [23:0]  pixel_data      ,   //像素点数据      
output  reg [10:0]  pixel_xpos      ,   //像素点横坐标
output  reg [10:0]  pixel_ypos          //像素点纵坐标
);parameter   H_SYNC  = 11'd80  ;         //行同步
parameter   H_BACK  = 11'd160 ;         //行显示后沿
parameter   H_DISP  = 11'd800 ;         //行有效数据
parameter   H_FRONT = 11'd16  ;         //行显示前沿
parameter   H_TOTAL = 11'd1056;         //行扫描周期parameter   V_SYNC  = 11'd3   ;         //场同步
parameter   V_BACK  = 11'd16  ;         //场显示后沿
parameter   V_DISP  = 11'd480 ;         //场有效数据
parameter   V_FRONT = 11'd1   ;         //场显示前沿
parameter   V_TOTAL = 11'd500 ;         //场扫描周期reg     [11:0]  cnt_h;
reg     [11:0]  cnt_v;
reg             video_en;assign  video_de = video_en;
assign  video_hs = (cnt_h < H_SYNC) ? 1'b0 : 1'b1;
assign  video_vs = (cnt_v < V_SYNC) ? 1'b0 : 1'b1;
//RGB888数据输出
assign video_rgb = video_en ? pixel_data : 24'd0;//行计数
always @(posedge pixel_clk or negedge sys_rst_n) beginif (!sys_rst_n) begincnt_h <= 12'd0;end else beginif (cnt_h < H_TOTAL - 1'b1) begincnt_h <= cnt_h + 1'b1;end else begincnt_h <= 12'd0;   end   end
end//行计数
always @(posedge pixel_clk or negedge sys_rst_n) beginif (!sys_rst_n) begincnt_v <= 12'd0;end else beginif (cnt_h == H_TOTAL - 1'b1) beginif (cnt_v < V_TOTAL - 1'b1) begincnt_v <= cnt_v + 1'b1;end else begincnt_v <= 12'd0;endend   end
end//数据请求信号
always @(posedge pixel_clk or negedge sys_rst_n ) beginif (!sys_rst_n) begindata_req <= 1'b0;end else if(((cnt_h >= H_SYNC + H_BACK - 2'd2) && (cnt_h < H_SYNC + H_BACK + H_DISP - 2'd2))&&((cnt_v >= V_SYNC + V_BACK ) && (cnt_v < V_SYNC + V_BACK + V_DISP)))begindata_req <= 1'b1;endelse begindata_req <= 1'b0;end
end//使能RGB数据输入
always @(posedge pixel_clk or negedge sys_rst_n) beginif (!sys_rst_n) beginvideo_en <= 1'b0;end else beginvideo_en <= data_req;    end
end//像素点x坐标
always @(posedge pixel_clk or negedge sys_rst_n ) beginif (!sys_rst_n) beginpixel_xpos <= 11'd0;end else if(data_req == 1'b1)beginpixel_xpos <= cnt_h + 2'd2 - H_BACK - H_SYNC;endelse beginpixel_xpos <= 11'd0;end
end//像素点y坐标
always @(posedge pixel_clk or negedge sys_rst_n ) beginif (!sys_rst_n) beginpixel_ypos <= 11'd0;end else if((cnt_v >= (V_SYNC + V_BACK)) && (cnt_v < (V_SYNC + V_BACK + V_DISP)))beginpixel_ypos <= cnt_v + 1'b1 - V_SYNC - V_BACK;endelse beginpixel_ypos <= 11'd0;end
endendmodule

4、video_display:彩条数据模块(参考LCD框图)

`timescale 1ns / 1psmodule 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        ;localparam      WHITE = 24'b11111111_11111111_11111111;
localparam      BLACK = 24'b00000000_00000000_00000000;
localparam      RED   = 24'b11111111_00001100_00000000;
localparam      GREEN = 24'b00000000_11111111_00000000;
localparam      BLUE  = 24'b00000000_00000000_11111111;//给不同区域指定颜色
always @(posedge pixel_clk or negedge sys_rst_n ) beginif (!sys_rst_n) beginpixel_data <= 24'd0;end else beginif ((pixel_xpos >= 1'b0) && (pixel_xpos < (H_DISP/5)*1)) beginpixel_data <= WHITE;end else if ((pixel_xpos >= (H_DISP/5)*1) && (pixel_xpos < (H_DISP/5)*2)) beginpixel_data <= BLACK;end  else if ((pixel_xpos >= (H_DISP/5)*2) && (pixel_xpos < (H_DISP/5)*3)) beginpixel_data <= RED;end  else if ((pixel_xpos >= (H_DISP/5)*3) && (pixel_xpos < (H_DISP/5)*4)) beginpixel_data <= GREEN;end  else beginpixel_data <= BLUE;endend
endendmodule

5、asyn_rst_syn:异步复位,同步释放,并转换成高电平有效

打拍实现 


// Descriptions:        异步复位,同步释放,并转换成高电平有效
module asyn_rst_syn(input clk,          //目的时钟域input reset_n,      //异步复位,低有效output syn_reset    //高有效);//reg define
reg reset_1;
reg reset_2;//*****************************************************
//**                    main code
//***************************************************** 
assign syn_reset  = reset_2;//对异步复位信号进行同步释放,并转换成高有效
always @ (posedge clk or negedge reset_n) beginif(!reset_n) beginreset_1 <= 1'b1;reset_2 <= 1'b1;endelse beginreset_1 <= 1'b0;reset_2 <= reset_1;end
endendmodule

6、serializer_10_to_1:实现10:1并串转换

//****************************************Copyright (c)***********************************//
//原子哥在线教学平台:www.yuanzige.com
//技术支持:www.openedv.com
//淘宝店铺:http://openedv.taobao.com
//关注微信公众平台微信号:"正点原子",免费获取ZYNQ & FPGA & STM32 & LINUX资料。
//版权所有,盗版必究。
//Copyright(C) 正点原子 2018-2028
//All rights reserved
//----------------------------------------------------------------------------------------
// File name:           serializer_10_to_1
// Last modified Date:  2020/05/28 20:28:08
// Last Version:        V1.0
// Descriptions:        用于实现10:1并串转换
//                      
//----------------------------------------------------------------------------------------
// Created by:          正点原子
// Created date:        2020/05/28 20:28:08
// Version:             V1.0
// Descriptions:        The original version
//
//----------------------------------------------------------------------------------------
//****************************************************************************************//`timescale 1ns / 1psmodule serializer_10_to_1(input           reset,              // 复位,高有效input           paralell_clk,       // 输入并行数据时钟input           serial_clk_5x,      // 输入串行数据时钟input   [9:0]   paralell_data,      // 输入并行数据output 			serial_data_out     // 输出串行数据);//wire define
wire		cascade1;     //用于两个OSERDESE2级联的信号
wire		cascade2;//*****************************************************
//**                    main code
//***************************************************** //例化OSERDESE2原语,实现并串转换,Master模式
OSERDESE2 #(.DATA_RATE_OQ   ("DDR"),       // 设置双倍数据速率.DATA_RATE_TQ   ("SDR"),       // DDR, BUF, SDR.DATA_WIDTH     (10),           // 输入的并行数据宽度为10bit.SERDES_MODE    ("MASTER"),    // 设置为Master,用于10bit宽度扩展    主.TBYTE_CTL      ("FALSE"),     // Enable tristate byte operation (FALSE, TRUE).TBYTE_SRC      ("FALSE"),     // Tristate byte source (FALSE, TRUE).TRISTATE_WIDTH (1)             // 3-state converter width (1,4)
)
OSERDESE2_Master (.CLK        (serial_clk_5x),    // 串行数据时钟,5倍时钟频率.CLKDIV     (paralell_clk),     // 并行数据时钟.RST        (reset),            // 1-bit input: Reset.OCE        (1'b1),             // 1-bit input: Output data clock enable.OQ         (serial_data_out),  // 串行输出数据.D1         (paralell_data[0]), // D1 - D8: 并行数据输入.D2         (paralell_data[1]),.D3         (paralell_data[2]),.D4         (paralell_data[3]),.D5         (paralell_data[4]),.D6         (paralell_data[5]),.D7         (paralell_data[6]),.D8         (paralell_data[7]),.SHIFTIN1   (cascade1),         // SHIFTIN1 用于位宽扩展.SHIFTIN2   (cascade2),         // SHIFTIN2.SHIFTOUT1  (),                 // SHIFTOUT1: 用于位宽扩展.SHIFTOUT2  (),                 // SHIFTOUT2.OFB        (),                 // 以下是未使用信号.T1         (1'b0),             .T2         (1'b0),.T3         (1'b0),.T4         (1'b0),.TBYTEIN    (1'b0),             .TCE        (1'b0),             .TBYTEOUT   (),                 .TFB        (),                 .TQ         ()                  
);//例化OSERDESE2原语,实现并串转换,Slave模式
OSERDESE2 #(.DATA_RATE_OQ   ("DDR"),       // 设置双倍数据速率.DATA_RATE_TQ   ("SDR"),       // DDR, BUF, SDR.DATA_WIDTH     (10),           // 输入的并行数据宽度为10bit.SERDES_MODE    ("SLAVE"),     // 设置为Slave,用于10bit宽度扩展                从.TBYTE_CTL      ("FALSE"),     // Enable tristate byte operation (FALSE, TRUE).TBYTE_SRC      ("FALSE"),     // Tristate byte source (FALSE, TRUE).TRISTATE_WIDTH (1)             // 3-state converter width (1,4)
)
OSERDESE2_Slave (.CLK        (serial_clk_5x),    // 串行数据时钟,5倍时钟频率.CLKDIV     (paralell_clk),     // 并行数据时钟.RST        (reset),            // 1-bit input: Reset.OCE        (1'b1),             // 1-bit input: Output data clock enable.OQ         (),                 // 串行输出数据.D1         (1'b0),             // D1 - D8: 并行数据输入.D2         (1'b0),.D3         (paralell_data[8]),.D4         (paralell_data[9]),.D5         (1'b0),.D6         (1'b0),.D7         (1'b0),.D8         (1'b0),.SHIFTIN1   (),                 // SHIFTIN1 用于位宽扩展.SHIFTIN2   (),                 // SHIFTIN2.SHIFTOUT1  (cascade1),         // SHIFTOUT1: 用于位宽扩展.SHIFTOUT2  (cascade2),         // SHIFTOUT2.OFB        (),                 // 以下是未使用信号.T1         (1'b0),             .T2         (1'b0),.T3         (1'b0),.T4         (1'b0),.TBYTEIN    (1'b0),             .TCE        (1'b0),             .TBYTEOUT   (),                 .TFB        (),                 .TQ         ()                  
);  endmodule

 七、仿真与下载验证

1、仿真

2、下载验证

关键字:HDMI彩条显示——FPGA学习笔记12

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: