blob: ae3562f06756858128b96dee4181798af7bd8517 [file] [log] [blame]
`default_nettype none
// ============================================================================
module receiver #
(
parameter WIDTH = 8,
parameter MODE = "SDR"
)
(
input wire CLK,
input wire RST,
input wire I_CLK,
input wire I_DAT,
output wire O_STB,
output wire [WIDTH-1:0] O_DAT,
input wire O_BITSLIP
);
// ============================================================================
// CLKDIV generation using a BUFR
wire i_clkdiv;
wire i_rstdiv;
// Divider for BUFR
localparam DIVIDE = (MODE == "SDR" && WIDTH == 2) ? "2" :
(MODE == "SDR" && WIDTH == 3) ? "3" :
(MODE == "SDR" && WIDTH == 4) ? "4" :
(MODE == "SDR" && WIDTH == 5) ? "5" :
(MODE == "SDR" && WIDTH == 6) ? "6" :
(MODE == "SDR" && WIDTH == 7) ? "7" :
(MODE == "SDR" && WIDTH == 8) ? "8" :
(MODE == "DDR" && WIDTH == 4) ? "2" :
(MODE == "DDR" && WIDTH == 6) ? "3" :
(MODE == "DDR" && WIDTH == 8) ? "4" : "BYPASS";
// BUFR
BUFR #
(
.BUFR_DIVIDE (DIVIDE)
)
bufr_div
(
.I (I_CLK),
.O (i_clkdiv),
.CLR (1'b0),
.CE (1'b1)
);
// ISERDES reset generator
reg [3:0] rst_sr;
initial rst_sr <= 4'hF;
always @(posedge i_clkdiv)
if (RST) rst_sr <= 4'hF;
else rst_sr <= rst_sr >> 1;
assign i_rstdiv = rst_sr[0];
// ============================================================================
// ISERDES
wire [7:0] d_dat;
(* KEEP, DONT_TOUCH *)
ISERDESE2 #
(
.DATA_RATE (MODE),
.DATA_WIDTH (WIDTH),
.INTERFACE_TYPE ("NETWORKING"),
.IS_CLKB_INVERTED (1'b1) // Do we have bits for that ??
)
iserdes
(
.CLK (I_CLK),
.CLKB (I_CLK),
.CLKDIV (i_clkdiv),
.CE1 (1'b1),
.CE2 (1'b1),
.RST (i_rstdiv),
.BITSLIP (bitslip),
.D (I_DAT),
.Q1 (d_dat[0]),
.Q2 (d_dat[1]),
.Q3 (d_dat[2]),
.Q4 (d_dat[3]),
.Q5 (d_dat[4]),
.Q6 (d_dat[5]),
.Q7 (d_dat[6]),
.Q8 (d_dat[7])
);
// ============================================================================
// Generate strobe synchronous to CLK
reg clk_p;
reg tick;
always @(posedge CLK)
clk_p <= i_clkdiv;
always @(posedge CLK)
if (RST)
tick <= 1'b0;
else
tick <= !clk_p && i_clkdiv;
// ============================================================================
// Bitslip. The bitslip signal should be synchronous to the CLKDIV. Here it is
// asserted for as long as the CLKDIV period but it is not synchronous to it.
reg bitslip_req;
reg bitslip;
always @(posedge CLK)
if (RST)
bitslip_req <= 1'b0;
else if (!bitslip_req && O_BITSLIP)
bitslip_req <= 1'b1;
else if (tick)
bitslip_req <= 1'b0;
always @(posedge CLK)
if (RST)
bitslip <= 1'd0;
else if (tick)
bitslip <= bitslip_req;
// ============================================================================
// Output sync to CLK
reg x_stb;
reg o_stb;
reg [WIDTH-1:0] o_dat;
always @(posedge CLK)
if (RST)
x_stb <= 1'b0;
else if(!x_stb && tick)
x_stb <= 1'b1;
else if( x_stb)
x_stb <= 1'b0;
always @(posedge CLK)
if (RST)
o_stb <= 1'd0;
else
o_stb <= x_stb;
always @(posedge CLK)
if (x_stb)
o_dat <= d_dat;
assign O_STB = o_stb;
assign O_DAT = o_dat[WIDTH-1:0];
endmodule