mirror of
https://github.com/enjoy-digital/litex.git
synced 2025-01-04 09:52:26 -05:00
examples: Wishbone interconnect test bench
This commit is contained in:
parent
c840848dba
commit
6f7a35e0a3
5 changed files with 398 additions and 0 deletions
examples/wb_intercon
20
examples/wb_intercon/Makefile
Normal file
20
examples/wb_intercon/Makefile
Normal file
|
@ -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
|
20
examples/wb_intercon/intercon_conv.py
Normal file
20
examples/wb_intercon/intercon_conv.py
Normal file
|
@ -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)
|
89
examples/wb_intercon/master.v
Normal file
89
examples/wb_intercon/master.v
Normal file
|
@ -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
|
||||||
|
|
55
examples/wb_intercon/slave.v
Normal file
55
examples/wb_intercon/slave.v
Normal file
|
@ -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
|
214
examples/wb_intercon/tb_intercon.v
Normal file
214
examples/wb_intercon/tb_intercon.v
Normal file
|
@ -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
|
Loading…
Reference in a new issue