📄 oversample_8x.v
字号:
//------------------------------------------------------------------------------
// Copyright (c) 2006 Xilinx, Inc.
// All Rights Reserved
//------------------------------------------------------------------------------
// ____ ____
// / /\/ /
// /___/ \ / Vendor: Xilinx
// \ \ \/ Author: John F. Snow, Advanced Product Division, Xilinx, Inc.
// \ \ Filename: $RCSfile: oversample_8x.v,rcs $
// / / Date Last Modified: $Date: 2006-09-22 14:00:22-06 $
// /___/ /\ Date Created: Jan 13, 2006
// \ \ / \
// \___\/\___\
//
//
// Revision History:
// $Log: oversample_8x.v,rcs $
// Revision 1.0 2006-09-22 14:00:22-06 jsnow
// Initial release.
//
//------------------------------------------------------------------------------
//
// XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS"
// SOLELY FOR USE IN DEVELOPING PROGRAMS AND SOLUTIONS FOR
// XILINX DEVICES. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION
// AS ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION
// OR STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS
// IMPLEMENTATION IS FREE FROM ANY CLAIMS OF INFRINGEMENT,
// AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
// FOR YOUR IMPLEMENTATION. XILINX EXPRESSLY DISCLAIMS ANY
// WARRANTY WHATSOEVER WITH RESPECT TO THE ADEQUACY OF THE
// IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OR
// REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM CLAIMS OF
// INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE.
//
//------------------------------------------------------------------------------
//
// This is a single channel 8X oversampling data recovery unit using bit-rate
// clocks. It requires two phases of a clock running at the bit rate and uses
// two IDELAY primitives to provide the 45 degree phase shifting of the serial
// data.
//
//------------------------------------------------------------------------------
module oversample_8x (
input wire clk0, // bit rate clock
input wire clk90, // clk0 shifted 90 degrees
input wire PAD_din_p, // serial input data
input wire PAD_din_n, // inverted serial input data
output reg dout_rdy, // output data ready
output reg [19:0] dout); // output data
parameter IDELAY_45_DEGREES = 6; // Specifies the delay for a
// 1/8 bit delay with IDELAY.
// 6 is correct value for 270 Mb/s.
//-----------------------------------------------------------------------------
// Signal definitions
//
wire sdata_in; // true output of IBUFDS_DIFF_OUT
wire sdata_inb; // complementary output of IBUFDS_DIFF_OUT
wire sdat_0_dly; // 0 degree data from IDELAY
wire sdatb_45_dly; // 45 degree data from IDELAY
(* EQUIVALENT_REGISTER_REMOVAL = "NO" *)
(* SHREG_EXTRACT = "NO" *)
wire a1, a2, a3; // 0 degree capture pipeline
(* EQUIVALENT_REGISTER_REMOVAL = "NO" *)
(* SHREG_EXTRACT = "NO" *)
wire b1, b2, b3; // 45 degree capture pipeline
(* EQUIVALENT_REGISTER_REMOVAL = "NO" *)
(* SHREG_EXTRACT = "NO" *)
wire c1, c2, c3; // 90 degree capture pipeline
(* EQUIVALENT_REGISTER_REMOVAL = "NO" *)
(* SHREG_EXTRACT = "NO" *)
wire d1, d2, d3; // 135 degree capture pipeline
(* EQUIVALENT_REGISTER_REMOVAL = "NO" *)
(* SHREG_EXTRACT = "NO" *)
wire e1, e2, e3; // 180 degree capture pipeline
(* EQUIVALENT_REGISTER_REMOVAL = "NO" *)
(* SHREG_EXTRACT = "NO" *)
wire f1, f2, f3; // 225 degree capture pipeline
(* EQUIVALENT_REGISTER_REMOVAL = "NO" *)
(* SHREG_EXTRACT = "NO" *)
wire g1, g2, g3; // 270 degree capture pipeline
(* EQUIVALENT_REGISTER_REMOVAL = "NO" *)
(* SHREG_EXTRACT = "NO" *)
wire h1, h2, h3; // 315 degree capture pipeline
wire [7:0] instage_dout; // 8X oversampled data from input stage
reg [7:0] samples_0 = 8'b0; // used to make 20-bit dout vector
reg [7:0] samples_1 = 8'b0; // used to make 20-bit dout vector
reg [7:0] samples_2 = 8'b0; // used to make 20-bit dout vector
(* KEEP = "TRUE" *)
reg [4:0] period = 5'b00001; // sequencer for 20-bit vector creation
//
// The IBUFDS_DIFF_OUT primitive provides both true and complementary outputs
// of an LVDS input pair.
//
(* DIFF_TERM = "TRUE" *)
IBUFDS_DIFF_OUT # (
.IOSTANDARD ("LVDS_25"))
IBUFSDI (
.I (PAD_din_p),
.IB (PAD_din_n),
.O (sdata_in),
.OB (sdata_inb));
//
// IDELAY primitives
//
// Two IDELAY primitives are used to create two phases of the data, one delayed
// 45 degrees relative to the other. Note that IDELAY block with 0 delay
// actually provides the data delayed by 45 degrees relative to the output
// of the other IDELAY block because the IDELAY primitive with the higher
// delay is providing older data. Also note that the 45 degree delayed data
// is inverted. This inversion is correct at the output of this module.
//
IDELAY #(
.IOBDELAY_TYPE ("FIXED"),
.IOBDELAY_VALUE (IDELAY_45_DEGREES))
IDLY (
.O (sdat_0_dly),
.C (1'b0),
.CE (1'b0),
.I (sdata_in),
.INC (1'b0),
.RST (1'b0));
IDELAY #(
.IOBDELAY_TYPE ("FIXED"),
.IOBDELAY_VALUE (0))
IDLYB (
.O (sdatb_45_dly),
.C (1'b0),
.CE (1'b0),
.I (sdata_inb),
.INC (1'b0),
.RST (1'b0));
//
// Data capture flip flops
//
// These FFs sample the data and transfer all samples into a common clock
// domain -- the rising edge of the clk0 phase.
//
// All FFs are instantiated as FF primitives so that they can be easily RLOCed
// relative to each other to keep routing delay and skew to a minimum.
//
//
// These 3 FFs provide the 0 degree sample point.
//
(* RLOC = "X1Y1" *)
(* IOB = "FALSE" *)
FDCPE a1FF (
.Q (a1),
.C (clk0),
.CE (1'b1),
.CLR (1'b0),
.D (sdat_0_dly),
.PRE (1'b0));
FDCPE a2FF (
.Q (a2),
.C (clk0),
.CE (1'b1),
.CLR (1'b0),
.D (a1),
.PRE (1'b0));
FDCPE a3FF (
.Q (a3),
.C (clk0),
.CE (1'b1),
.CLR (1'b0),
.D (a2),
.PRE (1'b0));
//
// These 3 FFs provide the 45 degree sample point.
//
(* RLOC = "X1Y1" *)
(* IOB = "FALSE" *)
FDCPE b1FF (
.Q (b1),
.C (clk0),
.CE (1'b1),
.CLR (1'b0),
.D (sdatb_45_dly),
.PRE (1'b0));
FDCPE b2FF (
.Q (b2),
.C (clk0),
.CE (1'b1),
.CLR (1'b0),
.D (b1),
.PRE (1'b0));
FDCPE b3FF (
.Q (b3),
.C (clk0),
.CE (1'b1),
.CLR (1'b0),
.D (b2),
.PRE (1'b0));
//
// These 3 FFs provide the 90 degree sample point.
//
(* RLOC = "X1Y0" *)
(* IOB = "FALSE" *)
FDCPE c1FF (
.Q (c1),
.C (clk90),
.CE (1'b1),
.CLR (1'b0),
.D (sdat_0_dly),
.PRE (1'b0));
FDCPE c2FF (
.Q (c2),
.C (clk0),
.CE (1'b1),
.CLR (1'b0),
.D (c1),
.PRE (1'b0));
FDCPE c3FF (
.Q (c3),
.C (clk0),
.CE (1'b1),
.CLR (1'b0),
.D (c2),
.PRE (1'b0));
//
// These 3 FFs provide the 135 degree sample point.
//
(* RLOC = "X1Y0" *)
(* IOB = "FALSE" *)
FDCPE d1FF (
.Q (d1),
.C (clk90),
.CE (1'b1),
.CLR (1'b0),
.D (sdatb_45_dly),
.PRE (1'b0));
FDCPE d2FF (
.Q (d2),
.C (clk0),
.CE (1'b1),
.CLR (1'b0),
.D (d1),
.PRE (1'b0));
FDCPE d3FF (
.Q (d3),
.C (clk0),
.CE (1'b1),
.CLR (1'b0),
.D (d2),
.PRE (1'b0));
//
// These 3 FFs provide the 180 degree sample point.
//
(* RLOC = "X0Y1" *)
(* IOB = "FALSE" *)
FDCPE e1FF (
.Q (e1),
.C (~clk0),
.CE (1'b1),
.CLR (1'b0),
.D (sdat_0_dly),
.PRE (1'b0));
FDCPE e2FF (
.Q (e2),
.C (~clk0),
.CE (1'b1),
.CLR (1'b0),
.D (e1),
.PRE (1'b0));
FDCPE e3FF (
.Q (e3),
.C (clk0),
.CE (1'b1),
.CLR (1'b0),
.D (e2),
.PRE (1'b0));
//
// These 3 FFs provide the 225 degree sample point.
//
(* RLOC = "X0Y1" *)
(* IOB = "FALSE" *)
FDCPE f1FF (
.Q (f1),
.C (~clk0),
.CE (1'b1),
.CLR (1'b0),
.D (sdatb_45_dly),
.PRE (1'b0));
FDCPE f2FF (
.Q (f2),
.C (~clk0),
.CE (1'b1),
.CLR (1'b0),
.D (f1),
.PRE (1'b0));
FDCPE f3FF (
.Q (f3),
.C (clk0),
.CE (1'b1),
.CLR (1'b0),
.D (f2),
.PRE (1'b0));
//
// These 3 FFs provide the 270 degree sample point.
//
(* RLOC = "X0Y0" *)
(* IOB = "FALSE" *)
FDCPE g1FF (
.Q (g1),
.C (~clk90),
.CE (1'b1),
.CLR (1'b0),
.D (sdat_0_dly),
.PRE (1'b0));
FDCPE g2FF (
.Q (g2),
.C (~clk0),
.CE (1'b1),
.CLR (1'b0),
.D (g1),
.PRE (1'b0));
FDCPE g3FF (
.Q (g3),
.C (clk0),
.CE (1'b1),
.CLR (1'b0),
.D (g2),
.PRE (1'b0));
//
// These 3 FFs provide the 315 degree sample point.
//
(* RLOC = "X0Y0" *)
(* IOB = "FALSE" *)
FDCPE h1FF (
.Q (h1),
.C (~clk90),
.CE (1'b1),
.CLR (1'b0),
.D (sdatb_45_dly),
.PRE (1'b0));
FDCPE h2FF (
.Q (h2),
.C (~clk0),
.CE (1'b1),
.CLR (1'b0),
.D (h1),
.PRE (1'b0));
FDCPE h3FF (
.Q (h3),
.C (clk0),
.CE (1'b1),
.CLR (1'b0),
.D (h2),
.PRE (1'b0));
//
// Input stage vector assignment. All samples created from the 45 degree data
// must be inverted to compensate for the fact that the 45 degree data is
// inverted.
//
assign instage_dout = {~h3, g3, ~f3, e3, ~d3, c3, ~b3, a3};
//
// 8-bit to 20-bit conversion
//
// This logic takes the 8 samples produced by the input stage every rising edge
// of clk0 and saves up 5 consecutive sets of these samples to create two
// 20-bit sample output vectors.
//
always @ (posedge clk0)
period <= {period[3:0], period[4]};
always @ (posedge clk0)
if (period[0] | period[3])
samples_0 <= instage_dout;
always @ (posedge clk0)
if (period[1] | period[4])
samples_1 <= instage_dout;
always @ (posedge clk0)
if (period[2])
samples_2 <= instage_dout;
always @ (posedge clk0)
if (period[3])
dout <= {samples_2[3:0], samples_1, samples_0};
else if (period[0])
dout <= {samples_1, samples_0, samples_2[7:4]};
//
// To provide the maximum amount of setup time into the DRU, the dout_rdy signal
// is asserted during the clock cycle just before dout is updated. Thus, the
// DRU takes the last data on the same clock edge on which dout is updated with
// new data.
//
always @ (posedge clk0)
dout_rdy <= period[2] | period[4];
endmodule
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -