diff options
Diffstat (limited to 'rx')
-rwxr-xr-x | rx/chnlbond.v | 170 | ||||
-rwxr-xr-x | rx/decode.v | 271 | ||||
-rwxr-xr-x | rx/decode_terc4.v | 66 | ||||
-rwxr-xr-x | rx/decodeb.v | 319 | ||||
-rwxr-xr-x | rx/decodeg.v | 319 | ||||
-rwxr-xr-x | rx/decoder.v | 318 | ||||
-rwxr-xr-x | rx/dvi_decoder.v | 634 | ||||
-rwxr-xr-x | rx/phsaligner.v | 301 | ||||
-rwxr-xr-x | rx/serdes_1_to_5_diff_data.v | 405 |
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 |