diff --git a/modules/wishbone/wb_crossbar/Manifest.py b/modules/wishbone/wb_crossbar/Manifest.py
new file mode 100644
index 0000000000000000000000000000000000000000..df804aee948ff7aadc31166212295be74e9e0559
--- /dev/null
+++ b/modules/wishbone/wb_crossbar/Manifest.py
@@ -0,0 +1 @@
+files = ["xwb_crossbar.vhd"];
diff --git a/modules/wishbone/wb_crossbar/xwb_crossbar.vhd b/modules/wishbone/wb_crossbar/xwb_crossbar.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..14db5901c18046cd5b9b631e852bdd2c8472eec9
--- /dev/null
+++ b/modules/wishbone/wb_crossbar/xwb_crossbar.vhd
@@ -0,0 +1,265 @@
+-------------------------------------------------------------------------------
+-- Title      : An MxS Wishbone crossbar switch
+-- Project    : General Cores Library (gencores)
+-------------------------------------------------------------------------------
+-- File       : xwb_crossbar.vhd
+-- Author     : Wesley W. Terpstra
+-- Company    : GSI
+-- Created    : 2011-06-08
+-- Last update: 2011-09-22
+-- Platform   : FPGA-generic
+-- Standard   : VHDL'93
+-------------------------------------------------------------------------------
+-- Description:
+--
+-- An MxS Wishbone crossbar switch
+-- 
+-- All masters, slaves, and the crossbar itself must share the same WB clock.
+-- 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.
+-- 
+-- The implementation of this crossbar locks a master to a slave so long as
+-- CYC_O is held high. If the master tries to address outside the slave's
+-- address range, ERR_I will be raised.
+--
+-------------------------------------------------------------------------------
+-- Copyright (c) 2011 GSI / Wesley W. Terpstra
+-------------------------------------------------------------------------------
+-- Revisions  :
+-- Date        Version  Author          Description
+-- 2011-06-08  1.0      wterpstra       import from SVN
+-------------------------------------------------------------------------------
+
+
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+use work.wishbone_pkg.all;
+
+entity xwb_crossbar is
+  generic(
+    g_num_masters : integer := 2;
+    g_num_slaves  : integer := 1;
+    g_registered  : boolean := false
+    );
+  port(
+    clk_sys_i     : in  std_logic;
+    rst_n_i       : in  std_logic;
+    -- Master connections (INTERCON is a slave)
+    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);
+    -- 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)
+    );
+end xwb_crossbar;
+
+architecture rtl of xwb_crossbar is
+  type matrix is array (g_num_masters-1 downto 0, g_num_slaves downto 0) of std_logic;
+  type column is array (g_num_masters-1 downto 0) of std_logic;
+  type row is array (g_num_slaves downto 0) of std_logic;
+
+  -- synchronous signals:
+  signal previous : matrix;             -- Previously connected pairs
+
+  -- (a)synchronous signals (depending on generic):
+  signal granted : matrix;  -- The connections to form this cycle selected previous bus
+  signal issue   : column;              -- Did last cycle issue a request
+  
+  procedure main_logic(
+    signal granted  : out matrix;
+    signal issue    : out column;
+    signal slave_i  : in  t_wishbone_slave_in_array(g_num_masters-1 downto 0);
+    signal previous : in  matrix) is
+    variable acc, tmp : std_logic;
+    variable request  : matrix;  -- Which slaves do the masters address log(S) 
+    variable selected : matrix;  -- Which master wins arbitration  log(M) request
+    variable sbusy    : row;  -- Does the slave's  previous connection persist?
+    variable mbusy    : column;  -- Does the master's previous connection persist?
+  begin
+    -- A slave is busy iff it services an in-progress cycle
+    for slave in g_num_slaves-1 downto 0 loop
+      acc := '0';
+      for master in g_num_masters-1 downto 0 loop
+        acc := acc or (previous(master, slave) and slave_i(master).CYC);
+      end loop;
+      sbusy(slave) := acc;
+    end loop;
+    sbusy(g_num_slaves) := '0';  -- Special case because the 'error device' supports multiple masters
+
+    -- A master is busy iff it services an in-progress cycle
+    for master in g_num_masters-1 downto 0 loop
+      acc := '0';
+      for slave in g_num_slaves downto 0 loop
+        acc := acc or previous(master, slave);
+      end loop;
+      mbusy(master) := acc and slave_i(master).CYC;
+    end loop;
+
+    -- Decode the request address to see if master wants access
+    for master in g_num_masters-1 downto 0 loop
+      acc := '0';
+      for slave in g_num_slaves-1 downto 0 loop
+        if (slave_i(master).ADR and  cfg_mask_i(slave)) = cfg_address_i(slave) then
+          tmp := '1';
+        else
+          tmp := '0';
+        end if;
+        acc                    := acc or tmp;
+        request(master, slave) := slave_i(master).CYC and slave_i(master).STB and tmp;
+      end loop;
+      -- If no slaves match request, bind to 'error device'
+      request(master, g_num_slaves) := slave_i(master).CYC and slave_i(master).STB and not acc;
+    end loop;
+
+    -- Arbitrate among the requesting masters
+    -- Policy: lowest numbered master first
+    for slave in g_num_slaves-1 downto 0 loop
+      acc := '0';
+      -- It is possible to break the chain of LUTs here using a sort of kogge-stone network
+      -- This probably only makes sense if you have more than 32 masters
+      for master in 0 to g_num_masters-1 loop
+        selected(master, slave) := request(master, slave) and not acc;
+        acc                     := acc or request(master, slave);
+      end loop;
+    end loop;
+
+    -- Multiple masters can be granted access to the 'error device'
+    for master in g_num_masters-1 downto 0 loop
+      selected(master, g_num_slaves) := request(master, g_num_slaves);
+    end loop;
+
+    -- Determine the master granted access
+    -- Policy: if cycle still in progress, preserve the previous choice
+    for slave in g_num_slaves downto 0 loop
+      for master in g_num_masters-1 downto 0 loop
+        if sbusy(slave) = '1' or mbusy(master) = '1' then
+          granted(master, slave) <= previous(master, slave);
+        else
+          granted(master, slave) <= selected(master, slave);
+        end if;
+      end loop;
+    end loop;
+
+    -- Record strobe status for virtual error device
+    for master in g_num_masters-1 downto 0 loop
+      issue(master) <= slave_i(master).CYC and slave_i(master).STB;
+    end loop;
+  end main_logic;
+
+  -- Select the master pins the slave will receive
+  procedure slave_logic(signal o       : out t_wishbone_master_out;
+                        signal slave_i : in  t_wishbone_slave_in_array(g_num_masters-1 downto 0);
+                        signal granted : in  matrix;
+                        slave          :     integer) is
+    variable acc             : t_wishbone_master_out;
+    variable granted_address : t_wishbone_address;
+    variable granted_select  : t_wishbone_byte_select;
+    variable granted_data    : t_wishbone_data;
+  begin
+    acc := (
+      CYC => '0',
+      STB => '0',
+      ADR => (others => '0'),
+      SEL => (others => '0'),
+      WE  => '0',
+      DAT => (others => '0'));
+
+    for master in g_num_masters-1 downto 0 loop
+      granted_address := (others => granted(master, slave));
+      granted_select  := (others => granted(master, slave));
+      granted_data    := (others => granted(master, slave));
+      acc := (
+        CYC => acc.CYC or (slave_i(master).CYC and granted(master, slave)),
+        STB => acc.STB or (slave_i(master).STB and granted(master, slave)),
+        ADR => acc.ADR or (slave_i(master).ADR and granted_address),
+        SEL => acc.SEL or (slave_i(master).SEL and granted_select),
+        WE  => acc.WE or (slave_i(master).WE and granted(master, slave)),
+        DAT => acc.DAT or (slave_i(master).DAT and granted_data));
+    end loop;
+    o <= acc;
+  end slave_logic;
+
+  -- Select the slave pins the master will receive
+  procedure master_logic(signal o        : out t_wishbone_slave_out;
+                         signal master_i : in  t_wishbone_master_in_array(g_num_slaves-1 downto 0);
+                         signal issue    : in  column;
+                         signal previous : in  matrix;
+                         signal granted  : in  matrix;
+                         master          :     integer) is
+    variable acc          : t_wishbone_slave_out;
+    variable granted_data : t_wishbone_data;
+  begin
+    acc := (
+      ACK   => '0',
+      ERR   => issue(master) and previous(master, g_num_slaves),  -- Error device connected and strobed?
+      RTY   => '0',
+      STALL => granted(master, g_num_slaves),
+      DAT   => (others => '0'),
+      INT => '0');
+
+    -- We use inverted logic on STALL so that if no slave granted => stall
+    for slave in g_num_slaves-1 downto 0 loop
+      granted_data := (others => granted(master, slave));
+      acc := (
+        ACK   => acc.ACK or (master_i(slave).ACK and granted(master, slave)),
+        ERR   => acc.ERR or (master_i(slave).ERR and granted(master, slave)),
+        RTY   => acc.RTY or (master_i(slave).RTY and granted(master, slave)),
+        STALL => acc.STALL or (not master_i(slave).STALL and granted(master, slave)),
+        DAT   => acc.DAT or (master_i(slave).DAT and granted_data),
+        INT =>'0');
+    end loop;
+    acc.STALL := not acc.STALL;
+
+    o <= acc;
+  end master_logic;
+begin
+  -- If async determine granted devices
+  granted_matrix : if not g_registered generate
+    main_logic(granted, issue, slave_i, previous);
+  end generate;
+
+  granted_driver : if g_registered generate
+    process(clk_sys_i)
+    begin
+      if rising_edge(clk_sys_i) then
+        if rst_n_i = '0' then
+          granted <= (others => (others => '0'));
+          issue   <= (others => '0');
+        else
+          main_logic(granted, issue, slave_i, previous);
+        end if;
+      end if;
+    end process;
+  end generate;
+
+  -- Make the slave connections
+  slave_matrix : for slave in g_num_slaves-1 downto 0 generate
+    slave_logic(master_o(slave), slave_i, granted, slave);
+  end generate;
+
+  -- Make the master connections
+  master_matrix : for master in g_num_masters-1 downto 0 generate
+    master_logic(slave_o(master), master_i, issue, previous, granted, master);
+  end generate;
+
+  -- Store the current grant to the previous registers
+  main : process(clk_sys_i)
+  begin
+    if rising_edge(clk_sys_i) then
+      if rst_n_i = '0' then
+        previous <= (others => (others => '0'));
+      else
+        previous <= granted;
+      end if;
+    end if;
+  end process main;
+  
+end rtl;