examples: Wishbone interconnect test bench
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Tue, 13 Dec 2011 13:10:56 +0000 (14:10 +0100)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Tue, 13 Dec 2011 13:10:56 +0000 (14:10 +0100)
examples/wb_intercon/Makefile [new file with mode: 0644]
examples/wb_intercon/intercon_conv.py [new file with mode: 0644]
examples/wb_intercon/master.v [new file with mode: 0644]
examples/wb_intercon/slave.v [new file with mode: 0644]
examples/wb_intercon/tb_intercon.v [new file with mode: 0644]

diff --git a/examples/wb_intercon/Makefile b/examples/wb_intercon/Makefile
new file mode 100644 (file)
index 0000000..fc9f857
--- /dev/null
@@ -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 (file)
index 0000000..06b046a
--- /dev/null
@@ -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 (file)
index 0000000..6698e69
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ */
+
+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 (file)
index 0000000..5ce2089
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ */
+
+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 (file)
index 0000000..5a0099d
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+ */
+
+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