|  | @@ -2,100 +2,72 @@
 | 
	
		
			
				|  |  |  // Encodes a word in TMDS 8/10 format
 | 
	
		
			
				|  |  |  //
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -`undef USE_TMDSROM
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -`ifdef USE_TMDSROM
 | 
	
		
			
				|  |  | -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 [1:0]	c, // Control word
 | 
	
		
			
				|  |  | -   output [9:0] q
 | 
	
		
			
				|  |  | -   );
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -   reg signed [3:0]	     disparity; // Running disparity/2
 | 
	
		
			
				|  |  | -   reg [9:0]		     qreg;
 | 
	
		
			
				|  |  | -   assign q = qreg;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -   wire [15:0]		     romq;
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -   tmdsrom tmdsrom (
 | 
	
		
			
				|  |  | -		    .clk ( clk ),
 | 
	
		
			
				|  |  | -		    .d ( d ),
 | 
	
		
			
				|  |  | -		    .q ( romq )
 | 
	
		
			
				|  |  | -		    );
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -   // Delay two cycles to match tmdsrom
 | 
	
		
			
				|  |  | -   reg [1:0]		     denreg;
 | 
	
		
			
				|  |  | -   reg [1:0]		     creg[2];
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -   wire invert =
 | 
	
		
			
				|  |  | -	(disparity > 4'sd0 & romq[10]) |
 | 
	
		
			
				|  |  | -	(disparity < 4'sd0 & romq[11]);
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -   wire cp =  creg[1][0];
 | 
	
		
			
				|  |  | -   wire cn = ~creg[1][0];
 | 
	
		
			
				|  |  | -   wire cx = ~creg[1][0] ^ creg[1][1]; // XNOR of C1 and C0
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -   always @(negedge rst_n or posedge clk)
 | 
	
		
			
				|  |  | -     if (~rst_n)
 | 
	
		
			
				|  |  | -       begin
 | 
	
		
			
				|  |  | -	  disparity <= 4'sd0;
 | 
	
		
			
				|  |  | -	  denreg    <= 2'b00;
 | 
	
		
			
				|  |  | -	  creg[0]   <= 2'b00;
 | 
	
		
			
				|  |  | -	  creg[1]   <= 2'b00;
 | 
	
		
			
				|  |  | -       end
 | 
	
		
			
				|  |  | -     else
 | 
	
		
			
				|  |  | -       begin
 | 
	
		
			
				|  |  | -	  denreg <= { denreg[0], den };
 | 
	
		
			
				|  |  | -	  creg[0] <= c;
 | 
	
		
			
				|  |  | -	  creg[1] <= creg[0];
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -	  if (denreg[1])
 | 
	
		
			
				|  |  | -	    begin
 | 
	
		
			
				|  |  | -	       qreg <= romq[9:0] ^ (invert ? 10'h2ff : 10'h000);
 | 
	
		
			
				|  |  | -	       disparity <= invert ?
 | 
	
		
			
				|  |  | -			    disparity - romq[15:12] :
 | 
	
		
			
				|  |  | -			    disparity + romq[15:12];
 | 
	
		
			
				|  |  | -	    end
 | 
	
		
			
				|  |  | -	  else
 | 
	
		
			
				|  |  | -	    begin
 | 
	
		
			
				|  |  | -	       qreg <= { cx, {4{cn, cp}}, cp };
 | 
	
		
			
				|  |  | -	       disparity <= 4'd0;
 | 
	
		
			
				|  |  | -	    end // else: !if(den)
 | 
	
		
			
				|  |  | -       end // else: !if(~rst_n)
 | 
	
		
			
				|  |  | -endmodule // tmdsenc
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | -`else // not USE_TMDSROM
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  |  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 [1:0]	c, // Control word
 | 
	
		
			
				|  |  | +   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
 | 
	
		
			
				|  |  |     output [9:0] q
 | 
	
		
			
				|  |  |     );
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -   reg signed [3:0] disparity; // Running disparity/2
 | 
	
		
			
				|  |  | -   reg [9:0]	    qreg = 10'b11010101000; // Symbol C0
 | 
	
		
			
				|  |  | +   // 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;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// 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
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   reg signed [4:0] disparity; // Running disparity/2
 | 
	
		
			
				|  |  | +   reg [9:0]	    qreg;
 | 
	
		
			
				|  |  |     assign q = qreg;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |     reg [7:0]	    dreg;
 | 
	
		
			
				|  |  |     reg		    denreg;
 | 
	
		
			
				|  |  | -   reg [1:0]	    creg;
 | 
	
		
			
				|  |  | +   reg [3:0]	    creg;
 | 
	
		
			
				|  |  | +   reg		    tercenreg;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -   wire signed [2:0] delta =
 | 
	
		
			
				|  |  | -	((dreg[7] + dreg[6]) + (dreg[5] + dreg[4])) +
 | 
	
		
			
				|  |  | -	((dreg[3] + dreg[2]) + (dreg[1] + dreg[0])) - 3'sd4;
 | 
	
		
			
				|  |  | +   wire signed [3:0] ddisp =
 | 
	
		
			
				|  |  | +	dreg[7] + dreg[6] + dreg[5] + dreg[4] +
 | 
	
		
			
				|  |  | +	dreg[3] + dreg[2] + dreg[1] + dreg[0] - 'sd4;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |     reg [8:0]	     dx;		// X(N)OR stage output
 | 
	
		
			
				|  |  | -   always @(*)
 | 
	
		
			
				|  |  | +   wire signed [3:0] xdisp =		// Does not include dx[8]!
 | 
	
		
			
				|  |  | +	dx[7] + dx[6] + dx[5] + dx[4] +
 | 
	
		
			
				|  |  | +	dx[3] + dx[2] + dx[1] + dx[0] - 'sd4;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   always_comb
 | 
	
		
			
				|  |  |       begin
 | 
	
		
			
				|  |  | -	dx[8] = (delta > 3'sd0) | (~&delta & ~dreg[0]);
 | 
	
		
			
				|  |  | +	dx[8] = $signed(ddisp | { 3'd0, ~dreg[0] }) <= 4'sd0;
 | 
	
		
			
				|  |  |  	dx[0] = dreg[0];
 | 
	
		
			
				|  |  |  	dx[1] = dx[0] ^ dreg[1] ^ ~dx[8];
 | 
	
		
			
				|  |  |  	dx[2] = dx[1] ^ dreg[2] ^ ~dx[8];
 | 
	
	
		
			
				|  | @@ -106,50 +78,47 @@ module tmdsenc
 | 
	
		
			
				|  |  |  	dx[7] = dx[6] ^ dreg[7] ^ ~dx[8];
 | 
	
		
			
				|  |  |       end // always @ (*)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -   wire cp =  creg[0];
 | 
	
		
			
				|  |  | -   wire cn = ~creg[0];
 | 
	
		
			
				|  |  | -   wire cx = ~creg[0] ^ creg[1];	// XNOR of c[1] and c[0]
 | 
	
		
			
				|  |  | +   reg [9:0] dq;		// Disparity stage output
 | 
	
		
			
				|  |  | +   reg	     dispsign;		// Disparity counter up or down
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   always_comb
 | 
	
		
			
				|  |  | +     begin
 | 
	
		
			
				|  |  | +	dq[9]   = ((disparity == 5'sd0) | (xdisp == 4'sd0))
 | 
	
		
			
				|  |  | +	  ? ~dx[8] : ( disparity[4] == xdisp[3] );
 | 
	
		
			
				|  |  | +	dq[8]   = dx[8];
 | 
	
		
			
				|  |  | +	dq[7:0] = dx[7:0] ^ {{8{dq[9]}}};
 | 
	
		
			
				|  |  | +     end
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +   wire signed [3:0] qdisp =
 | 
	
		
			
				|  |  | +	dq[9] + dq[8] + dq[7] + dq[6] + dq[5] +
 | 
	
		
			
				|  |  | +	dq[4] + dq[3] + dq[2] + dq[1] + dq[0] - 'sd5;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |     always @(negedge rst_n or posedge clk)
 | 
	
		
			
				|  |  |       if (~rst_n)
 | 
	
		
			
				|  |  |         begin
 | 
	
		
			
				|  |  | -	  disparity <= 4'sd0;
 | 
	
		
			
				|  |  | -	  qreg      <= 10'b11010101000;
 | 
	
		
			
				|  |  | -	  dreg      <= 8'hxx;
 | 
	
		
			
				|  |  | +	  dreg      <= 'b0;
 | 
	
		
			
				|  |  | +	  disparity <= 'sd0;
 | 
	
		
			
				|  |  | +	  qreg      <= csym(1'b0, 4'b0000);
 | 
	
		
			
				|  |  |  	  denreg    <= 1'b0;
 | 
	
		
			
				|  |  |  	  creg      <= 2'b00;
 | 
	
		
			
				|  |  | +	  tercenreg <= 1'b0;
 | 
	
		
			
				|  |  |         end
 | 
	
		
			
				|  |  |       else
 | 
	
		
			
				|  |  |         begin
 | 
	
		
			
				|  |  | -	  denreg <= den;
 | 
	
		
			
				|  |  | -	  creg   <= c;
 | 
	
		
			
				|  |  | -	  dreg   <= d;
 | 
	
		
			
				|  |  | +	  denreg    <= den;
 | 
	
		
			
				|  |  | +	  tercenreg <= tercen;
 | 
	
		
			
				|  |  | +	  creg      <= c;
 | 
	
		
			
				|  |  | +	  dreg      <= d;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  	  if (denreg)
 | 
	
		
			
				|  |  |  	    begin
 | 
	
		
			
				|  |  | -	       if ( (disparity == 4'sd0) | (delta == 3'sd0) )
 | 
	
		
			
				|  |  | -		 begin
 | 
	
		
			
				|  |  | -		    qreg <= { ~dx[8], dx[8], dx[7:0] ^ ~{8{dx[8]}} };
 | 
	
		
			
				|  |  | -	            disparity <= dx[8] ?
 | 
	
		
			
				|  |  | -			    disparity + delta :
 | 
	
		
			
				|  |  | -			    disparity - delta;
 | 
	
		
			
				|  |  | -	         end
 | 
	
		
			
				|  |  | -	       else if ( disparity[3] ^ ~delta[2] )
 | 
	
		
			
				|  |  | -		 begin
 | 
	
		
			
				|  |  | -		    qreg <= { 1'b1, dx[8], ~dx[7:0] };
 | 
	
		
			
				|  |  | -		    disparity <= disparity - (delta - dx[8]);
 | 
	
		
			
				|  |  | -		 end
 | 
	
		
			
				|  |  | -	       else
 | 
	
		
			
				|  |  | -		 begin
 | 
	
		
			
				|  |  | -		    qreg <= { 1'b0, dx[8], dx[7:0] };
 | 
	
		
			
				|  |  | -		    disparity <= disparity + (delta - ~dx[8]);
 | 
	
		
			
				|  |  | -		 end
 | 
	
		
			
				|  |  | -	    end // if (den)
 | 
	
		
			
				|  |  | +	       qreg <= dq;
 | 
	
		
			
				|  |  | +	       disparity <= disparity + qdisp;
 | 
	
		
			
				|  |  | +	    end
 | 
	
		
			
				|  |  |  	  else
 | 
	
		
			
				|  |  |  	    begin
 | 
	
		
			
				|  |  | -	       qreg <= { cx, {4{cn, cp}}, cp };
 | 
	
		
			
				|  |  | -	       disparity <= 4'sd0;
 | 
	
		
			
				|  |  | -	    end // else: !if(den)
 | 
	
		
			
				|  |  | +	       qreg <= csym(tercenreg, creg);
 | 
	
		
			
				|  |  | +	       disparity <= 'sd0;
 | 
	
		
			
				|  |  | +	    end
 | 
	
		
			
				|  |  |         end // else: !if(~rst_n)
 | 
	
		
			
				|  |  |  endmodule // tmdsenc
 | 
	
		
			
				|  |  | -`endif
 |