Commit aa3a163b authored by Dimitris Lampridis's avatar Dimitris Lampridis

[hdl] Split channel CSR from FIFO readout. *PLEASE TEST g_use_fifo_readout mode*!

parent d5ef17f8
......@@ -22,6 +22,8 @@ files = [
"fmc_tdc_direct_readout_slave_pkg.vhd",
"fmc_tdc_wrapper.vhd",
"timestamp_fifo.vhd",
"channel_regs.vhd",
"channel_regs_wbgen2_pkg.vhd",
"timestamp_fifo_wb.vhd",
"timestamp_fifo_wbgen2_pkg.vhd",
"timestamp_convert_filter.vhd",
......
---------------------------------------------------------------------------------------
-- Title : Wishbone slave core for Channel registers
---------------------------------------------------------------------------------------
-- File : channel_regs.vhd
-- Author : auto-generated by wbgen2 from wbgen/channel_regs.wb
-- Created : Thu Sep 26 16:43:02 2019
-- Standard : VHDL'87
---------------------------------------------------------------------------------------
-- THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE wbgen/channel_regs.wb
-- DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
---------------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
use work.ch_reg_wbgen2_pkg.all;
entity channel_regs is
port (
rst_n_i : in std_logic;
clk_sys_i : in std_logic;
slave_i : in t_wishbone_slave_in;
slave_o : out t_wishbone_slave_out;
int_o : out std_logic;
regs_i : in t_ch_reg_in_registers;
regs_o : out t_ch_reg_out_registers
);
end channel_regs;
architecture syn of channel_regs is
signal ch_reg_offset1_int : std_logic_vector(31 downto 0);
signal ch_reg_offset2_int : std_logic_vector(31 downto 0);
signal ch_reg_offset3_int : std_logic_vector(31 downto 0);
signal ch_reg_csr_delta_read_dly0 : std_logic ;
signal ch_reg_csr_delta_read_int : std_logic ;
signal ch_reg_csr_rst_seq_dly0 : std_logic ;
signal ch_reg_csr_rst_seq_int : std_logic ;
signal ch_reg_csr_delta_ref_int : std_logic_vector(2 downto 0);
signal ch_reg_csr_raw_mode_int : std_logic ;
signal ack_sreg : std_logic_vector(9 downto 0);
signal rddata_reg : std_logic_vector(31 downto 0);
signal wrdata_reg : std_logic_vector(31 downto 0);
signal bwsel_reg : std_logic_vector(3 downto 0);
signal rwaddr_reg : std_logic_vector(2 downto 0);
signal ack_in_progress : std_logic ;
signal wr_int : std_logic ;
signal rd_int : std_logic ;
signal allones : std_logic_vector(31 downto 0);
signal allzeros : std_logic_vector(31 downto 0);
begin
-- Some internal signals assignments
wrdata_reg <= slave_i.dat;
--
-- Main register bank access process.
process (clk_sys_i, rst_n_i)
begin
if (rst_n_i = '0') then
ack_sreg <= "0000000000";
ack_in_progress <= '0';
rddata_reg <= "00000000000000000000000000000000";
ch_reg_offset1_int <= "00000000000000000000000000000000";
ch_reg_offset2_int <= "00000000000000000000000000000000";
ch_reg_offset3_int <= "00000000000000000000000000000000";
ch_reg_csr_delta_read_int <= '0';
ch_reg_csr_rst_seq_int <= '0';
ch_reg_csr_delta_ref_int <= "000";
ch_reg_csr_raw_mode_int <= '0';
elsif rising_edge(clk_sys_i) then
-- advance the ACK generator shift register
ack_sreg(8 downto 0) <= ack_sreg(9 downto 1);
ack_sreg(9) <= '0';
if (ack_in_progress = '1') then
if (ack_sreg(0) = '1') then
ch_reg_csr_delta_read_int <= '0';
ch_reg_csr_rst_seq_int <= '0';
ack_in_progress <= '0';
else
end if;
else
if ((slave_i.cyc = '1') and (slave_i.stb = '1')) then
case rwaddr_reg(2 downto 0) is
when "000" =>
if (slave_i.we = '1') then
end if;
rddata_reg(31 downto 0) <= regs_i.delta1_i;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "001" =>
if (slave_i.we = '1') then
end if;
rddata_reg(31 downto 0) <= regs_i.delta2_i;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "010" =>
if (slave_i.we = '1') then
end if;
rddata_reg(31 downto 0) <= regs_i.delta3_i;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "011" =>
if (slave_i.we = '1') then
ch_reg_offset1_int <= wrdata_reg(31 downto 0);
end if;
rddata_reg(31 downto 0) <= ch_reg_offset1_int;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "100" =>
if (slave_i.we = '1') then
ch_reg_offset2_int <= wrdata_reg(31 downto 0);
end if;
rddata_reg(31 downto 0) <= ch_reg_offset2_int;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "101" =>
if (slave_i.we = '1') then
ch_reg_offset3_int <= wrdata_reg(31 downto 0);
end if;
rddata_reg(31 downto 0) <= ch_reg_offset3_int;
ack_sreg(0) <= '1';
ack_in_progress <= '1';
when "110" =>
if (slave_i.we = '1') then
ch_reg_csr_delta_read_int <= wrdata_reg(1);
ch_reg_csr_rst_seq_int <= wrdata_reg(2);
ch_reg_csr_delta_ref_int <= wrdata_reg(5 downto 3);
ch_reg_csr_raw_mode_int <= wrdata_reg(6);
end if;
rddata_reg(0) <= regs_i.csr_delta_ready_i;
rddata_reg(1) <= '0';
rddata_reg(2) <= '0';
rddata_reg(5 downto 3) <= ch_reg_csr_delta_ref_int;
rddata_reg(6) <= ch_reg_csr_raw_mode_int;
rddata_reg(7) <= 'X';
rddata_reg(8) <= 'X';
rddata_reg(9) <= 'X';
rddata_reg(10) <= 'X';
rddata_reg(11) <= 'X';
rddata_reg(12) <= 'X';
rddata_reg(13) <= 'X';
rddata_reg(14) <= 'X';
rddata_reg(15) <= 'X';
rddata_reg(16) <= 'X';
rddata_reg(17) <= 'X';
rddata_reg(18) <= 'X';
rddata_reg(19) <= 'X';
rddata_reg(20) <= 'X';
rddata_reg(21) <= 'X';
rddata_reg(22) <= 'X';
rddata_reg(23) <= 'X';
rddata_reg(24) <= 'X';
rddata_reg(25) <= 'X';
rddata_reg(26) <= 'X';
rddata_reg(27) <= 'X';
rddata_reg(28) <= 'X';
rddata_reg(29) <= 'X';
rddata_reg(30) <= 'X';
rddata_reg(31) <= 'X';
ack_sreg(2) <= '1';
ack_in_progress <= '1';
when others =>
-- prevent the slave from hanging the bus on invalid address
ack_in_progress <= '1';
ack_sreg(0) <= '1';
end case;
end if;
end if;
end if;
end process;
-- Drive the data output bus
slave_o.dat <= rddata_reg;
-- Delta Timestamp Word 1 (TAI cycles, signed)
-- Delta Timestamp Word 2 (8ns ticks, unsigned)
-- Delta Timestamp Word 3 (fractional part, unsigned)
-- Channel Offset Word 1 (TAI cycles, signed)
regs_o.offset1_o <= ch_reg_offset1_int;
-- Channel Offset Word 2 (8ns ticks, unsigned)
regs_o.offset2_o <= ch_reg_offset2_int;
-- Channel Offset Word 3 (fractional part, unsigned)
regs_o.offset3_o <= ch_reg_offset3_int;
-- Delta Timestamp Ready
-- Read Delta Timestamp
process (clk_sys_i, rst_n_i)
begin
if (rst_n_i = '0') then
ch_reg_csr_delta_read_dly0 <= '0';
regs_o.csr_delta_read_o <= '0';
elsif rising_edge(clk_sys_i) then
ch_reg_csr_delta_read_dly0 <= ch_reg_csr_delta_read_int;
regs_o.csr_delta_read_o <= ch_reg_csr_delta_read_int and (not ch_reg_csr_delta_read_dly0);
end if;
end process;
-- Reset Sequence Counter
process (clk_sys_i, rst_n_i)
begin
if (rst_n_i = '0') then
ch_reg_csr_rst_seq_dly0 <= '0';
regs_o.csr_rst_seq_o <= '0';
elsif rising_edge(clk_sys_i) then
ch_reg_csr_rst_seq_dly0 <= ch_reg_csr_rst_seq_int;
regs_o.csr_rst_seq_o <= ch_reg_csr_rst_seq_int and (not ch_reg_csr_rst_seq_dly0);
end if;
end process;
-- Delta Timestamp Reference Channel
regs_o.csr_delta_ref_o <= ch_reg_csr_delta_ref_int;
-- Raw readout mode
regs_o.csr_raw_mode_o <= ch_reg_csr_raw_mode_int;
rwaddr_reg <= slave_i.adr(4 downto 2);
slave_o.stall <= (not ack_sreg(0)) and (slave_i.stb and slave_i.cyc);
slave_o.err <= '0';
slave_o.rty <= '0';
-- ACK signal generation. Just pass the LSB of ACK counter.
slave_o.ack <= ack_sreg(0);
end syn;
---------------------------------------------------------------------------------------
-- Title : Wishbone slave core for Channel registers
---------------------------------------------------------------------------------------
-- File : channel_regs_wbgen2_pkg.vhd
-- Author : auto-generated by wbgen2 from wbgen/channel_regs.wb
-- Created : Thu Sep 26 16:43:02 2019
-- Standard : VHDL'87
---------------------------------------------------------------------------------------
-- THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE wbgen/channel_regs.wb
-- DO NOT HAND-EDIT UNLESS IT'S ABSOLUTELY NECESSARY!
---------------------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.wishbone_pkg.all;
package ch_reg_wbgen2_pkg is
-- Input registers (user design -> WB slave)
type t_ch_reg_in_registers is record
delta1_i : std_logic_vector(31 downto 0);
delta2_i : std_logic_vector(31 downto 0);
delta3_i : std_logic_vector(31 downto 0);
csr_delta_ready_i : std_logic;
end record;
constant c_ch_reg_in_registers_init_value: t_ch_reg_in_registers := (
delta1_i => (others => '0'),
delta2_i => (others => '0'),
delta3_i => (others => '0'),
csr_delta_ready_i => '0'
);
-- Output registers (WB slave -> user design)
type t_ch_reg_out_registers is record
offset1_o : std_logic_vector(31 downto 0);
offset2_o : std_logic_vector(31 downto 0);
offset3_o : std_logic_vector(31 downto 0);
csr_delta_read_o : std_logic;
csr_rst_seq_o : std_logic;
csr_delta_ref_o : std_logic_vector(2 downto 0);
csr_raw_mode_o : std_logic;
end record;
constant c_ch_reg_out_registers_init_value: t_ch_reg_out_registers := (
offset1_o => (others => '0'),
offset2_o => (others => '0'),
offset3_o => (others => '0'),
csr_delta_read_o => '0',
csr_rst_seq_o => '0',
csr_delta_ref_o => (others => '0'),
csr_raw_mode_o => '0'
);
function "or" (left, right: t_ch_reg_in_registers) return t_ch_reg_in_registers;
function f_x_to_zero (x:std_logic) return std_logic;
function f_x_to_zero (x:std_logic_vector) return std_logic_vector;
component channel_regs is
port (
rst_n_i : in std_logic;
clk_sys_i : in std_logic;
slave_i : in t_wishbone_slave_in;
slave_o : out t_wishbone_slave_out;
int_o : out std_logic;
regs_i : in t_ch_reg_in_registers;
regs_o : out t_ch_reg_out_registers
);
end component;
end package;
package body ch_reg_wbgen2_pkg is
function f_x_to_zero (x:std_logic) return std_logic is
begin
if x = '1' then
return '1';
else
return '0';
end if;
end function;
function f_x_to_zero (x:std_logic_vector) return std_logic_vector is
variable tmp: std_logic_vector(x'length-1 downto 0);
begin
for i in 0 to x'length-1 loop
if(x(i) = '1') then
tmp(i):= '1';
else
tmp(i):= '0';
end if;
end loop;
return tmp;
end function;
function "or" (left, right: t_ch_reg_in_registers) return t_ch_reg_in_registers is
variable tmp: t_ch_reg_in_registers;
begin
tmp.delta1_i := f_x_to_zero(left.delta1_i) or f_x_to_zero(right.delta1_i);
tmp.delta2_i := f_x_to_zero(left.delta2_i) or f_x_to_zero(right.delta2_i);
tmp.delta3_i := f_x_to_zero(left.delta3_i) or f_x_to_zero(right.delta3_i);
tmp.csr_delta_ready_i := f_x_to_zero(left.csr_delta_ready_i) or f_x_to_zero(right.csr_delta_ready_i);
return tmp;
end function;
end package body;
......@@ -224,7 +224,8 @@ architecture rtl of fmc_tdc_mezzanine is
constant c_WB_SLAVE_TDC_CORE_CONFIG : integer := 1; -- TDC core configuration registers
constant c_WB_SLAVE_TDC_EIC : integer := 2; -- TDC interrupts
constant c_WB_SLAVE_TDC_I2C : integer := 3; -- TDC mezzanine board system EEPROM I2C
constant c_WB_SLAVE_TDC_FIFO0 : integer := 4; -- Access to TDC core FIFO for timestamps retrieval
constant c_WB_SLAVE_TDC_CHANNEL0 : integer := 4; -- Access to TDC core channel registers
-- and FIFO for timestamps retrieval
constant c_WB_SLAVE_TDC_DMA : integer := 9; -- Access to TDC core DMA controller
-- Slave port on the wishbone crossbar
......@@ -436,42 +437,29 @@ begin
timestamp_o <= timestamp;
timestamp_valid_o <= timestamp_valid;
gen_enable_fifo_readout : if g_use_fifo_readout generate
gen_fifos : for i in 0 to 4 generate
U_TheFifo : entity work.timestamp_fifo
port map (
clk_sys_i => clk_sys_i,
rst_sys_n_i => rst_sys_n_i,
slave_i => cnx_master_out(c_WB_SLAVE_TDC_FIFO0 + i),
slave_o => cnx_master_in(c_WB_SLAVE_TDC_FIFO0 + i),
irq_o => irq_fifo(i),
enable_i => channel_enable(i),
tick_i => tick_1ms,
irq_threshold_i => irq_threshold,
irq_timeout_i => irq_timeout,
timestamp_i => timestamp(i),
timestamp_valid_i => timestamp_stb(i),
ts_offset_o => ts_offset(i),
reset_seq_o => reset_seq(i),
raw_enable_o => raw_enable(i));
timestamp_stb(i) <= timestamp_valid(i) and timestamp_ready(i);
end generate gen_fifos;
end generate gen_enable_fifo_readout;
gen_disable_fifo_readout : if not g_use_fifo_readout generate
gen_fifos : for i in 0 to 4 generate
timestamp_ready(i) <= '1';
cnx_master_in(c_WB_SLAVE_TDC_FIFO0 + i).ack <= '1';
cnx_master_in(c_WB_SLAVE_TDC_FIFO0 + i).stall <= '0';
cnx_master_in(c_WB_SLAVE_TDC_FIFO0 + i).err <= '0';
cnx_master_in(c_WB_SLAVE_TDC_FIFO0 + i).rty <= '0';
end generate gen_fifos;
end generate gen_disable_fifo_readout;
gen_fifos : for i in 0 to 4 generate
U_TheFifo : entity work.timestamp_fifo
generic map (
g_use_fifo_readout => g_use_fifo_readout)
port map (
clk_sys_i => clk_sys_i,
rst_sys_n_i => rst_sys_n_i,
slave_i => cnx_master_out(c_WB_SLAVE_TDC_CHANNEL0 + i),
slave_o => cnx_master_in(c_WB_SLAVE_TDC_CHANNEL0 + i),
irq_o => irq_fifo(i),
enable_i => channel_enable(i),
tick_i => tick_1ms,
irq_threshold_i => irq_threshold,
irq_timeout_i => irq_timeout,
timestamp_i => timestamp(i),
timestamp_valid_i => timestamp_stb(i),
ts_offset_o => ts_offset(i),
reset_seq_o => reset_seq(i),
raw_enable_o => raw_enable(i));
timestamp_stb(i) <= timestamp_valid(i) and timestamp_ready(i);
end generate gen_fifos;
gen_with_dma_readout : if g_use_dma_readout generate
U_DMA_Engine : entity work.tdc_dma_engine
......
......@@ -23,11 +23,14 @@ use ieee.std_logic_1164.all;
use ieee.NUMERIC_STD.all;
use work.tsf_wbgen2_pkg.all;
use work.ch_reg_wbgen2_pkg.all;
use work.tdc_core_pkg.all;
use work.wishbone_pkg.all;
use work.gencores_pkg.all;
entity timestamp_fifo is
generic (
g_USE_FIFO_READOUT : boolean := TRUE);
port (
clk_sys_i : in std_logic;
rst_sys_n_i : in std_logic;
......@@ -61,8 +64,6 @@ architecture rtl of timestamp_fifo is
signal buf_count : unsigned(9 downto 0);
signal last_ts : std_logic_vector(127 downto 0);
signal regs_in : t_tsf_in_registers;
signal regs_out : t_tsf_out_registers;
signal channel_id : std_logic_vector(2 downto 0);
signal timestamp_with_seq : std_logic_vector(127 downto 0);
......@@ -74,56 +75,59 @@ architecture rtl of timestamp_fifo is
signal sub_result : t_tdc_timestamp;
signal sub_result_latched : t_tdc_timestamp;
signal sub_out_valid_latched : std_logic;
begin
signal channel_reg_in : t_ch_reg_in_registers;
signal channel_reg_out : t_ch_reg_out_registers;
signal channel_reg_slave_in : t_wishbone_slave_in;
signal channel_reg_slave_out : t_wishbone_slave_out;
ts_offset_o.tai <= regs_out.offset1_o;
ts_offset_o.coarse <= regs_out.offset2_o;
ts_offset_o.frac <= regs_out.offset3_o(11 downto 0);
reset_seq_o <= regs_out.csr_rst_seq_o;
raw_enable_o <= regs_out.csr_raw_mode_o;
signal fifo_reg_in : t_tsf_in_registers;
signal fifo_reg_out : t_tsf_out_registers;
signal fifo_reg_slave_in : t_wishbone_slave_in;
signal fifo_reg_slave_out : t_wishbone_slave_out;
timestamp_with_seq(31 downto 0) <= std_logic_vector(resize(unsigned(timestamp_i.tai), 32));
timestamp_with_seq(63 downto 32) <= std_logic_vector(resize(unsigned(timestamp_i.coarse), 32));
timestamp_with_seq(95 downto 64) <= std_logic_vector(resize(unsigned(timestamp_i.frac), 32));
timestamp_with_seq(98 downto 96) <= timestamp_i.channel;
timestamp_with_seq(99) <= timestamp_i.slope;
timestamp_with_seq(127 downto 100) <= timestamp_i.seq(27 downto 0);
begin
-- Hack to maintain backward compatibility with previous
-- versions of the code when channel_regs and fifo_regs were
-- part of the same wbgen source, and the FIFO registers were
-- right after the channel registers.
--
-- For this to work now and in the future (without editing),
-- slave_i.adr must be byte addressed, and there can be no more
-- than 8 32-bit channel registers.
p_wb_mux : process (channel_reg_slave_out, fifo_reg_slave_out, slave_i) is
begin
-- register access
if slave_i.adr(5) = '0' then
channel_reg_slave_in <= slave_i;
slave_o <= channel_reg_slave_out;
fifo_reg_slave_in <= c_DUMMY_WB_SLAVE_IN;
-- FIFO access
else
fifo_reg_slave_in <= slave_i;
fifo_reg_slave_in.adr(5) <= '0';
slave_o <= fifo_reg_slave_out;
channel_reg_slave_in <= c_DUMMY_WB_SLAVE_IN;
end if;
end process p_wb_mux;
U_WB_Slave : entity work.timestamp_fifo_wb
U_CHANNEL_REG_WB_Slave : channel_regs
port map (
rst_n_i => rst_sys_n_i,
clk_sys_i => clk_sys_i,
slave_i => slave_i,
slave_o => slave_o,
regs_i => regs_in,
regs_o => regs_out);
buf_count <= resize(unsigned(regs_out.fifo_wr_usedw_o), 10);
slave_i => channel_reg_slave_in,
slave_o => channel_reg_slave_out,
regs_i => channel_reg_in,
regs_o => channel_reg_out);
p_fifo_write : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if rst_sys_n_i = '0' then
regs_in.fifo_wr_req_i <= '0';
else
ts_offset_o.tai <= channel_reg_out.offset1_o;
ts_offset_o.coarse <= channel_reg_out.offset2_o;
ts_offset_o.frac <= channel_reg_out.offset3_o(11 downto 0);
if(enable_i = '1' and regs_out.fifo_wr_full_o = '0' and timestamp_valid_i = '1') then
regs_in.fifo_wr_req_i <= '1';
else
regs_in.fifo_wr_req_i <= '0';
end if;
end if;
end if;
end process;
reset_seq_o <= channel_reg_out.csr_rst_seq_o;
regs_in.fifo_ts0_i <= timestamp_with_seq(31 downto 0);
regs_in.fifo_ts1_i <= timestamp_with_seq(63 downto 32);
regs_in.fifo_ts2_i <= timestamp_with_seq(95 downto 64);
regs_in.fifo_ts3_i <= timestamp_with_seq(127 downto 96);
raw_enable_o <= channel_reg_out.csr_raw_mode_o;
p_latch_ref_timestamp : process(clk_sys_i)
begin
......@@ -141,8 +145,8 @@ begin
end process;
sub_valid <= ref_valid and timestamp_valid_i;
U_Subtractor: entity work.tdc_ts_sub
U_Subtractor : entity work.tdc_ts_sub
port map (
clk_i => clk_sys_i,
rst_n_i => rst_sys_n_i,
......@@ -159,57 +163,108 @@ begin
if rst_sys_n_i = '0' or enable_i = '0' then
sub_out_valid_latched <= '0';
else
if regs_out.csr_delta_read_o = '1' then
sub_out_valid_latched <= '0';
regs_in.delta1_i <= sub_result_latched.tai;
regs_in.delta2_i <= sub_result_latched.coarse;
regs_in.delta3_i <= x"00000" & sub_result_latched.frac;
if channel_reg_out.csr_delta_read_o = '1' then
sub_out_valid_latched <= '0';
channel_reg_in.delta1_i <= sub_result_latched.tai;
channel_reg_in.delta2_i <= sub_result_latched.coarse;
channel_reg_in.delta3_i <= x"00000" & sub_result_latched.frac;
end if;
if(sub_out_valid = '1') then
sub_out_valid_latched <= '1';
sub_result_latched <= sub_result;
sub_result_latched <= sub_result;
end if;
end if;
end if;
end process;
regs_in.csr_delta_ready_i <= sub_out_valid_latched;
p_coalesce_irq : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if rst_sys_n_i = '0' or enable_i = '0' then
buf_irq_int <= '0';
else
if(regs_out.fifo_wr_empty_o = '1') then
channel_reg_in.csr_delta_ready_i <= sub_out_valid_latched;
gen_without_fifo_readout : if not g_USE_FIFO_READOUT generate
fifo_reg_slave_out <= c_DUMMY_WB_SLAVE_OUT;
fifo_reg_out <= c_tsf_out_registers_init_value;
irq_o <= '0';
end generate gen_without_fifo_readout;
gen_with_fifo_readout : if g_USE_FIFO_READOUT generate
timestamp_with_seq(31 downto 0) <= std_logic_vector(resize(unsigned(timestamp_i.tai), 32));
timestamp_with_seq(63 downto 32) <= std_logic_vector(resize(unsigned(timestamp_i.coarse), 32));
timestamp_with_seq(95 downto 64) <= std_logic_vector(resize(unsigned(timestamp_i.frac), 32));
timestamp_with_seq(98 downto 96) <= timestamp_i.channel;
timestamp_with_seq(99) <= timestamp_i.slope;
timestamp_with_seq(127 downto 100) <= timestamp_i.seq(27 downto 0);
U_FIFO_WB_Slave : timestamp_fifo_wb
port map (
rst_n_i => rst_sys_n_i,
clk_sys_i => clk_sys_i,
slave_i => fifo_reg_slave_in,
slave_o => fifo_reg_slave_out,
regs_i => fifo_reg_in,
regs_o => fifo_reg_out);
buf_count <= resize(unsigned(fifo_reg_out.fifo_wr_usedw_o), 10);
p_fifo_write : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if rst_sys_n_i = '0' then
fifo_reg_in.fifo_wr_req_i <= '0';
else
if(enable_i = '1' and fifo_reg_out.fifo_wr_full_o = '0' and timestamp_valid_i = '1') then
fifo_reg_in.fifo_wr_req_i <= '1';
else
fifo_reg_in.fifo_wr_req_i <= '0';
end if;
end if;
end if;
end process;
fifo_reg_in.fifo_ts0_i <= timestamp_with_seq(31 downto 0);
fifo_reg_in.fifo_ts1_i <= timestamp_with_seq(63 downto 32);
fifo_reg_in.fifo_ts2_i <= timestamp_with_seq(95 downto 64);
fifo_reg_in.fifo_ts3_i <= timestamp_with_seq(127 downto 96);
p_coalesce_irq : process(clk_sys_i)
begin
if rising_edge(clk_sys_i) then
if rst_sys_n_i = '0' or enable_i = '0' then
buf_irq_int <= '0';
tmr_timeout <= (others => '0');
else
if(fifo_reg_out.fifo_wr_empty_o = '1') then
buf_irq_int <= '0';
tmr_timeout <= (others => '0');
else
-- Simple interrupt coalescing :
-- Case 1: There is some data in the buffer
-- (but not exceeding the threshold) - assert the IRQ line after a
-- certain timeout.
if(buf_irq_int = '0') then
if(tmr_timeout = unsigned(irq_timeout_i(9 downto 0))) then
buf_irq_int <= '1';
tmr_timeout <= (others => '0');
elsif(tick_i = '1') then
tmr_timeout <= tmr_timeout + 1;
if(buf_irq_int = '0') then
if(tmr_timeout = unsigned(irq_timeout_i(9 downto 0))) then
buf_irq_int <= '1';
tmr_timeout <= (others => '0');
elsif(tick_i = '1') then
tmr_timeout <= tmr_timeout + 1;
end if;
end if;
end if;
-- Case 2: amount of data exceeded the threshold - assert the IRQ
-- line immediately.
if(regs_out.fifo_wr_full_o = '1' or (buf_count > unsigned(irq_threshold_i(9 downto 0)))) then
buf_irq_int <= '1';
if(fifo_reg_out.fifo_wr_full_o = '1' or
(buf_count > unsigned(irq_threshold_i(9 downto 0)))) then
buf_irq_int <= '1';
end if;
end if;
end if;
end if;
end if;
end process;
end process;
irq_o <= buf_irq_int;
irq_o <= buf_irq_int;
end generate gen_with_fifo_readout;
end rtl;
This diff is collapsed.
......@@ -3,7 +3,7 @@
---------------------------------------------------------------------------------------
-- File : timestamp_fifo_wbgen2_pkg.vhd
-- Author : auto-generated by wbgen2 from wbgen/timestamp_fifo_wb.wb
-- Created : Sun Sep 2 15:37:55 2018
-- Created : Thu Sep 26 16:42:08 2019
-- Standard : VHDL'87
---------------------------------------------------------------------------------------
-- THIS FILE WAS GENERATED BY wbgen2 FROM SOURCE FILE wbgen/timestamp_fifo_wb.wb
......@@ -27,10 +27,6 @@ package tsf_wbgen2_pkg is
fifo_ts1_i : std_logic_vector(31 downto 0);
fifo_ts2_i : std_logic_vector(31 downto 0);
fifo_ts3_i : std_logic_vector(31 downto 0);
delta1_i : std_logic_vector(31 downto 0);
delta2_i : std_logic_vector(31 downto 0);
delta3_i : std_logic_vector(31 downto 0);
csr_delta_ready_i : std_logic;
end record;
constant c_tsf_in_registers_init_value: t_tsf_in_registers := (
......@@ -38,11 +34,7 @@ package tsf_wbgen2_pkg is
fifo_ts0_i => (others => '0'),
fifo_ts1_i => (others => '0'),
fifo_ts2_i => (others => '0'),
fifo_ts3_i => (others => '0'),
delta1_i => (others => '0'),
delta2_i => (others => '0'),
delta3_i => (others => '0'),
csr_delta_ready_i => '0'
fifo_ts3_i => (others => '0')
);
-- Output registers (WB slave -> user design)
......@@ -51,82 +43,64 @@ package tsf_wbgen2_pkg is
fifo_wr_full_o : std_logic;
fifo_wr_empty_o : std_logic;
fifo_wr_usedw_o : std_logic_vector(5 downto 0);
offset1_o : std_logic_vector(31 downto 0);
offset2_o : std_logic_vector(31 downto 0);
offset3_o : std_logic_vector(31 downto 0);
csr_delta_read_o : std_logic;
csr_rst_seq_o : std_logic;
csr_delta_ref_o : std_logic_vector(2 downto 0);
csr_raw_mode_o : std_logic;
end record;
constant c_tsf_out_registers_init_value: t_tsf_out_registers := (
fifo_wr_full_o => '0',
fifo_wr_empty_o => '0',
fifo_wr_usedw_o => (others => '0'),
offset1_o => (others => '0'),
offset2_o => (others => '0'),
offset3_o => (others => '0'),
csr_delta_read_o => '0',
csr_rst_seq_o => '0',
csr_delta_ref_o => (others => '0'),
csr_raw_mode_o => '0'
fifo_wr_usedw_o => (others => '0')
);
function "or" (left, right: t_tsf_in_registers) return t_tsf_in_registers;
function f_x_to_zero (x:std_logic) return std_logic;
function f_x_to_zero (x:std_logic_vector) return std_logic_vector;
component timestamp_fifo_wb is
port (
rst_n_i : in std_logic;
clk_sys_i : in std_logic;
slave_i : in t_wishbone_slave_in;
slave_o : out t_wishbone_slave_out;
int_o : out std_logic;
regs_i : in t_tsf_in_registers;
regs_o : out t_tsf_out_registers
);
end component;
function "or" (left, right: t_tsf_in_registers) return t_tsf_in_registers;
function f_x_to_zero (x:std_logic) return std_logic;
function f_x_to_zero (x:std_logic_vector) return std_logic_vector;
component timestamp_fifo_wb is
port (
rst_n_i : in std_logic;
clk_sys_i : in std_logic;
slave_i : in t_wishbone_slave_in;
slave_o : out t_wishbone_slave_out;
int_o : out std_logic;
regs_i : in t_tsf_in_registers;
regs_o : out t_tsf_out_registers
);
end component;
end package;
package body tsf_wbgen2_pkg is
function f_x_to_zero (x:std_logic) return std_logic is
begin
if x = '1' then
return '1';
else
return '0';
end if;
end function;
function f_x_to_zero (x:std_logic_vector) return std_logic_vector is
variable tmp: std_logic_vector(x'length-1 downto 0);
begin
for i in 0 to x'length-1 loop
if(x(i) = 'X' or x(i) = 'U') then
tmp(i):= '0';
function f_x_to_zero (x:std_logic) return std_logic is
begin
if x = '1' then
return '1';
else
tmp(i):=x(i);
end if;
end loop;
return tmp;
end function;
function "or" (left, right: t_tsf_in_registers) return t_tsf_in_registers is
variable tmp: t_tsf_in_registers;
begin
tmp.fifo_wr_req_i := f_x_to_zero(left.fifo_wr_req_i) or f_x_to_zero(right.fifo_wr_req_i);
tmp.fifo_ts0_i := f_x_to_zero(left.fifo_ts0_i) or f_x_to_zero(right.fifo_ts0_i);
tmp.fifo_ts1_i := f_x_to_zero(left.fifo_ts1_i) or f_x_to_zero(right.fifo_ts1_i);
tmp.fifo_ts2_i := f_x_to_zero(left.fifo_ts2_i) or f_x_to_zero(right.fifo_ts2_i);
tmp.fifo_ts3_i := f_x_to_zero(left.fifo_ts3_i) or f_x_to_zero(right.fifo_ts3_i);
tmp.delta1_i := f_x_to_zero(left.delta1_i) or f_x_to_zero(right.delta1_i);
tmp.delta2_i := f_x_to_zero(left.delta2_i) or f_x_to_zero(right.delta2_i);
tmp.delta3_i := f_x_to_zero(left.delta3_i) or f_x_to_zero(right.delta3_i);
tmp.csr_delta_ready_i := f_x_to_zero(left.csr_delta_ready_i) or f_x_to_zero(right.csr_delta_ready_i);
return tmp;
end function;
return '0';
end if;
end function;
function f_x_to_zero (x:std_logic_vector) return std_logic_vector is
variable tmp: std_logic_vector(x'length-1 downto 0);
begin
for i in 0 to x'length-1 loop
if(x(i) = '1') then
tmp(i):= '1';
else
tmp(i):= '0';
end if;
end loop;
return tmp;
end function;
function "or" (left, right: t_tsf_in_registers) return t_tsf_in_registers is
variable tmp: t_tsf_in_registers;
begin
tmp.fifo_wr_req_i := f_x_to_zero(left.fifo_wr_req_i) or f_x_to_zero(right.fifo_wr_req_i);
tmp.fifo_ts0_i := f_x_to_zero(left.fifo_ts0_i) or f_x_to_zero(right.fifo_ts0_i);
tmp.fifo_ts1_i := f_x_to_zero(left.fifo_ts1_i) or f_x_to_zero(right.fifo_ts1_i);
tmp.fifo_ts2_i := f_x_to_zero(left.fifo_ts2_i) or f_x_to_zero(right.fifo_ts2_i);
tmp.fifo_ts3_i := f_x_to_zero(left.fifo_ts3_i) or f_x_to_zero(right.fifo_ts3_i);
return tmp;
end function;
end package body;
-- -*- Mode: LUA; tab-width: 2 -*-
peripheral {
name = "Channel registers";
prefix="ch_reg";
hdl_entity="channel_regs";
reg {
name = "Delta Timestamp Word 1";
prefix = "DELTA1";
field {
name = "Delta Timestamp Word 1 (TAI cycles, signed)";
type = SLV;
size = 32;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
};
reg {
name = "Delta Timestamp Word 2";
prefix = "DELTA2";
field {
name = "Delta Timestamp Word 2 (8ns ticks, unsigned)";
type = SLV;
size = 32;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
};
reg {
name = "Delta Timestamp Word 3";
prefix = "DELTA3";
field {
name = "Delta Timestamp Word 3 (fractional part, unsigned)";
type = SLV;
size = 32;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
};
reg {
name = "Channel Offset Word 1";
prefix = "OFFSET1";
field {
name = "Channel Offset Word 1 (TAI cycles, signed)";
type = SLV;
size = 32;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
reg {
name = "Channel Offset Word 2";
prefix = "OFFSET2";
field {
name = "Channel Offset Word 2 (8ns ticks, unsigned)";
type = SLV;
size = 32;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
reg {
name = "Channel Offset Word 3";
prefix = "OFFSET3";
field {
name = "Channel Offset Word 3 (fractional part, unsigned)";
type = SLV;
size = 32;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
reg {
name = "Control/Status";
prefix = "CSR";
field {
name = "Delta Timestamp Ready";
prefix = "DELTA_READY";
type = BIT;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
field {
name = "Read Delta Timestamp";
prefix = "DELTA_READ";
type = MONOSTABLE;
};
field {
name = "Reset Sequence Counter";
prefix = "RST_SEQ";
type = MONOSTABLE;
};
field {
name = "Delta Timestamp Reference Channel";
description = "Channel (0-4) to take as the reference for the delta timestamps";
prefix = "DELTA_REF";
type = SLV;
size = 3;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
field {
name = "Raw readout mode";
description = "1: enables readout of raw timestamps";
prefix = "RAW_MODE";
type = BIT;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
};
......@@ -45,134 +45,4 @@ peripheral {
size = 32;
};
};
reg {
name = "Delta Timestamp Word 1";
prefix = "DELTA1";
field {
name = "Delta Timestamp Word 1 (TAI cycles, signed)";
type = SLV;
size = 32;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
};
reg {
name = "Delta Timestamp Word 2";
prefix = "DELTA2";
field {
name = "Delta Timestamp Word 2 (8ns ticks, unsigned)";
type = SLV;
size = 32;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
};
reg {
name = "Delta Timestamp Word 3";
prefix = "DELTA3";
field {
name = "Delta Timestamp Word 3 (fractional part, unsigned)";
type = SLV;
size = 32;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
};
reg {
name = "Channel Offset Word 1";
prefix = "OFFSET1";
field {
name = "Channel Offset Word 1 (TAI cycles, signed)";
type = SLV;
size = 32;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
reg {
name = "Channel Offset Word 2";
prefix = "OFFSET2";
field {
name = "Channel Offset Word 2 (8ns ticks, unsigned)";
type = SLV;
size = 32;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
reg {
name = "Channel Offset Word 3";
prefix = "OFFSET3";
field {
name = "Channel Offset Word 3 (fractional part, unsigned)";
type = SLV;
size = 32;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
reg {
name = "Control/Status";
prefix = "CSR";
field {
name = "Delta Timestamp Ready";
prefix = "DELTA_READY";
type = BIT;
access_bus = READ_ONLY;
access_dev = WRITE_ONLY;
};
field {
name = "Read Delta Timestamp";
prefix = "DELTA_READ";
type = MONOSTABLE;
};
field {
name = "Reset Sequence Counter";
prefix = "RST_SEQ";
type = MONOSTABLE;
};
field {
name = "Delta Timestamp Reference Channel";
description = "Channel (0-4) to take as the reference for the delta timestamps";
prefix = "DELTA_REF";
type = SLV;
size = 3;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
field {
name = "Raw readout mode";
description = "1: enables readout of raw timestamps";
prefix = "RAW_MODE";
type = BIT;
access_bus = READ_WRITE;
access_dev = READ_ONLY;
};
};
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment