Commit 9ce72440 authored by David Cussans's avatar David Cussans

Checking in timestamp multiplexing code

git-svn-id: https://svn2.phy.bris.ac.uk/svn/uob-hep-pc049a/trunk@46 e1591323-3689-4d5a-aa31-d1a7cbdc5706
parent f9bf008a
......@@ -38,5 +38,6 @@ files = [
# "dpram.vhdl" ,
"ipbusDPRAM.vhdl",
"synchronizeRegisters_rtl.vhd",
"i2c_master_rtl.vhd"
]
"i2c_master_rtl.vhd",
"marocTriggerTimeStamp_rtl.vhd"
]
--=============================================================================
--! @file marocTimeStampMuxArray_rtl.vhd
--=============================================================================
--! Standard library
library IEEE;
--! Standard packages
use IEEE.std_logic_1164.ALL;
use IEEE.numeric_std.ALL;
--! Use UNISIM for Xilix primitives
--Library UNISIM;
--use UNISIM.vcomponents.all;
--type t_triggerTimeArray is array(natural range <>) of std_logic_vector(31 downto 0) ;
use work.maroc.ALL;
-------------------------------------------------------------------------------
-- --
-- University of Bristol, High Energy Physics Group.
-- --
------------------------------------------------------------------------------- --
-- unit name: marocTimeStampMuxArray_rtl (marocTimeStampMuxArray / rtl)
--
--! @brief Multiplexes between data streams from multiple FIFOs.
--
--! @author David Cussans , David.Cussans@bristol.ac.uk
--
--! @date 4\4\2016
--
--! @version v0.1
--
--! @details There is an array of data sources.
--! If there is data on more than one sources the source with highest index has priority.
--! N.B. There is no provision for back-pressure - downstream *must* be
--! ready to accept data or it will be lost.
--!
--! <b>Dependencies:</b>\n
--!
--! <b>References:</b>\n
--!
--! <b>Modified by:</b>\n
--! Author:
-------------------------------------------------------------------------------
--! \n\n<b>Last changes:</b>\n
--!
-------------------------------------------------------------------------------
--! @todo
--
---------------------------------------------------------------------------------
entity marocTimeStampMuxArray is
generic (
g_BUSWIDTH : positive := 32; --! Number of bits in input/output data
g_NCHANNELS : positive := 64
);
port (
clk_i : in std_logic; --! rising edge active
data_i : in t_timeStampArray(g_NCHANNELS-1 downto 0);
data_present_i : in std_logic_vector(g_NCHANNELS-1 downto 0); --! High if data present
read_data_o : out std_logic_vector(g_NCHANNELS-1 downto 0); --! Take high to read data
data_o : out std_logic_vector(g_BUSWIDTH-1 downto 0); --! Downstream data. Stays at state of last valid data.
data_present_o : out std_logic --! High if data present
);
end entity marocTimeStampMuxArray;
architecture rtl of marocTimeStampMuxArray is
signal s_downstream_data : t_timeStampArray(g_NCHANNELS-1 downto 0) := ( others => (others => '0')); -- data from one pipeline mux to another
signal s_downstream_data_present , s_read_upstream_data : std_logic_vector(g_NCHANNELS-1 downto 0) := (others => '0');
begin -- architecture rtl
-- connect the start of the pipeline to the channel with highest index.
s_downstream_data(g_NCHANNELS-1) <= data_i(g_NCHANNELS-1);
s_downstream_data_present(g_NCHANNELS-1) <= data_present_i(g_NCHANNELS-1);
read_data_o(g_NCHANNELS-1) <= s_read_upstream_data(g_NCHANNELS-1);
-- Generate an array of 2 way multiplexers....
gen_2wayMuxes: for channel in g_NCHANNELS-2 downto 0 generate
cmp_muxN: entity work.marocTimeStampMux PORT MAP (
clk_i => clk_i,
upstream_data_i => s_downstream_data(channel+1),
upstream_data_present_i => s_downstream_data_present(channel+1),
read_upstream_data_o => s_read_upstream_data(channel+1),
input_data_i => data_i(channel),
input_data_present_i => data_present_i(channel),
read_input_data_o => read_data_o(channel),
downstream_data_o => s_downstream_data(channel),
downstream_data_present_o => s_downstream_data_present(channel)
);
end generate gen_2wayMuxes;
-- copy the last stage of the pipeline to the output.....
data_o <= s_downstream_data(0);
data_present_o <= s_downstream_data_present(0);
end architecture rtl;
--=============================================================================
--! @file marocTimeStampMux_rtl.vhd
--=============================================================================
--! Standard library
library IEEE;
--! Standard packages
use IEEE.std_logic_1164.ALL;
use IEEE.numeric_std.ALL;
--! Use UNISIM for Xilix primitives
--Library UNISIM;
--use UNISIM.vcomponents.all;
-------------------------------------------------------------------------------
-- --
-- University of Bristol, High Energy Physics Group.
-- --
------------------------------------------------------------------------------- --
-- unit name: marocTimeStampMux_rtl (marocTimeStampMux / rtl)
--
--! @brief Multiplexes between two data streams from FIFOs.
--
--! @author David Cussans , David.Cussans@bristol.ac.uk
--
--! @date 4\4\2016
--
--! @version v0.1
--
--! @details There is an upstream data source and an input data source.
--! If there is data on both sources the upstream source has priority.
--! N.B. There is no provision for back-pressure - downstream *must* be
--! ready to accept data or it will be lost. (hence priority for upstream input)
--!
--! <b>Dependencies:</b>\n
--!
--! <b>References:</b>\n
--!
--! <b>Modified by:</b>\n
--! Author:
-------------------------------------------------------------------------------
--! \n\n<b>Last changes:</b>\n
--!
-------------------------------------------------------------------------------
--! @todo
--
---------------------------------------------------------------------------------
entity marocTimeStampMux is
generic (
g_BUSWIDTH : positive := 32 --! Number of bits in input/output data
);
port (
clk_i : in std_logic; --! rising edge active
upstream_data_i : in std_logic_vector(g_BUSWIDTH-1 downto 0); --! Upstream data
upstream_data_present_i : in std_logic; --! High if data present
read_upstream_data_o : out std_logic; --! Take high to read data
input_data_i : in std_logic_vector(g_BUSWIDTH-1 downto 0); --! Input data
input_data_present_i : in std_logic; --! High if data present
read_input_data_o : out std_logic; --! Take high to read data
downstream_data_o : out std_logic_vector(g_BUSWIDTH-1 downto 0); --! Downstream data. Remains at state of last valid data.
downstream_data_present_o : out std_logic --! High if data present
);
end entity marocTimeStampMux;
architecture rtl of marocTimeStampMux is
signal s_read_input_data , s_read_upstream_data : std_logic := '0';
begin -- architecture rtl
-- purpose: reads data from inputs and outputs downstream
-- type : combinational
-- inputs : clk_i
-- outputs: downstream_data_o , downstream_data_present_o
p_muxData: process (clk_i) is
begin -- process p_muxData
if rising_edge(clk_i) then
downstream_data_present_o <='0';
if (input_data_present_i = '1') and ( s_read_input_data = '0' ) and ( upstream_data_present_i = '0' ) then
s_read_input_data <='1';
else
s_read_input_data <='0';
end if;
if (upstream_data_present_i = '1') and ( s_read_upstream_data = '0' ) then
s_read_upstream_data <= '1';
else
s_read_upstream_data <='0';
end if;
---------
-- Data Mux
if s_read_upstream_data = '1' then
downstream_data_o <= upstream_data_i;
downstream_data_present_o <='1';
elsif s_read_input_data = '1' then
downstream_data_o <= input_data_i;
downstream_data_present_o <='1';
end if;
end if;
end process p_muxData;
read_input_data_o <= s_read_input_data;
read_upstream_data_o <= s_read_upstream_data;
end architecture rtl;
--=============================================================================
--! @file marocTriggerTimeStampArray_rtl.vhd
--=============================================================================
--! Standard library
library IEEE;
--! Standard packages
use IEEE.std_logic_1164.ALL;
use IEEE.numeric_std.ALL;
--! Package containing type definition and constants for MAROC interface
--use work.maroc.ALL;
--! Package containing type definition and constants for IPBUS
--use work.ipbus.all;
--! Use UNISIM for Xilix primitives
Library UNISIM;
use UNISIM.vcomponents.all;
-------------------------------------------------------------------------------
-- --
-- University of Bristol, High Energy Physics Group.
-- --
------------------------------------------------------------------------------- --
-- unit name: marocTriggerTimeStampArray_rtl (marocTriggerTimeStampArray / rtl)
--
--! @brief Array of marocTriggerTimeStamp entities with FIFO buffers on each output
--! fed into a multiplexer
--
--! @author David Cussans , David.Cussans@bristol.ac.uk
--
--! @date 30\3\2016
--
--! @version v0.1
--
--! @details
--!
--! <b>Dependencies:</b>\n
--! Instantiates marocTriggerTimeStamp
--!
--! <b>References:</b>\n
--!
--! <b>Modified by:</b>\n
--! Author:
-------------------------------------------------------------------------------
--! \n\n<b>Last changes:</b>\n
--!
-------------------------------------------------------------------------------
--! @todo
--
---------------------------------------------------------------------------------
entity marocTriggerTimeStampArray is
generic (
g_BUSWIDTH : positive := 32; --! IPBUS data width
g_NUM_CHANNELS : positive := 64;
g_IDENTWIDTH : positive := 6;
g_FINEBITWIDTH : positive := 2
);
port (
clk_i : in std_logic; --! slow clock ( normally IPBus clock 31.25 MHz)
clk_fast_i : in std_logic; --! fast clock ( 4 x slow clock . e.g 125MHz)
triggers_i : in std_logic_vector(g_NUM_CHANNELS-1 downto 0); --! triggers from MAROC
timestamp_i : in std_logic_vector( (g_BUSWIDTH - (g_IDENTWIDTH + g_FINEBITWIDTH))-1 downto 0); --! time-stamp that will be combined with fine-grain bits
triggers_fastclk_o : out std_logic_vector(g_NUM_CHANNELS-1 downto 0);--! retimed maroc triggers, pulses high g_TRIGGERWIDTH cycles of fast clock
triggers_slowclk_o : out std_logic_vector(g_NUM_CHANNELS-1 downto 0);--! maroc triggers, pulses high single cycle of slow clock
timestamp_data_o : out std_logic_vector(g_BUSWIDTH-1 downto 0); --! ident-code + coarse-bits + fine-bits
timestamp_data_ready_o : out std_logic --! High if there is timestamp data
);
end entity marocTriggerTimeStampArray;
architecture rtl of marocTriggerTimeStampArray is
signal s_timestamp_data_ready , s_timeStampFIFO_empty , s_timeStampFIFO_rd_en: std_logic_vector(g_NUM_CHANNELS-1 downto 0) := ( others => '0' ); -- pulses high for one cycle of slow clock for each trigger
type t_triggerTimeArray is array(natural range <>) of std_logic_vector(g_BUSWIDTH-1 downto 0) ;
signal s_timestamp_data , s_timestampFIFO_out : t_triggerTimeArray(g_NUM_CHANNELS-1 downto 0) := ( others => ( others => '0'));
begin -- architecture rtl
gen_timestamparray: for v_marocChannel in 0 to g_NUM_CHANNELS-1 generate
-- instantiate component to shift trigger onto internal clock domain
-- and produce a time-stamp
cmp_timestamp: entity work.marocTriggerTimeStamp
generic map (
g_IDENT => v_marocChannel)
PORT MAP (
clk_i => clk_i,
clk_fast_i => clk_fast_i,
trigger_i => triggers_i(v_marocChannel),
timestamp_i => timestamp_i,
trigger_o => triggers_fastclk_o(v_marocChannel),
timestamp_data_o => s_timestamp_data(v_marocChannel),
timestamp_data_ready_o => s_timestamp_data_ready(v_marocChannel)
);
triggers_slowclk_o <= s_timestamp_data_ready;
cmp_timestampFIFO : entity work.timeStampFIFO
port map (
clk => clk_i,
srst => '0',
din => s_timestamp_data(v_marocChannel),
wr_en => s_timestamp_data_ready(v_marocChannel),
rd_en => s_timeStampFIFO_rd_en(v_marocChannel),
dout => s_timestampFIFO_out(v_marocChannel),
full => open,
empty => s_timeStampFIFO_empty(v_marocChannel)
);
end generate gen_timestamparray;
end architecture rtl;
--=============================================================================
--! @file marocTriggerTimeStamp_rtl.vhd
--=============================================================================
--! Standard library
library IEEE;
--! Standard packages
use IEEE.std_logic_1164.ALL;
use IEEE.numeric_std.ALL;
--! Package containing type definition and constants for MAROC interface
--use work.maroc.ALL;
--! Package containing type definition and constants for IPBUS
--use work.ipbus.all;
--! Use UNISIM for Xilix primitives
Library UNISIM;
use UNISIM.vcomponents.all;
-------------------------------------------------------------------------------
-- --
-- University of Bristol, High Energy Physics Group.
-- --
------------------------------------------------------------------------------- --
-- unit name: marocTriggerTimeStamp_rtl (marocTriggerTimeStamp / rtl)
--
--! @brief accepts an input from maroc trigger line and outputs a single cycle
--! pulse synchronized to slow clock.
--! @author David Cussans , David.Cussans@bristol.ac.uk
--
--! @date 30\3\2016
--
--! @version v0.1
--
--! @details
--!
--! <b>Dependencies:</b>\n
--! Instantiates marocTriggerTimeStampFSM
--!
--! <b>References:</b>\n
--! referenced by marocTriggerTimeStamp \n
--!
--! <b>Modified by:</b>\n
--! Author:
-------------------------------------------------------------------------------
--! \n\n<b>Last changes:</b>\n
--!
-------------------------------------------------------------------------------
--! @todo
--
---------------------------------------------------------------------------------
entity marocTriggerTimeStamp is
generic (
g_BUSWIDTH : positive := 32; --! IPBUS data width
g_IDENTWIDTH : positive := 6; --! number of bits in channel identifier
g_IDENT : integer := 0; --! identifier to add to data
g_FINEBITWIDTH : positive := 2; --! Number of fine time-stamp bits. Input is DDR on clk_fast . i.e. 4 x clk_i --> 2 bits
g_TRIGGERWIDTH : positive := 4 --! width of trigger out ( in units of fast
--clock
);
port (
clk_i : in std_logic; --! slow clock ( normally IPBus clock 31.25 MHz)
clk_fast_i : in std_logic; --! fast clock ( 4 x slow clock . e.g 125MHz)
trigger_i : in std_logic; --! trigger from MAROC
timestamp_i : in std_logic_vector( (g_BUSWIDTH - (g_IDENTWIDTH + g_FINEBITWIDTH))-1 downto 0); -- time-stamp that will be combined with fine-grain bits
trigger_o : out std_logic; --! pulses high g_TRIGGERWIDTH cycles of fast clock
timestamp_data_o : out std_logic_vector(g_BUSWIDTH-1 downto 0); --! ident-code + coarse-bits + fine-bits
timestamp_data_ready_o : out std_logic --! High if there is timestamp data
);
end entity marocTriggerTimeStamp;
architecture rtl of marocTriggerTimeStamp is
signal s_trigger_in , s_trigger_d1 : std_logic := '0';
attribute shreg_extract : string; -- Don't want synchronizer registers optimized to SRL16
attribute shreg_extract of s_trigger_in: signal is "no";
attribute shreg_extract of s_trigger_d1: signal is "no";
signal s_trigger_sr : std_logic_vector(2*(2**g_FINEBITWIDTH)-1 downto 0) := ( others => '0'); --! Shift register to transfer from fast to slow clock. for fast clk = 4 * clk then length = 2*(2**2) = 8 bits.
signal s_trigger_sr_d1 , s_trigger_sr_d2 : std_logic_vector( s_trigger_sr'range ) := ( others => '0'); -- ! Transfer to slow clock
attribute shreg_extract of s_trigger_sr_d1: signal is "no";
attribute shreg_extract of s_trigger_sr_d2: signal is "no";
signal s_fineTimeStamp : std_logic_vector(g_FINEBITWIDTH-1 downto 0) := ( others => '0');
signal s_triggerfound ,s_triggerfound_d1 : std_logic := '0'; -- ! Goes high for one cycle of clk_i if rising edge detected
signal s_triggerData : std_logic_vector(g_BUSWIDTH-1 downto 0) := ( others => '0');
constant c_PARAM_WIDTH : integer := 4; -- width of pulse stretch parameter
begin -- architecture rtl
-- purpose: registers trigger from MAROC onto fast clock
-- type : combinational
-- inputs : clk_fast_i
-- outputs: s_trigger_in
p_triggerIn: process (clk_fast_i) is
begin -- process p_triggerIn
if rising_edge(clk_fast_i) then
s_trigger_d1 <= trigger_i;
s_trigger_in <= s_trigger_d1;
s_trigger_sr <= s_trigger_sr( (s_trigger_sr'left -1) downto 0 ) & s_trigger_in; -- LSB is the most recent
end if;
end process p_triggerIn;
-- stretch the incoming pulse ( now stretched onto fast clock domain ).
cmp_stretchFastPulse: entity work.stretchPulse
generic map (
g_PARAM_WIDTH => c_PARAM_WIDTH) --! number of bits in parameters (width, delay)
port map (
clk_i => clk_fast_i,
pulse_i => s_trigger_in,
pulseWidth_i => std_logic_vector(to_unsigned(g_TRIGGERWIDTH,c_PARAM_WIDTH)),
pulse_o => trigger_o
);
-- purpose: moves trigger shift register to slow clock domain
-- type : combinational
-- inputs : clk_i
-- outputs: s_trigger_sr_d2
p_crossToSlow: process (clk_i ) is
begin -- process p_crossToSlow
if rising_edge(clk_i) then
s_trigger_sr_d1 <= s_trigger_sr;
s_trigger_sr_d2 <= s_trigger_sr_d1;
end if;
end process p_crossToSlow;
-- purpose: decodes shift register to fine timestamp bits
-- type : combinational
-- inputs : clk_i
-- outputs: s_fineTimeStamp
p_decodeFineTimeStamp: process (clk_i) is
begin -- process p_decodeFineTimeStamp
if rising_edge(clk_i) then
-- LSB of shift reg is most recent. So sample with edge closest to MSB is
-- the oldest , so should have the lowest timestamp.
if std_match(s_trigger_sr_d2,"0011----") then
s_fineTimeStamp <= "00";
s_triggerFound <= '1';
elsif std_match(s_trigger_sr_d2,"-0011---") then
s_fineTimeStamp <= "01";
s_triggerFound <= '1';
elsif std_match(s_trigger_sr_d2,"--0011--") then
s_fineTimeStamp <= "10";
s_triggerFound <= '1';
elsif std_match(s_trigger_sr_d2,"---0011-") then
s_fineTimeStamp <= "11";
s_triggerFound <= '1';
else
s_fineTimeStamp <= "00";
s_triggerFound <= '0';
end if;
end if;
end process p_decodeFineTimeStamp;
-- purpose: combines data with ident and outputs
-- type : combinational
-- inputs : clk_i
-- outputs: timestamp_data_o
p_outputData: process (clk_i) is
begin -- process p_outputData
if rising_edge(clk_i) then
if s_triggerFound = '1' then
s_triggerData <= std_logic_vector(to_unsigned(g_IDENT,g_IDENTWIDTH)) & timestamp_i & s_fineTimeStamp;
else
s_triggerData <= ( others => '0');
end if;
s_triggerFound_d1 <= s_triggerFound;
timestamp_data_ready_o <= s_triggerFound_d1;
timestamp_data_o <= s_triggerData ;
end if;
end process p_outputData;
end architecture rtl;
......@@ -65,6 +65,8 @@ package maroc is
type t_integer_array is array (natural range <>) of integer; -- ! Used to pass clock domain values into fineTimestap
type t_bool_array is array (natural range <>) of boolean; -- ! Used to pass single/dual ISERDES flag to fineTimestamp
type t_timeStampArray is array(natural range <>) of std_logic_vector(c_BUSWIDTH-1 downto 0) ;
type maroc_input_signals is record -- Signals going to MAROC
CK_40M: STD_LOGIC;
HOLD2_2V5: STD_LOGIC;
......
--=============================================================================
--! @file stretchPulse_rtl.vhd
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.ALL;
--=============================================================================
--
-------------------------------------------------------------------------------
-- --
-- University of Bristol, High Energy Physics Group.
-- --
------------------------------------------------------------------------------- -
--! @brief looks for rising edge of input level then shifts out a pulse.
------------------------------------------------------------------------------- --
-- VHDL Architecture fmc_mTLU_lib.triggerLogic.rtl
--
--! @brief Takes a pulse on input, stretches it and delays it.
--
--! @author David Cussans , David.Cussans@bristol.ac.uk
--! @date 1/July/2013
-------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.numeric_std.all;
entity stretchPulse is
generic (
--g_OUTPUT_PATTERN : std_logic_vector -- gets shifted out
g_PULSE_LENGTH : positive := 8
) ;
g_PARAM_WIDTH : positive := 5); --! number of bits in parameters (width, delay)
port (
clk_i : in std_logic; -- active high
level_i : in std_logic; -- active high
pulse_out : out std_logic); -- rises high
clk_i : in std_logic; --! Active high
pulse_i : in std_logic; --! Active high
pulseWidth_i : in std_logic_vector(g_PARAM_WIDTH-1 downto 0); --! Minimum pulse width ( in clock cycles )
pulse_o : out std_logic --! delayed and stretched
end stretchPulse;
);
end entity stretchPulse;
-- For now just delay the pulse.
architecture rtl of stretchPulse is
signal s_level_d1 , s_level_d2 : std_logic := '0';
signal s_stretchSR : std_logic_vector( (2**g_PARAM_WIDTH) -1 downto 0) := ( others => '0' ); -- --! Shift register to generate delay
constant c_OUTPUT_PATTERN : std_logic_vector(0 to g_PULSE_LENGTH-1) := (others => '1'); -- Gets shifted out
signal s_shiftReg : std_logic_vector( c_OUTPUT_PATTERN'range ) := ( others => '0');
begin -- rtl
begin -- architecture rtl
p_shift_data: process (clk_i)
begin -- process p_shift_data
if rising_edge(clk_i) then -- rising clock edge
s_level_d1 <= level_i;
s_level_d2 <= s_level_d1;
if (s_level_d1='1' and s_level_d2='0') then
s_shiftReg <= c_OUTPUT_PATTERN;
--! Stretch pulse. the output pulse is always at least as long as the input pulse
p_stretchPulse: process (clk_i , pulse_i) is
begin -- process p_stretchPulse
if rising_edge(clk_i) then
if pulse_i = '1' then
s_stretchSR <= ( others => '1' ) ;
pulse_o <= pulse_i ;
else
s_shiftReg <= s_shiftReg( 1 to s_shiftReg'right) & '0' ;
s_stretchSR <= s_stretchSR( (s_stretchSR'left -1) downto 0 ) & '0';
pulse_o <= s_stretchSR( to_integer(unsigned(pulseWidth_i)) );
end if;
pulse_out <= s_shiftReg(0);
end if;
end process p_shift_data;
end process p_stretchPulse;
end architecture rtl;
end rtl;
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