diff --git a/examples/wb_intercon/Makefile b/examples/wb_intercon/Makefile
new file mode 100644
index 000000000..fc9f857e5
--- /dev/null
+++ b/examples/wb_intercon/Makefile
@@ -0,0 +1,20 @@
+SOURCES=tb_intercon.v intercon.v master.v slave.v
+
+all: tb_intercon
+
+sim: tb_intercon
+ ./tb_intercon
+
+cversim: $(SOURCES)
+ cver $(SOURCES)
+
+clean:
+ rm -f tb_intercon intercon.v intercon.vcd verilog.log
+
+tb_intercon: $(SOURCES)
+ iverilog -o tb_intercon $(SOURCES)
+
+intercon.v: intercon_conv.py
+ python3 intercon_conv.py > intercon.v
+
+.PHONY: clean sim cversim
diff --git a/examples/wb_intercon/intercon_conv.py b/examples/wb_intercon/intercon_conv.py
new file mode 100644
index 000000000..06b046a8d
--- /dev/null
+++ b/examples/wb_intercon/intercon_conv.py
@@ -0,0 +1,20 @@
+from migen.fhdl import verilog
+from migen.fhdl import structure as f
+from migen.bus import wishbone
+
+m1 = wishbone.Master("m1")
+m2 = wishbone.Master("m2")
+s1 = wishbone.Slave("s1")
+s2 = wishbone.Slave("s2")
+wishbonecon0 = wishbone.InterconnectShared(
+ [m1, m2],
+ [(0, s1), (1, s2)],
+ register=True,
+ offset=1)
+
+frag = wishbonecon0.GetFragment()
+v = verilog.Convert(frag, name="intercon", ios={m1.cyc_o, m1.stb_o, m1.we_o, m1.adr_o, m1.sel_o, m1.dat_o, m1.dat_i, m1.ack_i,
+ m2.cyc_o, m2.stb_o, m2.we_o, m2.adr_o, m2.sel_o, m2.dat_o, m2.dat_i, m2.ack_i,
+ s1.cyc_i, s1.stb_i, s1.we_i, s1.adr_i, s1.sel_i, s1.dat_i, s1.dat_o, s1.ack_o,
+ s2.cyc_i, s2.stb_i, s2.we_i, s2.adr_i, s2.sel_i, s2.dat_i, s2.dat_o, s2.ack_o})
+print(v)
diff --git a/examples/wb_intercon/master.v b/examples/wb_intercon/master.v
new file mode 100644
index 000000000..6698e69d1
--- /dev/null
+++ b/examples/wb_intercon/master.v
@@ -0,0 +1,89 @@
+/*
+ * Milkymist SoC
+ * Copyright (C) 2007, 2008, 2009, 2011 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+module master #(
+ parameter id = 0,
+ parameter nreads = 10,
+ parameter nwrites = 10,
+ parameter p = 4
+) (
+ input sys_clk,
+ input sys_rst,
+
+ output reg [31:0] dat_w,
+ input [31:0] dat_r,
+ output reg [31:0] adr,
+ output reg we,
+ output reg [3:0] sel,
+ output cyc,
+ output stb,
+ input ack,
+
+ output reg tend
+);
+
+integer rcounter;
+integer wcounter;
+reg active;
+
+assign cyc = active;
+assign stb = active;
+
+always @(posedge sys_clk) begin
+ if(sys_rst) begin
+ dat_w <= 0;
+ adr <= 0;
+ we <= 0;
+ sel <= 0;
+ active <= 0;
+ rcounter = 0;
+ wcounter = 0;
+ tend <= 0;
+ end else begin
+ if(ack) begin
+ if(~active)
+ $display("[M%d] Spurious ack", id);
+ else begin
+ if(we)
+ $display("[M%d] Ack W: %x:%x [%x]", id, adr, dat_w, sel);
+ else
+ $display("[M%d] Ack R: %x:%x [%x]", id, adr, dat_r, sel);
+ end
+ active <= 1'b0;
+ end else if(~active) begin
+ if(($random % p) == 0) begin
+ adr <= (($random % 5)<< (32-2)) + id;
+ sel <= sel + 1;
+ active <= 1'b1;
+ if(($random % 2) == 0) begin
+ /* Read */
+ we <= 1'b0;
+ rcounter = rcounter + 1;
+ end else begin
+ /* Write */
+ we <= 1'b1;
+ dat_w <= ($random << 16) + id;
+ wcounter = wcounter + 1;
+ end
+ end
+ end
+ tend <= (rcounter >= nreads) && (wcounter >= nwrites);
+ end
+end
+
+endmodule
+
diff --git a/examples/wb_intercon/slave.v b/examples/wb_intercon/slave.v
new file mode 100644
index 000000000..5ce208911
--- /dev/null
+++ b/examples/wb_intercon/slave.v
@@ -0,0 +1,55 @@
+/*
+ * Milkymist SoC
+ * Copyright (C) 2007, 2008, 2009, 2011 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+module slave #(
+ parameter id = 0,
+ parameter p = 3
+) (
+ input sys_clk,
+ input sys_rst,
+
+ input [31:0] dat_w,
+ output reg [31:0] dat_r,
+ input [31:0] adr,
+ input we,
+ input [3:0] sel,
+ input cyc,
+ input stb,
+ output reg ack
+);
+
+always @(posedge sys_clk) begin
+ if(sys_rst) begin
+ dat_r <= 0;
+ ack <= 0;
+ end else begin
+ if(cyc & stb & ~ack) begin
+ if(($random % p) == 0) begin
+ ack <= 1;
+ if(~we)
+ dat_r <= ($random << 16) + id;
+ if(we)
+ $display("[S%d] Ack W: %x:%x [%x]", id, adr, dat_w, sel);
+ else
+ $display("[S%d] Ack R: %x:%x [%x]", id, adr, dat_r, sel);
+ end
+ end else
+ ack <= 0;
+ end
+end
+
+endmodule
diff --git a/examples/wb_intercon/tb_intercon.v b/examples/wb_intercon/tb_intercon.v
new file mode 100644
index 000000000..5a0099da6
--- /dev/null
+++ b/examples/wb_intercon/tb_intercon.v
@@ -0,0 +1,214 @@
+/*
+ * Milkymist SoC
+ * Copyright (C) 2007, 2008, 2009, 2011 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+module tb_conbus();
+
+reg sys_rst;
+reg sys_clk;
+
+//------------------------------------------------------------------
+// Wishbone master wires
+//------------------------------------------------------------------
+wire [31:0] wishbone_m1_adr,
+ wishbone_m2_adr;
+
+wire [31:0] wishbone_m1_dat_r,
+ wishbone_m1_dat_w,
+ wishbone_m2_dat_r,
+ wishbone_m2_dat_w;
+
+wire [3:0] wishbone_m1_sel,
+ wishbone_m2_sel;
+
+wire wishbone_m1_we,
+ wishbone_m2_we;
+
+wire wishbone_m1_cyc,
+ wishbone_m2_cyc;
+
+wire wishbone_m1_stb,
+ wishbone_m2_stb;
+
+wire wishbone_m1_ack,
+ wishbone_m2_ack;
+
+//------------------------------------------------------------------
+// Wishbone slave wires
+//------------------------------------------------------------------
+wire [31:0] wishbone_s1_adr,
+ wishbone_s2_adr;
+
+wire [31:0] wishbone_s1_dat_r,
+ wishbone_s1_dat_w,
+ wishbone_s2_dat_r,
+ wishbone_s2_dat_w;
+
+wire [3:0] wishbone_s1_sel,
+ wishbone_s2_sel;
+
+wire wishbone_s1_we,
+ wishbone_s2_we;
+
+wire wishbone_s1_cyc,
+ wishbone_s2_cyc;
+
+wire wishbone_s1_stb,
+ wishbone_s2_stb;
+
+wire wishbone_s1_ack,
+ wishbone_s2_ack;
+
+//---------------------------------------------------------------------------
+// Wishbone switch
+//---------------------------------------------------------------------------
+intercon dut(
+ .sys_clk(sys_clk),
+ .sys_rst(sys_rst),
+
+ // Master 0
+ .wishbone_m1_dat_o(wishbone_m1_dat_w),
+ .wishbone_m1_dat_i(wishbone_m1_dat_r),
+ .wishbone_m1_adr_o(wishbone_m1_adr),
+ .wishbone_m1_we_o(wishbone_m1_we),
+ .wishbone_m1_sel_o(wishbone_m1_sel),
+ .wishbone_m1_cyc_o(wishbone_m1_cyc),
+ .wishbone_m1_stb_o(wishbone_m1_stb),
+ .wishbone_m1_ack_i(wishbone_m1_ack),
+ // Master 1
+ .wishbone_m2_dat_o(wishbone_m2_dat_w),
+ .wishbone_m2_dat_i(wishbone_m2_dat_r),
+ .wishbone_m2_adr_o(wishbone_m2_adr),
+ .wishbone_m2_we_o(wishbone_m2_we),
+ .wishbone_m2_sel_o(wishbone_m2_sel),
+ .wishbone_m2_cyc_o(wishbone_m2_cyc),
+ .wishbone_m2_stb_o(wishbone_m2_stb),
+ .wishbone_m2_ack_i(wishbone_m2_ack),
+
+ // Slave 0
+ .wishbone_s1_dat_o(wishbone_s1_dat_r),
+ .wishbone_s1_dat_i(wishbone_s1_dat_w),
+ .wishbone_s1_adr_i(wishbone_s1_adr),
+ .wishbone_s1_sel_i(wishbone_s1_sel),
+ .wishbone_s1_we_i(wishbone_s1_we),
+ .wishbone_s1_cyc_i(wishbone_s1_cyc),
+ .wishbone_s1_stb_i(wishbone_s1_stb),
+ .wishbone_s1_ack_o(wishbone_s1_ack),
+ // Slave 1
+ .wishbone_s2_dat_o(wishbone_s2_dat_r),
+ .wishbone_s2_dat_i(wishbone_s2_dat_w),
+ .wishbone_s2_adr_i(wishbone_s2_adr),
+ .wishbone_s2_sel_i(wishbone_s2_sel),
+ .wishbone_s2_we_i(wishbone_s2_we),
+ .wishbone_s2_cyc_i(wishbone_s2_cyc),
+ .wishbone_s2_stb_i(wishbone_s2_stb),
+ .wishbone_s2_ack_o(wishbone_s2_ack)
+);
+
+//---------------------------------------------------------------------------
+// Masters
+//---------------------------------------------------------------------------
+
+wire wishbone_m1_end;
+master #(
+ .id(0)
+) m0 (
+ .sys_clk(sys_clk),
+ .sys_rst(sys_rst),
+
+ .dat_w(wishbone_m1_dat_w),
+ .dat_r(wishbone_m1_dat_r),
+ .adr(wishbone_m1_adr),
+ .we(wishbone_m1_we),
+ .sel(wishbone_m1_sel),
+ .cyc(wishbone_m1_cyc),
+ .stb(wishbone_m1_stb),
+ .ack(wishbone_m1_ack),
+
+ .tend(wishbone_m1_end)
+);
+
+wire wishbone_m2_end;
+master #(
+ .id(1)
+) m1 (
+ .sys_clk(sys_clk),
+ .sys_rst(sys_rst),
+
+ .dat_w(wishbone_m2_dat_w),
+ .dat_r(wishbone_m2_dat_r),
+ .adr(wishbone_m2_adr),
+ .we(wishbone_m2_we),
+ .sel(wishbone_m2_sel),
+ .cyc(wishbone_m2_cyc),
+ .stb(wishbone_m2_stb),
+ .ack(wishbone_m2_ack),
+
+ .tend(wishbone_m2_end)
+);
+
+//---------------------------------------------------------------------------
+// Slaves
+//---------------------------------------------------------------------------
+
+slave #(
+ .id(0)
+) s0 (
+ .sys_clk(sys_clk),
+ .sys_rst(sys_rst),
+
+ .dat_w(wishbone_s1_dat_w),
+ .dat_r(wishbone_s1_dat_r),
+ .adr(wishbone_s1_adr),
+ .we(wishbone_s1_we),
+ .sel(wishbone_s1_sel),
+ .cyc(wishbone_s1_cyc),
+ .stb(wishbone_s1_stb),
+ .ack(wishbone_s1_ack)
+);
+
+slave #(
+ .id(1)
+) s1 (
+ .sys_clk(sys_clk),
+ .sys_rst(sys_rst),
+
+ .dat_w(wishbone_s2_dat_w),
+ .dat_r(wishbone_s2_dat_r),
+ .adr(wishbone_s2_adr),
+ .we(wishbone_s2_we),
+ .sel(wishbone_s2_sel),
+ .cyc(wishbone_s2_cyc),
+ .stb(wishbone_s2_stb),
+ .ack(wishbone_s2_ack)
+);
+
+initial sys_clk = 1'b0;
+always #5 sys_clk = ~sys_clk;
+
+wire all_end = wishbone_m1_end & wishbone_m2_end;
+
+always begin
+ $dumpfile("intercon.vcd");
+ $dumpvars(1, dut);
+ sys_rst = 1'b1;
+ @(posedge sys_clk);
+ #1 sys_rst = 1'b0;
+ @(posedge all_end);
+ $finish;
+end
+
+endmodule