]> jspc29.x-matter.uni-frankfurt.de Git - trb3.git/commitdiff
CBMNet: First version of sync-module (not fully tested yet), small changes to PHY
authorManuel Penschuck <manuel.penschuck@stud.uni-frankfurt.de>
Mon, 22 Sep 2014 16:16:25 +0000 (18:16 +0200)
committerManuel Penschuck <manuel.penschuck@stud.uni-frankfurt.de>
Mon, 22 Sep 2014 16:16:25 +0000 (18:16 +0200)
base/txt_util.vhd [new file with mode: 0644]
cbmnet/code/cbmnet_interface_pkg.vhd
cbmnet/code/cbmnet_phy_ecp3.vhd
cbmnet/code/cbmnet_phy_rx_gear.vhd
cbmnet/code/cbmnet_phy_tx_gear.vhd
cbmnet/code/cbmnet_readout_event_packer.vhd [new file with mode: 0644]
cbmnet/code/cbmnet_sync_module.vhd [new file with mode: 0644]
cbmnet/code/pos_edge_strech_sync.vhd [new file with mode: 0644]

diff --git a/base/txt_util.vhd b/base/txt_util.vhd
new file mode 100644 (file)
index 0000000..db9ac7f
--- /dev/null
@@ -0,0 +1,588 @@
+-- taken from www.stefanvhdl.com/vhdl/vhdl/txt_util.vhd\r
+\r
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+use std.textio.all;\r
+\r
+\r
+package txt_util is\r
+\r
+    -- prints a message to the screen\r
+    procedure print(text: string);\r
+\r
+    -- prints the message when active\r
+    -- useful for debug switches\r
+    procedure print(active: boolean; text: string);\r
+\r
+    -- converts std_logic into a character\r
+    function chr(sl: std_logic) return character;\r
+\r
+    -- converts std_logic into a string (1 to 1)\r
+    function str(sl: std_logic) return string;\r
+\r
+    -- converts std_logic_vector into a string (binary base)\r
+    function str(slv: std_logic_vector) return string;\r
+\r
+    -- converts boolean into a string\r
+    function str(b: boolean) return string;\r
+\r
+    -- converts an integer into a single character\r
+    -- (can also be used for hex conversion and other bases)\r
+    function chr(int: integer) return character;\r
+\r
+    -- converts integer into string using specified base\r
+    function str(int: integer; base: integer) return string;\r
+\r
+    -- converts integer to string, using base 10\r
+    function str(int: integer) return string;\r
+\r
+    -- convert std_logic_vector into a string in hex format\r
+    function hstr(slv: std_logic_vector) return string;\r
+\r
+\r
+    -- functions to manipulate strings\r
+    -----------------------------------\r
+\r
+    -- convert a character to upper case\r
+    function to_upper(c: character) return character;\r
+\r
+    -- convert a character to lower case\r
+    function to_lower(c: character) return character;\r
+\r
+    -- convert a string to upper case\r
+    function to_upper(s: string) return string;\r
+\r
+    -- convert a string to lower case\r
+    function to_lower(s: string) return string;\r
+\r
+   \r
+    \r
+    -- functions to convert strings into other formats\r
+    --------------------------------------------------\r
+    \r
+    -- converts a character into std_logic\r
+    function to_std_logic(c: character) return std_logic; \r
+    \r
+    -- converts a string into std_logic_vector\r
+    function to_std_logic_vector(s: string) return std_logic_vector; \r
+\r
+\r
+  \r
+    -- file I/O\r
+    -----------\r
+       \r
+    -- read variable length string from input file\r
+    procedure str_read(file in_file: TEXT; \r
+                       res_string: out string);\r
+        \r
+    -- print string to a file and start new line\r
+    procedure print(file out_file: TEXT;\r
+                    new_string: in  string);\r
+    \r
+    -- print character to a file and start new line\r
+    procedure print(file out_file: TEXT;\r
+                    char:       in  character);\r
+                    \r
+end txt_util;\r
+\r
+\r
+\r
+\r
+package body txt_util is\r
+\r
+\r
+\r
+\r
+   -- prints text to the screen\r
+\r
+   procedure print(text: string) is\r
+     variable msg_line: line;\r
+     begin\r
+       write(msg_line, text);\r
+       writeline(output, msg_line);\r
+   end print;\r
+\r
+\r
+\r
+\r
+   -- prints text to the screen when active\r
+\r
+   procedure print(active: boolean; text: string)  is\r
+     begin\r
+      if active then\r
+         print(text);\r
+      end if;\r
+   end print;\r
+\r
+\r
+   -- converts std_logic into a character\r
+\r
+   function chr(sl: std_logic) return character is\r
+    variable c: character;\r
+    begin\r
+      case sl is\r
+         when 'U' => c:= 'U';\r
+         when 'X' => c:= 'X';\r
+         when '0' => c:= '0';\r
+         when '1' => c:= '1';\r
+         when 'Z' => c:= 'Z';\r
+         when 'W' => c:= 'W';\r
+         when 'L' => c:= 'L';\r
+         when 'H' => c:= 'H';\r
+         when '-' => c:= '-';\r
+      end case;\r
+    return c;\r
+   end chr;\r
+\r
+\r
+\r
+   -- converts std_logic into a string (1 to 1)\r
+\r
+   function str(sl: std_logic) return string is\r
+    variable s: string(1 to 1);\r
+    begin\r
+        s(1) := chr(sl);\r
+        return s;\r
+   end str;\r
+\r
+\r
+\r
+   -- converts std_logic_vector into a string (binary base)\r
+   -- (this also takes care of the fact that the range of\r
+   --  a string is natural while a std_logic_vector may\r
+   --  have an integer range)\r
+\r
+   function str(slv: std_logic_vector) return string is\r
+     variable result : string (1 to slv'length);\r
+     variable r : integer;\r
+   begin\r
+     r := 1;\r
+     for i in slv'range loop\r
+        result(r) := chr(slv(i));\r
+        r := r + 1;\r
+     end loop;\r
+     return result;\r
+   end str;\r
+\r
+\r
+   function str(b: boolean) return string is\r
+\r
+    begin\r
+       if b then\r
+          return "true";\r
+      else\r
+        return "false";\r
+       end if;\r
+    end str;\r
+\r
+\r
+   -- converts an integer into a character\r
+   -- for 0 to 9 the obvious mapping is used, higher\r
+   -- values are mapped to the characters A-Z\r
+   -- (this is usefull for systems with base > 10)\r
+   -- (adapted from Steve Vogwell's posting in comp.lang.vhdl)\r
+\r
+   function chr(int: integer) return character is\r
+    variable c: character;\r
+   begin\r
+        case int is\r
+          when  0 => c := '0';\r
+          when  1 => c := '1';\r
+          when  2 => c := '2';\r
+          when  3 => c := '3';\r
+          when  4 => c := '4';\r
+          when  5 => c := '5';\r
+          when  6 => c := '6';\r
+          when  7 => c := '7';\r
+          when  8 => c := '8';\r
+          when  9 => c := '9';\r
+          when 10 => c := 'A';\r
+          when 11 => c := 'B';\r
+          when 12 => c := 'C';\r
+          when 13 => c := 'D';\r
+          when 14 => c := 'E';\r
+          when 15 => c := 'F';\r
+          when 16 => c := 'G';\r
+          when 17 => c := 'H';\r
+          when 18 => c := 'I';\r
+          when 19 => c := 'J';\r
+          when 20 => c := 'K';\r
+          when 21 => c := 'L';\r
+          when 22 => c := 'M';\r
+          when 23 => c := 'N';\r
+          when 24 => c := 'O';\r
+          when 25 => c := 'P';\r
+          when 26 => c := 'Q';\r
+          when 27 => c := 'R';\r
+          when 28 => c := 'S';\r
+          when 29 => c := 'T';\r
+          when 30 => c := 'U';\r
+          when 31 => c := 'V';\r
+          when 32 => c := 'W';\r
+          when 33 => c := 'X';\r
+          when 34 => c := 'Y';\r
+          when 35 => c := 'Z';\r
+          when others => c := '?';\r
+        end case;\r
+        return c;\r
+    end chr;\r
+\r
+\r
+\r
+   -- convert integer to string using specified base\r
+   -- (adapted from Steve Vogwell's posting in comp.lang.vhdl)\r
+\r
+   function str(int: integer; base: integer) return string is\r
+\r
+    variable temp:      string(1 to 10);\r
+    variable num:       integer;\r
+    variable abs_int:   integer;\r
+    variable len:       integer := 1;\r
+    variable power:     integer := 1;\r
+\r
+   begin\r
+\r
+    -- bug fix for negative numbers\r
+    abs_int := abs(int);\r
+\r
+    num     := abs_int;\r
+\r
+    while num >= base loop                     -- Determine how many\r
+      len := len + 1;                          -- characters required\r
+      num := num / base;                       -- to represent the\r
+    end loop ;                                 -- number.\r
+\r
+    for i in len downto 1 loop                 -- Convert the number to\r
+      temp(i) := chr(abs_int/power mod base);  -- a string starting\r
+      power := power * base;                   -- with the right hand\r
+    end loop ;                                 -- side.\r
+\r
+    -- return result and add sign if required\r
+    if int < 0 then\r
+       return '-'& temp(1 to len);\r
+     else\r
+       return temp(1 to len);\r
+    end if;\r
+\r
+   end str;\r
+\r
+\r
+  -- convert integer to string, using base 10\r
+  function str(int: integer) return string is\r
+\r
+   begin\r
+\r
+    return str(int, 10) ;\r
+\r
+   end str;\r
+\r
+\r
+\r
+   -- converts a std_logic_vector into a hex string.\r
+   function hstr(slv: std_logic_vector) return string is\r
+       variable hexlen: integer;\r
+       variable longslv : std_logic_vector(67 downto 0) := (others => '0');\r
+       variable hex : string(1 to 16);\r
+       variable fourbit : std_logic_vector(3 downto 0);\r
+     begin\r
+       hexlen := (slv'left+1)/4;\r
+       if (slv'left+1) mod 4 /= 0 then\r
+         hexlen := hexlen + 1;\r
+       end if;\r
+       longslv(slv'left downto 0) := slv;\r
+       for i in (hexlen -1) downto 0 loop\r
+         fourbit := longslv(((i*4)+3) downto (i*4));\r
+         case fourbit is\r
+           when "0000" => hex(hexlen -I) := '0';\r
+           when "0001" => hex(hexlen -I) := '1';\r
+           when "0010" => hex(hexlen -I) := '2';\r
+           when "0011" => hex(hexlen -I) := '3';\r
+           when "0100" => hex(hexlen -I) := '4';\r
+           when "0101" => hex(hexlen -I) := '5';\r
+           when "0110" => hex(hexlen -I) := '6';\r
+           when "0111" => hex(hexlen -I) := '7';\r
+           when "1000" => hex(hexlen -I) := '8';\r
+           when "1001" => hex(hexlen -I) := '9';\r
+           when "1010" => hex(hexlen -I) := 'A';\r
+           when "1011" => hex(hexlen -I) := 'B';\r
+           when "1100" => hex(hexlen -I) := 'C';\r
+           when "1101" => hex(hexlen -I) := 'D';\r
+           when "1110" => hex(hexlen -I) := 'E';\r
+           when "1111" => hex(hexlen -I) := 'F';\r
+           when "ZZZZ" => hex(hexlen -I) := 'z';\r
+           when "UUUU" => hex(hexlen -I) := 'u';\r
+           when "XXXX" => hex(hexlen -I) := 'x';\r
+           when others => hex(hexlen -I) := '?';\r
+         end case;\r
+       end loop;\r
+       return hex(1 to hexlen);\r
+     end hstr;\r
+\r
+\r
+\r
+   -- functions to manipulate strings\r
+   -----------------------------------\r
+\r
+\r
+   -- convert a character to upper case\r
+\r
+   function to_upper(c: character) return character is\r
+\r
+      variable u: character;\r
+\r
+    begin\r
+\r
+       case c is\r
+        when 'a' => u := 'A';\r
+        when 'b' => u := 'B';\r
+        when 'c' => u := 'C';\r
+        when 'd' => u := 'D';\r
+        when 'e' => u := 'E';\r
+        when 'f' => u := 'F';\r
+        when 'g' => u := 'G';\r
+        when 'h' => u := 'H';\r
+        when 'i' => u := 'I';\r
+        when 'j' => u := 'J';\r
+        when 'k' => u := 'K';\r
+        when 'l' => u := 'L';\r
+        when 'm' => u := 'M';\r
+        when 'n' => u := 'N';\r
+        when 'o' => u := 'O';\r
+        when 'p' => u := 'P';\r
+        when 'q' => u := 'Q';\r
+        when 'r' => u := 'R';\r
+        when 's' => u := 'S';\r
+        when 't' => u := 'T';\r
+        when 'u' => u := 'U';\r
+        when 'v' => u := 'V';\r
+        when 'w' => u := 'W';\r
+        when 'x' => u := 'X';\r
+        when 'y' => u := 'Y';\r
+        when 'z' => u := 'Z';\r
+        when others => u := c;\r
+    end case;\r
+\r
+      return u;\r
+\r
+   end to_upper;\r
+\r
+\r
+   -- convert a character to lower case\r
+\r
+   function to_lower(c: character) return character is\r
+\r
+      variable l: character;\r
+\r
+    begin\r
+\r
+       case c is\r
+        when 'A' => l := 'a';\r
+        when 'B' => l := 'b';\r
+        when 'C' => l := 'c';\r
+        when 'D' => l := 'd';\r
+        when 'E' => l := 'e';\r
+        when 'F' => l := 'f';\r
+        when 'G' => l := 'g';\r
+        when 'H' => l := 'h';\r
+        when 'I' => l := 'i';\r
+        when 'J' => l := 'j';\r
+        when 'K' => l := 'k';\r
+        when 'L' => l := 'l';\r
+        when 'M' => l := 'm';\r
+        when 'N' => l := 'n';\r
+        when 'O' => l := 'o';\r
+        when 'P' => l := 'p';\r
+        when 'Q' => l := 'q';\r
+        when 'R' => l := 'r';\r
+        when 'S' => l := 's';\r
+        when 'T' => l := 't';\r
+        when 'U' => l := 'u';\r
+        when 'V' => l := 'v';\r
+        when 'W' => l := 'w';\r
+        when 'X' => l := 'x';\r
+        when 'Y' => l := 'y';\r
+        when 'Z' => l := 'z';\r
+        when others => l := c;\r
+    end case;\r
+\r
+      return l;\r
+\r
+   end to_lower;\r
+\r
+\r
+\r
+   -- convert a string to upper case\r
+\r
+   function to_upper(s: string) return string is\r
+\r
+     variable uppercase: string (s'range);\r
+\r
+   begin\r
+\r
+     for i in s'range loop\r
+        uppercase(i):= to_upper(s(i));\r
+     end loop;\r
+     return uppercase;\r
+\r
+   end to_upper;\r
+\r
+\r
+\r
+   -- convert a string to lower case\r
+\r
+   function to_lower(s: string) return string is\r
+\r
+     variable lowercase: string (s'range);\r
+\r
+   begin\r
+\r
+     for i in s'range loop\r
+        lowercase(i):= to_lower(s(i));\r
+     end loop;\r
+     return lowercase;\r
+\r
+   end to_lower;\r
+\r
+\r
+\r
+-- functions to convert strings into other types\r
+\r
+\r
+-- converts a character into a std_logic\r
+\r
+function to_std_logic(c: character) return std_logic is \r
+    variable sl: std_logic;\r
+    begin\r
+      case c is\r
+        when 'U' => \r
+           sl := 'U'; \r
+        when 'X' =>\r
+           sl := 'X';\r
+        when '0' => \r
+           sl := '0';\r
+        when '1' => \r
+           sl := '1';\r
+        when 'Z' => \r
+           sl := 'Z';\r
+        when 'W' => \r
+           sl := 'W';\r
+        when 'L' => \r
+           sl := 'L';\r
+        when 'H' => \r
+           sl := 'H';\r
+        when '-' => \r
+           sl := '-';\r
+        when others =>\r
+           sl := 'X'; \r
+    end case;\r
+   return sl;\r
+  end to_std_logic;\r
+\r
+\r
+-- converts a string into std_logic_vector\r
+\r
+function to_std_logic_vector(s: string) return std_logic_vector is \r
+  variable slv: std_logic_vector(s'high-s'low downto 0);\r
+  variable k: integer;\r
+begin\r
+   k := s'high-s'low;\r
+  for i in s'range loop\r
+     slv(k) := to_std_logic(s(i));\r
+     k      := k - 1;\r
+  end loop;\r
+  return slv;\r
+end to_std_logic_vector;                                       \r
+                                       \r
+                                       \r
+                                       \r
+                                       \r
+                                       \r
+                                       \r
+----------------\r
+--  file I/O  --\r
+----------------\r
+\r
+\r
+\r
+-- read variable length string from input file\r
+     \r
+procedure str_read(file in_file: TEXT; \r
+                   res_string: out string) is\r
+       \r
+       variable l:         line;\r
+       variable c:         character;\r
+       variable is_string: boolean;\r
+       \r
+   begin\r
+           \r
+     readline(in_file, l);\r
+     -- clear the contents of the result string\r
+     for i in res_string'range loop\r
+         res_string(i) := ' ';\r
+     end loop;   \r
+     -- read all characters of the line, up to the length  \r
+     -- of the results string\r
+     for i in res_string'range loop\r
+        read(l, c, is_string);\r
+        res_string(i) := c;\r
+        if not is_string then -- found end of line\r
+           exit;\r
+        end if;   \r
+     end loop; \r
+                     \r
+end str_read;\r
+\r
+\r
+-- print string to a file\r
+procedure print(file out_file: TEXT;\r
+                new_string: in  string) is\r
+       \r
+       variable l: line;\r
+       \r
+   begin\r
+      \r
+     write(l, new_string);\r
+     writeline(out_file, l);\r
+                     \r
+end print;\r
+\r
+\r
+-- print character to a file and start new line\r
+procedure print(file out_file: TEXT;\r
+                char: in  character) is\r
+       \r
+       variable l: line;\r
+       \r
+   begin\r
+      \r
+     write(l, char);\r
+     writeline(out_file, l);\r
+                     \r
+end print;\r
+\r
+\r
+\r
+-- appends contents of a string to a file until line feed occurs\r
+-- (LF is considered to be the end of the string)\r
+\r
+procedure str_write(file out_file: TEXT; \r
+                    new_string: in  string) is\r
+ begin\r
+      \r
+   for i in new_string'range loop\r
+      print(out_file, new_string(i));\r
+      if new_string(i) = LF then -- end of string\r
+         exit;\r
+      end if;\r
+   end loop;               \r
+                     \r
+end str_write;\r
+\r
+\r
+\r
+\r
+end txt_util;\r
+\r
+\r
+\r
+\r
index d0aa0bf9c537e20caf5361766b4859584ce5e918..669f149468216bfdc4d4e04f1e94f7aa1434fc42 100644 (file)
@@ -522,6 +522,64 @@ package cbmnet_interface_pkg is
          FILLED_IN : in std_logic;
          FILLED_OUT : out std_logic
       );
+   end component;
+   
+   component pos_edge_strech_sync is
+      generic (
+         LENGTH : positive := 2
+      );
+      port (
+         IN_CLK_IN : std_logic;
+         DATA_IN : std_logic;
+         OUT_CLK_IN : std_logic;
+         DATA_OUT : std_logic
+      );
+   end component;
+   
+   component cbmnet_sync_module is
+      port(
+      -- TRB
+         TRB_CLK_IN     : in std_logic;  
+         TRB_RESET_IN   : in std_logic;
+         TRB_TRIGGER_OUT: out std_logic;
+
+         --data output for read-out
+         TRB_TRIGGER_IN       : in  std_logic;
+         TRB_RDO_VALID_IN     : in  std_logic;
+         TRB_RDO_DATA_OUT     : out std_logic_vector(31 downto 0);
+         TRB_RDO_WRITE_OUT    : out std_logic;
+         TRB_RDO_STATUSBIT_OUT: out std_logic_vector(31 downto 0);
+         TRB_RDO_FINISHED_OUT : out std_logic;
+
+         -- reg io
+         TRB_REGIO_ADDR_IN                  : in  std_logic_vector(15 downto 0);
+         TRB_REGIO_DATA_IN                  : in  std_logic_vector(31 downto 0);
+         TRB_REGIO_READ_ENABLE_IN           : in  std_logic;
+         TRB_REGIO_WRITE_ENABLE_IN          : in  std_logic;
+         TRB_REGIO_DATA_OUT                 : out std_logic_vector(31 downto 0);
+         TRB_REGIO_DATAREADY_OUT            : out std_logic;
+         TRB_REGIO_WRITE_ACK_OUT            : out std_logic;
+         TRB_REGIO_UNKNOWN_ADDR_OUT         : out std_logic;
+         
+      -- CBMNET
+         CBM_CLK_IN           : in std_logic;
+         CBM_RESET_IN         : in std_logic;
+         CBM_PHY_BARREL_SHIFTER_POS_IN : in std_logic_vector(3 downto 0);
+         
+         -- DLM port
+         CBM_DLM_REC_IN       : in std_logic_vector(3 downto 0);
+         CBM_DLM_REC_VALID_IN : in std_logic;
+         CBM_DLM_SENSE_OUT    : out std_logic;
+         CBM_PULSER_OUT       : out std_logic; -- connect to TDC
+         
+         -- Ctrl port
+         CBM_CTRL_DATA_IN        : in std_logic_vector(15 downto 0);
+         CBM_CTRL_DATA_START_IN  : in std_logic;
+         CBM_CTRL_DATA_END_IN    : in std_logic;
+         CBM_CTRL_DATA_STOP_OUT  : out std_logic;
+         
+         DEBUG_OUT      : out std_logic_vector(31 downto 0)    
+      );
    end component;   
 end package cbmnet_interface_pkg;
 
index 6965a10f2b2235d9f4689ddbba16a2103e881b3c..99e529c96c08e9b95f4bc46786fd158e61674773 100755 (executable)
@@ -56,20 +56,19 @@ entity cbmnet_phy_ecp3 is
       CTRL_OP            : in  std_logic_vector ( 15 downto 0) := (others => '0');
       DEBUG_OUT          : out std_logic_vector (511 downto 0) := (others => '0')
    );
+   
+   attribute BLOCKNET : boolean;
+   attribute BLOCKNET of DEBUG_OUT : signal is true;
 end entity;
 
 architecture cbmnet_phy_ecp3_arch of cbmnet_phy_ecp3 is
    -- Placer Directives
-   attribute HGROUP : string;
-   -- for whole architecture
-   attribute HGROUP of cbmnet_phy_ecp3_arch : architecture  is "cbmnet_phy_group";
-   
-   attribute syn_hier: string;
-   attribute syn_hier of cbmnet_phy_ecp3_arch : architecture is "hard"; 
-   
-   
-   attribute syn_sharing : string;
-   attribute syn_sharing of cbmnet_phy_ecp3_arch : architecture is "off";
+--    attribute syn_hier: string;
+--    attribute syn_hier of cbmnet_phy_ecp3_arch : architecture is "hard"; 
+--    
+--    
+--    attribute syn_sharing : string;
+--    attribute syn_sharing of cbmnet_phy_ecp3_arch : architecture is "off";
 
    constant WA_FIXATION : integer := c_YES;
    signal DETERMINISTIC_LATENCY_C : std_logic;
index f0f0166e57de0650e6ba7af609e7417bf40cea7c..ee5799db720d498ca1c6fe6950309f6e2eb6ace2 100644 (file)
@@ -32,8 +32,8 @@ entity CBMNET_PHY_RX_GEAR is
 end entity;
 
 architecture CBMNET_PHY_RX_GEAR_ARCH of CBMNET_PHY_RX_GEAR is
-   attribute HGROUP : string;
-   attribute HGROUP of CBMNET_PHY_RX_GEAR_ARCH : architecture  is "cbmnet_phy_rx_gear";
+--    attribute HGROUP : string;
+--    attribute HGROUP of CBMNET_PHY_RX_GEAR_ARCH : architecture  is "cbmnet_phy_rx_gear";
 
 
    type FSM_STATES_T is (FSM_START, FSM_WAIT_FOR_LOCK, FSM_LOCK_WAIT1, FSM_LOCK_WAIT2, FSM_LOCK_WAIT3, FSM_RESET, FSM_LOCKED);
@@ -55,7 +55,8 @@ architecture CBMNET_PHY_RX_GEAR_ARCH of CBMNET_PHY_RX_GEAR is
    
    signal data_in_buf_i : std_logic_vector( 8 downto 0); 
    
-   
+      signal delay_clock_x_i : std_logic;
+
    signal delay_clock_buf_i : std_logic;
    signal delay_clock_buf1_i : std_logic;
    signal last_delay_clock_i : std_logic := '0';
@@ -78,6 +79,7 @@ begin
          RESET_OUT <= '1';
          reset_timer_i <= '0';
          delay_clock_i <= '0';
+         delay_clock_x_i <= delay_clock_i;
          
          case (fsm_i) is
             when FSM_START =>
@@ -156,7 +158,7 @@ begin
 
 -- Implement the 2:1 gearing and clock down-sampling
    --delay_clock_buf1_i <= delay_clock_i when rising_edge(CLK_250_IN);
-   delay_clock_buf_i <= delay_clock_i when rising_edge(CLK_250_IN);
+   delay_clock_buf_i <= delay_clock_x_i when rising_edge(CLK_250_IN);
  
 
    proc_ctrl_gear: process
@@ -193,7 +195,7 @@ begin
    CLK_125_OUT <= clk_125_i; -- when rising_edge(CLK_250_IN);
    
    DEBUG_OUT(3 downto 0) <= STD_LOGIC_VECTOR(fsm_state_i);
-   DEBUG_OUT(4) <= delay_clock_i;
+   --DEBUG_OUT(4) <= delay_clock_i;
    DEBUG_OUT(5) <= indi_alignment_i;
    DEBUG_OUT(6) <= indi_misalignment_i;
    
index ca0ff1ef2a482a0ebc22446f81d133f74dc039f5..7ebdcb9d5076936af178430c658456be973986e0 100644 (file)
@@ -32,13 +32,14 @@ entity CBMNET_PHY_TX_GEAR is
 end entity;
 
 architecture CBMNET_PHY_TX_GEAR_ARCH of CBMNET_PHY_TX_GEAR is
-   attribute HGROUP : string;
-   attribute HGROUP of CBMNET_PHY_TX_GEAR_ARCH : architecture  is "cbmnet_phy_tx_gear";
+--    attribute HGROUP : string;
+--    attribute HGROUP of CBMNET_PHY_TX_GEAR_ARCH : architecture  is "cbmnet_phy_tx_gear";
 
-   type   FSM_STATES is (FSM_HIGH, FSM_LOW);
+   type   FSM_STATES is (FSM_LOCKING, FSM_HIGH, FSM_LOW);
    signal fsm_i : FSM_STATES;
    
    signal data_in_buf125_i : std_logic_vector(17 downto 0);
+   signal data_in_buf125_0_i : std_logic_vector(17 downto 0);
    signal data_in_buf250_i : std_logic_vector(17 downto 0);
    signal data_in_buf250_0_i : std_logic_vector(17 downto 0);
    
@@ -53,15 +54,11 @@ begin
    process is begin
       wait until rising_edge(CLK_250_IN);
       
-      if RESET_IN='1' then
-         delay_counter_i <= TO_UNSIGNED(0,16);
-      end if;
-      
       data_in_buf250_0_i <= data_in_buf125_i;
       data_in_buf250_i <= data_in_buf250_0_i;
       
       
-      clk_125_xfer_buf_i <= clk_125_xfer_i;
+      clk_125_xfer_buf_i <= CLK_125_IN;
       clk_125_xfer_del_i <= clk_125_xfer_buf_i;
       CLK_125_OUT <= '0';
       
@@ -79,19 +76,27 @@ begin
 --             end if;
 
             
-         when others =>
+         when FSM_LOW =>
             DATA_OUT <= delay_data_i;
             fsm_i <= FSM_HIGH;
+            
+         when others =>
+            if clk_125_xfer_del_i = '0' and clk_125_xfer_buf_i = '1' then
+               fsm_i <= FSM_HIGH;
+            end if;
       end case;
+      
+       if RESET_IN='1' then
+          fsm_i <= FSM_LOCKING;
+       end if;
    end process;
    
    TX_READY_OUT <= not RESET_IN;
    
    process is begin
       wait until rising_edge(CLK_125_IN);
-      
-      data_in_buf125_i <= DATA_IN;
-      clk_125_xfer_i   <= not clk_125_xfer_i;
+      data_in_buf125_0_i <= DATA_IN;
+      data_in_buf125_i <= data_in_buf125_0_i;
    end process;
    
    DEBUG_OUT <= (others => '0'); -- x"0000" & STD_LOGIC_VECTOR( delay_counter_i );
diff --git a/cbmnet/code/cbmnet_readout_event_packer.vhd b/cbmnet/code/cbmnet_readout_event_packer.vhd
new file mode 100644 (file)
index 0000000..21bbc56
--- /dev/null
@@ -0,0 +1,212 @@
+library ieee;
+   use ieee.std_logic_1164.all;
+   use ieee.numeric_std.all;
+
+entity CBMNET_READOUT_EVENT_PACKER is
+   port (
+   -- TrbNet
+      CLK_IN   : in std_logic;
+      RESET_IN : in std_logic;
+
+      -- connect to hub
+      HUB_CTS_NUMBER_IN              : in  std_logic_vector (15 downto 0);
+      HUB_CTS_CODE_IN                : in  std_logic_vector (7  downto 0);
+      HUB_CTS_INFORMATION_IN         : in  std_logic_vector (7  downto 0);
+      HUB_CTS_READOUT_TYPE_IN        : in  std_logic_vector (3  downto 0);
+      GBE_CTS_STATUS_BITS_IN         : in  std_logic_vector (31 downto 0);
+      
+      
+      -- connect to decoder
+      DEC_EVT_INFO_IN                : in  std_logic_vector(31 downto 0);
+      DEC_LENGTH_IN                  : in  std_logic_vector(15 downto 0);
+      DEC_SOURCE_IN                  : in  std_logic_vector(15 downto 0);
+      DEC_DATA_IN                    : in  std_logic_vector(15 downto 0);
+      DEC_DATA_READY_IN              : in  std_logic;
+      DEC_ACTIVE_IN                  : in  std_logic;
+      DEC_ERROR_IN                   : in  std_logic;
+      
+      DEC_DATA_READ_OUT              : out std_logic;
+      DEC_RESET_OUT                  : out std_logic;
+
+      -- connect to fifo
+      WADDR_STORE_OUT  : out std_logic;
+      WADDR_RESTORE_OUT: out std_logic;
+      WDATA_OUT        : out std_logic_vector(17 downto 0);
+      WENQUEUE_OUT     : out std_logic;
+      WPACKET_COMPLETE_OUT: out std_logic;
+      WFULL_IN         : in  std_logic;
+      
+      DEBUG_OUT                      : out std_logic_vector(31 downto 0)
+   );
+end entity;
+
+architecture cbmnet_readout_event_packer_arch of CBMNET_READOUT_EVENT_PACKER is
+   type FSM_STATES_T is (
+      WAIT_FOR_IDLE, IDLE, 
+      HDR_SIZE_H, HDR_SIZE_L, 
+      HDR_DECODING_H, HDR_DECODING_L,
+      HDR_ID_H, HDR_ID_L,
+      HDR_NUMBER_H, HDR_NUMBER_L,
+      PAYLOAD,
+      TRL_TRAILER_H, TRL_TRAILER_L,
+      TRL_STATUS_H, TRL_STATUS_L
+   );
+   
+   type FSM_STATES_ENC_T is array(FSM_STATES_T) of std_logic_vector(3 downto 0);
+   constant fsm_states_enc_c : FSM_STATES_ENC_T := (
+      WAIT_FOR_IDLE => x"0",
+      IDLE          => x"1",
+      HDR_SIZE_H    => x"2",
+      HDR_SIZE_L    => x"3",
+      HDR_DECODING_H=> x"4",
+      HDR_DECODING_L=> x"5",
+      HDR_ID_H      => x"6",
+      HDR_ID_L      => x"7",
+      HDR_NUMBER_H  => x"8",
+      HDR_NUMBER_L  => x"9",
+      PAYLOAD       => x"a",
+      TRL_TRAILER_H => x"b",
+      TRL_TRAILER_L => x"c",
+      TRL_STATUS_H  => x"d",
+      TRL_STATUS_L  => x"e"
+   );
+   
+   signal fsm_i : FSM_STATES_T;
+   signal header_data_i : std_logic_vector(15 downto 0);
+   signal header_enqueue_i : std_logic;
+   signal header_token_i : std_logic_vector(1 downto 0);
+   
+   signal copy_payload_i : std_logic;
+   
+   signal data_read_i, data_read_delayed_i : std_logic;
+
+-- local buffers   
+   signal wenqueue_i : std_logic;
+   signal wpacket_complete_i : std_logic;
+   signal waddr_restore_i : std_logic;
+   signal waddr_store_i : std_logic;
+begin
+   THE_PACKER: process is
+   begin
+      wait until rising_edge(CLK_IN);
+      
+      waddr_store_i <= '0';
+      waddr_restore_i <= '0';
+      DEC_RESET_OUT <= '0';    
+      copy_payload_i <= '0';
+      header_data_i <= (others => '-');
+      header_enqueue_i <= '0';
+      wpacket_complete_i <= '0';
+      header_token_i <= "00";
+      
+      if RESET_IN='1' then
+         fsm_i <= WAIT_FOR_IDLE;
+       
+      elsif fsm_i /= IDLE and (DEC_ERROR_IN = '1' or WFULL_IN = '1') then
+         waddr_restore_i <= '1';
+         DEC_RESET_OUT <= '1';
+         fsm_i <= WAIT_FOR_IDLE;
+         
+      else
+         case(fsm_i) is
+            when WAIT_FOR_IDLE =>
+               if DEC_ACTIVE_IN='0' then
+                  fsm_i <= IDLE;
+               end if;
+         
+            when IDLE =>
+               if DEC_ACTIVE_IN='1' then
+                  waddr_store_i <= '1';
+                  fsm_i <= HDR_SIZE_H;
+               end if;
+               
+            when HDR_SIZE_H =>
+               header_token_i <= "01";
+               header_data_i <= x"0000";
+               header_enqueue_i <= '1';
+               fsm_i <= HDR_SIZE_L;
+               
+            when HDR_SIZE_L =>
+               header_token_i <= "10";
+               
+               header_data_i <= STD_LOGIC_VECTOR(UNSIGNED(DEC_LENGTH_IN) + TO_UNSIGNED(16+8, 16)); -- 8 words of SE-Hdr and 4 words for SE-trailer 
+               header_enqueue_i <= '1';
+               fsm_i <= HDR_DECODING_H;
+
+            when HDR_DECODING_H =>
+               header_data_i <= x"0002";
+               header_enqueue_i <= '1';
+               fsm_i <= HDR_DECODING_L;
+            when HDR_DECODING_L =>
+               header_data_i <= x"00" & HUB_CTS_READOUT_TYPE_IN & x"1";
+               header_enqueue_i <= '1';
+               fsm_i <= HDR_ID_H;
+
+            when HDR_ID_H =>
+               header_data_i <= x"0000";
+               header_enqueue_i <= '1';
+               fsm_i <= HDR_ID_L;
+            when HDR_ID_L =>
+               header_data_i <= x"beaf";
+               header_enqueue_i <= '1';
+               fsm_i <= HDR_NUMBER_H;
+
+            when HDR_NUMBER_H =>
+               header_data_i <= x"00" & HUB_CTS_NUMBER_IN(15 downto 8);
+               header_enqueue_i <= '1';
+               fsm_i <= HDR_NUMBER_L;
+            when HDR_NUMBER_L =>
+               header_data_i <= HUB_CTS_NUMBER_IN(7 downto 0) & HUB_CTS_CODE_IN;
+               header_enqueue_i <= '1';
+               fsm_i <= PAYLOAD;
+
+            when PAYLOAD =>
+               if DEC_ACTIVE_IN = '0' then
+                  fsm_i <= TRL_TRAILER_H;
+               else
+                  copy_payload_i <= '1';
+               end if;
+               
+            when TRL_TRAILER_H =>
+               header_data_i <= x"0001";
+               header_enqueue_i <= '1';
+               fsm_i <= TRL_TRAILER_L;
+            when TRL_TRAILER_L =>
+               header_data_i <= x"5555";
+               header_enqueue_i <= '1';
+               fsm_i <= TRL_STATUS_H;            
+
+            when TRL_STATUS_H =>
+               header_data_i <= GBE_CTS_STATUS_BITS_IN(31 downto 16);
+               header_enqueue_i <= '1';
+               fsm_i <= TRL_STATUS_L;
+            when TRL_STATUS_L =>
+               header_token_i <= "11";
+               header_data_i <= GBE_CTS_STATUS_BITS_IN(15 downto  0);
+               header_enqueue_i <= '1';
+               wpacket_complete_i <= '1';
+               fsm_i <= IDLE;                         
+               
+         end case;
+      end if;
+   end process;
+   
+   WDATA_OUT(17 downto 0) <= "00" & DEC_DATA_IN when copy_payload_i='1' else header_token_i & header_data_i;
+   wenqueue_i <= header_enqueue_i or data_read_i;
+   
+   data_read_i <= copy_payload_i and DEC_DATA_READY_IN;
+   DEC_DATA_READ_OUT <= data_read_i;
+   data_read_delayed_i <= data_read_i when rising_edge(CLK_IN);
+
+-- Outputs   
+   WADDR_STORE_OUT <= waddr_store_i;
+   WADDR_RESTORE_OUT <= waddr_restore_i;
+   WENQUEUE_OUT <= wenqueue_i;
+   WPACKET_COMPLETE_OUT <= wpacket_complete_i;
+   
+-- Debug
+   DEBUG_OUT( 3 downto  0) <= fsm_states_enc_c(fsm_i);
+   DEBUG_OUT( 7 downto  4) <= DEC_DATA_READY_IN & DEC_ACTIVE_IN & DEC_ERROR_IN & data_read_i;
+   DEBUG_OUT(11 downto  8) <= wpacket_complete_i & waddr_restore_i & waddr_store_i & wenqueue_i;
+   DEBUG_OUT(15 downto 12) <= "000" & WFULL_IN;
+end architecture;
\ No newline at end of file
diff --git a/cbmnet/code/cbmnet_sync_module.vhd b/cbmnet/code/cbmnet_sync_module.vhd
new file mode 100644 (file)
index 0000000..ddf5853
--- /dev/null
@@ -0,0 +1,462 @@
+library ieee;
+   use ieee.std_logic_1164.all;
+   use ieee.numeric_std.all;
+   use work.cbmnet_interface_pkg.all;
+
+entity cbmnet_sync_module is
+   port(
+   -- TRB
+      TRB_CLK_IN     : in std_logic;  
+      TRB_RESET_IN   : in std_logic;
+      TRB_TRIGGER_OUT: out std_logic;
+
+      --data output for read-out
+      TRB_TRIGGER_IN       : in  std_logic;
+      TRB_RDO_VALID_IN     : in  std_logic;
+      TRB_RDO_DATA_OUT     : out std_logic_vector(31 downto 0);
+      TRB_RDO_WRITE_OUT    : out std_logic;
+      TRB_RDO_STATUSBIT_OUT: out std_logic_vector(31 downto 0);
+      TRB_RDO_FINISHED_OUT : out std_logic;
+
+      -- reg io
+      TRB_REGIO_ADDR_IN                  : in  std_logic_vector(15 downto 0);
+      TRB_REGIO_DATA_IN                  : in  std_logic_vector(31 downto 0);
+      TRB_REGIO_READ_ENABLE_IN           : in  std_logic;
+      TRB_REGIO_WRITE_ENABLE_IN          : in  std_logic;
+      TRB_REGIO_DATA_OUT                 : out std_logic_vector(31 downto 0);
+      TRB_REGIO_DATAREADY_OUT            : out std_logic;
+      TRB_REGIO_WRITE_ACK_OUT            : out std_logic;
+      TRB_REGIO_UNKNOWN_ADDR_OUT         : out std_logic;
+      
+   -- CBMNET
+      CBM_CLK_IN           : in std_logic;
+      CBM_RESET_IN         : in std_logic;
+      CBM_PHY_BARREL_SHIFTER_POS_IN : in std_logic_vector(3 downto 0);
+      
+      -- DLM port
+      CBM_DLM_REC_IN       : in std_logic_vector(3 downto 0);
+      CBM_DLM_REC_VALID_IN : in std_logic;
+      CBM_DLM_SENSE_OUT    : out std_logic;
+      CBM_PULSER_OUT       : out std_logic; -- connect to TDC
+      
+      -- Ctrl port
+      CBM_CTRL_DATA_IN        : in std_logic_vector(15 downto 0);
+      CBM_CTRL_DATA_START_IN  : in std_logic;
+      CBM_CTRL_DATA_END_IN    : in std_logic;
+      CBM_CTRL_DATA_STOP_OUT  : out std_logic;
+      
+      DEBUG_OUT      : out std_logic_vector(31 downto 0)    
+   );
+end entity;
+
+architecture cbmnet_sync_module_arch of cbmnet_sync_module is
+-- DETECT DLMs
+   signal trb_dlm_sense_mask_i : std_logic_vector(15 downto 0);
+   signal cbm_crs_trb_dlm_sense_mask_i : std_logic_vector(15 downto 0);
+   
+   signal cbm_dlm_sensed_i : std_logic;
+   signal trb_crs_cbm_dlm_sensed_i : std_logic;
+
+-- EPOCH
+   signal cbm_crs_trb_epoch_update_scheme_i : std_logic_vector(1 downto 0);
+
+   signal cbm_current_epoch_i : std_logic_vector(31 downto 0);
+   signal cbm_current_epoch_updated_i : std_logic;
+
+   signal trb_next_epoch_i : std_logic_vector(31 downto 0);
+   signal trb_next_epoch_updated_i : std_logic;
+   
+   signal cbm_next_epoch_i : std_logic_vector(31 downto 0);
+   signal cbm_next_epoch_updated_i : std_logic;
+
+   
+   signal cbm_crs_trb_next_epoch_i : std_logic_vector(31 downto 0);
+   signal cbm_crs_trb_next_epoch_updated_i : std_logic;
+   signal trb_crs_cbm_current_epoch_i : std_logic_vector(31 downto 0);
+   signal trb_crs_cbm_current_epoch_updated_i : std_logic;   
+   
+-- PULSER
+   signal trb_pulser_threshold_i : std_logic_vector(31 downto 0);
+   signal cbm_crs_trb_pulser_threshold_i : unsigned(31 downto 0);
+   signal cbm_pulser_i : unsigned(31 downto 0);
+   signal cbm_pulse_i : std_logic;
+   signal trb_crs_cbm_pulse_i : std_logic;
+
+-- TIMESTAMPS
+   signal trb_timestamp_i          : unsigned(31 downto 0);
+   signal trb_timestamp_last_dlm_i : unsigned(31 downto 0);
+   signal trb_timestamp_last_pulse_i : unsigned(31 downto 0);
+   signal trb_reset_counter_i      : unsigned(15 downto 0);
+   
+   signal cbm_timestamp_i          : unsigned(31 downto 0);
+   signal cbm_timestamp_last_dlm_i : unsigned(31 downto 0);
+   signal cbm_timestamp_last_pulse_i : unsigned(31 downto 0);
+   signal cbm_reset_counter_i      : unsigned(15 downto 0);
+   signal cbm_dlm_counter_i        : unsigned(31 downto 0);
+   signal cbm_pulser_counter_i     : unsigned(31 downto 0);
+   signal cbm_epoch_i              : std_logic_vector(31 downto 0);
+   
+   -- same signals as above, but in trbnet clock domain
+   signal trb_crs_cbm_timestamp_i          : unsigned(31 downto 0);
+   signal trb_crs_cbm_timestamp_last_dlm_i : unsigned(31 downto 0);
+   signal trb_crs_cbm_timestamp_last_pulse_i : unsigned(31 downto 0);
+   signal trb_crs_cbm_reset_counter_i      : unsigned(15 downto 0);   
+   signal trb_crs_cbm_dlm_counter_i        : unsigned(31 downto 0);
+   signal trb_crs_cbm_pulser_counter_i     : unsigned(31 downto 0);
+
+   
+-- CBMNET slow control
+   signal cbm_next_epoch_half_buf_i : std_logic_vector(15 downto 0);
+   type CBM_SLOW_CTRL_FSM_T is (WAIT_FOR_START, SHIFT_LOW_WORD);
+   signal cbm_slow_ctrl_fsm_i : CBM_SLOW_CTRL_FSM_T;
+
+-- TrbNet slow control
+   constant trb_sync_lowest_address_c : integer := 3;
+
+   type TRB_SYNC_BUFFER_T is array (trb_sync_lowest_address_c+1 to trb_sync_lowest_address_c+9) of std_logic_vector(31 downto 0);
+   signal trb_sync_buffer_i : TRB_SYNC_BUFFER_T;
+   signal trb_regio_addr_i : integer range 0 to 15;
+   signal trb_epoch_update_scheme_i : std_logic_vector(1 downto 0);
+   
+-- TrbNet read-out   
+   type TRB_RDO_BUFFER_T is array (0 to 10) of std_logic_vector(31 downto 0);
+   signal trb_rdo_buffer_i : TRB_RDO_BUFFER_T;
+   type TRB_RDO_FSM_T is (WAIT_FOR_TRIGGER, WAIT_FOR_VALID, COPY_DATA, FINISH);
+   signal trb_rdo_fsm_i : TRB_RDO_FSM_T;
+   signal trb_rdo_fsm_state_i : std_logic_vector(3 downto 0);
+   signal trb_rdo_counter_i : integer range 0 to 16;
+   
+   
+begin
+-- TRBNet read-out
+   TRBNET_READOUT_PROC: process is
+      variable header_v : std_logic_vector(31 downto 0);
+   begin
+      wait until rising_edge(TRB_CLK_IN);
+      header_v := (others => '0'); -- prevent storage
+      
+      TRB_RDO_WRITE_OUT <= '0';
+      TRB_RDO_STATUSBIT_OUT <= (others => '0');
+      TRB_RDO_FINISHED_OUT <= '0';
+      trb_rdo_counter_i <= 0;
+      
+      if TRB_RESET_IN='1' then
+         trb_rdo_fsm_i <= WAIT_FOR_TRIGGER;
+      else
+         case (trb_rdo_fsm_i) is
+            when WAIT_FOR_TRIGGER =>
+               trb_rdo_fsm_state_i <= x"0";
+               if TRB_TRIGGER_IN = '1' then
+               -- store data
+                  header_v(31 downto 28) := x"1"; -- version
+                  header_v(23 downto  8) := trb_pulser_threshold_i(15 downto 0);
+                  header_v( 7 downto  4) := CBM_PHY_BARREL_SHIFTER_POS_IN;
+                  header_v( 3 downto  0) := trb_crs_cbm_current_epoch_updated_i & "0" & trb_epoch_update_scheme_i;
+                  
+                  trb_rdo_buffer_i( 0) <= header_v;
+                  trb_rdo_buffer_i( 1) <= trb_crs_cbm_current_epoch_i;
+                  trb_rdo_buffer_i( 2) <= trb_crs_cbm_timestamp_i;
+                  trb_rdo_buffer_i( 3) <= trb_crs_cbm_timestamp_last_dlm_i;
+                  trb_rdo_buffer_i( 4) <= trb_crs_cbm_timestamp_last_pulse_i;
+                  trb_rdo_buffer_i( 5) <= trb_timestamp_i;
+                  trb_rdo_buffer_i( 6) <= trb_timestamp_last_dlm_i;
+                  trb_rdo_buffer_i( 7) <= trb_timestamp_last_pulse_i;
+                  trb_rdo_buffer_i( 8) <= trb_crs_cbm_dlm_counter_i;
+                  trb_rdo_buffer_i( 9) <= trb_crs_cbm_pulser_counter_i;
+                  trb_rdo_buffer_i(10) <= STD_LOGIC_VECTOR(trb_reset_counter_i) & STD_LOGIC_VECTOR(trb_crs_cbm_reset_counter_i);
+               
+               -- fsm
+                  trb_rdo_fsm_i <= WAIT_FOR_VALID;
+               elsif TRB_RDO_VALID_IN = '1' then
+                  trb_rdo_fsm_i <= FINISH;
+                  
+               end if;
+               
+            when WAIT_FOR_VALID =>
+               trb_rdo_fsm_state_i <= x"1";
+               if TRB_RDO_VALID_IN = '1' then
+                  trb_rdo_fsm_i <= COPY_DATA;
+               end if;
+            
+            when COPY_DATA =>
+               trb_rdo_fsm_state_i <= x"2";
+               TRB_RDO_DATA_OUT <= trb_rdo_buffer_i(trb_rdo_counter_i);
+               TRB_RDO_WRITE_OUT <= '1';
+
+               if trb_rdo_counter_i = TRB_RDO_DATA_OUT'high then
+                  trb_rdo_fsm_i <= FINISH;
+               end if;
+               trb_rdo_counter_i <= trb_rdo_counter_i + 1;
+               
+            when FINISH =>
+               trb_rdo_fsm_state_i <= x"3";
+               TRB_RDO_FINISHED_OUT <= '1';
+               trb_rdo_fsm_i <= WAIT_FOR_TRIGGER;
+               
+            
+         end case;
+      end if;
+   end process;
+
+-- TRBNet slow control
+   trb_regio_addr_i <= to_integer(UNSIGNED(TRB_REGIO_ADDR_IN(3 downto 0)));
+   
+   TRB_SLOW_CTRL_PROC: process is
+   begin
+      wait until rising_edge(TRB_CLK_IN);
+
+      TRB_REGIO_DATAREADY_OUT <= TRB_REGIO_READ_ENABLE_IN;
+      TRB_REGIO_WRITE_ACK_OUT <= TRB_REGIO_WRITE_ENABLE_IN;
+      TRB_REGIO_UNKNOWN_ADDR_OUT <= '0';
+      TRB_REGIO_DATA_OUT <= (others => '0');
+      
+      if trb_crs_cbm_dlm_sensed_i = '1' then
+         trb_next_epoch_updated_i <= '0';
+      end if;
+      
+      if TRB_RESET_IN = '1' then
+         trb_dlm_sense_mask_i <= x"0000";
+         trb_epoch_update_scheme_i <= "00";
+         trb_pulser_threshold_i <= (others => '0');
+         
+         trb_next_epoch_updated_i <= '0';
+         trb_next_epoch_i <= x"deadc0de";
+         
+      else
+         case (trb_regio_addr_i) is
+            when 0 => 
+               TRB_REGIO_DATA_OUT(31 downto 16) <= trb_dlm_sense_mask_i;
+               TRB_REGIO_DATA_OUT(11 downto  8) <= trb_rdo_fsm_state_i;
+               TRB_REGIO_DATA_OUT(4) <= trb_crs_cbm_current_epoch_updated_i;
+               TRB_REGIO_DATA_OUT( 3 downto  0) <= "00" & trb_epoch_update_scheme_i;
+            
+            when 1 =>
+               TRB_REGIO_DATA_OUT <= trb_pulser_threshold_i;
+               
+            when 2 =>
+               TRB_REGIO_DATA_OUT <= trb_next_epoch_i;
+            
+            when trb_sync_lowest_address_c =>
+               TRB_REGIO_DATA_OUT <= trb_crs_cbm_current_epoch_i;
+               trb_sync_buffer_i(trb_sync_lowest_address_c+1) <= trb_crs_cbm_timestamp_i;
+               trb_sync_buffer_i(trb_sync_lowest_address_c+2) <= trb_crs_cbm_timestamp_last_dlm_i;
+               trb_sync_buffer_i(trb_sync_lowest_address_c+3) <= trb_crs_cbm_timestamp_last_pulse_i;
+               trb_sync_buffer_i(trb_sync_lowest_address_c+4) <= trb_timestamp_i;
+               trb_sync_buffer_i(trb_sync_lowest_address_c+5) <= trb_timestamp_last_dlm_i;
+               trb_sync_buffer_i(trb_sync_lowest_address_c+6) <= trb_timestamp_last_pulse_i;
+               trb_sync_buffer_i(trb_sync_lowest_address_c+7) <= trb_crs_cbm_dlm_counter_i;
+               trb_sync_buffer_i(trb_sync_lowest_address_c+8) <= trb_crs_cbm_pulser_counter_i;
+               trb_sync_buffer_i(trb_sync_lowest_address_c+9) <= STD_LOGIC_VECTOR(trb_reset_counter_i) & STD_LOGIC_VECTOR(trb_crs_cbm_reset_counter_i);               
+            
+            when trb_sync_lowest_address_c + 1 to trb_sync_lowest_address_c + trb_sync_buffer_i'high =>
+               TRB_REGIO_DATA_OUT <= trb_sync_buffer_i(trb_regio_addr_i);
+               
+            when others =>
+               TRB_REGIO_UNKNOWN_ADDR_OUT <= TRB_REGIO_READ_ENABLE_IN or TRB_REGIO_WRITE_ENABLE_IN;
+               
+         end case;
+         
+         if TRB_REGIO_WRITE_ENABLE_IN = '1' then
+            case (trb_regio_addr_i) is
+               when 0 =>
+                  trb_dlm_sense_mask_i      <= TRB_REGIO_DATA_IN(31 downto 16);
+                  trb_epoch_update_scheme_i <= TRB_REGIO_DATA_IN(1 downto 0);
+               
+               when 1 =>
+                  trb_pulser_threshold_i <= TRB_REGIO_DATA_IN;
+                  
+               when 2 =>
+                  trb_next_epoch_i <= TRB_REGIO_DATA_IN;
+                  trb_next_epoch_updated_i <= '1';
+               
+               when others =>
+                  TRB_REGIO_UNKNOWN_ADDR_OUT <= '1';
+            end case;
+         end if;
+      end if;
+   end process;
+
+-- CBMNet slow control
+   CBMNET_SLOW_CTRL_PROC: process is
+   begin
+      wait until rising_edge(CBM_CLK_IN);
+      
+      if CBM_RESET_IN = '1' then
+         CBM_CTRL_DATA_STOP_OUT <= '1';
+         cbm_next_epoch_updated_i <= '0';
+         cbm_slow_ctrl_fsm_i <= WAIT_FOR_START;
+         
+      else
+         CBM_CTRL_DATA_STOP_OUT <= '0';
+         case cbm_slow_ctrl_fsm_i is
+            when WAIT_FOR_START =>
+               if CBM_CTRL_DATA_START_IN = '1' then
+                  cbm_next_epoch_half_buf_i <= CBM_CTRL_DATA_IN;
+                  cbm_slow_ctrl_fsm_i <= SHIFT_LOW_WORD;
+               end if;
+               
+            when SHIFT_LOW_WORD =>
+               cbm_slow_ctrl_fsm_i <= WAIT_FOR_START;
+               if CBM_CTRL_DATA_END_IN = '1' then
+                  cbm_next_epoch_i <= cbm_next_epoch_half_buf_i & CBM_CTRL_DATA_IN;
+                  cbm_next_epoch_updated_i <= '1';
+               end if;
+         end case;
+
+         if cbm_dlm_sensed_i = '1' then
+            cbm_next_epoch_updated_i <= '0';
+         end if;
+      end if;
+   end process;
+
+-- CBMNet DLM selection
+   CBM_DLM_SENSE_PROC: process is
+      variable dlm_v : integer range 0 to 15;
+      variable sensed_v : std_logic;
+   begin
+      wait until rising_edge(CBM_CLK_IN);
+      
+      dlm_v := to_integer(UNSIGNED(CBM_DLM_REC_IN));
+      sensed_v := cbm_crs_trb_dlm_sense_mask_i(dlm_v) and CBM_DLM_REC_VALID_IN;
+      cbm_dlm_sensed_i <= sensed_v;
+      
+      if CBM_RESET_IN='1' then
+         cbm_dlm_counter_i <= 0;
+      elsif sensed_v='1' then
+         cbm_dlm_counter_i <= cbm_dlm_counter_i + 1;
+      end if;
+   end process;
+   
+   CBM_DLM_SENSE_OUT <= cbm_dlm_sensed_i;
+   
+   CBM_EPOCH_PROC: process is
+   begin
+      wait until rising_edge(CBM_CLK_IN);
+      
+      if CBM_RESET_IN = '1' then
+         cbm_current_epoch_updated_i <= '0';
+         cbm_current_epoch_i <= (others => '0');
+         
+      elsif cbm_dlm_sensed_i = '1' then
+         case cbm_crs_trb_epoch_update_scheme_i is
+            when "01" => -- TRB defined
+               cbm_current_epoch_i <= cbm_crs_trb_next_epoch_i;
+               cbm_current_epoch_updated_i <= cbm_crs_trb_next_epoch_updated_i;
+               
+            when "10" => -- CBM defined
+               cbm_current_epoch_i <= cbm_next_epoch_i;
+               cbm_current_epoch_updated_i <= cbm_next_epoch_updated_i;
+               
+            when others =>
+               cbm_current_epoch_i <= STD_LOGIC_VECTOR(UNSIGNED(cbm_current_epoch_i) + TO_UNSIGNED(1,32));
+               cbm_current_epoch_updated_i <= '1';
+         
+         end case;
+      end if;
+   end process;
+         
+-- TIMESTAMPS
+   CBM_CLOCK_PROC: process is
+      variable last_reset_v : std_logic := '1';
+   begin
+      wait until rising_edge(CBM_CLK_IN);
+      if CBM_RESET_IN='1' then
+         cbm_timestamp_i <= (others => '0');
+         if last_reset_v = '0' then
+            cbm_reset_counter_i <= cbm_reset_counter_i + 1;
+         end if;
+      else
+         if cbm_dlm_sensed_i = '1' then
+            cbm_timestamp_last_dlm_i <= cbm_timestamp_i;
+         end if;
+      
+         cbm_timestamp_i <= cbm_timestamp_i + 1;
+      end if;
+      last_reset_v := CBM_RESET_IN;
+   end process;
+   
+   CBM_PULSER_PROC: process is
+   begin
+      wait until rising_edge(CBM_CLK_IN);
+      
+      cbm_crs_trb_pulser_threshold_i <= trb_pulser_threshold_i;
+      cbm_pulse_i <= '0';
+      
+      if CBM_RESET_IN='1' then
+         cbm_pulser_counter_i <= 0;
+      end if;
+      
+      
+      if CBM_RESET_IN='1' or cbm_crs_trb_pulser_threshold_i=x"00000000" then
+         cbm_pulser_i <= 0;
+         
+      elsif cbm_pulser_i = cbm_crs_trb_pulser_threshold_i then
+         cbm_pulser_i <= 0;
+         cbm_pulser_counter_i <= cbm_pulser_counter_i + 1;
+         cbm_timestamp_last_pulse_i <= cbm_timestamp_i;
+         cbm_pulse_i <= '1';
+      
+      elsif cbm_pulser_i > cbm_crs_trb_pulser_threshold_i then
+         cbm_pulser_i <= 0;
+         
+      else
+         cbm_pulser_i <= cbm_pulser_i + 1;
+      
+      end if;
+   end process;
+   CBM_PULSER_OUT <= cbm_pulse_i;
+
+   TRB_CLOCK_PROC: process is
+      variable last_reset_v : std_logic := '1';
+   begin
+      wait until rising_edge(TRB_CLK_IN);
+      if TRB_RESET_IN='1' then
+         trb_timestamp_i <= (others => '0');
+         if last_reset_v = '0' then
+            trb_reset_counter_i <= trb_reset_counter_i + 1;
+         end if;
+      else
+         if trb_crs_cbm_dlm_sensed_i = '1' then
+            trb_timestamp_last_dlm_i <= trb_timestamp_i;
+         end if;
+
+         if trb_crs_cbm_pulse_i = '1' then
+            trb_timestamp_last_pulse_i <= trb_timestamp_i;
+         end if;
+         
+         trb_timestamp_i <= trb_timestamp_i + 1;
+      end if;
+      last_reset_v := TRB_RESET_IN;
+   end process;
+   
+-- Clock Domain Crossing CBM -> TRB
+   THE_PULSE_SYNC: pos_edge_strech_sync port map (
+      IN_CLK_IN => CBM_CLK_IN, OUT_CLK_IN => TRB_CLK_IN,
+      DATA_IN => cbm_pulse_i,
+      DATA_OUT => trb_crs_cbm_pulse_i
+   );
+   
+   THE_DLM_SENSE_SYNC: pos_edge_strech_sync port map (
+      IN_CLK_IN => CBM_CLK_IN, OUT_CLK_IN => TRB_CLK_IN,
+      DATA_IN => cbm_dlm_sensed_i,
+      DATA_OUT => trb_crs_cbm_dlm_sensed_i
+   );
+
+   trb_crs_cbm_timestamp_i             <= cbm_timestamp_i             when rising_edge(TRB_CLK_IN);
+   trb_crs_cbm_timestamp_last_dlm_i    <= cbm_timestamp_last_dlm_i    when rising_edge(TRB_CLK_IN);
+   trb_crs_cbm_reset_counter_i         <= cbm_reset_counter_i         when rising_edge(TRB_CLK_IN);
+   trb_crs_cbm_dlm_counter_i           <= cbm_dlm_counter_i           when rising_edge(TRB_CLK_IN);
+   trb_crs_cbm_pulser_counter_i        <= cbm_pulser_counter_i        when rising_edge(TRB_CLK_IN);
+   trb_crs_cbm_timestamp_last_pulse_i  <= cbm_timestamp_last_pulse_i  when rising_edge(TRB_CLK_IN);
+
+   trb_crs_cbm_current_epoch_i         <= cbm_current_epoch_i         when rising_edge(TRB_CLK_IN);
+   trb_crs_cbm_current_epoch_updated_i <= cbm_current_epoch_updated_i when rising_edge(TRB_CLK_IN);
+
+-- Clock Domain Crossing TRB -> CBM
+   cbm_crs_trb_epoch_update_scheme_i   <= trb_epoch_update_scheme_i   when rising_edge(CBM_CLK_IN);
+   cbm_crs_trb_next_epoch_i            <= trb_next_epoch_i            when rising_edge(CBM_CLK_IN);
+   cbm_crs_trb_next_epoch_updated_i    <= trb_next_epoch_updated_i    when rising_edge(CBM_CLK_IN);
+   cbm_crs_trb_dlm_sense_mask_i        <= trb_dlm_sense_mask_i        when rising_edge(CBM_CLK_IN);
+   
+   
+end architecture;
\ No newline at end of file
diff --git a/cbmnet/code/pos_edge_strech_sync.vhd b/cbmnet/code/pos_edge_strech_sync.vhd
new file mode 100644 (file)
index 0000000..b8f1321
--- /dev/null
@@ -0,0 +1,27 @@
+library ieee;
+   use ieee.std_logic_1164.all;
+   use ieee.numeric_std.all;
+   use work.trb_net_std.all;
+
+entity pos_edge_strech_sync is
+   generic (
+      LENGTH : positive := 2
+   );
+   port (
+      IN_CLK_IN : std_logic;
+      DATA_IN : std_logic;
+      OUT_CLK_IN : std_logic;
+      DATA_OUT : std_logic
+   );
+end entity;
+
+architecture RTL of pos_edge_strech_sync is
+   signal in_buffer_i : std_logic_vector(LENGTH - 1 downto 0);
+   signal in_buffer_aggr_i : std_logic;
+   signal out_buffer_i : std_logic;
+begin
+   in_buffer_i <= in_buffer_i(LENGTH-2 downto 0) & DATA_IN when rising_edge(OUT_CLK_IN);
+   in_buffer_aggr_i <= OR_ALL(in_buffer_i);
+   
+   out_buffer_i <= not out_buffer_i and in_buffer_aggr_i when rising_edge(OUT_CLK_IN);
+end architecture;
\ No newline at end of file