// This module compares two bitstreams and automatically determines their // offset. This is done by iteratively changing bit delay for I_DAT_REF // every time the number of errors exceeds ERROR_COUNT. The output O_ERROR // signal is high for at least ERROR_HOLD cycles. `default_nettype none // ============================================================================ module comparator # ( parameter ERROR_COUNT = 8, parameter ERROR_HOLD = 2500000 ) ( input wire CLK, input wire RST, input wire I_DAT_REF, input wire I_DAT_IOB, output wire O_ERROR ); // ============================================================================ // Data latch reg [2:0] i_dat_ref_sr; reg [2:0] i_dat_iob_sr; always @(posedge CLK) i_dat_ref_sr <= (i_dat_ref_sr << 1) | I_DAT_REF; always @(posedge CLK) i_dat_iob_sr <= (i_dat_iob_sr << 1) | I_DAT_IOB; wire i_dat_ref = i_dat_ref_sr[2]; wire i_dat_iob = i_dat_iob_sr[2]; // ============================================================================ // Shift register for reference data, shift strobe generator. reg [31:0] sreg; reg [ 4:0] sreg_sel; wire sreg_dat; reg sreg_sh; always @(posedge CLK) sreg <= (sreg << 1) | i_dat_ref; always @(posedge CLK) if (RST) sreg_sel <= 0; else if(sreg_sh) sreg_sel <= sreg_sel + 1; assign sreg_dat = sreg[sreg_sel]; // ============================================================================ // Comparator and error counter wire cmp_err; reg [31:0] err_cnt; assign cmp_err = sreg_dat ^ i_dat_iob; always @(posedge CLK) if (RST) err_cnt <= 0; else if(sreg_sh) err_cnt <= 0; else if(cmp_err) err_cnt <= err_cnt + 1; always @(posedge CLK) if (RST) sreg_sh <= 0; else if(~sreg_sh && (err_cnt == ERROR_COUNT)) sreg_sh <= 1; else sreg_sh <= 0; // ============================================================================ // Output generator reg [24:0] o_cnt; always @(posedge CLK) if (RST) o_cnt <= -1; else if (cmp_err) o_cnt <= ERROR_HOLD - 2; else if (~o_cnt[24]) o_cnt <= o_cnt - 1; assign O_ERROR = !o_cnt[24]; endmodule