From 889a5a5395872eeb3740d5d3281b56c7afa47a6f Mon Sep 17 00:00:00 2001 From: bnewbold Date: Fri, 20 Jan 2012 19:14:58 -0500 Subject: initial import from NeTV archive This repository is simply a mirror of the file fpga/hdmi_overlay_0xD_src.tgz downloaded from http://www.kosagi.com/netv_hardware/ on Jan 19th, 2011. It seems to contain all the verilog and scripts required to build FPGA firmware for the NeTV HDMI device from Chumby/Sutajio Ko-Usagi; see http://www.kosagi.com/blog/ for more information. Licensing is vague; see ip/license.txt --- rx/serdes_1_to_5_diff_data.v | 405 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 405 insertions(+) create mode 100755 rx/serdes_1_to_5_diff_data.v (limited to 'rx/serdes_1_to_5_diff_data.v') 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 -- cgit v1.2.3