mirror of https://github.com/openXC7/prjxray.git
197 lines
3.7 KiB
Verilog
197 lines
3.7 KiB
Verilog
`default_nettype none
|
|
|
|
// ============================================================================
|
|
|
|
module oserdes_test #
|
|
(
|
|
parameter DATA_WIDTH = 8,
|
|
parameter DATA_RATE = "SDR",
|
|
parameter ERROR_HOLD = 2500000
|
|
)
|
|
(
|
|
// "Hi speed" clock and reset
|
|
input wire CLK,
|
|
input wire RST,
|
|
|
|
// OSERDES clocks
|
|
input wire CLK1,
|
|
input wire CLK2,
|
|
|
|
// Data pin
|
|
inout wire IO_DAT,
|
|
|
|
// Error indicator
|
|
output wire O_ERROR
|
|
);
|
|
|
|
// ============================================================================
|
|
// Generate CLK2 and CLKDIV for OSERDES using BUFRs
|
|
|
|
localparam CLKDIV_DIVIDE =
|
|
(DATA_RATE == "SDR" && DATA_WIDTH == 2) ? "2" :
|
|
(DATA_RATE == "SDR" && DATA_WIDTH == 3) ? "3" :
|
|
(DATA_RATE == "SDR" && DATA_WIDTH == 4) ? "4" :
|
|
(DATA_RATE == "SDR" && DATA_WIDTH == 5) ? "5" :
|
|
(DATA_RATE == "SDR" && DATA_WIDTH == 6) ? "6" :
|
|
(DATA_RATE == "SDR" && DATA_WIDTH == 7) ? "7" :
|
|
(DATA_RATE == "SDR" && DATA_WIDTH == 8) ? "8" :
|
|
|
|
(DATA_RATE == "DDR" && DATA_WIDTH == 4) ? "4" :
|
|
(DATA_RATE == "DDR" && DATA_WIDTH == 6) ? "6" :
|
|
(DATA_RATE == "DDR" && DATA_WIDTH == 8) ? "8" : "BYPASS";
|
|
|
|
wire CLKX;
|
|
wire CLKDIV;
|
|
|
|
BUFIO io_buf (.I((DATA_RATE == "DDR") ? CLK2 : CLK1), .O(CLKX));
|
|
|
|
BUFR #
|
|
(
|
|
.BUFR_DIVIDE (CLKDIV_DIVIDE)
|
|
)
|
|
bufr_clkdiv
|
|
(
|
|
.I (CLK1),
|
|
.O (CLKDIV),
|
|
.CLR (RST),
|
|
.CE (1'd1)
|
|
);
|
|
|
|
// The clock enable signal for the "hi speed" clock domain.
|
|
reg clkdiv_r;
|
|
wire ce;
|
|
|
|
always @(posedge CLK)
|
|
clkdiv_r <= CLKDIV;
|
|
|
|
assign ce = clkdiv_r && !CLKDIV;
|
|
|
|
// ============================================================================
|
|
// Data source
|
|
reg lfsr_stb;
|
|
wire [7:0] lfsr_dat;
|
|
|
|
lfsr lfsr
|
|
(
|
|
.CLK (CLK),
|
|
.RST (RST),
|
|
.CE (ce),
|
|
|
|
.O (lfsr_dat)
|
|
);
|
|
|
|
always @(posedge CLK)
|
|
if (RST)
|
|
lfsr_stb <= 1'b0;
|
|
else
|
|
lfsr_stb <= ce;
|
|
|
|
// Synchronize generated data wordst to the CLKDIV
|
|
reg [7:0] ser_dat;
|
|
|
|
always @(posedge CLKDIV)
|
|
ser_dat <= lfsr_dat;
|
|
|
|
// ============================================================================
|
|
// OSERDES
|
|
|
|
// OSERDES reset generator (required for it to work properly!)
|
|
reg [3:0] ser_rst_sr;
|
|
initial ser_rst_sr <= 4'hF;
|
|
|
|
always @(posedge CLKDIV or posedge RST)
|
|
if (RST) ser_rst_sr <= 4'hF;
|
|
else ser_rst_sr <= ser_rst_sr >> 1;
|
|
|
|
wire ser_rst = ser_rst_sr[0];
|
|
|
|
// OSERDES
|
|
wire ser_oq;
|
|
wire ser_tq;
|
|
|
|
OSERDESE2 #
|
|
(
|
|
.DATA_RATE_OQ (DATA_RATE),
|
|
.DATA_WIDTH (DATA_WIDTH),
|
|
.DATA_RATE_TQ ((DATA_RATE == "DDR" && DATA_WIDTH == 4) ? "DDR" : "SDR"),
|
|
.TRISTATE_WIDTH ((DATA_RATE == "DDR" && DATA_WIDTH == 4) ? 4 : 1)
|
|
)
|
|
oserdes
|
|
(
|
|
.CLK (CLKX),
|
|
.CLKDIV (CLKDIV),
|
|
.RST (ser_rst),
|
|
|
|
.OCE (1'b1),
|
|
.D1 (ser_dat[0]),
|
|
.D2 (ser_dat[1]),
|
|
.D3 (ser_dat[2]),
|
|
.D4 (ser_dat[3]),
|
|
.D5 (ser_dat[4]),
|
|
.D6 (ser_dat[5]),
|
|
.D7 (ser_dat[6]),
|
|
.D8 (ser_dat[7]),
|
|
.OQ (ser_oq),
|
|
|
|
.TCE (1'b1),
|
|
.T1 (1'b0), // All 0 to keep OBUFT always on.
|
|
.T2 (1'b0),
|
|
.T3 (1'b0),
|
|
.T4 (1'b0),
|
|
.TQ (ser_tq)
|
|
);
|
|
|
|
// ============================================================================
|
|
// IOB
|
|
wire iob_i;
|
|
|
|
OBUFT obuf
|
|
(
|
|
.I (ser_oq),
|
|
.T (ser_tq),
|
|
.O (IO_DAT)
|
|
);
|
|
|
|
IBUF ibuf
|
|
(
|
|
.I (IO_DAT),
|
|
.O (iob_i)
|
|
);
|
|
|
|
// ============================================================================
|
|
// Reference data serializer
|
|
reg [7:0] ref_sr;
|
|
wire ref_o;
|
|
|
|
always @(posedge CLK)
|
|
if (RST)
|
|
ref_sr <= 0;
|
|
else if (ce)
|
|
ref_sr <= lfsr_dat;
|
|
else
|
|
ref_sr <= ref_sr >> 1;
|
|
|
|
assign ref_o = ref_sr[0];
|
|
|
|
// ============================================================================
|
|
// Data comparator
|
|
|
|
comparator #
|
|
(
|
|
.ERROR_COUNT (16),
|
|
.ERROR_HOLD (ERROR_HOLD)
|
|
)
|
|
comparator
|
|
(
|
|
.CLK (CLK),
|
|
.RST (RST),
|
|
|
|
.I_DAT_REF (ref_o),
|
|
.I_DAT_IOB (iob_i),
|
|
|
|
.O_ERROR (O_ERROR)
|
|
);
|
|
|
|
endmodule
|
|
|