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