aboutsummaryrefslogtreecommitdiffstats
path: root/rx
diff options
context:
space:
mode:
Diffstat (limited to 'rx')
-rwxr-xr-xrx/chnlbond.v170
-rwxr-xr-xrx/decode.v271
-rwxr-xr-xrx/decode_terc4.v66
-rwxr-xr-xrx/decodeb.v319
-rwxr-xr-xrx/decodeg.v319
-rwxr-xr-xrx/decoder.v318
-rwxr-xr-xrx/dvi_decoder.v634
-rwxr-xr-xrx/phsaligner.v301
-rwxr-xr-xrx/serdes_1_to_5_diff_data.v405
9 files changed, 2803 insertions, 0 deletions
diff --git a/rx/chnlbond.v b/rx/chnlbond.v
new file mode 100755
index 0000000..c497d86
--- /dev/null
+++ b/rx/chnlbond.v
@@ -0,0 +1,170 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// Xilinx, Inc. 2007 www.xilinx.com
+//
+// XAPP xxx
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// File name : chnlbond.v
+//
+// Description : Channel Bonding Logic
+// TMDS channel de-skew
+//
+// Author : Bob Feng
+//
+// Disclaimer: LIMITED WARRANTY AND DISCLAMER. These designs are
+// provided to you "as is". Xilinx and its licensors makeand you
+// receive no warranties or conditions, express, implied,
+// statutory or otherwise, and Xilinx specificallydisclaims any
+// implied warranties of merchantability, non-infringement,or
+// fitness for a particular purpose. Xilinx does notwarrant that
+// the functions contained in these designs will meet your
+// requirements, or that the operation of these designswill be
+// uninterrupted or error free, or that defects in theDesigns
+// will be corrected. Furthermore, Xilinx does not warrantor
+// make any representations regarding use or the results ofthe
+// 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 forany
+// special, incidental, consequential, or indirect damages
+// arising from the use or operation of the designs or
+// accompanying documentation, however caused and on anytheory
+// 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 ofthe
+// essential purpose of any limited remedies herein.
+//
+// Copyright © 2004 Xilinx, Inc.
+// All rights reserved
+//
+//////////////////////////////////////////////////////////////////////////////
+`timescale 1 ns / 1ps
+
+module chnlbond (
+ input wire clk,
+ input wire [9:0] rawdata,
+ input wire iamvld,
+ input wire other_ch0_vld,
+ input wire other_ch1_vld,
+ input wire other_ch0_rdy,
+ input wire other_ch1_rdy,
+ output reg iamrdy,
+ output reg [9:0] sdata
+);
+
+ parameter CTRLTOKEN0 = 10'b1101010100;
+ parameter CTRLTOKEN1 = 10'b0010101011;
+ parameter CTRLTOKEN2 = 10'b0101010100;
+ parameter CTRLTOKEN3 = 10'b1010101011;
+
+ wire rawdata_vld;
+ assign rawdata_vld = other_ch0_vld & other_ch1_vld & iamvld;
+
+ reg [3:0] wa, ra;
+ reg we;
+
+ ////////////////////////////////////////////////////////
+ // FIFO Write Control Logic
+ ////////////////////////////////////////////////////////
+ always @ (posedge clk) begin
+ we <=#1 rawdata_vld;
+ end
+
+ always @ (posedge clk) begin
+ if(rawdata_vld)
+ wa <=#1 wa + 1'b1;
+ else
+ wa <=#1 4'h0;
+ end
+
+ wire [9:0] dpfo_dout;
+ DRAM16XN #(.data_width(10))
+ cbfifo_i (
+ .DATA_IN(rawdata),
+ .ADDRESS(wa),
+ .ADDRESS_DP(ra),
+ .WRITE_EN(we),
+ .CLK(clk),
+ .O_DATA_OUT(),
+ .O_DATA_OUT_DP(dpfo_dout));
+
+ always @ (posedge clk) begin
+ sdata <=#1 dpfo_dout;
+ end
+
+ ////////////////////////////////////////////////////////
+ // FIFO read Control Logic
+ ////////////////////////////////////////////////////////
+
+ ////////////////////////////////
+ // Use blank period beginning
+ // as a speical marker to
+ // align all channel together
+ ////////////////////////////////
+ reg rcvd_ctkn, rcvd_ctkn_q; //received control token
+ reg blnkbgn; //blank period begins
+ always @ (posedge clk) begin
+ rcvd_ctkn <=#1 ((sdata == CTRLTOKEN0) || (sdata == CTRLTOKEN1) || (sdata == CTRLTOKEN2) || (sdata == CTRLTOKEN3));
+ rcvd_ctkn_q <=#1 rcvd_ctkn;
+ blnkbgn <=#1 !rcvd_ctkn_q & rcvd_ctkn;
+ end
+
+ /////////////////////////////
+ //skip the current line
+ /////////////////////////////
+ wire next_blnkbgn;
+ reg skip_line;
+ always @ (posedge clk) begin
+ if(!rawdata_vld)
+ skip_line <=#1 1'b0;
+ else if(blnkbgn)
+ skip_line <=#1 1'b1;
+ end
+
+ assign next_blnkbgn = skip_line & blnkbgn;
+
+ //////////////////////////////
+ //Declare my own readiness
+ //////////////////////////////
+ always @ (posedge clk) begin
+ if(!rawdata_vld)
+ iamrdy <=#1 1'b0;
+ else if(next_blnkbgn)
+ iamrdy <=#1 1'b1;
+ end
+
+ reg rawdata_vld_q;
+ reg rawdata_vld_rising;
+ always @ (posedge clk) begin
+ rawdata_vld_q <=#1 rawdata_vld;
+ rawdata_vld_rising <=#1 rawdata_vld & !rawdata_vld_q;
+ end
+
+ //////////////////////////////////////////////////////////////////////////////////////////
+ // 1. FIFO flow through first when all channels are found valid(phase aligned)
+ // 2. When the speical marker on my channel is found, the fifo read is hold
+ // 3. Until the same markers are found across all three channels, the fifo read resumes
+ //////////////////////////////////////////////////////////////////////////////////////////
+ reg ra_en = 1'b0;
+ always @ (posedge clk) begin
+ if(rawdata_vld_rising || (other_ch0_rdy & other_ch1_rdy & iamrdy))
+ ra_en <=#1 1'b1;
+ else if(next_blnkbgn && !(other_ch0_rdy & other_ch1_rdy & iamrdy))
+ ra_en <=#1 1'b0;
+ end
+
+ /////////////////////////////////////////
+ //FIFO Read Address Counter
+ /////////////////////////////////////////
+ always @ (posedge clk) begin
+ if(!rawdata_vld)
+ ra <=#1 4'h0;
+ else if(ra_en)
+ ra <=#1 ra + 1'b1;
+ end
+
+endmodule
diff --git a/rx/decode.v b/rx/decode.v
new file mode 100755
index 0000000..6e5a7e0
--- /dev/null
+++ b/rx/decode.v
@@ -0,0 +1,271 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// Xilinx, Inc. 2010 www.xilinx.com
+//
+// XAPP xxx
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// File name : decoder.v
+//
+// Description : Spartan-6 dvi decoder
+//
+//
+// Author : Bob Feng
+//
+// Disclaimer: LIMITED WARRANTY AND DISCLAMER. These designs are
+// provided to you "as is". Xilinx and its licensors makeand you
+// receive no warranties or conditions, express, implied,
+// statutory or otherwise, and Xilinx specificallydisclaims any
+// implied warranties of merchantability, non-infringement,or
+// fitness for a particular purpose. Xilinx does notwarrant that
+// the functions contained in these designs will meet your
+// requirements, or that the operation of these designswill be
+// uninterrupted or error free, or that defects in theDesigns
+// will be corrected. Furthermore, Xilinx does not warrantor
+// make any representations regarding use or the results ofthe
+// 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 forany
+// special, incidental, consequential, or indirect damages
+// arising from the use or operation of the designs or
+// accompanying documentation, however caused and on anytheory
+// 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 ofthe
+// essential purpose of any limited remedies herein.
+//
+// Copyright © 2004 Xilinx, Inc.
+// All rights reserved
+//
+//////////////////////////////////////////////////////////////////////////////
+`timescale 1 ns / 1ps
+
+module decode (
+ input wire reset, //
+ input wire pclk, // pixel clock
+ input wire pclkx2, // double pixel rate for gear box
+ input wire pclkx10, // IOCLK
+ input wire serdesstrobe, // serdesstrobe for iserdes2
+ input wire din_p, // data from dvi cable
+ input wire din_n, // data from dvi cable
+ input wire other_ch0_vld, // other channel0 has valid data now
+ input wire other_ch1_vld, // other channel1 has valid data now
+ input wire other_ch0_rdy, // other channel0 has detected a valid starting pixel
+ input wire other_ch1_rdy, // other channel1 has detected a valid starting pixel
+
+ output wire iamvld, // I have valid data now
+ output wire iamrdy, // I have detected a valid new pixel
+ output wire psalgnerr, // Phase alignment error
+ output reg c0,
+ output reg c1,
+ output reg de,
+ output reg [9:0] sdout,
+ output reg [7:0] dout,
+ output reg dgb,
+ output reg vgb);
+
+ ////////////////////////////////
+ //
+ // 5-bit to 10-bit gear box
+ //
+ ////////////////////////////////
+ wire flipgear;
+ reg flipgearx2;
+
+ always @ (posedge pclkx2) begin
+ flipgearx2 <=#1 flipgear;
+ end
+
+ reg toggle = 1'b0;
+
+ always @ (posedge pclkx2 or posedge reset)
+ if (reset == 1'b1) begin
+ toggle <= 1'b0 ;
+ end else begin
+ toggle <=#1 ~toggle;
+ end
+
+ wire rx_toggle;
+
+ assign rx_toggle = toggle ^ flipgearx2; //reverse hi-lo position
+
+ wire [4:0] raw5bit;
+ reg [4:0] raw5bit_q;
+ reg [9:0] rawword;
+
+ always @ (posedge pclkx2) begin
+ raw5bit_q <=#1 raw5bit;
+
+ if(rx_toggle) //gear from 5 bit to 10 bit
+ rawword <=#1 {raw5bit, raw5bit_q};
+ end
+
+ ////////////////////////////////
+ //
+ // bitslip signal sync to pclkx2
+ //
+ ////////////////////////////////
+ reg bitslipx2 = 1'b0;
+ reg bitslip_q = 1'b0;
+ wire bitslip;
+
+ always @ (posedge pclkx2) begin
+ bitslip_q <=#1 bitslip;
+ bitslipx2 <=#1 bitslip & !bitslip_q;
+ end
+
+ /////////////////////////////////////////////
+ //
+ // 1:5 de-serializer working at x2 pclk rate
+ //
+ /////////////////////////////////////////////
+ serdes_1_to_5_diff_data # (
+ .DIFF_TERM("FALSE"),
+ .BITSLIP_ENABLE("TRUE")
+ ) des_0 (
+ .use_phase_detector(1'b1),
+ .datain_p(din_p),
+ .datain_n(din_n),
+ .rxioclk(pclkx10),
+ .rxserdesstrobe(serdesstrobe),
+ .reset(reset),
+ .gclk(pclkx2),
+ .bitslip(bitslipx2),
+ .data_out(raw5bit)
+ );
+
+ /////////////////////////////////////////////////////
+ // Doing word boundary detection here
+ /////////////////////////////////////////////////////
+ wire [9:0] rawdata = rawword;
+
+ ///////////////////////////////////////
+ // Phase Alignment Instance
+ ///////////////////////////////////////
+ phsaligner phsalgn_0 (
+ .rst(reset),
+ .clk(pclk),
+ .sdata(rawdata),
+ .bitslip(bitslip),
+ .flipgear(flipgear),
+ .psaligned(iamvld)
+ );
+
+ assign psalgnerr = 1'b0;
+
+ ///////////////////////////////////////
+ // Per Channel De-skew Instance
+ ///////////////////////////////////////
+ wire [9:0] sdata;
+ chnlbond cbnd (
+ .clk(pclk),
+ .rawdata(rawdata),
+ .iamvld(iamvld),
+ .other_ch0_vld(other_ch0_vld),
+ .other_ch1_vld(other_ch1_vld),
+ .other_ch0_rdy(other_ch0_rdy),
+ .other_ch1_rdy(other_ch1_rdy),
+ .iamrdy(iamrdy),
+ .sdata(sdata)
+ );
+
+ /////////////////////////////////////////////////////////////////
+ // Below performs the 10B-8B decoding function defined in DVI 1.0
+ // Specification: Section 3.3.3, Figure 3-6, page 31.
+ /////////////////////////////////////////////////////////////////
+ // Distinct Control Tokens
+ parameter CTRLTOKEN0 = 10'b1101010100;
+ parameter CTRLTOKEN1 = 10'b0010101011;
+ parameter CTRLTOKEN2 = 10'b0101010100;
+ parameter CTRLTOKEN3 = 10'b1010101011;
+
+ parameter DATA_GB = 10'b0100110011;
+ parameter VID_B_GB = 10'b1011001100;
+ parameter VID_G_GB = 10'b0100110011;
+ parameter VID_R_GB = 10'b1011001100;
+
+ wire [7:0] data;
+ assign data = (sdata[9]) ? ~sdata[7:0] : sdata[7:0];
+
+ always @ (posedge pclk) begin
+ if(iamrdy && other_ch0_rdy && other_ch1_rdy) begin
+ case (sdata)
+ CTRLTOKEN0: begin
+ c0 <=#1 1'b0;
+ c1 <=#1 1'b0;
+ de <=#1 1'b0;
+ dgb <= #1 1'b0;
+ vgb <= #1 1'b0;
+ end
+
+ CTRLTOKEN1: begin
+ c0 <=#1 1'b1;
+ c1 <=#1 1'b0;
+ de <=#1 1'b0;
+ dgb <= #1 1'b0;
+ vgb <= #1 1'b0;
+ end
+
+ CTRLTOKEN2: begin
+ c0 <=#1 1'b0;
+ c1 <=#1 1'b1;
+ de <=#1 1'b0;
+ dgb <= #1 1'b0;
+ vgb <= #1 1'b0;
+ end
+
+ CTRLTOKEN3: begin
+ c0 <=#1 1'b1;
+ c1 <=#1 1'b1;
+ de <=#1 1'b0;
+ dgb <= #1 1'b0;
+ vgb <= #1 1'b0;
+ end
+
+ DATA_GB: begin
+ c0 <=#1 1'b0;
+ c1 <=#1 1'b0;
+ de <=#1 1'b0;
+ dgb <= #1 1'b1;
+ vgb <= #1 1'b0;
+ end
+
+ VID_B_GB: begin
+ c0 <=#1 1'b0;
+ c1 <=#1 1'b0;
+ de <=#1 1'b0;
+ dgb <= #1 1'b0;
+ vgb <= #1 1'b1;
+ end
+
+ default: begin
+ dout[0] <=#1 data[0];
+ dout[1] <=#1 (sdata[8]) ? (data[1] ^ data[0]) : (data[1] ~^ data[0]);
+ dout[2] <=#1 (sdata[8]) ? (data[2] ^ data[1]) : (data[2] ~^ data[1]);
+ dout[3] <=#1 (sdata[8]) ? (data[3] ^ data[2]) : (data[3] ~^ data[2]);
+ dout[4] <=#1 (sdata[8]) ? (data[4] ^ data[3]) : (data[4] ~^ data[3]);
+ dout[5] <=#1 (sdata[8]) ? (data[5] ^ data[4]) : (data[5] ~^ data[4]);
+ dout[6] <=#1 (sdata[8]) ? (data[6] ^ data[5]) : (data[6] ~^ data[5]);
+ dout[7] <=#1 (sdata[8]) ? (data[7] ^ data[6]) : (data[7] ~^ data[6]);
+
+ de <=#1 1'b1;
+
+ dgb <= #1 1'b0;
+ vgb <= #1 1'b0;
+ end
+ endcase
+
+ sdout <=#1 sdata;
+ end else begin
+ c0 <= 1'b0;
+ c1 <= 1'b0;
+ de <= 1'b0;
+ dout <= 8'h0;
+ sdout <= 10'h0;
+ end
+ end
+endmodule
diff --git a/rx/decode_terc4.v b/rx/decode_terc4.v
new file mode 100755
index 0000000..2c0f5a8
--- /dev/null
+++ b/rx/decode_terc4.v
@@ -0,0 +1,66 @@
+//////////////////////////////////////////////////////////////////////////////
+// Copyright (c) 2011, Andrew "bunnie" Huang
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation and/or
+// other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+`timescale 1 ps / 1ps
+
+module decode_terc4 (
+ input clkin, // pixel clock input
+ input rstin, // async. reset input (active high)
+ input [9:0] din, // data inputs: expect registered
+ output reg [3:0] dout // data outputs
+);
+ reg [9:0] din_r;
+
+ always @(posedge clkin or posedge rstin) begin
+ if( rstin ) begin
+ dout[3:0] <= 4'h0;
+ din_r <= 10'b0;
+ end else begin
+ din_r <= din;
+ case (din_r[9:0])
+ 10'b1010011100: dout[3:0] <= 4'b0000;
+ 10'b1001100011: dout[3:0] <= 4'b0001;
+ 10'b1011100100: dout[3:0] <= 4'b0010;
+ 10'b1011100010: dout[3:0] <= 4'b0011;
+ 10'b0101110001: dout[3:0] <= 4'b0100;
+ 10'b0100011110: dout[3:0] <= 4'b0101;
+ 10'b0110001110: dout[3:0] <= 4'b0110;
+ 10'b0100111100: dout[3:0] <= 4'b0111;
+ 10'b1011001100: dout[3:0] <= 4'b1000;
+ 10'b0100111001: dout[3:0] <= 4'b1001;
+ 10'b0110011100: dout[3:0] <= 4'b1010;
+ 10'b1011000110: dout[3:0] <= 4'b1011;
+ 10'b1010001110: dout[3:0] <= 4'b1100;
+ 10'b1001110001: dout[3:0] <= 4'b1101;
+ 10'b0101100011: dout[3:0] <= 4'b1110;
+ 10'b1011000011: dout[3:0] <= 4'b1111;
+ // no default to allow for maximum coding flexibility...
+ endcase // case (din_q)
+ end // else: !if( rstin )
+ end // always @ (posedge clkin or posedge rstin)
+
+endmodule // decode_terc4
+
diff --git a/rx/decodeb.v b/rx/decodeb.v
new file mode 100755
index 0000000..813a111
--- /dev/null
+++ b/rx/decodeb.v
@@ -0,0 +1,319 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// Xilinx, Inc. 2010 www.xilinx.com
+//
+// XAPP xxx
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// File name : decoder.v
+//
+// Description : Spartan-6 dvi decoder
+//
+//
+// Author : Bob Feng
+//
+// Disclaimer: LIMITED WARRANTY AND DISCLAMER. These designs are
+// provided to you "as is". Xilinx and its licensors makeand you
+// receive no warranties or conditions, express, implied,
+// statutory or otherwise, and Xilinx specificallydisclaims any
+// implied warranties of merchantability, non-infringement,or
+// fitness for a particular purpose. Xilinx does notwarrant that
+// the functions contained in these designs will meet your
+// requirements, or that the operation of these designswill be
+// uninterrupted or error free, or that defects in theDesigns
+// will be corrected. Furthermore, Xilinx does not warrantor
+// make any representations regarding use or the results ofthe
+// 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 forany
+// special, incidental, consequential, or indirect damages
+// arising from the use or operation of the designs or
+// accompanying documentation, however caused and on anytheory
+// 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 ofthe
+// essential purpose of any limited remedies herein.
+//
+// Copyright © 2004 Xilinx, Inc.
+// All rights reserved
+//
+//////////////////////////////////////////////////////////////////////////////
+// Modifications copyright (c) 2011, Andrew "bunnie" Huang
+// All rights reserved as permitted by law.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation and/or
+// other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+`timescale 1 ns / 1ps
+
+module decodeb (
+ input wire reset, //
+ input wire pclk, // pixel clock
+ input wire pclkx2, // double pixel rate for gear box
+ input wire pclkx10, // IOCLK
+ input wire serdesstrobe, // serdesstrobe for iserdes2
+ input wire din_p, // data from dvi cable
+ input wire din_n, // data from dvi cable
+ input wire other_ch0_vld, // other channel0 has valid data now
+ input wire other_ch1_vld, // other channel1 has valid data now
+ input wire other_ch0_rdy, // other channel0 has detected a valid starting pixel
+ input wire other_ch1_rdy, // other channel1 has detected a valid starting pixel
+
+ output wire iamvld, // I have valid data now
+ output wire iamrdy, // I have detected a valid new pixel
+ output wire psalgnerr, // Phase alignment error
+ output reg c0,
+ output reg c1,
+ output reg de,
+ output reg [9:0] sdout,
+ output reg [7:0] dout,
+ output reg dgb,
+ output reg vgb,
+ output reg ctl_vld,
+ output wire line_end);
+
+ ////////////////////////////////
+ //
+ // 5-bit to 10-bit gear box
+ //
+ ////////////////////////////////
+ wire flipgear;
+ reg flipgearx2;
+
+ always @ (posedge pclkx2) begin
+ flipgearx2 <=#1 flipgear;
+ end
+
+ reg toggle = 1'b0;
+
+ always @ (posedge pclkx2 or posedge reset)
+ if (reset == 1'b1) begin
+ toggle <= 1'b0 ;
+ end else begin
+ toggle <=#1 ~toggle;
+ end
+
+ wire rx_toggle;
+
+ assign rx_toggle = toggle ^ flipgearx2; //reverse hi-lo position
+
+ wire [4:0] raw5bit;
+ reg [4:0] raw5bit_q;
+ reg [9:0] rawword;
+
+ always @ (posedge pclkx2) begin
+ raw5bit_q <=#1 raw5bit;
+
+ if(rx_toggle) //gear from 5 bit to 10 bit
+ rawword <=#1 {raw5bit, raw5bit_q};
+ end
+
+ ////////////////////////////////
+ //
+ // bitslip signal sync to pclkx2
+ //
+ ////////////////////////////////
+ reg bitslipx2 = 1'b0;
+ reg bitslip_q = 1'b0;
+ wire bitslip;
+
+ always @ (posedge pclkx2) begin
+ bitslip_q <=#1 bitslip;
+ bitslipx2 <=#1 bitslip & !bitslip_q;
+ end
+
+ /////////////////////////////////////////////
+ //
+ // 1:5 de-serializer working at x2 pclk rate
+ //
+ /////////////////////////////////////////////
+ serdes_1_to_5_diff_data # (
+ .DIFF_TERM("FALSE"),
+ .BITSLIP_ENABLE("TRUE")
+ ) des_0 (
+ .use_phase_detector(1'b1),
+ .datain_p(din_p),
+ .datain_n(din_n),
+ .rxioclk(pclkx10),
+ .rxserdesstrobe(serdesstrobe),
+ .reset(reset),
+ .gclk(pclkx2),
+ .bitslip(bitslipx2),
+ .data_out(raw5bit)
+ );
+
+ /////////////////////////////////////////////////////
+ // Doing word boundary detection here
+ /////////////////////////////////////////////////////
+ wire [9:0] rawdata = rawword;
+
+ ///////////////////////////////////////
+ // Phase Alignment Instance
+ ///////////////////////////////////////
+ phsaligner phsalgn_0 (
+ .rst(reset),
+ .clk(pclk),
+ .sdata(rawdata),
+ .bitslip(bitslip),
+ .flipgear(flipgear),
+ .psaligned(iamvld)
+ );
+
+ assign psalgnerr = 1'b0;
+
+ ///////////////////////////////////////
+ // Per Channel De-skew Instance
+ ///////////////////////////////////////
+ wire [9:0] sdata;
+ chnlbond cbnd (
+ .clk(pclk),
+ .rawdata(rawdata),
+ .iamvld(iamvld),
+ .other_ch0_vld(other_ch0_vld),
+ .other_ch1_vld(other_ch1_vld),
+ .other_ch0_rdy(other_ch0_rdy),
+ .other_ch1_rdy(other_ch1_rdy),
+ .iamrdy(iamrdy),
+ .sdata(sdata)
+ );
+
+ ////
+ // hack to accelerate detection of line end so that HDCP rekey
+ // can meet stringent timing spec requirement
+ ////
+ assign line_end = de &&
+ ((sdata == CTRLTOKEN0) ||
+ (sdata == CTRLTOKEN1) ||
+ (sdata == CTRLTOKEN2) ||
+ (sdata == CTRLTOKEN3));
+
+ /////////////////////////////////////////////////////////////////
+ // Below performs the 10B-8B decoding function defined in DVI 1.0
+ // Specification: Section 3.3.3, Figure 3-6, page 31.
+ /////////////////////////////////////////////////////////////////
+ // Distinct Control Tokens
+ parameter CTRLTOKEN0 = 10'b1101010100;
+ parameter CTRLTOKEN1 = 10'b0010101011;
+ parameter CTRLTOKEN2 = 10'b0101010100;
+ parameter CTRLTOKEN3 = 10'b1010101011;
+
+ parameter DATA_GB = 10'b0100110011;
+ parameter VID_B_GB = 10'b1011001100;
+ parameter VID_G_GB = 10'b0100110011;
+ parameter VID_R_GB = 10'b1011001100;
+
+ wire [7:0] data;
+ assign data = (sdata[9]) ? ~sdata[7:0] : sdata[7:0];
+
+ always @ (posedge pclk) begin
+ if(iamrdy && other_ch0_rdy && other_ch1_rdy) begin
+ case (sdata)
+ CTRLTOKEN0: begin
+ c0 <=#1 1'b0;
+ c1 <=#1 1'b0;
+ de <=#1 1'b0;
+ dgb <= #1 1'b0;
+ vgb <= #1 1'b0;
+ ctl_vld <= #1 1'b1;
+ end
+
+ CTRLTOKEN1: begin
+ c0 <=#1 1'b1;
+ c1 <=#1 1'b0;
+ de <=#1 1'b0;
+ dgb <= #1 1'b0;
+ vgb <= #1 1'b0;
+ ctl_vld <= #1 1'b1;
+ end
+
+ CTRLTOKEN2: begin
+ c0 <=#1 1'b0;
+ c1 <=#1 1'b1;
+ de <=#1 1'b0;
+ dgb <= #1 1'b0;
+ vgb <= #1 1'b0;
+ ctl_vld <= #1 1'b1;
+ end
+
+ CTRLTOKEN3: begin
+ c0 <=#1 1'b1;
+ c1 <=#1 1'b1;
+ de <=#1 1'b0;
+ dgb <= #1 1'b0;
+ vgb <= #1 1'b0;
+ ctl_vld <= #1 1'b1;
+ end
+
+ DATA_GB: begin
+ c0 <=#1 1'b0;
+ c1 <=#1 1'b0;
+ de <=#1 1'b0;
+ dgb <= #1 1'b1;
+ vgb <= #1 1'b0;
+ ctl_vld <= #1 1'b0;
+ end
+
+ VID_B_GB: begin
+ c0 <=#1 1'b0;
+ c1 <=#1 1'b0;
+ de <=#1 1'b0;
+ dgb <= #1 1'b0;
+ vgb <= #1 1'b1;
+ ctl_vld <= #1 1'b0;
+ end
+
+ default: begin
+ dout[0] <=#1 data[0];
+ dout[1] <=#1 (sdata[8]) ? (data[1] ^ data[0]) : (data[1] ~^ data[0]);
+ dout[2] <=#1 (sdata[8]) ? (data[2] ^ data[1]) : (data[2] ~^ data[1]);
+ dout[3] <=#1 (sdata[8]) ? (data[3] ^ data[2]) : (data[3] ~^ data[2]);
+ dout[4] <=#1 (sdata[8]) ? (data[4] ^ data[3]) : (data[4] ~^ data[3]);
+ dout[5] <=#1 (sdata[8]) ? (data[5] ^ data[4]) : (data[5] ~^ data[4]);
+ dout[6] <=#1 (sdata[8]) ? (data[6] ^ data[5]) : (data[6] ~^ data[5]);
+ dout[7] <=#1 (sdata[8]) ? (data[7] ^ data[6]) : (data[7] ~^ data[6]);
+
+ de <=#1 1'b1;
+
+ dgb <= #1 1'b0;
+ vgb <= #1 1'b0;
+ ctl_vld <= #1 1'b0;
+ end
+ endcase
+
+ sdout <=#1 sdata;
+ end else begin
+ c0 <= 1'b0;
+ c1 <= 1'b0;
+ de <= 1'b0;
+ dout <= 8'h0;
+ sdout <= 10'h0;
+
+ dgb <= 1'b0;
+ vgb <= 1'b0;
+ ctl_vld <= 1'b0;
+ end
+ end
+endmodule
diff --git a/rx/decodeg.v b/rx/decodeg.v
new file mode 100755
index 0000000..6d86925
--- /dev/null
+++ b/rx/decodeg.v
@@ -0,0 +1,319 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// Xilinx, Inc. 2010 www.xilinx.com
+//
+// XAPP xxx
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// File name : decoder.v
+//
+// Description : Spartan-6 dvi decoder
+//
+//
+// Author : Bob Feng
+//
+// Disclaimer: LIMITED WARRANTY AND DISCLAMER. These designs are
+// provided to you "as is". Xilinx and its licensors makeand you
+// receive no warranties or conditions, express, implied,
+// statutory or otherwise, and Xilinx specificallydisclaims any
+// implied warranties of merchantability, non-infringement,or
+// fitness for a particular purpose. Xilinx does notwarrant that
+// the functions contained in these designs will meet your
+// requirements, or that the operation of these designswill be
+// uninterrupted or error free, or that defects in theDesigns
+// will be corrected. Furthermore, Xilinx does not warrantor
+// make any representations regarding use or the results ofthe
+// 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 forany
+// special, incidental, consequential, or indirect damages
+// arising from the use or operation of the designs or
+// accompanying documentation, however caused and on anytheory
+// 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 ofthe
+// essential purpose of any limited remedies herein.
+//
+// Copyright © 2004 Xilinx, Inc.
+// All rights reserved
+//
+//////////////////////////////////////////////////////////////////////////////
+// Modifications copyright (c) 2011, Andrew "bunnie" Huang
+// All rights reserved as permitted by law.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation and/or
+// other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+`timescale 1 ns / 1ps
+
+module decodeg (
+ input wire reset, //
+ input wire pclk, // pixel clock
+ input wire pclkx2, // double pixel rate for gear box
+ input wire pclkx10, // IOCLK
+ input wire serdesstrobe, // serdesstrobe for iserdes2
+ input wire din_p, // data from dvi cable
+ input wire din_n, // data from dvi cable
+ input wire other_ch0_vld, // other channel0 has valid data now
+ input wire other_ch1_vld, // other channel1 has valid data now
+ input wire other_ch0_rdy, // other channel0 has detected a valid starting pixel
+ input wire other_ch1_rdy, // other channel1 has detected a valid starting pixel
+
+ output wire iamvld, // I have valid data now
+ output wire iamrdy, // I have detected a valid new pixel
+ output wire psalgnerr, // Phase alignment error
+ output reg c0,
+ output reg c1,
+ output reg de,
+ output reg [9:0] sdout,
+ output reg [7:0] dout,
+ output reg dgb,
+ output reg vgb,
+ output reg ctl_vld,
+ output wire line_end);
+
+ ////////////////////////////////
+ //
+ // 5-bit to 10-bit gear box
+ //
+ ////////////////////////////////
+ wire flipgear;
+ reg flipgearx2;
+
+ always @ (posedge pclkx2) begin
+ flipgearx2 <=#1 flipgear;
+ end
+
+ reg toggle = 1'b0;
+
+ always @ (posedge pclkx2 or posedge reset)
+ if (reset == 1'b1) begin
+ toggle <= 1'b0 ;
+ end else begin
+ toggle <=#1 ~toggle;
+ end
+
+ wire rx_toggle;
+
+ assign rx_toggle = toggle ^ flipgearx2; //reverse hi-lo position
+
+ wire [4:0] raw5bit;
+ reg [4:0] raw5bit_q;
+ reg [9:0] rawword;
+
+ always @ (posedge pclkx2) begin
+ raw5bit_q <=#1 raw5bit;
+
+ if(rx_toggle) //gear from 5 bit to 10 bit
+ rawword <=#1 {raw5bit, raw5bit_q};
+ end
+
+ ////////////////////////////////
+ //
+ // bitslip signal sync to pclkx2
+ //
+ ////////////////////////////////
+ reg bitslipx2 = 1'b0;
+ reg bitslip_q = 1'b0;
+ wire bitslip;
+
+ always @ (posedge pclkx2) begin
+ bitslip_q <=#1 bitslip;
+ bitslipx2 <=#1 bitslip & !bitslip_q;
+ end
+
+ /////////////////////////////////////////////
+ //
+ // 1:5 de-serializer working at x2 pclk rate
+ //
+ /////////////////////////////////////////////
+ serdes_1_to_5_diff_data # (
+ .DIFF_TERM("FALSE"),
+ .BITSLIP_ENABLE("TRUE")
+ ) des_0 (
+ .use_phase_detector(1'b1),
+ .datain_p(din_p),
+ .datain_n(din_n),
+ .rxioclk(pclkx10),
+ .rxserdesstrobe(serdesstrobe),
+ .reset(reset),
+ .gclk(pclkx2),
+ .bitslip(bitslipx2),
+ .data_out(raw5bit)
+ );
+
+ /////////////////////////////////////////////////////
+ // Doing word boundary detection here
+ /////////////////////////////////////////////////////
+ wire [9:0] rawdata = rawword;
+
+ ///////////////////////////////////////
+ // Phase Alignment Instance
+ ///////////////////////////////////////
+ phsaligner phsalgn_0 (
+ .rst(reset),
+ .clk(pclk),
+ .sdata(rawdata),
+ .bitslip(bitslip),
+ .flipgear(flipgear),
+ .psaligned(iamvld)
+ );
+
+ assign psalgnerr = 1'b0;
+
+ ///////////////////////////////////////
+ // Per Channel De-skew Instance
+ ///////////////////////////////////////
+ wire [9:0] sdata;
+ chnlbond cbnd (
+ .clk(pclk),
+ .rawdata(rawdata),
+ .iamvld(iamvld),
+ .other_ch0_vld(other_ch0_vld),
+ .other_ch1_vld(other_ch1_vld),
+ .other_ch0_rdy(other_ch0_rdy),
+ .other_ch1_rdy(other_ch1_rdy),
+ .iamrdy(iamrdy),
+ .sdata(sdata)
+ );
+
+ ////
+ // hack to accelerate detection of line end so that HDCP rekey
+ // can meet stringent timing spec requirement
+ ////
+ assign line_end = de &&
+ ((sdata == CTRLTOKEN0) ||
+ (sdata == CTRLTOKEN1) ||
+ (sdata == CTRLTOKEN2) ||
+ (sdata == CTRLTOKEN3));
+
+ /////////////////////////////////////////////////////////////////
+ // Below performs the 10B-8B decoding function defined in DVI 1.0
+ // Specification: Section 3.3.3, Figure 3-6, page 31.
+ /////////////////////////////////////////////////////////////////
+ // Distinct Control Tokens
+ parameter CTRLTOKEN0 = 10'b1101010100;
+ parameter CTRLTOKEN1 = 10'b0010101011;
+ parameter CTRLTOKEN2 = 10'b0101010100;
+ parameter CTRLTOKEN3 = 10'b1010101011;
+
+ parameter DATA_GB = 10'b0100110011;
+ parameter VID_B_GB = 10'b1011001100;
+ parameter VID_G_GB = 10'b0100110011;
+ parameter VID_R_GB = 10'b1011001100;
+
+ wire [7:0] data;
+ assign data = (sdata[9]) ? ~sdata[7:0] : sdata[7:0];
+
+ always @ (posedge pclk) begin
+ if(iamrdy && other_ch0_rdy && other_ch1_rdy) begin
+ case (sdata)
+ CTRLTOKEN0: begin
+ c0 <=#1 1'b0;
+ c1 <=#1 1'b0;
+ de <=#1 1'b0;
+ dgb <= #1 1'b0;
+ vgb <= #1 1'b0;
+ ctl_vld <= #1 1'b1;
+ end
+
+ CTRLTOKEN1: begin
+ c0 <=#1 1'b1;
+ c1 <=#1 1'b0;
+ de <=#1 1'b0;
+ dgb <= #1 1'b0;
+ vgb <= #1 1'b0;
+ ctl_vld <= #1 1'b1;
+ end
+
+ CTRLTOKEN2: begin
+ c0 <=#1 1'b0;
+ c1 <=#1 1'b1;
+ de <=#1 1'b0;
+ dgb <= #1 1'b0;
+ vgb <= #1 1'b0;
+ ctl_vld <= #1 1'b1;
+ end
+
+ CTRLTOKEN3: begin
+ c0 <=#1 1'b1;
+ c1 <=#1 1'b1;
+ de <=#1 1'b0;
+ dgb <= #1 1'b0;
+ vgb <= #1 1'b0;
+ ctl_vld <= #1 1'b1;
+ end
+
+ DATA_GB: begin
+ c0 <=#1 1'b0;
+ c1 <=#1 1'b0;
+ de <=#1 1'b0;
+ dgb <= #1 1'b1; // green is ambiguous between data and video guardbands
+ vgb <= #1 1'b1;
+ ctl_vld <= #1 1'b0;
+ end
+
+ VID_G_GB: begin
+ c0 <=#1 1'b0;
+ c1 <=#1 1'b0;
+ de <=#1 1'b0;
+ dgb <= #1 1'b1; // green is ambiguous between data and video guardbands
+ vgb <= #1 1'b1;
+ ctl_vld <= #1 1'b0;
+ end
+
+ default: begin
+ dout[0] <=#1 data[0];
+ dout[1] <=#1 (sdata[8]) ? (data[1] ^ data[0]) : (data[1] ~^ data[0]);
+ dout[2] <=#1 (sdata[8]) ? (data[2] ^ data[1]) : (data[2] ~^ data[1]);
+ dout[3] <=#1 (sdata[8]) ? (data[3] ^ data[2]) : (data[3] ~^ data[2]);
+ dout[4] <=#1 (sdata[8]) ? (data[4] ^ data[3]) : (data[4] ~^ data[3]);
+ dout[5] <=#1 (sdata[8]) ? (data[5] ^ data[4]) : (data[5] ~^ data[4]);
+ dout[6] <=#1 (sdata[8]) ? (data[6] ^ data[5]) : (data[6] ~^ data[5]);
+ dout[7] <=#1 (sdata[8]) ? (data[7] ^ data[6]) : (data[7] ~^ data[6]);
+
+ de <=#1 1'b1;
+
+ dgb <= #1 1'b0;
+ vgb <= #1 1'b0;
+ ctl_vld <= #1 1'b0;
+ end
+ endcase
+
+ sdout <=#1 sdata;
+ end else begin
+ c0 <= 1'b0;
+ c1 <= 1'b0;
+ de <= 1'b0;
+ dout <= 8'h0;
+ sdout <= 10'h0;
+
+ dgb <= 1'b0;
+ vgb <= 1'b0;
+ ctl_vld <= 1'b0;
+ end
+ end
+endmodule
diff --git a/rx/decoder.v b/rx/decoder.v
new file mode 100755
index 0000000..13210da
--- /dev/null
+++ b/rx/decoder.v
@@ -0,0 +1,318 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// Xilinx, Inc. 2010 www.xilinx.com
+//
+// XAPP xxx
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// File name : decoder.v
+//
+// Description : Spartan-6 dvi decoder
+//
+//
+// Author : Bob Feng
+//
+// Disclaimer: LIMITED WARRANTY AND DISCLAMER. These designs are
+// provided to you "as is". Xilinx and its licensors makeand you
+// receive no warranties or conditions, express, implied,
+// statutory or otherwise, and Xilinx specificallydisclaims any
+// implied warranties of merchantability, non-infringement,or
+// fitness for a particular purpose. Xilinx does notwarrant that
+// the functions contained in these designs will meet your
+// requirements, or that the operation of these designswill be
+// uninterrupted or error free, or that defects in theDesigns
+// will be corrected. Furthermore, Xilinx does not warrantor
+// make any representations regarding use or the results ofthe
+// 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 forany
+// special, incidental, consequential, or indirect damages
+// arising from the use or operation of the designs or
+// accompanying documentation, however caused and on anytheory
+// 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 ofthe
+// essential purpose of any limited remedies herein.
+//
+// Copyright © 2004 Xilinx, Inc.
+// All rights reserved
+//
+//////////////////////////////////////////////////////////////////////////////
+// Modifications copyright (c) 2011, Andrew "bunnie" Huang
+// All rights reserved as permitted by law.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation and/or
+// other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+//////////////////////////////////////////////////////////////////////////////
+`timescale 1 ns / 1ps
+
+module decoder (
+ input wire reset, //
+ input wire pclk, // pixel clock
+ input wire pclkx2, // double pixel rate for gear box
+ input wire pclkx10, // IOCLK
+ input wire serdesstrobe, // serdesstrobe for iserdes2
+ input wire din_p, // data from dvi cable
+ input wire din_n, // data from dvi cable
+ input wire other_ch0_vld, // other channel0 has valid data now
+ input wire other_ch1_vld, // other channel1 has valid data now
+ input wire other_ch0_rdy, // other channel0 has detected a valid starting pixel
+ input wire other_ch1_rdy, // other channel1 has detected a valid starting pixel
+
+ output wire iamvld, // I have valid data now
+ output wire iamrdy, // I have detected a valid new pixel
+ output wire psalgnerr, // Phase alignment error
+ output reg c0,
+ output reg c1,
+ output reg de,
+ output reg [9:0] sdout,
+ output reg [7:0] dout,
+ output reg dgb,
+ output reg vgb,
+ output reg ctl_vld,
+ output wire line_end);
+
+ ////////////////////////////////
+ //
+ // 5-bit to 10-bit gear box
+ //
+ ////////////////////////////////
+ wire flipgear;
+ reg flipgearx2;
+
+ always @ (posedge pclkx2) begin
+ flipgearx2 <=#1 flipgear;
+ end
+
+ reg toggle = 1'b0;
+
+ always @ (posedge pclkx2 or posedge reset)
+ if (reset == 1'b1) begin
+ toggle <= 1'b0 ;
+ end else begin
+ toggle <=#1 ~toggle;
+ end
+
+ wire rx_toggle;
+
+ assign rx_toggle = toggle ^ flipgearx2; //reverse hi-lo position
+
+ wire [4:0] raw5bit;
+ reg [4:0] raw5bit_q;
+ reg [9:0] rawword;
+
+ always @ (posedge pclkx2) begin
+ raw5bit_q <=#1 raw5bit;
+
+ if(rx_toggle) //gear from 5 bit to 10 bit
+ rawword <=#1 {raw5bit, raw5bit_q};
+ end
+
+ ////////////////////////////////
+ //
+ // bitslip signal sync to pclkx2
+ //
+ ////////////////////////////////
+ reg bitslipx2 = 1'b0;
+ reg bitslip_q = 1'b0;
+ wire bitslip;
+
+ always @ (posedge pclkx2) begin
+ bitslip_q <=#1 bitslip;
+ bitslipx2 <=#1 bitslip & !bitslip_q;
+ end
+
+ /////////////////////////////////////////////
+ //
+ // 1:5 de-serializer working at x2 pclk rate
+ //
+ /////////////////////////////////////////////
+ serdes_1_to_5_diff_data # (
+ .DIFF_TERM("FALSE"),
+ .BITSLIP_ENABLE("TRUE")
+ ) des_0 (
+ .use_phase_detector(1'b1),
+ .datain_p(din_p),
+ .datain_n(din_n),
+ .rxioclk(pclkx10),
+ .rxserdesstrobe(serdesstrobe),
+ .reset(reset),
+ .gclk(pclkx2),
+ .bitslip(bitslipx2),
+ .data_out(raw5bit)
+ );
+
+ /////////////////////////////////////////////////////
+ // Doing word boundary detection here
+ /////////////////////////////////////////////////////
+ wire [9:0] rawdata = rawword;
+
+ ///////////////////////////////////////
+ // Phase Alignment Instance
+ ///////////////////////////////////////
+ phsaligner phsalgn_0 (
+ .rst(reset),
+ .clk(pclk),
+ .sdata(rawdata),
+ .bitslip(bitslip),
+ .flipgear(flipgear),
+ .psaligned(iamvld)
+ );
+
+ assign psalgnerr = 1'b0;
+
+ ///////////////////////////////////////
+ // Per Channel De-skew Instance
+ ///////////////////////////////////////
+ wire [9:0] sdata;
+ chnlbond cbnd (
+ .clk(pclk),
+ .rawdata(rawdata),
+ .iamvld(iamvld),
+ .other_ch0_vld(other_ch0_vld),
+ .other_ch1_vld(other_ch1_vld),
+ .other_ch0_rdy(other_ch0_rdy),
+ .other_ch1_rdy(other_ch1_rdy),
+ .iamrdy(iamrdy),
+ .sdata(sdata)
+ );
+
+ ////
+ // hack to accelerate detection of line end so that HDCP rekey
+ // can meet stringent timing spec requirement
+ ////
+ assign line_end = de &&
+ ((sdata == CTRLTOKEN0) ||
+ (sdata == CTRLTOKEN1) ||
+ (sdata == CTRLTOKEN2) ||
+ (sdata == CTRLTOKEN3));
+
+ /////////////////////////////////////////////////////////////////
+ // Below performs the 10B-8B decoding function defined in DVI 1.0
+ // Specification: Section 3.3.3, Figure 3-6, page 31.
+ /////////////////////////////////////////////////////////////////
+ // Distinct Control Tokens
+ parameter CTRLTOKEN0 = 10'b1101010100;
+ parameter CTRLTOKEN1 = 10'b0010101011;
+ parameter CTRLTOKEN2 = 10'b0101010100;
+ parameter CTRLTOKEN3 = 10'b1010101011;
+
+ parameter DATA_GB = 10'b0100110011;
+ parameter VID_B_GB = 10'b1011001100;
+ parameter VID_G_GB = 10'b0100110011;
+ parameter VID_R_GB = 10'b1011001100;
+
+ wire [7:0] data;
+ assign data = (sdata[9]) ? ~sdata[7:0] : sdata[7:0];
+
+ always @ (posedge pclk) begin
+ if(iamrdy && other_ch0_rdy && other_ch1_rdy) begin
+ case (sdata)
+ CTRLTOKEN0: begin
+ c0 <=#1 1'b0;
+ c1 <=#1 1'b0;
+ de <=#1 1'b0;
+ dgb <= #1 1'b0;
+ vgb <= #1 1'b0;
+ ctl_vld <= #1 1'b1;
+ end
+
+ CTRLTOKEN1: begin
+ c0 <=#1 1'b1;
+ c1 <=#1 1'b0;
+ de <=#1 1'b0;
+ dgb <= #1 1'b0;
+ vgb <= #1 1'b0;
+ ctl_vld <= #1 1'b1;
+ end
+
+ CTRLTOKEN2: begin
+ c0 <=#1 1'b0;
+ c1 <=#1 1'b1;
+ de <=#1 1'b0;
+ dgb <= #1 1'b0;
+ vgb <= #1 1'b0;
+ ctl_vld <= #1 1'b1;
+ end
+
+ CTRLTOKEN3: begin
+ c0 <=#1 1'b1;
+ c1 <=#1 1'b1;
+ de <=#1 1'b0;
+ dgb <= #1 1'b0;
+ vgb <= #1 1'b0;
+ ctl_vld <= #1 1'b1;
+ end
+
+ DATA_GB: begin
+ c0 <=#1 1'b0;
+ c1 <=#1 1'b0;
+ de <=#1 1'b0;
+ dgb <= #1 1'b1;
+ vgb <= #1 1'b0;
+ ctl_vld <= #1 1'b0;
+ end
+
+ VID_R_GB: begin
+ c0 <=#1 1'b0;
+ c1 <=#1 1'b0;
+ de <=#1 1'b0;
+ dgb <= #1 1'b0;
+ vgb <= #1 1'b1;
+ ctl_vld <= #1 1'b0;
+ end
+
+ default: begin
+ dout[0] <=#1 data[0];
+ dout[1] <=#1 (sdata[8]) ? (data[1] ^ data[0]) : (data[1] ~^ data[0]);
+ dout[2] <=#1 (sdata[8]) ? (data[2] ^ data[1]) : (data[2] ~^ data[1]);
+ dout[3] <=#1 (sdata[8]) ? (data[3] ^ data[2]) : (data[3] ~^ data[2]);
+ dout[4] <=#1 (sdata[8]) ? (data[4] ^ data[3]) : (data[4] ~^ data[3]);
+ dout[5] <=#1 (sdata[8]) ? (data[5] ^ data[4]) : (data[5] ~^ data[4]);
+ dout[6] <=#1 (sdata[8]) ? (data[6] ^ data[5]) : (data[6] ~^ data[5]);
+ dout[7] <=#1 (sdata[8]) ? (data[7] ^ data[6]) : (data[7] ~^ data[6]);
+
+ de <=#1 1'b1;
+
+ dgb <= #1 1'b0;
+ vgb <= #1 1'b0;
+ ctl_vld <= #1 1'b0;
+ end
+ endcase
+
+ sdout <=#1 sdata;
+ end else begin
+ c0 <= 1'b0;
+ c1 <= 1'b0;
+ de <= 1'b0;
+ dout <= 8'h0;
+ sdout <= 10'h0;
+
+ dgb <= 1'b0;
+ vgb <= 1'b0;
+ ctl_vld <= 1'b0;
+ end
+ end
+endmodule
diff --git a/rx/dvi_decoder.v b/rx/dvi_decoder.v
new file mode 100755
index 0000000..1670c58
--- /dev/null
+++ b/rx/dvi_decoder.v
@@ -0,0 +1,634 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// Xilinx, Inc. 2010 www.xilinx.com
+//
+// XAPPxxx
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// File name : dvi_decoder.v
+//
+// Description : Spartan-6 DVI decoder top module
+//
+//
+// Author : Bob Feng
+//
+// Disclaimer: LIMITED WARRANTY AND DISCLAMER. These designs are
+// provided to you "as is". Xilinx and its licensors makeand you
+// receive no warranties or conditions, express, implied,
+// statutory or otherwise, and Xilinx specificallydisclaims any
+// implied warranties of merchantability, non-infringement,or
+// fitness for a particular purpose. Xilinx does notwarrant that
+// the functions contained in these designs will meet your
+// requirements, or that the operation of these designswill be
+// uninterrupted or error free, or that defects in theDesigns
+// will be corrected. Furthermore, Xilinx does not warrantor
+// make any representations regarding use or the results ofthe
+// 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 forany
+// special, incidental, consequential, or indirect damages
+// arising from the use or operation of the designs or
+// accompanying documentation, however caused and on anytheory
+// 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 ofthe
+// essential purpose of any limited remedies herein.
+//
+// Copyright © 2004 Xilinx, Inc.
+// All rights reserved
+//
+//////////////////////////////////////////////////////////////////////////////
+// Modifications copyright (c) 2011, Andrew "bunnie" Huang
+// All rights reserved as permitted by law.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation and/or
+// other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+//////////////////////////////////////////////////////////////////////////////
+`timescale 1 ns / 1ps
+
+// comment out the below line to turn off SS clocking
+// turned off currently because this form causes hdmi locking to fail, suspect lack of
+// phase lock to be the issue
+//`define SS_CLOCKING 1
+
+module dvi_decoder (
+ input wire tmdsclk_p, // tmds clock
+ input wire tmdsclk_n, // tmds clock
+ input wire blue_p, // Blue data in
+ input wire green_p, // Green data in
+ input wire red_p, // Red data in
+ input wire blue_n, // Blue data in
+ input wire green_n, // Green data in
+ input wire red_n, // Red data in
+ input wire exrst, // external reset input, e.g. reset button
+ input wire pllreset, // just reset the PLL only (after LoL)
+
+ output wire reset, // rx reset
+ output wire pclk, // regenerated pixel clock
+ output wire pclkx2, // double rate pixel clock
+ output wire pclkx10, // 10x pixel as IOCLK
+ output wire pllclk0, // send pllclk0 out so it can be fed into a different BUFPLL
+ output wire pllclk1, // PLL x1 output
+ output wire pllclk2, // PLL x2 output
+
+ output wire pll_lckd, // send pll_lckd out so it can be fed into a different BUFPLL
+ output wire serdesstrobe, // BUFPLL serdesstrobe output
+ output wire tmdsclk, // TMDS cable clock
+
+ output reg hsync, // hsync data
+ output reg vsync, // vsync data
+ output reg de, // data enable
+ output wire basic_de, // a DE that strobes even during data guardbands
+
+ output wire blue_vld,
+ output wire green_vld,
+ output wire red_vld,
+ output wire blue_rdy,
+ output wire green_rdy,
+ output wire red_rdy,
+
+ output wire psalgnerr,
+
+ output wire [29:0] sdout, // note this comes 2 pixclk earlier than pix colors
+ output reg [7:0] red, // pixel data out
+ output reg [7:0] green, // pixel data out
+ output reg [7:0] blue, // pixel data out
+
+ output reg encoding, // high when data island is valid
+ output wire hdcp_ena, // OR of data and video encyrption internal signals
+ output wire [3:0] red_di, // red data island
+ output wire [3:0] green_di, // green data island
+ output wire [3:0] blue_di, // blue data island
+ output reg data_gb, // guardbands
+ output reg video_gb,
+ output reg [3:0] ctl_code, // control code
+ output reg cv,
+ output wire line_end // fast-track signal that line ends for HDCP rekey
+ ) ;
+
+ wire g_dgb, b_dgb, r_dgb;
+ wire g_vgb, b_vgb, r_vgb;
+ wire g_cv, b_cv, r_cv;
+
+ wire [3:0] r_t4;
+ wire [3:0] b_t4;
+ wire [3:0] g_t4;
+
+ wire [9:0] sdout_blue;
+ wire [9:0] sdout_green;
+ wire [9:0] sdout_red;
+
+ wire [7:0] red_q1;
+ wire [7:0] blu_q1;
+ wire [7:0] grn_q1;
+
+ reg [7:0] red_q2;
+ reg [7:0] blu_q2;
+ reg [7:0] grn_q2;
+
+ reg de_q1, de_reg;
+ reg hsync_q1, vsync_q1;
+ wire de_q2;
+ wire hsync_q2, vsync_q2;
+ reg cv_q;
+
+ reg data_gb_q, video_gb_q;
+ reg [3:0] ctl_code_q;
+ wire [3:0] ctl_code_wire;
+
+/*
+ assign sdout = {sdout_red[9], sdout_green[9], sdout_blue[9], sdout_red[8], sdout_green[8], sdout_blue[8],
+ sdout_red[7], sdout_green[7], sdout_blue[7], sdout_red[6], sdout_green[6], sdout_blue[6],
+ sdout_red[5], sdout_green[5], sdout_blue[5], sdout_red[4], sdout_green[4], sdout_blue[4],
+ sdout_red[3], sdout_green[3], sdout_blue[3], sdout_red[2], sdout_green[2], sdout_blue[2],
+ sdout_red[1], sdout_green[1], sdout_blue[1], sdout_red[0], sdout_green[0], sdout_blue[0]} ;
+*/
+ parameter INIT = 8'b1 << 0;
+ parameter GOING_T4 = 8'b1 << 1;
+ parameter TERC4 = 8'b1 << 2;
+ parameter LEAVE_T4 = 8'b1 << 3;
+ parameter GOING_VID = 8'b1 << 4;
+ parameter VIDEO = 8'b1 << 5;
+ parameter PREAM_T4 = 8'b1 << 6;
+ parameter PREAM_VID = 8'b1 << 7;
+ parameter nSTATES = 8;
+
+ reg [(nSTATES-1):0] cstate = {{(nSTATES-1){1'b0}},1'b1};
+ reg [(nSTATES-1):0] nstate;
+
+ parameter ENC_TMDS = 1'b0;
+ parameter ENC_TERC4 = 1'b1;
+ parameter HDCP_OFF = 1'b0;
+ parameter HDCP_ON = 1'b1;
+
+// reg encoding;
+ reg encrypting_data;
+ reg encrypting_video;
+
+ assign hdcp_ena = encrypting_data | encrypting_video;
+
+ always @ (posedge pclk or posedge reset) begin
+ if (reset)
+ cstate <= INIT;
+ else
+ cstate <=#1 nstate;
+ end
+
+ always @ (*) begin
+ case (cstate) //synthesis parallel_case full_case
+ //// NOTE NOTE NOTE
+ //// green channel uses same code for video and data gb
+ //// so we can't consider its information in this state machine
+ INIT: begin
+ if( b_vgb & r_vgb & g_vgb ) begin
+// if( b_vgb | r_vgb | g_vgb ) begin
+ nstate = GOING_VID;
+ end else if (ctl_code_wire == 4'b0101) begin
+ // we've found a preamble for data
+ nstate = PREAM_T4;
+ end else if (ctl_code_wire == 4'b0001) begin
+ nstate = PREAM_VID;
+ end else begin
+ nstate = INIT;
+ end
+ end
+ PREAM_T4: begin
+ if( b_vgb & r_vgb & g_vgb ) begin
+// if( b_vgb | r_vgb | g_vgb ) begin
+ nstate = GOING_VID;
+ end else if (r_dgb & g_dgb) begin
+ // data guardband only happens on b/r channels
+ nstate = GOING_T4;
+ end else if (ctl_code_wire == 4'b0101) begin
+ nstate = PREAM_T4;
+ end else begin
+ nstate = INIT;
+ end
+ end
+ GOING_T4: begin
+ // wait till both dgb signals drop
+ nstate = (r_dgb & g_dgb) ? GOING_T4 : TERC4;
+ end
+ TERC4: begin
+ if( b_cv | r_cv | g_cv ) begin
+ nstate = INIT;
+ end else if( b_vgb & r_vgb & g_vgb ) begin
+// end else if( b_vgb | r_vgb | g_vgb ) begin
+ // if we see a video guardband and we think we're in terc4 encoding
+ // it means we missed the end of data guardband; simply re-initialize
+ // the machine so we always recover from bit error drops
+ nstate = GOING_VID;
+ end else if( r_dgb & g_dgb ) begin
+ // otherwise, gracefully leave
+ nstate = LEAVE_T4;
+ end else begin
+ nstate = TERC4;
+ end
+ end // case: TERC4
+ LEAVE_T4: begin
+ // wait till both dgb signals drop
+ nstate = (r_dgb & g_dgb) ? LEAVE_T4 : INIT;
+ end
+ PREAM_VID: begin
+ if( ctl_code_wire == 4'b0001 ) begin
+ nstate = PREAM_VID;
+ end else if( b_vgb & r_vgb & g_vgb ) begin
+// end else if( b_vgb | r_vgb | g_vgb ) begin
+ nstate = GOING_VID;
+ end else begin
+ nstate = INIT;
+ end
+ end
+ GOING_VID: begin
+ nstate = ( b_vgb & r_vgb & g_vgb ) ? GOING_VID : VIDEO;
+// nstate = ( b_vgb | r_vgb | g_vgb ) ? GOING_VID : VIDEO;
+ end
+ VIDEO: begin
+ if( b_cv | r_cv | g_cv ) begin
+// if( b_cv & r_cv & g_cv ) begin
+ nstate = INIT;
+ end else begin
+ nstate = VIDEO;
+ end
+ end
+ endcase // case (cstate)
+ end
+
+ always @ (posedge pclk or posedge reset) begin
+ if( reset ) begin
+ encoding <=#1 ENC_TMDS;
+ encrypting_data <=#1 HDCP_OFF;
+ end else begin
+ case (cstate) // synthesis parallel_case full_case
+ INIT: begin
+ encoding <= #1 ENC_TMDS;
+ encrypting_data <= #1 HDCP_OFF;
+ encrypting_video <= #1 HDCP_OFF;
+ de <= #1 1'b0;
+ end
+ PREAM_T4: begin
+ encoding <= #1 ENC_TMDS;
+ encrypting_data <= #1 HDCP_OFF;
+ encrypting_video <= #1 HDCP_OFF;
+ de <= #1 1'b0;
+ end
+ GOING_T4: begin
+ encoding <= #1 ENC_TERC4;
+ encrypting_data <= #1 HDCP_OFF;
+ encrypting_video <= #1 HDCP_OFF;
+ de <= #1 1'b0;
+ end
+ TERC4: begin
+ encoding <= #1 ENC_TERC4;
+ encrypting_data <= #1 HDCP_ON;
+ encrypting_video <= #1 HDCP_OFF;
+ de <= #1 1'b0;
+ end
+ LEAVE_T4: begin
+ encoding <= #1 ENC_TERC4;
+ encrypting_video <= #1 HDCP_OFF;
+ encrypting_data <= #1 HDCP_OFF;
+ de <= #1 1'b0;
+ end
+ PREAM_VID: begin
+ encoding <= #1 ENC_TMDS;
+ encrypting_data <= #1 HDCP_OFF;
+ encrypting_video <= #1 HDCP_OFF;
+ de <= #1 1'b0;
+ end
+ GOING_VID: begin
+ encoding <= #1 ENC_TMDS;
+ encrypting_data <= #1 HDCP_OFF;
+ encrypting_video <= #1 HDCP_OFF;
+ de <= #1 1'b0;
+ end
+ VIDEO: begin
+ encoding <= #1 ENC_TMDS;
+ encrypting_data <= #1 HDCP_OFF;
+ encrypting_video <= #1 HDCP_ON;
+ de <= #1 1'b1;
+ end
+ endcase // case (cstate)
+ end // else: !if( reset )
+ end // always @ (posedge pclk or posedge reset)
+
+
+ assign sdout = {sdout_red[9:5], sdout_green[9:5], sdout_blue[9:5],
+ sdout_red[4:0], sdout_green[4:0], sdout_blue[4:0]};
+
+ wire de_b, de_g, de_r;
+
+ assign de_q2 = de_b;
+ // to do: modify this against guard bands -- if dgb activates, set a flag to set terc4 coding
+ // until dgb triggers again; include a force-clear if a vgb is encountered
+
+ //wire blue_vld, green_vld, red_vld;
+ //wire blue_rdy, green_rdy, red_rdy;
+
+ wire blue_psalgnerr, green_psalgnerr, red_psalgnerr;
+
+ //
+ // Send TMDS clock to a differential buffer and then a BUFIO2
+ // This is a required path in Spartan-6 feed a PLL CLKIN
+ //
+ wire rxclkint;
+ IBUFDS #(.IOSTANDARD("TMDS_33"), .DIFF_TERM("FALSE")
+ ) ibuf_rxclk (.I(tmdsclk_p), .IB(tmdsclk_n), .O(rxclkint));
+
+ wire rxclk;
+`ifdef SS_CLOCKING
+ wire rxclk_pre_ss; //
+
+ BUFIO2 #(.DIVIDE_BYPASS("TRUE"), .DIVIDE(1))
+ bufio_tmdsclk (.DIVCLK(rxclk_pre_ss), .IOCLK(), .SERDESSTROBE(), .I(rxclkint));
+
+ BUFG tmdsclk_bufg (.I(rxclk), .O(tmdsclk));
+
+ // use spread spectrum clocking to reduce emissions...
+ DCM_CLKGEN #(
+ .DFS_OSCILLATOR_MODE("PHASE_FREQ_LOCK"),
+ .CLKIN_PERIOD ("13.48"),
+ .SPREAD_SPECTRUM ("CENTER_LOW_SPREAD"),
+ .CLKFX_MD_MAX("1.0"),
+ .CLKFX_MULTIPLY (4),
+ .CLKFX_DIVIDE (4) )
+ dcm_fcc_spreads_me_wide (
+ .CLKIN (rxclk_pre_ss),
+ .FREEZEDCM (1'b0),
+// .PROGDATA (progdata_int),
+// .PROGEN (progen_int),
+// .PROGCLK (clk26bufpll),
+// .PROGDONE (progdone),
+// .CLKFX180 (CLKFX180_DCM),
+// .CLKFXDV (CLKFXDV_DCM),
+ // .LOCKED (clkgen_locked),
+ .RST (rx0_reset),
+ .CLKFX (rxclk_ss)
+ );
+ BUFG tmdsclk_bfgss (.I(rxclk_ss), .O(rxclk) ); //
+`else // !`ifdef SS_CLOCKING
+
+ BUFIO2 #(.DIVIDE_BYPASS("TRUE"), .DIVIDE(1))
+ bufio_tmdsclk (.DIVCLK(rxclk), .IOCLK(), .SERDESSTROBE(), .I(rxclkint));
+
+ BUFG tmdsclk_bufg (.I(rxclk), .O(tmdsclk));
+
+`endif // !`ifdef SS_CLOCKING
+
+
+ //
+ // PLL is used to generate three clocks:
+ // 1. pclk: same rate as TMDS clock
+ // 2. pclkx2: double rate of pclk used for 5:10 soft gear box and ISERDES DIVCLK
+ // 3. pclkx10: 10x rate of pclk used as IO clock
+ //
+ wire clkfbin;
+ wire clkfbout;
+ wire clkfbin_fb;
+
+ PLL_BASE # (
+// .CLKIN_PERIOD(10.526315), // 95 MHz
+ .CLKIN_PERIOD(13.481449525), // 74.176 MHz
+ .CLKFBOUT_MULT(10), //set VCO to 10x of CLKIN
+ .CLKOUT0_DIVIDE(1),
+ .CLKOUT1_DIVIDE(10),
+ .CLKOUT2_DIVIDE(5),
+// .COMPENSATION("INTERNAL")
+// .BANDWIDTH("LOW"), // normally not here
+ .COMPENSATION("SOURCE_SYNCHRONOUS")
+ ) PLL_ISERDES (
+ .CLKFBOUT(clkfbout),
+ .CLKOUT0(pllclk0),
+ .CLKOUT1(pllclk1),
+ .CLKOUT2(pllclk2),
+ .CLKOUT3(),
+ .CLKOUT4(),
+ .CLKOUT5(),
+ .LOCKED(pll_lckd),
+ .CLKFBIN(clkfbin_fb),
+ .CLKIN(rxclk),
+ .RST(exrst || pllreset)
+ );
+
+ // feedback to source-synchronize the clock
+ BUFG pclkfbk (.I(clkfbout), .O(clkfbin) );
+ BUFIO2FB pclkfbk_fb (.I(clkfbin), .O(clkfbin_fb) );
+
+ //
+ // Pixel Rate clock buffer
+ //
+ BUFG pclkbufg (.I(pllclk1), .O(pclk));
+
+ //////////////////////////////////////////////////////////////////
+ // 2x pclk is going to be used to drive IOSERDES2 DIVCLK
+ //////////////////////////////////////////////////////////////////
+ BUFG pclkx2bufg (.I(pllclk2), .O(pclkx2));
+
+ //////////////////////////////////////////////////////////////////
+ // 10x pclk is used to drive IOCLK network so a bit rate reference
+ // can be used by IOSERDES2
+ //////////////////////////////////////////////////////////////////
+
+ wire bufpll_lock;
+ BUFPLL #(.DIVIDE(5)) ioclk_buf (.PLLIN(pllclk0), .GCLK(pclkx2), .LOCKED(pll_lckd),
+ .IOCLK(pclkx10), .SERDESSTROBE(serdesstrobe), .LOCK(bufpll_lock));
+
+ assign reset = ~bufpll_lock;
+
+ wire line_end_r;
+ wire line_end_g;
+ wire line_end_b;
+
+ // note instance-specific decode since each channel has its own specific
+ // guardband character.
+ decodeb dec_b (
+ .reset (reset),
+ .pclk (pclk),
+ .pclkx2 (pclkx2),
+ .pclkx10 (pclkx10),
+ .serdesstrobe (serdesstrobe),
+ .din_p (blue_p),
+ .din_n (blue_n),
+ .other_ch0_rdy(green_rdy),
+ .other_ch1_rdy(red_rdy),
+ .other_ch0_vld(green_vld),
+ .other_ch1_vld(red_vld),
+
+ .iamvld (blue_vld),
+ .iamrdy (blue_rdy),
+ .psalgnerr (blue_psalgnerr),
+ .c0 (hsync_q2),
+ .c1 (vsync_q2),
+ .de (de_b),
+ .sdout (sdout_blue),
+ .dout (blu_q1),
+ .dgb (b_dgb),
+ .vgb (b_vgb),
+ .ctl_vld (b_cv),
+ .line_end (line_end_b)) ;
+
+ decodeg dec_g (
+ .reset (reset),
+ .pclk (pclk),
+ .pclkx2 (pclkx2),
+ .pclkx10 (pclkx10),
+ .serdesstrobe (serdesstrobe),
+ .din_p (green_p),
+ .din_n (green_n),
+ .other_ch0_rdy(blue_rdy),
+ .other_ch1_rdy(red_rdy),
+ .other_ch0_vld(blue_vld),
+ .other_ch1_vld(red_vld),
+
+ .iamvld (green_vld),
+ .iamrdy (green_rdy),
+ .psalgnerr (green_psalgnerr),
+ .c0 (ctl_code_wire[0]),
+ .c1 (ctl_code_wire[1]),
+ .de (de_g),
+ .sdout (sdout_green),
+ .dout (grn_q1),
+ .dgb (g_dgb),
+ .vgb (g_vgb),
+ .ctl_vld (g_cv),
+ .line_end (line_end_g)) ;
+
+ decoder dec_r (
+ .reset (reset),
+ .pclk (pclk),
+ .pclkx2 (pclkx2),
+ .pclkx10 (pclkx10),
+ .serdesstrobe (serdesstrobe),
+ .din_p (red_p),
+ .din_n (red_n),
+ .other_ch0_rdy(blue_rdy),
+ .other_ch1_rdy(green_rdy),
+ .other_ch0_vld(blue_vld),
+ .other_ch1_vld(green_vld),
+
+ .iamvld (red_vld),
+ .iamrdy (red_rdy),
+ .psalgnerr (red_psalgnerr),
+ .c0 (ctl_code_wire[2]),
+ .c1 (ctl_code_wire[3]),
+ .de (de_r),
+ .sdout (sdout_red),
+ .dout (red_q1),
+ .dgb (r_dgb),
+ .vgb (r_vgb),
+ .ctl_vld (r_cv),
+ .line_end (line_end_r)) ;
+
+ assign basic_de = de_b | de_r | de_g | b_vgb | r_vgb | g_vgb;
+
+ assign line_end = line_end_g | line_end_r | line_end_b;
+
+ assign psalgnerr = red_psalgnerr | blue_psalgnerr | green_psalgnerr;
+
+ // pipe alignment registers
+ always @(posedge pclk or posedge reset) begin
+ if( reset ) begin
+ red <= 8'b0;
+ red_q2 <= 8'b0;
+ blue <= 8'b0;
+ blu_q2 <= 8'b0;
+ green <= 8'b0;
+ grn_q2 <= 8'b0;
+
+ hsync <= 1'b0;
+ hsync_q1 <= 1'b0;
+
+ vsync <= 1'b0;
+ vsync_q1 <= 1'b0;
+
+ de_reg <= 1'b0;
+ de_q1 <= 1'b0;
+
+ data_gb_q <= 1'b0;
+ data_gb <= 1'b0;
+ video_gb_q <= 1'b0;
+ video_gb <= 1'b0;
+ ctl_code_q <= 4'b0;
+ ctl_code <= 4'b0;
+
+ cv_q <= 1'b0;
+ cv <= 1'b0;
+ end else begin
+ red_q2 <= red_q1;
+ red <= red_q2;
+
+ blu_q2 <= blu_q1;
+ blue <= blu_q2;
+
+ grn_q2 <= grn_q1;
+ green <= grn_q2;
+
+ // reversed the naming convention for the following pipe stages
+ hsync <= hsync_q1;
+ hsync_q1 <= hsync_q2;
+
+ vsync <= vsync_q1;
+ vsync_q1 <= vsync_q2;
+
+ de_reg <= de_q1;
+ de_q1 <= de_q2;
+
+ data_gb_q <= r_dgb & g_vgb; // data guardbands only on red and green channels
+ data_gb <= data_gb_q;
+
+ video_gb_q <= r_vgb & b_vgb & g_vgb;
+ video_gb <= video_gb_q;
+
+ ctl_code_q <= ctl_code_wire;
+ ctl_code <= ctl_code_q;
+
+ cv_q <= b_cv & r_cv & g_cv;
+ cv <= cv_q;
+ end // else: !if( reset )
+ end // always @ (posedge pclk or posedge reset)
+// assign de = de_reg & (encoding == ENC_TMDS);
+
+ decode_terc4 dec_t4_g (
+ .rstin( reset ),
+ .clkin(pclk),
+ .din(sdout_green),
+ .dout(g_t4));
+
+ decode_terc4 dec_t4_r (
+ .rstin( reset ),
+ .clkin(pclk),
+ .din(sdout_red),
+ .dout(r_t4));
+
+ decode_terc4 dec_t4_b (
+ .rstin( reset ),
+ .clkin(pclk),
+ .din(sdout_blue),
+ .dout(b_t4));
+ assign red_di = r_t4;
+ assign green_di = g_t4;
+ assign blue_di = b_t4;
+
+endmodule
diff --git a/rx/phsaligner.v b/rx/phsaligner.v
new file mode 100755
index 0000000..683ac50
--- /dev/null
+++ b/rx/phsaligner.v
@@ -0,0 +1,301 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// Xilinx, Inc. 2010 www.xilinx.com
+//
+// XAPP xxx - TMDS serial stream phase aligner
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// File name : phasealigner.v
+//
+// Description : This module determines whether the Spartan-6 IOSERDES
+// has validate the incoming TMDS data stream
+//
+//
+// Note:
+//
+// 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
+//
+//////////////////////////////////////////////////////////////////////////////
+// Modifications copyright (c) 2011, Andrew "bunnie" Huang
+// All rights reserved as permitted by law.
+//
+// Redistribution and use in source and binary forms, with or without modification,
+// are permitted provided that the following conditions are met:
+//
+// * Redistributions of source code must retain the above copyright notice,
+// this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation and/or
+// other materials provided with the distribution.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+// OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+// SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+`timescale 1 ns / 1ps
+`define SIMULATION 1
+
+// here's what this module does.
+// 1. searches for an incoming control token
+// 2. when it finds one, makes sure it sticks around at least CTKNCNTWD.
+// 3. if it can't find one within SRCHTIMERWD, try a new bitslip and/or gearbox setting.
+// keep on trying bitslips and gear settings over and over again ewvery SRCHTIMERWD
+// until we've found a CTKNCNTWD.
+// 4. once the token has stuck around for the pre-determined number of cycles, repeat
+// the search to confirm it. (this function is degenerate in this implementation)
+// 5. once setting has been confirmed, assume it never changes.
+
+module phsaligner # (
+ parameter OPENEYE_CNT_WD = 3, // valid open eye counter width
+// parameter CTKNCNTWD = 7, // Control Token Counter Width (dvi spec is 128)
+ parameter CTKNCNTWD = 3, // Control Token Counter Width (hdmi spec is 8)
+ parameter SRCHTIMERWD = 12 // Idle Timer Width
+)
+(
+ input wire rst,
+ input wire clk,
+ input wire [9:0] sdata, // 10 bit serial stream sync. to clk
+ output reg flipgear,
+ output reg bitslip,
+ output reg psaligned // FSM output
+);
+
+ parameter CTRLTOKEN0 = 10'b1101010100;
+ parameter CTRLTOKEN1 = 10'b0010101011;
+ parameter CTRLTOKEN2 = 10'b0101010100;
+ parameter CTRLTOKEN3 = 10'b1010101011;
+
+ ///////////////////////////////////////////////////////
+ // Control Token Detection
+ ///////////////////////////////////////////////////////
+ reg rcvd_ctkn, rcvd_ctkn_q;
+ reg blnkbgn; //blank period begins
+
+ always @ (posedge clk) begin
+ rcvd_ctkn <=#1 ((sdata == CTRLTOKEN0) || (sdata == CTRLTOKEN1) ||
+ (sdata == CTRLTOKEN2) || (sdata == CTRLTOKEN3));
+
+ rcvd_ctkn_q <=#1 rcvd_ctkn;
+ blnkbgn <=#1 !rcvd_ctkn_q & rcvd_ctkn;
+ end
+
+ /////////////////////////////////////////////////////
+ // Control Token Search Timer
+ //
+ // DVI 1.0 Spec. says periodic blanking should start
+ // no less than every 50ms or 20HZ
+ // 2^24 of 74.25MHZ cycles is about 200ms
+ /////////////////////////////////////////////////////
+ reg [(SRCHTIMERWD-1):0] ctkn_srh_timer;
+ reg ctkn_srh_rst; //FSM output
+
+ always @ (posedge clk) begin
+ if (ctkn_srh_rst)
+ ctkn_srh_timer <=#1 {SRCHTIMERWD{1'b0}};
+ else
+ ctkn_srh_timer <=#1 ctkn_srh_timer + 1'b1;
+ end
+
+ reg ctkn_srh_tout;
+ always @ (posedge clk) begin
+ ctkn_srh_tout <=#1 (ctkn_srh_timer == {SRCHTIMERWD{1'b1}});
+ end
+
+ /////////////////////////////////////////////////////
+ // Contorl Token Event Counter
+ //
+ // DVI 1.0 Spec. says the minimal blanking period
+ // is at least 128 pixels long in order to achieve
+ // synchronization
+ //
+ // HDMI reduces this to as little as 8
+ /////////////////////////////////////////////////////
+ reg [(CTKNCNTWD-1):0] ctkn_counter;
+ reg ctkn_cnt_rst; //FSM output
+
+ always @ (posedge clk) begin
+ if(ctkn_cnt_rst)
+ ctkn_counter <=#1 {CTKNCNTWD{1'b0}};
+ else
+ ctkn_counter <=#1 ctkn_counter + 1'b1;
+ end
+
+ reg ctkn_cnt_tout;
+ always @ (posedge clk) begin
+ ctkn_cnt_tout <=#1 (ctkn_counter == {CTKNCNTWD{1'b1}});
+ end
+
+ //////////////////////////////////////////////////////////
+ // Below starts the phase alignment state machine
+ //////////////////////////////////////////////////////////
+ parameter INIT = 6'b1 << 0;
+ parameter SEARCH = 6'b1 << 1; // Searching for control tokens
+ parameter BITSLIP = 6'b1 << 2;
+ parameter RCVDCTKN = 6'b1 << 3; // Received at one Control Token and check for more
+ parameter BLNKPRD = 6'b1 << 4;
+ parameter PSALGND = 6'b1 << 5; // Phase alignment achieved
+ parameter nSTATES = 6;
+
+ reg [(nSTATES-1):0] cstate = {{(nSTATES-1){1'b0}}, 1'b1}; //current and next states
+ reg [(nSTATES-1):0] nstate;
+
+`ifdef SIMULATION
+ // synthesis translate_off
+ reg [8*20:1] state_ascii = "INIT ";
+ always @(cstate) begin
+ if (cstate == INIT ) state_ascii <= "INIT ";
+ else if (cstate == SEARCH ) state_ascii <= "SEARCH ";
+ else if (cstate == BITSLIP ) state_ascii <= "BITSLIP ";
+ else if (cstate == RCVDCTKN ) state_ascii <= "RCVDCTKN ";
+ else if (cstate == BLNKPRD ) state_ascii <= "BLNKPRD ";
+ else state_ascii <= "PSALGND ";
+ end
+ // synthesis translate_on
+`endif
+
+ always @ (posedge clk or posedge rst) begin
+ if (rst)
+ cstate <= INIT;
+ else
+ cstate <=#1 nstate;
+ end
+
+ //////////////////////////////////////////////////////////
+ // Counter counts number of blank period detected
+ // in order to qualify the bitslip position
+ //////////////////////////////////////////////////////////
+ parameter BLNKPRD_CNT_WD = 1;
+
+ reg [(BLNKPRD_CNT_WD-1):0] blnkprd_cnt = {BLNKPRD_CNT_WD{1'b0}};
+
+ always @ (*) begin
+ case (cstate) //synthesis parallel_case full_case
+ INIT: begin
+ nstate = (ctkn_srh_tout) ? SEARCH : INIT;
+ end
+
+ SEARCH: begin
+ if(blnkbgn)
+ nstate = RCVDCTKN;
+ else
+ nstate = (ctkn_srh_tout) ? BITSLIP : SEARCH;
+ end
+
+ BITSLIP: begin
+ nstate = SEARCH;
+ end
+
+ RCVDCTKN: begin
+ if(rcvd_ctkn)
+ nstate = (ctkn_cnt_tout) ? BLNKPRD : RCVDCTKN;
+ else
+ nstate = SEARCH;
+ end
+
+ BLNKPRD: begin
+ nstate = (blnkprd_cnt == {BLNKPRD_CNT_WD{1'b1}}) ? PSALGND : SEARCH;
+ end
+
+ PSALGND: begin
+ nstate = PSALGND; // Phase aligned so hang around here
+ end
+ endcase
+ end
+
+ reg [2:0] bitslip_cnt;
+
+ always @ (posedge clk or posedge rst) begin
+ if(rst) begin
+ psaligned <=#1 1'b0; //phase alignment success flag
+ bitslip <=#1 1'b0;
+ ctkn_srh_rst <=#1 1'b1; //control token search timer reset
+ ctkn_cnt_rst <=#1 1'b1; //control token counter reset
+
+ bitslip <=#1 1'b0;
+ bitslip_cnt <=#1 3'h0;
+ flipgear <=#1 1'b0;
+ blnkprd_cnt <=#1 {BLNKPRD_CNT_WD{1'b0}};
+ end else begin
+ case (cstate) // synthesis parallel_case full_case
+ INIT: begin
+ ctkn_srh_rst <=#1 1'b0;
+ ctkn_cnt_rst <=#1 1'b1;
+ bitslip <=#1 1'b0;
+ psaligned <=#1 1'b0;
+
+ bitslip <=#1 1'b0;
+ bitslip_cnt <=#1 3'h0;
+ flipgear <=#1 1'b0;
+ blnkprd_cnt <=#1 {BLNKPRD_CNT_WD{1'b0}};
+ end
+
+ SEARCH: begin
+ ctkn_srh_rst <=#1 1'b0;
+ ctkn_cnt_rst <=#1 1'b1;
+ bitslip <=#1 1'b0;
+ psaligned <=#1 1'b0;
+ end
+
+ BITSLIP: begin
+ ctkn_srh_rst <=#1 1'b1;
+
+ bitslip <=#1 1'b1;
+ bitslip_cnt <=#1 bitslip_cnt + 1'b1;
+ flipgear <=#1 bitslip_cnt[2]; //bitslip has toggled for 4 times
+ end
+
+ RCVDCTKN: begin
+ ctkn_srh_rst <=#1 1'b0;
+ ctkn_cnt_rst <=#1 1'b0;
+ end
+
+ BLNKPRD: begin
+ blnkprd_cnt <=#1 blnkprd_cnt + 1'b1;
+ end
+
+ PSALGND: begin
+ psaligned <=#1 1'b1;
+ end
+ endcase
+ end
+ end
+
+endmodule
diff --git a/rx/serdes_1_to_5_diff_data.v b/rx/serdes_1_to_5_diff_data.v
new file mode 100755
index 0000000..2465afa
--- /dev/null
+++ b/rx/serdes_1_to_5_diff_data.v
@@ -0,0 +1,405 @@
+//////////////////////////////////////////////////////////////////////////////
+//
+// Xilinx, Inc. 2010 www.xilinx.com
+//
+// XAPP xxx - 1:5 Differential Data De-serializer
+//
+//////////////////////////////////////////////////////////////////////////////
+//
+// File name : serdes_1_to_5_diff_data.v
+//
+// Description : This module instantiates IODELAY2 and ISERDES2 primitives
+// to receive TMDS differential data in 1:5 format
+//
+// Note:
+//
+// Author : Bob Feng
+//////////////////////////////////////////////////////////////////////////////
+//
+// Disclaimer:
+//
+// This disclaimer is not a license and does not grant any rights to the materials
+// distributed herewith. Except as otherwise provided in a valid license issued to you
+// by Xilinx, and to the maximum extent permitted by applicable law:
+// (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND WITH ALL FAULTS,
+// AND XILINX HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY,
+// INCLUDING BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON-INFRINGEMENT, OR
+// FITNESS FOR ANY PARTICULAR PURPOSE; and (2) Xilinx shall not be liable (whether in contract
+// or tort, including negligence, or under any other theory of liability) for any loss or damage
+// of any kind or nature related to, arising under or in connection with these materials,
+// including for any direct, or any indirect, special, incidental, or consequential loss
+// or damage (including loss of data, profits, goodwill, or any type of loss or damage suffered
+// as a result of any action brought by a third party) even if such damage or loss was
+// reasonably foreseeable or Xilinx had been advised of the possibility of the same.
+//
+// Critical Applications:
+//
+// Xilinx products are not designed or intended to be fail-safe, or for use in any application
+// requiring fail-safe performance, such as life-support or safety devices or systems,
+// Class III medical devices, nuclear facilities, applications related to the deployment of airbags,
+// or any other applications that could lead to death, personal injury, or severe property or
+// environmental damage (individually and collectively, "Critical Applications"). Customer assumes
+// the sole risk and liability of any use of Xilinx products in Critical Applications, subject only
+// to applicable laws and regulations governing limitations on product liability.
+//
+// THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS PART OF THIS FILE AT ALL TIMES.
+//
+//////////////////////////////////////////////////////////////////////////////
+
+`timescale 1ps/1ps
+
+module serdes_1_to_5_diff_data # (
+ parameter DIFF_TERM = "TRUE",
+ parameter SIM_TAP_DELAY = 49,
+ parameter BITSLIP_ENABLE = "FALSE"
+)(
+ input wire use_phase_detector, // '1' enables the phase detector logic
+ input wire datain_p, // Input from LVDS receiver pin
+ input wire datain_n, // Input from LVDS receiver pin
+ input wire rxioclk, // IO Clock network
+ input wire rxserdesstrobe, // Parallel data capture strobe
+ input wire reset, // Reset line
+ input wire gclk, // Global clock
+ input wire bitslip, // Bitslip control line
+ output wire [4:0] data_out // Output data
+);
+
+ wire ddly_m;
+ wire ddly_s;
+ wire busys;
+ wire rx_data_in;
+ wire cascade;
+ wire pd_edge;
+ reg [8:0] counter;
+ reg [3:0] state;
+ reg cal_data_sint;
+ wire busy_data;
+ reg busy_data_d;
+ wire cal_data_slave;
+ reg enable;
+ reg cal_data_master;
+ reg rst_data;
+ reg inc_data_int;
+ wire inc_data;
+ reg ce_data;
+ reg valid_data_d;
+ reg incdec_data_d;
+ reg [4:0] pdcounter;
+ wire valid_data;
+ wire incdec_data;
+ reg flag;
+ reg mux;
+ reg ce_data_inta ;
+ wire [1:0] incdec_data_or;
+ wire incdec_data_im;
+ wire [1:0] valid_data_or;
+ wire valid_data_im;
+ wire [1:0] busy_data_or;
+ wire all_ce;
+
+ wire [1:0] debug_in = 2'b00;
+
+ assign busy_data = busys ;
+
+ assign cal_data_slave = cal_data_sint ;
+
+ /////////////////////////////////////////////////
+ //
+ // IDELAY Calibration FSM
+ //
+ /////////////////////////////////////////////////
+ always @ (posedge gclk or posedge reset)
+ begin
+ if (reset == 1'b1) begin
+ state <= 0 ;
+ cal_data_master <= 1'b0 ;
+ cal_data_sint <= 1'b0 ;
+ counter <= 9'h000 ;
+ enable <= 1'b0 ;
+ mux <= 1'h1 ;
+ end
+ else begin
+ counter <= counter + 9'h001 ;
+ if (counter[8] == 1'b1) begin
+ counter <= 9'h000 ;
+ end
+ if (counter[5] == 1'b1) begin
+ enable <= 1'b1 ;
+ end
+ if (state == 0 && enable == 1'b1) begin // Wait for IODELAY to be available
+ cal_data_master <= 1'b0 ;
+ cal_data_sint <= 1'b0 ;
+ rst_data <= 1'b0 ;
+ if (busy_data_d == 1'b0) begin
+ state <= 1 ;
+ end
+ end
+ else if (state == 1) begin // Issue calibrate command to both master and slave, needed for simulation, not for the silicon
+ cal_data_master <= 1'b1 ;
+ cal_data_sint <= 1'b1 ;
+ if (busy_data_d == 1'b1) begin // and wait for command to be accepted
+ state <= 2 ;
+ end
+ end
+ else if (state == 2) begin // Now RST master and slave IODELAYs needed for simulation, not for the silicon
+ cal_data_master <= 1'b0 ;
+ cal_data_sint <= 1'b0 ;
+ if (busy_data_d == 1'b0) begin
+ rst_data <= 1'b1 ;
+ state <= 3 ;
+ end
+ end
+ else if (state == 3) begin // Wait for IODELAY to be available
+ rst_data <= 1'b0 ;
+ if (busy_data_d == 1'b0) begin
+ state <= 4 ;
+ end
+ end
+ else if (state == 4) begin // Wait for occasional enable
+ if (counter[8] == 1'b1) begin
+ state <= 5 ;
+ end
+ end
+ else if (state == 5) begin // Calibrate slave only
+ if (busy_data_d == 1'b0) begin
+ cal_data_sint <= 1'b1 ;
+ state <= 6 ;
+ end
+ end
+ else if (state == 6) begin // Wait for command to be accepted
+ cal_data_sint <= 1'b0 ;
+ if (busy_data_d == 1'b1) begin
+ state <= 7 ;
+ end
+ end
+ else if (state == 7) begin // Wait for all IODELAYs to be available, ie CAL command finished
+ cal_data_sint <= 1'b0 ;
+ if (busy_data_d == 1'b0) begin
+ state <= 4 ;
+ end
+ end
+ end
+ end
+
+always @ (posedge gclk or posedge reset) // Per-bit phase detection state machine
+begin
+if (reset == 1'b1) begin
+ pdcounter <= 5'b1000 ;
+ ce_data_inta <= 1'b0 ;
+ flag <= 1'b0 ; // flag is there to only allow one inc or dec per cal (test)
+end
+else begin
+ busy_data_d <= busy_data_or[1] ;
+ if (use_phase_detector == 1'b1) begin // decide whther pd is used
+ incdec_data_d <= incdec_data_or[1] ;
+ valid_data_d <= valid_data_or[1] ;
+ if (ce_data_inta == 1'b1) begin
+ ce_data = mux ;
+ end
+ else begin
+ ce_data = 64'h0000000000000000 ;
+ end
+ if (state == 7) begin
+ flag <= 1'b0 ;
+ end
+ else if (state != 4 || busy_data_d == 1'b1) begin // Reset filter if state machine issues a cal command or unit is busy
+ pdcounter <= 5'b10000 ;
+ ce_data_inta <= 1'b0 ;
+ end
+ else if (pdcounter == 5'b11111 && flag == 1'b0) begin // Filter has reached positive max - increment the tap count
+ ce_data_inta <= 1'b1 ;
+ inc_data_int <= 1'b1 ;
+ pdcounter <= 5'b10000 ;
+ flag <= 1'b1 ;
+ end
+ else if (pdcounter == 5'b00000 && flag == 1'b0) begin // Filter has reached negative max - decrement the tap count
+ ce_data_inta <= 1'b1 ;
+ inc_data_int <= 1'b0 ;
+ pdcounter <= 5'b10000 ;
+ flag <= 1'b1 ;
+ end
+ else if (valid_data_d == 1'b1) begin // increment filter
+ ce_data_inta <= 1'b0 ;
+ if (incdec_data_d == 1'b1 && pdcounter != 5'b11111) begin
+ pdcounter <= pdcounter + 5'b00001 ;
+ end
+ else if (incdec_data_d == 1'b0 && pdcounter != 5'b00000) begin // decrement filter
+ pdcounter <= pdcounter + 5'b11111 ;
+ end
+ end
+ else begin
+ ce_data_inta <= 1'b0 ;
+ end
+ end
+ else begin
+ ce_data = all_ce ;
+ inc_data_int = debug_in[1] ;
+ end
+end
+end
+
+assign inc_data = inc_data_int ;
+
+assign incdec_data_or[0] = 1'b0 ; // Input Mux - Initialise generate loop OR gates
+assign valid_data_or[0] = 1'b0 ;
+assign busy_data_or[0] = 1'b0 ;
+
+assign incdec_data_im = incdec_data & mux; // Input muxes
+assign incdec_data_or[1] = incdec_data_im | incdec_data_or; // AND gates to allow just one signal through at a tome
+assign valid_data_im = valid_data & mux; // followed by an OR
+assign valid_data_or[1] = valid_data_im | valid_data_or; // for the three inputs from each PD
+assign busy_data_or[1] = busy_data | busy_data_or; // The busy signals just need an OR gate
+
+assign all_ce = debug_in[0] ;
+
+IBUFDS #(
+ .DIFF_TERM (DIFF_TERM))
+data_in (
+ .I (datain_p),
+ .IB (datain_n),
+ .O (rx_data_in)
+);
+
+//
+// Master IDELAY
+//
+IODELAY2 #(
+ .DATA_RATE ("SDR"),
+ .IDELAY_VALUE (0),
+ .IDELAY2_VALUE (0),
+ .IDELAY_MODE ("NORMAL" ),
+ .ODELAY_VALUE (0),
+ .IDELAY_TYPE ("DIFF_PHASE_DETECTOR"),
+ .COUNTER_WRAPAROUND ("STAY_AT_LIMIT"), //("WRAPAROUND"), // this setting is for implementation
+// .COUNTER_WRAPAROUND ("WRAPAROUND"), // this setting is for simulation
+ .DELAY_SRC ("IDATAIN"),
+ .SERDES_MODE ("MASTER"),
+ .SIM_TAPDELAY_VALUE (SIM_TAP_DELAY)
+) iodelay_m (
+ .IDATAIN (rx_data_in), // data from IBUFDS
+ .TOUT (), // tri-state signal to IOB
+ .DOUT (), // output data to IOB
+ .T (1'b1), // tri-state control from OLOGIC/OSERDES2
+ .ODATAIN (1'b0), // data from OLOGIC/OSERDES2
+ .DATAOUT (ddly_m), // Output data 1 to ILOGIC/ISERDES2
+ .DATAOUT2 (), // Output data 2 to ILOGIC/ISERDES2
+ .IOCLK0 (rxioclk), // High speed clock for calibration
+ .IOCLK1 (1'b0), // High speed clock for calibration
+ .CLK (gclk), // Fabric clock (GCLK) for control signals
+ .CAL (cal_data_master), // Calibrate control signal
+ .INC (inc_data), // Increment counter
+ .CE (ce_data), // Clock Enable
+ .RST (rst_data), // Reset delay line
+ .BUSY () // output signal indicating sync circuit has finished / calibration has finished
+);
+
+//
+// Slave IDELAY
+//
+IODELAY2 #(
+ .DATA_RATE ("SDR"),
+ .IDELAY_VALUE (0),
+ .IDELAY2_VALUE (0),
+ .IDELAY_MODE ("NORMAL" ),
+ .ODELAY_VALUE (0),
+ .IDELAY_TYPE ("DIFF_PHASE_DETECTOR"),
+ .COUNTER_WRAPAROUND ("STAY_AT_LIMIT"), // this lacked the note about impl/sim
+// .COUNTER_WRAPAROUND ("WRAPAROUND"),
+ .DELAY_SRC ("IDATAIN"),
+ .SERDES_MODE ("SLAVE"),
+ .SIM_TAPDELAY_VALUE (SIM_TAP_DELAY)
+) iodelay_s (
+ .IDATAIN (rx_data_in), // data from IBUFDS
+ .TOUT (), // tri-state signal to IOB
+ .DOUT (), // output data to IOB
+ .T (1'b1), // tri-state control from OLOGIC/OSERDES2
+ .ODATAIN (1'b0), // data from OLOGIC/OSERDES2
+ .DATAOUT (ddly_s), // Slave output data to ILOGIC/ISERDES2
+ .DATAOUT2 (), //
+ .IOCLK0 (rxioclk), // High speed IO clock for calibration
+ .IOCLK1 (1'b0),
+ .CLK (gclk), // Fabric clock (GCLK) for control signals
+ .CAL (cal_data_slave), // Calibrate control signal
+ .INC (inc_data), // Increment counter
+ .CE (ce_data), // Clock Enable
+ .RST (rst_data), // Reset delay line
+ .BUSY (busys) // output signal indicating sync circuit has finished / calibration has finished
+);
+
+//
+// Master ISERDES
+//
+
+ISERDES2 #(
+ .DATA_WIDTH (5),
+ .DATA_RATE ("SDR"),
+ .BITSLIP_ENABLE (BITSLIP_ENABLE),
+ .SERDES_MODE ("MASTER"),
+ .INTERFACE_TYPE ("RETIMED"))
+iserdes_m (
+ .D (ddly_m),
+ .CE0 (1'b1),
+ .CLK0 (rxioclk),
+ .CLK1 (1'b0),
+ .IOCE (rxserdesstrobe),
+ .RST (reset),
+ .CLKDIV (gclk),
+ .SHIFTIN (pd_edge),
+ .BITSLIP (bitslip),
+ .FABRICOUT (),
+ .Q4 (data_out[4]),
+ .Q3 (data_out[3]),
+ .Q2 (data_out[2]),
+ .Q1 (data_out[1]),
+ .DFB (),
+ .CFB0 (),
+ .CFB1 (),
+ .VALID (valid_data),
+ .INCDEC (incdec_data),
+ .SHIFTOUT (cascade));
+
+//
+// Slave ISERDES
+//
+
+ISERDES2 #(
+ .DATA_WIDTH (5),
+ .DATA_RATE ("SDR"),
+ .BITSLIP_ENABLE (BITSLIP_ENABLE),
+ .SERDES_MODE ("SLAVE"),
+ .INTERFACE_TYPE ("RETIMED")
+) iserdes_s (
+ .D (ddly_s),
+ .CE0 (1'b1),
+ .CLK0 (rxioclk),
+ .CLK1 (1'b0),
+ .IOCE (rxserdesstrobe),
+ .RST (reset),
+ .CLKDIV (gclk),
+ .SHIFTIN (cascade),
+ .BITSLIP (bitslip),
+ .FABRICOUT (),
+ .Q4 (data_out[0]),
+ .Q3 (),
+ .Q2 (),
+ .Q1 (),
+ .DFB (),
+ .CFB0 (),
+ .CFB1 (),
+ .VALID (),
+ .INCDEC (),
+ .SHIFTOUT (pd_edge));
+
+
+reg [7:0] rxpdcntr = 8'h7f;
+always @ (posedge gclk or posedge reset) begin
+ if (reset)
+ rxpdcntr <= 8'h7f;
+ else if (ce_data)
+ if (inc_data)
+ rxpdcntr <= rxpdcntr + 1'b1;
+ else
+ rxpdcntr <= rxpdcntr - 1'b1;
+end
+
+endmodule