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