Browse Source

hdmi/tmds: fix symbol data ordering

H. Peter Anvin 3 years ago
parent
commit
74d9da52b0
2 changed files with 72 additions and 70 deletions
  1. 39 44
      fpga/tmdsenc.sv
  2. 33 26
      fpga/video.sv

+ 39 - 44
fpga/tmdsenc.sv

@@ -6,46 +6,39 @@ module tmdsenc
   (
    input	rst_n,
    input	clk,
-   input	den,	// It is a data word, not a control word
-   input [7:0]	d,	// Data word
-   input	tercen, // Control data is TERC4 encoded
-   input [3:0]	c,	// Control or TERC4 word
+   input	den,    // Video data enable
+   input [7:0]	d,      // Video data word
+   input	ten,	// TERC data enable
+   input [3:0]	t,      // TERC data
+   input [1:0]	c,      // Control symbol
    output [9:0] q
    );
 
-   // Bit 4 is TERC4 enable
-   function logic [9:0] csym(input tercen, input [4:0] sym);
-      casez ({tercen, sym})
-	// Plain TMDS control symbols
-	5'b0_??00: csym = 10'b11010_10100;
-	5'b0_??01: csym = 10'b00101_01011;
-	5'b0_??10: csym = 10'b01010_10100;
-	5'b0_??11: csym = 10'b10101_01011;
+   // Control symbols
+   wire [9:0]	csym[0:3];
+   assign csym[ 0] = 10'b11010_10100;
+   assign csym[ 1] = 10'b00101_01011;
+   assign csym[ 2] = 10'b01010_10100;
+   assign csym[ 3] = 10'b10101_01011;
 
-	// TERC4 control symbols
-	5'b1_0000: csym = 10'b10100_11100;
-	5'b1_0001: csym = 10'b1001100011;
-	5'b1_0010: csym = 10'b1011100100;
-	5'b1_0011: csym = 10'b1011100010;
-	5'b1_0100: csym = 10'b0101110001;
-	5'b1_0101: csym = 10'b0100011110;
-	5'b1_0110: csym = 10'b0110001110;
-	5'b1_0111: csym = 10'b0100111100;
-	5'b1_1000: csym = 10'b1011001100;
-	5'b1_1001: csym = 10'b0100111001;
-	5'b1_1010: csym = 10'b0110011100;
-	5'b1_1011: csym = 10'b1011000110;
-	5'b1_1100: csym = 10'b1010001110;
-	5'b1_1101: csym = 10'b1001110001;
-	5'b1_1110: csym = 10'b0101100011;
-	5'b1_1111: csym = 10'b1011000011;
-      endcase // casez (sym)
-   endfunction // csym
-
-   function logic [9:0] bitrev10(input [9:0] in);
-      for (int i = 0; i < 10; i++)
-	bitrev10[i] = in[9-i];
-   endfunction // bitrev10
+   // TERC4 symbols
+   wire [9:0]	tsym[0:15];
+   assign tsym[ 0] = 10'b10100_11100;
+   assign tsym[ 1] = 10'b10011_00011;
+   assign tsym[ 2] = 10'b10111_00100;
+   assign tsym[ 3] = 10'b10111_00010;
+   assign tsym[ 4] = 10'b01011_10001;
+   assign tsym[ 5] = 10'b01000_11110;
+   assign tsym[ 6] = 10'b01100_01110;
+   assign tsym[ 7] = 10'b01001_11100;
+   assign tsym[ 8] = 10'b10110_01100;
+   assign tsym[ 9] = 10'b01001_11001;
+   assign tsym[10] = 10'b01100_11100;
+   assign tsym[11] = 10'b10110_00110;
+   assign tsym[12] = 10'b10100_01110;
+   assign tsym[13] = 10'b10011_10001;
+   assign tsym[14] = 10'b01011_00011;
+   assign tsym[15] = 10'b10110_00011;
 
    reg signed [4:0] disparity; // Running disparity/2
    reg [9:0]	    qreg;
@@ -53,8 +46,9 @@ module tmdsenc
 
    reg [7:0]	    dreg;
    reg		    denreg;
-   reg [3:0]	    creg;
-   reg		    tercenreg;
+   reg [3:0]	    treg;
+   reg		    tenreg;
+   reg [1:0]	    creg;
 
    wire signed [3:0] ddisp =
 	dreg[7] + dreg[6] + dreg[5] + dreg[4] +
@@ -79,7 +73,6 @@ module tmdsenc
      end // always @ (*)
 
    reg [9:0] dq;		// Disparity stage output
-   reg	     dispsign;		// Disparity counter up or down
 
    always_comb
      begin
@@ -96,18 +89,20 @@ module tmdsenc
    always @(negedge rst_n or posedge clk)
      if (~rst_n)
        begin
-	  dreg      <= 'b0;
 	  disparity <= 'sd0;
-	  qreg      <= csym(1'b0, 4'b0000);
+	  qreg      <= csym[0];
+	  dreg      <= 8'bx;
 	  denreg    <= 1'b0;
+	  tenreg    <= 1'b0;
+	  treg      <= 4'bx;
 	  creg      <= 2'b00;
-	  tercenreg <= 1'b0;
        end
      else
        begin
 	  denreg    <= den;
-	  tercenreg <= tercen;
+	  tenreg    <= ten;
 	  creg      <= c;
+	  treg      <= t;
 	  dreg      <= d;
 
 	  if (denreg)
@@ -117,7 +112,7 @@ module tmdsenc
 	    end
 	  else
 	    begin
-	       qreg <= csym(tercenreg, creg);
+	       qreg <= tenreg ? tsym[treg] : csym[creg];
 	       disparity <= 'sd0;
 	    end
        end // else: !if(~rst_n)

+ 33 - 26
fpga/video.sv

@@ -82,19 +82,19 @@ module video (
        end // else: !if(~rst_n)
 
    wire [7:0] hdmi_data[0:2];
-
-   assign hdmi_data[2] = r;
-   assign hdmi_data[1] = g;
-   assign hdmi_data[0] = b;
-
-   // hdmi_ctl[4] enables TERC4 encoding
-   wire [4:0] hdmi_ctl[0:2];
-
-   assign hdmi_ctl[0][0]   = hsync;
-   assign hdmi_ctl[0][1]   = vsync;
-   assign hdmi_ctl[0][4:2] = 3'b0_00;
-   assign hdmi_ctl[1]      = 5'b0_0000;
-   assign hdmi_ctl[2]      = 5'b0_0000;
+   //assign hdmi_data[2] = r;
+   //assign hdmi_data[1] = g;
+   //assign hdmi_data[0] = b;
+   //assign hdmi_data[2] = 8'b11110000;
+   //assign hdmi_data[1] = 8'b11001100;
+   assign hdmi_data[2] = 8'b10101010;
+   assign hdmi_data[1] = 8'b10101010;
+   assign hdmi_data[0] = 8'b10101010;
+
+   wire [1:0] hdmi_ctl[0:2];
+   assign hdmi_ctl[0]      = { vsync, hsync };
+   assign hdmi_ctl[1]      = 2'b00;
+   assign hdmi_ctl[2]      = 2'b00;
 
    wire [9:0] hdmi_tmds_data[0:2]; // TMDS encoded data per channel
 
@@ -103,14 +103,15 @@ module video (
       for (i = 0; i < 3; i = i + 1)
 	begin : hdmitmds
 	   tmdsenc enc (
-		    .rst_n ( rst_n ),
-		    .clk ( vid_clk ),
-		    .den ( ~hblank & ~vblank ),
-		    .d ( hdmi_data[i] ),
-		    .c ( hdmi_ctl[i][3:0] ),
-		    .tercen( hdmi_ctl[i][4] ),
-		    .q ( hdmi_tmds_data[i] )
-		    );
+			.rst_n ( rst_n ),
+			.clk   ( vid_clk ),
+			.den   ( ~hblank & ~vblank ),
+			.d     ( hdmi_data[i] ),
+			.ten   ( 1'b0 ), // TERC data not supported yet
+			.t     ( 4'bx ),
+			.c     ( hdmi_ctl[i] ),
+			.q     ( hdmi_tmds_data[i] )
+			);
 	end
    endgenerate
 
@@ -119,14 +120,20 @@ module video (
    assign hdmi_hpd = 1'bz;
 
    //
-   // The ALTLVDS_TX megafunctions is MSB-first and in time-major order.
-   // However, TMDS is LSB-first, and we have three TMDS words that
-   // concatenate in word(channel)-major order.
+   // The ALTLVDS_TX megafunctions is MSB-first in channel-major
+   // order, but TMDS is LSB first. Thus, bit-reverse the data within
+   // each channel.
    //
    wire [29:0] hdmi_to_tx;	// TMDS data in the order hdmitx expects
 
-   transpose #(.words(3), .bits(10), .reverse_b(1),
-	       .reg_d(0), .reg_q(0)) hdmitranspose
+   transpose #(.words( 3 ),
+	       .bits( 10 ),
+	       .reverse_b ( 1'b1 ),
+	       .reverse_w ( 1'b0 ),
+	       .transpose ( 1'b0 ),
+	       .reg_d ( 1'b0 ),
+	       .reg_q ( 1'b0 )
+	       ) hdmitranspose
      (
       .clk ( vid_clk ),
       .d ( { hdmi_tmds_data[2], hdmi_tmds_data[1], hdmi_tmds_data[0] } ),