mirror of
https://github.com/corundum/corundum.git
synced 2025-01-30 08:32:52 +08:00
Add AXI nonblocking crossbar interconnect module and testbench
This commit is contained in:
parent
365e063bc7
commit
7b713199ad
331
rtl/axi_crossbar.v
Normal file
331
rtl/axi_crossbar.v
Normal file
@ -0,0 +1,331 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2018 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
// Language: Verilog 2001
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
/*
|
||||
* AXI4 crossbar
|
||||
*/
|
||||
module axi_crossbar #
|
||||
(
|
||||
parameter S_COUNT = 4,
|
||||
parameter M_COUNT = 4,
|
||||
parameter DATA_WIDTH = 32,
|
||||
parameter ADDR_WIDTH = 32,
|
||||
parameter STRB_WIDTH = (DATA_WIDTH/8),
|
||||
parameter S_ID_WIDTH = 8,
|
||||
parameter M_ID_WIDTH = S_ID_WIDTH+$clog2(S_COUNT),
|
||||
parameter AWUSER_ENABLE = 0,
|
||||
parameter AWUSER_WIDTH = 1,
|
||||
parameter WUSER_ENABLE = 0,
|
||||
parameter WUSER_WIDTH = 1,
|
||||
parameter BUSER_ENABLE = 0,
|
||||
parameter BUSER_WIDTH = 1,
|
||||
parameter ARUSER_ENABLE = 0,
|
||||
parameter ARUSER_WIDTH = 1,
|
||||
parameter RUSER_ENABLE = 0,
|
||||
parameter RUSER_WIDTH = 1,
|
||||
parameter S_THREADS = {S_COUNT{32'd2}},
|
||||
parameter S_ACCEPT = {S_COUNT{32'd16}},
|
||||
parameter M_REGIONS = 1,
|
||||
parameter M_BASE_ADDR = {32'h03000000, 32'h02000000, 32'h01000000, 32'h00000000},
|
||||
parameter M_ADDR_WIDTH = {M_COUNT{{M_REGIONS{32'd24}}}},
|
||||
parameter M_CONNECT_READ = {M_COUNT{{S_COUNT{1'b1}}}},
|
||||
parameter M_CONNECT_WRITE = {M_COUNT{{S_COUNT{1'b1}}}},
|
||||
parameter M_ISSUE = {M_COUNT{32'd4}},
|
||||
parameter M_SECURE = {M_COUNT{1'b0}},
|
||||
parameter S_AW_REG_TYPE = {S_COUNT{2'd0}},
|
||||
parameter S_W_REG_TYPE = {S_COUNT{2'd0}},
|
||||
parameter S_B_REG_TYPE = {S_COUNT{2'd1}},
|
||||
parameter S_AR_REG_TYPE = {S_COUNT{2'd0}},
|
||||
parameter S_R_REG_TYPE = {S_COUNT{2'd2}},
|
||||
parameter M_AW_REG_TYPE = {M_COUNT{2'd1}},
|
||||
parameter M_W_REG_TYPE = {M_COUNT{2'd2}},
|
||||
parameter M_B_REG_TYPE = {M_COUNT{2'd0}},
|
||||
parameter M_AR_REG_TYPE = {M_COUNT{2'd1}},
|
||||
parameter M_R_REG_TYPE = {M_COUNT{2'd0}}
|
||||
)
|
||||
(
|
||||
input wire clk,
|
||||
input wire rst,
|
||||
|
||||
/*
|
||||
* AXI slave interfaces
|
||||
*/
|
||||
input wire [S_COUNT*S_ID_WIDTH-1:0] s_axi_awid,
|
||||
input wire [S_COUNT*ADDR_WIDTH-1:0] s_axi_awaddr,
|
||||
input wire [S_COUNT*8-1:0] s_axi_awlen,
|
||||
input wire [S_COUNT*3-1:0] s_axi_awsize,
|
||||
input wire [S_COUNT*2-1:0] s_axi_awburst,
|
||||
input wire [S_COUNT-1:0] s_axi_awlock,
|
||||
input wire [S_COUNT*4-1:0] s_axi_awcache,
|
||||
input wire [S_COUNT*3-1:0] s_axi_awprot,
|
||||
input wire [S_COUNT*4-1:0] s_axi_awqos,
|
||||
input wire [S_COUNT*AWUSER_WIDTH-1:0] s_axi_awuser,
|
||||
input wire [S_COUNT-1:0] s_axi_awvalid,
|
||||
output wire [S_COUNT-1:0] s_axi_awready,
|
||||
input wire [S_COUNT*DATA_WIDTH-1:0] s_axi_wdata,
|
||||
input wire [S_COUNT*STRB_WIDTH-1:0] s_axi_wstrb,
|
||||
input wire [S_COUNT-1:0] s_axi_wlast,
|
||||
input wire [S_COUNT*WUSER_WIDTH-1:0] s_axi_wuser,
|
||||
input wire [S_COUNT-1:0] s_axi_wvalid,
|
||||
output wire [S_COUNT-1:0] s_axi_wready,
|
||||
output wire [S_COUNT*S_ID_WIDTH-1:0] s_axi_bid,
|
||||
output wire [S_COUNT*2-1:0] s_axi_bresp,
|
||||
output wire [S_COUNT*BUSER_WIDTH-1:0] s_axi_buser,
|
||||
output wire [S_COUNT-1:0] s_axi_bvalid,
|
||||
input wire [S_COUNT-1:0] s_axi_bready,
|
||||
input wire [S_COUNT*S_ID_WIDTH-1:0] s_axi_arid,
|
||||
input wire [S_COUNT*ADDR_WIDTH-1:0] s_axi_araddr,
|
||||
input wire [S_COUNT*8-1:0] s_axi_arlen,
|
||||
input wire [S_COUNT*3-1:0] s_axi_arsize,
|
||||
input wire [S_COUNT*2-1:0] s_axi_arburst,
|
||||
input wire [S_COUNT-1:0] s_axi_arlock,
|
||||
input wire [S_COUNT*4-1:0] s_axi_arcache,
|
||||
input wire [S_COUNT*3-1:0] s_axi_arprot,
|
||||
input wire [S_COUNT*4-1:0] s_axi_arqos,
|
||||
input wire [S_COUNT*ARUSER_WIDTH-1:0] s_axi_aruser,
|
||||
input wire [S_COUNT-1:0] s_axi_arvalid,
|
||||
output wire [S_COUNT-1:0] s_axi_arready,
|
||||
output wire [S_COUNT*S_ID_WIDTH-1:0] s_axi_rid,
|
||||
output wire [S_COUNT*DATA_WIDTH-1:0] s_axi_rdata,
|
||||
output wire [S_COUNT*2-1:0] s_axi_rresp,
|
||||
output wire [S_COUNT-1:0] s_axi_rlast,
|
||||
output wire [S_COUNT*RUSER_WIDTH-1:0] s_axi_ruser,
|
||||
output wire [S_COUNT-1:0] s_axi_rvalid,
|
||||
input wire [S_COUNT-1:0] s_axi_rready,
|
||||
|
||||
/*
|
||||
* AXI master interfaces
|
||||
*/
|
||||
output wire [M_COUNT*M_ID_WIDTH-1:0] m_axi_awid,
|
||||
output wire [M_COUNT*ADDR_WIDTH-1:0] m_axi_awaddr,
|
||||
output wire [M_COUNT*8-1:0] m_axi_awlen,
|
||||
output wire [M_COUNT*3-1:0] m_axi_awsize,
|
||||
output wire [M_COUNT*2-1:0] m_axi_awburst,
|
||||
output wire [M_COUNT-1:0] m_axi_awlock,
|
||||
output wire [M_COUNT*4-1:0] m_axi_awcache,
|
||||
output wire [M_COUNT*3-1:0] m_axi_awprot,
|
||||
output wire [M_COUNT*4-1:0] m_axi_awqos,
|
||||
output wire [M_COUNT*4-1:0] m_axi_awregion,
|
||||
output wire [M_COUNT*AWUSER_WIDTH-1:0] m_axi_awuser,
|
||||
output wire [M_COUNT-1:0] m_axi_awvalid,
|
||||
input wire [M_COUNT-1:0] m_axi_awready,
|
||||
output wire [M_COUNT*DATA_WIDTH-1:0] m_axi_wdata,
|
||||
output wire [M_COUNT*STRB_WIDTH-1:0] m_axi_wstrb,
|
||||
output wire [M_COUNT-1:0] m_axi_wlast,
|
||||
output wire [M_COUNT*WUSER_WIDTH-1:0] m_axi_wuser,
|
||||
output wire [M_COUNT-1:0] m_axi_wvalid,
|
||||
input wire [M_COUNT-1:0] m_axi_wready,
|
||||
input wire [M_COUNT*M_ID_WIDTH-1:0] m_axi_bid,
|
||||
input wire [M_COUNT*2-1:0] m_axi_bresp,
|
||||
input wire [M_COUNT*BUSER_WIDTH-1:0] m_axi_buser,
|
||||
input wire [M_COUNT-1:0] m_axi_bvalid,
|
||||
output wire [M_COUNT-1:0] m_axi_bready,
|
||||
output wire [M_COUNT*M_ID_WIDTH-1:0] m_axi_arid,
|
||||
output wire [M_COUNT*ADDR_WIDTH-1:0] m_axi_araddr,
|
||||
output wire [M_COUNT*8-1:0] m_axi_arlen,
|
||||
output wire [M_COUNT*3-1:0] m_axi_arsize,
|
||||
output wire [M_COUNT*2-1:0] m_axi_arburst,
|
||||
output wire [M_COUNT-1:0] m_axi_arlock,
|
||||
output wire [M_COUNT*4-1:0] m_axi_arcache,
|
||||
output wire [M_COUNT*3-1:0] m_axi_arprot,
|
||||
output wire [M_COUNT*4-1:0] m_axi_arqos,
|
||||
output wire [M_COUNT*4-1:0] m_axi_arregion,
|
||||
output wire [M_COUNT*ARUSER_WIDTH-1:0] m_axi_aruser,
|
||||
output wire [M_COUNT-1:0] m_axi_arvalid,
|
||||
input wire [M_COUNT-1:0] m_axi_arready,
|
||||
input wire [M_COUNT*M_ID_WIDTH-1:0] m_axi_rid,
|
||||
input wire [M_COUNT*DATA_WIDTH-1:0] m_axi_rdata,
|
||||
input wire [M_COUNT*2-1:0] m_axi_rresp,
|
||||
input wire [M_COUNT-1:0] m_axi_rlast,
|
||||
input wire [M_COUNT*RUSER_WIDTH-1:0] m_axi_ruser,
|
||||
input wire [M_COUNT-1:0] m_axi_rvalid,
|
||||
output wire [M_COUNT-1:0] m_axi_rready
|
||||
);
|
||||
|
||||
axi_crossbar_wr #(
|
||||
.S_COUNT(S_COUNT),
|
||||
.M_COUNT(M_COUNT),
|
||||
.DATA_WIDTH(DATA_WIDTH),
|
||||
.ADDR_WIDTH(ADDR_WIDTH),
|
||||
.STRB_WIDTH(STRB_WIDTH),
|
||||
.S_ID_WIDTH(S_ID_WIDTH),
|
||||
.M_ID_WIDTH(M_ID_WIDTH),
|
||||
.AWUSER_ENABLE(AWUSER_ENABLE),
|
||||
.AWUSER_WIDTH(AWUSER_WIDTH),
|
||||
.WUSER_ENABLE(WUSER_ENABLE),
|
||||
.WUSER_WIDTH(WUSER_WIDTH),
|
||||
.BUSER_ENABLE(BUSER_ENABLE),
|
||||
.BUSER_WIDTH(BUSER_WIDTH),
|
||||
.S_THREADS(S_THREADS),
|
||||
.S_ACCEPT(S_ACCEPT),
|
||||
.M_REGIONS(M_REGIONS),
|
||||
.M_BASE_ADDR(M_BASE_ADDR),
|
||||
.M_ADDR_WIDTH(M_ADDR_WIDTH),
|
||||
.M_CONNECT(M_CONNECT_WRITE),
|
||||
.M_ISSUE(M_ISSUE),
|
||||
.M_SECURE(M_SECURE),
|
||||
.S_AW_REG_TYPE(S_AW_REG_TYPE),
|
||||
.S_W_REG_TYPE (S_W_REG_TYPE),
|
||||
.S_B_REG_TYPE (S_B_REG_TYPE)
|
||||
)
|
||||
axi_crossbar_wr_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
/*
|
||||
* AXI slave interfaces
|
||||
*/
|
||||
.s_axi_awid(s_axi_awid),
|
||||
.s_axi_awaddr(s_axi_awaddr),
|
||||
.s_axi_awlen(s_axi_awlen),
|
||||
.s_axi_awsize(s_axi_awsize),
|
||||
.s_axi_awburst(s_axi_awburst),
|
||||
.s_axi_awlock(s_axi_awlock),
|
||||
.s_axi_awcache(s_axi_awcache),
|
||||
.s_axi_awprot(s_axi_awprot),
|
||||
.s_axi_awqos(s_axi_awqos),
|
||||
.s_axi_awuser(s_axi_awuser),
|
||||
.s_axi_awvalid(s_axi_awvalid),
|
||||
.s_axi_awready(s_axi_awready),
|
||||
.s_axi_wdata(s_axi_wdata),
|
||||
.s_axi_wstrb(s_axi_wstrb),
|
||||
.s_axi_wlast(s_axi_wlast),
|
||||
.s_axi_wuser(s_axi_wuser),
|
||||
.s_axi_wvalid(s_axi_wvalid),
|
||||
.s_axi_wready(s_axi_wready),
|
||||
.s_axi_bid(s_axi_bid),
|
||||
.s_axi_bresp(s_axi_bresp),
|
||||
.s_axi_buser(s_axi_buser),
|
||||
.s_axi_bvalid(s_axi_bvalid),
|
||||
.s_axi_bready(s_axi_bready),
|
||||
|
||||
/*
|
||||
* AXI master interfaces
|
||||
*/
|
||||
.m_axi_awid(m_axi_awid),
|
||||
.m_axi_awaddr(m_axi_awaddr),
|
||||
.m_axi_awlen(m_axi_awlen),
|
||||
.m_axi_awsize(m_axi_awsize),
|
||||
.m_axi_awburst(m_axi_awburst),
|
||||
.m_axi_awlock(m_axi_awlock),
|
||||
.m_axi_awcache(m_axi_awcache),
|
||||
.m_axi_awprot(m_axi_awprot),
|
||||
.m_axi_awqos(m_axi_awqos),
|
||||
.m_axi_awregion(m_axi_awregion),
|
||||
.m_axi_awuser(m_axi_awuser),
|
||||
.m_axi_awvalid(m_axi_awvalid),
|
||||
.m_axi_awready(m_axi_awready),
|
||||
.m_axi_wdata(m_axi_wdata),
|
||||
.m_axi_wstrb(m_axi_wstrb),
|
||||
.m_axi_wlast(m_axi_wlast),
|
||||
.m_axi_wuser(m_axi_wuser),
|
||||
.m_axi_wvalid(m_axi_wvalid),
|
||||
.m_axi_wready(m_axi_wready),
|
||||
.m_axi_bid(m_axi_bid),
|
||||
.m_axi_bresp(m_axi_bresp),
|
||||
.m_axi_buser(m_axi_buser),
|
||||
.m_axi_bvalid(m_axi_bvalid),
|
||||
.m_axi_bready(m_axi_bready)
|
||||
);
|
||||
|
||||
axi_crossbar_rd #(
|
||||
.S_COUNT(S_COUNT),
|
||||
.M_COUNT(M_COUNT),
|
||||
.DATA_WIDTH(DATA_WIDTH),
|
||||
.ADDR_WIDTH(ADDR_WIDTH),
|
||||
.STRB_WIDTH(STRB_WIDTH),
|
||||
.S_ID_WIDTH(S_ID_WIDTH),
|
||||
.M_ID_WIDTH(M_ID_WIDTH),
|
||||
.ARUSER_ENABLE(ARUSER_ENABLE),
|
||||
.ARUSER_WIDTH(ARUSER_WIDTH),
|
||||
.RUSER_ENABLE(RUSER_ENABLE),
|
||||
.RUSER_WIDTH(RUSER_WIDTH),
|
||||
.S_THREADS(S_THREADS),
|
||||
.S_ACCEPT(S_ACCEPT),
|
||||
.M_REGIONS(M_REGIONS),
|
||||
.M_BASE_ADDR(M_BASE_ADDR),
|
||||
.M_ADDR_WIDTH(M_ADDR_WIDTH),
|
||||
.M_CONNECT(M_CONNECT_READ),
|
||||
.M_ISSUE(M_ISSUE),
|
||||
.M_SECURE(M_SECURE),
|
||||
.S_AR_REG_TYPE(S_AR_REG_TYPE),
|
||||
.S_R_REG_TYPE (S_R_REG_TYPE)
|
||||
)
|
||||
axi_crossbar_rd_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
/*
|
||||
* AXI slave interfaces
|
||||
*/
|
||||
.s_axi_arid(s_axi_arid),
|
||||
.s_axi_araddr(s_axi_araddr),
|
||||
.s_axi_arlen(s_axi_arlen),
|
||||
.s_axi_arsize(s_axi_arsize),
|
||||
.s_axi_arburst(s_axi_arburst),
|
||||
.s_axi_arlock(s_axi_arlock),
|
||||
.s_axi_arcache(s_axi_arcache),
|
||||
.s_axi_arprot(s_axi_arprot),
|
||||
.s_axi_arqos(s_axi_arqos),
|
||||
.s_axi_aruser(s_axi_aruser),
|
||||
.s_axi_arvalid(s_axi_arvalid),
|
||||
.s_axi_arready(s_axi_arready),
|
||||
.s_axi_rid(s_axi_rid),
|
||||
.s_axi_rdata(s_axi_rdata),
|
||||
.s_axi_rresp(s_axi_rresp),
|
||||
.s_axi_rlast(s_axi_rlast),
|
||||
.s_axi_ruser(s_axi_ruser),
|
||||
.s_axi_rvalid(s_axi_rvalid),
|
||||
.s_axi_rready(s_axi_rready),
|
||||
|
||||
/*
|
||||
* AXI master interfaces
|
||||
*/
|
||||
.m_axi_arid(m_axi_arid),
|
||||
.m_axi_araddr(m_axi_araddr),
|
||||
.m_axi_arlen(m_axi_arlen),
|
||||
.m_axi_arsize(m_axi_arsize),
|
||||
.m_axi_arburst(m_axi_arburst),
|
||||
.m_axi_arlock(m_axi_arlock),
|
||||
.m_axi_arcache(m_axi_arcache),
|
||||
.m_axi_arprot(m_axi_arprot),
|
||||
.m_axi_arqos(m_axi_arqos),
|
||||
.m_axi_arregion(m_axi_arregion),
|
||||
.m_axi_aruser(m_axi_aruser),
|
||||
.m_axi_arvalid(m_axi_arvalid),
|
||||
.m_axi_arready(m_axi_arready),
|
||||
.m_axi_rid(m_axi_rid),
|
||||
.m_axi_rdata(m_axi_rdata),
|
||||
.m_axi_rresp(m_axi_rresp),
|
||||
.m_axi_rlast(m_axi_rlast),
|
||||
.m_axi_ruser(m_axi_ruser),
|
||||
.m_axi_rvalid(m_axi_rvalid),
|
||||
.m_axi_rready(m_axi_rready)
|
||||
);
|
||||
|
||||
endmodule
|
326
rtl/axi_crossbar_addr.v
Normal file
326
rtl/axi_crossbar_addr.v
Normal file
@ -0,0 +1,326 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2018 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
// Language: Verilog 2001
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
/*
|
||||
* AXI4 crossbar address decode and admission control
|
||||
*/
|
||||
module axi_crossbar_addr #
|
||||
(
|
||||
parameter S = 0,
|
||||
parameter S_COUNT = 4,
|
||||
parameter M_COUNT = 4,
|
||||
parameter ADDR_WIDTH = 32,
|
||||
parameter ID_WIDTH = 8,
|
||||
parameter S_THREADS = 32'd2,
|
||||
parameter S_ACCEPT = 32'd16,
|
||||
parameter M_REGIONS = 1,
|
||||
parameter M_BASE_ADDR = {32'h03000000, 32'h02000000, 32'h01000000, 32'h00000000},
|
||||
parameter M_ADDR_WIDTH = {M_COUNT{{M_REGIONS{32'd24}}}},
|
||||
parameter M_CONNECT = {M_COUNT{{S_COUNT{1'b1}}}},
|
||||
parameter M_SECURE = {M_COUNT{1'b0}},
|
||||
parameter WC_OUTPUT = 0
|
||||
)
|
||||
(
|
||||
input wire clk,
|
||||
input wire rst,
|
||||
|
||||
/*
|
||||
* Address input
|
||||
*/
|
||||
input wire [ID_WIDTH-1:0] s_axi_aid,
|
||||
input wire [ADDR_WIDTH-1:0] s_axi_aaddr,
|
||||
input wire [2:0] s_axi_aprot,
|
||||
input wire [3:0] s_axi_aqos,
|
||||
input wire s_axi_avalid,
|
||||
output wire s_axi_aready,
|
||||
|
||||
/*
|
||||
* Address output
|
||||
*/
|
||||
output wire [3:0] m_axi_aregion,
|
||||
output wire [$clog2(M_COUNT)-1:0] m_select,
|
||||
output wire m_axi_avalid,
|
||||
input wire m_axi_aready,
|
||||
|
||||
/*
|
||||
* Write command output
|
||||
*/
|
||||
output wire [$clog2(M_COUNT)-1:0] m_wc_select,
|
||||
output wire m_wc_decerr,
|
||||
output wire m_wc_valid,
|
||||
input wire m_wc_ready,
|
||||
|
||||
/*
|
||||
* Reply command output
|
||||
*/
|
||||
output wire m_rc_decerr,
|
||||
output wire m_rc_valid,
|
||||
input wire m_rc_ready,
|
||||
|
||||
/*
|
||||
* Completion input
|
||||
*/
|
||||
input wire [ID_WIDTH-1:0] s_cpl_id,
|
||||
input wire s_cpl_valid
|
||||
);
|
||||
|
||||
parameter CL_S_COUNT = $clog2(S_COUNT);
|
||||
parameter CL_M_COUNT = $clog2(M_COUNT);
|
||||
|
||||
parameter S_INT_THREADS = S_THREADS > S_ACCEPT ? S_ACCEPT : S_THREADS;
|
||||
parameter CL_S_INT_THREADS = $clog2(S_INT_THREADS);
|
||||
parameter CL_S_ACCEPT = $clog2(S_ACCEPT);
|
||||
|
||||
integer i, j;
|
||||
|
||||
// check configuration
|
||||
initial begin
|
||||
if (S_ACCEPT < 1) begin
|
||||
$error("Error: need at least 1 accept");
|
||||
$finish;
|
||||
end
|
||||
|
||||
if (S_THREADS < 1) begin
|
||||
$error("Error: need at least 1 thread");
|
||||
$finish;
|
||||
end
|
||||
|
||||
if (S_THREADS > S_ACCEPT) begin
|
||||
$warning("Warning: requested thread count larger than accept count; limiting thread count to accept count");
|
||||
end
|
||||
|
||||
if (M_REGIONS < 1) begin
|
||||
$error("Error: need at least 1 region");
|
||||
$finish;
|
||||
end
|
||||
|
||||
for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin
|
||||
if (M_ADDR_WIDTH[i*32 +: 32] && (M_ADDR_WIDTH[i*32 +: 32] < 12 || M_ADDR_WIDTH[i*32 +: 32] > ADDR_WIDTH)) begin
|
||||
$error("Error: address width out of range");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin
|
||||
for (j = i+1; j < M_COUNT*M_REGIONS; j = j + 1) begin
|
||||
if (M_ADDR_WIDTH[i*32 +: 32] && M_ADDR_WIDTH[j*32 +: 32]) begin
|
||||
if (((M_BASE_ADDR[i*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[i*32 +: 32])) <= (M_BASE_ADDR[j*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[j*32 +: 32])))) && ((M_BASE_ADDR[j*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[j*32 +: 32])) <= (M_BASE_ADDR[i*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[i*32 +: 32]))))) begin
|
||||
$display("%d: %08x / %02d -- %08x-%08x", i, M_BASE_ADDR[i*ADDR_WIDTH +: ADDR_WIDTH], M_ADDR_WIDTH[i*32 +: 32], M_BASE_ADDR[i*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[i*32 +: 32]), M_BASE_ADDR[i*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[i*32 +: 32])));
|
||||
$display("%d: %08x / %02d -- %08x-%08x", j, M_BASE_ADDR[j*ADDR_WIDTH +: ADDR_WIDTH], M_ADDR_WIDTH[j*32 +: 32], M_BASE_ADDR[j*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[j*32 +: 32]), M_BASE_ADDR[j*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[j*32 +: 32])));
|
||||
$error("Error: address ranges overlap");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
localparam [2:0]
|
||||
STATE_IDLE = 3'd0,
|
||||
STATE_DECODE = 3'd1;
|
||||
|
||||
reg [2:0] state_reg = STATE_IDLE, state_next;
|
||||
|
||||
reg match;
|
||||
reg trans_start;
|
||||
reg trans_complete;
|
||||
|
||||
reg [$clog2(S_ACCEPT+1)-1:0] trans_count_reg = 0;
|
||||
wire trans_limit = trans_count_reg >= S_ACCEPT && !trans_complete;
|
||||
|
||||
// transfer ID thread tracking
|
||||
reg [ID_WIDTH-1:0] thread_id_reg[S_INT_THREADS-1:0];
|
||||
reg [CL_M_COUNT-1:0] thread_m_reg[S_INT_THREADS-1:0];
|
||||
reg [3:0] thread_region_reg[S_INT_THREADS-1:0];
|
||||
reg [$clog2(S_ACCEPT+1)-1:0] thread_count_reg[S_INT_THREADS-1:0];
|
||||
|
||||
wire [S_INT_THREADS-1:0] thread_active;
|
||||
wire [S_INT_THREADS-1:0] thread_match;
|
||||
wire [S_INT_THREADS-1:0] thread_cpl_match;
|
||||
wire [S_INT_THREADS-1:0] thread_trans_start;
|
||||
wire [S_INT_THREADS-1:0] thread_trans_complete;
|
||||
|
||||
generate
|
||||
genvar n;
|
||||
|
||||
for (n = 0; n < S_INT_THREADS; n = n + 1) begin
|
||||
initial begin
|
||||
thread_count_reg[n] <= 0;
|
||||
end
|
||||
|
||||
assign thread_active[n] = thread_count_reg[n] != 0;
|
||||
assign thread_match[n] = thread_active[n] && thread_id_reg[n] == s_axi_aid;
|
||||
assign thread_cpl_match[n] = thread_active[n] && thread_id_reg[n] == s_cpl_id;
|
||||
assign thread_trans_start[n] = (thread_match[n] || (!thread_active[n] && !thread_match && !(thread_trans_start & ({S_INT_THREADS{1'b1}} >> (S_INT_THREADS-n))))) && trans_start;
|
||||
assign thread_trans_complete[n] = thread_cpl_match[n] && trans_complete;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
thread_count_reg[n] <= 0;
|
||||
end else begin
|
||||
if (thread_trans_start[n] && !thread_trans_complete[n]) begin
|
||||
thread_count_reg[n] <= thread_count_reg[n] + 1;
|
||||
end else if (!thread_trans_start[n] && thread_trans_complete[n]) begin
|
||||
thread_count_reg[n] <= thread_count_reg[n] - 1;
|
||||
end
|
||||
end
|
||||
|
||||
if (thread_trans_start[n]) begin
|
||||
thread_id_reg[n] <= s_axi_aid;
|
||||
thread_m_reg[n] <= m_select_next;
|
||||
thread_region_reg[n] <= m_axi_aregion_next;
|
||||
end
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
reg s_axi_aready_reg = 0, s_axi_aready_next;
|
||||
|
||||
reg [3:0] m_axi_aregion_reg = 4'd0, m_axi_aregion_next;
|
||||
reg [CL_M_COUNT-1:0] m_select_reg = {CL_M_COUNT{1'b0}}, m_select_next;
|
||||
reg m_axi_avalid_reg = 1'b0, m_axi_avalid_next;
|
||||
reg m_decerr_reg = 1'b0, m_decerr_next;
|
||||
reg m_wc_valid_reg = 1'b0, m_wc_valid_next;
|
||||
reg m_rc_valid_reg = 1'b0, m_rc_valid_next;
|
||||
|
||||
assign s_axi_aready = s_axi_aready_reg;
|
||||
|
||||
assign m_axi_aregion = m_axi_aregion_reg;
|
||||
assign m_select = m_select_reg;
|
||||
assign m_axi_avalid = m_axi_avalid_reg;
|
||||
|
||||
assign m_wc_select = m_select_reg;
|
||||
assign m_wc_decerr = m_decerr_reg;
|
||||
assign m_wc_valid = m_wc_valid_reg;
|
||||
|
||||
assign m_rc_decerr = m_decerr_reg;
|
||||
assign m_rc_valid = m_rc_valid_reg;
|
||||
|
||||
always @* begin
|
||||
state_next = STATE_IDLE;
|
||||
|
||||
match = 1'b0;
|
||||
trans_start = 1'b0;
|
||||
trans_complete = 1'b0;
|
||||
|
||||
s_axi_aready_next = 1'b0;
|
||||
|
||||
m_axi_aregion_next = m_axi_aregion_reg;
|
||||
m_select_next = m_select_reg;
|
||||
m_select_next = m_select_reg;
|
||||
m_axi_avalid_next = m_axi_avalid_reg && !m_axi_aready;
|
||||
m_decerr_next = m_decerr_reg;
|
||||
m_wc_valid_next = m_wc_valid_reg && !m_wc_ready;
|
||||
m_rc_valid_next = m_rc_valid_reg && !m_rc_ready;
|
||||
|
||||
case (state_reg)
|
||||
STATE_IDLE: begin
|
||||
// idle state, store values
|
||||
s_axi_aready_next = 1'b0;
|
||||
|
||||
if (s_axi_avalid && !s_axi_aready) begin
|
||||
match = 1'b0;
|
||||
for (i = 0; i < M_COUNT; i = i + 1) begin
|
||||
for (j = 0; j < M_REGIONS; j = j + 1) begin
|
||||
if (M_ADDR_WIDTH[(i*M_REGIONS+j)*32 +: 32] && (!M_SECURE[i] || !s_axi_aprot[1]) && (M_CONNECT & (1 << (S+i*S_COUNT))) && (s_axi_aaddr >> M_ADDR_WIDTH[(i*M_REGIONS+j)*32 +: 32]) == (M_BASE_ADDR[(i*M_REGIONS+j)*ADDR_WIDTH +: ADDR_WIDTH] >> M_ADDR_WIDTH[(i*M_REGIONS+j)*32 +: 32])) begin
|
||||
m_select_next = i;
|
||||
m_axi_aregion_next = j;
|
||||
match = 1'b1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if (match) begin
|
||||
// address decode successful
|
||||
if (!trans_limit && (thread_match || !(&thread_active))) begin
|
||||
// transaction limit not reached
|
||||
m_axi_avalid_next = 1'b1;
|
||||
m_decerr_next = 1'b0;
|
||||
m_wc_valid_next = WC_OUTPUT;
|
||||
m_rc_valid_next = 1'b0;
|
||||
trans_start = 1'b1;
|
||||
state_next = STATE_DECODE;
|
||||
end else begin
|
||||
// transaction limit reached; block in idle
|
||||
state_next = STATE_IDLE;
|
||||
end
|
||||
end else begin
|
||||
// decode error
|
||||
m_axi_avalid_next = 1'b0;
|
||||
m_decerr_next = 1'b1;
|
||||
m_wc_valid_next = WC_OUTPUT;
|
||||
m_rc_valid_next = 1'b1;
|
||||
state_next = STATE_DECODE;
|
||||
end
|
||||
end else begin
|
||||
state_next = STATE_IDLE;
|
||||
end
|
||||
end
|
||||
STATE_DECODE: begin
|
||||
if (!m_axi_avalid_next && (!m_wc_valid_next || !WC_OUTPUT) && !m_rc_valid_next) begin
|
||||
s_axi_aready_next = 1'b1;
|
||||
state_next = STATE_IDLE;
|
||||
end else begin
|
||||
state_next = STATE_DECODE;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
|
||||
// manage completions
|
||||
trans_complete = s_cpl_valid;
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
state_reg <= STATE_IDLE;
|
||||
s_axi_aready_reg <= 1'b0;
|
||||
m_axi_avalid_reg <= 1'b0;
|
||||
m_wc_valid_reg <= 1'b0;
|
||||
m_rc_valid_reg <= 1'b0;
|
||||
|
||||
trans_count_reg <= 0;
|
||||
end else begin
|
||||
state_reg <= state_next;
|
||||
s_axi_aready_reg <= s_axi_aready_next;
|
||||
m_axi_avalid_reg <= m_axi_avalid_next;
|
||||
m_wc_valid_reg <= m_wc_valid_next;
|
||||
m_rc_valid_reg <= m_rc_valid_next;
|
||||
|
||||
if (trans_start && !trans_complete) begin
|
||||
trans_count_reg <= trans_count_reg + 1;
|
||||
end else if (!trans_start && trans_complete) begin
|
||||
trans_count_reg <= trans_count_reg - 1;
|
||||
end
|
||||
end
|
||||
|
||||
m_axi_aregion_reg <= m_axi_aregion_next;
|
||||
m_select_reg <= m_select_next;
|
||||
m_decerr_reg <= m_decerr_next;
|
||||
end
|
||||
|
||||
endmodule
|
527
rtl/axi_crossbar_rd.v
Normal file
527
rtl/axi_crossbar_rd.v
Normal file
@ -0,0 +1,527 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2018 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
// Language: Verilog 2001
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
/*
|
||||
* AXI4 crossbar (read)
|
||||
*/
|
||||
module axi_crossbar_rd #
|
||||
(
|
||||
parameter S_COUNT = 4,
|
||||
parameter M_COUNT = 4,
|
||||
parameter DATA_WIDTH = 32,
|
||||
parameter ADDR_WIDTH = 32,
|
||||
parameter STRB_WIDTH = (DATA_WIDTH/8),
|
||||
parameter S_ID_WIDTH = 8,
|
||||
parameter M_ID_WIDTH = S_ID_WIDTH+$clog2(S_COUNT),
|
||||
parameter ARUSER_ENABLE = 0,
|
||||
parameter ARUSER_WIDTH = 1,
|
||||
parameter RUSER_ENABLE = 0,
|
||||
parameter RUSER_WIDTH = 1,
|
||||
parameter S_THREADS = {S_COUNT{32'd2}},
|
||||
parameter S_ACCEPT = {S_COUNT{32'd16}},
|
||||
parameter M_REGIONS = 1,
|
||||
parameter M_BASE_ADDR = {32'h03000000, 32'h02000000, 32'h01000000, 32'h00000000},
|
||||
parameter M_ADDR_WIDTH = {M_COUNT{{M_REGIONS{32'd24}}}},
|
||||
parameter M_CONNECT = {M_COUNT{{S_COUNT{1'b1}}}},
|
||||
parameter M_ISSUE = {M_COUNT{32'd4}},
|
||||
parameter M_SECURE = {M_COUNT{1'b0}},
|
||||
parameter S_AR_REG_TYPE = {S_COUNT{2'd0}},
|
||||
parameter S_R_REG_TYPE = {S_COUNT{2'd2}},
|
||||
parameter M_AR_REG_TYPE = {M_COUNT{2'd1}},
|
||||
parameter M_R_REG_TYPE = {M_COUNT{2'd0}}
|
||||
)
|
||||
(
|
||||
input wire clk,
|
||||
input wire rst,
|
||||
|
||||
/*
|
||||
* AXI slave interfaces
|
||||
*/
|
||||
input wire [S_COUNT*S_ID_WIDTH-1:0] s_axi_arid,
|
||||
input wire [S_COUNT*ADDR_WIDTH-1:0] s_axi_araddr,
|
||||
input wire [S_COUNT*8-1:0] s_axi_arlen,
|
||||
input wire [S_COUNT*3-1:0] s_axi_arsize,
|
||||
input wire [S_COUNT*2-1:0] s_axi_arburst,
|
||||
input wire [S_COUNT-1:0] s_axi_arlock,
|
||||
input wire [S_COUNT*4-1:0] s_axi_arcache,
|
||||
input wire [S_COUNT*3-1:0] s_axi_arprot,
|
||||
input wire [S_COUNT*4-1:0] s_axi_arqos,
|
||||
input wire [S_COUNT*ARUSER_WIDTH-1:0] s_axi_aruser,
|
||||
input wire [S_COUNT-1:0] s_axi_arvalid,
|
||||
output wire [S_COUNT-1:0] s_axi_arready,
|
||||
output wire [S_COUNT*S_ID_WIDTH-1:0] s_axi_rid,
|
||||
output wire [S_COUNT*DATA_WIDTH-1:0] s_axi_rdata,
|
||||
output wire [S_COUNT*2-1:0] s_axi_rresp,
|
||||
output wire [S_COUNT-1:0] s_axi_rlast,
|
||||
output wire [S_COUNT*RUSER_WIDTH-1:0] s_axi_ruser,
|
||||
output wire [S_COUNT-1:0] s_axi_rvalid,
|
||||
input wire [S_COUNT-1:0] s_axi_rready,
|
||||
|
||||
/*
|
||||
* AXI master interfaces
|
||||
*/
|
||||
output wire [M_COUNT*M_ID_WIDTH-1:0] m_axi_arid,
|
||||
output wire [M_COUNT*ADDR_WIDTH-1:0] m_axi_araddr,
|
||||
output wire [M_COUNT*8-1:0] m_axi_arlen,
|
||||
output wire [M_COUNT*3-1:0] m_axi_arsize,
|
||||
output wire [M_COUNT*2-1:0] m_axi_arburst,
|
||||
output wire [M_COUNT-1:0] m_axi_arlock,
|
||||
output wire [M_COUNT*4-1:0] m_axi_arcache,
|
||||
output wire [M_COUNT*3-1:0] m_axi_arprot,
|
||||
output wire [M_COUNT*4-1:0] m_axi_arqos,
|
||||
output wire [M_COUNT*4-1:0] m_axi_arregion,
|
||||
output wire [M_COUNT*ARUSER_WIDTH-1:0] m_axi_aruser,
|
||||
output wire [M_COUNT-1:0] m_axi_arvalid,
|
||||
input wire [M_COUNT-1:0] m_axi_arready,
|
||||
input wire [M_COUNT*M_ID_WIDTH-1:0] m_axi_rid,
|
||||
input wire [M_COUNT*DATA_WIDTH-1:0] m_axi_rdata,
|
||||
input wire [M_COUNT*2-1:0] m_axi_rresp,
|
||||
input wire [M_COUNT-1:0] m_axi_rlast,
|
||||
input wire [M_COUNT*RUSER_WIDTH-1:0] m_axi_ruser,
|
||||
input wire [M_COUNT-1:0] m_axi_rvalid,
|
||||
output wire [M_COUNT-1:0] m_axi_rready
|
||||
);
|
||||
|
||||
parameter CL_S_COUNT = $clog2(S_COUNT);
|
||||
parameter CL_M_COUNT = $clog2(M_COUNT);
|
||||
parameter M_COUNT_P1 = M_COUNT+1;
|
||||
parameter CL_M_COUNT_P1 = $clog2(M_COUNT_P1);
|
||||
|
||||
integer i;
|
||||
|
||||
// check configuration
|
||||
initial begin
|
||||
if (M_ID_WIDTH < S_ID_WIDTH+$clog2(S_COUNT)) begin
|
||||
$error("Error: M_ID_WIDTH must be at least $clog2(S_COUNT) larger than S_ID_WIDTH");
|
||||
$finish;
|
||||
end
|
||||
|
||||
for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin
|
||||
if (M_ADDR_WIDTH[i*32 +: 32] && (M_ADDR_WIDTH[i*32 +: 32] < 12 || M_ADDR_WIDTH[i*32 +: 32] > ADDR_WIDTH)) begin
|
||||
$error("Error: value out of range");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
wire [S_COUNT*S_ID_WIDTH-1:0] int_s_axi_arid;
|
||||
wire [S_COUNT*ADDR_WIDTH-1:0] int_s_axi_araddr;
|
||||
wire [S_COUNT*8-1:0] int_s_axi_arlen;
|
||||
wire [S_COUNT*3-1:0] int_s_axi_arsize;
|
||||
wire [S_COUNT*2-1:0] int_s_axi_arburst;
|
||||
wire [S_COUNT-1:0] int_s_axi_arlock;
|
||||
wire [S_COUNT*4-1:0] int_s_axi_arcache;
|
||||
wire [S_COUNT*3-1:0] int_s_axi_arprot;
|
||||
wire [S_COUNT*4-1:0] int_s_axi_arqos;
|
||||
wire [S_COUNT*4-1:0] int_s_axi_arregion;
|
||||
wire [S_COUNT*ARUSER_WIDTH-1:0] int_s_axi_aruser;
|
||||
wire [S_COUNT-1:0] int_s_axi_arvalid;
|
||||
wire [S_COUNT-1:0] int_s_axi_arready;
|
||||
|
||||
wire [S_COUNT*M_COUNT-1:0] int_axi_arvalid;
|
||||
wire [M_COUNT*S_COUNT-1:0] int_axi_arready;
|
||||
|
||||
wire [M_COUNT*M_ID_WIDTH-1:0] int_m_axi_rid;
|
||||
wire [M_COUNT*DATA_WIDTH-1:0] int_m_axi_rdata;
|
||||
wire [M_COUNT*2-1:0] int_m_axi_rresp;
|
||||
wire [M_COUNT-1:0] int_m_axi_rlast;
|
||||
wire [M_COUNT*RUSER_WIDTH-1:0] int_m_axi_ruser;
|
||||
wire [M_COUNT-1:0] int_m_axi_rvalid;
|
||||
wire [M_COUNT-1:0] int_m_axi_rready;
|
||||
|
||||
wire [M_COUNT*S_COUNT-1:0] int_axi_rvalid;
|
||||
wire [S_COUNT*M_COUNT-1:0] int_axi_rready;
|
||||
|
||||
generate
|
||||
|
||||
genvar m, n;
|
||||
|
||||
for (m = 0; m < S_COUNT; m = m + 1) begin : s_ifaces
|
||||
// address decode and admission control
|
||||
wire [CL_M_COUNT-1:0] a_select;
|
||||
|
||||
wire m_axi_avalid;
|
||||
wire m_axi_aready;
|
||||
|
||||
wire m_rc_decerr;
|
||||
wire m_rc_valid;
|
||||
wire m_rc_ready;
|
||||
|
||||
wire [S_ID_WIDTH-1:0] s_cpl_id;
|
||||
wire s_cpl_valid;
|
||||
|
||||
axi_crossbar_addr #(
|
||||
.S(m),
|
||||
.S_COUNT(S_COUNT),
|
||||
.M_COUNT(M_COUNT),
|
||||
.ADDR_WIDTH(ADDR_WIDTH),
|
||||
.ID_WIDTH(S_ID_WIDTH),
|
||||
.S_THREADS(S_THREADS[m*32 +: 32]),
|
||||
.S_ACCEPT(S_ACCEPT[m*32 +: 32]),
|
||||
.M_REGIONS(M_REGIONS),
|
||||
.M_BASE_ADDR(M_BASE_ADDR),
|
||||
.M_ADDR_WIDTH(M_ADDR_WIDTH),
|
||||
.M_CONNECT(M_CONNECT),
|
||||
.M_SECURE(M_SECURE),
|
||||
.WC_OUTPUT(0)
|
||||
)
|
||||
addr_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
/*
|
||||
* Address input
|
||||
*/
|
||||
.s_axi_aid(int_s_axi_arid[m*S_ID_WIDTH +: S_ID_WIDTH]),
|
||||
.s_axi_aaddr(int_s_axi_araddr[m*ADDR_WIDTH +: ADDR_WIDTH]),
|
||||
.s_axi_aprot(int_s_axi_arprot[m*3 +: 3]),
|
||||
.s_axi_aqos(int_s_axi_arqos[m*4 +: 4]),
|
||||
.s_axi_avalid(int_s_axi_arvalid[m]),
|
||||
.s_axi_aready(int_s_axi_arready[m]),
|
||||
|
||||
/*
|
||||
* Address output
|
||||
*/
|
||||
.m_axi_aregion(int_s_axi_arregion[m*4 +: 4]),
|
||||
.m_select(a_select),
|
||||
.m_axi_avalid(m_axi_avalid),
|
||||
.m_axi_aready(m_axi_aready),
|
||||
|
||||
/*
|
||||
* Write command output
|
||||
*/
|
||||
.m_wc_select(),
|
||||
.m_wc_decerr(),
|
||||
.m_wc_valid(),
|
||||
.m_wc_ready(1'b1),
|
||||
|
||||
/*
|
||||
* Response command output
|
||||
*/
|
||||
.m_rc_decerr(m_rc_decerr),
|
||||
.m_rc_valid(m_rc_valid),
|
||||
.m_rc_ready(m_rc_ready),
|
||||
|
||||
/*
|
||||
* Completion input
|
||||
*/
|
||||
.s_cpl_id(s_cpl_id),
|
||||
.s_cpl_valid(s_cpl_valid)
|
||||
);
|
||||
|
||||
assign int_axi_arvalid[m*M_COUNT +: M_COUNT] = m_axi_avalid << a_select;
|
||||
assign m_axi_aready = int_axi_arready[a_select*S_COUNT+m];
|
||||
|
||||
// decode error handling
|
||||
reg [S_ID_WIDTH-1:0] decerr_m_axi_rid_reg = {S_ID_WIDTH{1'b0}}, decerr_m_axi_rid_next;
|
||||
reg decerr_m_axi_rlast_reg = 1'b0, decerr_m_axi_rlast_next;
|
||||
reg decerr_m_axi_rvalid_reg = 1'b0, decerr_m_axi_rvalid_next;
|
||||
wire decerr_m_axi_rready;
|
||||
|
||||
reg [7:0] decerr_len_reg = 8'd0, decerr_len_next;
|
||||
|
||||
assign m_rc_ready = !decerr_m_axi_rvalid_reg;
|
||||
|
||||
always @* begin
|
||||
decerr_len_next = decerr_len_reg;
|
||||
decerr_m_axi_rid_next = decerr_m_axi_rid_reg;
|
||||
decerr_m_axi_rlast_next = decerr_m_axi_rlast_reg;
|
||||
decerr_m_axi_rvalid_next = decerr_m_axi_rvalid_reg;
|
||||
|
||||
if (decerr_m_axi_rvalid_reg) begin
|
||||
if (decerr_m_axi_rready) begin
|
||||
if (decerr_len_reg > 0) begin
|
||||
decerr_len_next = decerr_len_reg-1;
|
||||
decerr_m_axi_rlast_next = (decerr_len_next == 0);
|
||||
decerr_m_axi_rvalid_next = 1'b1;
|
||||
end else begin
|
||||
decerr_m_axi_rvalid_next = 1'b0;
|
||||
end
|
||||
end
|
||||
end else if (m_rc_valid && m_rc_ready) begin
|
||||
decerr_len_next = int_s_axi_arlen[m*8 +: 8];
|
||||
decerr_m_axi_rid_next = int_s_axi_arid[m*S_ID_WIDTH +: S_ID_WIDTH];
|
||||
decerr_m_axi_rlast_next = (decerr_len_next == 0);
|
||||
decerr_m_axi_rvalid_next = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
decerr_m_axi_rvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
decerr_m_axi_rvalid_reg <= decerr_m_axi_rvalid_next;
|
||||
end
|
||||
|
||||
decerr_m_axi_rid_reg <= decerr_m_axi_rid_next;
|
||||
decerr_m_axi_rlast_reg <= decerr_m_axi_rlast_next;
|
||||
decerr_len_reg <= decerr_len_next;
|
||||
end
|
||||
|
||||
// read response arbitration
|
||||
wire [M_COUNT_P1-1:0] r_request;
|
||||
wire [M_COUNT_P1-1:0] r_acknowledge;
|
||||
wire [M_COUNT_P1-1:0] r_grant;
|
||||
wire r_grant_valid;
|
||||
wire [CL_M_COUNT_P1-1:0] r_grant_encoded;
|
||||
|
||||
arbiter #(
|
||||
.PORTS(M_COUNT_P1),
|
||||
.TYPE("ROUND_ROBIN"),
|
||||
.BLOCK("ACKNOWLEDGE"),
|
||||
.LSB_PRIORITY("HIGH")
|
||||
)
|
||||
r_arb_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.request(r_request),
|
||||
.acknowledge(r_acknowledge),
|
||||
.grant(r_grant),
|
||||
.grant_valid(r_grant_valid),
|
||||
.grant_encoded(r_grant_encoded)
|
||||
);
|
||||
|
||||
// read response mux
|
||||
wire [S_ID_WIDTH-1:0] m_axi_rid_mux = {decerr_m_axi_rid_reg, int_m_axi_rid} >> r_grant_encoded*M_ID_WIDTH;
|
||||
wire [DATA_WIDTH-1:0] m_axi_rdata_mux = {{DATA_WIDTH{1'b0}}, int_m_axi_rdata} >> r_grant_encoded*DATA_WIDTH;
|
||||
wire [1:0] m_axi_rresp_mux = {2'b11, int_m_axi_rresp} >> r_grant_encoded*2;
|
||||
wire m_axi_rlast_mux = {decerr_m_axi_rlast_reg, int_m_axi_rlast} >> r_grant_encoded;
|
||||
wire [RUSER_WIDTH-1:0] m_axi_ruser_mux = {{RUSER_WIDTH{1'b0}}, int_m_axi_ruser} >> r_grant_encoded*RUSER_WIDTH;
|
||||
wire m_axi_rvalid_mux = ({decerr_m_axi_rvalid_reg, int_m_axi_rvalid} >> r_grant_encoded) && r_grant_valid;
|
||||
wire m_axi_rready_mux;
|
||||
|
||||
assign int_axi_rready[m*M_COUNT +: M_COUNT] = (r_grant_valid && m_axi_rready_mux) << r_grant_encoded;
|
||||
assign decerr_m_axi_rready = (r_grant_valid && m_axi_rready_mux) && (r_grant_encoded == M_COUNT_P1-1);
|
||||
|
||||
for (n = 0; n < M_COUNT; n = n + 1) begin
|
||||
assign r_request[n] = int_axi_rvalid[n*S_COUNT+m] && !r_grant[n];
|
||||
assign r_acknowledge[n] = r_grant[n] && int_axi_rvalid[n*S_COUNT+m] && m_axi_rlast_mux && m_axi_rready_mux;
|
||||
end
|
||||
|
||||
assign r_request[M_COUNT_P1-1] = decerr_m_axi_rvalid_reg && !r_grant[M_COUNT_P1-1];
|
||||
assign r_acknowledge[M_COUNT_P1-1] = r_grant[M_COUNT_P1-1] && decerr_m_axi_rvalid_reg && decerr_m_axi_rlast_reg && m_axi_rready_mux;
|
||||
|
||||
assign s_cpl_id = m_axi_rid_mux;
|
||||
assign s_cpl_valid = m_axi_rvalid_mux && m_axi_rready_mux && m_axi_rlast_mux;
|
||||
|
||||
// S side register
|
||||
axi_register_rd #(
|
||||
.DATA_WIDTH(DATA_WIDTH),
|
||||
.ADDR_WIDTH(ADDR_WIDTH),
|
||||
.STRB_WIDTH(STRB_WIDTH),
|
||||
.ID_WIDTH(S_ID_WIDTH),
|
||||
.ARUSER_ENABLE(ARUSER_ENABLE),
|
||||
.ARUSER_WIDTH(ARUSER_WIDTH),
|
||||
.RUSER_ENABLE(RUSER_ENABLE),
|
||||
.RUSER_WIDTH(RUSER_WIDTH),
|
||||
.AR_REG_TYPE(S_AR_REG_TYPE),
|
||||
.R_REG_TYPE(S_R_REG_TYPE)
|
||||
)
|
||||
reg_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.s_axi_arid(s_axi_arid[m*S_ID_WIDTH +: S_ID_WIDTH]),
|
||||
.s_axi_araddr(s_axi_araddr[m*ADDR_WIDTH +: ADDR_WIDTH]),
|
||||
.s_axi_arlen(s_axi_arlen[m*8 +: 8]),
|
||||
.s_axi_arsize(s_axi_arsize[m*3 +: 3]),
|
||||
.s_axi_arburst(s_axi_arburst[m*2 +: 2]),
|
||||
.s_axi_arlock(s_axi_arlock[m]),
|
||||
.s_axi_arcache(s_axi_arcache[m*4 +: 4]),
|
||||
.s_axi_arprot(s_axi_arprot[m*3 +: 3]),
|
||||
.s_axi_arqos(s_axi_arqos[m*4 +: 4]),
|
||||
.s_axi_arregion(4'd0),
|
||||
.s_axi_aruser(s_axi_aruser[m*ARUSER_WIDTH +: ARUSER_WIDTH]),
|
||||
.s_axi_arvalid(s_axi_arvalid[m]),
|
||||
.s_axi_arready(s_axi_arready[m]),
|
||||
.s_axi_rid(s_axi_rid[m*S_ID_WIDTH +: S_ID_WIDTH]),
|
||||
.s_axi_rdata(s_axi_rdata[m*DATA_WIDTH +: DATA_WIDTH]),
|
||||
.s_axi_rresp(s_axi_rresp[m*2 +: 2]),
|
||||
.s_axi_rlast(s_axi_rlast[m]),
|
||||
.s_axi_ruser(s_axi_ruser[m*RUSER_WIDTH +: RUSER_WIDTH]),
|
||||
.s_axi_rvalid(s_axi_rvalid[m]),
|
||||
.s_axi_rready(s_axi_rready[m]),
|
||||
.m_axi_arid(int_s_axi_arid[m*S_ID_WIDTH +: S_ID_WIDTH]),
|
||||
.m_axi_araddr(int_s_axi_araddr[m*ADDR_WIDTH +: ADDR_WIDTH]),
|
||||
.m_axi_arlen(int_s_axi_arlen[m*8 +: 8]),
|
||||
.m_axi_arsize(int_s_axi_arsize[m*3 +: 3]),
|
||||
.m_axi_arburst(int_s_axi_arburst[m*2 +: 2]),
|
||||
.m_axi_arlock(int_s_axi_arlock[m]),
|
||||
.m_axi_arcache(int_s_axi_arcache[m*4 +: 4]),
|
||||
.m_axi_arprot(int_s_axi_arprot[m*3 +: 3]),
|
||||
.m_axi_arqos(int_s_axi_arqos[m*4 +: 4]),
|
||||
.m_axi_arregion(),
|
||||
.m_axi_aruser(int_s_axi_aruser[m*ARUSER_WIDTH +: ARUSER_WIDTH]),
|
||||
.m_axi_arvalid(int_s_axi_arvalid[m]),
|
||||
.m_axi_arready(int_s_axi_arready[m]),
|
||||
.m_axi_rid(m_axi_rid_mux),
|
||||
.m_axi_rdata(m_axi_rdata_mux),
|
||||
.m_axi_rresp(m_axi_rresp_mux),
|
||||
.m_axi_rlast(m_axi_rlast_mux),
|
||||
.m_axi_ruser(m_axi_ruser_mux),
|
||||
.m_axi_rvalid(m_axi_rvalid_mux),
|
||||
.m_axi_rready(m_axi_rready_mux)
|
||||
);
|
||||
end // s_ifaces
|
||||
|
||||
for (n = 0; n < M_COUNT; n = n + 1) begin : m_ifaces
|
||||
// in-flight transaction count
|
||||
wire trans_start;
|
||||
wire trans_complete;
|
||||
reg [$clog2(M_ISSUE[n*32 +: 32]+1)-1:0] trans_count_reg = 0;
|
||||
|
||||
wire trans_limit = trans_count_reg >= M_ISSUE[n*32 +: 32] && !trans_complete;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
trans_count_reg <= 0;
|
||||
end else begin
|
||||
if (trans_start && !trans_complete) begin
|
||||
trans_count_reg <= trans_count_reg + 1;
|
||||
end else if (!trans_start && trans_complete) begin
|
||||
trans_count_reg <= trans_count_reg - 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// address arbitration
|
||||
wire [S_COUNT-1:0] a_request;
|
||||
wire [S_COUNT-1:0] a_acknowledge;
|
||||
wire [S_COUNT-1:0] a_grant;
|
||||
wire a_grant_valid;
|
||||
wire [CL_S_COUNT-1:0] a_grant_encoded;
|
||||
|
||||
arbiter #(
|
||||
.PORTS(S_COUNT),
|
||||
.TYPE("ROUND_ROBIN"),
|
||||
.BLOCK("ACKNOWLEDGE"),
|
||||
.LSB_PRIORITY("HIGH")
|
||||
)
|
||||
a_arb_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.request(a_request),
|
||||
.acknowledge(a_acknowledge),
|
||||
.grant(a_grant),
|
||||
.grant_valid(a_grant_valid),
|
||||
.grant_encoded(a_grant_encoded)
|
||||
);
|
||||
|
||||
// address mux
|
||||
wire [M_ID_WIDTH-1:0] s_axi_arid_mux = int_s_axi_arid[a_grant_encoded*S_ID_WIDTH +: S_ID_WIDTH] | (a_grant_encoded << S_ID_WIDTH);
|
||||
wire [ADDR_WIDTH-1:0] s_axi_araddr_mux = int_s_axi_araddr[a_grant_encoded*ADDR_WIDTH +: ADDR_WIDTH];
|
||||
wire [7:0] s_axi_arlen_mux = int_s_axi_arlen[a_grant_encoded*8 +: 8];
|
||||
wire [2:0] s_axi_arsize_mux = int_s_axi_arsize[a_grant_encoded*3 +: 3];
|
||||
wire [1:0] s_axi_arburst_mux = int_s_axi_arburst[a_grant_encoded*2 +: 2];
|
||||
wire s_axi_arlock_mux = int_s_axi_arlock[a_grant_encoded];
|
||||
wire [3:0] s_axi_arcache_mux = int_s_axi_arcache[a_grant_encoded*4 +: 4];
|
||||
wire [2:0] s_axi_arprot_mux = int_s_axi_arprot[a_grant_encoded*3 +: 3];
|
||||
wire [3:0] s_axi_arqos_mux = int_s_axi_arqos[a_grant_encoded*4 +: 4];
|
||||
wire [3:0] s_axi_arregion_mux = int_s_axi_arregion[a_grant_encoded*4 +: 4];
|
||||
wire [ARUSER_WIDTH-1:0] s_axi_aruser_mux = int_s_axi_aruser[a_grant_encoded*ARUSER_WIDTH +: ARUSER_WIDTH];
|
||||
wire s_axi_arvalid_mux = int_axi_arvalid[a_grant_encoded*M_COUNT+n] && a_grant_valid;
|
||||
wire s_axi_arready_mux;
|
||||
|
||||
assign int_axi_arready[n*S_COUNT +: S_COUNT] = (a_grant_valid && s_axi_arready_mux) << a_grant_encoded;
|
||||
|
||||
for (m = 0; m < S_COUNT; m = m + 1) begin
|
||||
assign a_request[m] = int_axi_arvalid[m*M_COUNT+n] && !a_grant[m] && !trans_limit;
|
||||
assign a_acknowledge[m] = a_grant[m] && int_axi_arvalid[m*M_COUNT+n] && s_axi_arready_mux;
|
||||
end
|
||||
|
||||
assign trans_start = s_axi_arvalid_mux && s_axi_arready_mux && a_grant_valid;
|
||||
|
||||
// read response forwarding
|
||||
wire [CL_S_COUNT-1:0] r_select = m_axi_rid[n*M_ID_WIDTH +: M_ID_WIDTH] >> S_ID_WIDTH;
|
||||
|
||||
assign int_axi_rvalid[n*S_COUNT +: S_COUNT] = int_m_axi_rvalid[n] << r_select;
|
||||
assign int_m_axi_rready[n] = int_axi_rready[r_select*M_COUNT+n];
|
||||
|
||||
assign trans_complete = int_m_axi_rvalid[n] && int_m_axi_rready[n] && int_m_axi_rlast[n];
|
||||
|
||||
// M side register
|
||||
axi_register_rd #(
|
||||
.DATA_WIDTH(DATA_WIDTH),
|
||||
.ADDR_WIDTH(ADDR_WIDTH),
|
||||
.STRB_WIDTH(STRB_WIDTH),
|
||||
.ID_WIDTH(M_ID_WIDTH),
|
||||
.ARUSER_ENABLE(ARUSER_ENABLE),
|
||||
.ARUSER_WIDTH(ARUSER_WIDTH),
|
||||
.RUSER_ENABLE(RUSER_ENABLE),
|
||||
.RUSER_WIDTH(RUSER_WIDTH),
|
||||
.AR_REG_TYPE(M_AR_REG_TYPE),
|
||||
.R_REG_TYPE(M_R_REG_TYPE)
|
||||
)
|
||||
reg_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.s_axi_arid(s_axi_arid_mux),
|
||||
.s_axi_araddr(s_axi_araddr_mux),
|
||||
.s_axi_arlen(s_axi_arlen_mux),
|
||||
.s_axi_arsize(s_axi_arsize_mux),
|
||||
.s_axi_arburst(s_axi_arburst_mux),
|
||||
.s_axi_arlock(s_axi_arlock_mux),
|
||||
.s_axi_arcache(s_axi_arcache_mux),
|
||||
.s_axi_arprot(s_axi_arprot_mux),
|
||||
.s_axi_arqos(s_axi_arqos_mux),
|
||||
.s_axi_arregion(s_axi_arregion_mux),
|
||||
.s_axi_aruser(s_axi_aruser_mux),
|
||||
.s_axi_arvalid(s_axi_arvalid_mux),
|
||||
.s_axi_arready(s_axi_arready_mux),
|
||||
.s_axi_rid(int_m_axi_rid[n*M_ID_WIDTH +: M_ID_WIDTH]),
|
||||
.s_axi_rdata(int_m_axi_rdata[n*DATA_WIDTH +: DATA_WIDTH]),
|
||||
.s_axi_rresp(int_m_axi_rresp[n*2 +: 2]),
|
||||
.s_axi_rlast(int_m_axi_rlast[n]),
|
||||
.s_axi_ruser(int_m_axi_ruser[n*RUSER_WIDTH +: RUSER_WIDTH]),
|
||||
.s_axi_rvalid(int_m_axi_rvalid[n]),
|
||||
.s_axi_rready(int_m_axi_rready[n]),
|
||||
.m_axi_arid(m_axi_arid[n*M_ID_WIDTH +: M_ID_WIDTH]),
|
||||
.m_axi_araddr(m_axi_araddr[n*ADDR_WIDTH +: ADDR_WIDTH]),
|
||||
.m_axi_arlen(m_axi_arlen[n*8 +: 8]),
|
||||
.m_axi_arsize(m_axi_arsize[n*3 +: 3]),
|
||||
.m_axi_arburst(m_axi_arburst[n*2 +: 2]),
|
||||
.m_axi_arlock(m_axi_arlock[n]),
|
||||
.m_axi_arcache(m_axi_arcache[n*4 +: 4]),
|
||||
.m_axi_arprot(m_axi_arprot[n*3 +: 3]),
|
||||
.m_axi_arqos(m_axi_arqos[n*4 +: 4]),
|
||||
.m_axi_arregion(m_axi_arregion[n*4 +: 4]),
|
||||
.m_axi_aruser(m_axi_aruser[n*ARUSER_WIDTH +: ARUSER_WIDTH]),
|
||||
.m_axi_arvalid(m_axi_arvalid[n]),
|
||||
.m_axi_arready(m_axi_arready[n]),
|
||||
.m_axi_rid(m_axi_rid[n*M_ID_WIDTH +: M_ID_WIDTH]),
|
||||
.m_axi_rdata(m_axi_rdata[n*DATA_WIDTH +: DATA_WIDTH]),
|
||||
.m_axi_rresp(m_axi_rresp[n*2 +: 2]),
|
||||
.m_axi_rlast(m_axi_rlast[n]),
|
||||
.m_axi_ruser(m_axi_ruser[n*RUSER_WIDTH +: RUSER_WIDTH]),
|
||||
.m_axi_rvalid(m_axi_rvalid[n]),
|
||||
.m_axi_rready(m_axi_rready[n])
|
||||
);
|
||||
end // m_ifaces
|
||||
|
||||
endgenerate
|
||||
|
||||
endmodule
|
630
rtl/axi_crossbar_wr.v
Normal file
630
rtl/axi_crossbar_wr.v
Normal file
@ -0,0 +1,630 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2018 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
// Language: Verilog 2001
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
/*
|
||||
* AXI4 crossbar (write)
|
||||
*/
|
||||
module axi_crossbar_wr #
|
||||
(
|
||||
parameter S_COUNT = 4,
|
||||
parameter M_COUNT = 4,
|
||||
parameter DATA_WIDTH = 32,
|
||||
parameter ADDR_WIDTH = 32,
|
||||
parameter STRB_WIDTH = (DATA_WIDTH/8),
|
||||
parameter S_ID_WIDTH = 8,
|
||||
parameter M_ID_WIDTH = S_ID_WIDTH+$clog2(S_COUNT),
|
||||
parameter AWUSER_ENABLE = 0,
|
||||
parameter AWUSER_WIDTH = 1,
|
||||
parameter WUSER_ENABLE = 0,
|
||||
parameter WUSER_WIDTH = 1,
|
||||
parameter BUSER_ENABLE = 0,
|
||||
parameter BUSER_WIDTH = 1,
|
||||
parameter S_THREADS = {S_COUNT{32'd2}},
|
||||
parameter S_ACCEPT = {S_COUNT{32'd16}},
|
||||
parameter M_REGIONS = 1,
|
||||
parameter M_BASE_ADDR = {32'h03000000, 32'h02000000, 32'h01000000, 32'h00000000},
|
||||
parameter M_ADDR_WIDTH = {M_COUNT{{M_REGIONS{32'd24}}}},
|
||||
parameter M_CONNECT = {M_COUNT{{S_COUNT{1'b1}}}},
|
||||
parameter M_ISSUE = {M_COUNT{32'd4}},
|
||||
parameter M_SECURE = {M_COUNT{1'b0}},
|
||||
parameter S_AW_REG_TYPE = {S_COUNT{2'd0}},
|
||||
parameter S_W_REG_TYPE = {S_COUNT{2'd0}},
|
||||
parameter S_B_REG_TYPE = {S_COUNT{2'd1}},
|
||||
parameter M_AW_REG_TYPE = {M_COUNT{2'd1}},
|
||||
parameter M_W_REG_TYPE = {M_COUNT{2'd2}},
|
||||
parameter M_B_REG_TYPE = {M_COUNT{2'd0}}
|
||||
)
|
||||
(
|
||||
input wire clk,
|
||||
input wire rst,
|
||||
|
||||
/*
|
||||
* AXI slave interfaces
|
||||
*/
|
||||
input wire [S_COUNT*S_ID_WIDTH-1:0] s_axi_awid,
|
||||
input wire [S_COUNT*ADDR_WIDTH-1:0] s_axi_awaddr,
|
||||
input wire [S_COUNT*8-1:0] s_axi_awlen,
|
||||
input wire [S_COUNT*3-1:0] s_axi_awsize,
|
||||
input wire [S_COUNT*2-1:0] s_axi_awburst,
|
||||
input wire [S_COUNT-1:0] s_axi_awlock,
|
||||
input wire [S_COUNT*4-1:0] s_axi_awcache,
|
||||
input wire [S_COUNT*3-1:0] s_axi_awprot,
|
||||
input wire [S_COUNT*4-1:0] s_axi_awqos,
|
||||
input wire [S_COUNT*AWUSER_WIDTH-1:0] s_axi_awuser,
|
||||
input wire [S_COUNT-1:0] s_axi_awvalid,
|
||||
output wire [S_COUNT-1:0] s_axi_awready,
|
||||
input wire [S_COUNT*DATA_WIDTH-1:0] s_axi_wdata,
|
||||
input wire [S_COUNT*STRB_WIDTH-1:0] s_axi_wstrb,
|
||||
input wire [S_COUNT-1:0] s_axi_wlast,
|
||||
input wire [S_COUNT*WUSER_WIDTH-1:0] s_axi_wuser,
|
||||
input wire [S_COUNT-1:0] s_axi_wvalid,
|
||||
output wire [S_COUNT-1:0] s_axi_wready,
|
||||
output wire [S_COUNT*S_ID_WIDTH-1:0] s_axi_bid,
|
||||
output wire [S_COUNT*2-1:0] s_axi_bresp,
|
||||
output wire [S_COUNT*BUSER_WIDTH-1:0] s_axi_buser,
|
||||
output wire [S_COUNT-1:0] s_axi_bvalid,
|
||||
input wire [S_COUNT-1:0] s_axi_bready,
|
||||
|
||||
/*
|
||||
* AXI master interfaces
|
||||
*/
|
||||
output wire [M_COUNT*M_ID_WIDTH-1:0] m_axi_awid,
|
||||
output wire [M_COUNT*ADDR_WIDTH-1:0] m_axi_awaddr,
|
||||
output wire [M_COUNT*8-1:0] m_axi_awlen,
|
||||
output wire [M_COUNT*3-1:0] m_axi_awsize,
|
||||
output wire [M_COUNT*2-1:0] m_axi_awburst,
|
||||
output wire [M_COUNT-1:0] m_axi_awlock,
|
||||
output wire [M_COUNT*4-1:0] m_axi_awcache,
|
||||
output wire [M_COUNT*3-1:0] m_axi_awprot,
|
||||
output wire [M_COUNT*4-1:0] m_axi_awqos,
|
||||
output wire [M_COUNT*4-1:0] m_axi_awregion,
|
||||
output wire [M_COUNT*AWUSER_WIDTH-1:0] m_axi_awuser,
|
||||
output wire [M_COUNT-1:0] m_axi_awvalid,
|
||||
input wire [M_COUNT-1:0] m_axi_awready,
|
||||
output wire [M_COUNT*DATA_WIDTH-1:0] m_axi_wdata,
|
||||
output wire [M_COUNT*STRB_WIDTH-1:0] m_axi_wstrb,
|
||||
output wire [M_COUNT-1:0] m_axi_wlast,
|
||||
output wire [M_COUNT*WUSER_WIDTH-1:0] m_axi_wuser,
|
||||
output wire [M_COUNT-1:0] m_axi_wvalid,
|
||||
input wire [M_COUNT-1:0] m_axi_wready,
|
||||
input wire [M_COUNT*M_ID_WIDTH-1:0] m_axi_bid,
|
||||
input wire [M_COUNT*2-1:0] m_axi_bresp,
|
||||
input wire [M_COUNT*BUSER_WIDTH-1:0] m_axi_buser,
|
||||
input wire [M_COUNT-1:0] m_axi_bvalid,
|
||||
output wire [M_COUNT-1:0] m_axi_bready
|
||||
);
|
||||
|
||||
parameter CL_S_COUNT = $clog2(S_COUNT);
|
||||
parameter CL_M_COUNT = $clog2(M_COUNT);
|
||||
parameter M_COUNT_P1 = M_COUNT+1;
|
||||
parameter CL_M_COUNT_P1 = $clog2(M_COUNT_P1);
|
||||
|
||||
integer i;
|
||||
|
||||
// check configuration
|
||||
initial begin
|
||||
if (M_ID_WIDTH < S_ID_WIDTH+$clog2(S_COUNT)) begin
|
||||
$error("Error: M_ID_WIDTH must be at least $clog2(S_COUNT) larger than S_ID_WIDTH");
|
||||
$finish;
|
||||
end
|
||||
|
||||
for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin
|
||||
if (M_ADDR_WIDTH[i*32 +: 32] && (M_ADDR_WIDTH[i*32 +: 32] < 12 || M_ADDR_WIDTH[i*32 +: 32] > ADDR_WIDTH)) begin
|
||||
$error("Error: value out of range");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
wire [S_COUNT*S_ID_WIDTH-1:0] int_s_axi_awid;
|
||||
wire [S_COUNT*ADDR_WIDTH-1:0] int_s_axi_awaddr;
|
||||
wire [S_COUNT*8-1:0] int_s_axi_awlen;
|
||||
wire [S_COUNT*3-1:0] int_s_axi_awsize;
|
||||
wire [S_COUNT*2-1:0] int_s_axi_awburst;
|
||||
wire [S_COUNT-1:0] int_s_axi_awlock;
|
||||
wire [S_COUNT*4-1:0] int_s_axi_awcache;
|
||||
wire [S_COUNT*3-1:0] int_s_axi_awprot;
|
||||
wire [S_COUNT*4-1:0] int_s_axi_awqos;
|
||||
wire [S_COUNT*4-1:0] int_s_axi_awregion;
|
||||
wire [S_COUNT*AWUSER_WIDTH-1:0] int_s_axi_awuser;
|
||||
wire [S_COUNT-1:0] int_s_axi_awvalid;
|
||||
wire [S_COUNT-1:0] int_s_axi_awready;
|
||||
|
||||
wire [S_COUNT*M_COUNT-1:0] int_axi_awvalid;
|
||||
wire [M_COUNT*S_COUNT-1:0] int_axi_awready;
|
||||
|
||||
wire [S_COUNT*DATA_WIDTH-1:0] int_s_axi_wdata;
|
||||
wire [S_COUNT*STRB_WIDTH-1:0] int_s_axi_wstrb;
|
||||
wire [S_COUNT-1:0] int_s_axi_wlast;
|
||||
wire [S_COUNT*WUSER_WIDTH-1:0] int_s_axi_wuser;
|
||||
wire [S_COUNT-1:0] int_s_axi_wvalid;
|
||||
wire [S_COUNT-1:0] int_s_axi_wready;
|
||||
|
||||
wire [S_COUNT*M_COUNT-1:0] int_axi_wvalid;
|
||||
wire [M_COUNT*S_COUNT-1:0] int_axi_wready;
|
||||
|
||||
wire [M_COUNT*M_ID_WIDTH-1:0] int_m_axi_bid;
|
||||
wire [M_COUNT*2-1:0] int_m_axi_bresp;
|
||||
wire [M_COUNT*BUSER_WIDTH-1:0] int_m_axi_buser;
|
||||
wire [M_COUNT-1:0] int_m_axi_bvalid;
|
||||
wire [M_COUNT-1:0] int_m_axi_bready;
|
||||
|
||||
wire [M_COUNT*S_COUNT-1:0] int_axi_bvalid;
|
||||
wire [S_COUNT*M_COUNT-1:0] int_axi_bready;
|
||||
|
||||
generate
|
||||
|
||||
genvar m, n;
|
||||
|
||||
for (m = 0; m < S_COUNT; m = m + 1) begin : s_ifaces
|
||||
// address decode and admission control
|
||||
wire [CL_M_COUNT-1:0] a_select;
|
||||
|
||||
wire m_axi_avalid;
|
||||
wire m_axi_aready;
|
||||
|
||||
wire [CL_M_COUNT-1:0] m_wc_select;
|
||||
wire m_wc_decerr;
|
||||
wire m_wc_valid;
|
||||
wire m_wc_ready;
|
||||
|
||||
wire m_rc_decerr;
|
||||
wire m_rc_valid;
|
||||
wire m_rc_ready;
|
||||
|
||||
wire [S_ID_WIDTH-1:0] s_cpl_id;
|
||||
wire s_cpl_valid;
|
||||
|
||||
axi_crossbar_addr #(
|
||||
.S(m),
|
||||
.S_COUNT(S_COUNT),
|
||||
.M_COUNT(M_COUNT),
|
||||
.ADDR_WIDTH(ADDR_WIDTH),
|
||||
.ID_WIDTH(S_ID_WIDTH),
|
||||
.S_THREADS(S_THREADS[m*32 +: 32]),
|
||||
.S_ACCEPT(S_ACCEPT[m*32 +: 32]),
|
||||
.M_REGIONS(M_REGIONS),
|
||||
.M_BASE_ADDR(M_BASE_ADDR),
|
||||
.M_ADDR_WIDTH(M_ADDR_WIDTH),
|
||||
.M_CONNECT(M_CONNECT),
|
||||
.M_SECURE(M_SECURE),
|
||||
.WC_OUTPUT(1)
|
||||
)
|
||||
addr_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
|
||||
/*
|
||||
* Address input
|
||||
*/
|
||||
.s_axi_aid(int_s_axi_awid[m*S_ID_WIDTH +: S_ID_WIDTH]),
|
||||
.s_axi_aaddr(int_s_axi_awaddr[m*ADDR_WIDTH +: ADDR_WIDTH]),
|
||||
.s_axi_aprot(int_s_axi_awprot[m*3 +: 3]),
|
||||
.s_axi_aqos(int_s_axi_awqos[m*4 +: 4]),
|
||||
.s_axi_avalid(int_s_axi_awvalid[m]),
|
||||
.s_axi_aready(int_s_axi_awready[m]),
|
||||
|
||||
/*
|
||||
* Address output
|
||||
*/
|
||||
.m_axi_aregion(int_s_axi_awregion[m*4 +: 4]),
|
||||
.m_select(a_select),
|
||||
.m_axi_avalid(m_axi_avalid),
|
||||
.m_axi_aready(m_axi_aready),
|
||||
|
||||
/*
|
||||
* Write command output
|
||||
*/
|
||||
.m_wc_select(m_wc_select),
|
||||
.m_wc_decerr(m_wc_decerr),
|
||||
.m_wc_valid(m_wc_valid),
|
||||
.m_wc_ready(m_wc_ready),
|
||||
|
||||
/*
|
||||
* Response command output
|
||||
*/
|
||||
.m_rc_decerr(m_rc_decerr),
|
||||
.m_rc_valid(m_rc_valid),
|
||||
.m_rc_ready(m_rc_ready),
|
||||
|
||||
/*
|
||||
* Completion input
|
||||
*/
|
||||
.s_cpl_id(s_cpl_id),
|
||||
.s_cpl_valid(s_cpl_valid)
|
||||
);
|
||||
|
||||
assign int_axi_awvalid[m*M_COUNT +: M_COUNT] = m_axi_avalid << a_select;
|
||||
assign m_axi_aready = int_axi_awready[a_select*S_COUNT+m];
|
||||
|
||||
// write command handling
|
||||
reg [CL_M_COUNT-1:0] w_select_reg = 0, w_select_next;
|
||||
reg w_drop_reg = 1'b0, w_drop_next;
|
||||
reg w_select_valid_reg = 1'b0, w_select_valid_next;
|
||||
|
||||
assign m_wc_ready = !w_select_valid_reg;
|
||||
|
||||
always @* begin
|
||||
w_select_next = w_select_reg;
|
||||
w_drop_next = w_drop_reg && !(int_s_axi_wvalid[m] && int_s_axi_wready[m] && int_s_axi_wlast[m]);
|
||||
w_select_valid_next = w_select_valid_reg && !(int_s_axi_wvalid[m] && int_s_axi_wready[m] && int_s_axi_wlast[m]);
|
||||
|
||||
if (m_wc_valid && !w_select_valid_reg) begin
|
||||
w_select_next = m_wc_select;
|
||||
w_drop_next = m_wc_decerr;
|
||||
w_select_valid_next = m_wc_valid;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
w_select_valid_reg <= 1'b0;
|
||||
end else begin
|
||||
w_select_valid_reg <= w_select_valid_next;
|
||||
end
|
||||
|
||||
w_select_reg <= w_select_next;
|
||||
w_drop_reg <= w_drop_next;
|
||||
end
|
||||
|
||||
// write data forwarding
|
||||
assign int_axi_wvalid[m*M_COUNT +: M_COUNT] = (int_s_axi_wvalid[m] && w_select_valid_reg && !w_drop_reg) << w_select_reg;
|
||||
assign int_s_axi_wready[m] = int_axi_wready[w_select_reg*S_COUNT+m] || w_drop_reg;
|
||||
|
||||
// decode error handling
|
||||
reg [S_ID_WIDTH-1:0] decerr_m_axi_bid_reg = {S_ID_WIDTH{1'b0}}, decerr_m_axi_bid_next;
|
||||
reg decerr_m_axi_bvalid_reg = 1'b0, decerr_m_axi_bvalid_next;
|
||||
wire decerr_m_axi_bready;
|
||||
|
||||
assign m_rc_ready = !decerr_m_axi_bvalid_reg;
|
||||
|
||||
always @* begin
|
||||
decerr_m_axi_bid_next = decerr_m_axi_bid_reg;
|
||||
decerr_m_axi_bvalid_next = decerr_m_axi_bvalid_reg;
|
||||
|
||||
if (decerr_m_axi_bvalid_reg) begin
|
||||
if (decerr_m_axi_bready) begin
|
||||
decerr_m_axi_bvalid_next = 1'b0;
|
||||
end
|
||||
end else if (m_rc_valid && m_rc_ready) begin
|
||||
decerr_m_axi_bid_next = int_s_axi_awid[m*S_ID_WIDTH +: S_ID_WIDTH];
|
||||
decerr_m_axi_bvalid_next = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
decerr_m_axi_bvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
decerr_m_axi_bvalid_reg <= decerr_m_axi_bvalid_next;
|
||||
end
|
||||
|
||||
decerr_m_axi_bid_reg <= decerr_m_axi_bid_next;
|
||||
end
|
||||
|
||||
// write response arbitration
|
||||
wire [M_COUNT_P1-1:0] b_request;
|
||||
wire [M_COUNT_P1-1:0] b_acknowledge;
|
||||
wire [M_COUNT_P1-1:0] b_grant;
|
||||
wire b_grant_valid;
|
||||
wire [CL_M_COUNT_P1-1:0] b_grant_encoded;
|
||||
|
||||
arbiter #(
|
||||
.PORTS(M_COUNT_P1),
|
||||
.TYPE("ROUND_ROBIN"),
|
||||
.BLOCK("ACKNOWLEDGE"),
|
||||
.LSB_PRIORITY("HIGH")
|
||||
)
|
||||
b_arb_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.request(b_request),
|
||||
.acknowledge(b_acknowledge),
|
||||
.grant(b_grant),
|
||||
.grant_valid(b_grant_valid),
|
||||
.grant_encoded(b_grant_encoded)
|
||||
);
|
||||
|
||||
// write response mux
|
||||
wire [S_ID_WIDTH-1:0] m_axi_bid_mux = {decerr_m_axi_bid_reg, int_m_axi_bid} >> b_grant_encoded*M_ID_WIDTH;
|
||||
wire [1:0] m_axi_bresp_mux = {2'b11, int_m_axi_bresp} >> b_grant_encoded*2;
|
||||
wire [BUSER_WIDTH-1:0] m_axi_buser_mux = {{BUSER_WIDTH{1'b0}}, int_m_axi_buser} >> b_grant_encoded*BUSER_WIDTH;
|
||||
wire m_axi_bvalid_mux = ({decerr_m_axi_bvalid_reg, int_m_axi_bvalid} >> b_grant_encoded) && b_grant_valid;
|
||||
wire m_axi_bready_mux;
|
||||
|
||||
assign int_axi_bready[m*M_COUNT +: M_COUNT] = (b_grant_valid && m_axi_bready_mux) << b_grant_encoded;
|
||||
assign decerr_m_axi_bready = (b_grant_valid && m_axi_bready_mux) && (b_grant_encoded == M_COUNT_P1-1);
|
||||
|
||||
for (n = 0; n < M_COUNT; n = n + 1) begin
|
||||
assign b_request[n] = int_axi_bvalid[n*S_COUNT+m] && !b_grant[n];
|
||||
assign b_acknowledge[n] = b_grant[n] && int_axi_bvalid[n*S_COUNT+m] && m_axi_bready_mux;
|
||||
end
|
||||
|
||||
assign b_request[M_COUNT_P1-1] = decerr_m_axi_bvalid_reg && !b_grant[M_COUNT_P1-1];
|
||||
assign b_acknowledge[M_COUNT_P1-1] = b_grant[M_COUNT_P1-1] && decerr_m_axi_bvalid_reg && m_axi_bready_mux;
|
||||
|
||||
assign s_cpl_id = m_axi_bid_mux;
|
||||
assign s_cpl_valid = m_axi_bvalid_mux && m_axi_bready_mux;
|
||||
|
||||
// S side register
|
||||
axi_register_wr #(
|
||||
.DATA_WIDTH(DATA_WIDTH),
|
||||
.ADDR_WIDTH(ADDR_WIDTH),
|
||||
.STRB_WIDTH(STRB_WIDTH),
|
||||
.ID_WIDTH(S_ID_WIDTH),
|
||||
.AWUSER_ENABLE(AWUSER_ENABLE),
|
||||
.AWUSER_WIDTH(AWUSER_WIDTH),
|
||||
.WUSER_ENABLE(WUSER_ENABLE),
|
||||
.WUSER_WIDTH(WUSER_WIDTH),
|
||||
.BUSER_ENABLE(BUSER_ENABLE),
|
||||
.BUSER_WIDTH(BUSER_WIDTH),
|
||||
.AW_REG_TYPE(S_AW_REG_TYPE[m*2 +: 2]),
|
||||
.W_REG_TYPE(S_W_REG_TYPE[m*2 +: 2]),
|
||||
.B_REG_TYPE(S_B_REG_TYPE[m*2 +: 2])
|
||||
)
|
||||
reg_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.s_axi_awid(s_axi_awid[m*S_ID_WIDTH +: S_ID_WIDTH]),
|
||||
.s_axi_awaddr(s_axi_awaddr[m*ADDR_WIDTH +: ADDR_WIDTH]),
|
||||
.s_axi_awlen(s_axi_awlen[m*8 +: 8]),
|
||||
.s_axi_awsize(s_axi_awsize[m*3 +: 3]),
|
||||
.s_axi_awburst(s_axi_awburst[m*2 +: 2]),
|
||||
.s_axi_awlock(s_axi_awlock[m]),
|
||||
.s_axi_awcache(s_axi_awcache[m*4 +: 4]),
|
||||
.s_axi_awprot(s_axi_awprot[m*3 +: 3]),
|
||||
.s_axi_awqos(s_axi_awqos[m*4 +: 4]),
|
||||
.s_axi_awregion(4'd0),
|
||||
.s_axi_awuser(s_axi_awuser[m*AWUSER_WIDTH +: AWUSER_WIDTH]),
|
||||
.s_axi_awvalid(s_axi_awvalid[m]),
|
||||
.s_axi_awready(s_axi_awready[m]),
|
||||
.s_axi_wdata(s_axi_wdata[m*DATA_WIDTH +: DATA_WIDTH]),
|
||||
.s_axi_wstrb(s_axi_wstrb[m*STRB_WIDTH +: STRB_WIDTH]),
|
||||
.s_axi_wlast(s_axi_wlast[m]),
|
||||
.s_axi_wuser(s_axi_wuser[m*WUSER_WIDTH +: WUSER_WIDTH]),
|
||||
.s_axi_wvalid(s_axi_wvalid[m]),
|
||||
.s_axi_wready(s_axi_wready[m]),
|
||||
.s_axi_bid(s_axi_bid[m*S_ID_WIDTH +: S_ID_WIDTH]),
|
||||
.s_axi_bresp(s_axi_bresp[m*2 +: 2]),
|
||||
.s_axi_buser(s_axi_buser[m*BUSER_WIDTH +: BUSER_WIDTH]),
|
||||
.s_axi_bvalid(s_axi_bvalid[m]),
|
||||
.s_axi_bready(s_axi_bready[m]),
|
||||
.m_axi_awid(int_s_axi_awid[m*S_ID_WIDTH +: S_ID_WIDTH]),
|
||||
.m_axi_awaddr(int_s_axi_awaddr[m*ADDR_WIDTH +: ADDR_WIDTH]),
|
||||
.m_axi_awlen(int_s_axi_awlen[m*8 +: 8]),
|
||||
.m_axi_awsize(int_s_axi_awsize[m*3 +: 3]),
|
||||
.m_axi_awburst(int_s_axi_awburst[m*2 +: 2]),
|
||||
.m_axi_awlock(int_s_axi_awlock[m]),
|
||||
.m_axi_awcache(int_s_axi_awcache[m*4 +: 4]),
|
||||
.m_axi_awprot(int_s_axi_awprot[m*3 +: 3]),
|
||||
.m_axi_awqos(int_s_axi_awqos[m*4 +: 4]),
|
||||
.m_axi_awregion(),
|
||||
.m_axi_awuser(int_s_axi_awuser[m*AWUSER_WIDTH +: AWUSER_WIDTH]),
|
||||
.m_axi_awvalid(int_s_axi_awvalid[m]),
|
||||
.m_axi_awready(int_s_axi_awready[m]),
|
||||
.m_axi_wdata(int_s_axi_wdata[m*DATA_WIDTH +: DATA_WIDTH]),
|
||||
.m_axi_wstrb(int_s_axi_wstrb[m*STRB_WIDTH +: STRB_WIDTH]),
|
||||
.m_axi_wlast(int_s_axi_wlast[m]),
|
||||
.m_axi_wuser(int_s_axi_wuser[m*WUSER_WIDTH +: WUSER_WIDTH]),
|
||||
.m_axi_wvalid(int_s_axi_wvalid[m]),
|
||||
.m_axi_wready(int_s_axi_wready[m]),
|
||||
.m_axi_bid(m_axi_bid_mux),
|
||||
.m_axi_bresp(m_axi_bresp_mux),
|
||||
.m_axi_buser(m_axi_buser_mux),
|
||||
.m_axi_bvalid(m_axi_bvalid_mux),
|
||||
.m_axi_bready(m_axi_bready_mux)
|
||||
);
|
||||
end // s_ifaces
|
||||
|
||||
for (n = 0; n < M_COUNT; n = n + 1) begin : m_ifaces
|
||||
// in-flight transaction count
|
||||
wire trans_start;
|
||||
wire trans_complete;
|
||||
reg [$clog2(M_ISSUE[n*32 +: 32]+1)-1:0] trans_count_reg = 0;
|
||||
|
||||
wire trans_limit = trans_count_reg >= M_ISSUE[n*32 +: 32] && !trans_complete;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
trans_count_reg <= 0;
|
||||
end else begin
|
||||
if (trans_start && !trans_complete) begin
|
||||
trans_count_reg <= trans_count_reg + 1;
|
||||
end else if (!trans_start && trans_complete) begin
|
||||
trans_count_reg <= trans_count_reg - 1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// address arbitration
|
||||
reg [CL_S_COUNT-1:0] w_select_reg = 0, w_select_next;
|
||||
reg w_select_valid_reg = 1'b0, w_select_valid_next;
|
||||
reg w_select_new_reg = 1'b0, w_select_new_next;
|
||||
|
||||
wire [S_COUNT-1:0] a_request;
|
||||
wire [S_COUNT-1:0] a_acknowledge;
|
||||
wire [S_COUNT-1:0] a_grant;
|
||||
wire a_grant_valid;
|
||||
wire [CL_S_COUNT-1:0] a_grant_encoded;
|
||||
|
||||
arbiter #(
|
||||
.PORTS(S_COUNT),
|
||||
.TYPE("ROUND_ROBIN"),
|
||||
.BLOCK("ACKNOWLEDGE"),
|
||||
.LSB_PRIORITY("HIGH")
|
||||
)
|
||||
a_arb_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.request(a_request),
|
||||
.acknowledge(a_acknowledge),
|
||||
.grant(a_grant),
|
||||
.grant_valid(a_grant_valid),
|
||||
.grant_encoded(a_grant_encoded)
|
||||
);
|
||||
|
||||
// address mux
|
||||
wire [M_ID_WIDTH-1:0] s_axi_awid_mux = int_s_axi_awid[a_grant_encoded*S_ID_WIDTH +: S_ID_WIDTH] | (a_grant_encoded << S_ID_WIDTH);
|
||||
wire [ADDR_WIDTH-1:0] s_axi_awaddr_mux = int_s_axi_awaddr[a_grant_encoded*ADDR_WIDTH +: ADDR_WIDTH];
|
||||
wire [7:0] s_axi_awlen_mux = int_s_axi_awlen[a_grant_encoded*8 +: 8];
|
||||
wire [2:0] s_axi_awsize_mux = int_s_axi_awsize[a_grant_encoded*3 +: 3];
|
||||
wire [1:0] s_axi_awburst_mux = int_s_axi_awburst[a_grant_encoded*2 +: 2];
|
||||
wire s_axi_awlock_mux = int_s_axi_awlock[a_grant_encoded];
|
||||
wire [3:0] s_axi_awcache_mux = int_s_axi_awcache[a_grant_encoded*4 +: 4];
|
||||
wire [2:0] s_axi_awprot_mux = int_s_axi_awprot[a_grant_encoded*3 +: 3];
|
||||
wire [3:0] s_axi_awqos_mux = int_s_axi_awqos[a_grant_encoded*4 +: 4];
|
||||
wire [3:0] s_axi_awregion_mux = int_s_axi_awregion[a_grant_encoded*4 +: 4];
|
||||
wire [AWUSER_WIDTH-1:0] s_axi_awuser_mux = int_s_axi_awuser[a_grant_encoded*AWUSER_WIDTH +: AWUSER_WIDTH];
|
||||
wire s_axi_awvalid_mux = int_axi_awvalid[a_grant_encoded*M_COUNT+n] && a_grant_valid;
|
||||
wire s_axi_awready_mux;
|
||||
|
||||
assign int_axi_awready[n*S_COUNT +: S_COUNT] = (a_grant_valid && s_axi_awready_mux) << a_grant_encoded;
|
||||
|
||||
for (m = 0; m < S_COUNT; m = m + 1) begin
|
||||
assign a_request[m] = int_axi_awvalid[m*M_COUNT+n] && !a_grant[m] && !trans_limit && !w_select_valid_next;
|
||||
assign a_acknowledge[m] = a_grant[m] && int_axi_awvalid[m*M_COUNT+n] && s_axi_awready_mux;
|
||||
end
|
||||
|
||||
assign trans_start = s_axi_awvalid_mux && s_axi_awready_mux && a_grant_valid;
|
||||
|
||||
// write data routing
|
||||
always @* begin
|
||||
w_select_next = w_select_reg;
|
||||
w_select_valid_next = w_select_valid_reg && !(s_axi_wvalid_mux && s_axi_wready_mux && s_axi_wlast_mux);
|
||||
w_select_new_next = w_select_new_reg || !a_grant_valid || a_acknowledge;
|
||||
|
||||
if (a_grant_valid && !w_select_valid_reg && w_select_new_reg) begin
|
||||
w_select_next = a_grant_encoded;
|
||||
w_select_valid_next = a_grant_valid;
|
||||
w_select_new_next = 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
w_select_valid_reg <= 1'b0;
|
||||
w_select_new_reg <= 1'b1;
|
||||
end else begin
|
||||
w_select_valid_reg <= w_select_valid_next;
|
||||
w_select_new_reg <= w_select_new_next;
|
||||
end
|
||||
|
||||
w_select_reg <= w_select_next;
|
||||
end
|
||||
|
||||
// write data mux
|
||||
wire [DATA_WIDTH-1:0] s_axi_wdata_mux = int_s_axi_wdata[w_select_reg*DATA_WIDTH +: DATA_WIDTH];
|
||||
wire [STRB_WIDTH-1:0] s_axi_wstrb_mux = int_s_axi_wstrb[w_select_reg*STRB_WIDTH +: STRB_WIDTH];
|
||||
wire s_axi_wlast_mux = int_s_axi_wlast[w_select_reg];
|
||||
wire [WUSER_WIDTH-1:0] s_axi_wuser_mux = int_s_axi_wuser[w_select_reg*WUSER_WIDTH +: WUSER_WIDTH];
|
||||
wire s_axi_wvalid_mux = int_axi_wvalid[w_select_reg*M_COUNT+n] && w_select_valid_reg;
|
||||
wire s_axi_wready_mux;
|
||||
|
||||
assign int_axi_wready[n*S_COUNT +: S_COUNT] = (w_select_valid_reg && s_axi_wready_mux) << w_select_reg;
|
||||
|
||||
// write response forwarding
|
||||
wire [CL_S_COUNT-1:0] b_select = m_axi_bid[n*M_ID_WIDTH +: M_ID_WIDTH] >> S_ID_WIDTH;
|
||||
|
||||
assign int_axi_bvalid[n*S_COUNT +: S_COUNT] = int_m_axi_bvalid[n] << b_select;
|
||||
assign int_m_axi_bready[n] = int_axi_bready[b_select*M_COUNT+n];
|
||||
|
||||
assign trans_complete = int_m_axi_bvalid[n] && int_m_axi_bready[n];
|
||||
|
||||
// M side register
|
||||
axi_register_wr #(
|
||||
.DATA_WIDTH(DATA_WIDTH),
|
||||
.ADDR_WIDTH(ADDR_WIDTH),
|
||||
.STRB_WIDTH(STRB_WIDTH),
|
||||
.ID_WIDTH(M_ID_WIDTH),
|
||||
.AWUSER_ENABLE(AWUSER_ENABLE),
|
||||
.AWUSER_WIDTH(AWUSER_WIDTH),
|
||||
.WUSER_ENABLE(WUSER_ENABLE),
|
||||
.WUSER_WIDTH(WUSER_WIDTH),
|
||||
.BUSER_ENABLE(BUSER_ENABLE),
|
||||
.BUSER_WIDTH(BUSER_WIDTH),
|
||||
.AW_REG_TYPE(M_AW_REG_TYPE[n*2 +: 2]),
|
||||
.W_REG_TYPE(M_W_REG_TYPE[n*2 +: 2]),
|
||||
.B_REG_TYPE(M_B_REG_TYPE[n*2 +: 2])
|
||||
)
|
||||
reg_inst (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.s_axi_awid(s_axi_awid_mux),
|
||||
.s_axi_awaddr(s_axi_awaddr_mux),
|
||||
.s_axi_awlen(s_axi_awlen_mux),
|
||||
.s_axi_awsize(s_axi_awsize_mux),
|
||||
.s_axi_awburst(s_axi_awburst_mux),
|
||||
.s_axi_awlock(s_axi_awlock_mux),
|
||||
.s_axi_awcache(s_axi_awcache_mux),
|
||||
.s_axi_awprot(s_axi_awprot_mux),
|
||||
.s_axi_awqos(s_axi_awqos_mux),
|
||||
.s_axi_awregion(s_axi_awregion_mux),
|
||||
.s_axi_awuser(s_axi_awuser_mux),
|
||||
.s_axi_awvalid(s_axi_awvalid_mux),
|
||||
.s_axi_awready(s_axi_awready_mux),
|
||||
.s_axi_wdata(s_axi_wdata_mux),
|
||||
.s_axi_wstrb(s_axi_wstrb_mux),
|
||||
.s_axi_wlast(s_axi_wlast_mux),
|
||||
.s_axi_wuser(s_axi_wuser_mux),
|
||||
.s_axi_wvalid(s_axi_wvalid_mux),
|
||||
.s_axi_wready(s_axi_wready_mux),
|
||||
.s_axi_bid(int_m_axi_bid[n*M_ID_WIDTH +: M_ID_WIDTH]),
|
||||
.s_axi_bresp(int_m_axi_bresp[n*2 +: 2]),
|
||||
.s_axi_buser(int_m_axi_buser[n*BUSER_WIDTH +: BUSER_WIDTH]),
|
||||
.s_axi_bvalid(int_m_axi_bvalid[n]),
|
||||
.s_axi_bready(int_m_axi_bready[n]),
|
||||
.m_axi_awid(m_axi_awid[n*M_ID_WIDTH +: M_ID_WIDTH]),
|
||||
.m_axi_awaddr(m_axi_awaddr[n*ADDR_WIDTH +: ADDR_WIDTH]),
|
||||
.m_axi_awlen(m_axi_awlen[n*8 +: 8]),
|
||||
.m_axi_awsize(m_axi_awsize[n*3 +: 3]),
|
||||
.m_axi_awburst(m_axi_awburst[n*2 +: 2]),
|
||||
.m_axi_awlock(m_axi_awlock[n]),
|
||||
.m_axi_awcache(m_axi_awcache[n*4 +: 4]),
|
||||
.m_axi_awprot(m_axi_awprot[n*3 +: 3]),
|
||||
.m_axi_awqos(m_axi_awqos[n*4 +: 4]),
|
||||
.m_axi_awregion(m_axi_awregion[n*4 +: 4]),
|
||||
.m_axi_awuser(m_axi_awuser[n*AWUSER_WIDTH +: AWUSER_WIDTH]),
|
||||
.m_axi_awvalid(m_axi_awvalid[n]),
|
||||
.m_axi_awready(m_axi_awready[n]),
|
||||
.m_axi_wdata(m_axi_wdata[n*DATA_WIDTH +: DATA_WIDTH]),
|
||||
.m_axi_wstrb(m_axi_wstrb[n*STRB_WIDTH +: STRB_WIDTH]),
|
||||
.m_axi_wlast(m_axi_wlast[n]),
|
||||
.m_axi_wuser(m_axi_wuser[n*WUSER_WIDTH +: WUSER_WIDTH]),
|
||||
.m_axi_wvalid(m_axi_wvalid[n]),
|
||||
.m_axi_wready(m_axi_wready[n]),
|
||||
.m_axi_bid(m_axi_bid[n*M_ID_WIDTH +: M_ID_WIDTH]),
|
||||
.m_axi_bresp(m_axi_bresp[n*2 +: 2]),
|
||||
.m_axi_buser(m_axi_buser[n*BUSER_WIDTH +: BUSER_WIDTH]),
|
||||
.m_axi_bvalid(m_axi_bvalid[n]),
|
||||
.m_axi_bready(m_axi_bready[n])
|
||||
);
|
||||
end // m_ifaces
|
||||
|
||||
endgenerate
|
||||
|
||||
endmodule
|
788
tb/test_axi_crossbar_4x4.py
Executable file
788
tb/test_axi_crossbar_4x4.py
Executable file
@ -0,0 +1,788 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
|
||||
Copyright (c) 2018 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
"""
|
||||
|
||||
from myhdl import *
|
||||
import os
|
||||
|
||||
import axi
|
||||
import math
|
||||
|
||||
module = 'axi_crossbar'
|
||||
testbench = 'test_%s_4x4' % module
|
||||
|
||||
srcs = []
|
||||
|
||||
srcs.append("../rtl/%s.v" % module)
|
||||
srcs.append("../rtl/axi_crossbar_addr.v")
|
||||
srcs.append("../rtl/axi_crossbar_rd.v")
|
||||
srcs.append("../rtl/axi_crossbar_wr.v")
|
||||
srcs.append("../rtl/axi_register_rd.v")
|
||||
srcs.append("../rtl/axi_register_wr.v")
|
||||
srcs.append("../rtl/arbiter.v")
|
||||
srcs.append("../rtl/priority_encoder.v")
|
||||
srcs.append("%s.v" % testbench)
|
||||
|
||||
src = ' '.join(srcs)
|
||||
|
||||
build_cmd = "iverilog -o %s.vvp %s" % (testbench, src)
|
||||
|
||||
def bench():
|
||||
|
||||
# Parameters
|
||||
S_COUNT = 4
|
||||
M_COUNT = 4
|
||||
DATA_WIDTH = 32
|
||||
ADDR_WIDTH = 32
|
||||
STRB_WIDTH = (DATA_WIDTH/8)
|
||||
S_ID_WIDTH = 8
|
||||
M_ID_WIDTH = S_ID_WIDTH+math.ceil(math.log(M_COUNT, 2))
|
||||
AWUSER_ENABLE = 0
|
||||
AWUSER_WIDTH = 1
|
||||
WUSER_ENABLE = 0
|
||||
WUSER_WIDTH = 1
|
||||
BUSER_ENABLE = 0
|
||||
BUSER_WIDTH = 1
|
||||
ARUSER_ENABLE = 0
|
||||
ARUSER_WIDTH = 1
|
||||
RUSER_ENABLE = 0
|
||||
RUSER_WIDTH = 1
|
||||
S_THREADS = [2]*S_COUNT
|
||||
S_ACCEPT = [16]*S_COUNT
|
||||
M_REGIONS = 1
|
||||
M_BASE_ADDR = [0x00000000, 0x01000000, 0x02000000, 0x03000000]
|
||||
M_ADDR_WIDTH = [24]*M_COUNT*M_REGIONS
|
||||
M_CONNECT_READ = [0b1111]*M_COUNT
|
||||
M_CONNECT_WRITE = [0b1111]*M_COUNT
|
||||
M_ISSUE = [4]*M_COUNT
|
||||
M_SECURE = [0]*M_COUNT
|
||||
S_AW_REG_TYPE = [0]*S_COUNT
|
||||
S_W_REG_TYPE = [0]*S_COUNT
|
||||
S_B_REG_TYPE = [1]*S_COUNT
|
||||
S_AR_REG_TYPE = [0]*S_COUNT
|
||||
S_R_REG_TYPE = [1]*S_COUNT
|
||||
M_AW_REG_TYPE = [1]*M_COUNT
|
||||
M_W_REG_TYPE = [2]*M_COUNT
|
||||
M_B_REG_TYPE = [0]*M_COUNT
|
||||
M_AR_REG_TYPE = [1]*M_COUNT
|
||||
M_R_REG_TYPE = [0]*M_COUNT
|
||||
|
||||
# Inputs
|
||||
clk = Signal(bool(0))
|
||||
rst = Signal(bool(0))
|
||||
current_test = Signal(intbv(0)[8:])
|
||||
|
||||
s_axi_awid_list = [Signal(intbv(0)[S_ID_WIDTH:]) for i in range(S_COUNT)]
|
||||
s_axi_awaddr_list = [Signal(intbv(0)[ADDR_WIDTH:]) for i in range(S_COUNT)]
|
||||
s_axi_awlen_list = [Signal(intbv(0)[8:]) for i in range(S_COUNT)]
|
||||
s_axi_awsize_list = [Signal(intbv(0)[3:]) for i in range(S_COUNT)]
|
||||
s_axi_awburst_list = [Signal(intbv(0)[2:]) for i in range(S_COUNT)]
|
||||
s_axi_awlock_list = [Signal(bool(0)) for i in range(S_COUNT)]
|
||||
s_axi_awcache_list = [Signal(intbv(0)[4:]) for i in range(S_COUNT)]
|
||||
s_axi_awprot_list = [Signal(intbv(0)[3:]) for i in range(S_COUNT)]
|
||||
s_axi_awqos_list = [Signal(intbv(0)[4:]) for i in range(S_COUNT)]
|
||||
s_axi_awuser_list = [Signal(intbv(0)[AWUSER_WIDTH:]) for i in range(S_COUNT)]
|
||||
s_axi_awvalid_list = [Signal(bool(0)) for i in range(S_COUNT)]
|
||||
s_axi_wdata_list = [Signal(intbv(0)[DATA_WIDTH:]) for i in range(S_COUNT)]
|
||||
s_axi_wstrb_list = [Signal(intbv(0)[STRB_WIDTH:]) for i in range(S_COUNT)]
|
||||
s_axi_wlast_list = [Signal(bool(0)) for i in range(S_COUNT)]
|
||||
s_axi_wuser_list = [Signal(intbv(0)[WUSER_WIDTH:]) for i in range(S_COUNT)]
|
||||
s_axi_wvalid_list = [Signal(bool(0)) for i in range(S_COUNT)]
|
||||
s_axi_bready_list = [Signal(bool(0)) for i in range(S_COUNT)]
|
||||
s_axi_arid_list = [Signal(intbv(0)[S_ID_WIDTH:]) for i in range(S_COUNT)]
|
||||
s_axi_araddr_list = [Signal(intbv(0)[ADDR_WIDTH:]) for i in range(S_COUNT)]
|
||||
s_axi_arlen_list = [Signal(intbv(0)[8:]) for i in range(S_COUNT)]
|
||||
s_axi_arsize_list = [Signal(intbv(0)[3:]) for i in range(S_COUNT)]
|
||||
s_axi_arburst_list = [Signal(intbv(0)[2:]) for i in range(S_COUNT)]
|
||||
s_axi_arlock_list = [Signal(bool(0)) for i in range(S_COUNT)]
|
||||
s_axi_arcache_list = [Signal(intbv(0)[4:]) for i in range(S_COUNT)]
|
||||
s_axi_arprot_list = [Signal(intbv(0)[3:]) for i in range(S_COUNT)]
|
||||
s_axi_arqos_list = [Signal(intbv(0)[4:]) for i in range(S_COUNT)]
|
||||
s_axi_aruser_list = [Signal(intbv(0)[ARUSER_WIDTH:]) for i in range(S_COUNT)]
|
||||
s_axi_arvalid_list = [Signal(bool(0)) for i in range(S_COUNT)]
|
||||
s_axi_rready_list = [Signal(bool(0)) for i in range(S_COUNT)]
|
||||
m_axi_awready_list = [Signal(bool(0)) for i in range(M_COUNT)]
|
||||
m_axi_wready_list = [Signal(bool(0)) for i in range(M_COUNT)]
|
||||
m_axi_bid_list = [Signal(intbv(0)[M_ID_WIDTH:]) for i in range(M_COUNT)]
|
||||
m_axi_bresp_list = [Signal(intbv(0)[2:]) for i in range(M_COUNT)]
|
||||
m_axi_buser_list = [Signal(intbv(0)[BUSER_WIDTH:]) for i in range(M_COUNT)]
|
||||
m_axi_bvalid_list = [Signal(bool(0)) for i in range(M_COUNT)]
|
||||
m_axi_arready_list = [Signal(bool(0)) for i in range(M_COUNT)]
|
||||
m_axi_rid_list = [Signal(intbv(0)[M_ID_WIDTH:]) for i in range(M_COUNT)]
|
||||
m_axi_rdata_list = [Signal(intbv(0)[DATA_WIDTH:]) for i in range(M_COUNT)]
|
||||
m_axi_rresp_list = [Signal(intbv(0)[2:]) for i in range(M_COUNT)]
|
||||
m_axi_rlast_list = [Signal(bool(0)) for i in range(M_COUNT)]
|
||||
m_axi_ruser_list = [Signal(intbv(0)[RUSER_WIDTH:]) for i in range(M_COUNT)]
|
||||
m_axi_rvalid_list = [Signal(bool(0)) for i in range(M_COUNT)]
|
||||
|
||||
s_axi_awid = ConcatSignal(*reversed(s_axi_awid_list))
|
||||
s_axi_awaddr = ConcatSignal(*reversed(s_axi_awaddr_list))
|
||||
s_axi_awlen = ConcatSignal(*reversed(s_axi_awlen_list))
|
||||
s_axi_awsize = ConcatSignal(*reversed(s_axi_awsize_list))
|
||||
s_axi_awburst = ConcatSignal(*reversed(s_axi_awburst_list))
|
||||
s_axi_awlock = ConcatSignal(*reversed(s_axi_awlock_list))
|
||||
s_axi_awcache = ConcatSignal(*reversed(s_axi_awcache_list))
|
||||
s_axi_awprot = ConcatSignal(*reversed(s_axi_awprot_list))
|
||||
s_axi_awqos = ConcatSignal(*reversed(s_axi_awqos_list))
|
||||
s_axi_awuser = ConcatSignal(*reversed(s_axi_awuser_list))
|
||||
s_axi_awvalid = ConcatSignal(*reversed(s_axi_awvalid_list))
|
||||
s_axi_wdata = ConcatSignal(*reversed(s_axi_wdata_list))
|
||||
s_axi_wstrb = ConcatSignal(*reversed(s_axi_wstrb_list))
|
||||
s_axi_wlast = ConcatSignal(*reversed(s_axi_wlast_list))
|
||||
s_axi_wuser = ConcatSignal(*reversed(s_axi_wuser_list))
|
||||
s_axi_wvalid = ConcatSignal(*reversed(s_axi_wvalid_list))
|
||||
s_axi_bready = ConcatSignal(*reversed(s_axi_bready_list))
|
||||
s_axi_arid = ConcatSignal(*reversed(s_axi_arid_list))
|
||||
s_axi_araddr = ConcatSignal(*reversed(s_axi_araddr_list))
|
||||
s_axi_arlen = ConcatSignal(*reversed(s_axi_arlen_list))
|
||||
s_axi_arsize = ConcatSignal(*reversed(s_axi_arsize_list))
|
||||
s_axi_arburst = ConcatSignal(*reversed(s_axi_arburst_list))
|
||||
s_axi_arlock = ConcatSignal(*reversed(s_axi_arlock_list))
|
||||
s_axi_arcache = ConcatSignal(*reversed(s_axi_arcache_list))
|
||||
s_axi_arprot = ConcatSignal(*reversed(s_axi_arprot_list))
|
||||
s_axi_arqos = ConcatSignal(*reversed(s_axi_arqos_list))
|
||||
s_axi_aruser = ConcatSignal(*reversed(s_axi_aruser_list))
|
||||
s_axi_arvalid = ConcatSignal(*reversed(s_axi_arvalid_list))
|
||||
s_axi_rready = ConcatSignal(*reversed(s_axi_rready_list))
|
||||
m_axi_awready = ConcatSignal(*reversed(m_axi_awready_list))
|
||||
m_axi_wready = ConcatSignal(*reversed(m_axi_wready_list))
|
||||
m_axi_bid = ConcatSignal(*reversed(m_axi_bid_list))
|
||||
m_axi_bresp = ConcatSignal(*reversed(m_axi_bresp_list))
|
||||
m_axi_buser = ConcatSignal(*reversed(m_axi_buser_list))
|
||||
m_axi_bvalid = ConcatSignal(*reversed(m_axi_bvalid_list))
|
||||
m_axi_arready = ConcatSignal(*reversed(m_axi_arready_list))
|
||||
m_axi_rid = ConcatSignal(*reversed(m_axi_rid_list))
|
||||
m_axi_rdata = ConcatSignal(*reversed(m_axi_rdata_list))
|
||||
m_axi_rresp = ConcatSignal(*reversed(m_axi_rresp_list))
|
||||
m_axi_rlast = ConcatSignal(*reversed(m_axi_rlast_list))
|
||||
m_axi_ruser = ConcatSignal(*reversed(m_axi_ruser_list))
|
||||
m_axi_rvalid = ConcatSignal(*reversed(m_axi_rvalid_list))
|
||||
|
||||
# Outputs
|
||||
s_axi_awready = Signal(intbv(0)[S_COUNT:])
|
||||
s_axi_wready = Signal(intbv(0)[S_COUNT:])
|
||||
s_axi_bid = Signal(intbv(0)[S_COUNT*S_ID_WIDTH:])
|
||||
s_axi_bresp = Signal(intbv(0)[S_COUNT*2:])
|
||||
s_axi_buser = Signal(intbv(0)[S_COUNT*BUSER_WIDTH:])
|
||||
s_axi_bvalid = Signal(intbv(0)[S_COUNT:])
|
||||
s_axi_arready = Signal(intbv(0)[S_COUNT:])
|
||||
s_axi_rid = Signal(intbv(0)[S_COUNT*S_ID_WIDTH:])
|
||||
s_axi_rdata = Signal(intbv(0)[S_COUNT*DATA_WIDTH:])
|
||||
s_axi_rresp = Signal(intbv(0)[S_COUNT*2:])
|
||||
s_axi_rlast = Signal(intbv(0)[S_COUNT:])
|
||||
s_axi_ruser = Signal(intbv(0)[S_COUNT*RUSER_WIDTH:])
|
||||
s_axi_rvalid = Signal(intbv(0)[S_COUNT:])
|
||||
m_axi_awid = Signal(intbv(0)[M_COUNT*M_ID_WIDTH:])
|
||||
m_axi_awaddr = Signal(intbv(0)[M_COUNT*ADDR_WIDTH:])
|
||||
m_axi_awlen = Signal(intbv(0)[M_COUNT*8:])
|
||||
m_axi_awsize = Signal(intbv(0)[M_COUNT*3:])
|
||||
m_axi_awburst = Signal(intbv(0)[M_COUNT*2:])
|
||||
m_axi_awlock = Signal(intbv(0)[M_COUNT:])
|
||||
m_axi_awcache = Signal(intbv(0)[M_COUNT*4:])
|
||||
m_axi_awprot = Signal(intbv(0)[M_COUNT*3:])
|
||||
m_axi_awqos = Signal(intbv(0)[M_COUNT*4:])
|
||||
m_axi_awregion = Signal(intbv(0)[M_COUNT*4:])
|
||||
m_axi_awuser = Signal(intbv(0)[M_COUNT*AWUSER_WIDTH:])
|
||||
m_axi_awvalid = Signal(intbv(0)[M_COUNT:])
|
||||
m_axi_wdata = Signal(intbv(0)[M_COUNT*DATA_WIDTH:])
|
||||
m_axi_wstrb = Signal(intbv(0)[M_COUNT*STRB_WIDTH:])
|
||||
m_axi_wlast = Signal(intbv(0)[M_COUNT:])
|
||||
m_axi_wuser = Signal(intbv(0)[M_COUNT*WUSER_WIDTH:])
|
||||
m_axi_wvalid = Signal(intbv(0)[M_COUNT:])
|
||||
m_axi_bready = Signal(intbv(0)[M_COUNT:])
|
||||
m_axi_arid = Signal(intbv(0)[M_COUNT*M_ID_WIDTH:])
|
||||
m_axi_araddr = Signal(intbv(0)[M_COUNT*ADDR_WIDTH:])
|
||||
m_axi_arlen = Signal(intbv(0)[M_COUNT*8:])
|
||||
m_axi_arsize = Signal(intbv(0)[M_COUNT*3:])
|
||||
m_axi_arburst = Signal(intbv(0)[M_COUNT*2:])
|
||||
m_axi_arlock = Signal(intbv(0)[M_COUNT:])
|
||||
m_axi_arcache = Signal(intbv(0)[M_COUNT*4:])
|
||||
m_axi_arprot = Signal(intbv(0)[M_COUNT*3:])
|
||||
m_axi_arqos = Signal(intbv(0)[M_COUNT*4:])
|
||||
m_axi_arregion = Signal(intbv(0)[M_COUNT*4:])
|
||||
m_axi_aruser = Signal(intbv(0)[M_COUNT*ARUSER_WIDTH:])
|
||||
m_axi_arvalid = Signal(intbv(0)[M_COUNT:])
|
||||
m_axi_rready = Signal(intbv(0)[M_COUNT:])
|
||||
|
||||
s_axi_awready_list = [s_axi_awready(i) for i in range(S_COUNT)]
|
||||
s_axi_wready_list = [s_axi_wready(i) for i in range(S_COUNT)]
|
||||
s_axi_bid_list = [s_axi_bid((i+1)*S_ID_WIDTH, i*S_ID_WIDTH) for i in range(S_COUNT)]
|
||||
s_axi_bresp_list = [s_axi_bresp((i+1)*2, i*2) for i in range(S_COUNT)]
|
||||
s_axi_buser_list = [s_axi_buser((i+1)*BUSER_WIDTH, i*BUSER_WIDTH) for i in range(S_COUNT)]
|
||||
s_axi_bvalid_list = [s_axi_bvalid(i) for i in range(S_COUNT)]
|
||||
s_axi_arready_list = [s_axi_arready(i) for i in range(S_COUNT)]
|
||||
s_axi_rid_list = [s_axi_rid((i+1)*S_ID_WIDTH, i*S_ID_WIDTH) for i in range(S_COUNT)]
|
||||
s_axi_rdata_list = [s_axi_rdata((i+1)*DATA_WIDTH, i*DATA_WIDTH) for i in range(S_COUNT)]
|
||||
s_axi_rresp_list = [s_axi_rresp((i+1)*2, i*2) for i in range(S_COUNT)]
|
||||
s_axi_rlast_list = [s_axi_rlast(i) for i in range(S_COUNT)]
|
||||
s_axi_ruser_list = [s_axi_ruser((i+1)*RUSER_WIDTH, i*RUSER_WIDTH) for i in range(S_COUNT)]
|
||||
s_axi_rvalid_list = [s_axi_rvalid(i) for i in range(S_COUNT)]
|
||||
m_axi_awid_list = [m_axi_awid((i+1)*M_ID_WIDTH, i*M_ID_WIDTH) for i in range(M_COUNT)]
|
||||
m_axi_awaddr_list = [m_axi_awaddr((i+1)*ADDR_WIDTH, i*ADDR_WIDTH) for i in range(M_COUNT)]
|
||||
m_axi_awlen_list = [m_axi_awlen((i+1)*8, i*8) for i in range(M_COUNT)]
|
||||
m_axi_awsize_list = [m_axi_awsize((i+1)*3, i*3) for i in range(M_COUNT)]
|
||||
m_axi_awburst_list = [m_axi_awburst((i+1)*2, i*2) for i in range(M_COUNT)]
|
||||
m_axi_awlock_list = [m_axi_awlock(i) for i in range(M_COUNT)]
|
||||
m_axi_awcache_list = [m_axi_awcache((i+1)*4, i*4) for i in range(M_COUNT)]
|
||||
m_axi_awprot_list = [m_axi_awprot((i+1)*3, i*3) for i in range(M_COUNT)]
|
||||
m_axi_awqos_list = [m_axi_awqos((i+1)*4, i*4) for i in range(M_COUNT)]
|
||||
m_axi_awregion_list = [m_axi_awregion((i+1)*4, i*4) for i in range(M_COUNT)]
|
||||
m_axi_awuser_list = [m_axi_awuser((i+1)*AWUSER_WIDTH, i*AWUSER_WIDTH) for i in range(M_COUNT)]
|
||||
m_axi_awvalid_list = [m_axi_awvalid(i) for i in range(M_COUNT)]
|
||||
m_axi_wdata_list = [m_axi_wdata((i+1)*DATA_WIDTH, i*DATA_WIDTH) for i in range(M_COUNT)]
|
||||
m_axi_wstrb_list = [m_axi_wstrb((i+1)*STRB_WIDTH, i*STRB_WIDTH) for i in range(M_COUNT)]
|
||||
m_axi_wlast_list = [m_axi_wlast(i) for i in range(M_COUNT)]
|
||||
m_axi_wuser_list = [m_axi_wuser((i+1)*WUSER_WIDTH, i*WUSER_WIDTH) for i in range(M_COUNT)]
|
||||
m_axi_wvalid_list = [m_axi_wvalid(i) for i in range(M_COUNT)]
|
||||
m_axi_bready_list = [m_axi_bready(i) for i in range(M_COUNT)]
|
||||
m_axi_arid_list = [m_axi_arid((i+1)*M_ID_WIDTH, i*M_ID_WIDTH) for i in range(M_COUNT)]
|
||||
m_axi_araddr_list = [m_axi_araddr((i+1)*ADDR_WIDTH, i*ADDR_WIDTH) for i in range(M_COUNT)]
|
||||
m_axi_arlen_list = [m_axi_arlen((i+1)*8, i*8) for i in range(M_COUNT)]
|
||||
m_axi_arsize_list = [m_axi_arsize((i+1)*3, i*3) for i in range(M_COUNT)]
|
||||
m_axi_arburst_list = [m_axi_arburst((i+1)*2, i*2) for i in range(M_COUNT)]
|
||||
m_axi_arlock_list = [m_axi_arlock(i) for i in range(M_COUNT)]
|
||||
m_axi_arcache_list = [m_axi_arcache((i+1)*4, i*4) for i in range(M_COUNT)]
|
||||
m_axi_arprot_list = [m_axi_arprot((i+1)*3, i*3) for i in range(M_COUNT)]
|
||||
m_axi_arqos_list = [m_axi_arqos((i+1)*4, i*4) for i in range(M_COUNT)]
|
||||
m_axi_arregion_list = [m_axi_arregion((i+1)*4, i*4) for i in range(M_COUNT)]
|
||||
m_axi_aruser_list = [m_axi_aruser((i+1)*ARUSER_WIDTH, i*ARUSER_WIDTH) for i in range(M_COUNT)]
|
||||
m_axi_arvalid_list = [m_axi_arvalid(i) for i in range(M_COUNT)]
|
||||
m_axi_rready_list = [m_axi_rready(i) for i in range(M_COUNT)]
|
||||
|
||||
# AXI4 masters
|
||||
axi_master_inst_list = []
|
||||
axi_master_pause_list = []
|
||||
axi_master_logic = []
|
||||
|
||||
for k in range(S_COUNT):
|
||||
m = axi.AXIMaster()
|
||||
p = Signal(bool(False))
|
||||
|
||||
axi_master_inst_list.append(m)
|
||||
axi_master_pause_list.append(p)
|
||||
|
||||
axi_master_logic.append(m.create_logic(
|
||||
clk,
|
||||
rst,
|
||||
m_axi_awid=s_axi_awid_list[k],
|
||||
m_axi_awaddr=s_axi_awaddr_list[k],
|
||||
m_axi_awlen=s_axi_awlen_list[k],
|
||||
m_axi_awsize=s_axi_awsize_list[k],
|
||||
m_axi_awburst=s_axi_awburst_list[k],
|
||||
m_axi_awlock=s_axi_awlock_list[k],
|
||||
m_axi_awcache=s_axi_awcache_list[k],
|
||||
m_axi_awprot=s_axi_awprot_list[k],
|
||||
m_axi_awqos=s_axi_awqos_list[k],
|
||||
m_axi_awvalid=s_axi_awvalid_list[k],
|
||||
m_axi_awready=s_axi_awready_list[k],
|
||||
m_axi_wdata=s_axi_wdata_list[k],
|
||||
m_axi_wstrb=s_axi_wstrb_list[k],
|
||||
m_axi_wlast=s_axi_wlast_list[k],
|
||||
m_axi_wvalid=s_axi_wvalid_list[k],
|
||||
m_axi_wready=s_axi_wready_list[k],
|
||||
m_axi_bid=s_axi_bid_list[k],
|
||||
m_axi_bresp=s_axi_bresp_list[k],
|
||||
m_axi_bvalid=s_axi_bvalid_list[k],
|
||||
m_axi_bready=s_axi_bready_list[k],
|
||||
m_axi_arid=s_axi_arid_list[k],
|
||||
m_axi_araddr=s_axi_araddr_list[k],
|
||||
m_axi_arlen=s_axi_arlen_list[k],
|
||||
m_axi_arsize=s_axi_arsize_list[k],
|
||||
m_axi_arburst=s_axi_arburst_list[k],
|
||||
m_axi_arlock=s_axi_arlock_list[k],
|
||||
m_axi_arcache=s_axi_arcache_list[k],
|
||||
m_axi_arprot=s_axi_arprot_list[k],
|
||||
m_axi_arqos=s_axi_arqos_list[k],
|
||||
m_axi_arvalid=s_axi_arvalid_list[k],
|
||||
m_axi_arready=s_axi_arready_list[k],
|
||||
m_axi_rid=s_axi_rid_list[k],
|
||||
m_axi_rdata=s_axi_rdata_list[k],
|
||||
m_axi_rresp=s_axi_rresp_list[k],
|
||||
m_axi_rlast=s_axi_rlast_list[k],
|
||||
m_axi_rvalid=s_axi_rvalid_list[k],
|
||||
m_axi_rready=s_axi_rready_list[k],
|
||||
pause=p,
|
||||
name='master_%d' % k
|
||||
))
|
||||
|
||||
# AXI4 RAM models
|
||||
axi_ram_inst_list = []
|
||||
axi_ram_pause_list = []
|
||||
axi_ram_logic = []
|
||||
|
||||
for k in range(M_COUNT):
|
||||
r = axi.AXIRam(2**16)
|
||||
p = Signal(bool(False))
|
||||
|
||||
axi_ram_inst_list.append(r)
|
||||
axi_ram_pause_list.append(p)
|
||||
|
||||
axi_ram_logic.append(r.create_port(
|
||||
clk,
|
||||
s_axi_awid=m_axi_awid_list[k],
|
||||
s_axi_awaddr=m_axi_awaddr_list[k],
|
||||
s_axi_awlen=m_axi_awlen_list[k],
|
||||
s_axi_awsize=m_axi_awsize_list[k],
|
||||
s_axi_awburst=m_axi_awburst_list[k],
|
||||
s_axi_awlock=m_axi_awlock_list[k],
|
||||
s_axi_awcache=m_axi_awcache_list[k],
|
||||
s_axi_awprot=m_axi_awprot_list[k],
|
||||
s_axi_awvalid=m_axi_awvalid_list[k],
|
||||
s_axi_awready=m_axi_awready_list[k],
|
||||
s_axi_wdata=m_axi_wdata_list[k],
|
||||
s_axi_wstrb=m_axi_wstrb_list[k],
|
||||
s_axi_wlast=m_axi_wlast_list[k],
|
||||
s_axi_wvalid=m_axi_wvalid_list[k],
|
||||
s_axi_wready=m_axi_wready_list[k],
|
||||
s_axi_bid=m_axi_bid_list[k],
|
||||
s_axi_bresp=m_axi_bresp_list[k],
|
||||
s_axi_bvalid=m_axi_bvalid_list[k],
|
||||
s_axi_bready=m_axi_bready_list[k],
|
||||
s_axi_arid=m_axi_arid_list[k],
|
||||
s_axi_araddr=m_axi_araddr_list[k],
|
||||
s_axi_arlen=m_axi_arlen_list[k],
|
||||
s_axi_arsize=m_axi_arsize_list[k],
|
||||
s_axi_arburst=m_axi_arburst_list[k],
|
||||
s_axi_arlock=m_axi_arlock_list[k],
|
||||
s_axi_arcache=m_axi_arcache_list[k],
|
||||
s_axi_arprot=m_axi_arprot_list[k],
|
||||
s_axi_arvalid=m_axi_arvalid_list[k],
|
||||
s_axi_arready=m_axi_arready_list[k],
|
||||
s_axi_rid=m_axi_rid_list[k],
|
||||
s_axi_rdata=m_axi_rdata_list[k],
|
||||
s_axi_rresp=m_axi_rresp_list[k],
|
||||
s_axi_rlast=m_axi_rlast_list[k],
|
||||
s_axi_rvalid=m_axi_rvalid_list[k],
|
||||
s_axi_rready=m_axi_rready_list[k],
|
||||
pause=p,
|
||||
name='ram_%d' % k
|
||||
))
|
||||
|
||||
# DUT
|
||||
if os.system(build_cmd):
|
||||
raise Exception("Error running build command")
|
||||
|
||||
dut = Cosimulation(
|
||||
"vvp -m myhdl %s.vvp -lxt2" % testbench,
|
||||
clk=clk,
|
||||
rst=rst,
|
||||
current_test=current_test,
|
||||
s_axi_awid=s_axi_awid,
|
||||
s_axi_awaddr=s_axi_awaddr,
|
||||
s_axi_awlen=s_axi_awlen,
|
||||
s_axi_awsize=s_axi_awsize,
|
||||
s_axi_awburst=s_axi_awburst,
|
||||
s_axi_awlock=s_axi_awlock,
|
||||
s_axi_awcache=s_axi_awcache,
|
||||
s_axi_awprot=s_axi_awprot,
|
||||
s_axi_awqos=s_axi_awqos,
|
||||
s_axi_awuser=s_axi_awuser,
|
||||
s_axi_awvalid=s_axi_awvalid,
|
||||
s_axi_awready=s_axi_awready,
|
||||
s_axi_wdata=s_axi_wdata,
|
||||
s_axi_wstrb=s_axi_wstrb,
|
||||
s_axi_wlast=s_axi_wlast,
|
||||
s_axi_wuser=s_axi_wuser,
|
||||
s_axi_wvalid=s_axi_wvalid,
|
||||
s_axi_wready=s_axi_wready,
|
||||
s_axi_bid=s_axi_bid,
|
||||
s_axi_bresp=s_axi_bresp,
|
||||
s_axi_buser=s_axi_buser,
|
||||
s_axi_bvalid=s_axi_bvalid,
|
||||
s_axi_bready=s_axi_bready,
|
||||
s_axi_arid=s_axi_arid,
|
||||
s_axi_araddr=s_axi_araddr,
|
||||
s_axi_arlen=s_axi_arlen,
|
||||
s_axi_arsize=s_axi_arsize,
|
||||
s_axi_arburst=s_axi_arburst,
|
||||
s_axi_arlock=s_axi_arlock,
|
||||
s_axi_arcache=s_axi_arcache,
|
||||
s_axi_arprot=s_axi_arprot,
|
||||
s_axi_arqos=s_axi_arqos,
|
||||
s_axi_aruser=s_axi_aruser,
|
||||
s_axi_arvalid=s_axi_arvalid,
|
||||
s_axi_arready=s_axi_arready,
|
||||
s_axi_rid=s_axi_rid,
|
||||
s_axi_rdata=s_axi_rdata,
|
||||
s_axi_rresp=s_axi_rresp,
|
||||
s_axi_rlast=s_axi_rlast,
|
||||
s_axi_ruser=s_axi_ruser,
|
||||
s_axi_rvalid=s_axi_rvalid,
|
||||
s_axi_rready=s_axi_rready,
|
||||
m_axi_awid=m_axi_awid,
|
||||
m_axi_awaddr=m_axi_awaddr,
|
||||
m_axi_awlen=m_axi_awlen,
|
||||
m_axi_awsize=m_axi_awsize,
|
||||
m_axi_awburst=m_axi_awburst,
|
||||
m_axi_awlock=m_axi_awlock,
|
||||
m_axi_awcache=m_axi_awcache,
|
||||
m_axi_awprot=m_axi_awprot,
|
||||
m_axi_awqos=m_axi_awqos,
|
||||
m_axi_awregion=m_axi_awregion,
|
||||
m_axi_awuser=m_axi_awuser,
|
||||
m_axi_awvalid=m_axi_awvalid,
|
||||
m_axi_awready=m_axi_awready,
|
||||
m_axi_wdata=m_axi_wdata,
|
||||
m_axi_wstrb=m_axi_wstrb,
|
||||
m_axi_wlast=m_axi_wlast,
|
||||
m_axi_wuser=m_axi_wuser,
|
||||
m_axi_wvalid=m_axi_wvalid,
|
||||
m_axi_wready=m_axi_wready,
|
||||
m_axi_bid=m_axi_bid,
|
||||
m_axi_bresp=m_axi_bresp,
|
||||
m_axi_buser=m_axi_buser,
|
||||
m_axi_bvalid=m_axi_bvalid,
|
||||
m_axi_bready=m_axi_bready,
|
||||
m_axi_arid=m_axi_arid,
|
||||
m_axi_araddr=m_axi_araddr,
|
||||
m_axi_arlen=m_axi_arlen,
|
||||
m_axi_arsize=m_axi_arsize,
|
||||
m_axi_arburst=m_axi_arburst,
|
||||
m_axi_arlock=m_axi_arlock,
|
||||
m_axi_arcache=m_axi_arcache,
|
||||
m_axi_arprot=m_axi_arprot,
|
||||
m_axi_arqos=m_axi_arqos,
|
||||
m_axi_arregion=m_axi_arregion,
|
||||
m_axi_aruser=m_axi_aruser,
|
||||
m_axi_arvalid=m_axi_arvalid,
|
||||
m_axi_arready=m_axi_arready,
|
||||
m_axi_rid=m_axi_rid,
|
||||
m_axi_rdata=m_axi_rdata,
|
||||
m_axi_rresp=m_axi_rresp,
|
||||
m_axi_rlast=m_axi_rlast,
|
||||
m_axi_ruser=m_axi_ruser,
|
||||
m_axi_rvalid=m_axi_rvalid,
|
||||
m_axi_rready=m_axi_rready
|
||||
)
|
||||
|
||||
@always(delay(4))
|
||||
def clkgen():
|
||||
clk.next = not clk
|
||||
|
||||
def wait_normal():
|
||||
while not all([axi_master_inst_list[k].idle() for k in range(S_COUNT)]):
|
||||
yield clk.posedge
|
||||
|
||||
def wait_pause_master():
|
||||
while not all([axi_master_inst_list[k].idle() for k in range(S_COUNT)]):
|
||||
for k in range(S_COUNT):
|
||||
axi_master_pause_list[k].next = True
|
||||
yield clk.posedge
|
||||
yield clk.posedge
|
||||
yield clk.posedge
|
||||
for k in range(S_COUNT):
|
||||
axi_master_pause_list[k].next = False
|
||||
yield clk.posedge
|
||||
|
||||
def wait_pause_slave():
|
||||
while not all([axi_master_inst_list[k].idle() for k in range(S_COUNT)]):
|
||||
for k in range(M_COUNT):
|
||||
axi_ram_pause_list[k].next = True
|
||||
yield clk.posedge
|
||||
yield clk.posedge
|
||||
yield clk.posedge
|
||||
for k in range(M_COUNT):
|
||||
axi_ram_pause_list[k].next = False
|
||||
yield clk.posedge
|
||||
|
||||
@instance
|
||||
def check():
|
||||
yield delay(100)
|
||||
yield clk.posedge
|
||||
rst.next = 1
|
||||
yield clk.posedge
|
||||
rst.next = 0
|
||||
yield clk.posedge
|
||||
yield delay(100)
|
||||
yield clk.posedge
|
||||
|
||||
# testbench stimulus
|
||||
|
||||
yield clk.posedge
|
||||
print("test 1: write")
|
||||
current_test.next = 1
|
||||
|
||||
addr = 4
|
||||
test_data = b'\x11\x22\x33\x44'
|
||||
|
||||
axi_master_inst_list[0].init_write(addr, test_data)
|
||||
|
||||
yield axi_master_inst_list[0].wait()
|
||||
yield clk.posedge
|
||||
|
||||
data = axi_ram_inst_list[0].read_mem(addr&0xffffff80, 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert axi_ram_inst_list[0].read_mem(addr, len(test_data)) == test_data
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 2: read")
|
||||
current_test.next = 2
|
||||
|
||||
addr = 4
|
||||
test_data = b'\x11\x22\x33\x44'
|
||||
|
||||
axi_ram_inst_list[0].write_mem(addr, test_data)
|
||||
|
||||
axi_master_inst_list[0].init_read(addr, len(test_data))
|
||||
|
||||
yield axi_master_inst_list[0].wait()
|
||||
yield clk.posedge
|
||||
|
||||
data = axi_master_inst_list[0].get_read_data()
|
||||
assert data[0] == addr
|
||||
assert data[1] == test_data
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 3: one to many")
|
||||
current_test.next = 3
|
||||
|
||||
addr = 4
|
||||
test_data = b'\x11\x22\x33\x44'
|
||||
|
||||
for k in range(S_COUNT):
|
||||
axi_master_inst_list[0].init_write(addr+M_BASE_ADDR[k], test_data)
|
||||
|
||||
yield axi_master_inst_list[0].wait()
|
||||
yield clk.posedge
|
||||
|
||||
for k in range(S_COUNT):
|
||||
data = axi_ram_inst_list[k].read_mem(addr&0xffffff80, 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
for k in range(S_COUNT):
|
||||
assert axi_ram_inst_list[k].read_mem(addr, len(test_data)) == test_data
|
||||
|
||||
for k in range(S_COUNT):
|
||||
axi_master_inst_list[0].init_read(addr+M_BASE_ADDR[k], len(test_data))
|
||||
|
||||
yield axi_master_inst_list[0].wait()
|
||||
yield clk.posedge
|
||||
|
||||
for k in range(S_COUNT):
|
||||
data = axi_master_inst_list[0].get_read_data()
|
||||
assert data[0] == addr+M_BASE_ADDR[k]
|
||||
assert data[1] == test_data
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 4: many to one")
|
||||
current_test.next = 4
|
||||
|
||||
for k in range(M_COUNT):
|
||||
axi_master_inst_list[k].init_write(k*4, bytearray([(k+1)*17]*4))
|
||||
|
||||
for k in range(M_COUNT):
|
||||
yield axi_master_inst_list[k].wait()
|
||||
yield clk.posedge
|
||||
|
||||
data = axi_ram_inst_list[0].read_mem(addr&0xffffff80, 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
for k in range(M_COUNT):
|
||||
assert axi_ram_inst_list[0].read_mem(k*4, 4) == bytearray([(k+1)*17]*4)
|
||||
|
||||
for k in range(M_COUNT):
|
||||
axi_master_inst_list[k].init_read(k*4, 4)
|
||||
|
||||
for k in range(M_COUNT):
|
||||
yield axi_master_inst_list[k].wait()
|
||||
yield clk.posedge
|
||||
|
||||
for k in range(M_COUNT):
|
||||
data = axi_master_inst_list[k].get_read_data()
|
||||
assert data[0] == k*4
|
||||
assert data[1] == bytearray([(k+1)*17]*4)
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 10: transaction limit and ordering test")
|
||||
current_test.next = 10
|
||||
|
||||
length = 256
|
||||
test_data = bytearray([x%256 for x in range(length)])
|
||||
|
||||
for k in range(10):
|
||||
axi_master_inst_list[0].init_write(length*k+M_BASE_ADDR[0], bytearray([k+1]*length))
|
||||
|
||||
yield axi_master_inst_list[0].wait()
|
||||
yield clk.posedge
|
||||
|
||||
for k in range(10):
|
||||
data = axi_ram_inst_list[0].read_mem((length*k)&0xffffff80, 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
for k in range(10):
|
||||
assert axi_ram_inst_list[0].read_mem(length*k, length) == bytearray([k+1]*length)
|
||||
|
||||
for k in range(10):
|
||||
axi_master_inst_list[0].init_read(length*k+M_BASE_ADDR[0], length)
|
||||
|
||||
yield axi_master_inst_list[0].wait()
|
||||
yield clk.posedge
|
||||
|
||||
for k in range(10):
|
||||
data = axi_master_inst_list[0].get_read_data()
|
||||
assert data[0] == length*k+M_BASE_ADDR[0]
|
||||
assert data[1] == bytearray([k+1]*length)
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 5: various writes")
|
||||
current_test.next = 5
|
||||
|
||||
for length in list(range(1,8))+[1024]:
|
||||
for offset in list(range(4,8))+[4096-4]:
|
||||
for wait in wait_normal, wait_pause_master, wait_pause_slave:
|
||||
print("length %d, offset %d"% (length, offset))
|
||||
#addr = 256*(16*offset+length)+offset
|
||||
addr = offset
|
||||
test_data = bytearray([x%256 for x in range(length)])
|
||||
|
||||
axi_ram_inst_list[0].write_mem(addr&0xffffff80, b'\xAA'*(length+256))
|
||||
axi_master_inst_list[0].init_write(addr, test_data)
|
||||
|
||||
yield wait()
|
||||
yield clk.posedge
|
||||
|
||||
data = axi_ram_inst_list[0].read_mem(addr&0xffffff80, 32)
|
||||
for i in range(0, len(data), 16):
|
||||
print(" ".join(("{:02x}".format(c) for c in bytearray(data[i:i+16]))))
|
||||
|
||||
assert axi_ram_inst_list[0].read_mem(addr, length) == test_data
|
||||
assert axi_ram_inst_list[0].read_mem(addr-1, 1) == b'\xAA'
|
||||
assert axi_ram_inst_list[0].read_mem(addr+length, 1) == b'\xAA'
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 6: various reads")
|
||||
current_test.next = 6
|
||||
|
||||
for length in list(range(1,8))+[1024]:
|
||||
for offset in list(range(4,8))+[4096-4]:
|
||||
for wait in wait_normal, wait_pause_master, wait_pause_slave:
|
||||
print("length %d, offset %d"% (length, offset))
|
||||
#addr = 256*(16*offset+length)+offset
|
||||
addr = offset
|
||||
test_data = bytearray([x%256 for x in range(length)])
|
||||
|
||||
axi_ram_inst_list[0].write_mem(addr, test_data)
|
||||
|
||||
axi_master_inst_list[0].init_read(addr, length)
|
||||
|
||||
yield wait()
|
||||
yield clk.posedge
|
||||
|
||||
data = axi_master_inst_list[0].get_read_data()
|
||||
assert data[0] == addr
|
||||
assert data[1] == test_data
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 7: concurrent operations")
|
||||
current_test.next = 7
|
||||
|
||||
for count in [1, 2, 4, 8]:
|
||||
for stride in [2, 3, 5, 7]:
|
||||
for wait in wait_normal, wait_pause_master, wait_pause_slave:
|
||||
print("count %d, stride %d"% (count, stride))
|
||||
|
||||
for k in range(S_COUNT):
|
||||
for l in range(count):
|
||||
ram = ((k*61+l)*stride)%M_COUNT
|
||||
offset = k*256+l*4
|
||||
axi_ram_inst_list[ram].write_mem(offset, b'\xAA'*4)
|
||||
axi_master_inst_list[k].init_write(M_BASE_ADDR[ram]+offset, bytearray([0xaa, k, l, 0xaa]))
|
||||
|
||||
ram = ((k*61+l+67)*stride)%M_COUNT
|
||||
offset = k*256+l*4
|
||||
axi_ram_inst_list[ram].write_mem(offset+0x8000, bytearray([0xaa, k, l, 0xaa]))
|
||||
axi_master_inst_list[k].init_read(M_BASE_ADDR[ram]+offset+0x8000, 4)
|
||||
|
||||
yield wait()
|
||||
yield clk.posedge
|
||||
|
||||
for k in range(S_COUNT):
|
||||
for l in range(count):
|
||||
ram = ((k*61+l)*stride)%M_COUNT
|
||||
offset = k*256+l*4
|
||||
axi_ram_inst_list[ram].read_mem(offset, 4) == bytearray([0xaa, k, l, 0xaa])
|
||||
|
||||
ram = ((k*61+l+67)*stride)%M_COUNT
|
||||
offset = k*256+l*4
|
||||
data = axi_master_inst_list[k].get_read_data()
|
||||
assert data[0] == M_BASE_ADDR[ram]+offset+0x8000
|
||||
assert data[1] == bytearray([0xaa, k, l, 0xaa])
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 8: bad write")
|
||||
current_test.next = 8
|
||||
|
||||
axi_master_inst_list[0].init_write(0xff000000, b'\xDE\xAD\xBE\xEF')
|
||||
|
||||
yield axi_master_inst_list[0].wait()
|
||||
yield clk.posedge
|
||||
|
||||
yield delay(100)
|
||||
|
||||
yield clk.posedge
|
||||
print("test 9: bad read")
|
||||
current_test.next = 9
|
||||
|
||||
axi_master_inst_list[0].init_read(0xff000000, 4)
|
||||
|
||||
yield axi_master_inst_list[0].wait()
|
||||
yield clk.posedge
|
||||
|
||||
data = axi_master_inst_list[0].get_read_data()
|
||||
assert data[0] == 0xff000000
|
||||
|
||||
yield delay(100)
|
||||
|
||||
raise StopSimulation
|
||||
|
||||
return instances()
|
||||
|
||||
def test_bench():
|
||||
sim = Simulation(bench())
|
||||
sim.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Running test...")
|
||||
test_bench()
|
396
tb/test_axi_crossbar_4x4.v
Normal file
396
tb/test_axi_crossbar_4x4.v
Normal file
@ -0,0 +1,396 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2018 Alex Forencich
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
*/
|
||||
|
||||
// Language: Verilog 2001
|
||||
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
/*
|
||||
* Testbench for axi_crossbar
|
||||
*/
|
||||
module test_axi_crossbar_4x4;
|
||||
|
||||
// Parameters
|
||||
parameter S_COUNT = 4;
|
||||
parameter M_COUNT = 4;
|
||||
parameter DATA_WIDTH = 32;
|
||||
parameter ADDR_WIDTH = 32;
|
||||
parameter STRB_WIDTH = (DATA_WIDTH/8);
|
||||
parameter S_ID_WIDTH = 8;
|
||||
parameter M_ID_WIDTH = S_ID_WIDTH+$clog2(S_COUNT);
|
||||
parameter AWUSER_ENABLE = 0;
|
||||
parameter AWUSER_WIDTH = 1;
|
||||
parameter WUSER_ENABLE = 0;
|
||||
parameter WUSER_WIDTH = 1;
|
||||
parameter BUSER_ENABLE = 0;
|
||||
parameter BUSER_WIDTH = 1;
|
||||
parameter ARUSER_ENABLE = 0;
|
||||
parameter ARUSER_WIDTH = 1;
|
||||
parameter RUSER_ENABLE = 0;
|
||||
parameter RUSER_WIDTH = 1;
|
||||
parameter S_THREADS = {S_COUNT{32'd2}};
|
||||
parameter S_ACCEPT = {S_COUNT{32'd16}};
|
||||
parameter M_REGIONS = 1;
|
||||
parameter M_BASE_ADDR = {32'h03000000, 32'h02000000, 32'h01000000, 32'h00000000};
|
||||
parameter M_ADDR_WIDTH = {M_COUNT{{M_REGIONS{32'd24}}}};
|
||||
parameter M_CONNECT_READ = {M_COUNT{{S_COUNT{1'b1}}}};
|
||||
parameter M_CONNECT_WRITE = {M_COUNT{{S_COUNT{1'b1}}}};
|
||||
parameter M_ISSUE = {M_COUNT{32'd4}};
|
||||
parameter M_SECURE = {M_COUNT{1'b0}};
|
||||
parameter S_AW_REG_TYPE = {S_COUNT{2'd0}};
|
||||
parameter S_W_REG_TYPE = {S_COUNT{2'd0}};
|
||||
parameter S_B_REG_TYPE = {S_COUNT{2'd1}};
|
||||
parameter S_AR_REG_TYPE = {S_COUNT{2'd0}};
|
||||
parameter S_R_REG_TYPE = {S_COUNT{2'd1}};
|
||||
parameter M_AW_REG_TYPE = {M_COUNT{2'd1}};
|
||||
parameter M_W_REG_TYPE = {M_COUNT{2'd2}};
|
||||
parameter M_B_REG_TYPE = {M_COUNT{2'd0}};
|
||||
parameter M_AR_REG_TYPE = {M_COUNT{2'd1}};
|
||||
parameter M_R_REG_TYPE = {M_COUNT{2'd0}};
|
||||
|
||||
// Inputs
|
||||
reg clk = 0;
|
||||
reg rst = 0;
|
||||
reg [7:0] current_test = 0;
|
||||
|
||||
reg [S_COUNT*S_ID_WIDTH-1:0] s_axi_awid = 0;
|
||||
reg [S_COUNT*ADDR_WIDTH-1:0] s_axi_awaddr = 0;
|
||||
reg [S_COUNT*8-1:0] s_axi_awlen = 0;
|
||||
reg [S_COUNT*3-1:0] s_axi_awsize = 0;
|
||||
reg [S_COUNT*2-1:0] s_axi_awburst = 0;
|
||||
reg [S_COUNT-1:0] s_axi_awlock = 0;
|
||||
reg [S_COUNT*4-1:0] s_axi_awcache = 0;
|
||||
reg [S_COUNT*3-1:0] s_axi_awprot = 0;
|
||||
reg [S_COUNT*4-1:0] s_axi_awqos = 0;
|
||||
reg [S_COUNT*AWUSER_WIDTH-1:0] s_axi_awuser = 0;
|
||||
reg [S_COUNT-1:0] s_axi_awvalid = 0;
|
||||
reg [S_COUNT*DATA_WIDTH-1:0] s_axi_wdata = 0;
|
||||
reg [S_COUNT*STRB_WIDTH-1:0] s_axi_wstrb = 0;
|
||||
reg [S_COUNT-1:0] s_axi_wlast = 0;
|
||||
reg [S_COUNT*WUSER_WIDTH-1:0] s_axi_wuser = 0;
|
||||
reg [S_COUNT-1:0] s_axi_wvalid = 0;
|
||||
reg [S_COUNT-1:0] s_axi_bready = 0;
|
||||
reg [S_COUNT*S_ID_WIDTH-1:0] s_axi_arid = 0;
|
||||
reg [S_COUNT*ADDR_WIDTH-1:0] s_axi_araddr = 0;
|
||||
reg [S_COUNT*8-1:0] s_axi_arlen = 0;
|
||||
reg [S_COUNT*3-1:0] s_axi_arsize = 0;
|
||||
reg [S_COUNT*2-1:0] s_axi_arburst = 0;
|
||||
reg [S_COUNT-1:0] s_axi_arlock = 0;
|
||||
reg [S_COUNT*4-1:0] s_axi_arcache = 0;
|
||||
reg [S_COUNT*3-1:0] s_axi_arprot = 0;
|
||||
reg [S_COUNT*4-1:0] s_axi_arqos = 0;
|
||||
reg [S_COUNT*ARUSER_WIDTH-1:0] s_axi_aruser = 0;
|
||||
reg [S_COUNT-1:0] s_axi_arvalid = 0;
|
||||
reg [S_COUNT-1:0] s_axi_rready = 0;
|
||||
reg [M_COUNT-1:0] m_axi_awready = 0;
|
||||
reg [M_COUNT-1:0] m_axi_wready = 0;
|
||||
reg [M_COUNT*M_ID_WIDTH-1:0] m_axi_bid = 0;
|
||||
reg [M_COUNT*2-1:0] m_axi_bresp = 0;
|
||||
reg [M_COUNT*BUSER_WIDTH-1:0] m_axi_buser = 0;
|
||||
reg [M_COUNT-1:0] m_axi_bvalid = 0;
|
||||
reg [M_COUNT-1:0] m_axi_arready = 0;
|
||||
reg [M_COUNT*M_ID_WIDTH-1:0] m_axi_rid = 0;
|
||||
reg [M_COUNT*DATA_WIDTH-1:0] m_axi_rdata = 0;
|
||||
reg [M_COUNT*2-1:0] m_axi_rresp = 0;
|
||||
reg [M_COUNT-1:0] m_axi_rlast = 0;
|
||||
reg [M_COUNT*RUSER_WIDTH-1:0] m_axi_ruser = 0;
|
||||
reg [M_COUNT-1:0] m_axi_rvalid = 0;
|
||||
|
||||
// Outputs
|
||||
wire [S_COUNT-1:0] s_axi_awready;
|
||||
wire [S_COUNT-1:0] s_axi_wready;
|
||||
wire [S_COUNT*S_ID_WIDTH-1:0] s_axi_bid;
|
||||
wire [S_COUNT*2-1:0] s_axi_bresp;
|
||||
wire [S_COUNT*BUSER_WIDTH-1:0] s_axi_buser;
|
||||
wire [S_COUNT-1:0] s_axi_bvalid;
|
||||
wire [S_COUNT-1:0] s_axi_arready;
|
||||
wire [S_COUNT*S_ID_WIDTH-1:0] s_axi_rid;
|
||||
wire [S_COUNT*DATA_WIDTH-1:0] s_axi_rdata;
|
||||
wire [S_COUNT*2-1:0] s_axi_rresp;
|
||||
wire [S_COUNT-1:0] s_axi_rlast;
|
||||
wire [S_COUNT*RUSER_WIDTH-1:0] s_axi_ruser;
|
||||
wire [S_COUNT-1:0] s_axi_rvalid;
|
||||
wire [M_COUNT*M_ID_WIDTH-1:0] m_axi_awid;
|
||||
wire [M_COUNT*ADDR_WIDTH-1:0] m_axi_awaddr;
|
||||
wire [M_COUNT*8-1:0] m_axi_awlen;
|
||||
wire [M_COUNT*3-1:0] m_axi_awsize;
|
||||
wire [M_COUNT*2-1:0] m_axi_awburst;
|
||||
wire [M_COUNT-1:0] m_axi_awlock;
|
||||
wire [M_COUNT*4-1:0] m_axi_awcache;
|
||||
wire [M_COUNT*3-1:0] m_axi_awprot;
|
||||
wire [M_COUNT*4-1:0] m_axi_awqos;
|
||||
wire [M_COUNT*4-1:0] m_axi_awregion;
|
||||
wire [M_COUNT*AWUSER_WIDTH-1:0] m_axi_awuser;
|
||||
wire [M_COUNT-1:0] m_axi_awvalid;
|
||||
wire [M_COUNT*DATA_WIDTH-1:0] m_axi_wdata;
|
||||
wire [M_COUNT*STRB_WIDTH-1:0] m_axi_wstrb;
|
||||
wire [M_COUNT-1:0] m_axi_wlast;
|
||||
wire [M_COUNT*WUSER_WIDTH-1:0] m_axi_wuser;
|
||||
wire [M_COUNT-1:0] m_axi_wvalid;
|
||||
wire [M_COUNT-1:0] m_axi_bready;
|
||||
wire [M_COUNT*M_ID_WIDTH-1:0] m_axi_arid;
|
||||
wire [M_COUNT*ADDR_WIDTH-1:0] m_axi_araddr;
|
||||
wire [M_COUNT*8-1:0] m_axi_arlen;
|
||||
wire [M_COUNT*3-1:0] m_axi_arsize;
|
||||
wire [M_COUNT*2-1:0] m_axi_arburst;
|
||||
wire [M_COUNT-1:0] m_axi_arlock;
|
||||
wire [M_COUNT*4-1:0] m_axi_arcache;
|
||||
wire [M_COUNT*3-1:0] m_axi_arprot;
|
||||
wire [M_COUNT*4-1:0] m_axi_arqos;
|
||||
wire [M_COUNT*4-1:0] m_axi_arregion;
|
||||
wire [M_COUNT*ARUSER_WIDTH-1:0] m_axi_aruser;
|
||||
wire [M_COUNT-1:0] m_axi_arvalid;
|
||||
wire [M_COUNT-1:0] m_axi_rready;
|
||||
|
||||
initial begin
|
||||
// myhdl integration
|
||||
$from_myhdl(
|
||||
clk,
|
||||
rst,
|
||||
current_test,
|
||||
s_axi_awid,
|
||||
s_axi_awaddr,
|
||||
s_axi_awlen,
|
||||
s_axi_awsize,
|
||||
s_axi_awburst,
|
||||
s_axi_awlock,
|
||||
s_axi_awcache,
|
||||
s_axi_awprot,
|
||||
s_axi_awqos,
|
||||
s_axi_awuser,
|
||||
s_axi_awvalid,
|
||||
s_axi_wdata,
|
||||
s_axi_wstrb,
|
||||
s_axi_wlast,
|
||||
s_axi_wuser,
|
||||
s_axi_wvalid,
|
||||
s_axi_bready,
|
||||
s_axi_arid,
|
||||
s_axi_araddr,
|
||||
s_axi_arlen,
|
||||
s_axi_arsize,
|
||||
s_axi_arburst,
|
||||
s_axi_arlock,
|
||||
s_axi_arcache,
|
||||
s_axi_arprot,
|
||||
s_axi_arqos,
|
||||
s_axi_aruser,
|
||||
s_axi_arvalid,
|
||||
s_axi_rready,
|
||||
m_axi_awready,
|
||||
m_axi_wready,
|
||||
m_axi_bid,
|
||||
m_axi_bresp,
|
||||
m_axi_buser,
|
||||
m_axi_bvalid,
|
||||
m_axi_arready,
|
||||
m_axi_rid,
|
||||
m_axi_rdata,
|
||||
m_axi_rresp,
|
||||
m_axi_rlast,
|
||||
m_axi_ruser,
|
||||
m_axi_rvalid
|
||||
);
|
||||
$to_myhdl(
|
||||
s_axi_awready,
|
||||
s_axi_wready,
|
||||
s_axi_bid,
|
||||
s_axi_bresp,
|
||||
s_axi_buser,
|
||||
s_axi_bvalid,
|
||||
s_axi_arready,
|
||||
s_axi_rid,
|
||||
s_axi_rdata,
|
||||
s_axi_rresp,
|
||||
s_axi_rlast,
|
||||
s_axi_ruser,
|
||||
s_axi_rvalid,
|
||||
m_axi_awid,
|
||||
m_axi_awaddr,
|
||||
m_axi_awlen,
|
||||
m_axi_awsize,
|
||||
m_axi_awburst,
|
||||
m_axi_awlock,
|
||||
m_axi_awcache,
|
||||
m_axi_awprot,
|
||||
m_axi_awqos,
|
||||
m_axi_awregion,
|
||||
m_axi_awuser,
|
||||
m_axi_awvalid,
|
||||
m_axi_wdata,
|
||||
m_axi_wstrb,
|
||||
m_axi_wlast,
|
||||
m_axi_wuser,
|
||||
m_axi_wvalid,
|
||||
m_axi_bready,
|
||||
m_axi_arid,
|
||||
m_axi_araddr,
|
||||
m_axi_arlen,
|
||||
m_axi_arsize,
|
||||
m_axi_arburst,
|
||||
m_axi_arlock,
|
||||
m_axi_arcache,
|
||||
m_axi_arprot,
|
||||
m_axi_arqos,
|
||||
m_axi_arregion,
|
||||
m_axi_aruser,
|
||||
m_axi_arvalid,
|
||||
m_axi_rready
|
||||
);
|
||||
|
||||
// dump file
|
||||
$dumpfile("test_axi_crossbar_4x4.lxt");
|
||||
$dumpvars(0, test_axi_crossbar_4x4);
|
||||
end
|
||||
|
||||
axi_crossbar #(
|
||||
.S_COUNT(S_COUNT),
|
||||
.M_COUNT(M_COUNT),
|
||||
.DATA_WIDTH(DATA_WIDTH),
|
||||
.ADDR_WIDTH(ADDR_WIDTH),
|
||||
.STRB_WIDTH(STRB_WIDTH),
|
||||
.S_ID_WIDTH(S_ID_WIDTH),
|
||||
.M_ID_WIDTH(M_ID_WIDTH),
|
||||
.AWUSER_ENABLE(AWUSER_ENABLE),
|
||||
.AWUSER_WIDTH(AWUSER_WIDTH),
|
||||
.WUSER_ENABLE(WUSER_ENABLE),
|
||||
.WUSER_WIDTH(WUSER_WIDTH),
|
||||
.BUSER_ENABLE(BUSER_ENABLE),
|
||||
.BUSER_WIDTH(BUSER_WIDTH),
|
||||
.ARUSER_ENABLE(ARUSER_ENABLE),
|
||||
.ARUSER_WIDTH(ARUSER_WIDTH),
|
||||
.RUSER_ENABLE(RUSER_ENABLE),
|
||||
.RUSER_WIDTH(RUSER_WIDTH),
|
||||
.S_THREADS(S_THREADS),
|
||||
.S_ACCEPT(S_ACCEPT),
|
||||
.M_REGIONS(M_REGIONS),
|
||||
.M_BASE_ADDR(M_BASE_ADDR),
|
||||
.M_ADDR_WIDTH(M_ADDR_WIDTH),
|
||||
.M_CONNECT_READ(M_CONNECT_READ),
|
||||
.M_CONNECT_WRITE(M_CONNECT_WRITE),
|
||||
.M_ISSUE(M_ISSUE),
|
||||
.M_SECURE(M_SECURE),
|
||||
.S_AW_REG_TYPE(S_AW_REG_TYPE),
|
||||
.S_W_REG_TYPE(S_W_REG_TYPE),
|
||||
.S_B_REG_TYPE(S_B_REG_TYPE),
|
||||
.S_AR_REG_TYPE(S_AR_REG_TYPE),
|
||||
.S_R_REG_TYPE(S_R_REG_TYPE),
|
||||
.M_AW_REG_TYPE(M_AW_REG_TYPE),
|
||||
.M_W_REG_TYPE(M_W_REG_TYPE),
|
||||
.M_B_REG_TYPE(M_B_REG_TYPE),
|
||||
.M_AR_REG_TYPE(M_AR_REG_TYPE),
|
||||
.M_R_REG_TYPE(M_R_REG_TYPE)
|
||||
)
|
||||
UUT (
|
||||
.clk(clk),
|
||||
.rst(rst),
|
||||
.s_axi_awid(s_axi_awid),
|
||||
.s_axi_awaddr(s_axi_awaddr),
|
||||
.s_axi_awlen(s_axi_awlen),
|
||||
.s_axi_awsize(s_axi_awsize),
|
||||
.s_axi_awburst(s_axi_awburst),
|
||||
.s_axi_awlock(s_axi_awlock),
|
||||
.s_axi_awcache(s_axi_awcache),
|
||||
.s_axi_awprot(s_axi_awprot),
|
||||
.s_axi_awqos(s_axi_awqos),
|
||||
.s_axi_awuser(s_axi_awuser),
|
||||
.s_axi_awvalid(s_axi_awvalid),
|
||||
.s_axi_awready(s_axi_awready),
|
||||
.s_axi_wdata(s_axi_wdata),
|
||||
.s_axi_wstrb(s_axi_wstrb),
|
||||
.s_axi_wlast(s_axi_wlast),
|
||||
.s_axi_wuser(s_axi_wuser),
|
||||
.s_axi_wvalid(s_axi_wvalid),
|
||||
.s_axi_wready(s_axi_wready),
|
||||
.s_axi_bid(s_axi_bid),
|
||||
.s_axi_bresp(s_axi_bresp),
|
||||
.s_axi_buser(s_axi_buser),
|
||||
.s_axi_bvalid(s_axi_bvalid),
|
||||
.s_axi_bready(s_axi_bready),
|
||||
.s_axi_arid(s_axi_arid),
|
||||
.s_axi_araddr(s_axi_araddr),
|
||||
.s_axi_arlen(s_axi_arlen),
|
||||
.s_axi_arsize(s_axi_arsize),
|
||||
.s_axi_arburst(s_axi_arburst),
|
||||
.s_axi_arlock(s_axi_arlock),
|
||||
.s_axi_arcache(s_axi_arcache),
|
||||
.s_axi_arprot(s_axi_arprot),
|
||||
.s_axi_arqos(s_axi_arqos),
|
||||
.s_axi_aruser(s_axi_aruser),
|
||||
.s_axi_arvalid(s_axi_arvalid),
|
||||
.s_axi_arready(s_axi_arready),
|
||||
.s_axi_rid(s_axi_rid),
|
||||
.s_axi_rdata(s_axi_rdata),
|
||||
.s_axi_rresp(s_axi_rresp),
|
||||
.s_axi_rlast(s_axi_rlast),
|
||||
.s_axi_ruser(s_axi_ruser),
|
||||
.s_axi_rvalid(s_axi_rvalid),
|
||||
.s_axi_rready(s_axi_rready),
|
||||
.m_axi_awid(m_axi_awid),
|
||||
.m_axi_awaddr(m_axi_awaddr),
|
||||
.m_axi_awlen(m_axi_awlen),
|
||||
.m_axi_awsize(m_axi_awsize),
|
||||
.m_axi_awburst(m_axi_awburst),
|
||||
.m_axi_awlock(m_axi_awlock),
|
||||
.m_axi_awcache(m_axi_awcache),
|
||||
.m_axi_awprot(m_axi_awprot),
|
||||
.m_axi_awqos(m_axi_awqos),
|
||||
.m_axi_awregion(m_axi_awregion),
|
||||
.m_axi_awuser(m_axi_awuser),
|
||||
.m_axi_awvalid(m_axi_awvalid),
|
||||
.m_axi_awready(m_axi_awready),
|
||||
.m_axi_wdata(m_axi_wdata),
|
||||
.m_axi_wstrb(m_axi_wstrb),
|
||||
.m_axi_wlast(m_axi_wlast),
|
||||
.m_axi_wuser(m_axi_wuser),
|
||||
.m_axi_wvalid(m_axi_wvalid),
|
||||
.m_axi_wready(m_axi_wready),
|
||||
.m_axi_bid(m_axi_bid),
|
||||
.m_axi_bresp(m_axi_bresp),
|
||||
.m_axi_buser(m_axi_buser),
|
||||
.m_axi_bvalid(m_axi_bvalid),
|
||||
.m_axi_bready(m_axi_bready),
|
||||
.m_axi_arid(m_axi_arid),
|
||||
.m_axi_araddr(m_axi_araddr),
|
||||
.m_axi_arlen(m_axi_arlen),
|
||||
.m_axi_arsize(m_axi_arsize),
|
||||
.m_axi_arburst(m_axi_arburst),
|
||||
.m_axi_arlock(m_axi_arlock),
|
||||
.m_axi_arcache(m_axi_arcache),
|
||||
.m_axi_arprot(m_axi_arprot),
|
||||
.m_axi_arqos(m_axi_arqos),
|
||||
.m_axi_arregion(m_axi_arregion),
|
||||
.m_axi_aruser(m_axi_aruser),
|
||||
.m_axi_arvalid(m_axi_arvalid),
|
||||
.m_axi_arready(m_axi_arready),
|
||||
.m_axi_rid(m_axi_rid),
|
||||
.m_axi_rdata(m_axi_rdata),
|
||||
.m_axi_rresp(m_axi_rresp),
|
||||
.m_axi_rlast(m_axi_rlast),
|
||||
.m_axi_ruser(m_axi_ruser),
|
||||
.m_axi_rvalid(m_axi_rvalid),
|
||||
.m_axi_rready(m_axi_rready)
|
||||
);
|
||||
|
||||
endmodule
|
Loading…
x
Reference in New Issue
Block a user