]> jspc29.x-matter.uni-frankfurt.de Git - trb3.git/commitdiff
add module to receive R3B white rabbit timestamps to CTS
authorJan Michel <j.michel@gsi.de>
Mon, 11 Oct 2021 18:00:45 +0000 (20:00 +0200)
committerJan Michel <j.michel@gsi.de>
Mon, 11 Oct 2021 18:00:45 +0000 (20:00 +0200)
base/code/input_statistics.vhd
cts/source/r3b_timestamp_recv.vhd [new file with mode: 0644]

index 4ef7be87769dece66bc68dc7aec79c4f9564c611..968619143991ff085c2ab6576188fb8353738668 100644 (file)
@@ -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 (file)
index 0000000..e873928
--- /dev/null
@@ -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;