diff --git a/modules/wishbone/wb_crossbar/sdwb_rom.vhd b/modules/wishbone/wb_crossbar/sdwb_rom.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..248894e634291ec115f6f166a344febea349e745
--- /dev/null
+++ b/modules/wishbone/wb_crossbar/sdwb_rom.vhd
@@ -0,0 +1,111 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+use work.wishbone_pkg.all;
+
+entity sdwb_rom is
+  generic(
+    g_layout      : t_sdwb_device_array;
+    g_bus_end     : unsigned(63 downto 0));
+  port(
+    clk_sys_i     : in  std_logic;
+    slave_i       : in  t_wishbone_slave_in;
+    slave_o       : out t_wishbone_slave_out);
+end sdwb_rom;
+
+architecture rtl of sdwb_rom is
+  function f_ceil_log2(x : natural) return natural is
+  begin
+    if x <= 1
+    then return 0;
+    else return f_ceil_log2((x+1)/2) +1;
+    end if;
+  end f_ceil_log2;
+
+  constant c_version : natural := 1;
+  constant c_date    : natural := 16#20120305#;
+  constant c_rom_description : string(1 to 16) := "WB4-Crossbar-GSI";
+
+  -- The ROM must describe all slaves and the crossbar itself
+  alias c_layout : t_sdwb_device_array(1 to g_layout'length) is g_layout;
+  constant c_used_entries : natural := g_layout'length + 1;
+  constant c_rom_entries  : natural := 2**f_ceil_log2(c_used_entries); -- next power of 2
+  constant c_sdwb_words   : natural := c_sdwb_device_length / c_wishbone_data_width;
+  constant c_rom_words    : natural := c_rom_entries * c_sdwb_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
+    variable res : t_rom := (others => (others => '0'));
+    variable sdwb_device : std_logic_vector(0 to c_sdwb_device_length-1) := (others => '0');
+  begin
+    sdwb_device(  0 to 127) := not x"40f6e98c29eae24c7e6461ae8d2af247";          -- magic
+    sdwb_device(128 to 191) := std_logic_vector(g_bus_end);                      -- bus_end
+    sdwb_device(192 to 207) := std_logic_vector(to_unsigned(c_used_entries, 8)); -- sdwb_records
+    sdwb_device(208 to 215) := x"01";                                            -- sdwb_ver_major
+    sdwb_device(216 to 223) := x"00";                                            -- sdwb_ver_minor
+    sdwb_device(224 to 255) := x"00000651";                                      -- bus_vendor (GSI)
+    sdwb_device(256 to 287) := x"00000004";                                      -- bus_device
+    sdwb_device(288 to 319) := std_logic_vector(to_unsigned(c_version, 32));     -- bus_version
+    sdwb_device(320 to 351) := std_logic_vector(to_unsigned(c_date,    32));     -- bus_date
+    sdwb_device(352 to 383) := x"00000000";                                      -- bus_flags
+    for i in 1 to 16 loop
+      sdwb_device(376+i*8 to 383+i*8) := 
+        std_logic_vector(to_unsigned(character'pos(c_rom_description(i)), 8));
+    end loop;
+    
+    for i in 0 to c_sdwb_words-1 loop
+      res(i) := 
+        sdwb_device(i*c_wishbone_data_width to (i+1)*c_wishbone_data_width-1);
+    end loop;
+    
+    for slave in 1 to c_used_entries-1 loop
+      sdwb_device(  0 to  63) := std_logic_vector(c_layout(slave).wbd_begin);
+      sdwb_device( 64 to 127) := std_logic_vector(c_layout(slave).wbd_end);
+      sdwb_device(128 to 191) := std_logic_vector(c_layout(slave).sdwb_child);
+      sdwb_device(192 to 199) := c_layout(slave).wbd_flags;
+      sdwb_device(200 to 207) := c_layout(slave).wbd_width;
+      sdwb_device(208 to 215) := std_logic_vector(c_layout(slave).abi_ver_major);
+      sdwb_device(216 to 223) := std_logic_vector(c_layout(slave).abi_ver_minor);
+      sdwb_device(224 to 255) := c_layout(slave).abi_class;
+      sdwb_device(256 to 287) := c_layout(slave).dev_vendor;
+      sdwb_device(288 to 319) := c_layout(slave).dev_device;
+      sdwb_device(320 to 351) := c_layout(slave).dev_version;
+      sdwb_device(352 to 383) := c_layout(slave).dev_date;
+      for i in 1 to 16 loop
+        -- string to ascii
+        sdwb_device(376+i*8 to 383+i*8) := 
+          std_logic_vector(to_unsigned(character'pos(g_layout(slave).description(i)), 8));
+      end loop;
+      
+      for i in 0 to c_sdwb_words-1 loop
+        res(slave*c_sdwb_words + i) := 
+          sdwb_device(i*c_wishbone_data_width to (i+1)*c_wishbone_data_width-1);
+      end loop;
+    end loop;
+    return res;
+  end f_build_rom;
+   
+  signal rom : t_rom := f_build_rom;
+  signal adr_reg : unsigned(c_rom_depth-1 downto 0);
+
+begin
+  -- Simple ROM; ignore we/sel/dat
+  slave_o.err   <= '0';
+  slave_o.rty   <= '0';
+  slave_o.stall <= '0';
+  slave_o.int   <= '0'; -- Tom sucks! This should not be here.
+
+  slave_o.dat <= rom(to_integer(adr_reg));
+  
+  slave_clk : process(clk_sys_i)
+  begin
+    if (rising_edge(clk_sys_i)) then
+      adr_reg <= unsigned(slave_i.adr(c_rom_depth+c_rom_lowbits-1 downto c_rom_lowbits));
+      slave_o.ack <= slave_i.cyc and slave_i.stb;
+    end if;
+  end process;
+  
+end rtl;
diff --git a/modules/wishbone/wb_crossbar/xwb_crossbar.vhd b/modules/wishbone/wb_crossbar/xwb_crossbar.vhd
index 17dbe3427472eb8dbe29dc3f3804740c0490c4b5..14ed1ddf9740786ed4a7f42cbd96eaa90f04e35e 100644
--- a/modules/wishbone/wb_crossbar/xwb_crossbar.vhd
+++ b/modules/wishbone/wb_crossbar/xwb_crossbar.vhd
@@ -18,9 +18,8 @@
 -- All participants must support the same data bus width. 
 -- 
 -- If a master raises STB_O with an address not mapped by the crossbar,
--- ERR_I will be raised. If the crossbar has overlapping address ranges,
--- the lowest numbered slave is selected. If two masters address the same
--- slave simultaneously, the lowest numbered master is granted access.
+-- ERR_I will be raised. If two masters address the same slave
+-- simultaneously, the lowest numbered master is granted access.
 -- 
 -- The implementation of this crossbar locks a master to a slave so long as
 -- CYC_O is held high. 
@@ -40,6 +39,7 @@
 -------------------------------------------------------------------------------
 -- Revisions  :
 -- Date        Version  Author          Description
+-- 2012-03-05  3.0      wterpstra       made address generic and check overlap
 -- 2011-11-04  2.0      wterpstra       timing improvements
 -- 2011-06-08  1.0      wterpstra       import from SVN
 -------------------------------------------------------------------------------
@@ -54,8 +54,10 @@ entity xwb_crossbar is
   generic(
     g_num_masters : integer := 2;
     g_num_slaves  : integer := 1;
-    g_registered  : boolean := false
-    );
+    g_registered  : boolean := false;
+    -- Address of the slaves connected
+    g_address     : t_wishbone_address_array;
+    g_mask        : t_wishbone_address_array);
   port(
     clk_sys_i     : in  std_logic;
     rst_n_i       : in  std_logic;
@@ -64,14 +66,13 @@ entity xwb_crossbar is
     slave_o       : out t_wishbone_slave_out_array(g_num_masters-1 downto 0);
     -- Slave connections (INTERCON is a master)
     master_i      : in  t_wishbone_master_in_array(g_num_slaves-1 downto 0);
-    master_o      : out t_wishbone_master_out_array(g_num_slaves-1 downto 0);
-    -- Address of the slaves connected
-    cfg_address_i : in  t_wishbone_address_array(g_num_slaves-1 downto 0);
-    cfg_mask_i    : in  t_wishbone_address_array(g_num_slaves-1 downto 0)
-    );
+    master_o      : out t_wishbone_master_out_array(g_num_slaves-1 downto 0));
 end xwb_crossbar;
 
 architecture rtl of xwb_crossbar is
+  alias c_address : t_wishbone_address_array(g_num_slaves-1 downto 0) is g_address;
+  alias c_mask    : t_wishbone_address_array(g_num_slaves-1 downto 0) is g_mask;
+
   -- Crossbar connection matrix
   type matrix is array (g_num_masters-1 downto 0, g_num_slaves downto 0) of std_logic;
   
@@ -144,8 +145,8 @@ architecture rtl of xwb_crossbar is
     return output;
   end ks_OR;
   
-  -- Impure because it accesses cfg_{address_i, mask_i}
-  impure function matrix_logic(
+  -- Impure because it accesses c_{address, mask}
+  function matrix_logic(
     matrix_old : matrix;
     slave_i    : t_wishbone_slave_in_array(g_num_masters-1 downto 0))
     return matrix
@@ -182,7 +183,7 @@ architecture rtl of xwb_crossbar is
     -- Decode the request address to see if master wants access
     for master in g_num_masters-1 downto 0 loop
       for slave in g_num_slaves-1 downto 0 loop
-        tmp := not vector_OR((slave_i(master).ADR and cfg_mask_i(slave)) xor cfg_address_i(slave));
+        tmp := not vector_OR((slave_i(master).ADR and c_mask(slave)) xor c_address(slave));
         tmp_column(slave) := tmp;
         request(master, slave) := slave_i(master).CYC and slave_i(master).STB and tmp;
       end loop;
@@ -362,4 +363,6 @@ begin
   master_matrix : for master in g_num_masters-1 downto 0 generate
     slave_o(master) <= master_logic(master, granted, master_ie);
   end generate;
+  
+  -- !!! check for overlap
 end rtl;
diff --git a/modules/wishbone/wb_crossbar/xwb_sdwb_crossbar.vhd b/modules/wishbone/wb_crossbar/xwb_sdwb_crossbar.vhd
index 28a68345dcb68332cbcd58f7c8a0a9e0a95e1088..52bc97aaf4e5a7c5080282717707c8db5d47e389 100644
--- a/modules/wishbone/wb_crossbar/xwb_sdwb_crossbar.vhd
+++ b/modules/wishbone/wb_crossbar/xwb_sdwb_crossbar.vhd
@@ -8,8 +8,8 @@ entity xwb_sdwb_crossbar is
     g_num_masters : natural := 1;
     g_num_slaves  : natural := 1;
     g_registered  : boolean := false;
-    g_address     : t_wishbone_address_array;
-    g_mask        : t_wishbone_address_array;
+    g_wraparound  : boolean := true;
+    g_layout      : t_sdwb_device_array;
     g_sdwb_addr   : t_wishbone_address);
   port(
     clk_sys_i     : in  std_logic;
@@ -23,81 +23,118 @@ entity xwb_sdwb_crossbar is
 end xwb_sdwb_crossbar;
 
 architecture rtl of xwb_sdwb_crossbar is
-  function ceil_log2(x : natural) return natural is
+  -- Step 1. Find the size of the bus address lines
+  type bus_size is record
+    bus_end  : unsigned(63 downto 0);
+    bus_bits : natural;
+  end record bus_size;
+  
+  function f_bus_size return bus_size is
+    variable result : bus_size;
+  begin
+    if not g_wraparound then
+      result.bus_bits := c_wishbone_address_width;
+      result.bus_end := (others => '0');
+      for i in 0 to c_wishbone_address_width-1 loop
+        result.bus_end(i) := '1';
+      end loop;
+    else
+      result.bus_end := (others => '0');
+      for i in g_layout'range loop
+        if g_layout(i).wbd_end > result.bus_end then
+          result.bus_end := g_layout(i).wbd_end;
+        end if;
+      end loop;
+      -- round result up to a power of two -1
+      result.bus_bits := 0;
+      for i in 0 to 63 loop
+        if result.bus_end(i) = '1' then
+          result.bus_bits := i + 1;
+        end if;
+      end loop;
+      for i in 62 downto 0 loop
+        result.bus_end(i) := result.bus_end(i) or result.bus_end(i+1);
+      end loop;
+    end if;
+    return result;
+  end f_bus_size;
+  
+  constant c_bus_size : bus_size := f_bus_size;
+  constant c_bus_bits : natural  := c_bus_size.bus_bits;
+  constant c_bus_end  : unsigned(63 downto 0) := c_bus_size.bus_end;
+  
+  function f_addresses return t_wishbone_address_array is
+    variable result : t_wishbone_address_array(g_layout'range);
+  begin
+    for i in g_layout'range loop
+      result(i) := std_logic_vector(g_layout(i).wbd_begin(c_wishbone_address_width-1 downto 0));
+      -- !!! report if address is too big
+      -- !!! report if end < begin
+    end loop;
+    return result;
+  end f_addresses;
+  
+  function f_masks return t_wishbone_address_array is
+    variable result : t_wishbone_address_array(g_layout'range);
+    variable size : unsigned(63 downto 0);
+  begin
+    for i in g_layout'range loop
+      size := (g_layout(i).wbd_end - g_layout(i).wbd_begin);
+      -- !!! report if size not a power of 2
+      -- !!! report if address is misaligned
+      result(i) := std_logic_vector(c_bus_bits - size);
+    end loop;
+    return result;
+  end f_masks;
+  
+  function f_ceil_log2(x : natural) return natural is
   begin
     if x <= 1
     then return 0;
-    else return ceil_log2((x+1)/2) +1;
+    else return f_ceil_log2((x+1)/2) +1;
     end if;
-  end ceil_log2;
+  end f_ceil_log2;
   
-  -- Our next crossbar will have one extra slave
-  -- The ROM must describe all slaves and the crossbar itself
-  constant c_rom_entries  : natural := 2**ceil_log2(g_num_slaves + 2);
-  constant c_sdwb_words   : natural := c_sdwb_device_length / c_wishbone_data_width;
-  constant c_rom_words    : natural := c_rom_entries * c_sdwb_words;
-  constant c_rom_depth    : natural := ceil_log2(c_rom_words);
-  constant c_rom_lowbits  : natural := ceil_log2(c_wishbone_data_width / 8);
-  constant c_rom_mask : t_wishbone_address := 
-    not std_logic_vector(to_unsigned((c_rom_words*c_wishbone_data_width/8) - 1, 
-                                     c_wishbone_address_width));
+  -- How much space does the ROM need?
+  constant c_used_entries : natural := g_layout'length + 1;
+  constant c_rom_entries  : natural := 2**f_ceil_log2(c_used_entries); -- next power of 2
+  constant c_sdwb_bytes   : natural := c_sdwb_device_length / 8;
+  constant c_rom_bytes    : natural := c_rom_entries * c_sdwb_bytes;
+  constant c_rom_mask     : unsigned(63 downto 0) := c_bus_bits - to_unsigned(c_rom_bytes-1, 64);
+  constant c_sdwb_mask    : t_wishbone_address := std_logic_vector(c_rom_mask(c_wishbone_address_width-1 downto 0));
   
   constant c_address : t_wishbone_address_array(g_num_slaves downto 0) :=
-     g_sdwb_addr & g_address(g_num_slaves-1 downto 0);
+     g_sdwb_addr & f_addresses;
   constant c_mask : t_wishbone_address_array(g_num_slaves downto 0) :=
-     c_rom_mask & g_mask(g_num_slaves-1 downto 0);
+     c_sdwb_mask & f_masks;
   
-  type t_rom is array(c_rom_words-1 downto 0) of t_wishbone_data;
-  function build_rom
-    return t_rom is
-    variable res : t_rom := (others => (others => '0'));
-    variable sdwb_device : std_logic_vector(c_sdwb_device_length-1 downto 0) := (others => '0');
-  begin
-    for slave in 1 to g_num_slaves loop
-      res(slave*c_sdwb_words+0) := c_address(slave-1);
-      res(slave*c_sdwb_words+1) := c_mask(slave-1);
-    end loop;
-    return res;
-  end build_rom;
-   
-  signal rom : t_rom := build_rom;
-  signal rom_i : t_wishbone_slave_in;
-  signal rom_o : t_wishbone_slave_out;
-  signal rom_reg : unsigned(c_rom_depth-1 downto 0);
-
   signal master_i_1 :  t_wishbone_master_in_array(g_num_slaves downto 0);
   signal master_o_1 : t_wishbone_master_out_array(g_num_slaves downto 0);
 begin
-  master_i_1 <= rom_o & master_i;
+  master_i_1(g_num_slaves-1 downto 0) <=  master_i;
   master_o <= master_o_1(g_num_slaves-1 downto 0);
-  rom_i <= master_o_1(g_num_slaves);
   
-  -- Simple ROM; ignore we/sel/dat
-  rom_o.err <= '0';
-  rom_o.rty <= '0';
-  rom_o.stall <= '0';
-  rom_o.int <= '0'; -- Tom sucks! This should not be here.
-  rom_o.dat <= rom(to_integer(rom_reg));
-  rom_clk : process(clk_sys_i)
-  begin
-    if (rising_edge(clk_sys_i)) then
-      rom_reg <= unsigned(rom_i.adr(c_rom_depth+c_rom_lowbits-1 downto c_rom_lowbits));
-      rom_o.ack <= rom_i.cyc and rom_i.stb;
-    end if;
-  end process;
+  rom : sdwb_rom
+    generic map(
+      g_layout  => g_layout,
+      g_bus_end => c_bus_end)
+    port map(
+      clk_sys_i => clk_sys_i,
+      slave_i   => master_o_1(g_num_slaves),
+      slave_o   => master_i_1(g_num_slaves));
   
   crossbar : xwb_crossbar
     generic map(
       g_num_masters => g_num_masters,
       g_num_slaves  => g_num_slaves + 1,
-      g_registered  => g_registered)
+      g_registered  => g_registered,
+      g_address     => c_address,
+      g_mask        => c_mask)
     port map(
       clk_sys_i     => clk_sys_i,
       rst_n_i       => rst_n_i,
       slave_i       => slave_i, 
       slave_o       => slave_o, 
       master_i      => master_i_1, 
-      master_o      => master_o_1, 
-      cfg_address_i => c_address,
-      cfg_mask_i    => c_mask);
+      master_o      => master_o_1);
 end rtl;
diff --git a/modules/wishbone/wishbone_pkg.vhd b/modules/wishbone/wishbone_pkg.vhd
index a1f56a2a1403f0bf977c206387a0afc9799c2747..04811c54fefb532990e111ef6fb8f35bf4a7efb6 100644
--- a/modules/wishbone/wishbone_pkg.vhd
+++ b/modules/wishbone/wishbone_pkg.vhd
@@ -73,21 +73,21 @@ package wishbone_pkg is
 ------------------------------------------------------------------------------
   constant c_sdwb_device_length : natural := 512; -- bits
   type t_sdwb_device is record
-    vendor        : std_logic_vector(63 downto 0);
-    device        : std_logic_vector(31 downto 0);
-    wbd_width     : std_logic_vector(7 downto 0);
-    wbd_reserved  : std_logic_vector(7 downto 0);
-    wbd_ver_major : std_logic_vector(7 downto 0);
-    wbd_ver_minor : std_logic_vector(7 downto 0);
-    hdl_base      : std_logic_vector(63 downto 0);
-    hdl_size      : std_logic_vector(63 downto 0);
-    wbd_flags     : std_logic_vector(31 downto 0);
-    hdl_class     : std_logic_vector(31 downto 0);
-    hdl_version   : std_logic_vector(31 downto 0);
-    hdl_date      : std_logic_vector(31 downto 0);
-    description   : string(1 to 16);
+    wbd_begin          : unsigned(63 downto 0);
+    wbd_end            : unsigned(63 downto 0);
+    sdwb_child         : unsigned(63 downto 0);
+    wbd_flags          : std_logic_vector(7 downto 0);
+    wbd_width          : std_logic_vector(7 downto 0);
+    abi_ver_major      : unsigned(7 downto 0);
+    abi_ver_minor      : unsigned(7 downto 0);
+    abi_class          : std_logic_vector(31 downto 0);
+    dev_vendor         : std_logic_vector(31 downto 0);
+    dev_device         : std_logic_vector(31 downto 0);
+    dev_version        : std_logic_vector(31 downto 0);
+    dev_date           : std_logic_vector(31 downto 0);
+    description        : string(1 to 16);
   end record t_sdwb_device;
-  type t_sdwb_devices_array is array(natural range <>) of t_sdwb_device;
+  type t_sdwb_device_array is array(natural range <>) of t_sdwb_device;
 
 ------------------------------------------------------------------------------
 -- Components declaration
@@ -200,25 +200,25 @@ package wishbone_pkg is
     generic (
       g_num_masters : integer;
       g_num_slaves  : integer;
-      g_registered  : boolean);
+      g_registered  : boolean;
+      g_address     : t_wishbone_address_array;
+      g_mask        : t_wishbone_address_array);
     port (
       clk_sys_i     : in  std_logic;
       rst_n_i       : in  std_logic;
       slave_i       : in  t_wishbone_slave_in_array(g_num_masters-1 downto 0);
       slave_o       : out t_wishbone_slave_out_array(g_num_masters-1 downto 0);
       master_i      : in  t_wishbone_master_in_array(g_num_slaves-1 downto 0);
-      master_o      : out t_wishbone_master_out_array(g_num_slaves-1 downto 0);
-      cfg_address_i : in  t_wishbone_address_array(g_num_slaves-1 downto 0);
-      cfg_mask_i    : in  t_wishbone_address_array(g_num_slaves-1 downto 0));
+      master_o      : out t_wishbone_master_out_array(g_num_slaves-1 downto 0));
   end component;
 
   component xwb_sdwb_crossbar
     generic (
       g_num_masters : integer;
       g_num_slaves  : integer;
-      g_registered  : boolean;
-      g_address     : t_wishbone_address_array;
-      g_mask        : t_wishbone_address_array;
+      g_registered  : boolean := false;
+      g_wraparound  : boolean := true;
+      g_layout      : t_sdwb_device_array;
       g_sdwb_addr   : t_wishbone_address);
     port (
       clk_sys_i     : in  std_logic;
@@ -229,6 +229,16 @@ package wishbone_pkg is
       master_o      : out t_wishbone_master_out_array(g_num_slaves-1 downto 0));
   end component;
 
+  component sdwb_rom is
+    generic(
+      g_layout      : t_sdwb_device_array;
+      g_bus_end     : unsigned(63 downto 0));
+    port(
+      clk_sys_i     : in  std_logic;
+      slave_i       : in  t_wishbone_slave_in;
+      slave_o       : out t_wishbone_slave_out);
+  end component;
+  
   component xwb_dpram
     generic (
       g_size                  : natural;