2020-08-15

HDMI显示实验
在vivado中文件的层次机构如下
在这里插入图片描述
其中VGA_shift为VGA模块生成的888+2RGB数据和Hs,Vs行核场同步信号
encode为8bits转10bits译码器
parallel_to_serial为10bits转1bit的并行转串行差分输出转换器
HDMI_CLK输出VGA并行时钟与HDMI串行时钟
HDMI.V代码如下:

module	HDMI(
		input 	wire		rst_n,
		input	wire		clk,
		output	wire 		hdmi_oen,
		output	wire 		clk_742_5_n,
		output	wire 		clk_742_5_p,
		output	wire		D0_n,
		output	wire		D0_p,
		output	wire		D1_n,
		output	wire		D1_p,
		output	wire		D2_n,
		output	wire		D2_p
		
		
);
parameter  	CNT_MAX 	= 	1000;
reg 	[10:0]		cnt ;
wire      [7:0]	  rgb_r        	;//输出图像值
wire      [7:0]	  rgb_g        	;//输出图像值
wire      [7:0]	  rgb_b  		;
wire			      vpg_vs;
wire			      vpg_hs;
wire 		clk_148_5;
wire 		clk_742_5;
wire			vpg_de;
wire			[9:0]	R_10;
wire			[9:0]	G_10;
wire			[9:0]	B_10;
/* assign hdmi_oen=1; */
/* wire		D0_n,D0_p;//红色HDMI输出
wire		D1_n,D1_p;//绿色HDMI输出
wire		D2_n,D2_p;//蓝色HDMI输出 */
/* hdmi_oen为HDMI输出使能。设置在1000个时钟周期后输出 */
reg 	hdmi_oen_r;
assign hdmi_oen = hdmi_oen_r;

always @(posedge clk_148_5) begin
	if (rst_n==0) begin
		cnt <= 'd0;
	end
	else if(cnt < CNT_MAX)begin
		cnt <= cnt + 1'b1;
	end
	else begin
		cnt <= cnt;
	end
end

always @(posedge clk_148_5) begin
	if (rst_n==0) begin
		hdmi_oen_r <= 1'b0;
	end
	else if(cnt == CNT_MAX)begin
		hdmi_oen_r <= 1'b1;
	end
end


	HDMI_CLK HDMI_CLK_inst
   (
    // Clock out ports
    .clk_148_5(clk_148_5),     // output clk_148_5
    .clk_742_5(clk_742_5),     // output clk_742_5
    // Status and control signals
    .reset(~rst_n), // input reset
    .locked(),       // output locked
   // Clock in ports
    .sys_clk(clk));      // input sys_clk
	
/* 	例化VGA模块,输出8*8*8的RGB数据 */
	vga_shift vga_shift_inst(
		// .clk(),// input   wire			  clk   		,//clock 50M
		.rst(~rst_n),// input	wire			  rst_n    		,//复位
		.vpg_pclk(clk_148_5),// output	wire			  vpg_pclk    	,//像素时钟
		.vpg_de(vpg_de),// output	wire			  vpg_de      	,//输出数据有效信号
		.vpg_hs(vpg_hs),// output	reg			      vpg_hs      	,//行同步信号
		.vpg_vs(vpg_vs),// output	reg			      vpg_vs      	,//场同步信号
		.rgb_r(rgb_r),// 
		.rgb_g(rgb_g),
		.rgb_b(rgb_b)
);




/* 红色8bits转换成10bits的数据 */
 encode VGA_R(
		.clkin(clk_148_5),// input            clkin,    // pixel clock input
		.rstin(~rst_n),// input            rstin,    // async. reset input (active high)
		.din(rgb_r),// input      [7:0] din,      // data inputs: expect registered
		.c0(1'b0),// input            c0,       // c0 input
		.c1(1'b0),// input            c1,       // c1 input
		.de(vpg_de),// input            de,       // de input
		.dout(R_10)// output reg [9:0] dout      // data outputs
);

/* 绿色8bits转换成10bits的数据 */
 encode VGA_G(
		.clkin(clk_148_5),// input            clkin,    // pixel clock input
		.rstin(~rst_n),// input            rstin,    // async. reset input (active high)
		.din(rgb_g),// input      [7:0] din,      // data inputs: expect registered
		.c0(1'b0),// input            c0,       // c0 input
		.c1(1'b0),// input            c1,       // c1 input
		.de(vpg_de),// input            de,       // de input
		.dout(G_10)// output reg [9:0] dout      // data outputs
);

/* 蓝色8bits转换成10bits的数据 */
 encode VGA_B(
		.clkin(clk_148_5),// input            clkin,    // pixel clock input
		.rstin(~rst_n),// input            rstin,    // async. reset input (active high)
		.din(rgb_b),// input      [7:0] din,      // data inputs: expect registered
		.c0(vpg_hs),// input            c0,       // c0 input
		.c1(vpg_vs),// input            c1,       // c1 input
		.de(vpg_de),// input            de,       // de input
		.dout(B_10)// output reg [9:0] dout      // data outputs
);
/* 	10位R并行改串行的数据 */
 parallel_to_serial HDMI_R(
		.clk1x(clk_148_5),// input 	wire 			clk1x	,
		.clk5x(clk_742_5),// input 	wire 			clk5x	,
		.rst(~rst_n),// input	wire 			rst 	,
		.din(R_10),// input 	wire 	[9:0]	din 	,
		.dout_p(D0_p),// output	wire			dout_p 	,
		.dout_n(D0_n)// output 	wire 			dout_n
	);
/* 	10位G并行改串行的数据 */
 parallel_to_serial HDMI_G(
		.clk1x(clk_148_5),// input 	wire 			clk1x	,
		.clk5x(clk_742_5),// input 	wire 			clk5x	,
		.rst(~rst_n),// input	wire 			rst 	,
		.din(G_10),// input 	wire 	[9:0]	din 	,
		.dout_p(D1_p),// output	wire			dout_p 	,
		.dout_n(D1_n)// output 	wire 			dout_n
	);
/* 	10位B并行改串行的数据 */	
 parallel_to_serial HDMI_B(
		.clk1x(clk_148_5),// input 	wire 			clk1x	,
		.clk5x(clk_742_5),// input 	wire 			clk5x	,
		.rst(~rst_n),// input	wire 			rst 	,
		.din(B_10),// input 	wire 	[9:0]	din 	,
		.dout_p(D2_p),// output	wire			dout_p 	,
		.dout_n(D2_n)// output 	wire 			dout_n
	);
	
/* 742.5MHZ的时钟差分输出	 */

	parallel_to_serial HDMI_CLK_742_5
		(
			.clk1x  (clk_148_5),
			.clk5x  (clk_742_5),
			.rst    (~rst_n),
			.din    (10'b11111_00000),
			.dout_p (clk_742_5_p),
			.dout_n (clk_742_5_n));
endmodule

其中encode为官方下载文件代码如下

//
//
//  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

parallel_to_serial为10bits转1bit的并行转串行差分输出转换器是将2个OSERDESE2组合作为10位输入1位差分输出具体代码如下

// --------------------------------------------------------------------

// --------------------------------------------------------------------
// --------------------------------------------------------------------
module parallel_to_serial(
	input 	wire 			clk1x	,
	input 	wire 			clk5x	,
	input	wire 			rst 	,
	input 	wire 	[9:0]	din 	,
	output	wire			dout_p 	,
	output 	wire 			dout_n
	);


wire 		dout 		;
wire 		shift_in1	;
wire 		shift_in2 	; 	



 OBUFDS #(
      .IOSTANDARD("DEFAULT"), // Specify the output I/O standard
      .SLEW("SLOW")           // Specify the output slew rate
   ) OBUFDS_inst (
      .O(dout_p),     // Diff_p output (connect directly to top-level port)
      .OB(dout_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
      .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_master (
      .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(clk5x),             // 1-bit input: High speed clock
      .CLKDIV(clk1x),       // 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(rst),             // 1-bit input: Reset
      // SHIFTIN1 / SHIFTIN2: 1-bit (each) input: Data input expansion (1-bit each)
      .SHIFTIN1(shift_in1),
      .SHIFTIN2(shift_in2),
      // 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
   );


   OSERDESE2 #(
      .DATA_RATE_OQ("DDR"),   // DDR, SDR
      .DATA_RATE_TQ("SDR"),   // DDR, BUF, SDR
      .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_slave (
      .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(shift_in1),
      .SHIFTOUT2(shift_in2),
      .TBYTEOUT(),   // 1-bit output: Byte group tristate
      .TFB(),             // 1-bit output: 3-state control
      .TQ(),               // 1-bit output: 3-state control
      .CLK(clk5x),             // 1-bit input: High speed clock
      .CLKDIV(clk1x),       // 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(),
      .D6(),
      .D7(),
      .D8(),
      .OCE(1'b1),             // 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(),
      .SHIFTIN2(),
      // 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
   );



endmodule



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值