目录
HDMI,高清晰度多媒体接口(High Definition Multimedia Interface)是标准的数字化视频/音频接口技术,可用于机顶盒、DVD播放机、个人电脑与电视机。HDMI可以同时传送音频和影音信号,能高品质地传输未经压缩的高清视频和多声道音频数据,最高数据传输速度为 50Gbps 左右。
常见的 HDMI 有19 根 pin,此外还有二十多跟 pin 脚的 HDMI 接口这里也只介绍此类常见的 HDMI接口,接口序号和定义如下:
| 引脚 | 信号 | 引脚 | 信号 |
| 1 | 数据2+ | 11 | 时钟屏蔽 |
| 2 | 数据2屏蔽 | 12 | 时钟- |
| 3 | 数据2- | 13 | |
| 4 | 数据1+ | 14 | 保留 |
| 5 | 数据1屏蔽 | 15 | SCL |
| 6 | 数据1- | 16 | SDA |
| 7 | 数据0+ | 17 | DDC/CEC地 |
| 8 | 数据0屏蔽 | 18 | +5v电源 |
| 9 | 数据0- | 19 | 热插拔检测 |
| 10 | 时钟+ |
过渡调制差分信号,也被称为最小化传输差分信号,是指通过异或及异或非等逻辑算法将原始信号数据转换成 10 位,前 8 位数据由原始信号经运算后获得,第9位指示运算的方式,第 10 位用来对应直流平衡(DC-balanced,就是指在编码过程中保证信道中直流偏移为零,电平转化实现不同逻辑接口间的匹配),转换后的数据以差分传动方式传送。
下图为 HDMI 链路的框架图

TMDS 的链路如下图所示,可以看到链路主要有两部分:source 和 sink 端,source 端为传输数据的起始端,sink 端为传输数据的目的端。同时链路由四条通道组成,分别为蓝色通道、、绿色通道、红色通道和时钟通道。
蓝色通道
蓝色通道包含8位的蓝色数据通道,两位的行同步和场同步信号,以及四位的音频信号。
绿色通道
绿色通道包含8位的绿色数据通道,两位的控制信号,以及四位的音频信号。
红色通道
红色通道包含8位的红色数据通道,两位的控制信号,以及四位的音频信号。
时钟通道
为什么要导读设立一个时钟通道呢?这是为了使source端和sink端的数据保持在同一个pixel clock下,便于数据的稳定发送和接收。
在 source 端,每个通道的中还包含 Encoder 和 Serializer 模块,即编码模块和并转串模块,对应到 sink 端为解码模块和串转并模块。
在编码阶段,编码器将视频源中的像素数据、HDMI的音频/附件数据,以及行、场同步信号分别编码成10位的字符流。
在并串转换阶段将上述的10位字符流转换成串行数据流,并将其从三个差分输出通道发送出去。这个10:1的并转串过程所产生的串行速率是实际像素时钟速率的10倍。但是在并转串中采用的为DDR即双沿采样,因此时钟频率可以减小为原来的一半,也就是像素时钟的 5 倍。

下图为 TMDS 的编码算法的流程示意图,每一个数据通道都通过编码算法,将 8 位的视、音频数据转换成最小化传输、直流平衡的 10 位数据。这使得数据的传输和恢复更加可靠。最小化传输差分信号是通过异或及异或非等逻辑算法将原始 8位信号数据转换成 10 位,前 8 为数据由原始信号经运算后获得,第 9 位指示运算的方式,第 10位用来对应直流平衡。这种算法可以减小传输信号过程的上冲和下冲,什么是上冲和下冲呢,顾名思义上冲就是由0转变为1,下冲就是由1转变为0,如果频繁的上下冲就会导致信号传输不稳定,而DC平衡使信号对传输线的电磁干扰减少,DC平衡指的是在码流中0和1的个数相当。总结来说,信号频繁的0、1变化和0和1数量不均衡都会影响信号的质量,编码的目的就在于此。

这个编码代码可以直接调用Xilinx官网的,在例化此模块时,需要对每个通道分别进行例化。
- //
- //
- // Xilinx, Inc. 2008 www.xilinx.com
- //
- //
- //
- // File name : encode.v
- //
- // Description : TMDS encoder
- //
- // Date - revision : Jan. 2008 - v 1.0
- //
- // Author : Bob Feng
- //
- // Disclaimer: LIMITED WARRANTY AND DISCLAMER. These designs are
- // provided to you "as is". Xilinx and its licensors make and you
- // receive no warranties or conditions, express, implied,
- // statutory or otherwise, and Xilinx specifically disclaims any
- // implied warranties of merchantability, non-infringement,or
- // fitness for a particular purpose. Xilinx does not warrant that
- // the functions contained in these designs will meet your
- // requirements, or that the operation of these designs will be
- // uninterrupted or error free, or that defects in the Designs
- // will be corrected. Furthermore, Xilinx does not warrantor
- // make any representations regarding use or the results of the
- // use of the designs in terms of correctness, accuracy,
- // reliability, or otherwise.
- //
- // LIMITATION OF LIABILITY. In no event will Xilinx or its
- // licensors be liable for any loss of data, lost profits,cost
- // or procurement of substitute goods or services, or for any
- // special, incidental, consequential, or indirect damages
- // arising from the use or operation of the designs or
- // accompanying documentation, however caused and on any theory
- // of liability. This limitation will apply even if Xilinx
- // has been advised of the possibility of such damage. This
- // limitation shall apply not-withstanding the failure of the
- // essential purpose of any limited remedies herein.
- //
- // Copyright © 2006 Xilinx, Inc.
- // All rights reserved
- //
- //
- `timescale 1 ps / 1ps
-
- module encode (
- input clkin, // pixel clock input
- input rstin, // async. reset input (active high)
- input [7:0] din, // data inputs: expect registered
- input c0, // c0 input
- input c1, // c1 input
- input de, // de input
- output 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
- // output
-
- reg [3:0] n1d; //number of 1s in din
- reg [7:0] din_q;
-
- always @ (posedge clkin) begin
- n1d <= din[0] + din[1] + din[2] + din[3] + din[4] + din[5] + din[6] + din[7];
-
- din_q <= 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));
- /*
- reg [8:0] q_m;
- always @ (posedge clkin) begin
- q_m[0] <=#1 din_q[0];
- q_m[1] <=#1 (decision1) ? (q_m[0] ^~ din_q[1]) : (q_m[0] ^ din_q[1]);
- q_m[2] <=#1 (decision1) ? (q_m[1] ^~ din_q[2]) : (q_m[1] ^ din_q[2]);
- q_m[3] <=#1 (decision1) ? (q_m[2] ^~ din_q[3]) : (q_m[2] ^ din_q[3]);
- q_m[4] <=#1 (decision1) ? (q_m[3] ^~ din_q[4]) : (q_m[3] ^ din_q[4]);
- q_m[5] <=#1 (decision1) ? (q_m[4] ^~ din_q[5]) : (q_m[4] ^ din_q[5]);
- q_m[6] <=#1 (decision1) ? (q_m[5] ^~ din_q[6]) : (q_m[5] ^ din_q[6]);
- q_m[7] <=#1 (decision1) ? (q_m[6] ^~ din_q[7]) : (q_m[6] ^ din_q[7]);
- q_m[8] <=#1 (decision1) ? 1'b0 : 1'b1;
- end
- */
- 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_m
- always @ (posedge clkin) begin
- n1q_m <= 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 <= 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]);
- end
-
- parameter 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 bit
- wire 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 alignment
-
- reg de_q, de_reg;
- reg c0_q, c1_q;
- reg c0_reg, c1_reg;
- reg [8:0] q_m_reg;
- always @ (posedge clkin) begin
- de_q <= de;
- de_reg <= de_q;
-
- c0_q <= c0;
- c0_reg <= c0_q;
- c1_q <= c1;
- c1_reg <= c1_q;
- q_m_reg <= q_m;
- end
- ///
- // 10-bit out
- // disparity counter
- ///
- always @ (posedge clkin or posedge rstin) begin
- if(rstin) begin
- dout <= 10'h0;
- cnt <= 5'h0;
- end else begin
- if (de_reg) begin
- if(decision2) begin
- dout[9] <= ~q_m_reg[8];
- dout[8] <= q_m_reg[8];
- dout[7:0] <= (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 begin
- if(decision3) begin
- dout[9] <= 1'b1;
- dout[8] <= q_m_reg[8];
- dout[7:0] <= ~q_m_reg[7:0];
-
- cnt <=#1 cnt + {q_m_reg[8], 1'b0} + (n0q_m - n1q_m);
- end else begin
- dout[9] <= 1'b0;
- dout[8] <= q_m_reg[8];
- dout[7:0] <= q_m_reg[7:0];
-
- cnt <= cnt - {~q_m_reg[8], 1'b0} + (n1q_m - n0q_m);
- end
- end
- end else begin
- case ({c1_reg, c0_reg})
- 2'b00: dout <= CTRLTOKEN0;
- 2'b01: dout <= CTRLTOKEN1;
- 2'b10: dout <= CTRLTOKEN2;
- default: dout <= CTRLTOKEN3;
- endcase
-
- cnt <= 5'h0;
- end
- end
- end
-
- endmodule
并串模块可以直接调用原语OSERDESE2,该原语可以将并行数据转为串行数据,支持的位宽为2-8、10、14,并且支持DDR还是SDR采样等模式配置,经过并转串原语出来的串行数据,由于TMDS的传输为差分信号,因此还需要将单端信号转变为差分信号,同样也可以借用原语实现,OBUFDS就可以实现这样的功能,将输出的单端信号转为差分信号。注意需要对每个通道进行例化。
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
- // Author : Linest-5
- // File : serial10_1.v
- // Create : 2022-10-04 15:41:01
- // Revise : 2022-10-04 17:07:13
- // Module Name :
- // Description :
- // Editor : sublime text3, tab size (4)
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
- module serial10_1(
- input divclk, //并行时钟
- input serclk, //串行时钟
- input rst,
- input [9:0] din,
- output do_p,
- output do_n
- );
- reg init_rst;
- wire cascade_di1;
- wire cascade_di2;
- wire dout;
-
- always @(posedge divclk or posedge rst) begin
- if (rst) begin
- init_rst <= 'd1;
- end
- else begin
- init_rst <= 'd0;
- end
- end
-
- OBUFDS #(
- .IOSTANDARD("DEFAULT"), // Specify the output I/O standard
- .SLEW("SLOW") // Specify the output slew rate
- ) OBUFDS_inst (
- .O(do_p), // Diff_p output (connect directly to top-level port)
- .OB(do_n), // Diff_n output (connect directly to top-level port)
- .I(dout) // Buffer input
- );
-
- OSERDESE2 #(
- .DATA_RATE_OQ("DDR"), // DDR, SDR
- .DATA_RATE_TQ("SDR"), // DDR, BUF, SDR 控制OQ输出的buffer是输出还是三态
- .DATA_WIDTH(10), // 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(1) // 3-state converter width (1,4)
- )
- OSERDESE2_inst_M (
- .OFB(), // 1-bit output: Feedback path for data
- .OQ(dout), // 1-bit output: Data path output
- // SHIFTOUT1 / SHIFTOUT2: 1-bit (each) output: Data output expansion (1-bit each)
- .SHIFTOUT1(),
- .SHIFTOUT2(),
- .TBYTEOUT(), // 1-bit output: Byte group tristate
- .TFB(), // 1-bit output: 3-state control
- .TQ(), // 1-bit output: 3-state control
- .CLK(serclk), // 1-bit input: High speed clock
- .CLKDIV(divclk), // 1-bit input: Divided clock
- // D1 - D8: 1-bit (each) input: Parallel data inputs (1-bit each)
- .D1(din[0]),
- .D2(din[1]),
- .D3(din[2]),
- .D4(din[3]),
- .D5(din[4]),
- .D6(din[5]),
- .D7(din[6]),
- .D8(din[7]),
- .OCE(1'b1), // 1-bit input: Output data clock enable
- .RST(init_rst), // 1-bit input: Reset
- // SHIFTIN1 / SHIFTIN2: 1-bit (each) input: Data input expansion (1-bit each)
- .SHIFTIN1(cascade_di1),
- .SHIFTIN2(cascade_di2),
- // T1 - T4: 1-bit (each) input: Parallel 3-state inputs
- .T1(0),
- .T2(0),
- .T3(0),
- .T4(0),
- .TBYTEIN(0), // 1-bit input: Byte group tristate
- .TCE(0) // 1-bit input: 3-state clock enable
- );
- OSERDESE2 #(
- .DATA_RATE_OQ("DDR"), // DDR, SDR
- .DATA_RATE_TQ("SDR"), // DDR, BUF, SDR 控制OQ输出的buffer是输出还是三态
- .DATA_WIDTH(10), // 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("SLAVE"), // 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(1) // 3-state converter width (1,4)
- )
- OSERDESE2_inst_S (
- .OFB(), // 1-bit output: Feedback path for data
- .OQ(), // 1-bit output: Data path output
- // SHIFTOUT1 / SHIFTOUT2: 1-bit (each) output: Data output expansion (1-bit each)
- .SHIFTOUT1(cascade_di1),
- .SHIFTOUT2(cascade_di2),
- .TBYTEOUT(), // 1-bit output: Byte group tristate
- .TFB(), // 1-bit output: 3-state control
- .TQ(), // 1-bit output: 3-state control
- .CLK(serclk), // 1-bit input: High speed clock
- .CLKDIV(divclk), // 1-bit input: Divided clock
- // D1 - D8: 1-bit (each) input: Parallel data inputs (1-bit each)
- .D1(),
- .D2(),
- .D3(din[8]),
- .D4(din[9]),
- .D5(0),
- .D6(0),
- .D7(0),
- .D8(0),
- .OCE(1'b1), // 1-bit input: Output data clock enable
- .RST(init_rst), // 1-bit input: Reset
- // SHIFTIN1 / SHIFTIN2: 1-bit (each) input: Data input expansion (1-bit each)
- .SHIFTIN1(),
- .SHIFTIN2(),
- // T1 - T4: 1-bit (each) input: Parallel 3-state inputs
- .T1(0),
- .T2(0),
- .T3(0),
- .T4(0),
- .TBYTEIN(0), // 1-bit input: Byte group tristate
- .TCE(0) // 1-bit input: 3-state clock enable
- );
-
- endmodule
这部分在 VGA 中讲过,不多叙述,可以在VESA查询不同分辨率和帧数所对应的参数


VGA的时序驱动代码也在VGA中有,不同分辨率的参数设定都已经参数化,根据不同的情况更改参数即可。
以下为 VGA 驱动设计系列博客直达链接。
在次顶层模块对编码模块和并转串模块进行例化,需要对每个通道都进行例化一遍。
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
- // Author : Linest-5
- // File : hdmi_trans.v
- // Create : 2022-10-04 16:39:39
- // Revise : 2022-10-04 16:57:56
- // Module Name :
- // Description :
- // Editor : sublime text3, tab size (4)
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
- module hdmi_trans(
- input clk1x,
- input clk5x,
- input rst,
- input locked,
- input [7:0] vga_r,
- input [7:0] vga_g,
- input [7:0] vga_b,
- input de,
- input v_sync,
- input h_sync,
- output hdmi_clk_p,
- output hdmi_clk_n,
- output hdmi_chan0_p,
- output hdmi_chan0_n,
- output hdmi_chan1_p,
- output hdmi_chan1_n,
- output hdmi_chan2_p,
- output hdmi_chan2_n
- );
-
- wire sysrst;
- wire [9:0] do_red;
- wire [9:0] do_green;
- wire [9:0] do_blue;
-
- assign sysrst = rst | (~locked);
-
- encode inst_encode_red (
- .clkin (clk1x),
- .rstin (sysrst),
- .din (vga_r),
- .c0 (1'b0),
- .c1 (1'b0),
- .de (de),
- .dout (do_red)
- );
-
- encode inst_encode_green (
- .clkin (clk1x),
- .rstin (sysrst),
- .din (vga_g),
- .c0 (1'b0),
- .c1 (1'b0),
- .de (de),
- .dout (do_green)
- );
-
- encode inst_encode_blue (
- .clkin (clk1x),
- .rstin (sysrst),
- .din (vga_b),
- .c0 (h_sync),
- .c1 (v_sync),
- .de (de),
- .dout (do_blue)
- );
-
- serial10_1 inst_serial10_1_clk(
- .divclk (clk1x),
- .serclk (clk5x),
- .rst (sysrst),
- .din (10'b1111_0000),
- .do_p (hdmi_clk_p),
- .do_n (hdmi_clk_n)
- );
- serial10_1 inst_serial10_1_red(
- .divclk (clk1x),
- .serclk (clk5x),
- .rst (sysrst),
- .din (do_red),
- .do_p (hdmi_chan2_p),
- .do_n (hdmi_chan2_n)
- );
- serial10_1 inst_serial10_1_green(
- .divclk (clk1x),
- .serclk (clk5x),
- .rst (sysrst),
- .din (do_green),
- .do_p (hdmi_chan1_p),
- .do_n (hdmi_chan1_n)
- );
- serial10_1 inst_serial10_1_blue(
- .divclk (clk1x),
- .serclk (clk5x),
- .rst (sysrst),
- .din (do_blue),
- .do_p (hdmi_chan0_p),
- .do_n (hdmi_chan0_n)
- );
- endmodule
最后进行最顶层模块的书写,将通带次顶层模块和VGA时序模块及逆行例化,同时由于我使用的板子输入时钟为200M的差分时钟,所以还需要例化锁相环模块。
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
- // Author : Linest-5
- // File : hdmi_top.v
- // Create : 2022-10-04 20:54:00
- // Revise : 2022-10-04 21:16:21
- // Module Name :
- // Description :
- // Editor : sublime text3, tab size (4)
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
- /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
- `timescale 1ns / 1ps
-
- module hdmi_top(
- input clk_p,
- input clk_n,
- output hdmi_clk_p,
- output hdmi_clk_n,
- output hdmi_chan0_p,
- output hdmi_chan0_n,
- output hdmi_chan1_p,
- output hdmi_chan1_n,
- output hdmi_chan2_p,
- output hdmi_chan2_n
- );
-
- wire clk1x;
- wire clk5x;
- wire locked;
- wire [7:0] vga_r;
- wire [7:0] vga_g;
- wire [7:0] vga_b;
- wire de;
- wire v_sync;
- wire h_sync;
-
-
-
- diff2single inst_diff2single(
- // Clock out ports
- .clk_out1(clk1x), // output clk_out1
- .clk_out2(clk5x), // output clk_out2
- // Status and control signals
- .locked(locked), // output locked
- // Clock in ports
- .clk_in1_p(clk_p), // input clk_in1_p
- .clk_in1_n(clk_n)); // input clk_in1_n
-
- hdmi_trans inst_hdmi_trans (
- .clk1x (clk1x),
- .clk5x (clk5x),
- .rst (0),
- .locked (locked),
- .vga_r (vga_r),
- .vga_g (vga_g),
- .vga_b (vga_b),
- .de (de),
- .v_sync (v_sync),
- .h_sync (h_sync),
- .hdmi_clk_p (hdmi_clk_p),
- .hdmi_clk_n (hdmi_clk_n),
- .hdmi_chan0_p (hdmi_chan0_p),
- .hdmi_chan0_n (hdmi_chan0_n),
- .hdmi_chan1_p (hdmi_chan1_p),
- .hdmi_chan1_n (hdmi_chan1_n),
- .hdmi_chan2_p (hdmi_chan2_p),
- .hdmi_chan2_n (hdmi_chan2_n)
- );
-
- VGA_TIMING inst_VGA_TIMING (
- .sclk (clk1x),
- .rst_n (locked),
- .po_vga_r (vga_r),
- .po_vga_g (vga_g),
- .po_vga_b (vga_b),
- .po_de (de),
- .po_v_sync (v_sync),
- .po_h_sync (h_sync)
- );
-
-
-
-
- endmodule
在 Vivado 对工程进行搭建,将几个文件导入,并添加相应的 IP 模块即可。
以下为实验工程的模块间框图

最后绑定管脚并生成比特流文件,烧录至FPGA中,将HDMI输出口接到带有HDMI口的显示器,就可以看到在显示屏上呈现彩条。