HDMI接口介绍及其代码

news/2024/12/2 23:57:42/

一、初衷

HDMI是之前项目的一部分,本来不打算上传博客的,最近我们专业课设开始,恰好可以选择完成HDMI显示,也重新整理一下之前的项目,对于课设,这只是实现了基本功能,附加条件等过几天再更;希望这篇博客能帮助更多的初学者,结尾附代码;

二、开发平台

这个项目开发板我使用的是Xilinx的zynq-7030,读者可进行更改管脚进行更换;调用了vivado的pll以及ROM的IP;读者需要进行配置,在此,我就不做介绍,请自行百度;

三、项目介绍

先将图片转为coe文件存入ROM中,从ROM中读取24位真彩数据通过HDMI进行显示,显示的大小设置为1280*1024,如下所示:

 图片大小为500*500;读者可根据需要自行更改;

由于我正在一家公司实习,开发板无法使用,故没有展示环节,代码曾经下过开发板了,可以正常使用;故只提供仿真波形,如果有问题可以留言,我看到就会回复;

四、HDMI接口

 英文全称:H-High,D-Definition,M-Multimedia,I-Interface;高清晰度多媒体接口。

HDMI的数据传输有TMDS0,TMDS1,TMDS2三个通道,每个通道的传输流程都是一样的:

  

如上图所示,发送端将8bit的数据进入TMDS编码器,得到抗干扰性强的10bit TMDS信号,然后再进行串行化输出,在接收端收到串行的HDMI信号后,进行信号复原,得到10bit的TMDS信号,最后用TMDS解码器解码得到原来的8bit数据。

本项目使用的是1.3版本的HDMI接口,它支持的最大速率为10.2Gbps,而1.3版本的一个HDMI包括3个TMDS数据通道和1个TMDS时钟通道。什么是TMDS呢?

——TMDS(Transition Minimized Differential signal),最小化传输差分信号。

下图能很好的解释差分信号的优势:

                           

它能很好的屏蔽噪声的影响;

实际上,我们只需要完成发送端这部分,即:

               第一步:将8位并行RED数据发送到TMDS Tx。

       第二步:进行最小化传输处理,加上第9位,即编码过程。第9位数据称为编码位。

       第三步:并/串转换。   

               第四步:串行转差分          

对第二步进行补充:每个数据通道都通过编码算法(异或、异或非等),将8位数据转换成10位数据,前8位数据由原始信号经运算后获得,第9位指示运算的方式,第10位用来对应直流平衡。通过这种算法,会使得数据的传输和恢复更加可靠。

对传输速率及时钟的一些补充:

PCLK:像素时钟
以1920x1080p/60hz为例:1920*1080*60=124.4MHz
以1280x720p/60hz为例:1280*720*60=55.3MHz

带宽:1s内传输的数据量(bit)

4K频率需要的带宽:选最常用的3840x2160分辨率,色深的话常用的是8位,RGB三色就是24bit,我们的目标是60Hz刷新率(60fps)→→→ 3840*2160*24bit*60fps=11.94Gbps

HDMI1.3/1.4版本像素时钟高达340MHz,即最大带宽是:
       →→→ 340MHz*10bit(10bit编码)*3(3个数据通道)=10.2Gbps

但是由于HDMI采用的是8bit/10bit编码方式,实际效率是理论值的80%,所以10.2Gbps能传输的最大视频带宽是10.2*0.8=8.1Gbps

借鉴:(38条消息) HDMI接口简介---分辨率 时钟频率 lane速率计算_打怪升级ing的博客-CSDN博客_hdmi带宽计算https://blog.csdn.net/weixin_42229404/article/details/80461700

 则本项目

              -   频率:1280*1024*60 = 78.6Mhz,为什么不一样?我觉得可能是图像无效区也应该是进去;

          - 实际频率:1688*1066*60 = 107.9Mhz,与定义的相同;

              -  速率:108*10*3 = 3.24Gpbs;

五、代码讲解

       (1)顶层:

             由于我使用的开发板输入的是差分时钟,所以输入时钟是两对;

             注意观察可以发现,有个540M的时钟;由于将并行的10bit数据转换为串行的数据,时钟频率需要快10倍;但是是差分输出,所以只需要5倍时钟,即540M;   

//**************************************************************************
// *** 名称 : hdmixs_top
// *** 作者 : 不想上体育课
// *** 博客 : https://blog.csdn.net/m0_47220307?type=blog
// *** 日期 : 2022.09
// *** 描述 : top
//**************************************************************************`timescale 1ns / 1ps  
module hdmixs_top(input                                        sys_clk_n ,//差分时钟输入input                                        sys_clk_p ,input                                        sys_rst_n ,output                                       tmds_clk_n,//TMDS时钟通道output                                       tmds_clk_p,output         [2:0]                         tmds_data_n,//TMDS数据通道output         [2:0]                         tmds_data_p);wire                                             rst_n   ;
wire                                             clk_out1;
wire                                             clk_out2;
wire                                             locked;
wire                                             hdmi_hs;
wire                                             hdmi_vs;
wire              [10:0]                          w_x_pixel;
wire              [10:0]                          w_y_pixel;
// wire [15:0] pixel_data;
wire                                             hdmi_de;
wire              [23:0]                         rgb_data;
wire                                             tmds_oen;//TMDS输出使能
wire              [23:0]                         pixel_data;assign rst_n=sys_rst_n&locked;               //在保证时钟稳定的情况下,才保证正常工作
assign clk_out1 = sys_clk_n;
assign clk_out2 = sys_clk_p;clk_wiz_0 clk_div(.clk_out1                                  (clk_108M         ),   //输出108MHZ的频率.clk_out2                                  (clk_540M         ), .reset                                     (1'b0             ), .locked                                    (locked           ),.clk_in1_p                                 (sys_clk_p        ),.clk_in1_n                                 (sys_clk_n        )
);hdmixs_driver dri(.clk_out1                                  (clk_108M         ),.rst_n                                     (rst_n            ),.pixel_data                                (pixel_data       ),.hdmi_hs                                   (hdmi_hs          ),.hdmi_vs                                   (hdmi_vs          ),.hdmi_de                                   (hdmi_de          ),.vedio_rgb                                 (rgb_data         ),.x_pixel                                   (w_x_pixel        ),.y_pixel                                   (w_y_pixel        )
);hdmixs_display dis(.clk_out1                                  (clk_108M         ),.rst_n                                     (rst_n            ),.x_pixel                                   (w_x_pixel        ),.y_pixel                                   (w_y_pixel        ),.pixel_data                                (pixel_data       )
);rgb_to_hdmi urtg(.clk_out1                                  (clk_108M         ),  //输出108MHZ的频率.clk_out2                                  (clk_540M         ), .rst_n                                     (rst_n            ),.hdmi_de                                   (hdmi_de          ),.pixel_data                                (rgb_data         ),.hdmi_hs                                   (hdmi_hs          ),.hdmi_vs                                   (hdmi_vs          ),.tmds_clk_n                                (tmds_clk_n       ),.tmds_clk_p                                (tmds_clk_p       ),.tmds_oen                                  (tmds_oen         ),.tmds_data_n                               (tmds_data_n      ),.tmds_data_p                               (tmds_data_p      )
);endmodule

       (2) 显示驱动设置:

               此模块可以定义显示的屏幕设置,以及输出当前行列计数值和图像数据;

//**************************************************************************
// *** 名称 : hdmixs_driver
// *** 作者 : 不想上体育课
// *** 博客 : https://blog.csdn.net/m0_47220307?type=blog
// *** 日期 : 2022.09
// *** 描述 : 显示大小设置
//**************************************************************************`timescale 1ns / 1ps
module hdmixs_driver(input                    clk_out1  ,input                    rst_n     ,input      [23:0]        pixel_data,output      reg          hdmi_de   ,output                   hdmi_hs   ,	output                   hdmi_vs   ,output     [23:0]        vedio_rgb ,output     [ 10:0]       y_pixel   ,  //y像素坐标output     [ 10:0]       x_pixel      //x像素坐标);//1280*1024@60Hz 108Mhz
parameter Hor_Total_Time              =      11'd1688;		//
parameter Hor_Sync                    =      10'd112;	    //
parameter Hor_Back_Porch              =      10'd248;		//	
parameter Hor_Addr_Time               =      11'd1280;		//
parameter Hor_Front_Porch             =      10'd48;		//parameter Ver_Total_Time              =      11'd1066;		//
parameter Ver_Sync                    =      10'd3;		    //
parameter Ver_Back_Porch              =      10'd38;		//	
parameter Ver_Addr_Time               =      11'd1024;		//
parameter Ver_Front_Porch             =      10'd1;		    // //行列计数器
reg [10:0] x_cnt;
reg [10:0] y_cnt;always@(posedge clk_out1 or negedge rst_n)beginif(!rst_n)begin x_cnt<= 11'd0;y_cnt<= 11'd0;end else if(x_cnt==Hor_Total_Time)begin x_cnt<= 11'd0;if(y_cnt==Ver_Total_Time)y_cnt<=11'd0;elsey_cnt<= y_cnt+1'b1;endelse x_cnt<= x_cnt + 1'b1;endassign hdmi_hs=(x_cnt < Hor_Sync)?1'b0:1'b1;
assign hdmi_vs=(y_cnt < Ver_Sync)?1'b0:1'b1;always@(*)     //使能、以及得到像素坐标beginhdmi_de<=(x_cnt>(Hor_Sync + Hor_Back_Porch)&&x_cnt<=(Hor_Sync+Hor_Back_Porch+Hor_Addr_Time)&&y_cnt>(Ver_Sync+Ver_Back_Porch)&&y_cnt<=(Ver_Sync+Ver_Back_Porch+Ver_Addr_Time));endassign vedio_rgb=(hdmi_de)?pixel_data:24'd0;
assign x_pixel=(hdmi_de)?(x_cnt-(Hor_Sync + Hor_Back_Porch)):10'd0;        //行像素坐标
assign y_pixel=(hdmi_de)?(y_cnt-(Ver_Sync + Ver_Back_Porch)):10'd0;       //列像素坐标endmodule

       (3)图像显示模块

                此模块可以设置需要显示的图片大小及位置,并输出图像;

//**************************************************************************
// *** 名称 : hdmixs_display
// *** 作者 : 不想上体育课
// *** 博客 : https://blog.csdn.net/m0_47220307?type=blog
// *** 日期 : 2022.09
// *** 描述 : 显示图像区域设置
//**************************************************************************
`timescale 1ns / 1ps  
module hdmixs_display(input           wire                clk_out1  ,input           wire                rst_n     ,input           wire    [10:0]      x_pixel   ,input           wire    [10:0]      y_pixel   ,output          reg     [23:0]      pixel_data
);parameter height = 10'd500, width  = 10'd500;
parameter pos_x0 = 320, pos_y0 = 272;// picture  wire               rom_rd_en0;        //读ROM使能信号  
wire [32:0]        total;
wire [23:0]        rom_data0;reg  [23:0]        rom_addr0;  //读ROM有效信号 assign total = height*width;assign rom_rd_en0 =(x_pixel > pos_x0)&&(x_pixel<=pos_x0+width)&&(y_pixel>pos_y0)&&(y_pixel<=pos_y0+height)?1'b1:1'b0;       //first picture locationalways @(posedge clk_out1 or  negedge rst_n)begin if(!rst_n)beginpixel_data  <=  24'b0;endelse if(rom_rd_en0)pixel_data  <=  rom_data0;elsepixel_data  <=  24'h000_000;endalways@(posedge clk_out1 or negedge rst_n)beginif(!rst_n)rom_addr0<=24'd0;else if(rom_rd_en0)beginif(rom_addr0<total-1'b1)rom_addr0<=rom_addr0+1'b1;else rom_addr0<=24'd0;endelse rom_addr0<=rom_addr0;endblk_mem_gen_0 rom1(.addra(rom_addr0),.ena(1),.clka(clk_out1),.douta(rom_data0));	endmodule

        (4)rgb2hdmi模块

                这个模块例化了其他两个子模块;实现了8bit/10bit,以及并行转串行;并使用原语OBUFDS进行串行转差分;

//**************************************************************************
// *** 名称 : rgb_to_hdmi
// *** 作者 : 不想上体育课
// *** 博客 : https://blog.csdn.net/m0_47220307?type=blog
// *** 日期 : 2022.09
// *** 描述 : 差分输出
//**************************************************************************`timescale 1ns / 1ps
module rgb_to_hdmi(input                     clk_out1    ,input                     clk_out2    ,input                     rst_n       ,input                     hdmi_de     ,input     [24:0]          pixel_data  ,input                     hdmi_hs     ,input                     hdmi_vs     ,output                    tmds_clk_n  ,output                    tmds_clk_p  ,  output                    tmds_oen    ,  output     [2:0]          tmds_data_n ,output     [2:0]          tmds_data_p );wire        [9:0]             clk_10bit;wire                          syn_rst;wire        [9:0]             encode_red;wire        [9:0]             encode_green;wire        [9:0]             encode_blue;wire        [2:0]             serial_data;wire                          serial_out_clk;assign clk_10bit=10'b11111_00000;
assign tmds_oen=1'b1;asyn_to_syn syn(
.clk(clk_out1),
.rst_n(rst_n),
.syn_rst(syn_rst)
);encoder r(.clkin(clk_out1),    .rstin(syn_rst),   .din(pixel_data[23:16]),    .c0(1'b0),     .c1(1'b0),      .de(hdmi_de),      .dout(encode_red)     
);encoder g(.clkin(clk_out1),    .rstin(syn_rst),   .din(pixel_data[15:8]),    .c0(1'b0),     .c1(1'b0),      .de(hdmi_de),      .dout(encode_green)     
);encoder b(.clkin(clk_out1),    .rstin(syn_rst),   .din(pixel_data[7:0]),    .c0(hdmi_hs),     .c1(hdmi_vs),      .de(hdmi_de),      .dout(encode_blue)     
);serializer red(.paralell_data(encode_red),.paralell_clk(clk_out1),.reset(syn_rst),.serial_clk(clk_out2),.serial_data_out(serial_data[2])
);serializer green(.paralell_data(encode_green),.paralell_clk(clk_out1),.reset(syn_rst),.serial_clk(clk_out2),.serial_data_out(serial_data[1])
);serializer blue(.paralell_data(encode_blue),.paralell_clk(clk_out1),.reset(syn_rst),.serial_clk(clk_out2),.serial_data_out(serial_data[0])
);serializer clk(.paralell_data(clk_10bit),.paralell_clk(clk_out1),.reset(syn_rst),.serial_clk(clk_out2),.serial_data_out(serial_out_clk)
);OBUFDS #(.IOSTANDARD("TMDS_33"), // Specify the output I/O standard.SLEW("SLOW") // Specify the output slew rate
) TMDS0 (.O(tmds_data_p[0]), // Diff_p output (connect directly to top-level port).OB(tmds_data_n[0]), // Diff_n output (connect directly to top-level port).I(serial_data[0]) // Buffer input
);OBUFDS #(.IOSTANDARD("TMDS_33"), // Specify the output I/O standard.SLEW("SLOW") // Specify the output slew rate
) TMDS1 (.O(tmds_data_p[1]), // Diff_p output (connect directly to top-level port).OB(tmds_data_n[1]), // Diff_n output (connect directly to top-level port).I(serial_data[1]) // Buffer input
);OBUFDS #(.IOSTANDARD("TMDS_33"), // Specify the output I/O standard.SLEW("SLOW") // Specify the output slew rate
) TMDS2 (.O(tmds_data_p[2]), // Diff_p output (connect directly to top-level port).OB(tmds_data_n[2]), // Diff_n output (connect directly to top-level port).I(serial_data[2]) // Buffer input
);OBUFDS #(.IOSTANDARD("TMDS_33"), // Specify the output I/O standard.SLEW("SLOW") // Specify the output slew rate
) TMDS_clk (.O(tmds_clk_p), // Diff_p output (connect directly to top-level port).OB(tmds_clk_n), // Diff_n output (connect directly to top-level port).I(serial_out_clk) // Buffer input
);endmodule

       (5)编码模块:

                    实现了8bit/10bit

//**************************************************************************
// *** 名称 : encoder
// *** 作者 : 不想上体育课
// *** 博客 : https://blog.csdn.net/m0_47220307?type=blog
// *** 日期 : 2022.09
// *** 描述 : 编码模块
//**************************************************************************
`timescale 1ns / 1ps
module 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;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));
/*reg [8:0] q_m;always @ (posedge clkin) beginq_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_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;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

       (6)并行数据转串行

               使用原语OSERDESE2进行串行转差分操作;

//**************************************************************************
// *** 名称 : serializer
// *** 作者 : 不想上体育课
// *** 博客 : https://blog.csdn.net/m0_47220307?type=blog
// *** 日期 : 2022.09
// *** 描述 : 并行数据转串行
//**************************************************************************`timescale 1ns / 1ps
module serializer(input                reset       ,input                paralell_clk,    //并行input [9:0]          paralell_data,input                serial_clk,     //串行,比并行数据高output               serial_data_out);wire                    cascade1;wire                    cascade2;OSERDESE2 #(.DATA_RATE_OQ("DDR"),   // DDR, SDR.DATA_RATE_TQ("SDR"),   // DDR, BUF, SDR.DATA_WIDTH(10),         // Parallel data width (2-8,10,14).SERDES_MODE("MASTER"), // MASTER, SLAVE.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_MAS (.CLK(serial_clk),             // 1-bit input: High speed clock.CLKDIV(paralell_clk),       // 1-bit input: Divided clock.RST(reset),             // 1-bit input: Reset.OCE(1'b1),             // 1-bit input: Output data clock enable.OQ(serial_data_out),               // 1-bit output: Data path output// D1 - D8: 1-bit (each) input: Parallel data inputs (1-bit each).D1(paralell_data[0]),.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]),.SHIFTOUT1(),.SHIFTOUT2(),.SHIFTIN1(cascade1),	  .SHIFTIN2(cascade2),.OFB(),             // 1-bit output: Feedback path for data// T1 - T4: 1-bit (each) input: Parallel 3-state inputs.T1(1'b0),.T2(1'b0),.T3(1'b0),.T4(1'b0),.TBYTEIN(1'b0),     // 1-bit input: Byte group tristate.TCE(1'b0),              // 1-bit input: 3-state clock enable.TBYTEOUT(),   // 1-bit output: Byte group tristate.TFB(),             // 1-bit output: 3-state control.TQ()               // 1-bit output: 3-state control);OSERDESE2 #(.DATA_RATE_OQ("DDR"),   // DDR, SDR.DATA_RATE_TQ("SDR"),   // DDR, BUF, SDR.DATA_WIDTH(10),         // Parallel data width (2-8,10,14).SERDES_MODE("SLAVE"), // MASTER, SLAVE.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_SLA (.CLK(serial_clk),             // 1-bit input: High speed clock.CLKDIV(paralell_clk),       // 1-bit input: Divided clock.RST(reset),             // 1-bit input: Reset.OCE(1'b1),             // 1-bit input: Output data clock enable.OQ(),               // 1-bit output: Data path output// D1 - D8: 1-bit (each) input: Parallel data inputs (1-bit each).D1(1'b0),.D2(1'b0),.D3(paralell_data[8]),.D4(paralell_data[9]),.D5(1'b0),.D6(1'b0),.D7(1'b0),.D8(1'b0),.SHIFTOUT1(cascade1),.SHIFTOUT2(cascade2),.SHIFTIN1(),	  .SHIFTIN2(),.OFB(),             // 1-bit output: Feedback path for data// T1 - T4: 1-bit (each) input: Parallel 3-state inputs.T1(1'b0),.T2(1'b0),.T3(1'b0),.T4(1'b0),.TBYTEIN(1'b0),     // 1-bit input: Byte group tristate.TCE(1'b0),              // 1-bit input: 3-state clock enable.TBYTEOUT(),   // 1-bit output: Byte group tristate.TFB(),             // 1-bit output: 3-state control.TQ()              // 1-bit output: 3-state control);endmodule

       (7)同步模块

                   对复位进行同步处理(异步复位,同步释放);

//**************************************************************************
// *** 名称 : asyn_to_syn
// *** 作者 : 不想上体育课
// *** 博客 : https://blog.csdn.net/m0_47220307?type=blog
// *** 日期 : 2022.09
// *** 描述 : 同步处理模块
//**************************************************************************
`timescale 1ns / 1ps
module asyn_to_syn(input      clk,input      rst_n,output     syn_rst);reg rst_1;
reg rst_2;assign syn_rst=rst_2;
always @(posedge clk or negedge rst_n)beginif(!rst_n)begin rst_1<=1'b1;rst_2<=1'b1;endelsebegin rst_1<=1'b0;rst_2<=rst_1;endendendmodule

六、Testbench编写

          由于使用的是差分时钟,使用需要产生一个差分时钟:

//**************************************************************************
// *** 名称 : tb_hdmixs_top
// *** 作者 : 不想上体育课
// *** 博客 : https://blog.csdn.net/m0_47220307?type=blog
// *** 日期 : 2022.09
// *** 描述 : 测试模块
//**************************************************************************
·timescale 1ns/1ps
module tb_hdmixs_top();reg                                          sys_clk_n   ;
reg                                          sys_clk_p   ;
reg                                          sys_rst_n   ;wire                                         tmds_clk_n  ;//TMDS时钟通道
wire                                         tmds_clk_p  ;
wire           [2:0]                         tmds_data_n ;//TMDS数据通道
wire           [2:0]                         tmds_data_p ;initialbeginsys_clk_p = 1'b0;sys_clk_n = 1'b1;sys_rst_n <= 1'b0;#20sys_rst_n <= 1'b1;endalways #2.5 sys_clk_p = ~sys_clk_p;
always #2.5 sys_clk_n = ~sys_clk_n;hdmixs_top hdmixs_top_inst(.sys_clk_n   (sys_clk_n  ),.sys_clk_p   (sys_clk_p  ),.sys_rst_n   (sys_rst_n  ),.tmds_clk_n  (tmds_clk_n ),//TMDS时钟通道.tmds_clk_p  (tmds_clk_p ),.tmds_data_n (tmds_data_n),//TMDS数据通道.tmds_data_p (tmds_data_p));endmodule

七、Vivado仿真结果与COE对比

        读取的数据与COE文件一致。


http://www.ppmy.cn/news/380055.html

相关文章

转发一个写的很好的MHL技术文章

MHL这个只是经常听说&#xff0c;没有见过的东西&#xff0c;现在已经非常火热了&#xff0c;我们才刚刚开始做&#xff0c;人家三星都推出几款带MHL接口的手机了&#xff0c;电视 机顶盒。。。。。反正好多设备上都已经开始用MHL了。 Silicon Image厂家来人给我们做了MHL技术的…

MHL接口是一种废品接口

去年底开始&#xff0c;很多手机带上了一个新接口叫MHL&#xff0c;全称叫做移动终端高清影音标准接口&#xff08;Mobile High-Definition Link&#xff09;&#xff0c;随之而来是一些文章说MHL多么优秀&#xff0c;把Micro USB和HDMI合二为一了&#xff0c;比HDMI更强之类的…

AB32VG1:SDK_AB53XX_V061(5)蓝牙BLE测试笔记

文章目录 1.配置工程&#xff0c;重新编译1.1替换链接库libbtstack_dm.a1.2 《config.h》打开编译开关1.3 在 Downloader 里面打开 BLE 开关 2.ABLink&#xff08;手机APP&#xff09;控制2.1 app下载2.2 安装后打开&#xff0c;搜索蓝牙Bluetrum&#xff1a;2.3 操作存储卡 3.…

BTree和B+Tree详解

BTree和BTree详解 B树索引是B树在数据库中的一种实现&#xff0c;是最常见也是数据库中使用最为频繁的一种索引。B树中的B代表平衡(balance)&#xff0c;而不是二叉(binary)&#xff0c;因为B树是从最早的平衡二叉树演化而来的。在讲B树之前必须先了解二叉查找树、平衡二叉树(…

TDEngine3.x数据查询及插入调优

一、数据库创建 vgroups 配置 如果不了解vgroup概念&#xff0c;建议到官网查看&#xff1a;TDEngine官网-数据模型和整体架构 从服务端配置的角度&#xff0c;要根据系统中磁盘的数量&#xff0c;磁盘的 I/O 能力&#xff0c;以及处理器能力在创建数据库时设置适当的 vgroups…

Vue中如何进行颜色选择与取色器?

Vue中如何进行颜色选择与取色器&#xff1f; 在Web开发中&#xff0c;颜色选择器是一个非常常见的功能。在Vue.js中&#xff0c;我们可以使用现成的颜色选择器组件或者自己编写一个颜色选择器组件。本文将介绍如何在Vue.js中实现颜色选择器组件和取色器功能。 颜色选择器组件 …

推挽电路应用

1. 推挽电路&#xff0c;常用上N下P型 2. 输出与输入同相&#xff1a; 输入低电平&#xff0c;输出低电平&#xff0c;输出受输入限制&#xff0c;输入输出同相 输入高电平&#xff0c;输出低电平&#xff0c;输出受输入限制&#xff0c;输入输出同相 3. N管烧坏原因分析 当…

Lambda表达式详解

文章目录 什么是LambdaLambda表达式的语法Lambda表达式的应用场景GUI应用Lambda表达式的优缺点总结 什么是Lambda java中的Lambda表达式是一种函数式编程的风格&#xff0c;它允许我们将代码作为数据传递&#xff0c;并在需要时执行。Lambda表达式能够极大地简化代码&#xff0…