| `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 | 
 |  |