diff --git a/modules/wishbone/wb_crossbar/sdb_rom.vhd b/modules/wishbone/wb_crossbar/sdb_rom.vhd
index 419c17820f727ed47e0ab40399e710ac46685859..cd332bd017d06cf1ea7bd5a51b730e904395e596 100644
--- a/modules/wishbone/wb_crossbar/sdb_rom.vhd
+++ b/modules/wishbone/wb_crossbar/sdb_rom.vhd
@@ -5,7 +5,9 @@ use work.wishbone_pkg.all;
 
 entity sdb_rom is
   generic(
+    g_use_info    : boolean := false;
     g_layout      : t_sdb_record_array;
+    g_info        : t_sdb_record_array;
     g_bus_end     : unsigned(63 downto 0));
   port(
     clk_sys_i     : in  std_logic;
@@ -15,16 +17,31 @@ end sdb_rom;
 
 architecture rtl of sdb_rom is
   alias c_layout : t_sdb_record_array(g_layout'length downto 1) is g_layout;
-  
-  -- The ROM must describe all slaves and the crossbar itself
-  constant c_used_entries : natural := c_layout'length + 1;
-  constant c_rom_entries  : natural := 2**f_ceil_log2(c_used_entries); -- next power of 2
-  constant c_sdb_words    : natural := c_sdb_device_length / c_wishbone_data_width;
-  constant c_rom_words    : natural := c_rom_entries * c_sdb_words;
-  constant c_rom_depth    : natural := f_ceil_log2(c_rom_words);
-  constant c_rom_lowbits  : natural := f_ceil_log2(c_wishbone_data_width / 8);
+  alias c_info   : t_sdb_record_array(g_info'length downto 1) is g_info;
+
+  function f_info_entries(b : boolean; length : natural) return natural is
+    variable ret : natural;
+  begin
+    if b = true then
+      ret := length;
+    else
+      ret := 0;
+    end if;
+    return ret;
+  end f_info_entries;
+
+  -- The ROM must describe all slaves, the crossbar itself and the optional information records
+  constant c_device_entries : natural := c_layout'length;
+  constant c_info_entries   : natural := f_info_entries(g_use_info, g_info'length);
+  constant c_used_entries   : natural := c_device_entries + c_info_entries + 1;
+  constant c_rom_entries    : natural := 2**f_ceil_log2(c_used_entries); -- next power of 2
+  constant c_sdb_words      : natural := c_sdb_device_length / c_wishbone_data_width;
+  constant c_rom_words      : natural := c_rom_entries * c_sdb_words;
+  constant c_rom_depth      : natural := f_ceil_log2(c_rom_words);
+  constant c_rom_lowbits    : natural := f_ceil_log2(c_wishbone_data_width / 8);
   
   type t_rom is array(c_rom_words-1 downto 0) of t_wishbone_data;
+
   function f_build_rom
     return t_rom 
   is
@@ -52,7 +69,7 @@ architecture rtl of sdb_rom is
         sdb_device((i+1)*c_wishbone_data_width-1 downto i*c_wishbone_data_width);
     end loop;
     
-    for slave in 1 to c_used_entries-1 loop
+    for slave in 1 to c_device_entries loop
       sdb_device(511 downto 0) := c_layout(slave);
       
       for i in 0 to c_sdb_words-1 loop
@@ -60,6 +77,25 @@ architecture rtl of sdb_rom is
           sdb_device((i+1)*c_wishbone_data_width-1 downto i*c_wishbone_data_width);
       end loop;
     end loop;
+
+    assert False report "SDB device records: " & Integer'image(c_device_entries)
+    severity Note;
+
+    assert False report "SDB meta-information records: " & Integer'image(c_info_entries)
+    severity Note;
+
+    -- Add optional meta-information entries, if any
+    if c_info_entries /= 0 then
+      for info in 1 to c_info_entries loop
+        sdb_device(511 downto 0) := c_info(info);
+
+        for i in 0 to c_sdb_words-1 loop
+          res((info+c_device_entries+1)*c_sdb_words-1-i) :=
+            sdb_device((i+1)*c_wishbone_data_width-1 downto i*c_wishbone_data_width);
+        end loop;
+      end loop;
+    end if;
+
     return res;
   end f_build_rom;
    
diff --git a/modules/wishbone/wb_crossbar/xwb_sdb_crossbar.vhd b/modules/wishbone/wb_crossbar/xwb_sdb_crossbar.vhd
index 4b3e512d9c0c1df48f9076365a5f6cd419f8b61e..2b140c2124f9373a688b6aaa8d1175ee1cf8b421 100644
--- a/modules/wishbone/wb_crossbar/xwb_sdb_crossbar.vhd
+++ b/modules/wishbone/wb_crossbar/xwb_sdb_crossbar.vhd
@@ -9,7 +9,9 @@ entity xwb_sdb_crossbar is
     g_num_slaves  : natural := 1;
     g_registered  : boolean := false;
     g_wraparound  : boolean := true;
+    g_use_info    : boolean := false;
     g_layout      : t_sdb_record_array;
+    g_info        : t_sdb_record_array := (0 => (others => '0'));
     g_sdb_addr    : t_wishbone_address);
   port(
     clk_sys_i     : in  std_logic;
@@ -36,12 +38,25 @@ architecture rtl of xwb_sdb_crossbar is
     return s(1 to cut);
   end f_trim;
 
+  function f_info_entries(b : boolean; length : natural) return natural is
+    variable ret : natural;
+  begin
+    if b = true then
+      ret := length;
+    else
+      ret := 0;
+    end if;
+    return ret;
+  end f_info_entries;
+
   -- Step 1. Place the SDB ROM on the bus
   -- How much space does the ROM need?
-  constant c_used_entries : natural := c_layout'length + 1;
-  constant c_rom_entries  : natural := 2**f_ceil_log2(c_used_entries); -- next power of 2
-  constant c_sdb_bytes    : natural := c_sdb_device_length / 8;
-  constant c_rom_bytes    : natural := c_rom_entries * c_sdb_bytes;
+  constant c_device_entries : natural := c_layout'length;
+  constant c_info_entries   : natural := f_info_entries(g_use_info, g_info'length);
+  constant c_used_entries   : natural := c_device_entries + c_info_entries + 1;
+  constant c_rom_entries    : natural := 2**f_ceil_log2(c_used_entries); -- next power of 2
+  constant c_sdb_bytes      : natural := c_sdb_device_length / 8;
+  constant c_rom_bytes      : natural := c_rom_entries * c_sdb_bytes;
   
   -- Step 2. Find the size of the bus
   function f_bus_end return unsigned is
@@ -155,8 +170,10 @@ begin
   
   rom : sdb_rom
     generic map(
-      g_layout  => c_layout,
-      g_bus_end => c_bus_end)
+      g_use_info => g_use_info,
+      g_layout   => c_layout,
+      g_info     => g_info,
+      g_bus_end  => c_bus_end)
     port map(
       clk_sys_i => clk_sys_i,
       slave_i   => master_o_1(g_num_slaves),
diff --git a/modules/wishbone/wishbone_pkg.vhd b/modules/wishbone/wishbone_pkg.vhd
index ce82e7bd5f1c323158c1470aee179163e46f5de1..01d408f5ebb3b1a2db53a2374831d9a8f66f089d 100644
--- a/modules/wishbone/wishbone_pkg.vhd
+++ b/modules/wishbone/wishbone_pkg.vhd
@@ -76,6 +76,10 @@ package wishbone_pkg is
   function f_ceil_log2(x   : natural) return natural;
   function f_bits2string(s : std_logic_vector) return string;
 
+  function f_string2bits(s : string) return std_logic_vector;
+  function f_string2svl (s : string) return std_logic_vector;
+  function f_slv2string (slv : std_logic_vector) return string;
+
 ------------------------------------------------------------------------------
 -- SDB declaration
 ------------------------------------------------------------------------------
@@ -114,12 +118,35 @@ package wishbone_pkg is
     sdb_component : t_sdb_component;
   end record t_sdb_bridge;
 
+  type t_sdb_integration is record
+    product : t_sdb_product;
+  end record t_sdb_integration;
+
+  type t_sdb_repo_url is record
+    repo_url : string(1 to 63);
+  end record t_sdb_repo_url;
+
+  type t_sdb_synthesis is record
+    syn_module_name  : string(1 to 16);
+    syn_commit_id    : string(1 to 32);
+    syn_tool_name    : string(1 to 8);
+    syn_tool_version : std_logic_vector(31 downto 0);
+    syn_date         : std_logic_vector(31 downto 0);
+    syn_username     : string(1 to 15);
+  end record t_sdb_synthesis;
+
   -- Used to configure a device at a certain address
   function f_sdb_embed_device(device : t_sdb_device; address : t_wishbone_address) return t_sdb_record;
   function f_sdb_embed_bridge(bridge : t_sdb_bridge; address : t_wishbone_address) return t_sdb_record;
+  function f_sdb_embed_integration(integr : t_sdb_integration) return t_sdb_record;
+  function f_sdb_embed_repo_url(url : t_sdb_repo_url) return t_sdb_record;
+  function f_sdb_embed_synthesis(syn : t_sdb_synthesis) return t_sdb_record;
 
   function f_sdb_extract_device(sdb_record : t_sdb_record) return t_sdb_device;
   function f_sdb_extract_bridge(sdb_record : t_sdb_record) return t_sdb_bridge;
+  function f_sdb_extract_integration(sdb_record : t_sdb_record) return t_sdb_integration;
+  function f_sdb_extract_repo_url(sdb_record : t_sdb_record) return t_sdb_repo_url;
+  function f_sdb_extract_synthesis(sdb_record : t_sdb_record) return t_sdb_synthesis;
 
   -- For internal use by the crossbar
   function f_sdb_embed_product(product         : t_sdb_product) return std_logic_vector;  -- (319 downto 8)
@@ -266,7 +293,9 @@ package wishbone_pkg is
       g_num_slaves  : integer;
       g_registered  : boolean := false;
       g_wraparound  : boolean := true;
+      g_use_info    : boolean := false;
       g_layout      : t_sdb_record_array;
+      g_info        : t_sdb_record_array := (0 => (others => '0'));
       g_sdb_addr    : t_wishbone_address);
     port (
       clk_sys_i : in  std_logic;
@@ -281,6 +310,10 @@ package wishbone_pkg is
     generic(
       g_layout  : t_sdb_record_array;
       g_bus_end : unsigned(63 downto 0));
+      g_use_info    : boolean := false;
+      g_layout      : t_sdb_record_array;
+      g_info        : t_sdb_record_array;
+      g_bus_end     : unsigned(63 downto 0));
     port(
       clk_sys_i : in  std_logic;
       slave_i   : in  t_wishbone_slave_in;
@@ -899,6 +932,89 @@ package body wishbone_pkg is
     return result;
   end;
 
+  function f_sdb_embed_integration(integr : t_sdb_integration)
+    return t_sdb_record
+  is
+    variable result : t_sdb_record;
+  begin
+    result(511 downto 320) := (others => '0');
+    result(319 downto 8)   := f_sdb_embed_product(integr.product);
+    result(7 downto 0)     := x"80"; -- integration record
+    return result;
+  end f_sdb_embed_integration;
+
+  function f_sdb_extract_integration(sdb_record : t_sdb_record)
+    return t_sdb_integration
+  is
+    variable result : t_sdb_integration;
+  begin
+    result.product := f_sdb_extract_product(sdb_record(319 downto 8));
+
+    assert sdb_record(7 downto 0) = x"80"
+    report "Cannot extract t_sdb_integration from record of type " & Integer'image(to_integer(unsigned(sdb_record(7 downto 0)))) & "."
+    severity Failure;
+
+    return result;
+  end f_sdb_extract_integration;
+
+  function f_sdb_embed_repo_url(url : t_sdb_repo_url)
+    return t_sdb_record
+  is
+    variable result : t_sdb_record;
+  begin
+    result(511 downto 8) := f_string2svl(url.repo_url);
+    result(  7 downto 0) := x"81"; -- repo_url record
+    return result;
+  end;
+
+  function f_sdb_extract_repo_url(sdb_record : t_sdb_record)
+    return t_sdb_repo_url
+  is
+    variable result : t_sdb_repo_url;
+  begin
+    result.repo_url     := f_slv2string(sdb_record(511 downto 8));
+
+    assert sdb_record(7 downto 0) = x"81"
+    report "Cannot extract t_sdb_repo_url from record of type " & Integer'image(to_integer(unsigned(sdb_record(7 downto 0)))) & "."
+    severity Failure;
+
+    return result;
+  end;
+
+  function f_sdb_embed_synthesis(syn : t_sdb_synthesis)
+    return t_sdb_record
+  is
+    variable result : t_sdb_record;
+  begin
+    result(511 downto 384) := f_string2svl(syn.syn_module_name);
+    result(383 downto 256) := f_string2bits(syn.syn_commit_id);
+    result(255 downto 192) := f_string2svl(syn.syn_tool_name);
+    result(191 downto 160) := syn.syn_tool_version;
+    result(159 downto 128) := syn.syn_date;
+    result(127 downto   8) := f_string2svl(syn.syn_username);
+    result(  7 downto   0) := x"82"; -- synthesis record
+    return result;
+  end;
+
+  function f_sdb_extract_synthesis(sdb_record : t_sdb_record)
+    return t_sdb_synthesis
+  is
+    variable result : t_sdb_synthesis;
+  begin
+    result.syn_module_name  := f_slv2string(sdb_record(511 downto 384));
+    result.syn_commit_id    := f_bits2string(sdb_record(383 downto 256));
+    result.syn_tool_name    := f_slv2string(sdb_record(255 downto 192));
+    result.syn_tool_version := sdb_record(191 downto 160);
+    result.syn_date         := sdb_record(159 downto 128);
+    result.syn_username     := f_slv2string(sdb_record(127 downto   8));
+
+    assert sdb_record(7 downto 0) = x"82"
+    report "Cannot extract t_sdb_repo_url from record of type " & Integer'image(to_integer(unsigned(sdb_record(7 downto 0)))) & "."
+    severity Failure;
+
+    return result;
+  end;
+
   function f_sdb_embed_bridge(bridge : t_sdb_bridge; address : t_wishbone_address)
     return t_sdb_record
   is
@@ -1056,5 +1172,62 @@ package body wishbone_pkg is
 
     return "0x" & result(cut downto 1);
   end f_bits2string;
-  
+
+  -- Converts string (hex number, without leading 0x) to std_logic_vector
+  function f_string2bits(s : string) return std_logic_vector is
+    variable slv : std_logic_vector(s'length*4-1 downto 0);
+    variable nibble : std_logic_vector(3 downto 0);
+  begin
+    for i in 0 to s'length-1 loop
+      case s(i+1) is
+        when '0' => nibble := X"0";
+        when '1' => nibble := X"1";
+        when '2' => nibble := X"2";
+        when '3' => nibble := X"3";
+        when '4' => nibble := X"4";
+        when '5' => nibble := X"5";
+        when '6' => nibble := X"6";
+        when '7' => nibble := X"7";
+        when '8' => nibble := X"8";
+        when '9' => nibble := X"9";
+        when 'a' => nibble := X"A";
+        when 'A' => nibble := X"A";
+        when 'b' => nibble := X"B";
+        when 'B' => nibble := X"B";
+        when 'c' => nibble := X"C";
+        when 'C' => nibble := X"C";
+        when 'd' => nibble := X"D";
+        when 'D' => nibble := X"D";
+        when 'e' => nibble := X"E";
+        when 'E' => nibble := X"E";
+        when 'f' => nibble := X"F";
+        when 'F' => nibble := X"F";
+        when others => nibble := "XXXX";
+      end case;
+      slv(((i+1)*4)-1 downto i*4) := nibble;
+    end loop;
+    return slv;
+  end f_string2bits;
+
+  -- Converts string to ascii (std_logic_vector)
+  function f_string2svl (s : string) return std_logic_vector is
+    variable slv : std_logic_vector((s'length * 8) - 1 downto 0);
+  begin
+    for i in 0 to s'length-1 loop
+      slv(slv'high-i*8 downto (slv'high-7)-i*8) :=
+        std_logic_vector(to_unsigned(character'pos(s(i+1)), 8));
+    end loop;
+    return slv;
+  end f_string2svl;
+
+  -- Converts ascii (std_logic_vector) to string
+  function f_slv2string (slv : std_logic_vector) return string is
+    variable s : string(1 to slv'length/8);
+  begin
+    for i in 0 to (slv'length/8)-1 loop
+      s(i+1) := character'val(to_integer(unsigned(slv(slv'high-i*8 downto (slv'high-7)-i*8))));
+    end loop;
+    return s;
+  end f_slv2string;
+
 end wishbone_pkg;