mirror of https://github.com/openXC7/prjxray.git
122 lines
3.0 KiB
Verilog
122 lines
3.0 KiB
Verilog
// Copyright (C) 2017-2020 The Project X-Ray Authors.
|
|
//
|
|
// Use of this source code is governed by a ISC-style
|
|
// license that can be found in the LICENSE file or at
|
|
// https://opensource.org/licenses/ISC
|
|
//
|
|
// SPDX-License-Identifier: ISC
|
|
|
|
`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
|
|
|