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