From: Jan Michel Date: Mon, 11 Oct 2021 18:00:45 +0000 (+0200) Subject: add module to receive R3B white rabbit timestamps to CTS X-Git-Url: https://jspc29.x-matter.uni-frankfurt.de/git/?a=commitdiff_plain;h=825dbf8cbdd2e6b3fb4764da81707d2655954476;p=trb3.git add module to receive R3B white rabbit timestamps to CTS --- diff --git a/base/code/input_statistics.vhd b/base/code/input_statistics.vhd index 4ef7be8..9686191 100644 --- a/base/code/input_statistics.vhd +++ b/base/code/input_statistics.vhd @@ -45,7 +45,7 @@ signal trigger_fifo_channel_enable : std_logic; signal reset_cnt : std_logic; signal timer_rst : std_logic; -signal enable : std_logic_vector(31+32*(input_above32+input_above64) downto 0); --(95 downto 0); +signal enable : std_logic_vector(31+32*(input_above32+input_above64) downto 0) := (others => '0'); --(95 downto 0); signal invert : std_logic_vector(31+32*(input_above32+input_above64) downto 0); --(95 downto 0); signal rate : unsigned(31 downto 0); diff --git a/cts/source/r3b_timestamp_recv.vhd b/cts/source/r3b_timestamp_recv.vhd new file mode 100644 index 0000000..e873928 --- /dev/null +++ b/cts/source/r3b_timestamp_recv.vhd @@ -0,0 +1,284 @@ + + +--Event data +-- 0: timestamp lower 32 Bit +-- 1: timestamp upper 32 Bit +-- 2: empty word +-- 3: status flags + +library IEEE; +use IEEE.STD_LOGIC_1164.ALL; +use IEEE.numeric_std.All; + +library work; +use work.rataser_records.all; +use work.rataser_sym24word8_util; + +entity r3b_timestamp_recv is + port( + CLK : in std_logic; + CLK_SENDER : in std_logic; + RESET_IN : in std_logic; + + SERIAL_IN : in std_logic; + SERIAL_OUT : out std_logic; + TRG_SYNC_OUT : out std_logic; + + --data output for read-out + TRIGGER_IN : in std_logic; + DATA_OUT : out std_logic_vector(31 downto 0); + WRITE_OUT : out std_logic; + STATUSBIT_OUT : out std_logic_vector(31 downto 0); + FINISHED_OUT : out std_logic; + HEADER_REG_OUT : out std_logic_vector( 1 downto 0); + --Registers / Debug + CONTROL_REG_IN : in std_logic_vector(31 downto 0); + STATUS_REG_OUT : out std_logic_vector(31 downto 0) := (others => '0'); + DEBUG : out std_logic_vector(31 downto 0) + ); +end entity; + + + +architecture arch of r3b_timestamp_recv is + + type state_readout is (RDO_IDLE, RDO_WRITE1, RDO_WRITE2, RDO_WRITE3, RDO_WRITE4, RDO_FINISH); + signal rdostate : state_readout := RDO_IDLE; + + + signal timestamp_i : std_logic_vector(63 downto 0); + signal time_since_timestamp : unsigned(31 downto 0); + signal status_i : std_logic_vector(31 downto 0); + + signal CONF_time_offset : std_logic_vector(15 downto 0); + signal CONF_clear_status_i : std_logic; + signal CONF_loopback : std_logic; + signal serial_in_i : std_logic; + signal serial_out_i : std_logic; + signal aux_sigs_i : std_logic_vector(4 downto 0); + signal sync_status_i : std_logic_vector(2 downto 0); + signal sync_lost_i : std_logic_vector(2 downto 0); + signal bad_signals_i : std_logic_vector(4 downto 0); + signal sender_timestamp : unsigned(63 downto 0); + signal sender_timestamp_upper_enable : std_logic; + + component rataser_clock_recv is + generic( + period_bits: integer; + num_last_edges: integer; + pipeline_sym24_diff_in : boolean := true; + pipeline_sym24_diff_1 : boolean := false; + pipeline_sym24_diff_2 : boolean := false; + pipeline_sym24_diff_out : boolean := true; + pipeline_sym24_match_out : boolean := false; + pipeline_sym24_pick : boolean := false; + pipeline_sym24_out : boolean := false; + pipeline_hamming_parity : boolean := true; + pipeline_hamming_dual : boolean := true); + port ( + clk: in std_logic; + clk90: in std_logic; + receive: in std_logic; + eight_slot: in std_logic; + expect_edge: in std_logic_vector(1 downto 0); + last_edges: out std_logic_vector(num_last_edges*2-1 downto 0); + use_auto_edge: in std_logic; + auto_edge: out std_logic_vector(1 downto 0); + receive_delay_ns: in std_logic_vector(15 downto 0); + tick_ns_lo: out std_logic_vector(31 downto 0); + tick_ns_hi: out std_logic_vector(63 downto 32); + aux_sigs: out std_logic_vector(4 downto 0); + info_bit: out std_logic; + msg_strobe: out std_logic; + sync_status: out std_logic_vector(2 downto 0); + sync_lost: out std_logic_vector(2 downto 0); + bad_signals: out std_logic_vector(4 downto 0); + clear_status: in std_logic; + pulse_period_clks: in std_logic_vector(period_bits-1 downto 0); + clk_period_ns: in std_logic_vector(9 downto 0); + sym8_debug: out rataser_sym8word1_debug + ); + end component; + + component rataser_clock_send is + generic(-- Number of bits for pulse period. + period_bits: integer + ); + port ( + clk: in std_logic; + -- Absolute time (the timestamp that is sent). + tick_ns: in std_logic_vector(63 downto 0); + -- Auxiliary signals. + aux_sigs: in std_logic_vector(4 downto 0); + -- Auxiliary information. + info_bit: in std_logic; + -- Pulse period (in clk cycles, controls sender). + pulse_period_clks: in std_logic_vector(period_bits-1 downto 0); + -- Minimum duty cycle of pulse pause (remaining length after long). + duty_low_min_clks: in std_logic_vector(period_bits-1 downto 0); + -- Maximum duty cycle of pulse pause (remaining length after short). + duty_low_max_clks: in std_logic_vector(period_bits-1 downto 0); + -- Use 8 pulses to encode 1 raw bit (for PLL reception). + eight_slot: in std_logic; + -- Pulse period (in ns, encoded in message). + pulse_period_ns: in std_logic_vector(9 downto 0); + -- Message delay (in ns, added to time in message). + message_delay_ns: in std_logic_vector(21 downto 0); + -- Output message. + transmit: out std_logic := '0'; + -- Oscilloscope sync signal for message. + transmit_sync: out std_logic := '0' + ); + end component; + + +begin + +--------------------------------------------------------------------------- +-- I/O +--------------------------------------------------------------------------- +serial_in_i <= SERIAL_IN when CONF_loopback = '0' else serial_out_i; +SERIAL_OUT <= serial_out_i; + + +--------------------------------------------------------------------------- +-- Receiver +--------------------------------------------------------------------------- + +THE_RATASER_CLOCK : rataser_clock_recv + generic map( + period_bits => 1, -- Number of bits for pulse period. + num_last_edges => 1 -- Number of edges to report + ) + port map( + clk => CLK, + clk90 => '0', -- 90 degree phase shifted clock (only needed for eight_slot/4phase). + + receive => serial_in_i, -- Input serial signal. + + eight_slot => '0', -- Use 8 pulses to decode 1 raw bit (for PLL reception). + -- The two following only used for 4phase_sample / eight_slot: + expect_edge => "00", -- Where is the edge expected? + last_edges => open, -- Sequence of edges seen most recently. (For monitoring/setup.), two bits for each edge, most recent in 1 downto 0. + use_auto_edge => '0', -- Use routine to automatically lock onto edge. NOTE! This is *NOT* repeatable when signal is at clock edge! + auto_edge => open, -- The edge currently determined by the edge tracker. + + receive_delay_ns => CONF_time_offset, -- Reception delay (in ns, added to timestamp). + + tick_ns_lo => timestamp_i(31 downto 0), -- Output timestamp, low 32 bits. + tick_ns_hi => timestamp_i(63 downto 32), -- High 32 bits of timestamp, latch one cycle later than low word. + + aux_sigs => aux_sigs_i, -- Aux signals. + info_bit => open, -- Auxiliary information. + msg_strobe => TRG_SYNC_OUT, -- Strobe signal that we have decoded a new info bit message. + sync_status => sync_status_i, -- Report current sync status (0 = pulse, 1 = 24-slot, 2 = time). + sync_lost => sync_lost_i, -- Report if any sync status has been lost since clear. + bad_signals => bad_signals_i, -- Report different kinds of protocol issues since clear. + clear_status => CONF_clear_status_i, + pulse_period_clks=> (others => '0'), -- When operated behind a PLL, the pulse length (in clock cycles) + clk_period_ns => (others => '0'), -- When operated behind a PLL, the frequency must be given. + + sym8_debug => open + ); + +--------------------------------------------------------------------------- +-- Event data output +--------------------------------------------------------------------------- + PROC_RDO : process begin + wait until rising_edge(CLK); + WRITE_OUT <= '0'; + FINISHED_OUT <= '0'; + STATUSBIT_OUT <= (others => '0');--(23 => data_status_reg(0), others => '0'); + DATA_OUT <= x"00000000"; + case rdostate is + when RDO_IDLE => + DATA_OUT <= x"00000000"; + if TRIGGER_IN = '1' then + rdostate <= RDO_WRITE1; + end if; + when RDO_WRITE1 => + rdostate <= RDO_WRITE2; + DATA_OUT <= timestamp_i(31 downto 0); + WRITE_OUT <= '1'; + when RDO_WRITE2 => + rdostate <= RDO_WRITE3; + DATA_OUT <= timestamp_i(63 downto 32); + WRITE_OUT <= '1'; + when RDO_WRITE3 => + rdostate <= RDO_WRITE4; + DATA_OUT <= (others => '0'); + WRITE_OUT <= '1'; + when RDO_WRITE4 => + rdostate <= RDO_FINISH; + DATA_OUT <= status_i; + WRITE_OUT <= '1'; + when RDO_FINISH => + FINISHED_OUT <= '1'; + rdostate <= RDO_IDLE; + end case; + end process; + + +--------------------------------------------------------------------------- +-- Registers +--------------------------------------------------------------------------- + status_i <= "000" & aux_sigs_i + & "00000" & sync_status_i + & "00000" & sync_lost_i + & "000" & bad_signals_i when rising_edge(CLK); + + STATUS_REG_OUT <= status_i; + + CONF_time_offset <= CONTROL_REG_IN(15 downto 0) when rising_edge(CLK); + CONF_clear_status_i <= CONTROL_REG_IN(16) when rising_edge(CLK); + CONF_loopback <= CONTROL_REG_IN(31) when rising_edge(CLK); + + DEBUG <= x"00000000"; + + HEADER_REG_OUT <= b"10"; -- send four words on DATA_OUT + + +--------------------------------------------------------------------------- +-- Dummy timestamp sender +--------------------------------------------------------------------------- +THE_SENDER: rataser_clock_send + generic map( + period_bits => 6 + ) + port map( + clk => CLK, + tick_ns => std_logic_vector(sender_timestamp), + aux_sigs => "00000", + info_bit => '0', + + pulse_period_clks => "100000", + duty_low_min_clks => "001000", + duty_low_max_clks => "010000", + eight_slot => '0', + + pulse_period_ns => 320, + message_delay_ns => (others => '0'), + + transmit => serial_out_i, + transmit_sync => open + ); + + +PROC_TIMESTAMP : process begin + wait until rising_edge(CLK); + + sender_timestamp(31 downto 0) <= sender_timestamp(31 downto 0) + 10; + + if sender_timestamp_upper_enable = '1' then + sender_timestamp(63 downto 32) <= sender_timestamp(63 downto 32) + 1; + end if; + + sender_timestamp_upper_enable <= '0'; + if sender_timestamp(31 downto 0) < 10 then + sender_timestamp_upper_enable <= '1'; + end if; + +end process; + + +end architecture;