| `default_nettype none | 
 |  | 
 | // ============================================================================ | 
 |  | 
 | module error_counter # | 
 | ( | 
 | parameter COUNT_WIDTH = 24, | 
 | parameter DELAY_TAPS  = 32, | 
 |  | 
 | parameter TRIGGER_INTERVAL = 20,//100000000, | 
 | parameter HOLDOFF_TIME     = 4,//10, | 
 | parameter MEASURE_TIME     = 10//50000 | 
 | ) | 
 | ( | 
 | input  wire CLK, | 
 | input  wire RST, | 
 |  | 
 | input  wire I_STB, | 
 | input  wire I_ERR, | 
 |  | 
 | output wire DLY_LD, | 
 | output wire [$clog2(DELAY_TAPS)-1:0] DLY_CNT, | 
 |  | 
 | output wire O_STB, | 
 | output wire [COUNT_WIDTH*DELAY_TAPS-1:0] O_DAT | 
 | ); | 
 |  | 
 | // ============================================================================ | 
 | // FSM | 
 | integer fsm; | 
 |  | 
 | localparam FSM_IDLE     = 'h00; | 
 | localparam FSM_SETUP    = 'h10; | 
 | localparam FSM_HOLDOFF  = 'h20; | 
 | localparam FSM_PREPARE  = 'h30; | 
 | localparam FSM_MEASURE  = 'h40; | 
 | localparam FSM_STORE    = 'h50; | 
 | localparam FSM_OUTPUT   = 'h60; | 
 |  | 
 | // ============================================================================ | 
 | // Counters | 
 | reg [32:0] ps_cnt; | 
 | reg [$clog2(DELAY_TAPS)-1:0] dly_cnt; | 
 |  | 
 | initial ps_cnt <= TRIGGER_INTERVAL - 1; | 
 |  | 
 | always @(posedge CLK) | 
 |     case (fsm) | 
 |  | 
 |     FSM_IDLE:       ps_cnt <= ps_cnt - 1; | 
 |     FSM_SETUP:      ps_cnt <= HOLDOFF_TIME - 1; | 
 |     FSM_HOLDOFF:    ps_cnt <= ps_cnt - 1; | 
 |     FSM_PREPARE:    ps_cnt <= MEASURE_TIME - 1; | 
 |     FSM_MEASURE:    ps_cnt <= ps_cnt - 1; | 
 |     FSM_OUTPUT:     ps_cnt <= TRIGGER_INTERVAL - 1; | 
 |  | 
 |     endcase | 
 |  | 
 | always @(posedge CLK) | 
 |     case (fsm) | 
 |  | 
 |     FSM_IDLE:       dly_cnt <= 0; | 
 |     FSM_STORE:      dly_cnt <= dly_cnt + 1; | 
 |  | 
 |     endcase | 
 |  | 
 | // ============================================================================ | 
 | // IDELAY control | 
 | assign DLY_LD  = (fsm == FSM_SETUP); | 
 | assign DLY_CNT = dly_cnt; | 
 |  | 
 | // ============================================================================ | 
 | // Error counter and output shift register | 
 | reg [(COUNT_WIDTH*DELAY_TAPS)-1:0] o_dat_sr; | 
 | reg [COUNT_WIDTH-1:0] err_cnt; | 
 |  | 
 | always @(posedge CLK) | 
 |     case (fsm) | 
 |  | 
 |     FSM_PREPARE:           err_cnt <= 0; | 
 |     FSM_MEASURE: if(I_STB) err_cnt <= err_cnt + I_ERR; | 
 |  | 
 |     endcase | 
 |  | 
 | always @(posedge CLK) | 
 |     if (fsm == FSM_STORE) | 
 |         o_dat_sr <= (o_dat_sr << COUNT_WIDTH) | err_cnt; | 
 |  | 
 | // ============================================================================ | 
 | // Control FSM | 
 | always @(posedge CLK) | 
 |     if (RST) | 
 |         fsm <= FSM_IDLE; | 
 |     else case (fsm) | 
 |  | 
 |     FSM_IDLE:       if (ps_cnt == 0)  fsm <= FSM_SETUP; | 
 |     FSM_SETUP:      fsm <= FSM_HOLDOFF; | 
 |     FSM_HOLDOFF:    if (ps_cnt == 0)  fsm <= FSM_PREPARE; | 
 |     FSM_PREPARE:    fsm <= FSM_MEASURE; | 
 |     FSM_MEASURE:    if (ps_cnt == 0)  fsm <= FSM_STORE; | 
 |     FSM_STORE:      if (dly_cnt == (DELAY_TAPS-1)) | 
 |                         fsm <= FSM_OUTPUT; | 
 |                     else | 
 |                         fsm <= FSM_SETUP; | 
 |     FSM_OUTPUT:     fsm <= FSM_IDLE; | 
 |  | 
 |     endcase | 
 |  | 
 | // ============================================================================ | 
 | // Output | 
 | assign O_STB = (fsm == FSM_OUTPUT); | 
 | assign O_DAT = o_dat_sr; | 
 |  | 
 | endmodule | 
 |  |