switch to new model
This commit is contained in:
parent
1f1029ec07
commit
d2842e7a16
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
[submodule "sim/model/axi"]
|
||||
path = sim/model/axi
|
||||
url = https://github.com/pulp-platform/axi
|
@ -1,166 +0,0 @@
|
||||
/*------------------------------------------------------------------------------
|
||||
--------------------------------------------------------------------------------
|
||||
Copyright (c) 2016, Loongson Technology Corporation Limited.
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of Loongson Technology Corporation Limited nor the names of
|
||||
its contributors may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL LOONGSON TECHNOLOGY CORPORATION LIMITED BE LIABLE
|
||||
TO ANY PARTY FOR DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
--------------------------------------------------------------------------------
|
||||
------------------------------------------------------------------------------*/
|
||||
|
||||
module axi_wrap(
|
||||
input m_aclk,
|
||||
input m_aresetn,
|
||||
//ar
|
||||
input [3 :0] m_arid ,
|
||||
input [31:0] m_araddr ,
|
||||
input [3 :0] m_arlen ,
|
||||
input [2 :0] m_arsize ,
|
||||
input [1 :0] m_arburst,
|
||||
input [1 :0] m_arlock ,
|
||||
input [3 :0] m_arcache,
|
||||
input [2 :0] m_arprot ,
|
||||
input m_arvalid,
|
||||
output m_arready,
|
||||
//r
|
||||
output [3 :0] m_rid ,
|
||||
output [31:0] m_rdata ,
|
||||
output [1 :0] m_rresp ,
|
||||
output m_rlast ,
|
||||
output m_rvalid ,
|
||||
input m_rready ,
|
||||
//aw
|
||||
input [3 :0] m_awid ,
|
||||
input [31:0] m_awaddr ,
|
||||
input [3 :0] m_awlen ,
|
||||
input [2 :0] m_awsize ,
|
||||
input [1 :0] m_awburst,
|
||||
input [1 :0] m_awlock ,
|
||||
input [3 :0] m_awcache,
|
||||
input [2 :0] m_awprot ,
|
||||
input m_awvalid,
|
||||
output m_awready,
|
||||
//w
|
||||
input [3 :0] m_wid ,
|
||||
input [31:0] m_wdata ,
|
||||
input [3 :0] m_wstrb ,
|
||||
input m_wlast ,
|
||||
input m_wvalid ,
|
||||
output m_wready ,
|
||||
//b
|
||||
output [3 :0] m_bid ,
|
||||
output [1 :0] m_bresp ,
|
||||
output m_bvalid ,
|
||||
input m_bready ,
|
||||
|
||||
output s_aclk,
|
||||
output s_aresetn,
|
||||
//ar
|
||||
output [3 :0] s_arid ,
|
||||
output [31:0] s_araddr ,
|
||||
output [3 :0] s_arlen ,
|
||||
output [2 :0] s_arsize ,
|
||||
output [1 :0] s_arburst,
|
||||
output [1 :0] s_arlock ,
|
||||
output [3 :0] s_arcache,
|
||||
output [2 :0] s_arprot ,
|
||||
output s_arvalid,
|
||||
input s_arready,
|
||||
//r
|
||||
input [3 :0] s_rid ,
|
||||
input [31:0] s_rdata ,
|
||||
input [1 :0] s_rresp ,
|
||||
input s_rlast ,
|
||||
input s_rvalid ,
|
||||
output s_rready ,
|
||||
//aw
|
||||
output [3 :0] s_awid ,
|
||||
output [31:0] s_awaddr ,
|
||||
output [3 :0] s_awlen ,
|
||||
output [2 :0] s_awsize ,
|
||||
output [1 :0] s_awburst,
|
||||
output [1 :0] s_awlock ,
|
||||
output [3 :0] s_awcache,
|
||||
output [2 :0] s_awprot ,
|
||||
output s_awvalid,
|
||||
input s_awready,
|
||||
//w
|
||||
output [3 :0] s_wid ,
|
||||
output [31:0] s_wdata ,
|
||||
output [3 :0] s_wstrb ,
|
||||
output s_wlast ,
|
||||
output s_wvalid ,
|
||||
input s_wready ,
|
||||
//b
|
||||
input [3 :0] s_bid ,
|
||||
input [1 :0] s_bresp ,
|
||||
input s_bvalid ,
|
||||
output s_bready
|
||||
);
|
||||
assign s_aclk = m_aclk ;
|
||||
assign s_aresetn = m_aresetn;
|
||||
//ar
|
||||
assign s_arid = m_arid ;
|
||||
assign s_araddr = m_araddr ;
|
||||
assign s_arlen = m_arlen ;
|
||||
assign s_arsize = m_arsize ;
|
||||
assign s_arburst = m_arburst;
|
||||
assign s_arlock = m_arlock ;
|
||||
assign s_arcache = m_arcache;
|
||||
assign s_arprot = m_arprot ;
|
||||
assign s_arvalid = m_arvalid;
|
||||
assign m_arready = s_arready;
|
||||
//r
|
||||
assign m_rid = m_rvalid ? s_rid : 4'd0 ;
|
||||
assign m_rdata = m_rvalid ? s_rdata : 32'd0 ;
|
||||
assign m_rresp = m_rvalid ? s_rresp : 2'd0 ;
|
||||
assign m_rlast = m_rvalid ? s_rlast : 1'd0 ;
|
||||
assign m_rvalid = s_rvalid;
|
||||
assign s_rready = m_rready;
|
||||
//aw
|
||||
assign s_awid = m_awid ;
|
||||
assign s_awaddr = m_awaddr ;
|
||||
assign s_awlen = m_awlen ;
|
||||
assign s_awsize = m_awsize ;
|
||||
assign s_awburst = m_awburst;
|
||||
assign s_awlock = m_awlock ;
|
||||
assign s_awcache = m_awcache;
|
||||
assign s_awprot = m_awprot ;
|
||||
assign s_awvalid = m_awvalid;
|
||||
assign m_awready = s_awready;
|
||||
//w
|
||||
assign s_wid = m_wid ;
|
||||
assign s_wdata = m_wdata ;
|
||||
assign s_wstrb = m_wstrb ;
|
||||
assign s_wlast = m_wlast ;
|
||||
assign s_wvalid = m_wvalid ;
|
||||
assign m_wready = s_wready ;
|
||||
//b
|
||||
assign m_bid = m_bvalid ? s_bid : 4'd0 ;
|
||||
assign m_bresp = m_bvalid ? s_bresp : 2'd0 ;
|
||||
assign m_bvalid = s_bvalid ;
|
||||
assign s_bready = m_bready ;
|
||||
endmodule
|
@ -1,293 +0,0 @@
|
||||
/*------------------------------------------------------------------------------
|
||||
--------------------------------------------------------------------------------
|
||||
Copyright (c) 2016, Loongson Technology Corporation Limited.
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of Loongson Technology Corporation Limited nor the names of
|
||||
its contributors may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL LOONGSON TECHNOLOGY CORPORATION LIMITED BE LIABLE
|
||||
TO ANY PARTY FOR DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
|
||||
GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
||||
THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
--------------------------------------------------------------------------------
|
||||
------------------------------------------------------------------------------*/
|
||||
//for func test, no define RUN_PERF_TEST
|
||||
`define _RUN_PERF_TEST
|
||||
`define _RUN_PERF_NO_DELAY
|
||||
|
||||
module axi_wrap_ram(
|
||||
input aclk,
|
||||
input aresetn,
|
||||
//ar
|
||||
input [3 :0] axi_arid ,
|
||||
input [31:0] axi_araddr ,
|
||||
input [7 :0] axi_arlen ,
|
||||
input [2 :0] axi_arsize ,
|
||||
input [1 :0] axi_arburst,
|
||||
input [1 :0] axi_arlock ,
|
||||
input [3 :0] axi_arcache,
|
||||
input [2 :0] axi_arprot ,
|
||||
input axi_arvalid,
|
||||
output axi_arready,
|
||||
//r
|
||||
output [3 :0] axi_rid ,
|
||||
output [31:0] axi_rdata ,
|
||||
output [1 :0] axi_rresp ,
|
||||
output axi_rlast ,
|
||||
output axi_rvalid ,
|
||||
input axi_rready ,
|
||||
//aw
|
||||
input [3 :0] axi_awid ,
|
||||
input [31:0] axi_awaddr ,
|
||||
input [7 :0] axi_awlen ,
|
||||
input [2 :0] axi_awsize ,
|
||||
input [1 :0] axi_awburst,
|
||||
input [1 :0] axi_awlock ,
|
||||
input [3 :0] axi_awcache,
|
||||
input [2 :0] axi_awprot ,
|
||||
input axi_awvalid,
|
||||
output axi_awready,
|
||||
//w
|
||||
input [3 :0] axi_wid ,
|
||||
input [31:0] axi_wdata ,
|
||||
input [3 :0] axi_wstrb ,
|
||||
input axi_wlast ,
|
||||
input axi_wvalid ,
|
||||
output axi_wready ,
|
||||
//b
|
||||
output [3 :0] axi_bid ,
|
||||
output [1 :0] axi_bresp ,
|
||||
output axi_bvalid ,
|
||||
input axi_bready ,
|
||||
|
||||
//from confreg
|
||||
input [4 :0] ram_random_mask
|
||||
);
|
||||
wire axi_arvalid_m_masked;
|
||||
wire axi_rready_m_masked;
|
||||
wire axi_awvalid_m_masked;
|
||||
wire axi_wvalid_m_masked;
|
||||
wire axi_bready_m_masked;
|
||||
|
||||
wire axi_arready_s_unmasked;
|
||||
wire axi_rvalid_s_unmasked;
|
||||
wire axi_awready_s_unmasked;
|
||||
wire axi_wready_s_unmasked;
|
||||
wire axi_bvalid_s_unmasked;
|
||||
|
||||
wire ar_and;
|
||||
wire r_and;
|
||||
wire aw_and;
|
||||
wire w_and;
|
||||
wire b_and;
|
||||
reg ar_nomask;
|
||||
reg aw_nomask;
|
||||
reg w_nomask;
|
||||
reg [4:0] pf_r2r;
|
||||
reg [1:0] pf_b2b;
|
||||
wire pf_r2r_nomask= pf_r2r==5'd0;
|
||||
wire pf_b2b_nomask= pf_b2b==2'd0;
|
||||
|
||||
//mask
|
||||
`ifdef RUN_PERF_TEST
|
||||
assign ar_and = 1'b1;
|
||||
assign aw_and = 1'b1;
|
||||
assign w_and = 1'b1;
|
||||
`ifdef RUN_PERF_NO_DELAY
|
||||
assign r_and = 1'b1;
|
||||
assign b_and = 1'b1;
|
||||
`else
|
||||
assign r_and = pf_r2r_nomask;
|
||||
assign b_and = pf_b2b_nomask;
|
||||
`endif
|
||||
`else
|
||||
assign ar_and = ram_random_mask[4] | ar_nomask;
|
||||
assign r_and = ram_random_mask[3] ;
|
||||
assign aw_and = ram_random_mask[2] | aw_nomask;
|
||||
assign w_and = ram_random_mask[1] | w_nomask;
|
||||
assign b_and = ram_random_mask[0] ;
|
||||
`endif
|
||||
always @(posedge aclk)
|
||||
begin
|
||||
//for func test, random mask
|
||||
ar_nomask <= !aresetn ? 1'b0 :
|
||||
axi_arvalid_m_masked&&axi_arready ? 1'b0 :
|
||||
axi_arvalid_m_masked ? 1'b1 : ar_nomask;
|
||||
|
||||
aw_nomask <= !aresetn ? 1'b0 :
|
||||
axi_awvalid_m_masked&&axi_awready ? 1'b0 :
|
||||
axi_awvalid_m_masked ? 1'b1 : aw_nomask;
|
||||
|
||||
w_nomask <= !aresetn ? 1'b0 :
|
||||
axi_wvalid_m_masked&&axi_wready ? 1'b0 :
|
||||
axi_wvalid_m_masked ? 1'b1 : w_nomask;
|
||||
//for perf test
|
||||
pf_r2r <= !aresetn ? 5'd0 :
|
||||
axi_arvalid_m_masked&&axi_arready ? 5'd25 :
|
||||
!pf_r2r_nomask ? pf_r2r-1'b1 : pf_r2r;
|
||||
pf_b2b <= !aresetn ? 2'd0 :
|
||||
axi_awvalid_m_masked&&axi_awready ? 2'd3 :
|
||||
!pf_b2b_nomask ? pf_b2b-1'b1 : pf_b2b;
|
||||
end
|
||||
|
||||
|
||||
//-----{master -> slave}-----
|
||||
assign axi_arvalid_m_masked = axi_arvalid & ar_and;
|
||||
assign axi_rready_m_masked = axi_rready & r_and;
|
||||
assign axi_awvalid_m_masked = axi_awvalid & aw_and;
|
||||
assign axi_wvalid_m_masked = axi_wvalid & w_and;
|
||||
assign axi_bready_m_masked = axi_bready & b_and;
|
||||
|
||||
//-----{slave -> master}-----
|
||||
assign axi_arready = axi_arready_s_unmasked & ar_and;
|
||||
assign axi_rvalid = axi_rvalid_s_unmasked & r_and;
|
||||
assign axi_awready = axi_awready_s_unmasked & aw_and;
|
||||
assign axi_wready = axi_wready_s_unmasked & w_and;
|
||||
assign axi_bvalid = axi_bvalid_s_unmasked & b_and;
|
||||
|
||||
//ram axi
|
||||
//ar
|
||||
wire [3 :0] ram_arid ;
|
||||
wire [31:0] ram_araddr ;
|
||||
wire [7 :0] ram_arlen ;
|
||||
wire [2 :0] ram_arsize ;
|
||||
wire [1 :0] ram_arburst;
|
||||
wire [1 :0] ram_arlock ;
|
||||
wire [3 :0] ram_arcache;
|
||||
wire [2 :0] ram_arprot ;
|
||||
wire ram_arvalid;
|
||||
wire ram_arready;
|
||||
//r
|
||||
wire [3 :0] ram_rid ;
|
||||
wire [31:0] ram_rdata ;
|
||||
wire [1 :0] ram_rresp ;
|
||||
wire ram_rlast ;
|
||||
wire ram_rvalid ;
|
||||
wire ram_rready ;
|
||||
//aw
|
||||
wire [3 :0] ram_awid ;
|
||||
wire [31:0] ram_awaddr ;
|
||||
wire [7 :0] ram_awlen ;
|
||||
wire [2 :0] ram_awsize ;
|
||||
wire [1 :0] ram_awburst;
|
||||
wire [1 :0] ram_awlock ;
|
||||
wire [3 :0] ram_awcache;
|
||||
wire [2 :0] ram_awprot ;
|
||||
wire ram_awvalid;
|
||||
wire ram_awready;
|
||||
//w
|
||||
wire [3 :0] ram_wid ;
|
||||
wire [31:0] ram_wdata ;
|
||||
wire [3 :0] ram_wstrb ;
|
||||
wire ram_wlast ;
|
||||
wire ram_wvalid ;
|
||||
wire ram_wready ;
|
||||
//b
|
||||
wire [3 :0] ram_bid ;
|
||||
wire [1 :0] ram_bresp ;
|
||||
wire ram_bvalid ;
|
||||
wire ram_bready ;
|
||||
|
||||
|
||||
// inst ram axi
|
||||
axi_ram ram(
|
||||
.s_aclk (aclk ),
|
||||
.s_aresetn (aresetn ),
|
||||
|
||||
//ar
|
||||
.s_axi_arid (ram_arid ),
|
||||
.s_axi_araddr (ram_araddr ),
|
||||
.s_axi_arlen (ram_arlen ),
|
||||
.s_axi_arsize (ram_arsize ),
|
||||
.s_axi_arburst (ram_arburst ),
|
||||
.s_axi_arvalid (ram_arvalid ),
|
||||
.s_axi_arready (ram_arready ),
|
||||
//r
|
||||
.s_axi_rid (ram_rid ),
|
||||
.s_axi_rdata (ram_rdata ),
|
||||
.s_axi_rresp (ram_rresp ),
|
||||
.s_axi_rlast (ram_rlast ),
|
||||
.s_axi_rvalid (ram_rvalid ),
|
||||
.s_axi_rready (ram_rready ),
|
||||
//aw
|
||||
.s_axi_awid (ram_awid ),
|
||||
.s_axi_awaddr (ram_awaddr ),
|
||||
.s_axi_awlen (ram_awlen ),
|
||||
.s_axi_awsize (ram_awsize ),
|
||||
.s_axi_awburst (ram_awburst ),
|
||||
.s_axi_awvalid (ram_awvalid ),
|
||||
.s_axi_awready (ram_awready ),
|
||||
//w
|
||||
.s_axi_wdata (ram_wdata ),
|
||||
.s_axi_wstrb (ram_wstrb ),
|
||||
.s_axi_wlast (ram_wlast ),
|
||||
.s_axi_wvalid (ram_wvalid ),
|
||||
.s_axi_wready (ram_wready ),
|
||||
//b
|
||||
.s_axi_bid (ram_bid ),
|
||||
.s_axi_bresp (ram_bresp ),
|
||||
.s_axi_bvalid (ram_bvalid ),
|
||||
.s_axi_bready (ram_bready )
|
||||
);
|
||||
|
||||
//ar
|
||||
assign ram_arid = axi_arid ;
|
||||
assign ram_araddr = axi_araddr ;
|
||||
assign ram_arlen = axi_arlen ;
|
||||
assign ram_arsize = axi_arsize ;
|
||||
assign ram_arburst = axi_arburst;
|
||||
assign ram_arlock = axi_arlock ;
|
||||
assign ram_arcache = axi_arcache;
|
||||
assign ram_arprot = axi_arprot ;
|
||||
assign ram_arvalid = axi_arvalid_m_masked;
|
||||
assign axi_arready_s_unmasked = ram_arready;
|
||||
//r
|
||||
assign axi_rid = axi_rvalid ? ram_rid : 4'd0 ;
|
||||
assign axi_rdata = axi_rvalid ? ram_rdata : 32'd0 ;
|
||||
assign axi_rresp = axi_rvalid ? ram_rresp : 2'd0 ;
|
||||
assign axi_rlast = axi_rvalid ? ram_rlast : 1'd0 ;
|
||||
assign axi_rvalid_s_unmasked = ram_rvalid;
|
||||
assign ram_rready = axi_rready_m_masked;
|
||||
//aw
|
||||
assign ram_awid = axi_awid ;
|
||||
assign ram_awaddr = axi_awaddr ;
|
||||
assign ram_awlen = axi_awlen ;
|
||||
assign ram_awsize = axi_awsize ;
|
||||
assign ram_awburst = axi_awburst;
|
||||
assign ram_awlock = axi_awlock ;
|
||||
assign ram_awcache = axi_awcache;
|
||||
assign ram_awprot = axi_awprot ;
|
||||
assign ram_awvalid = axi_awvalid_m_masked;
|
||||
assign axi_awready_s_unmasked = ram_awready;
|
||||
//w
|
||||
assign ram_wid = axi_wid ;
|
||||
assign ram_wdata = axi_wdata ;
|
||||
assign ram_wstrb = axi_wstrb ;
|
||||
assign ram_wlast = axi_wlast ;
|
||||
assign ram_wvalid = axi_wvalid_m_masked;
|
||||
assign axi_wready_s_unmasked = ram_wready ;
|
||||
//b
|
||||
assign axi_bid = axi_bvalid ? ram_bid : 4'd0 ;
|
||||
assign axi_bresp = axi_bvalid ? ram_bresp : 2'd0 ;
|
||||
assign axi_bvalid_s_unmasked = ram_bvalid ;
|
||||
assign ram_bready = axi_bready_m_masked;
|
||||
endmodule
|
@ -1,528 +0,0 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module soc_axi_lite_top #(parameter SIMULATION=1'b0)
|
||||
(
|
||||
input resetn,
|
||||
input clk,
|
||||
|
||||
//------gpio-------
|
||||
output [15:0] led,
|
||||
output [1 :0] led_rg0,
|
||||
output [1 :0] led_rg1,
|
||||
output [7 :0] num_csn,
|
||||
output [6 :0] num_a_g,
|
||||
input [7 :0] switch,
|
||||
output [3 :0] btn_key_col,
|
||||
input [3 :0] btn_key_row,
|
||||
input [1 :0] btn_step
|
||||
);
|
||||
//debug signals
|
||||
wire [31:0] debug_wb_pc;
|
||||
wire [3 :0] debug_wb_rf_wen;
|
||||
wire [4 :0] debug_wb_rf_wnum;
|
||||
wire [31:0] debug_wb_rf_wdata;
|
||||
wire [31:0] debug_wb1_pc;
|
||||
wire [3 :0] debug_wb1_rf_wen;
|
||||
wire [4 :0] debug_wb1_rf_wnum;
|
||||
wire [31:0] debug_wb1_rf_wdata;
|
||||
wire debug_wb_pc_A;
|
||||
|
||||
//cpu axi
|
||||
wire [3 :0] cpu_arid ;
|
||||
wire [31:0] cpu_araddr ;
|
||||
wire [3 :0] cpu_arlen ;
|
||||
wire [2 :0] cpu_arsize ;
|
||||
wire [1 :0] cpu_arburst;
|
||||
wire [1 :0] cpu_arlock ;
|
||||
wire [3 :0] cpu_arcache;
|
||||
wire [2 :0] cpu_arprot ;
|
||||
wire cpu_arvalid;
|
||||
wire cpu_arready;
|
||||
wire [3 :0] cpu_rid ;
|
||||
wire [31:0] cpu_rdata ;
|
||||
wire [1 :0] cpu_rresp ;
|
||||
wire cpu_rlast ;
|
||||
wire cpu_rvalid ;
|
||||
wire cpu_rready ;
|
||||
wire [3 :0] cpu_awid ;
|
||||
wire [31:0] cpu_awaddr ;
|
||||
wire [3 :0] cpu_awlen ;
|
||||
wire [2 :0] cpu_awsize ;
|
||||
wire [1 :0] cpu_awburst;
|
||||
wire [1 :0] cpu_awlock ;
|
||||
wire [3 :0] cpu_awcache;
|
||||
wire [2 :0] cpu_awprot ;
|
||||
wire cpu_awvalid;
|
||||
wire cpu_awready;
|
||||
wire [3 :0] cpu_wid ;
|
||||
wire [31:0] cpu_wdata ;
|
||||
wire [3 :0] cpu_wstrb ;
|
||||
wire cpu_wlast ;
|
||||
wire cpu_wvalid ;
|
||||
wire cpu_wready ;
|
||||
wire [3 :0] cpu_bid ;
|
||||
wire [1 :0] cpu_bresp ;
|
||||
wire cpu_bvalid ;
|
||||
wire cpu_bready ;
|
||||
|
||||
//cpu axi wrap
|
||||
wire cpu_wrap_aresetn;
|
||||
wire [3 :0] cpu_wrap_arid ;
|
||||
wire [31:0] cpu_wrap_araddr ;
|
||||
wire [3 :0] cpu_wrap_arlen ;
|
||||
wire [2 :0] cpu_wrap_arsize ;
|
||||
wire [1 :0] cpu_wrap_arburst;
|
||||
wire [1 :0] cpu_wrap_arlock ;
|
||||
wire [3 :0] cpu_wrap_arcache;
|
||||
wire [2 :0] cpu_wrap_arprot ;
|
||||
wire cpu_wrap_arvalid;
|
||||
wire cpu_wrap_arready;
|
||||
wire [3 :0] cpu_wrap_rid ;
|
||||
wire [31:0] cpu_wrap_rdata ;
|
||||
wire [1 :0] cpu_wrap_rresp ;
|
||||
wire cpu_wrap_rlast ;
|
||||
wire cpu_wrap_rvalid ;
|
||||
wire cpu_wrap_rready ;
|
||||
wire [3 :0] cpu_wrap_awid ;
|
||||
wire [31:0] cpu_wrap_awaddr ;
|
||||
wire [3 :0] cpu_wrap_awlen ;
|
||||
wire [2 :0] cpu_wrap_awsize ;
|
||||
wire [1 :0] cpu_wrap_awburst;
|
||||
wire [1 :0] cpu_wrap_awlock ;
|
||||
wire [3 :0] cpu_wrap_awcache;
|
||||
wire [2 :0] cpu_wrap_awprot ;
|
||||
wire cpu_wrap_awvalid;
|
||||
wire cpu_wrap_awready;
|
||||
wire [3 :0] cpu_wrap_wid ;
|
||||
wire [31:0] cpu_wrap_wdata ;
|
||||
wire [3 :0] cpu_wrap_wstrb ;
|
||||
wire cpu_wrap_wlast ;
|
||||
wire cpu_wrap_wvalid ;
|
||||
wire cpu_wrap_wready ;
|
||||
wire [3 :0] cpu_wrap_bid ;
|
||||
wire [1 :0] cpu_wrap_bresp ;
|
||||
wire cpu_wrap_bvalid ;
|
||||
wire cpu_wrap_bready ;
|
||||
|
||||
//axi ram
|
||||
wire [3 :0] ram_arid ;
|
||||
wire [31:0] ram_araddr ;
|
||||
wire [7 :0] ram_arlen ;
|
||||
wire [2 :0] ram_arsize ;
|
||||
wire [1 :0] ram_arburst;
|
||||
wire [1 :0] ram_arlock ;
|
||||
wire [3 :0] ram_arcache;
|
||||
wire [2 :0] ram_arprot ;
|
||||
wire ram_arvalid;
|
||||
wire ram_arready;
|
||||
wire [3 :0] ram_rid ;
|
||||
wire [31:0] ram_rdata ;
|
||||
wire [1 :0] ram_rresp ;
|
||||
wire ram_rlast ;
|
||||
wire ram_rvalid ;
|
||||
wire ram_rready ;
|
||||
wire [3 :0] ram_awid ;
|
||||
wire [31:0] ram_awaddr ;
|
||||
wire [7 :0] ram_awlen ;
|
||||
wire [2 :0] ram_awsize ;
|
||||
wire [1 :0] ram_awburst;
|
||||
wire [1 :0] ram_awlock ;
|
||||
wire [3 :0] ram_awcache;
|
||||
wire [2 :0] ram_awprot ;
|
||||
wire ram_awvalid;
|
||||
wire ram_awready;
|
||||
wire [3 :0] ram_wid ;
|
||||
wire [31:0] ram_wdata ;
|
||||
wire [3 :0] ram_wstrb ;
|
||||
wire ram_wlast ;
|
||||
wire ram_wvalid ;
|
||||
wire ram_wready ;
|
||||
wire [3 :0] ram_bid ;
|
||||
wire [1 :0] ram_bresp ;
|
||||
wire ram_bvalid ;
|
||||
wire ram_bready ;
|
||||
|
||||
//conf
|
||||
wire [3 :0] conf_arid ;
|
||||
wire [31:0] conf_araddr ;
|
||||
wire [7 :0] conf_arlen ;
|
||||
wire [2 :0] conf_arsize ;
|
||||
wire [1 :0] conf_arburst;
|
||||
wire [1 :0] conf_arlock ;
|
||||
wire [3 :0] conf_arcache;
|
||||
wire [2 :0] conf_arprot ;
|
||||
wire conf_arvalid;
|
||||
wire conf_arready;
|
||||
wire [3 :0] conf_rid ;
|
||||
wire [31:0] conf_rdata ;
|
||||
wire [1 :0] conf_rresp ;
|
||||
wire conf_rlast ;
|
||||
wire conf_rvalid ;
|
||||
wire conf_rready ;
|
||||
wire [3 :0] conf_awid ;
|
||||
wire [31:0] conf_awaddr ;
|
||||
wire [7 :0] conf_awlen ;
|
||||
wire [2 :0] conf_awsize ;
|
||||
wire [1 :0] conf_awburst;
|
||||
wire [1 :0] conf_awlock ;
|
||||
wire [3 :0] conf_awcache;
|
||||
wire [2 :0] conf_awprot ;
|
||||
wire conf_awvalid;
|
||||
wire conf_awready;
|
||||
wire [3 :0] conf_wid ;
|
||||
wire [31:0] conf_wdata ;
|
||||
wire [3 :0] conf_wstrb ;
|
||||
wire conf_wlast ;
|
||||
wire conf_wvalid ;
|
||||
wire conf_wready ;
|
||||
wire [3 :0] conf_bid ;
|
||||
wire [1 :0] conf_bresp ;
|
||||
wire conf_bvalid ;
|
||||
wire conf_bready ;
|
||||
|
||||
//for lab6
|
||||
wire [4 :0] ram_random_mask;
|
||||
|
||||
//cpu axi
|
||||
mycpu_top u_cpu(
|
||||
.ext_int (6'd0 ), //high active
|
||||
|
||||
.aclk (clk ),
|
||||
.aresetn (resetn ), //low active
|
||||
|
||||
.arid (cpu_arid ),
|
||||
.araddr (cpu_araddr ),
|
||||
.arlen (cpu_arlen ),
|
||||
.arsize (cpu_arsize ),
|
||||
.arburst (cpu_arburst ),
|
||||
.arlock (cpu_arlock ),
|
||||
.arcache (cpu_arcache ),
|
||||
.arprot (cpu_arprot ),
|
||||
.arvalid (cpu_arvalid ),
|
||||
.arready (cpu_arready ),
|
||||
|
||||
.rid (cpu_rid ),
|
||||
.rdata (cpu_rdata ),
|
||||
.rresp (cpu_rresp ),
|
||||
.rlast (cpu_rlast ),
|
||||
.rvalid (cpu_rvalid ),
|
||||
.rready (cpu_rready ),
|
||||
|
||||
.awid (cpu_awid ),
|
||||
.awaddr (cpu_awaddr ),
|
||||
.awlen (cpu_awlen ),
|
||||
.awsize (cpu_awsize ),
|
||||
.awburst (cpu_awburst ),
|
||||
.awlock (cpu_awlock ),
|
||||
.awcache (cpu_awcache ),
|
||||
.awprot (cpu_awprot ),
|
||||
.awvalid (cpu_awvalid ),
|
||||
.awready (cpu_awready ),
|
||||
|
||||
.wid (cpu_wid ),
|
||||
.wdata (cpu_wdata ),
|
||||
.wstrb (cpu_wstrb ),
|
||||
.wlast (cpu_wlast ),
|
||||
.wvalid (cpu_wvalid ),
|
||||
.wready (cpu_wready ),
|
||||
|
||||
.bid (cpu_bid ),
|
||||
.bresp (cpu_bresp ),
|
||||
.bvalid (cpu_bvalid ),
|
||||
.bready (cpu_bready ),
|
||||
|
||||
//debug interface
|
||||
.debug_wb_pc (debug_wb_pc ),
|
||||
.debug_wb_rf_wen (debug_wb_rf_wen ),
|
||||
.debug_wb_rf_wnum (debug_wb_rf_wnum ),
|
||||
.debug_wb_rf_wdata (debug_wb_rf_wdata ),
|
||||
.debug_wb1_pc (debug_wb1_pc ),
|
||||
.debug_wb1_rf_wen (debug_wb1_rf_wen ),
|
||||
.debug_wb1_rf_wnum (debug_wb1_rf_wnum ),
|
||||
.debug_wb1_rf_wdata(debug_wb1_rf_wdata),
|
||||
.debug_wb_pc_A (debug_wb_pc_A )
|
||||
);
|
||||
|
||||
//cpu axi wrap
|
||||
axi_wrap u_cpu_axi_wrap(
|
||||
.m_aclk ( clk ),
|
||||
.m_aresetn ( resetn ),
|
||||
//ar
|
||||
.m_arid ( cpu_arid ),
|
||||
.m_araddr ( cpu_araddr ),
|
||||
.m_arlen ( cpu_arlen ),
|
||||
.m_arsize ( cpu_arsize ),
|
||||
.m_arburst ( cpu_arburst ),
|
||||
.m_arlock ( cpu_arlock ),
|
||||
.m_arcache ( cpu_arcache ),
|
||||
.m_arprot ( cpu_arprot ),
|
||||
.m_arvalid ( cpu_arvalid ),
|
||||
.m_arready ( cpu_arready ),
|
||||
//r
|
||||
.m_rid ( cpu_rid ),
|
||||
.m_rdata ( cpu_rdata ),
|
||||
.m_rresp ( cpu_rresp ),
|
||||
.m_rlast ( cpu_rlast ),
|
||||
.m_rvalid ( cpu_rvalid ),
|
||||
.m_rready ( cpu_rready ),
|
||||
//aw
|
||||
.m_awid ( cpu_awid ),
|
||||
.m_awaddr ( cpu_awaddr ),
|
||||
.m_awlen ( cpu_awlen ),
|
||||
.m_awsize ( cpu_awsize ),
|
||||
.m_awburst ( cpu_awburst ),
|
||||
.m_awlock ( cpu_awlock ),
|
||||
.m_awcache ( cpu_awcache ),
|
||||
.m_awprot ( cpu_awprot ),
|
||||
.m_awvalid ( cpu_awvalid ),
|
||||
.m_awready ( cpu_awready ),
|
||||
//w
|
||||
.m_wid ( cpu_wid ),
|
||||
.m_wdata ( cpu_wdata ),
|
||||
.m_wstrb ( cpu_wstrb ),
|
||||
.m_wlast ( cpu_wlast ),
|
||||
.m_wvalid ( cpu_wvalid ),
|
||||
.m_wready ( cpu_wready ),
|
||||
//b
|
||||
.m_bid ( cpu_bid ),
|
||||
.m_bresp ( cpu_bresp ),
|
||||
.m_bvalid ( cpu_bvalid ),
|
||||
.m_bready ( cpu_bready ),
|
||||
|
||||
.s_aclk ( cpu_wrap_aclk ),
|
||||
.s_aresetn ( cpu_wrap_aresetn ),
|
||||
//ar
|
||||
.s_arid ( cpu_wrap_arid ),
|
||||
.s_araddr ( cpu_wrap_araddr ),
|
||||
.s_arlen ( cpu_wrap_arlen ),
|
||||
.s_arsize ( cpu_wrap_arsize ),
|
||||
.s_arburst ( cpu_wrap_arburst ),
|
||||
.s_arlock ( cpu_wrap_arlock ),
|
||||
.s_arcache ( cpu_wrap_arcache ),
|
||||
.s_arprot ( cpu_wrap_arprot ),
|
||||
.s_arvalid ( cpu_wrap_arvalid ),
|
||||
.s_arready ( cpu_wrap_arready ),
|
||||
//r
|
||||
.s_rid ( cpu_wrap_rid ),
|
||||
.s_rdata ( cpu_wrap_rdata ),
|
||||
.s_rresp ( cpu_wrap_rresp ),
|
||||
.s_rlast ( cpu_wrap_rlast ),
|
||||
.s_rvalid ( cpu_wrap_rvalid ),
|
||||
.s_rready ( cpu_wrap_rready ),
|
||||
//aw
|
||||
.s_awid ( cpu_wrap_awid ),
|
||||
.s_awaddr ( cpu_wrap_awaddr ),
|
||||
.s_awlen ( cpu_wrap_awlen ),
|
||||
.s_awsize ( cpu_wrap_awsize ),
|
||||
.s_awburst ( cpu_wrap_awburst ),
|
||||
.s_awlock ( cpu_wrap_awlock ),
|
||||
.s_awcache ( cpu_wrap_awcache ),
|
||||
.s_awprot ( cpu_wrap_awprot ),
|
||||
.s_awvalid ( cpu_wrap_awvalid ),
|
||||
.s_awready ( cpu_wrap_awready ),
|
||||
//w
|
||||
.s_wid ( cpu_wrap_wid ),
|
||||
.s_wdata ( cpu_wrap_wdata ),
|
||||
.s_wstrb ( cpu_wrap_wstrb ),
|
||||
.s_wlast ( cpu_wrap_wlast ),
|
||||
.s_wvalid ( cpu_wrap_wvalid ),
|
||||
.s_wready ( cpu_wrap_wready ),
|
||||
//b
|
||||
.s_bid ( cpu_wrap_bid ),
|
||||
.s_bresp ( cpu_wrap_bresp ),
|
||||
.s_bvalid ( cpu_wrap_bvalid ),
|
||||
.s_bready ( cpu_wrap_bready )
|
||||
);
|
||||
|
||||
axi_crossbar u_axi_crossbar_1x2(
|
||||
.clk ( clk ), // i, 1
|
||||
.rst ( ~resetn ), // i, 1
|
||||
|
||||
.s_axi_arid ( cpu_wrap_arid ),
|
||||
.s_axi_araddr ( cpu_wrap_araddr ),
|
||||
.s_axi_arlen ( cpu_wrap_arlen[3:0] ),
|
||||
.s_axi_arsize ( cpu_wrap_arsize ),
|
||||
.s_axi_arburst ( cpu_wrap_arburst ),
|
||||
.s_axi_arlock ( cpu_wrap_arlock ),
|
||||
.s_axi_arcache ( cpu_wrap_arcache ),
|
||||
.s_axi_arprot ( cpu_wrap_arprot ),
|
||||
.s_axi_arqos ( 4'd0 ),
|
||||
.s_axi_arvalid ( cpu_wrap_arvalid ),
|
||||
.s_axi_arready ( cpu_wrap_arready ),
|
||||
.s_axi_rid ( cpu_wrap_rid ),
|
||||
.s_axi_rdata ( cpu_wrap_rdata ),
|
||||
.s_axi_rresp ( cpu_wrap_rresp ),
|
||||
.s_axi_rlast ( cpu_wrap_rlast ),
|
||||
.s_axi_rvalid ( cpu_wrap_rvalid ),
|
||||
.s_axi_rready ( cpu_wrap_rready ),
|
||||
.s_axi_awid ( cpu_wrap_awid ),
|
||||
.s_axi_awaddr ( cpu_wrap_awaddr ),
|
||||
.s_axi_awlen ( cpu_wrap_awlen[3:0] ),
|
||||
.s_axi_awsize ( cpu_wrap_awsize ),
|
||||
.s_axi_awburst ( cpu_wrap_awburst ),
|
||||
.s_axi_awlock ( cpu_wrap_awlock ),
|
||||
.s_axi_awcache ( cpu_wrap_awcache ),
|
||||
.s_axi_awprot ( cpu_wrap_awprot ),
|
||||
.s_axi_awqos ( 4'd0 ),
|
||||
.s_axi_awvalid ( cpu_wrap_awvalid ),
|
||||
.s_axi_awready ( cpu_wrap_awready ),
|
||||
//.s_axi_wid ( cpu_wrap_wid ),
|
||||
.s_axi_wdata ( cpu_wrap_wdata ),
|
||||
.s_axi_wstrb ( cpu_wrap_wstrb ),
|
||||
.s_axi_wlast ( cpu_wrap_wlast ),
|
||||
.s_axi_wvalid ( cpu_wrap_wvalid ),
|
||||
.s_axi_wready ( cpu_wrap_wready ),
|
||||
.s_axi_bid ( cpu_wrap_bid ),
|
||||
.s_axi_bresp ( cpu_wrap_bresp ),
|
||||
.s_axi_bvalid ( cpu_wrap_bvalid ),
|
||||
.s_axi_bready ( cpu_wrap_bready ),
|
||||
|
||||
.m_axi_arid ( {ram_arid ,conf_arid } ),
|
||||
.m_axi_araddr ( {ram_araddr ,conf_araddr } ),
|
||||
.m_axi_arlen ( {ram_arlen ,conf_arlen } ),
|
||||
.m_axi_arsize ( {ram_arsize ,conf_arsize } ),
|
||||
.m_axi_arburst ( {ram_arburst,conf_arburst} ),
|
||||
.m_axi_arlock ( {ram_arlock ,conf_arlock } ),
|
||||
.m_axi_arcache ( {ram_arcache,conf_arcache} ),
|
||||
.m_axi_arprot ( {ram_arprot ,conf_arprot } ),
|
||||
.m_axi_arqos ( ),
|
||||
.m_axi_arvalid ( {ram_arvalid,conf_arvalid} ),
|
||||
.m_axi_arready ( {ram_arready,conf_arready} ),
|
||||
.m_axi_rid ( {ram_rid ,conf_rid } ),
|
||||
.m_axi_rdata ( {ram_rdata ,conf_rdata } ),
|
||||
.m_axi_rresp ( {ram_rresp ,conf_rresp } ),
|
||||
.m_axi_rlast ( {ram_rlast ,conf_rlast } ),
|
||||
.m_axi_rvalid ( {ram_rvalid ,conf_rvalid } ),
|
||||
.m_axi_rready ( {ram_rready ,conf_rready } ),
|
||||
.m_axi_awid ( {ram_awid ,conf_awid } ),
|
||||
.m_axi_awaddr ( {ram_awaddr ,conf_awaddr } ),
|
||||
.m_axi_awlen ( {ram_awlen ,conf_awlen } ),
|
||||
.m_axi_awsize ( {ram_awsize ,conf_awsize } ),
|
||||
.m_axi_awburst ( {ram_awburst,conf_awburst} ),
|
||||
.m_axi_awlock ( {ram_awlock ,conf_awlock } ),
|
||||
.m_axi_awcache ( {ram_awcache,conf_awcache} ),
|
||||
.m_axi_awprot ( {ram_awprot ,conf_awprot } ),
|
||||
.m_axi_awqos ( ),
|
||||
.m_axi_awvalid ( {ram_awvalid,conf_awvalid} ),
|
||||
.m_axi_awready ( {ram_awready,conf_awready} ),
|
||||
//.m_axi_wid ( {ram_wid ,conf_wid } ),
|
||||
.m_axi_wdata ( {ram_wdata ,conf_wdata } ),
|
||||
.m_axi_wstrb ( {ram_wstrb ,conf_wstrb } ),
|
||||
.m_axi_wlast ( {ram_wlast ,conf_wlast } ),
|
||||
.m_axi_wvalid ( {ram_wvalid ,conf_wvalid } ),
|
||||
.m_axi_wready ( {ram_wready ,conf_wready } ),
|
||||
.m_axi_bid ( {ram_bid ,conf_bid } ),
|
||||
.m_axi_bresp ( {ram_bresp ,conf_bresp } ),
|
||||
.m_axi_bvalid ( {ram_bvalid ,conf_bvalid } ),
|
||||
.m_axi_bready ( {ram_bready ,conf_bready } )
|
||||
);
|
||||
|
||||
//axi ram
|
||||
axi_wrap_ram u_axi_ram
|
||||
(
|
||||
.aclk ( clk ),
|
||||
.aresetn ( resetn ),
|
||||
//ar
|
||||
.axi_arid ( ram_arid ),
|
||||
.axi_araddr ( ram_araddr ),
|
||||
.axi_arlen ( ram_arlen ),
|
||||
.axi_arsize ( ram_arsize ),
|
||||
.axi_arburst ( ram_arburst ),
|
||||
.axi_arlock ( ram_arlock ),
|
||||
.axi_arcache ( ram_arcache ),
|
||||
.axi_arprot ( ram_arprot ),
|
||||
.axi_arvalid ( ram_arvalid ),
|
||||
.axi_arready ( ram_arready ),
|
||||
//r
|
||||
.axi_rid ( ram_rid ),
|
||||
.axi_rdata ( ram_rdata ),
|
||||
.axi_rresp ( ram_rresp ),
|
||||
.axi_rlast ( ram_rlast ),
|
||||
.axi_rvalid ( ram_rvalid ),
|
||||
.axi_rready ( ram_rready ),
|
||||
//aw
|
||||
.axi_awid ( ram_awid ),
|
||||
.axi_awaddr ( ram_awaddr ),
|
||||
.axi_awlen ( {4'd0,ram_awlen[3:0]} ),
|
||||
.axi_awsize ( ram_awsize ),
|
||||
.axi_awburst ( ram_awburst ),
|
||||
.axi_awlock ( ram_awlock ),
|
||||
.axi_awcache ( ram_awcache ),
|
||||
.axi_awprot ( ram_awprot ),
|
||||
.axi_awvalid ( ram_awvalid ),
|
||||
.axi_awready ( ram_awready ),
|
||||
//w
|
||||
.axi_wid ( ram_wid ),
|
||||
.axi_wdata ( ram_wdata ),
|
||||
.axi_wstrb ( ram_wstrb ),
|
||||
.axi_wlast ( ram_wlast ),
|
||||
.axi_wvalid ( ram_wvalid ),
|
||||
.axi_wready ( ram_wready ),
|
||||
//b ram
|
||||
.axi_bid ( ram_bid ),
|
||||
.axi_bresp ( ram_bresp ),
|
||||
.axi_bvalid ( ram_bvalid ),
|
||||
.axi_bready ( ram_bready ),
|
||||
|
||||
//random mask
|
||||
.ram_random_mask ( ram_random_mask )
|
||||
);
|
||||
|
||||
//confreg
|
||||
confreg #(.SIMULATION(SIMULATION)) u_confreg
|
||||
(
|
||||
.timer_clk ( clk ), // i, 1
|
||||
.aclk ( clk ), // i, 1
|
||||
.aresetn ( resetn ), // i, 1
|
||||
|
||||
.arid (conf_arid ),
|
||||
.araddr (conf_araddr ),
|
||||
.arlen (conf_arlen ),
|
||||
.arsize (conf_arsize ),
|
||||
.arburst (conf_arburst ),
|
||||
.arlock (conf_arlock ),
|
||||
.arcache (conf_arcache ),
|
||||
.arprot (conf_arprot ),
|
||||
.arvalid (conf_arvalid ),
|
||||
.arready (conf_arready ),
|
||||
.rid (conf_rid ),
|
||||
.rdata (conf_rdata ),
|
||||
.rresp (conf_rresp ),
|
||||
.rlast (conf_rlast ),
|
||||
.rvalid (conf_rvalid ),
|
||||
.rready (conf_rready ),
|
||||
.awid (conf_awid ),
|
||||
.awaddr (conf_awaddr ),
|
||||
.awlen (conf_awlen ),
|
||||
.awsize (conf_awsize ),
|
||||
.awburst (conf_awburst ),
|
||||
.awlock (conf_awlock ),
|
||||
.awcache (conf_awcache ),
|
||||
.awprot (conf_awprot ),
|
||||
.awvalid (conf_awvalid ),
|
||||
.awready (conf_awready ),
|
||||
.wid (conf_wid ),
|
||||
.wdata (conf_wdata ),
|
||||
.wstrb (conf_wstrb ),
|
||||
.wlast (conf_wlast ),
|
||||
.wvalid (conf_wvalid ),
|
||||
.wready (conf_wready ),
|
||||
.bid (conf_bid ),
|
||||
.bresp (conf_bresp ),
|
||||
.bvalid (conf_bvalid ),
|
||||
.bready (conf_bready ),
|
||||
|
||||
.ram_random_mask ( ram_random_mask ),
|
||||
.led ( led ), // o, 16
|
||||
.led_rg0 ( led_rg0 ), // o, 2
|
||||
.led_rg1 ( led_rg1 ), // o, 2
|
||||
.num_csn ( num_csn ), // o, 8
|
||||
.num_a_g ( num_a_g ), // o, 7
|
||||
.switch ( switch ), // i, 8
|
||||
.btn_key_col ( btn_key_col), // o, 4
|
||||
.btn_key_row ( btn_key_row), // i, 4
|
||||
.btn_step ( btn_step ) // i, 2
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
@ -1,176 +0,0 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
`define CONFREG_NUM_REG soc_lite.u_confreg.num_data
|
||||
`define CONFREG_NUM_MONITOR soc_lite.u_confreg.num_monitor
|
||||
|
||||
`define CONFREG_UART_DISPLAY soc_lite.u_confreg.write_uart_valid
|
||||
`define CONFREG_UART_DATA soc_lite.u_confreg.write_uart_data
|
||||
|
||||
`define END_PC 32'hbfc00100
|
||||
|
||||
module testbench_top ();
|
||||
logic resetn;
|
||||
logic clk;
|
||||
|
||||
//gpio
|
||||
logic [ 3:0] btn_key_col;
|
||||
logic [ 3:0] btn_key_row;
|
||||
logic [ 1:0] btn_step;
|
||||
|
||||
logic uart_display;
|
||||
logic [ 7:0] uart_data;
|
||||
logic [31:0] confreg_num_reg;
|
||||
logic [31:0] confreg_num_reg_r;
|
||||
|
||||
assign switch_sim = 8'hff;
|
||||
assign btn_key_row = 4'd0;
|
||||
assign btn_step = 2'd3;
|
||||
assign uart_display = `CONFREG_UART_DISPLAY;
|
||||
assign uart_data = `CONFREG_UART_DATA;
|
||||
assign confreg_num_reg = `CONFREG_NUM_REG;
|
||||
|
||||
// soc clk & debug info
|
||||
logic [31:0] debug_wb_pc;
|
||||
logic [ 3:0] debug_wb_rf_wen;
|
||||
logic [ 4:0] debug_wb_rf_wnum;
|
||||
logic [31:0] debug_wb_rf_wdata;
|
||||
logic [31:0] debug_wb1_pc;
|
||||
logic [ 3:0] debug_wb1_rf_wen;
|
||||
logic [ 4:0] debug_wb1_rf_wnum;
|
||||
logic [31:0] debug_wb1_rf_wdata;
|
||||
logic debug_wb_pc_A;
|
||||
logic [ 3:0] dbg_0_rf_wen;
|
||||
logic [31:0] dbg_0_pc;
|
||||
logic [ 4:0] dbg_0_rf_wnum;
|
||||
logic [31:0] dbg_0_rf_wdata;
|
||||
logic [ 3:0] dbg_1_rf_wen;
|
||||
logic [31:0] dbg_1_pc;
|
||||
logic [ 4:0] dbg_1_rf_wnum;
|
||||
logic [31:0] dbg_1_rf_wdata;
|
||||
assign debug_wb_pc = soc_lite.debug_wb_pc;
|
||||
assign debug_wb_rf_wen = soc_lite.debug_wb_rf_wen;
|
||||
assign debug_wb_rf_wnum = soc_lite.debug_wb_rf_wnum;
|
||||
assign debug_wb_rf_wdata = soc_lite.debug_wb_rf_wdata;
|
||||
assign debug_wb1_pc = soc_lite.u_cpu.debug_wb1_pc;
|
||||
assign debug_wb1_rf_wen = soc_lite.u_cpu.debug_wb1_rf_wen;
|
||||
assign debug_wb1_rf_wnum = soc_lite.u_cpu.debug_wb1_rf_wnum;
|
||||
assign debug_wb1_rf_wdata = soc_lite.u_cpu.debug_wb1_rf_wdata;
|
||||
assign debug_wb_pc_A = soc_lite.u_cpu.debug_wb_pc_A;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (debug_wb_pc_A) begin
|
||||
dbg_0_rf_wen <= debug_wb1_rf_wen;
|
||||
dbg_0_pc <= debug_wb1_pc;
|
||||
dbg_0_rf_wnum <= debug_wb1_rf_wnum;
|
||||
dbg_0_rf_wdata <= debug_wb1_rf_wdata;
|
||||
|
||||
dbg_1_rf_wen <= debug_wb_rf_wen;
|
||||
dbg_1_pc <= debug_wb_pc;
|
||||
dbg_1_rf_wnum <= debug_wb_rf_wnum;
|
||||
dbg_1_rf_wdata <= debug_wb_rf_wdata;
|
||||
end else begin
|
||||
dbg_1_rf_wen <= debug_wb1_rf_wen;
|
||||
dbg_1_pc <= debug_wb1_pc;
|
||||
dbg_1_rf_wnum <= debug_wb1_rf_wnum;
|
||||
dbg_1_rf_wdata <= debug_wb1_rf_wdata;
|
||||
|
||||
dbg_0_rf_wen <= debug_wb_rf_wen;
|
||||
dbg_0_pc <= debug_wb_pc;
|
||||
dbg_0_rf_wnum <= debug_wb_rf_wnum;
|
||||
dbg_0_rf_wdata <= debug_wb_rf_wdata;
|
||||
end
|
||||
|
||||
//if (|dbg_0_rf_wen & resetn) begin
|
||||
// $display("path0 : PC = 0x%8h, wb_rf_wnum = 0x%2h, wb_rf_wdata = 0x%8h, wen= %d",
|
||||
// dbg_0_pc, dbg_0_rf_wnum, dbg_0_rf_wdata, |dbg_0_rf_wen);
|
||||
//end
|
||||
//if (|dbg_1_rf_wen & resetn) begin
|
||||
// $display("path1 : PC = 0x%8h, wb_rf_wnum = 0x%2h, wb_rf_wdata = 0x%8h, wen= %d",
|
||||
// dbg_1_pc, dbg_1_rf_wnum, dbg_1_rf_wdata, |dbg_1_rf_wen);
|
||||
//end
|
||||
end
|
||||
|
||||
// UART
|
||||
always @(posedge clk) begin
|
||||
if (uart_display) begin
|
||||
if (uart_data == 8'hff) begin
|
||||
; //$finish;
|
||||
end else begin
|
||||
$write("%c", uart_data);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// Numeric Display
|
||||
logic [7:0] err_count;
|
||||
always_ff @(posedge clk) begin
|
||||
confreg_num_reg_r <= confreg_num_reg;
|
||||
if (!resetn) begin
|
||||
err_count <= 8'd0;
|
||||
end else if (confreg_num_reg_r != confreg_num_reg && `CONFREG_NUM_MONITOR) begin
|
||||
if (confreg_num_reg[7:0] != confreg_num_reg_r[7:0] + 1'b1) begin
|
||||
$display("--------------------------------------------------------------");
|
||||
$display("[%t] Error(%d)! Occurred in number 8'd%02d Functional Test Point!", $time, err_count, confreg_num_reg[31:24]);
|
||||
$display("--------------------------------------------------------------");
|
||||
err_count <= err_count + 1'b1;
|
||||
$finish;
|
||||
end else if (confreg_num_reg[31:24] != confreg_num_reg_r[31:24] + 1'b1) begin
|
||||
$display("--------------------------------------------------------------");
|
||||
$display("[%t] Error(%d)! Unknown, Functional Test Point numbers are unequal!", $time, err_count);
|
||||
$display("--------------------------------------------------------------");
|
||||
err_count <= err_count + 1'b1;
|
||||
$finish;
|
||||
end else begin
|
||||
$display("----[%t] Number 8'd%02d Functional Test Point PASS!", $time, confreg_num_reg[31:24]);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
//test end
|
||||
logic test_end;
|
||||
assign test_end = (dbg_0_pc == `END_PC) || (dbg_1_pc == `END_PC) || (uart_display && uart_data == 8'hff);
|
||||
always @(posedge clk)
|
||||
if (test_end) begin
|
||||
if (err_count != 0) begin
|
||||
$display("");
|
||||
$display("==============================================================");
|
||||
$display("Test end with ERROR!");
|
||||
end else begin
|
||||
$display("");
|
||||
$display("==============================================================");
|
||||
$display("Test end!");
|
||||
end
|
||||
$finish;
|
||||
end
|
||||
|
||||
soc_axi_lite_top #(
|
||||
.SIMULATION(1'b1)
|
||||
) soc_lite (
|
||||
.resetn(resetn),
|
||||
.clk (clk),
|
||||
|
||||
//------gpio-------
|
||||
.num_csn (num_csn),
|
||||
.num_a_g (num_a_g),
|
||||
.led (led),
|
||||
.led_rg0 (led_rg0),
|
||||
.led_rg1 (led_rg1),
|
||||
.switch (switch_sim),
|
||||
.btn_key_col(btn_key_col),
|
||||
.btn_key_row(btn_key_row),
|
||||
.btn_step (btn_step)
|
||||
);
|
||||
|
||||
initial begin
|
||||
resetn = 1'b0;
|
||||
#200;
|
||||
resetn = 1'b1;
|
||||
end
|
||||
|
||||
initial begin
|
||||
clk = 1'b0;
|
||||
forever #5 clk = ~clk;
|
||||
end
|
||||
|
||||
|
||||
endmodule
|
@ -16,6 +16,7 @@ VERILATOR_BUILD_FLAGS += --trace --trace-fst --trace-params --trace-structs --tr
|
||||
VERILATOR_BUILD_FLAGS += --assert
|
||||
VERILATOR_BUILD_FLAGS += --coverage
|
||||
#VERILATOR_BUILD_FLAGS += --report-unoptflat
|
||||
#VERILATOR_BUILD_FLAGS += --debug --debugi-V3Width 9
|
||||
|
||||
VERILATOR_COV_FLAGS += --annotate logs/annotated
|
||||
VERILATOR_COV_FLAGS += --annotate-min 1
|
||||
@ -27,11 +28,12 @@ VERILATOR_FLAGS += -sv -DSIMULATION_VERILATOR -DSIMULATION_PC
|
||||
####################
|
||||
# Sources #
|
||||
####################
|
||||
SOURCE = ./config.vlt $(wildcard ./model/*.v ./model/*.sv ../src/*.v ../src/*.sv ../src/**/*.v ../src/**/*.sv)
|
||||
INCLUDE = $(addprefix -I, $(dir $(wildcard ../src/*/. ../src/**/*/.)))
|
||||
MODEL_SOURCE = $(wildcard ./model/*.sv ./model/axi/src/axi_pkg.sv ./model/axi/src/axi_sim_mem.sv)
|
||||
SOURCE = ./config.vlt $(MODEL_SOURCE) $(wildcard ../src/*.v ../src/*.sv ../src/**/*.v ../src/**/*.sv)
|
||||
INCLUDE = $(addprefix -I, $(dir $(wildcard ../src/*/. ../src/**/*/. model/axi/include/.)))
|
||||
VERILATOR_INPUT = -top testbench_top sim_main.cpp
|
||||
|
||||
TB_FUNC_SOURCE = $(wildcard ../resources/tb.sv ../resources/func_test/*.v ../resources/func_test/**/*.v)
|
||||
TB_FUNC_SOURCE = $(wildcard ./top/*.sv ./top/*.v)
|
||||
|
||||
####################
|
||||
# Targets #
|
||||
|
@ -3,12 +3,11 @@ lint_off -rule TIMESCALEMOD
|
||||
lint_off -rule DECLFILENAME
|
||||
lint_off -rule UNUSEDSIGNAL
|
||||
|
||||
lint_off -file "model/*.v"
|
||||
lint_off -file "../resources/func_test/*.v"
|
||||
lint_off -file "top/*.v"
|
||||
lint_off -file "top/*.sv"
|
||||
//lint_off -file "model/*.sv"
|
||||
//lint_off -file "model/axi/src/*.sv"
|
||||
|
||||
lint_off -rule UNOPTFLAT -file "model/axi_crossbar_addr.v"
|
||||
lint_off -rule UNOPTFLAT -file "model/priority_encoder.v"
|
||||
lint_off -rule INITIALDLY -file "model/axi_crossbar_addr.v"
|
||||
lint_off -rule BLKSEQ -file "../src/CP0/CP0.sv"
|
||||
|
||||
lint_off -rule UNOPTFLAT
|
||||
|
@ -1,154 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2014-2021 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
|
||||
|
||||
`resetall
|
||||
`timescale 1ns / 1ps
|
||||
`default_nettype none
|
||||
|
||||
/*
|
||||
* Arbiter module
|
||||
*/
|
||||
module arbiter #
|
||||
(
|
||||
parameter PORTS = 4,
|
||||
// select round robin arbitration
|
||||
parameter ARB_TYPE_ROUND_ROBIN = 0,
|
||||
// blocking arbiter enable
|
||||
parameter ARB_BLOCK = 0,
|
||||
// block on acknowledge assert when nonzero, request deassert when 0
|
||||
parameter ARB_BLOCK_ACK = 1,
|
||||
// LSB priority selection
|
||||
parameter ARB_LSB_HIGH_PRIORITY = 0
|
||||
)
|
||||
(
|
||||
input wire clk,
|
||||
input wire rst,
|
||||
|
||||
input wire [PORTS-1:0] request,
|
||||
input wire [PORTS-1:0] acknowledge,
|
||||
|
||||
output wire [PORTS-1:0] grant,
|
||||
output wire grant_valid,
|
||||
output wire [$clog2(PORTS)-1:0] grant_encoded
|
||||
);
|
||||
|
||||
reg [PORTS-1:0] grant_reg = 0, grant_next;
|
||||
reg grant_valid_reg = 0, grant_valid_next;
|
||||
reg [$clog2(PORTS)-1:0] grant_encoded_reg = 0, grant_encoded_next;
|
||||
|
||||
assign grant_valid = grant_valid_reg;
|
||||
assign grant = grant_reg;
|
||||
assign grant_encoded = grant_encoded_reg;
|
||||
|
||||
wire request_valid;
|
||||
wire [$clog2(PORTS)-1:0] request_index;
|
||||
wire [PORTS-1:0] request_mask;
|
||||
|
||||
priority_encoder #(
|
||||
.WIDTH(PORTS),
|
||||
.LSB_HIGH_PRIORITY(ARB_LSB_HIGH_PRIORITY)
|
||||
)
|
||||
priority_encoder_inst (
|
||||
.input_unencoded(request),
|
||||
.output_valid(request_valid),
|
||||
.output_encoded(request_index),
|
||||
.output_unencoded(request_mask)
|
||||
);
|
||||
|
||||
reg [PORTS-1:0] mask_reg = 0, mask_next;
|
||||
|
||||
wire masked_request_valid;
|
||||
wire [$clog2(PORTS)-1:0] masked_request_index;
|
||||
wire [PORTS-1:0] masked_request_mask;
|
||||
|
||||
priority_encoder #(
|
||||
.WIDTH(PORTS),
|
||||
.LSB_HIGH_PRIORITY(ARB_LSB_HIGH_PRIORITY)
|
||||
)
|
||||
priority_encoder_masked (
|
||||
.input_unencoded(request & mask_reg),
|
||||
.output_valid(masked_request_valid),
|
||||
.output_encoded(masked_request_index),
|
||||
.output_unencoded(masked_request_mask)
|
||||
);
|
||||
|
||||
always @* begin
|
||||
grant_next = 0;
|
||||
grant_valid_next = 0;
|
||||
grant_encoded_next = 0;
|
||||
mask_next = mask_reg;
|
||||
|
||||
if (ARB_BLOCK && !ARB_BLOCK_ACK && grant_reg & request) begin
|
||||
// granted request still asserted; hold it
|
||||
grant_valid_next = grant_valid_reg;
|
||||
grant_next = grant_reg;
|
||||
grant_encoded_next = grant_encoded_reg;
|
||||
end else if (ARB_BLOCK && ARB_BLOCK_ACK && grant_valid && !(grant_reg & acknowledge)) begin
|
||||
// granted request not yet acknowledged; hold it
|
||||
grant_valid_next = grant_valid_reg;
|
||||
grant_next = grant_reg;
|
||||
grant_encoded_next = grant_encoded_reg;
|
||||
end else if (request_valid) begin
|
||||
if (ARB_TYPE_ROUND_ROBIN) begin
|
||||
if (masked_request_valid) begin
|
||||
grant_valid_next = 1;
|
||||
grant_next = masked_request_mask;
|
||||
grant_encoded_next = masked_request_index;
|
||||
if (ARB_LSB_HIGH_PRIORITY) begin
|
||||
mask_next = {PORTS{1'b1}} << (masked_request_index + 1);
|
||||
end else begin
|
||||
mask_next = {PORTS{1'b1}} >> (PORTS - masked_request_index);
|
||||
end
|
||||
end else begin
|
||||
grant_valid_next = 1;
|
||||
grant_next = request_mask;
|
||||
grant_encoded_next = request_index;
|
||||
if (ARB_LSB_HIGH_PRIORITY) begin
|
||||
mask_next = {PORTS{1'b1}} << (request_index + 1);
|
||||
end else begin
|
||||
mask_next = {PORTS{1'b1}} >> (PORTS - request_index);
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
grant_valid_next = 1;
|
||||
grant_next = request_mask;
|
||||
grant_encoded_next = request_index;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
grant_reg <= 0;
|
||||
grant_valid_reg <= 0;
|
||||
grant_encoded_reg <= 0;
|
||||
mask_reg <= 0;
|
||||
end else begin
|
||||
grant_reg <= grant_next;
|
||||
grant_valid_reg <= grant_valid_next;
|
||||
grant_encoded_reg <= grant_encoded_next;
|
||||
mask_reg <= mask_next;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
`resetall
|
1
sim/model/axi
Submodule
1
sim/model/axi
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit fccffb5953ec8564218ba05e20adbedec845e014
|
@ -1,386 +0,0 @@
|
||||
/*
|
||||
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
|
||||
|
||||
`resetall
|
||||
`timescale 1ns / 1ps
|
||||
`default_nettype none
|
||||
|
||||
/*
|
||||
* AXI4 crossbar
|
||||
*/
|
||||
module axi_crossbar #
|
||||
(
|
||||
// Number of AXI inputs (slave interfaces)
|
||||
parameter S_COUNT = 1,
|
||||
// Number of AXI outputs (master interfaces)
|
||||
parameter M_COUNT = 2,
|
||||
// Width of data bus in bits
|
||||
parameter DATA_WIDTH = 32,
|
||||
// Width of address bus in bits
|
||||
parameter ADDR_WIDTH = 32,
|
||||
// Width of wstrb (width of data bus in words)
|
||||
parameter STRB_WIDTH = (DATA_WIDTH/8),
|
||||
// Input ID field width (from AXI masters)
|
||||
parameter S_ID_WIDTH = 4,
|
||||
// Output ID field width (towards AXI slaves)
|
||||
// Additional bits required for response routing
|
||||
parameter M_ID_WIDTH = S_ID_WIDTH+$clog2(S_COUNT),
|
||||
// Propagate awuser signal
|
||||
parameter AWUSER_ENABLE = 0,
|
||||
// Width of awuser signal
|
||||
parameter AWUSER_WIDTH = 1,
|
||||
// Propagate wuser signal
|
||||
parameter WUSER_ENABLE = 0,
|
||||
// Width of wuser signal
|
||||
parameter WUSER_WIDTH = 1,
|
||||
// Propagate buser signal
|
||||
parameter BUSER_ENABLE = 0,
|
||||
// Width of buser signal
|
||||
parameter BUSER_WIDTH = 1,
|
||||
// Propagate aruser signal
|
||||
parameter ARUSER_ENABLE = 0,
|
||||
// Width of aruser signal
|
||||
parameter ARUSER_WIDTH = 1,
|
||||
// Propagate ruser signal
|
||||
parameter RUSER_ENABLE = 0,
|
||||
// Width of ruser signal
|
||||
parameter RUSER_WIDTH = 1,
|
||||
// Number of concurrent unique IDs for each slave interface
|
||||
// S_COUNT concatenated fields of 32 bits
|
||||
parameter S_THREADS = {S_COUNT{32'd2}},
|
||||
// Number of concurrent operations for each slave interface
|
||||
// S_COUNT concatenated fields of 32 bits
|
||||
parameter S_ACCEPT = {S_COUNT{32'd16}},
|
||||
// Number of regions per master interface
|
||||
parameter M_REGIONS = 5,
|
||||
// Master interface base addresses
|
||||
// M_COUNT concatenated fields of M_REGIONS concatenated fields of ADDR_WIDTH bits
|
||||
// set to zero for default addressing based on M_ADDR_WIDTH
|
||||
parameter M_BASE_ADDR = {{32'h1fc00000, 32'h20000000, 32'h40000000, 32'h80000000, 32'h0}, {32'h1faf0000, 32'hffffffff, 32'hffffffff, 32'hffffffff, 32'hffffffff}},
|
||||
// Master interface address widths
|
||||
// M_COUNT concatenated fields of M_REGIONS concatenated fields of 32 bits
|
||||
parameter M_ADDR_WIDTH = {{32'd22, 32'd29, 32'd30, 32'd28, 32'd28}, {32'd16, 32'd0, 32'd0, 32'd0, 32'd0}}, //{M_COUNT{{M_REGIONS{32'd24}}}},
|
||||
// Read connections between interfaces
|
||||
// M_COUNT concatenated fields of S_COUNT bits
|
||||
parameter M_CONNECT_READ = {M_COUNT{{S_COUNT{1'b1}}}},
|
||||
// Write connections between interfaces
|
||||
// M_COUNT concatenated fields of S_COUNT bits
|
||||
parameter M_CONNECT_WRITE = {M_COUNT{{S_COUNT{1'b1}}}},
|
||||
// Number of concurrent operations for each master interface
|
||||
// M_COUNT concatenated fields of 32 bits
|
||||
parameter M_ISSUE = {M_COUNT{32'd4}},
|
||||
// Secure master (fail operations based on awprot/arprot)
|
||||
// M_COUNT bits
|
||||
parameter M_SECURE = {M_COUNT{1'b0}},
|
||||
// Slave interface AW channel register type (input)
|
||||
// 0 to bypass, 1 for simple buffer, 2 for skid buffer
|
||||
parameter S_AW_REG_TYPE = {S_COUNT{2'd1}},
|
||||
// Slave interface W channel register type (input)
|
||||
// 0 to bypass, 1 for simple buffer, 2 for skid buffer
|
||||
parameter S_W_REG_TYPE = {S_COUNT{2'd1}},
|
||||
// Slave interface B channel register type (output)
|
||||
// 0 to bypass, 1 for simple buffer, 2 for skid buffer
|
||||
parameter S_B_REG_TYPE = {S_COUNT{2'd1}},
|
||||
// Slave interface AR channel register type (input)
|
||||
// 0 to bypass, 1 for simple buffer, 2 for skid buffer
|
||||
parameter S_AR_REG_TYPE = {S_COUNT{2'd1}},
|
||||
// Slave interface R channel register type (output)
|
||||
// 0 to bypass, 1 for simple buffer, 2 for skid buffer
|
||||
parameter S_R_REG_TYPE = {S_COUNT{2'd1}},
|
||||
// Master interface AW channel register type (output)
|
||||
// 0 to bypass, 1 for simple buffer, 2 for skid buffer
|
||||
parameter M_AW_REG_TYPE = {M_COUNT{2'd1}},
|
||||
// Master interface W channel register type (output)
|
||||
// 0 to bypass, 1 for simple buffer, 2 for skid buffer
|
||||
parameter M_W_REG_TYPE = {M_COUNT{2'd1}},
|
||||
// Master interface B channel register type (input)
|
||||
// 0 to bypass, 1 for simple buffer, 2 for skid buffer
|
||||
parameter M_B_REG_TYPE = {M_COUNT{2'd1}},
|
||||
// Master interface AR channel register type (output)
|
||||
// 0 to bypass, 1 for simple buffer, 2 for skid buffer
|
||||
parameter M_AR_REG_TYPE = {M_COUNT{2'd1}},
|
||||
// Master interface R channel register type (input)
|
||||
// 0 to bypass, 1 for simple buffer, 2 for skid buffer
|
||||
parameter M_R_REG_TYPE = {M_COUNT{2'd1}}
|
||||
)
|
||||
(
|
||||
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
|
||||
|
||||
`resetall
|
@ -1,413 +0,0 @@
|
||||
/*
|
||||
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
|
||||
|
||||
`resetall
|
||||
`timescale 1ns / 1ps
|
||||
`default_nettype none
|
||||
|
||||
/*
|
||||
* AXI4 crossbar address decode and admission control
|
||||
*/
|
||||
module axi_crossbar_addr #
|
||||
(
|
||||
// Slave interface index
|
||||
parameter S = 0,
|
||||
// Number of AXI inputs (slave interfaces)
|
||||
parameter S_COUNT = 4,
|
||||
// Number of AXI outputs (master interfaces)
|
||||
parameter M_COUNT = 4,
|
||||
// Width of address bus in bits
|
||||
parameter ADDR_WIDTH = 32,
|
||||
// ID field width
|
||||
parameter ID_WIDTH = 8,
|
||||
// Number of concurrent unique IDs
|
||||
parameter S_THREADS = 32'd2,
|
||||
// Number of concurrent operations
|
||||
parameter S_ACCEPT = 32'd16,
|
||||
// Number of regions per master interface
|
||||
parameter M_REGIONS = 1,
|
||||
// Master interface base addresses
|
||||
// M_COUNT concatenated fields of M_REGIONS concatenated fields of ADDR_WIDTH bits
|
||||
// set to zero for default addressing based on M_ADDR_WIDTH
|
||||
parameter M_BASE_ADDR = 0,
|
||||
// Master interface address widths
|
||||
// M_COUNT concatenated fields of M_REGIONS concatenated fields of 32 bits
|
||||
parameter M_ADDR_WIDTH = {M_COUNT{{M_REGIONS{32'd24}}}},
|
||||
// Connections between interfaces
|
||||
// M_COUNT concatenated fields of S_COUNT bits
|
||||
parameter M_CONNECT = {M_COUNT{{S_COUNT{1'b1}}}},
|
||||
// Secure master (fail operations based on awprot/arprot)
|
||||
// M_COUNT bits
|
||||
parameter M_SECURE = {M_COUNT{1'b0}},
|
||||
// Enable write command output
|
||||
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);
|
||||
|
||||
// default address computation
|
||||
function [M_COUNT*M_REGIONS*ADDR_WIDTH-1:0] calcBaseAddrs(input [31:0] dummy);
|
||||
integer i;
|
||||
reg [ADDR_WIDTH-1:0] base;
|
||||
reg [ADDR_WIDTH-1:0] width;
|
||||
reg [ADDR_WIDTH-1:0] size;
|
||||
reg [ADDR_WIDTH-1:0] mask;
|
||||
begin
|
||||
calcBaseAddrs = {M_COUNT*M_REGIONS*ADDR_WIDTH{1'b0}};
|
||||
base = 0;
|
||||
for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin
|
||||
width = M_ADDR_WIDTH[i*32 +: 32];
|
||||
mask = {ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - width);
|
||||
size = mask + 1;
|
||||
if (width > 0) begin
|
||||
if ((base & mask) != 0) begin
|
||||
base = base + size - (base & mask); // align
|
||||
end
|
||||
calcBaseAddrs[i * ADDR_WIDTH +: ADDR_WIDTH] = base;
|
||||
base = base + size; // increment
|
||||
end
|
||||
end
|
||||
end
|
||||
endfunction
|
||||
|
||||
parameter M_BASE_ADDR_INT = M_BASE_ADDR ? M_BASE_ADDR : calcBaseAddrs(0);
|
||||
|
||||
integer i, j;
|
||||
|
||||
// check configuration
|
||||
initial begin
|
||||
if (S_ACCEPT < 1) begin
|
||||
$error("Error: need at least 1 accept (instance %m)");
|
||||
$finish;
|
||||
end
|
||||
|
||||
if (S_THREADS < 1) begin
|
||||
$error("Error: need at least 1 thread (instance %m)");
|
||||
$finish;
|
||||
end
|
||||
|
||||
if (S_THREADS > S_ACCEPT) begin
|
||||
$warning("Warning: requested thread count larger than accept count; limiting thread count to accept count (instance %m)");
|
||||
end
|
||||
|
||||
if (M_REGIONS < 1) begin
|
||||
$error("Error: need at least 1 region (instance %m)");
|
||||
$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 (instance %m)");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
$display("Addressing configuration for axi_crossbar_addr instance %m");
|
||||
for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin
|
||||
if (M_ADDR_WIDTH[i*32 +: 32]) begin
|
||||
$display("%2d (%2d): %x / %02d -- %x-%x",
|
||||
i/M_REGIONS, i%M_REGIONS,
|
||||
M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH],
|
||||
M_ADDR_WIDTH[i*32 +: 32],
|
||||
M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[i*32 +: 32]),
|
||||
M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[i*32 +: 32]))
|
||||
);
|
||||
end
|
||||
end
|
||||
|
||||
for (i = 0; i < M_COUNT*M_REGIONS; i = i + 1) begin
|
||||
if ((M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] & (2**M_ADDR_WIDTH[i*32 +: 32]-1)) != 0) begin
|
||||
$display("Region not aligned:");
|
||||
$display("%2d (%2d): %x / %2d -- %x-%x",
|
||||
i/M_REGIONS, i%M_REGIONS,
|
||||
M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH],
|
||||
M_ADDR_WIDTH[i*32 +: 32],
|
||||
M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[i*32 +: 32]),
|
||||
M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[i*32 +: 32]))
|
||||
);
|
||||
$error("Error: address range not aligned (instance %m)");
|
||||
$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_INT[i*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[i*32 +: 32])) <= (M_BASE_ADDR_INT[j*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[j*32 +: 32]))))
|
||||
&& ((M_BASE_ADDR_INT[j*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[j*32 +: 32])) <= (M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[i*32 +: 32]))))) begin
|
||||
$display("Overlapping regions:");
|
||||
$display("%2d (%2d): %x / %2d -- %x-%x",
|
||||
i/M_REGIONS, i%M_REGIONS,
|
||||
M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH],
|
||||
M_ADDR_WIDTH[i*32 +: 32],
|
||||
M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[i*32 +: 32]),
|
||||
M_BASE_ADDR_INT[i*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[i*32 +: 32]))
|
||||
);
|
||||
$display("%2d (%2d): %x / %2d -- %x-%x",
|
||||
j/M_REGIONS, j%M_REGIONS,
|
||||
M_BASE_ADDR_INT[j*ADDR_WIDTH +: ADDR_WIDTH],
|
||||
M_ADDR_WIDTH[j*32 +: 32],
|
||||
M_BASE_ADDR_INT[j*ADDR_WIDTH +: ADDR_WIDTH] & ({ADDR_WIDTH{1'b1}} << M_ADDR_WIDTH[j*32 +: 32]),
|
||||
M_BASE_ADDR_INT[j*ADDR_WIDTH +: ADDR_WIDTH] | ({ADDR_WIDTH{1'b1}} >> (ADDR_WIDTH - M_ADDR_WIDTH[j*32 +: 32]))
|
||||
);
|
||||
$error("Error: address ranges overlap (instance %m)");
|
||||
$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 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 = 0, 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;
|
||||
|
||||
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_match_dest;
|
||||
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_match_dest[n] = thread_match[n] && thread_m_reg[n] == m_select_next && (M_REGIONS < 2 || thread_region_reg[n] == m_axi_aregion_next);
|
||||
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
|
||||
|
||||
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_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_INT[(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_dest || (!(&thread_active) && !thread_match))) 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
|
||||
|
||||
`resetall
|
@ -1,564 +0,0 @@
|
||||
/*
|
||||
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
|
||||
|
||||
`resetall
|
||||
`timescale 1ns / 1ps
|
||||
`default_nettype none
|
||||
|
||||
/*
|
||||
* AXI4 crossbar (read)
|
||||
*/
|
||||
module axi_crossbar_rd #
|
||||
(
|
||||
// Number of AXI inputs (slave interfaces)
|
||||
parameter S_COUNT = 4,
|
||||
// Number of AXI outputs (master interfaces)
|
||||
parameter M_COUNT = 4,
|
||||
// Width of data bus in bits
|
||||
parameter DATA_WIDTH = 32,
|
||||
// Width of address bus in bits
|
||||
parameter ADDR_WIDTH = 32,
|
||||
// Width of wstrb (width of data bus in words)
|
||||
parameter STRB_WIDTH = (DATA_WIDTH/8),
|
||||
// Input ID field width (from AXI masters)
|
||||
parameter S_ID_WIDTH = 8,
|
||||
// Output ID field width (towards AXI slaves)
|
||||
// Additional bits required for response routing
|
||||
parameter M_ID_WIDTH = S_ID_WIDTH+$clog2(S_COUNT),
|
||||
// Propagate aruser signal
|
||||
parameter ARUSER_ENABLE = 0,
|
||||
// Width of aruser signal
|
||||
parameter ARUSER_WIDTH = 1,
|
||||
// Propagate ruser signal
|
||||
parameter RUSER_ENABLE = 0,
|
||||
// Width of ruser signal
|
||||
parameter RUSER_WIDTH = 1,
|
||||
// Number of concurrent unique IDs for each slave interface
|
||||
// S_COUNT concatenated fields of 32 bits
|
||||
parameter S_THREADS = {S_COUNT{32'd2}},
|
||||
// Number of concurrent operations for each slave interface
|
||||
// S_COUNT concatenated fields of 32 bits
|
||||
parameter S_ACCEPT = {S_COUNT{32'd16}},
|
||||
// Number of regions per master interface
|
||||
parameter M_REGIONS = 1,
|
||||
// Master interface base addresses
|
||||
// M_COUNT concatenated fields of M_REGIONS concatenated fields of ADDR_WIDTH bits
|
||||
// set to zero for default addressing based on M_ADDR_WIDTH
|
||||
parameter M_BASE_ADDR = 0,
|
||||
// Master interface address widths
|
||||
// M_COUNT concatenated fields of M_REGIONS concatenated fields of 32 bits
|
||||
parameter M_ADDR_WIDTH = {M_COUNT{{M_REGIONS{32'd24}}}},
|
||||
// Read connections between interfaces
|
||||
// M_COUNT concatenated fields of S_COUNT bits
|
||||
parameter M_CONNECT = {M_COUNT{{S_COUNT{1'b1}}}},
|
||||
// Number of concurrent operations for each master interface
|
||||
// M_COUNT concatenated fields of 32 bits
|
||||
parameter M_ISSUE = {M_COUNT{32'd4}},
|
||||
// Secure master (fail operations based on awprot/arprot)
|
||||
// M_COUNT bits
|
||||
parameter M_SECURE = {M_COUNT{1'b0}},
|
||||
// Slave interface AR channel register type (input)
|
||||
// 0 to bypass, 1 for simple buffer, 2 for skid buffer
|
||||
parameter S_AR_REG_TYPE = {S_COUNT{2'd0}},
|
||||
// Slave interface R channel register type (output)
|
||||
// 0 to bypass, 1 for simple buffer, 2 for skid buffer
|
||||
parameter S_R_REG_TYPE = {S_COUNT{2'd2}},
|
||||
// Master interface AR channel register type (output)
|
||||
// 0 to bypass, 1 for simple buffer, 2 for skid buffer
|
||||
parameter M_AR_REG_TYPE = {M_COUNT{2'd1}},
|
||||
// Master interface R channel register type (input)
|
||||
// 0 to bypass, 1 for simple buffer, 2 for skid buffer
|
||||
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 (instance %m)");
|
||||
$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 (instance %m)");
|
||||
$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),
|
||||
.ARB_TYPE_ROUND_ROBIN(1),
|
||||
.ARB_BLOCK(1),
|
||||
.ARB_BLOCK_ACK(1),
|
||||
.ARB_LSB_HIGH_PRIORITY(1)
|
||||
)
|
||||
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[m*2 +: 2]),
|
||||
.R_REG_TYPE(S_R_REG_TYPE[m*2 +: 2])
|
||||
)
|
||||
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),
|
||||
.ARB_TYPE_ROUND_ROBIN(1),
|
||||
.ARB_BLOCK(1),
|
||||
.ARB_BLOCK_ACK(1),
|
||||
.ARB_LSB_HIGH_PRIORITY(1)
|
||||
)
|
||||
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[n*2 +: 2]),
|
||||
.R_REG_TYPE(M_R_REG_TYPE[n*2 +: 2])
|
||||
)
|
||||
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
|
||||
|
||||
`resetall
|
@ -1,673 +0,0 @@
|
||||
/*
|
||||
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
|
||||
|
||||
`resetall
|
||||
`timescale 1ns / 1ps
|
||||
`default_nettype none
|
||||
|
||||
/*
|
||||
* AXI4 crossbar (write)
|
||||
*/
|
||||
module axi_crossbar_wr #
|
||||
(
|
||||
// Number of AXI inputs (slave interfaces)
|
||||
parameter S_COUNT = 4,
|
||||
// Number of AXI outputs (master interfaces)
|
||||
parameter M_COUNT = 4,
|
||||
// Width of data bus in bits
|
||||
parameter DATA_WIDTH = 32,
|
||||
// Width of address bus in bits
|
||||
parameter ADDR_WIDTH = 32,
|
||||
// Width of wstrb (width of data bus in words)
|
||||
parameter STRB_WIDTH = (DATA_WIDTH/8),
|
||||
// Input ID field width (from AXI masters)
|
||||
parameter S_ID_WIDTH = 8,
|
||||
// Output ID field width (towards AXI slaves)
|
||||
// Additional bits required for response routing
|
||||
parameter M_ID_WIDTH = S_ID_WIDTH+$clog2(S_COUNT),
|
||||
// Propagate awuser signal
|
||||
parameter AWUSER_ENABLE = 0,
|
||||
// Width of awuser signal
|
||||
parameter AWUSER_WIDTH = 1,
|
||||
// Propagate wuser signal
|
||||
parameter WUSER_ENABLE = 0,
|
||||
// Width of wuser signal
|
||||
parameter WUSER_WIDTH = 1,
|
||||
// Propagate buser signal
|
||||
parameter BUSER_ENABLE = 0,
|
||||
// Width of buser signal
|
||||
parameter BUSER_WIDTH = 1,
|
||||
// Number of concurrent unique IDs for each slave interface
|
||||
// S_COUNT concatenated fields of 32 bits
|
||||
parameter S_THREADS = {S_COUNT{32'd2}},
|
||||
// Number of concurrent operations for each slave interface
|
||||
// S_COUNT concatenated fields of 32 bits
|
||||
parameter S_ACCEPT = {S_COUNT{32'd16}},
|
||||
// Number of regions per master interface
|
||||
parameter M_REGIONS = 1,
|
||||
// Master interface base addresses
|
||||
// M_COUNT concatenated fields of M_REGIONS concatenated fields of ADDR_WIDTH bits
|
||||
// set to zero for default addressing based on M_ADDR_WIDTH
|
||||
parameter M_BASE_ADDR = 0,
|
||||
// Master interface address widths
|
||||
// M_COUNT concatenated fields of M_REGIONS concatenated fields of 32 bits
|
||||
parameter M_ADDR_WIDTH = {M_COUNT{{M_REGIONS{32'd24}}}},
|
||||
// Write connections between interfaces
|
||||
// M_COUNT concatenated fields of S_COUNT bits
|
||||
parameter M_CONNECT = {M_COUNT{{S_COUNT{1'b1}}}},
|
||||
// Number of concurrent operations for each master interface
|
||||
// M_COUNT concatenated fields of 32 bits
|
||||
parameter M_ISSUE = {M_COUNT{32'd4}},
|
||||
// Secure master (fail operations based on awprot/arprot)
|
||||
// M_COUNT bits
|
||||
parameter M_SECURE = {M_COUNT{1'b0}},
|
||||
// Slave interface AW channel register type (input)
|
||||
// 0 to bypass, 1 for simple buffer, 2 for skid buffer
|
||||
parameter S_AW_REG_TYPE = {S_COUNT{2'd0}},
|
||||
// Slave interface W channel register type (input)
|
||||
// 0 to bypass, 1 for simple buffer, 2 for skid buffer
|
||||
parameter S_W_REG_TYPE = {S_COUNT{2'd0}},
|
||||
// Slave interface B channel register type (output)
|
||||
// 0 to bypass, 1 for simple buffer, 2 for skid buffer
|
||||
parameter S_B_REG_TYPE = {S_COUNT{2'd1}},
|
||||
// Master interface AW channel register type (output)
|
||||
// 0 to bypass, 1 for simple buffer, 2 for skid buffer
|
||||
parameter M_AW_REG_TYPE = {M_COUNT{2'd1}},
|
||||
// Master interface W channel register type (output)
|
||||
// 0 to bypass, 1 for simple buffer, 2 for skid buffer
|
||||
parameter M_W_REG_TYPE = {M_COUNT{2'd2}},
|
||||
// Master interface B channel register type (input)
|
||||
// 0 to bypass, 1 for simple buffer, 2 for skid buffer
|
||||
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 (instance %m)");
|
||||
$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 (instance %m)");
|
||||
$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),
|
||||
.ARB_TYPE_ROUND_ROBIN(1),
|
||||
.ARB_BLOCK(1),
|
||||
.ARB_BLOCK_ACK(1),
|
||||
.ARB_LSB_HIGH_PRIORITY(1)
|
||||
)
|
||||
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),
|
||||
.ARB_TYPE_ROUND_ROBIN(1),
|
||||
.ARB_BLOCK(1),
|
||||
.ARB_BLOCK_ACK(1),
|
||||
.ARB_LSB_HIGH_PRIORITY(1)
|
||||
)
|
||||
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 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 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 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
|
||||
|
||||
`resetall
|
@ -1,397 +0,0 @@
|
||||
/*
|
||||
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
|
||||
|
||||
`resetall
|
||||
`timescale 1ns / 1ps
|
||||
`default_nettype none
|
||||
|
||||
/*
|
||||
* AXI4 RAM
|
||||
*/
|
||||
module axi_ram #
|
||||
(
|
||||
// Width of data bus in bits
|
||||
parameter DATA_WIDTH = 32,
|
||||
// Width of address bus in bits
|
||||
parameter ADDR_WIDTH = 28,
|
||||
// Width of wstrb (width of data bus in words)
|
||||
parameter STRB_WIDTH = (DATA_WIDTH/8),
|
||||
// Width of ID signal
|
||||
parameter ID_WIDTH = 4,
|
||||
// Extra pipeline register on output
|
||||
parameter PIPELINE_OUTPUT = 0
|
||||
)
|
||||
(
|
||||
input wire s_aclk,
|
||||
input wire s_aresetn,
|
||||
|
||||
input wire [ID_WIDTH-1:0] s_axi_awid,
|
||||
input wire [ADDR_WIDTH-1:0] s_axi_awaddr,
|
||||
input wire [7:0] s_axi_awlen,
|
||||
input wire [2:0] s_axi_awsize,
|
||||
input wire [1:0] s_axi_awburst,
|
||||
input wire s_axi_awvalid,
|
||||
output wire s_axi_awready,
|
||||
input wire [DATA_WIDTH-1:0] s_axi_wdata,
|
||||
input wire [STRB_WIDTH-1:0] s_axi_wstrb,
|
||||
input wire s_axi_wlast,
|
||||
input wire s_axi_wvalid,
|
||||
output wire s_axi_wready,
|
||||
output wire [ID_WIDTH-1:0] s_axi_bid,
|
||||
output wire [1:0] s_axi_bresp,
|
||||
output wire s_axi_bvalid,
|
||||
input wire s_axi_bready,
|
||||
input wire [ID_WIDTH-1:0] s_axi_arid,
|
||||
input wire [ADDR_WIDTH-1:0] s_axi_araddr,
|
||||
input wire [7:0] s_axi_arlen,
|
||||
input wire [2:0] s_axi_arsize,
|
||||
input wire [1:0] s_axi_arburst,
|
||||
input wire s_axi_arvalid,
|
||||
output wire s_axi_arready,
|
||||
output wire [ID_WIDTH-1:0] s_axi_rid,
|
||||
output wire [DATA_WIDTH-1:0] s_axi_rdata,
|
||||
output wire [1:0] s_axi_rresp,
|
||||
output wire s_axi_rlast,
|
||||
output wire s_axi_rvalid,
|
||||
input wire s_axi_rready
|
||||
);
|
||||
|
||||
parameter VALID_ADDR_WIDTH = ADDR_WIDTH - $clog2(STRB_WIDTH);
|
||||
parameter WORD_WIDTH = STRB_WIDTH;
|
||||
parameter WORD_SIZE = DATA_WIDTH/WORD_WIDTH;
|
||||
|
||||
// bus width assertions
|
||||
initial begin
|
||||
if (WORD_SIZE * STRB_WIDTH != DATA_WIDTH) begin
|
||||
$error("Error: AXI data width not evenly divisble (instance %m)");
|
||||
$finish;
|
||||
end
|
||||
|
||||
if (2**$clog2(WORD_WIDTH) != WORD_WIDTH) begin
|
||||
$error("Error: AXI word width must be even power of two (instance %m)");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
localparam [0:0]
|
||||
READ_STATE_IDLE = 1'd0,
|
||||
READ_STATE_BURST = 1'd1;
|
||||
|
||||
reg [0:0] read_state_reg = READ_STATE_IDLE, read_state_next;
|
||||
|
||||
localparam [1:0]
|
||||
WRITE_STATE_IDLE = 2'd0,
|
||||
WRITE_STATE_BURST = 2'd1,
|
||||
WRITE_STATE_RESP = 2'd2;
|
||||
|
||||
reg [1:0] write_state_reg = WRITE_STATE_IDLE, write_state_next;
|
||||
|
||||
reg mem_wr_en;
|
||||
reg mem_rd_en;
|
||||
|
||||
reg [ID_WIDTH-1:0] read_id_reg = {ID_WIDTH{1'b0}}, read_id_next;
|
||||
reg [ADDR_WIDTH-1:0] read_addr_reg = {ADDR_WIDTH{1'b0}}, read_addr_next;
|
||||
reg [7:0] read_count_reg = 8'd0, read_count_next;
|
||||
reg [2:0] read_size_reg = 3'd0, read_size_next;
|
||||
reg [1:0] read_burst_reg = 2'd0, read_burst_next;
|
||||
reg [ID_WIDTH-1:0] write_id_reg = {ID_WIDTH{1'b0}}, write_id_next;
|
||||
reg [ADDR_WIDTH-1:0] write_addr_reg = {ADDR_WIDTH{1'b0}}, write_addr_next;
|
||||
reg [7:0] write_count_reg = 8'd0, write_count_next;
|
||||
reg [2:0] write_size_reg = 3'd0, write_size_next;
|
||||
reg [1:0] write_burst_reg = 2'd0, write_burst_next;
|
||||
|
||||
reg s_axi_awready_reg = 1'b0, s_axi_awready_next;
|
||||
reg s_axi_wready_reg = 1'b0, s_axi_wready_next;
|
||||
reg [ID_WIDTH-1:0] s_axi_bid_reg = {ID_WIDTH{1'b0}}, s_axi_bid_next;
|
||||
reg s_axi_bvalid_reg = 1'b0, s_axi_bvalid_next;
|
||||
reg s_axi_arready_reg = 1'b0, s_axi_arready_next;
|
||||
reg [ID_WIDTH-1:0] s_axi_rid_reg = {ID_WIDTH{1'b0}}, s_axi_rid_next;
|
||||
reg [DATA_WIDTH-1:0] s_axi_rdata_reg = {DATA_WIDTH{1'b0}}, s_axi_rdata_next;
|
||||
reg s_axi_rlast_reg = 1'b0, s_axi_rlast_next;
|
||||
reg s_axi_rvalid_reg = 1'b0, s_axi_rvalid_next;
|
||||
reg [ID_WIDTH-1:0] s_axi_rid_pipe_reg = {ID_WIDTH{1'b0}};
|
||||
reg [DATA_WIDTH-1:0] s_axi_rdata_pipe_reg = {DATA_WIDTH{1'b0}};
|
||||
reg s_axi_rlast_pipe_reg = 1'b0;
|
||||
reg s_axi_rvalid_pipe_reg = 1'b0;
|
||||
|
||||
// (* RAM_STYLE="BLOCK" *)
|
||||
reg [DATA_WIDTH-1:0] mem[(2**VALID_ADDR_WIDTH)-1:0];
|
||||
initial begin
|
||||
// ADDR_WIDTH = 28
|
||||
// (28 - 4)
|
||||
// |
|
||||
// v
|
||||
// 1ff0_0000: 0001 1111 1111 0000 0000 0000 0000 0000 -> 0x3fc0000
|
||||
// bfc0_0000: 1011 1111 1100 0000 0000 0000 0000 0000 -> 0x3f00000
|
||||
// 1fc0_0000: 0001 1111 1100 0000 0000 0000 0000 0000 -> 0x3f00000
|
||||
// 9fc0_0000: 1001 1111 1100 0000 0000 0000 0000 0000 -> 0x3f00000
|
||||
// 8800_0000: 1000 1000 0000 0000 0000 0000 0000 0000 -> 0x2000000
|
||||
// 8000_0000: 1000 0000 0000 0000 0000 0000 0000 0000 -> 0x0000000
|
||||
// |------------------------------|
|
||||
|
||||
$display("[%0t] Loading inst_ram.mif", $time);
|
||||
$readmemb("inst_ram.mif", mem, 'h3f00000);
|
||||
|
||||
$display("[%0t] Loading data_ram.mif", $time);
|
||||
$readmemb("data_ram.mif", mem, 'h40);
|
||||
|
||||
$display("[%0t] ram[0x3f00000] = 0x%0h", $time, mem['h3f00000]);
|
||||
$display("[%0t] ram[0x3f00001] = 0x%0h", $time, mem['h3f00001]);
|
||||
$display("[%0t] ram[0x3f00002] = 0x%0h", $time, mem['h3f00002]);
|
||||
$display("[%0t] ram[0x40] = 0x%0h", $time, mem['h40]);
|
||||
$display("[%0t] ram[0x1000000] = 0x%0h", $time, mem['h1000000]);
|
||||
$display("[%0t] ram[0x1000001] = 0x%0h", $time, mem['h1000001]);
|
||||
$display("[%0t] ram[0x1000002] = 0x%0h", $time, mem['h1000002]);
|
||||
end
|
||||
|
||||
reg [31:0] trace_before = 0;
|
||||
always @(posedge s_aclk) begin
|
||||
if (mem['h1000000] != trace_before) begin
|
||||
trace_before <= mem['h1000000];
|
||||
$display("[%0t] ram[0x1000000] = 0x%0h, before = 0x%0h", $time, mem['h1000000], trace_before);
|
||||
end
|
||||
end
|
||||
|
||||
wire [VALID_ADDR_WIDTH-1:0] s_axi_awaddr_valid = s_axi_awaddr >> (ADDR_WIDTH - VALID_ADDR_WIDTH);
|
||||
wire [VALID_ADDR_WIDTH-1:0] s_axi_araddr_valid = s_axi_araddr >> (ADDR_WIDTH - VALID_ADDR_WIDTH);
|
||||
wire [VALID_ADDR_WIDTH-1:0] read_addr_valid = read_addr_reg >> (ADDR_WIDTH - VALID_ADDR_WIDTH);
|
||||
wire [VALID_ADDR_WIDTH-1:0] write_addr_valid = write_addr_reg >> (ADDR_WIDTH - VALID_ADDR_WIDTH);
|
||||
|
||||
assign s_axi_awready = s_axi_awready_reg;
|
||||
assign s_axi_wready = s_axi_wready_reg;
|
||||
assign s_axi_bid = s_axi_bid_reg;
|
||||
assign s_axi_bresp = 2'b00;
|
||||
assign s_axi_bvalid = s_axi_bvalid_reg;
|
||||
assign s_axi_arready = s_axi_arready_reg;
|
||||
assign s_axi_rid = PIPELINE_OUTPUT ? s_axi_rid_pipe_reg : s_axi_rid_reg;
|
||||
assign s_axi_rdata = PIPELINE_OUTPUT ? s_axi_rdata_pipe_reg : s_axi_rdata_reg;
|
||||
assign s_axi_rresp = 2'b00;
|
||||
assign s_axi_rlast = PIPELINE_OUTPUT ? s_axi_rlast_pipe_reg : s_axi_rlast_reg;
|
||||
assign s_axi_rvalid = PIPELINE_OUTPUT ? s_axi_rvalid_pipe_reg : s_axi_rvalid_reg;
|
||||
|
||||
integer i, j;
|
||||
|
||||
// initial begin
|
||||
// // two nested loops for smaller number of iterations per loop
|
||||
// // workaround for synthesizer complaints about large loop counts
|
||||
// for (i = 0; i < 2**VALID_ADDR_WIDTH; i = i + 2**(VALID_ADDR_WIDTH/2)) begin
|
||||
// for (j = i; j < i + 2**(VALID_ADDR_WIDTH/2); j = j + 1) begin
|
||||
// mem[j] = 0;
|
||||
// end
|
||||
// end
|
||||
// end
|
||||
|
||||
always @* begin
|
||||
write_state_next = WRITE_STATE_IDLE;
|
||||
|
||||
mem_wr_en = 1'b0;
|
||||
|
||||
write_id_next = write_id_reg;
|
||||
write_addr_next = write_addr_reg;
|
||||
write_count_next = write_count_reg;
|
||||
write_size_next = write_size_reg;
|
||||
write_burst_next = write_burst_reg;
|
||||
|
||||
s_axi_awready_next = 1'b0;
|
||||
s_axi_wready_next = 1'b0;
|
||||
s_axi_bid_next = s_axi_bid_reg;
|
||||
s_axi_bvalid_next = s_axi_bvalid_reg && !s_axi_bready;
|
||||
|
||||
case (write_state_reg)
|
||||
WRITE_STATE_IDLE: begin
|
||||
s_axi_awready_next = 1'b1;
|
||||
|
||||
if (s_axi_awready && s_axi_awvalid) begin
|
||||
write_id_next = s_axi_awid;
|
||||
write_addr_next = s_axi_awaddr;
|
||||
write_count_next = s_axi_awlen;
|
||||
write_size_next = s_axi_awsize < $clog2(STRB_WIDTH) ? s_axi_awsize : $clog2(STRB_WIDTH);
|
||||
write_burst_next = s_axi_awburst;
|
||||
|
||||
s_axi_awready_next = 1'b0;
|
||||
s_axi_wready_next = 1'b1;
|
||||
write_state_next = WRITE_STATE_BURST;
|
||||
end else begin
|
||||
write_state_next = WRITE_STATE_IDLE;
|
||||
end
|
||||
end
|
||||
WRITE_STATE_BURST: begin
|
||||
s_axi_wready_next = 1'b1;
|
||||
|
||||
if (s_axi_wready && s_axi_wvalid) begin
|
||||
mem_wr_en = 1'b1;
|
||||
if (write_burst_reg != 2'b00) begin
|
||||
write_addr_next = write_addr_reg + (1 << write_size_reg);
|
||||
end
|
||||
write_count_next = write_count_reg - 1;
|
||||
if (write_count_reg > 0) begin
|
||||
write_state_next = WRITE_STATE_BURST;
|
||||
end else begin
|
||||
s_axi_wready_next = 1'b0;
|
||||
if (s_axi_bready || !s_axi_bvalid) begin
|
||||
s_axi_bid_next = write_id_reg;
|
||||
s_axi_bvalid_next = 1'b1;
|
||||
s_axi_awready_next = 1'b1;
|
||||
write_state_next = WRITE_STATE_IDLE;
|
||||
end else begin
|
||||
write_state_next = WRITE_STATE_RESP;
|
||||
end
|
||||
end
|
||||
end else begin
|
||||
write_state_next = WRITE_STATE_BURST;
|
||||
end
|
||||
end
|
||||
WRITE_STATE_RESP: begin
|
||||
if (s_axi_bready || !s_axi_bvalid) begin
|
||||
s_axi_bid_next = write_id_reg;
|
||||
s_axi_bvalid_next = 1'b1;
|
||||
s_axi_awready_next = 1'b1;
|
||||
write_state_next = WRITE_STATE_IDLE;
|
||||
end else begin
|
||||
write_state_next = WRITE_STATE_RESP;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
always @(posedge s_aclk) begin
|
||||
write_state_reg <= write_state_next;
|
||||
|
||||
write_id_reg <= write_id_next;
|
||||
write_addr_reg <= write_addr_next;
|
||||
write_count_reg <= write_count_next;
|
||||
write_size_reg <= write_size_next;
|
||||
write_burst_reg <= write_burst_next;
|
||||
|
||||
s_axi_awready_reg <= s_axi_awready_next;
|
||||
s_axi_wready_reg <= s_axi_wready_next;
|
||||
s_axi_bid_reg <= s_axi_bid_next;
|
||||
s_axi_bvalid_reg <= s_axi_bvalid_next;
|
||||
|
||||
for (i = 0; i < WORD_WIDTH; i = i + 1) begin
|
||||
if (mem_wr_en & s_axi_wstrb[i]) begin
|
||||
mem[write_addr_valid][WORD_SIZE*i +: WORD_SIZE] <= s_axi_wdata[WORD_SIZE*i +: WORD_SIZE];
|
||||
end
|
||||
end
|
||||
|
||||
if (~s_aresetn) begin
|
||||
write_state_reg <= WRITE_STATE_IDLE;
|
||||
|
||||
s_axi_awready_reg <= 1'b0;
|
||||
s_axi_wready_reg <= 1'b0;
|
||||
s_axi_bvalid_reg <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
always @* begin
|
||||
read_state_next = READ_STATE_IDLE;
|
||||
|
||||
mem_rd_en = 1'b0;
|
||||
|
||||
s_axi_rid_next = s_axi_rid_reg;
|
||||
s_axi_rlast_next = s_axi_rlast_reg;
|
||||
s_axi_rvalid_next = s_axi_rvalid_reg && !(s_axi_rready || (PIPELINE_OUTPUT && !s_axi_rvalid_pipe_reg));
|
||||
|
||||
read_id_next = read_id_reg;
|
||||
read_addr_next = read_addr_reg;
|
||||
read_count_next = read_count_reg;
|
||||
read_size_next = read_size_reg;
|
||||
read_burst_next = read_burst_reg;
|
||||
|
||||
s_axi_arready_next = 1'b0;
|
||||
|
||||
case (read_state_reg)
|
||||
READ_STATE_IDLE: begin
|
||||
s_axi_arready_next = 1'b1;
|
||||
|
||||
if (s_axi_arready && s_axi_arvalid) begin
|
||||
read_id_next = s_axi_arid;
|
||||
read_addr_next = s_axi_araddr;
|
||||
read_count_next = s_axi_arlen;
|
||||
read_size_next = s_axi_arsize < $clog2(STRB_WIDTH) ? s_axi_arsize : $clog2(STRB_WIDTH);
|
||||
read_burst_next = s_axi_arburst;
|
||||
|
||||
s_axi_arready_next = 1'b0;
|
||||
read_state_next = READ_STATE_BURST;
|
||||
end else begin
|
||||
read_state_next = READ_STATE_IDLE;
|
||||
end
|
||||
end
|
||||
READ_STATE_BURST: begin
|
||||
if (s_axi_rready || (PIPELINE_OUTPUT && !s_axi_rvalid_pipe_reg) || !s_axi_rvalid_reg) begin
|
||||
mem_rd_en = 1'b1;
|
||||
s_axi_rvalid_next = 1'b1;
|
||||
s_axi_rid_next = read_id_reg;
|
||||
s_axi_rlast_next = read_count_reg == 0;
|
||||
if (read_burst_reg != 2'b00) begin
|
||||
read_addr_next = read_addr_reg + (1 << read_size_reg);
|
||||
end
|
||||
read_count_next = read_count_reg - 1;
|
||||
if (read_count_reg > 0) begin
|
||||
read_state_next = READ_STATE_BURST;
|
||||
end else begin
|
||||
s_axi_arready_next = 1'b1;
|
||||
read_state_next = READ_STATE_IDLE;
|
||||
end
|
||||
end else begin
|
||||
read_state_next = READ_STATE_BURST;
|
||||
end
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
always @(posedge s_aclk) begin
|
||||
read_state_reg <= read_state_next;
|
||||
|
||||
read_id_reg <= read_id_next;
|
||||
read_addr_reg <= read_addr_next;
|
||||
read_count_reg <= read_count_next;
|
||||
read_size_reg <= read_size_next;
|
||||
read_burst_reg <= read_burst_next;
|
||||
|
||||
s_axi_arready_reg <= s_axi_arready_next;
|
||||
s_axi_rid_reg <= s_axi_rid_next;
|
||||
s_axi_rlast_reg <= s_axi_rlast_next;
|
||||
s_axi_rvalid_reg <= s_axi_rvalid_next;
|
||||
|
||||
if (mem_rd_en) begin
|
||||
s_axi_rdata_reg <= mem[read_addr_valid];
|
||||
end
|
||||
|
||||
if (!s_axi_rvalid_pipe_reg || s_axi_rready) begin
|
||||
s_axi_rid_pipe_reg <= s_axi_rid_reg;
|
||||
s_axi_rdata_pipe_reg <= s_axi_rdata_reg;
|
||||
s_axi_rlast_pipe_reg <= s_axi_rlast_reg;
|
||||
s_axi_rvalid_pipe_reg <= s_axi_rvalid_reg;
|
||||
end
|
||||
|
||||
if (~s_aresetn) begin
|
||||
read_state_reg <= READ_STATE_IDLE;
|
||||
|
||||
s_axi_arready_reg <= 1'b0;
|
||||
s_axi_rvalid_reg <= 1'b0;
|
||||
s_axi_rvalid_pipe_reg <= 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
endmodule
|
||||
|
||||
`resetall
|
@ -1,530 +0,0 @@
|
||||
/*
|
||||
|
||||
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
|
||||
|
||||
`resetall
|
||||
`timescale 1ns / 1ps
|
||||
`default_nettype none
|
||||
|
||||
/*
|
||||
* AXI4 register (read)
|
||||
*/
|
||||
module axi_register_rd #
|
||||
(
|
||||
// Width of data bus in bits
|
||||
parameter DATA_WIDTH = 32,
|
||||
// Width of address bus in bits
|
||||
parameter ADDR_WIDTH = 32,
|
||||
// Width of wstrb (width of data bus in words)
|
||||
parameter STRB_WIDTH = (DATA_WIDTH/8),
|
||||
// Width of ID signal
|
||||
parameter ID_WIDTH = 8,
|
||||
// Propagate aruser signal
|
||||
parameter ARUSER_ENABLE = 0,
|
||||
// Width of aruser signal
|
||||
parameter ARUSER_WIDTH = 1,
|
||||
// Propagate ruser signal
|
||||
parameter RUSER_ENABLE = 0,
|
||||
// Width of ruser signal
|
||||
parameter RUSER_WIDTH = 1,
|
||||
// AR channel register type
|
||||
// 0 to bypass, 1 for simple buffer, 2 for skid buffer
|
||||
parameter AR_REG_TYPE = 1,
|
||||
// R channel register type
|
||||
// 0 to bypass, 1 for simple buffer, 2 for skid buffer
|
||||
parameter R_REG_TYPE = 2
|
||||
)
|
||||
(
|
||||
input wire clk,
|
||||
input wire rst,
|
||||
|
||||
/*
|
||||
* AXI slave interface
|
||||
*/
|
||||
input wire [ID_WIDTH-1:0] s_axi_arid,
|
||||
input wire [ADDR_WIDTH-1:0] s_axi_araddr,
|
||||
input wire [7:0] s_axi_arlen,
|
||||
input wire [2:0] s_axi_arsize,
|
||||
input wire [1:0] s_axi_arburst,
|
||||
input wire s_axi_arlock,
|
||||
input wire [3:0] s_axi_arcache,
|
||||
input wire [2:0] s_axi_arprot,
|
||||
input wire [3:0] s_axi_arqos,
|
||||
input wire [3:0] s_axi_arregion,
|
||||
input wire [ARUSER_WIDTH-1:0] s_axi_aruser,
|
||||
input wire s_axi_arvalid,
|
||||
output wire s_axi_arready,
|
||||
output wire [ID_WIDTH-1:0] s_axi_rid,
|
||||
output wire [DATA_WIDTH-1:0] s_axi_rdata,
|
||||
output wire [1:0] s_axi_rresp,
|
||||
output wire s_axi_rlast,
|
||||
output wire [RUSER_WIDTH-1:0] s_axi_ruser,
|
||||
output wire s_axi_rvalid,
|
||||
input wire s_axi_rready,
|
||||
|
||||
/*
|
||||
* AXI master interface
|
||||
*/
|
||||
output wire [ID_WIDTH-1:0] m_axi_arid,
|
||||
output wire [ADDR_WIDTH-1:0] m_axi_araddr,
|
||||
output wire [7:0] m_axi_arlen,
|
||||
output wire [2:0] m_axi_arsize,
|
||||
output wire [1:0] m_axi_arburst,
|
||||
output wire m_axi_arlock,
|
||||
output wire [3:0] m_axi_arcache,
|
||||
output wire [2:0] m_axi_arprot,
|
||||
output wire [3:0] m_axi_arqos,
|
||||
output wire [3:0] m_axi_arregion,
|
||||
output wire [ARUSER_WIDTH-1:0] m_axi_aruser,
|
||||
output wire m_axi_arvalid,
|
||||
input wire m_axi_arready,
|
||||
input wire [ID_WIDTH-1:0] m_axi_rid,
|
||||
input wire [DATA_WIDTH-1:0] m_axi_rdata,
|
||||
input wire [1:0] m_axi_rresp,
|
||||
input wire m_axi_rlast,
|
||||
input wire [RUSER_WIDTH-1:0] m_axi_ruser,
|
||||
input wire m_axi_rvalid,
|
||||
output wire m_axi_rready
|
||||
);
|
||||
|
||||
generate
|
||||
|
||||
// AR channel
|
||||
|
||||
if (AR_REG_TYPE > 1) begin
|
||||
// skid buffer, no bubble cycles
|
||||
|
||||
// datapath registers
|
||||
reg s_axi_arready_reg = 1'b0;
|
||||
|
||||
reg [ID_WIDTH-1:0] m_axi_arid_reg = {ID_WIDTH{1'b0}};
|
||||
reg [ADDR_WIDTH-1:0] m_axi_araddr_reg = {ADDR_WIDTH{1'b0}};
|
||||
reg [7:0] m_axi_arlen_reg = 8'd0;
|
||||
reg [2:0] m_axi_arsize_reg = 3'd0;
|
||||
reg [1:0] m_axi_arburst_reg = 2'd0;
|
||||
reg m_axi_arlock_reg = 1'b0;
|
||||
reg [3:0] m_axi_arcache_reg = 4'd0;
|
||||
reg [2:0] m_axi_arprot_reg = 3'd0;
|
||||
reg [3:0] m_axi_arqos_reg = 4'd0;
|
||||
reg [3:0] m_axi_arregion_reg = 4'd0;
|
||||
reg [ARUSER_WIDTH-1:0] m_axi_aruser_reg = {ARUSER_WIDTH{1'b0}};
|
||||
reg m_axi_arvalid_reg = 1'b0, m_axi_arvalid_next;
|
||||
|
||||
reg [ID_WIDTH-1:0] temp_m_axi_arid_reg = {ID_WIDTH{1'b0}};
|
||||
reg [ADDR_WIDTH-1:0] temp_m_axi_araddr_reg = {ADDR_WIDTH{1'b0}};
|
||||
reg [7:0] temp_m_axi_arlen_reg = 8'd0;
|
||||
reg [2:0] temp_m_axi_arsize_reg = 3'd0;
|
||||
reg [1:0] temp_m_axi_arburst_reg = 2'd0;
|
||||
reg temp_m_axi_arlock_reg = 1'b0;
|
||||
reg [3:0] temp_m_axi_arcache_reg = 4'd0;
|
||||
reg [2:0] temp_m_axi_arprot_reg = 3'd0;
|
||||
reg [3:0] temp_m_axi_arqos_reg = 4'd0;
|
||||
reg [3:0] temp_m_axi_arregion_reg = 4'd0;
|
||||
reg [ARUSER_WIDTH-1:0] temp_m_axi_aruser_reg = {ARUSER_WIDTH{1'b0}};
|
||||
reg temp_m_axi_arvalid_reg = 1'b0, temp_m_axi_arvalid_next;
|
||||
|
||||
// datapath control
|
||||
reg store_axi_ar_input_to_output;
|
||||
reg store_axi_ar_input_to_temp;
|
||||
reg store_axi_ar_temp_to_output;
|
||||
|
||||
assign s_axi_arready = s_axi_arready_reg;
|
||||
|
||||
assign m_axi_arid = m_axi_arid_reg;
|
||||
assign m_axi_araddr = m_axi_araddr_reg;
|
||||
assign m_axi_arlen = m_axi_arlen_reg;
|
||||
assign m_axi_arsize = m_axi_arsize_reg;
|
||||
assign m_axi_arburst = m_axi_arburst_reg;
|
||||
assign m_axi_arlock = m_axi_arlock_reg;
|
||||
assign m_axi_arcache = m_axi_arcache_reg;
|
||||
assign m_axi_arprot = m_axi_arprot_reg;
|
||||
assign m_axi_arqos = m_axi_arqos_reg;
|
||||
assign m_axi_arregion = m_axi_arregion_reg;
|
||||
assign m_axi_aruser = ARUSER_ENABLE ? m_axi_aruser_reg : {ARUSER_WIDTH{1'b0}};
|
||||
assign m_axi_arvalid = m_axi_arvalid_reg;
|
||||
|
||||
// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input)
|
||||
wire s_axi_arready_early = m_axi_arready | (~temp_m_axi_arvalid_reg & (~m_axi_arvalid_reg | ~s_axi_arvalid));
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
m_axi_arvalid_next = m_axi_arvalid_reg;
|
||||
temp_m_axi_arvalid_next = temp_m_axi_arvalid_reg;
|
||||
|
||||
store_axi_ar_input_to_output = 1'b0;
|
||||
store_axi_ar_input_to_temp = 1'b0;
|
||||
store_axi_ar_temp_to_output = 1'b0;
|
||||
|
||||
if (s_axi_arready_reg) begin
|
||||
// input is ready
|
||||
if (m_axi_arready | ~m_axi_arvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
m_axi_arvalid_next = s_axi_arvalid;
|
||||
store_axi_ar_input_to_output = 1'b1;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_m_axi_arvalid_next = s_axi_arvalid;
|
||||
store_axi_ar_input_to_temp = 1'b1;
|
||||
end
|
||||
end else if (m_axi_arready) begin
|
||||
// input is not ready, but output is ready
|
||||
m_axi_arvalid_next = temp_m_axi_arvalid_reg;
|
||||
temp_m_axi_arvalid_next = 1'b0;
|
||||
store_axi_ar_temp_to_output = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
s_axi_arready_reg <= 1'b0;
|
||||
m_axi_arvalid_reg <= 1'b0;
|
||||
temp_m_axi_arvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
s_axi_arready_reg <= s_axi_arready_early;
|
||||
m_axi_arvalid_reg <= m_axi_arvalid_next;
|
||||
temp_m_axi_arvalid_reg <= temp_m_axi_arvalid_next;
|
||||
end
|
||||
|
||||
// datapath
|
||||
if (store_axi_ar_input_to_output) begin
|
||||
m_axi_arid_reg <= s_axi_arid;
|
||||
m_axi_araddr_reg <= s_axi_araddr;
|
||||
m_axi_arlen_reg <= s_axi_arlen;
|
||||
m_axi_arsize_reg <= s_axi_arsize;
|
||||
m_axi_arburst_reg <= s_axi_arburst;
|
||||
m_axi_arlock_reg <= s_axi_arlock;
|
||||
m_axi_arcache_reg <= s_axi_arcache;
|
||||
m_axi_arprot_reg <= s_axi_arprot;
|
||||
m_axi_arqos_reg <= s_axi_arqos;
|
||||
m_axi_arregion_reg <= s_axi_arregion;
|
||||
m_axi_aruser_reg <= s_axi_aruser;
|
||||
end else if (store_axi_ar_temp_to_output) begin
|
||||
m_axi_arid_reg <= temp_m_axi_arid_reg;
|
||||
m_axi_araddr_reg <= temp_m_axi_araddr_reg;
|
||||
m_axi_arlen_reg <= temp_m_axi_arlen_reg;
|
||||
m_axi_arsize_reg <= temp_m_axi_arsize_reg;
|
||||
m_axi_arburst_reg <= temp_m_axi_arburst_reg;
|
||||
m_axi_arlock_reg <= temp_m_axi_arlock_reg;
|
||||
m_axi_arcache_reg <= temp_m_axi_arcache_reg;
|
||||
m_axi_arprot_reg <= temp_m_axi_arprot_reg;
|
||||
m_axi_arqos_reg <= temp_m_axi_arqos_reg;
|
||||
m_axi_arregion_reg <= temp_m_axi_arregion_reg;
|
||||
m_axi_aruser_reg <= temp_m_axi_aruser_reg;
|
||||
end
|
||||
|
||||
if (store_axi_ar_input_to_temp) begin
|
||||
temp_m_axi_arid_reg <= s_axi_arid;
|
||||
temp_m_axi_araddr_reg <= s_axi_araddr;
|
||||
temp_m_axi_arlen_reg <= s_axi_arlen;
|
||||
temp_m_axi_arsize_reg <= s_axi_arsize;
|
||||
temp_m_axi_arburst_reg <= s_axi_arburst;
|
||||
temp_m_axi_arlock_reg <= s_axi_arlock;
|
||||
temp_m_axi_arcache_reg <= s_axi_arcache;
|
||||
temp_m_axi_arprot_reg <= s_axi_arprot;
|
||||
temp_m_axi_arqos_reg <= s_axi_arqos;
|
||||
temp_m_axi_arregion_reg <= s_axi_arregion;
|
||||
temp_m_axi_aruser_reg <= s_axi_aruser;
|
||||
end
|
||||
end
|
||||
|
||||
end else if (AR_REG_TYPE == 1) begin
|
||||
// simple register, inserts bubble cycles
|
||||
|
||||
// datapath registers
|
||||
reg s_axi_arready_reg = 1'b0;
|
||||
|
||||
reg [ID_WIDTH-1:0] m_axi_arid_reg = {ID_WIDTH{1'b0}};
|
||||
reg [ADDR_WIDTH-1:0] m_axi_araddr_reg = {ADDR_WIDTH{1'b0}};
|
||||
reg [7:0] m_axi_arlen_reg = 8'd0;
|
||||
reg [2:0] m_axi_arsize_reg = 3'd0;
|
||||
reg [1:0] m_axi_arburst_reg = 2'd0;
|
||||
reg m_axi_arlock_reg = 1'b0;
|
||||
reg [3:0] m_axi_arcache_reg = 4'd0;
|
||||
reg [2:0] m_axi_arprot_reg = 3'd0;
|
||||
reg [3:0] m_axi_arqos_reg = 4'd0;
|
||||
reg [3:0] m_axi_arregion_reg = 4'd0;
|
||||
reg [ARUSER_WIDTH-1:0] m_axi_aruser_reg = {ARUSER_WIDTH{1'b0}};
|
||||
reg m_axi_arvalid_reg = 1'b0, m_axi_arvalid_next;
|
||||
|
||||
// datapath control
|
||||
reg store_axi_ar_input_to_output;
|
||||
|
||||
assign s_axi_arready = s_axi_arready_reg;
|
||||
|
||||
assign m_axi_arid = m_axi_arid_reg;
|
||||
assign m_axi_araddr = m_axi_araddr_reg;
|
||||
assign m_axi_arlen = m_axi_arlen_reg;
|
||||
assign m_axi_arsize = m_axi_arsize_reg;
|
||||
assign m_axi_arburst = m_axi_arburst_reg;
|
||||
assign m_axi_arlock = m_axi_arlock_reg;
|
||||
assign m_axi_arcache = m_axi_arcache_reg;
|
||||
assign m_axi_arprot = m_axi_arprot_reg;
|
||||
assign m_axi_arqos = m_axi_arqos_reg;
|
||||
assign m_axi_arregion = m_axi_arregion_reg;
|
||||
assign m_axi_aruser = ARUSER_ENABLE ? m_axi_aruser_reg : {ARUSER_WIDTH{1'b0}};
|
||||
assign m_axi_arvalid = m_axi_arvalid_reg;
|
||||
|
||||
// enable ready input next cycle if output buffer will be empty
|
||||
wire s_axi_arready_early = !m_axi_arvalid_next;
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
m_axi_arvalid_next = m_axi_arvalid_reg;
|
||||
|
||||
store_axi_ar_input_to_output = 1'b0;
|
||||
|
||||
if (s_axi_arready_reg) begin
|
||||
m_axi_arvalid_next = s_axi_arvalid;
|
||||
store_axi_ar_input_to_output = 1'b1;
|
||||
end else if (m_axi_arready) begin
|
||||
m_axi_arvalid_next = 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
s_axi_arready_reg <= 1'b0;
|
||||
m_axi_arvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
s_axi_arready_reg <= s_axi_arready_early;
|
||||
m_axi_arvalid_reg <= m_axi_arvalid_next;
|
||||
end
|
||||
|
||||
// datapath
|
||||
if (store_axi_ar_input_to_output) begin
|
||||
m_axi_arid_reg <= s_axi_arid;
|
||||
m_axi_araddr_reg <= s_axi_araddr;
|
||||
m_axi_arlen_reg <= s_axi_arlen;
|
||||
m_axi_arsize_reg <= s_axi_arsize;
|
||||
m_axi_arburst_reg <= s_axi_arburst;
|
||||
m_axi_arlock_reg <= s_axi_arlock;
|
||||
m_axi_arcache_reg <= s_axi_arcache;
|
||||
m_axi_arprot_reg <= s_axi_arprot;
|
||||
m_axi_arqos_reg <= s_axi_arqos;
|
||||
m_axi_arregion_reg <= s_axi_arregion;
|
||||
m_axi_aruser_reg <= s_axi_aruser;
|
||||
end
|
||||
end
|
||||
|
||||
end else begin
|
||||
|
||||
// bypass AR channel
|
||||
assign m_axi_arid = s_axi_arid;
|
||||
assign m_axi_araddr = s_axi_araddr;
|
||||
assign m_axi_arlen = s_axi_arlen;
|
||||
assign m_axi_arsize = s_axi_arsize;
|
||||
assign m_axi_arburst = s_axi_arburst;
|
||||
assign m_axi_arlock = s_axi_arlock;
|
||||
assign m_axi_arcache = s_axi_arcache;
|
||||
assign m_axi_arprot = s_axi_arprot;
|
||||
assign m_axi_arqos = s_axi_arqos;
|
||||
assign m_axi_arregion = s_axi_arregion;
|
||||
assign m_axi_aruser = ARUSER_ENABLE ? s_axi_aruser : {ARUSER_WIDTH{1'b0}};
|
||||
assign m_axi_arvalid = s_axi_arvalid;
|
||||
assign s_axi_arready = m_axi_arready;
|
||||
|
||||
end
|
||||
|
||||
// R channel
|
||||
|
||||
if (R_REG_TYPE > 1) begin
|
||||
// skid buffer, no bubble cycles
|
||||
|
||||
// datapath registers
|
||||
reg m_axi_rready_reg = 1'b0;
|
||||
|
||||
reg [ID_WIDTH-1:0] s_axi_rid_reg = {ID_WIDTH{1'b0}};
|
||||
reg [DATA_WIDTH-1:0] s_axi_rdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [1:0] s_axi_rresp_reg = 2'b0;
|
||||
reg s_axi_rlast_reg = 1'b0;
|
||||
reg [RUSER_WIDTH-1:0] s_axi_ruser_reg = {RUSER_WIDTH{1'b0}};
|
||||
reg s_axi_rvalid_reg = 1'b0, s_axi_rvalid_next;
|
||||
|
||||
reg [ID_WIDTH-1:0] temp_s_axi_rid_reg = {ID_WIDTH{1'b0}};
|
||||
reg [DATA_WIDTH-1:0] temp_s_axi_rdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [1:0] temp_s_axi_rresp_reg = 2'b0;
|
||||
reg temp_s_axi_rlast_reg = 1'b0;
|
||||
reg [RUSER_WIDTH-1:0] temp_s_axi_ruser_reg = {RUSER_WIDTH{1'b0}};
|
||||
reg temp_s_axi_rvalid_reg = 1'b0, temp_s_axi_rvalid_next;
|
||||
|
||||
// datapath control
|
||||
reg store_axi_r_input_to_output;
|
||||
reg store_axi_r_input_to_temp;
|
||||
reg store_axi_r_temp_to_output;
|
||||
|
||||
assign m_axi_rready = m_axi_rready_reg;
|
||||
|
||||
assign s_axi_rid = s_axi_rid_reg;
|
||||
assign s_axi_rdata = s_axi_rdata_reg;
|
||||
assign s_axi_rresp = s_axi_rresp_reg;
|
||||
assign s_axi_rlast = s_axi_rlast_reg;
|
||||
assign s_axi_ruser = RUSER_ENABLE ? s_axi_ruser_reg : {RUSER_WIDTH{1'b0}};
|
||||
assign s_axi_rvalid = s_axi_rvalid_reg;
|
||||
|
||||
// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input)
|
||||
wire m_axi_rready_early = s_axi_rready | (~temp_s_axi_rvalid_reg & (~s_axi_rvalid_reg | ~m_axi_rvalid));
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
s_axi_rvalid_next = s_axi_rvalid_reg;
|
||||
temp_s_axi_rvalid_next = temp_s_axi_rvalid_reg;
|
||||
|
||||
store_axi_r_input_to_output = 1'b0;
|
||||
store_axi_r_input_to_temp = 1'b0;
|
||||
store_axi_r_temp_to_output = 1'b0;
|
||||
|
||||
if (m_axi_rready_reg) begin
|
||||
// input is ready
|
||||
if (s_axi_rready | ~s_axi_rvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
s_axi_rvalid_next = m_axi_rvalid;
|
||||
store_axi_r_input_to_output = 1'b1;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_s_axi_rvalid_next = m_axi_rvalid;
|
||||
store_axi_r_input_to_temp = 1'b1;
|
||||
end
|
||||
end else if (s_axi_rready) begin
|
||||
// input is not ready, but output is ready
|
||||
s_axi_rvalid_next = temp_s_axi_rvalid_reg;
|
||||
temp_s_axi_rvalid_next = 1'b0;
|
||||
store_axi_r_temp_to_output = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
m_axi_rready_reg <= 1'b0;
|
||||
s_axi_rvalid_reg <= 1'b0;
|
||||
temp_s_axi_rvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
m_axi_rready_reg <= m_axi_rready_early;
|
||||
s_axi_rvalid_reg <= s_axi_rvalid_next;
|
||||
temp_s_axi_rvalid_reg <= temp_s_axi_rvalid_next;
|
||||
end
|
||||
|
||||
// datapath
|
||||
if (store_axi_r_input_to_output) begin
|
||||
s_axi_rid_reg <= m_axi_rid;
|
||||
s_axi_rdata_reg <= m_axi_rdata;
|
||||
s_axi_rresp_reg <= m_axi_rresp;
|
||||
s_axi_rlast_reg <= m_axi_rlast;
|
||||
s_axi_ruser_reg <= m_axi_ruser;
|
||||
end else if (store_axi_r_temp_to_output) begin
|
||||
s_axi_rid_reg <= temp_s_axi_rid_reg;
|
||||
s_axi_rdata_reg <= temp_s_axi_rdata_reg;
|
||||
s_axi_rresp_reg <= temp_s_axi_rresp_reg;
|
||||
s_axi_rlast_reg <= temp_s_axi_rlast_reg;
|
||||
s_axi_ruser_reg <= temp_s_axi_ruser_reg;
|
||||
end
|
||||
|
||||
if (store_axi_r_input_to_temp) begin
|
||||
temp_s_axi_rid_reg <= m_axi_rid;
|
||||
temp_s_axi_rdata_reg <= m_axi_rdata;
|
||||
temp_s_axi_rresp_reg <= m_axi_rresp;
|
||||
temp_s_axi_rlast_reg <= m_axi_rlast;
|
||||
temp_s_axi_ruser_reg <= m_axi_ruser;
|
||||
end
|
||||
end
|
||||
|
||||
end else if (R_REG_TYPE == 1) begin
|
||||
// simple register, inserts bubble cycles
|
||||
|
||||
// datapath registers
|
||||
reg m_axi_rready_reg = 1'b0;
|
||||
|
||||
reg [ID_WIDTH-1:0] s_axi_rid_reg = {ID_WIDTH{1'b0}};
|
||||
reg [DATA_WIDTH-1:0] s_axi_rdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [1:0] s_axi_rresp_reg = 2'b0;
|
||||
reg s_axi_rlast_reg = 1'b0;
|
||||
reg [RUSER_WIDTH-1:0] s_axi_ruser_reg = {RUSER_WIDTH{1'b0}};
|
||||
reg s_axi_rvalid_reg = 1'b0, s_axi_rvalid_next;
|
||||
|
||||
// datapath control
|
||||
reg store_axi_r_input_to_output;
|
||||
|
||||
assign m_axi_rready = m_axi_rready_reg;
|
||||
|
||||
assign s_axi_rid = s_axi_rid_reg;
|
||||
assign s_axi_rdata = s_axi_rdata_reg;
|
||||
assign s_axi_rresp = s_axi_rresp_reg;
|
||||
assign s_axi_rlast = s_axi_rlast_reg;
|
||||
assign s_axi_ruser = RUSER_ENABLE ? s_axi_ruser_reg : {RUSER_WIDTH{1'b0}};
|
||||
assign s_axi_rvalid = s_axi_rvalid_reg;
|
||||
|
||||
// enable ready input next cycle if output buffer will be empty
|
||||
wire m_axi_rready_early = !s_axi_rvalid_next;
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
s_axi_rvalid_next = s_axi_rvalid_reg;
|
||||
|
||||
store_axi_r_input_to_output = 1'b0;
|
||||
|
||||
if (m_axi_rready_reg) begin
|
||||
s_axi_rvalid_next = m_axi_rvalid;
|
||||
store_axi_r_input_to_output = 1'b1;
|
||||
end else if (s_axi_rready) begin
|
||||
s_axi_rvalid_next = 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
m_axi_rready_reg <= 1'b0;
|
||||
s_axi_rvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
m_axi_rready_reg <= m_axi_rready_early;
|
||||
s_axi_rvalid_reg <= s_axi_rvalid_next;
|
||||
end
|
||||
|
||||
// datapath
|
||||
if (store_axi_r_input_to_output) begin
|
||||
s_axi_rid_reg <= m_axi_rid;
|
||||
s_axi_rdata_reg <= m_axi_rdata;
|
||||
s_axi_rresp_reg <= m_axi_rresp;
|
||||
s_axi_rlast_reg <= m_axi_rlast;
|
||||
s_axi_ruser_reg <= m_axi_ruser;
|
||||
end
|
||||
end
|
||||
|
||||
end else begin
|
||||
|
||||
// bypass R channel
|
||||
assign s_axi_rid = m_axi_rid;
|
||||
assign s_axi_rdata = m_axi_rdata;
|
||||
assign s_axi_rresp = m_axi_rresp;
|
||||
assign s_axi_rlast = m_axi_rlast;
|
||||
assign s_axi_ruser = RUSER_ENABLE ? m_axi_ruser : {RUSER_WIDTH{1'b0}};
|
||||
assign s_axi_rvalid = m_axi_rvalid;
|
||||
assign m_axi_rready = s_axi_rready;
|
||||
|
||||
end
|
||||
|
||||
endgenerate
|
||||
|
||||
endmodule
|
||||
|
||||
`resetall
|
@ -1,691 +0,0 @@
|
||||
/*
|
||||
|
||||
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
|
||||
|
||||
`resetall
|
||||
`timescale 1ns / 1ps
|
||||
`default_nettype none
|
||||
|
||||
/*
|
||||
* AXI4 register (write)
|
||||
*/
|
||||
module axi_register_wr #
|
||||
(
|
||||
// Width of data bus in bits
|
||||
parameter DATA_WIDTH = 32,
|
||||
// Width of address bus in bits
|
||||
parameter ADDR_WIDTH = 32,
|
||||
// Width of wstrb (width of data bus in words)
|
||||
parameter STRB_WIDTH = (DATA_WIDTH/8),
|
||||
// Width of ID signal
|
||||
parameter ID_WIDTH = 8,
|
||||
// Propagate awuser signal
|
||||
parameter AWUSER_ENABLE = 0,
|
||||
// Width of awuser signal
|
||||
parameter AWUSER_WIDTH = 1,
|
||||
// Propagate wuser signal
|
||||
parameter WUSER_ENABLE = 0,
|
||||
// Width of wuser signal
|
||||
parameter WUSER_WIDTH = 1,
|
||||
// Propagate buser signal
|
||||
parameter BUSER_ENABLE = 0,
|
||||
// Width of buser signal
|
||||
parameter BUSER_WIDTH = 1,
|
||||
// AW channel register type
|
||||
// 0 to bypass, 1 for simple buffer, 2 for skid buffer
|
||||
parameter AW_REG_TYPE = 1,
|
||||
// W channel register type
|
||||
// 0 to bypass, 1 for simple buffer, 2 for skid buffer
|
||||
parameter W_REG_TYPE = 2,
|
||||
// B channel register type
|
||||
// 0 to bypass, 1 for simple buffer, 2 for skid buffer
|
||||
parameter B_REG_TYPE = 1
|
||||
)
|
||||
(
|
||||
input wire clk,
|
||||
input wire rst,
|
||||
|
||||
/*
|
||||
* AXI slave interface
|
||||
*/
|
||||
input wire [ID_WIDTH-1:0] s_axi_awid,
|
||||
input wire [ADDR_WIDTH-1:0] s_axi_awaddr,
|
||||
input wire [7:0] s_axi_awlen,
|
||||
input wire [2:0] s_axi_awsize,
|
||||
input wire [1:0] s_axi_awburst,
|
||||
input wire s_axi_awlock,
|
||||
input wire [3:0] s_axi_awcache,
|
||||
input wire [2:0] s_axi_awprot,
|
||||
input wire [3:0] s_axi_awqos,
|
||||
input wire [3:0] s_axi_awregion,
|
||||
input wire [AWUSER_WIDTH-1:0] s_axi_awuser,
|
||||
input wire s_axi_awvalid,
|
||||
output wire s_axi_awready,
|
||||
input wire [DATA_WIDTH-1:0] s_axi_wdata,
|
||||
input wire [STRB_WIDTH-1:0] s_axi_wstrb,
|
||||
input wire s_axi_wlast,
|
||||
input wire [WUSER_WIDTH-1:0] s_axi_wuser,
|
||||
input wire s_axi_wvalid,
|
||||
output wire s_axi_wready,
|
||||
output wire [ID_WIDTH-1:0] s_axi_bid,
|
||||
output wire [1:0] s_axi_bresp,
|
||||
output wire [BUSER_WIDTH-1:0] s_axi_buser,
|
||||
output wire s_axi_bvalid,
|
||||
input wire s_axi_bready,
|
||||
|
||||
/*
|
||||
* AXI master interface
|
||||
*/
|
||||
output wire [ID_WIDTH-1:0] m_axi_awid,
|
||||
output wire [ADDR_WIDTH-1:0] m_axi_awaddr,
|
||||
output wire [7:0] m_axi_awlen,
|
||||
output wire [2:0] m_axi_awsize,
|
||||
output wire [1:0] m_axi_awburst,
|
||||
output wire m_axi_awlock,
|
||||
output wire [3:0] m_axi_awcache,
|
||||
output wire [2:0] m_axi_awprot,
|
||||
output wire [3:0] m_axi_awqos,
|
||||
output wire [3:0] m_axi_awregion,
|
||||
output wire [AWUSER_WIDTH-1:0] m_axi_awuser,
|
||||
output wire m_axi_awvalid,
|
||||
input wire m_axi_awready,
|
||||
output wire [DATA_WIDTH-1:0] m_axi_wdata,
|
||||
output wire [STRB_WIDTH-1:0] m_axi_wstrb,
|
||||
output wire m_axi_wlast,
|
||||
output wire [WUSER_WIDTH-1:0] m_axi_wuser,
|
||||
output wire m_axi_wvalid,
|
||||
input wire m_axi_wready,
|
||||
input wire [ID_WIDTH-1:0] m_axi_bid,
|
||||
input wire [1:0] m_axi_bresp,
|
||||
input wire [BUSER_WIDTH-1:0] m_axi_buser,
|
||||
input wire m_axi_bvalid,
|
||||
output wire m_axi_bready
|
||||
);
|
||||
|
||||
generate
|
||||
|
||||
// AW channel
|
||||
|
||||
if (AW_REG_TYPE > 1) begin
|
||||
// skid buffer, no bubble cycles
|
||||
|
||||
// datapath registers
|
||||
reg s_axi_awready_reg = 1'b0;
|
||||
|
||||
reg [ID_WIDTH-1:0] m_axi_awid_reg = {ID_WIDTH{1'b0}};
|
||||
reg [ADDR_WIDTH-1:0] m_axi_awaddr_reg = {ADDR_WIDTH{1'b0}};
|
||||
reg [7:0] m_axi_awlen_reg = 8'd0;
|
||||
reg [2:0] m_axi_awsize_reg = 3'd0;
|
||||
reg [1:0] m_axi_awburst_reg = 2'd0;
|
||||
reg m_axi_awlock_reg = 1'b0;
|
||||
reg [3:0] m_axi_awcache_reg = 4'd0;
|
||||
reg [2:0] m_axi_awprot_reg = 3'd0;
|
||||
reg [3:0] m_axi_awqos_reg = 4'd0;
|
||||
reg [3:0] m_axi_awregion_reg = 4'd0;
|
||||
reg [AWUSER_WIDTH-1:0] m_axi_awuser_reg = {AWUSER_WIDTH{1'b0}};
|
||||
reg m_axi_awvalid_reg = 1'b0, m_axi_awvalid_next;
|
||||
|
||||
reg [ID_WIDTH-1:0] temp_m_axi_awid_reg = {ID_WIDTH{1'b0}};
|
||||
reg [ADDR_WIDTH-1:0] temp_m_axi_awaddr_reg = {ADDR_WIDTH{1'b0}};
|
||||
reg [7:0] temp_m_axi_awlen_reg = 8'd0;
|
||||
reg [2:0] temp_m_axi_awsize_reg = 3'd0;
|
||||
reg [1:0] temp_m_axi_awburst_reg = 2'd0;
|
||||
reg temp_m_axi_awlock_reg = 1'b0;
|
||||
reg [3:0] temp_m_axi_awcache_reg = 4'd0;
|
||||
reg [2:0] temp_m_axi_awprot_reg = 3'd0;
|
||||
reg [3:0] temp_m_axi_awqos_reg = 4'd0;
|
||||
reg [3:0] temp_m_axi_awregion_reg = 4'd0;
|
||||
reg [AWUSER_WIDTH-1:0] temp_m_axi_awuser_reg = {AWUSER_WIDTH{1'b0}};
|
||||
reg temp_m_axi_awvalid_reg = 1'b0, temp_m_axi_awvalid_next;
|
||||
|
||||
// datapath control
|
||||
reg store_axi_aw_input_to_output;
|
||||
reg store_axi_aw_input_to_temp;
|
||||
reg store_axi_aw_temp_to_output;
|
||||
|
||||
assign s_axi_awready = s_axi_awready_reg;
|
||||
|
||||
assign m_axi_awid = m_axi_awid_reg;
|
||||
assign m_axi_awaddr = m_axi_awaddr_reg;
|
||||
assign m_axi_awlen = m_axi_awlen_reg;
|
||||
assign m_axi_awsize = m_axi_awsize_reg;
|
||||
assign m_axi_awburst = m_axi_awburst_reg;
|
||||
assign m_axi_awlock = m_axi_awlock_reg;
|
||||
assign m_axi_awcache = m_axi_awcache_reg;
|
||||
assign m_axi_awprot = m_axi_awprot_reg;
|
||||
assign m_axi_awqos = m_axi_awqos_reg;
|
||||
assign m_axi_awregion = m_axi_awregion_reg;
|
||||
assign m_axi_awuser = AWUSER_ENABLE ? m_axi_awuser_reg : {AWUSER_WIDTH{1'b0}};
|
||||
assign m_axi_awvalid = m_axi_awvalid_reg;
|
||||
|
||||
// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input)
|
||||
wire s_axi_awready_early = m_axi_awready | (~temp_m_axi_awvalid_reg & (~m_axi_awvalid_reg | ~s_axi_awvalid));
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
m_axi_awvalid_next = m_axi_awvalid_reg;
|
||||
temp_m_axi_awvalid_next = temp_m_axi_awvalid_reg;
|
||||
|
||||
store_axi_aw_input_to_output = 1'b0;
|
||||
store_axi_aw_input_to_temp = 1'b0;
|
||||
store_axi_aw_temp_to_output = 1'b0;
|
||||
|
||||
if (s_axi_awready_reg) begin
|
||||
// input is ready
|
||||
if (m_axi_awready | ~m_axi_awvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
m_axi_awvalid_next = s_axi_awvalid;
|
||||
store_axi_aw_input_to_output = 1'b1;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_m_axi_awvalid_next = s_axi_awvalid;
|
||||
store_axi_aw_input_to_temp = 1'b1;
|
||||
end
|
||||
end else if (m_axi_awready) begin
|
||||
// input is not ready, but output is ready
|
||||
m_axi_awvalid_next = temp_m_axi_awvalid_reg;
|
||||
temp_m_axi_awvalid_next = 1'b0;
|
||||
store_axi_aw_temp_to_output = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
s_axi_awready_reg <= 1'b0;
|
||||
m_axi_awvalid_reg <= 1'b0;
|
||||
temp_m_axi_awvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
s_axi_awready_reg <= s_axi_awready_early;
|
||||
m_axi_awvalid_reg <= m_axi_awvalid_next;
|
||||
temp_m_axi_awvalid_reg <= temp_m_axi_awvalid_next;
|
||||
end
|
||||
|
||||
// datapath
|
||||
if (store_axi_aw_input_to_output) begin
|
||||
m_axi_awid_reg <= s_axi_awid;
|
||||
m_axi_awaddr_reg <= s_axi_awaddr;
|
||||
m_axi_awlen_reg <= s_axi_awlen;
|
||||
m_axi_awsize_reg <= s_axi_awsize;
|
||||
m_axi_awburst_reg <= s_axi_awburst;
|
||||
m_axi_awlock_reg <= s_axi_awlock;
|
||||
m_axi_awcache_reg <= s_axi_awcache;
|
||||
m_axi_awprot_reg <= s_axi_awprot;
|
||||
m_axi_awqos_reg <= s_axi_awqos;
|
||||
m_axi_awregion_reg <= s_axi_awregion;
|
||||
m_axi_awuser_reg <= s_axi_awuser;
|
||||
end else if (store_axi_aw_temp_to_output) begin
|
||||
m_axi_awid_reg <= temp_m_axi_awid_reg;
|
||||
m_axi_awaddr_reg <= temp_m_axi_awaddr_reg;
|
||||
m_axi_awlen_reg <= temp_m_axi_awlen_reg;
|
||||
m_axi_awsize_reg <= temp_m_axi_awsize_reg;
|
||||
m_axi_awburst_reg <= temp_m_axi_awburst_reg;
|
||||
m_axi_awlock_reg <= temp_m_axi_awlock_reg;
|
||||
m_axi_awcache_reg <= temp_m_axi_awcache_reg;
|
||||
m_axi_awprot_reg <= temp_m_axi_awprot_reg;
|
||||
m_axi_awqos_reg <= temp_m_axi_awqos_reg;
|
||||
m_axi_awregion_reg <= temp_m_axi_awregion_reg;
|
||||
m_axi_awuser_reg <= temp_m_axi_awuser_reg;
|
||||
end
|
||||
|
||||
if (store_axi_aw_input_to_temp) begin
|
||||
temp_m_axi_awid_reg <= s_axi_awid;
|
||||
temp_m_axi_awaddr_reg <= s_axi_awaddr;
|
||||
temp_m_axi_awlen_reg <= s_axi_awlen;
|
||||
temp_m_axi_awsize_reg <= s_axi_awsize;
|
||||
temp_m_axi_awburst_reg <= s_axi_awburst;
|
||||
temp_m_axi_awlock_reg <= s_axi_awlock;
|
||||
temp_m_axi_awcache_reg <= s_axi_awcache;
|
||||
temp_m_axi_awprot_reg <= s_axi_awprot;
|
||||
temp_m_axi_awqos_reg <= s_axi_awqos;
|
||||
temp_m_axi_awregion_reg <= s_axi_awregion;
|
||||
temp_m_axi_awuser_reg <= s_axi_awuser;
|
||||
end
|
||||
end
|
||||
|
||||
end else if (AW_REG_TYPE == 1) begin
|
||||
// simple register, inserts bubble cycles
|
||||
|
||||
// datapath registers
|
||||
reg s_axi_awready_reg = 1'b0;
|
||||
|
||||
reg [ID_WIDTH-1:0] m_axi_awid_reg = {ID_WIDTH{1'b0}};
|
||||
reg [ADDR_WIDTH-1:0] m_axi_awaddr_reg = {ADDR_WIDTH{1'b0}};
|
||||
reg [7:0] m_axi_awlen_reg = 8'd0;
|
||||
reg [2:0] m_axi_awsize_reg = 3'd0;
|
||||
reg [1:0] m_axi_awburst_reg = 2'd0;
|
||||
reg m_axi_awlock_reg = 1'b0;
|
||||
reg [3:0] m_axi_awcache_reg = 4'd0;
|
||||
reg [2:0] m_axi_awprot_reg = 3'd0;
|
||||
reg [3:0] m_axi_awqos_reg = 4'd0;
|
||||
reg [3:0] m_axi_awregion_reg = 4'd0;
|
||||
reg [AWUSER_WIDTH-1:0] m_axi_awuser_reg = {AWUSER_WIDTH{1'b0}};
|
||||
reg m_axi_awvalid_reg = 1'b0, m_axi_awvalid_next;
|
||||
|
||||
// datapath control
|
||||
reg store_axi_aw_input_to_output;
|
||||
|
||||
assign s_axi_awready = s_axi_awready_reg;
|
||||
|
||||
assign m_axi_awid = m_axi_awid_reg;
|
||||
assign m_axi_awaddr = m_axi_awaddr_reg;
|
||||
assign m_axi_awlen = m_axi_awlen_reg;
|
||||
assign m_axi_awsize = m_axi_awsize_reg;
|
||||
assign m_axi_awburst = m_axi_awburst_reg;
|
||||
assign m_axi_awlock = m_axi_awlock_reg;
|
||||
assign m_axi_awcache = m_axi_awcache_reg;
|
||||
assign m_axi_awprot = m_axi_awprot_reg;
|
||||
assign m_axi_awqos = m_axi_awqos_reg;
|
||||
assign m_axi_awregion = m_axi_awregion_reg;
|
||||
assign m_axi_awuser = AWUSER_ENABLE ? m_axi_awuser_reg : {AWUSER_WIDTH{1'b0}};
|
||||
assign m_axi_awvalid = m_axi_awvalid_reg;
|
||||
|
||||
// enable ready input next cycle if output buffer will be empty
|
||||
wire s_axi_awready_eawly = !m_axi_awvalid_next;
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
m_axi_awvalid_next = m_axi_awvalid_reg;
|
||||
|
||||
store_axi_aw_input_to_output = 1'b0;
|
||||
|
||||
if (s_axi_awready_reg) begin
|
||||
m_axi_awvalid_next = s_axi_awvalid;
|
||||
store_axi_aw_input_to_output = 1'b1;
|
||||
end else if (m_axi_awready) begin
|
||||
m_axi_awvalid_next = 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
s_axi_awready_reg <= 1'b0;
|
||||
m_axi_awvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
s_axi_awready_reg <= s_axi_awready_eawly;
|
||||
m_axi_awvalid_reg <= m_axi_awvalid_next;
|
||||
end
|
||||
|
||||
// datapath
|
||||
if (store_axi_aw_input_to_output) begin
|
||||
m_axi_awid_reg <= s_axi_awid;
|
||||
m_axi_awaddr_reg <= s_axi_awaddr;
|
||||
m_axi_awlen_reg <= s_axi_awlen;
|
||||
m_axi_awsize_reg <= s_axi_awsize;
|
||||
m_axi_awburst_reg <= s_axi_awburst;
|
||||
m_axi_awlock_reg <= s_axi_awlock;
|
||||
m_axi_awcache_reg <= s_axi_awcache;
|
||||
m_axi_awprot_reg <= s_axi_awprot;
|
||||
m_axi_awqos_reg <= s_axi_awqos;
|
||||
m_axi_awregion_reg <= s_axi_awregion;
|
||||
m_axi_awuser_reg <= s_axi_awuser;
|
||||
end
|
||||
end
|
||||
|
||||
end else begin
|
||||
|
||||
// bypass AW channel
|
||||
assign m_axi_awid = s_axi_awid;
|
||||
assign m_axi_awaddr = s_axi_awaddr;
|
||||
assign m_axi_awlen = s_axi_awlen;
|
||||
assign m_axi_awsize = s_axi_awsize;
|
||||
assign m_axi_awburst = s_axi_awburst;
|
||||
assign m_axi_awlock = s_axi_awlock;
|
||||
assign m_axi_awcache = s_axi_awcache;
|
||||
assign m_axi_awprot = s_axi_awprot;
|
||||
assign m_axi_awqos = s_axi_awqos;
|
||||
assign m_axi_awregion = s_axi_awregion;
|
||||
assign m_axi_awuser = AWUSER_ENABLE ? s_axi_awuser : {AWUSER_WIDTH{1'b0}};
|
||||
assign m_axi_awvalid = s_axi_awvalid;
|
||||
assign s_axi_awready = m_axi_awready;
|
||||
|
||||
end
|
||||
|
||||
// W channel
|
||||
|
||||
if (W_REG_TYPE > 1) begin
|
||||
// skid buffer, no bubble cycles
|
||||
|
||||
// datapath registers
|
||||
reg s_axi_wready_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] m_axi_wdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [STRB_WIDTH-1:0] m_axi_wstrb_reg = {STRB_WIDTH{1'b0}};
|
||||
reg m_axi_wlast_reg = 1'b0;
|
||||
reg [WUSER_WIDTH-1:0] m_axi_wuser_reg = {WUSER_WIDTH{1'b0}};
|
||||
reg m_axi_wvalid_reg = 1'b0, m_axi_wvalid_next;
|
||||
|
||||
reg [DATA_WIDTH-1:0] temp_m_axi_wdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [STRB_WIDTH-1:0] temp_m_axi_wstrb_reg = {STRB_WIDTH{1'b0}};
|
||||
reg temp_m_axi_wlast_reg = 1'b0;
|
||||
reg [WUSER_WIDTH-1:0] temp_m_axi_wuser_reg = {WUSER_WIDTH{1'b0}};
|
||||
reg temp_m_axi_wvalid_reg = 1'b0, temp_m_axi_wvalid_next;
|
||||
|
||||
// datapath control
|
||||
reg store_axi_w_input_to_output;
|
||||
reg store_axi_w_input_to_temp;
|
||||
reg store_axi_w_temp_to_output;
|
||||
|
||||
assign s_axi_wready = s_axi_wready_reg;
|
||||
|
||||
assign m_axi_wdata = m_axi_wdata_reg;
|
||||
assign m_axi_wstrb = m_axi_wstrb_reg;
|
||||
assign m_axi_wlast = m_axi_wlast_reg;
|
||||
assign m_axi_wuser = WUSER_ENABLE ? m_axi_wuser_reg : {WUSER_WIDTH{1'b0}};
|
||||
assign m_axi_wvalid = m_axi_wvalid_reg;
|
||||
|
||||
// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input)
|
||||
wire s_axi_wready_early = m_axi_wready | (~temp_m_axi_wvalid_reg & (~m_axi_wvalid_reg | ~s_axi_wvalid));
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
m_axi_wvalid_next = m_axi_wvalid_reg;
|
||||
temp_m_axi_wvalid_next = temp_m_axi_wvalid_reg;
|
||||
|
||||
store_axi_w_input_to_output = 1'b0;
|
||||
store_axi_w_input_to_temp = 1'b0;
|
||||
store_axi_w_temp_to_output = 1'b0;
|
||||
|
||||
if (s_axi_wready_reg) begin
|
||||
// input is ready
|
||||
if (m_axi_wready | ~m_axi_wvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
m_axi_wvalid_next = s_axi_wvalid;
|
||||
store_axi_w_input_to_output = 1'b1;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_m_axi_wvalid_next = s_axi_wvalid;
|
||||
store_axi_w_input_to_temp = 1'b1;
|
||||
end
|
||||
end else if (m_axi_wready) begin
|
||||
// input is not ready, but output is ready
|
||||
m_axi_wvalid_next = temp_m_axi_wvalid_reg;
|
||||
temp_m_axi_wvalid_next = 1'b0;
|
||||
store_axi_w_temp_to_output = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
s_axi_wready_reg <= 1'b0;
|
||||
m_axi_wvalid_reg <= 1'b0;
|
||||
temp_m_axi_wvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
s_axi_wready_reg <= s_axi_wready_early;
|
||||
m_axi_wvalid_reg <= m_axi_wvalid_next;
|
||||
temp_m_axi_wvalid_reg <= temp_m_axi_wvalid_next;
|
||||
end
|
||||
|
||||
// datapath
|
||||
if (store_axi_w_input_to_output) begin
|
||||
m_axi_wdata_reg <= s_axi_wdata;
|
||||
m_axi_wstrb_reg <= s_axi_wstrb;
|
||||
m_axi_wlast_reg <= s_axi_wlast;
|
||||
m_axi_wuser_reg <= s_axi_wuser;
|
||||
end else if (store_axi_w_temp_to_output) begin
|
||||
m_axi_wdata_reg <= temp_m_axi_wdata_reg;
|
||||
m_axi_wstrb_reg <= temp_m_axi_wstrb_reg;
|
||||
m_axi_wlast_reg <= temp_m_axi_wlast_reg;
|
||||
m_axi_wuser_reg <= temp_m_axi_wuser_reg;
|
||||
end
|
||||
|
||||
if (store_axi_w_input_to_temp) begin
|
||||
temp_m_axi_wdata_reg <= s_axi_wdata;
|
||||
temp_m_axi_wstrb_reg <= s_axi_wstrb;
|
||||
temp_m_axi_wlast_reg <= s_axi_wlast;
|
||||
temp_m_axi_wuser_reg <= s_axi_wuser;
|
||||
end
|
||||
end
|
||||
|
||||
end else if (W_REG_TYPE == 1) begin
|
||||
// simple register, inserts bubble cycles
|
||||
|
||||
// datapath registers
|
||||
reg s_axi_wready_reg = 1'b0;
|
||||
|
||||
reg [DATA_WIDTH-1:0] m_axi_wdata_reg = {DATA_WIDTH{1'b0}};
|
||||
reg [STRB_WIDTH-1:0] m_axi_wstrb_reg = {STRB_WIDTH{1'b0}};
|
||||
reg m_axi_wlast_reg = 1'b0;
|
||||
reg [WUSER_WIDTH-1:0] m_axi_wuser_reg = {WUSER_WIDTH{1'b0}};
|
||||
reg m_axi_wvalid_reg = 1'b0, m_axi_wvalid_next;
|
||||
|
||||
// datapath control
|
||||
reg store_axi_w_input_to_output;
|
||||
|
||||
assign s_axi_wready = s_axi_wready_reg;
|
||||
|
||||
assign m_axi_wdata = m_axi_wdata_reg;
|
||||
assign m_axi_wstrb = m_axi_wstrb_reg;
|
||||
assign m_axi_wlast = m_axi_wlast_reg;
|
||||
assign m_axi_wuser = WUSER_ENABLE ? m_axi_wuser_reg : {WUSER_WIDTH{1'b0}};
|
||||
assign m_axi_wvalid = m_axi_wvalid_reg;
|
||||
|
||||
// enable ready input next cycle if output buffer will be empty
|
||||
wire s_axi_wready_ewly = !m_axi_wvalid_next;
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
m_axi_wvalid_next = m_axi_wvalid_reg;
|
||||
|
||||
store_axi_w_input_to_output = 1'b0;
|
||||
|
||||
if (s_axi_wready_reg) begin
|
||||
m_axi_wvalid_next = s_axi_wvalid;
|
||||
store_axi_w_input_to_output = 1'b1;
|
||||
end else if (m_axi_wready) begin
|
||||
m_axi_wvalid_next = 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
s_axi_wready_reg <= 1'b0;
|
||||
m_axi_wvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
s_axi_wready_reg <= s_axi_wready_ewly;
|
||||
m_axi_wvalid_reg <= m_axi_wvalid_next;
|
||||
end
|
||||
|
||||
// datapath
|
||||
if (store_axi_w_input_to_output) begin
|
||||
m_axi_wdata_reg <= s_axi_wdata;
|
||||
m_axi_wstrb_reg <= s_axi_wstrb;
|
||||
m_axi_wlast_reg <= s_axi_wlast;
|
||||
m_axi_wuser_reg <= s_axi_wuser;
|
||||
end
|
||||
end
|
||||
|
||||
end else begin
|
||||
|
||||
// bypass W channel
|
||||
assign m_axi_wdata = s_axi_wdata;
|
||||
assign m_axi_wstrb = s_axi_wstrb;
|
||||
assign m_axi_wlast = s_axi_wlast;
|
||||
assign m_axi_wuser = WUSER_ENABLE ? s_axi_wuser : {WUSER_WIDTH{1'b0}};
|
||||
assign m_axi_wvalid = s_axi_wvalid;
|
||||
assign s_axi_wready = m_axi_wready;
|
||||
|
||||
end
|
||||
|
||||
// B channel
|
||||
|
||||
if (B_REG_TYPE > 1) begin
|
||||
// skid buffer, no bubble cycles
|
||||
|
||||
// datapath registers
|
||||
reg m_axi_bready_reg = 1'b0;
|
||||
|
||||
reg [ID_WIDTH-1:0] s_axi_bid_reg = {ID_WIDTH{1'b0}};
|
||||
reg [1:0] s_axi_bresp_reg = 2'b0;
|
||||
reg [BUSER_WIDTH-1:0] s_axi_buser_reg = {BUSER_WIDTH{1'b0}};
|
||||
reg s_axi_bvalid_reg = 1'b0, s_axi_bvalid_next;
|
||||
|
||||
reg [ID_WIDTH-1:0] temp_s_axi_bid_reg = {ID_WIDTH{1'b0}};
|
||||
reg [1:0] temp_s_axi_bresp_reg = 2'b0;
|
||||
reg [BUSER_WIDTH-1:0] temp_s_axi_buser_reg = {BUSER_WIDTH{1'b0}};
|
||||
reg temp_s_axi_bvalid_reg = 1'b0, temp_s_axi_bvalid_next;
|
||||
|
||||
// datapath control
|
||||
reg store_axi_b_input_to_output;
|
||||
reg store_axi_b_input_to_temp;
|
||||
reg store_axi_b_temp_to_output;
|
||||
|
||||
assign m_axi_bready = m_axi_bready_reg;
|
||||
|
||||
assign s_axi_bid = s_axi_bid_reg;
|
||||
assign s_axi_bresp = s_axi_bresp_reg;
|
||||
assign s_axi_buser = BUSER_ENABLE ? s_axi_buser_reg : {BUSER_WIDTH{1'b0}};
|
||||
assign s_axi_bvalid = s_axi_bvalid_reg;
|
||||
|
||||
// enable ready input next cycle if output is ready or the temp reg will not be filled on the next cycle (output reg empty or no input)
|
||||
wire m_axi_bready_early = s_axi_bready | (~temp_s_axi_bvalid_reg & (~s_axi_bvalid_reg | ~m_axi_bvalid));
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
s_axi_bvalid_next = s_axi_bvalid_reg;
|
||||
temp_s_axi_bvalid_next = temp_s_axi_bvalid_reg;
|
||||
|
||||
store_axi_b_input_to_output = 1'b0;
|
||||
store_axi_b_input_to_temp = 1'b0;
|
||||
store_axi_b_temp_to_output = 1'b0;
|
||||
|
||||
if (m_axi_bready_reg) begin
|
||||
// input is ready
|
||||
if (s_axi_bready | ~s_axi_bvalid_reg) begin
|
||||
// output is ready or currently not valid, transfer data to output
|
||||
s_axi_bvalid_next = m_axi_bvalid;
|
||||
store_axi_b_input_to_output = 1'b1;
|
||||
end else begin
|
||||
// output is not ready, store input in temp
|
||||
temp_s_axi_bvalid_next = m_axi_bvalid;
|
||||
store_axi_b_input_to_temp = 1'b1;
|
||||
end
|
||||
end else if (s_axi_bready) begin
|
||||
// input is not ready, but output is ready
|
||||
s_axi_bvalid_next = temp_s_axi_bvalid_reg;
|
||||
temp_s_axi_bvalid_next = 1'b0;
|
||||
store_axi_b_temp_to_output = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
m_axi_bready_reg <= 1'b0;
|
||||
s_axi_bvalid_reg <= 1'b0;
|
||||
temp_s_axi_bvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
m_axi_bready_reg <= m_axi_bready_early;
|
||||
s_axi_bvalid_reg <= s_axi_bvalid_next;
|
||||
temp_s_axi_bvalid_reg <= temp_s_axi_bvalid_next;
|
||||
end
|
||||
|
||||
// datapath
|
||||
if (store_axi_b_input_to_output) begin
|
||||
s_axi_bid_reg <= m_axi_bid;
|
||||
s_axi_bresp_reg <= m_axi_bresp;
|
||||
s_axi_buser_reg <= m_axi_buser;
|
||||
end else if (store_axi_b_temp_to_output) begin
|
||||
s_axi_bid_reg <= temp_s_axi_bid_reg;
|
||||
s_axi_bresp_reg <= temp_s_axi_bresp_reg;
|
||||
s_axi_buser_reg <= temp_s_axi_buser_reg;
|
||||
end
|
||||
|
||||
if (store_axi_b_input_to_temp) begin
|
||||
temp_s_axi_bid_reg <= m_axi_bid;
|
||||
temp_s_axi_bresp_reg <= m_axi_bresp;
|
||||
temp_s_axi_buser_reg <= m_axi_buser;
|
||||
end
|
||||
end
|
||||
|
||||
end else if (B_REG_TYPE == 1) begin
|
||||
// simple register, inserts bubble cycles
|
||||
|
||||
// datapath registers
|
||||
reg m_axi_bready_reg = 1'b0;
|
||||
|
||||
reg [ID_WIDTH-1:0] s_axi_bid_reg = {ID_WIDTH{1'b0}};
|
||||
reg [1:0] s_axi_bresp_reg = 2'b0;
|
||||
reg [BUSER_WIDTH-1:0] s_axi_buser_reg = {BUSER_WIDTH{1'b0}};
|
||||
reg s_axi_bvalid_reg = 1'b0, s_axi_bvalid_next;
|
||||
|
||||
// datapath control
|
||||
reg store_axi_b_input_to_output;
|
||||
|
||||
assign m_axi_bready = m_axi_bready_reg;
|
||||
|
||||
assign s_axi_bid = s_axi_bid_reg;
|
||||
assign s_axi_bresp = s_axi_bresp_reg;
|
||||
assign s_axi_buser = BUSER_ENABLE ? s_axi_buser_reg : {BUSER_WIDTH{1'b0}};
|
||||
assign s_axi_bvalid = s_axi_bvalid_reg;
|
||||
|
||||
// enable ready input next cycle if output buffer will be empty
|
||||
wire m_axi_bready_early = !s_axi_bvalid_next;
|
||||
|
||||
always @* begin
|
||||
// transfer sink ready state to source
|
||||
s_axi_bvalid_next = s_axi_bvalid_reg;
|
||||
|
||||
store_axi_b_input_to_output = 1'b0;
|
||||
|
||||
if (m_axi_bready_reg) begin
|
||||
s_axi_bvalid_next = m_axi_bvalid;
|
||||
store_axi_b_input_to_output = 1'b1;
|
||||
end else if (s_axi_bready) begin
|
||||
s_axi_bvalid_next = 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge clk) begin
|
||||
if (rst) begin
|
||||
m_axi_bready_reg <= 1'b0;
|
||||
s_axi_bvalid_reg <= 1'b0;
|
||||
end else begin
|
||||
m_axi_bready_reg <= m_axi_bready_early;
|
||||
s_axi_bvalid_reg <= s_axi_bvalid_next;
|
||||
end
|
||||
|
||||
// datapath
|
||||
if (store_axi_b_input_to_output) begin
|
||||
s_axi_bid_reg <= m_axi_bid;
|
||||
s_axi_bresp_reg <= m_axi_bresp;
|
||||
s_axi_buser_reg <= m_axi_buser;
|
||||
end
|
||||
end
|
||||
|
||||
end else begin
|
||||
|
||||
// bypass B channel
|
||||
assign s_axi_bid = m_axi_bid;
|
||||
assign s_axi_bresp = m_axi_bresp;
|
||||
assign s_axi_buser = BUSER_ENABLE ? m_axi_buser : {BUSER_WIDTH{1'b0}};
|
||||
assign s_axi_bvalid = m_axi_bvalid;
|
||||
assign m_axi_bready = s_axi_bready;
|
||||
|
||||
end
|
||||
|
||||
endgenerate
|
||||
|
||||
endmodule
|
||||
|
||||
`resetall
|
@ -1,87 +0,0 @@
|
||||
/*
|
||||
Copyright (c) 2014-2021 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
|
||||
|
||||
`resetall
|
||||
`timescale 1ns / 1ps
|
||||
`default_nettype none
|
||||
|
||||
/*
|
||||
* Priority encoder module
|
||||
*/
|
||||
module priority_encoder #
|
||||
(
|
||||
parameter WIDTH = 4,
|
||||
// LSB priority selection
|
||||
parameter LSB_HIGH_PRIORITY = 0
|
||||
)
|
||||
(
|
||||
input wire [WIDTH-1:0] input_unencoded,
|
||||
output wire output_valid,
|
||||
output wire [$clog2(WIDTH)-1:0] output_encoded,
|
||||
output wire [WIDTH-1:0] output_unencoded
|
||||
);
|
||||
|
||||
parameter LEVELS = WIDTH > 2 ? $clog2(WIDTH) : 1;
|
||||
parameter W = 2**LEVELS;
|
||||
|
||||
// pad input to even power of two
|
||||
wire [W-1:0] input_padded = {{W-WIDTH{1'b0}}, input_unencoded};
|
||||
|
||||
wire [W/2-1:0] stage_valid[LEVELS-1:0];
|
||||
wire [W/2-1:0] stage_enc[LEVELS-1:0];
|
||||
|
||||
generate
|
||||
genvar l, n;
|
||||
|
||||
// process input bits; generate valid bit and encoded bit for each pair
|
||||
for (n = 0; n < W/2; n = n + 1) begin : loop_in
|
||||
assign stage_valid[0][n] = |input_padded[n*2+1:n*2];
|
||||
if (LSB_HIGH_PRIORITY) begin
|
||||
// bit 0 is highest priority
|
||||
assign stage_enc[0][n] = !input_padded[n*2+0];
|
||||
end else begin
|
||||
// bit 0 is lowest priority
|
||||
assign stage_enc[0][n] = input_padded[n*2+1];
|
||||
end
|
||||
end
|
||||
|
||||
// compress down to single valid bit and encoded bus
|
||||
for (l = 1; l < LEVELS; l = l + 1) begin : loop_levels
|
||||
for (n = 0; n < W/(2*2**l); n = n + 1) begin : loop_compress
|
||||
assign stage_valid[l][n] = |stage_valid[l-1][n*2+1:n*2];
|
||||
if (LSB_HIGH_PRIORITY) begin
|
||||
// bit 0 is highest priority
|
||||
assign stage_enc[l][(n+1)*(l+1)-1:n*(l+1)] = stage_valid[l-1][n*2+0] ? {1'b0, stage_enc[l-1][(n*2+1)*l-1:(n*2+0)*l]} : {1'b1, stage_enc[l-1][(n*2+2)*l-1:(n*2+1)*l]};
|
||||
end else begin
|
||||
// bit 0 is lowest priority
|
||||
assign stage_enc[l][(n+1)*(l+1)-1:n*(l+1)] = stage_valid[l-1][n*2+1] ? {1'b1, stage_enc[l-1][(n*2+2)*l-1:(n*2+1)*l]} : {1'b0, stage_enc[l-1][(n*2+1)*l-1:(n*2+0)*l]};
|
||||
end
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
assign output_valid = stage_valid[LEVELS-1];
|
||||
assign output_encoded = stage_enc[LEVELS-1];
|
||||
assign output_unencoded = 1 << output_encoded;
|
||||
|
||||
endmodule
|
||||
|
||||
`resetall
|
217
sim/top/axi_wrap_ram.sv
Executable file
217
sim/top/axi_wrap_ram.sv
Executable file
@ -0,0 +1,217 @@
|
||||
`include "axi/typedef.svh"
|
||||
`include "axi/assign.svh"
|
||||
|
||||
// for func test, do not define RUN_PERF_TEST
|
||||
`define _RUN_PERF_TEST
|
||||
`define _RUN_PERF_NO_DELAY
|
||||
|
||||
module axi_wrap_ram(
|
||||
input aclk,
|
||||
input aresetn,
|
||||
//ar
|
||||
input [3 :0] axi_arid ,
|
||||
input [31:0] axi_araddr ,
|
||||
input [7 :0] axi_arlen ,
|
||||
input [2 :0] axi_arsize ,
|
||||
input [1 :0] axi_arburst,
|
||||
input [1 :0] axi_arlock ,
|
||||
input [3 :0] axi_arcache,
|
||||
input [2 :0] axi_arprot ,
|
||||
input axi_arvalid,
|
||||
output axi_arready,
|
||||
//r
|
||||
output [3 :0] axi_rid ,
|
||||
output [31:0] axi_rdata ,
|
||||
output [1 :0] axi_rresp ,
|
||||
output axi_rlast ,
|
||||
output axi_rvalid ,
|
||||
input axi_rready ,
|
||||
//aw
|
||||
input [3 :0] axi_awid ,
|
||||
input [31:0] axi_awaddr ,
|
||||
input [7 :0] axi_awlen ,
|
||||
input [2 :0] axi_awsize ,
|
||||
input [1 :0] axi_awburst,
|
||||
input [1 :0] axi_awlock ,
|
||||
input [3 :0] axi_awcache,
|
||||
input [2 :0] axi_awprot ,
|
||||
input axi_awvalid,
|
||||
output axi_awready,
|
||||
//w
|
||||
input [3 :0] axi_wid ,
|
||||
input [31:0] axi_wdata ,
|
||||
input [3 :0] axi_wstrb ,
|
||||
input axi_wlast ,
|
||||
input axi_wvalid ,
|
||||
output axi_wready ,
|
||||
//b
|
||||
output [3 :0] axi_bid ,
|
||||
output [1 :0] axi_bresp ,
|
||||
output axi_bvalid ,
|
||||
input axi_bready ,
|
||||
|
||||
//from confreg
|
||||
input [4 :0] ram_random_mask
|
||||
);
|
||||
|
||||
wire axi_arvalid_m_masked;
|
||||
wire axi_rready_m_masked;
|
||||
wire axi_awvalid_m_masked;
|
||||
wire axi_wvalid_m_masked;
|
||||
wire axi_bready_m_masked;
|
||||
|
||||
wire axi_arready_s_unmasked;
|
||||
wire axi_rvalid_s_unmasked;
|
||||
wire axi_awready_s_unmasked;
|
||||
wire axi_wready_s_unmasked;
|
||||
wire axi_bvalid_s_unmasked;
|
||||
|
||||
wire ar_and;
|
||||
wire r_and;
|
||||
wire aw_and;
|
||||
wire w_and;
|
||||
wire b_and;
|
||||
reg ar_nomask;
|
||||
reg aw_nomask;
|
||||
reg w_nomask;
|
||||
reg [4:0] pf_r2r;
|
||||
reg [1:0] pf_b2b;
|
||||
wire pf_r2r_nomask= pf_r2r==5'd0;
|
||||
wire pf_b2b_nomask= pf_b2b==2'd0;
|
||||
|
||||
//mask
|
||||
`ifdef RUN_PERF_TEST
|
||||
assign ar_and = 1'b1;
|
||||
assign aw_and = 1'b1;
|
||||
assign w_and = 1'b1;
|
||||
`ifdef RUN_PERF_NO_DELAY
|
||||
assign r_and = 1'b1;
|
||||
assign b_and = 1'b1;
|
||||
`else
|
||||
assign r_and = pf_r2r_nomask;
|
||||
assign b_and = pf_b2b_nomask;
|
||||
`endif
|
||||
`else
|
||||
assign ar_and = ram_random_mask[4] | ar_nomask;
|
||||
assign r_and = ram_random_mask[3] ;
|
||||
assign aw_and = ram_random_mask[2] | aw_nomask;
|
||||
assign w_and = ram_random_mask[1] | w_nomask;
|
||||
assign b_and = ram_random_mask[0] ;
|
||||
`endif
|
||||
always @(posedge aclk)
|
||||
begin
|
||||
//for func test, random mask
|
||||
ar_nomask <= !aresetn ? 1'b0 :
|
||||
axi_arvalid_m_masked&&axi_arready ? 1'b0 :
|
||||
axi_arvalid_m_masked ? 1'b1 : ar_nomask;
|
||||
|
||||
aw_nomask <= !aresetn ? 1'b0 :
|
||||
axi_awvalid_m_masked&&axi_awready ? 1'b0 :
|
||||
axi_awvalid_m_masked ? 1'b1 : aw_nomask;
|
||||
|
||||
w_nomask <= !aresetn ? 1'b0 :
|
||||
axi_wvalid_m_masked&&axi_wready ? 1'b0 :
|
||||
axi_wvalid_m_masked ? 1'b1 : w_nomask;
|
||||
//for perf test
|
||||
pf_r2r <= !aresetn ? 5'd0 :
|
||||
axi_arvalid_m_masked&&axi_arready ? 5'd25 :
|
||||
!pf_r2r_nomask ? pf_r2r-1'b1 : pf_r2r;
|
||||
pf_b2b <= !aresetn ? 2'd0 :
|
||||
axi_awvalid_m_masked&&axi_awready ? 2'd3 :
|
||||
!pf_b2b_nomask ? pf_b2b-1'b1 : pf_b2b;
|
||||
end
|
||||
|
||||
|
||||
//-----{master -> slave}-----
|
||||
assign axi_arvalid_m_masked = axi_arvalid & ar_and;
|
||||
assign axi_rready_m_masked = axi_rready & r_and;
|
||||
assign axi_awvalid_m_masked = axi_awvalid & aw_and;
|
||||
assign axi_wvalid_m_masked = axi_wvalid & w_and;
|
||||
assign axi_bready_m_masked = axi_bready & b_and;
|
||||
|
||||
//-----{slave -> master}-----
|
||||
assign axi_arready = axi_arready_s_unmasked & ar_and;
|
||||
assign axi_rvalid = axi_rvalid_s_unmasked & r_and;
|
||||
assign axi_awready = axi_awready_s_unmasked & aw_and;
|
||||
assign axi_wready = axi_wready_s_unmasked & w_and;
|
||||
assign axi_bvalid = axi_bvalid_s_unmasked & b_and;
|
||||
|
||||
// struct
|
||||
typedef logic [31:0] axi_addr_t;
|
||||
typedef logic [31:0] axi_data_t;
|
||||
typedef logic [ 3:0] axi_id_t ;
|
||||
typedef logic [ 3:0] axi_strb_t;
|
||||
typedef logic [ 3:0] axi_user_t;
|
||||
`AXI_TYPEDEF_ALL(axi, axi_addr_t, axi_id_t, axi_data_t, axi_strb_t, axi_user_t)
|
||||
|
||||
axi_req_t req;
|
||||
axi_resp_t rsp;
|
||||
|
||||
// inst ram axi
|
||||
axi_sim_mem #(
|
||||
.AddrWidth (32'd32),
|
||||
.DataWidth (32'd32),
|
||||
.IdWidth (32'd04),
|
||||
.UserWidth (32'd04),
|
||||
.WarnUninitialized ( 1'b1 ),
|
||||
.axi_req_t (axi_req_t),
|
||||
.axi_rsp_t (axi_resp_t)
|
||||
) axi_ram (
|
||||
.clk_i (aclk),
|
||||
.rst_ni (aresetn),
|
||||
.axi_req_i (req),
|
||||
.axi_rsp_o (rsp)
|
||||
);
|
||||
|
||||
//ar
|
||||
|
||||
assign req.ar.id = axi_arid;
|
||||
assign req.ar.addr = axi_araddr;
|
||||
assign req.ar.len = axi_arlen;
|
||||
assign req.ar.size = axi_arsize;
|
||||
assign req.ar.burst = axi_arburst;
|
||||
assign req.ar.lock = axi_arlock;
|
||||
assign req.ar.cache = axi_arcache;
|
||||
assign req.ar.prot = axi_arprot;
|
||||
assign req.ar_valid = axi_arvalid_m_masked;
|
||||
assign axi_arready_s_unmasked = rsp.ar_ready;
|
||||
|
||||
//r
|
||||
|
||||
assign axi_rid = axi_rvalid ? rsp.r.id : 4'd0 ;
|
||||
assign axi_rdata = axi_rvalid ? rsp.r.data : 32'd0 ;
|
||||
assign axi_rresp = axi_rvalid ? rsp.r.resp : 2'd0 ;
|
||||
assign axi_rlast = axi_rvalid ? rsp.r.last : 1'd0 ;
|
||||
assign axi_rvalid_s_unmasked = rsp.r_valid;
|
||||
assign req.r_ready = axi_rready_m_masked;
|
||||
|
||||
//aw
|
||||
|
||||
assign req.aw.id = axi_awid;
|
||||
assign req.aw.addr = axi_awaddr;
|
||||
assign req.aw.len = axi_awlen;
|
||||
assign req.aw.size = axi_awsize;
|
||||
assign req.aw.burst = axi_awburst;
|
||||
assign req.aw.lock = axi_awlock;
|
||||
assign req.aw.cache = axi_awcache;
|
||||
assign req.aw.prot = axi_awprot;
|
||||
assign req.aw_valid = axi_awvalid_m_masked;
|
||||
assign axi_awready_s_unmasked = rsp.aw_ready;
|
||||
|
||||
//w
|
||||
|
||||
// assign ram_wid = axi_wid ;
|
||||
assign req.w.data = axi_wdata;
|
||||
assign req.w.strb = axi_wstrb;
|
||||
assign req.w.last = axi_wlast;
|
||||
assign req.w_valid = axi_wvalid_m_masked;
|
||||
assign axi_wready_s_unmasked = rsp.w_ready;
|
||||
|
||||
//b
|
||||
|
||||
assign axi_bid = axi_bvalid ? rsp.b.id : 4'd0;
|
||||
assign axi_bresp = axi_bvalid ? rsp.b.resp : 2'd0;
|
||||
assign axi_bvalid_s_unmasked = rsp.b_valid;
|
||||
assign req.b_ready = axi_bready_m_masked;
|
||||
|
||||
endmodule
|
510
sim/top/soc_axi_lite_top.v
Executable file
510
sim/top/soc_axi_lite_top.v
Executable file
@ -0,0 +1,510 @@
|
||||
`timescale 1ns / 1ps
|
||||
|
||||
module soc_axi_lite_top #(parameter SIMULATION=1'b0)
|
||||
(
|
||||
input resetn,
|
||||
input clk,
|
||||
|
||||
//------gpio-------
|
||||
output [15:0] led,
|
||||
output [1 :0] led_rg0,
|
||||
output [1 :0] led_rg1,
|
||||
output [7 :0] num_csn,
|
||||
output [6 :0] num_a_g,
|
||||
input [7 :0] switch,
|
||||
output [3 :0] btn_key_col,
|
||||
input [3 :0] btn_key_row,
|
||||
input [1 :0] btn_step
|
||||
);
|
||||
|
||||
//debug signals
|
||||
wire [31:0] debug_wb_pc;
|
||||
wire [3 :0] debug_wb_rf_wen;
|
||||
wire [4 :0] debug_wb_rf_wnum;
|
||||
wire [31:0] debug_wb_rf_wdata;
|
||||
wire [31:0] debug_wb1_pc;
|
||||
wire [3 :0] debug_wb1_rf_wen;
|
||||
wire [4 :0] debug_wb1_rf_wnum;
|
||||
wire [31:0] debug_wb1_rf_wdata;
|
||||
wire debug_wb_pc_A;
|
||||
|
||||
//cpu axi
|
||||
wire [3 :0] cpu_arid ;
|
||||
wire [31:0] cpu_araddr ;
|
||||
wire [3 :0] cpu_arlen ;
|
||||
wire [2 :0] cpu_arsize ;
|
||||
wire [1 :0] cpu_arburst;
|
||||
wire [1 :0] cpu_arlock ;
|
||||
wire [3 :0] cpu_arcache;
|
||||
wire [2 :0] cpu_arprot ;
|
||||
wire cpu_arvalid;
|
||||
wire cpu_arready;
|
||||
wire [3 :0] cpu_rid ;
|
||||
wire [31:0] cpu_rdata ;
|
||||
wire [1 :0] cpu_rresp ;
|
||||
wire cpu_rlast ;
|
||||
wire cpu_rvalid ;
|
||||
wire cpu_rready ;
|
||||
wire [3 :0] cpu_awid ;
|
||||
wire [31:0] cpu_awaddr ;
|
||||
wire [3 :0] cpu_awlen ;
|
||||
wire [2 :0] cpu_awsize ;
|
||||
wire [1 :0] cpu_awburst;
|
||||
wire [1 :0] cpu_awlock ;
|
||||
wire [3 :0] cpu_awcache;
|
||||
wire [2 :0] cpu_awprot ;
|
||||
wire cpu_awvalid;
|
||||
wire cpu_awready;
|
||||
wire [3 :0] cpu_wid ;
|
||||
wire [31:0] cpu_wdata ;
|
||||
wire [3 :0] cpu_wstrb ;
|
||||
wire cpu_wlast ;
|
||||
wire cpu_wvalid ;
|
||||
wire cpu_wready ;
|
||||
wire [3 :0] cpu_bid ;
|
||||
wire [1 :0] cpu_bresp ;
|
||||
wire cpu_bvalid ;
|
||||
wire cpu_bready ;
|
||||
|
||||
//axi ram
|
||||
wire [3 :0] ram_arid ;
|
||||
wire [31:0] ram_araddr ;
|
||||
wire [7 :0] ram_arlen ;
|
||||
wire [2 :0] ram_arsize ;
|
||||
wire [1 :0] ram_arburst;
|
||||
wire [1 :0] ram_arlock ;
|
||||
wire [3 :0] ram_arcache;
|
||||
wire [2 :0] ram_arprot ;
|
||||
wire ram_arvalid;
|
||||
wire ram_arready;
|
||||
wire [3 :0] ram_rid ;
|
||||
wire [31:0] ram_rdata ;
|
||||
wire [1 :0] ram_rresp ;
|
||||
wire ram_rlast ;
|
||||
wire ram_rvalid ;
|
||||
wire ram_rready ;
|
||||
wire [3 :0] ram_awid ;
|
||||
wire [31:0] ram_awaddr ;
|
||||
wire [7 :0] ram_awlen ;
|
||||
wire [2 :0] ram_awsize ;
|
||||
wire [1 :0] ram_awburst;
|
||||
wire [1 :0] ram_awlock ;
|
||||
wire [3 :0] ram_awcache;
|
||||
wire [2 :0] ram_awprot ;
|
||||
wire ram_awvalid;
|
||||
wire ram_awready;
|
||||
wire [3 :0] ram_wid ;
|
||||
wire [31:0] ram_wdata ;
|
||||
wire [3 :0] ram_wstrb ;
|
||||
wire ram_wlast ;
|
||||
wire ram_wvalid ;
|
||||
wire ram_wready ;
|
||||
wire [3 :0] ram_bid ;
|
||||
wire [1 :0] ram_bresp ;
|
||||
wire ram_bvalid ;
|
||||
wire ram_bready ;
|
||||
|
||||
//conf
|
||||
wire [3 :0] conf_arid ;
|
||||
wire [31:0] conf_araddr ;
|
||||
wire [7 :0] conf_arlen ;
|
||||
wire [2 :0] conf_arsize ;
|
||||
wire [1 :0] conf_arburst;
|
||||
wire [1 :0] conf_arlock ;
|
||||
wire [3 :0] conf_arcache;
|
||||
wire [2 :0] conf_arprot ;
|
||||
wire conf_arvalid;
|
||||
wire conf_arready;
|
||||
wire [3 :0] conf_rid ;
|
||||
wire [31:0] conf_rdata ;
|
||||
wire [1 :0] conf_rresp ;
|
||||
wire conf_rlast ;
|
||||
wire conf_rvalid ;
|
||||
wire conf_rready ;
|
||||
wire [3 :0] conf_awid ;
|
||||
wire [31:0] conf_awaddr ;
|
||||
wire [7 :0] conf_awlen ;
|
||||
wire [2 :0] conf_awsize ;
|
||||
wire [1 :0] conf_awburst;
|
||||
wire [1 :0] conf_awlock ;
|
||||
wire [3 :0] conf_awcache;
|
||||
wire [2 :0] conf_awprot ;
|
||||
wire conf_awvalid;
|
||||
wire conf_awready;
|
||||
wire [3 :0] conf_wid ;
|
||||
wire [31:0] conf_wdata ;
|
||||
wire [3 :0] conf_wstrb ;
|
||||
wire conf_wlast ;
|
||||
wire conf_wvalid ;
|
||||
wire conf_wready ;
|
||||
wire [3 :0] conf_bid ;
|
||||
wire [1 :0] conf_bresp ;
|
||||
wire conf_bvalid ;
|
||||
wire conf_bready ;
|
||||
|
||||
//for lab6
|
||||
wire [4 :0] ram_random_mask;
|
||||
|
||||
//cpu axi
|
||||
mycpu_top u_cpu(
|
||||
.ext_int (6'd0 ), //high active
|
||||
|
||||
.aclk (clk ),
|
||||
.aresetn (resetn ), //low active
|
||||
|
||||
.arid (cpu_arid ),
|
||||
.araddr (cpu_araddr ),
|
||||
.arlen (cpu_arlen ),
|
||||
.arsize (cpu_arsize ),
|
||||
.arburst (cpu_arburst ),
|
||||
.arlock (cpu_arlock ),
|
||||
.arcache (cpu_arcache ),
|
||||
.arprot (cpu_arprot ),
|
||||
.arvalid (cpu_arvalid ),
|
||||
.arready (cpu_arready ),
|
||||
|
||||
.rid (cpu_rid ),
|
||||
.rdata (cpu_rdata ),
|
||||
.rresp (cpu_rresp ),
|
||||
.rlast (cpu_rlast ),
|
||||
.rvalid (cpu_rvalid ),
|
||||
.rready (cpu_rready ),
|
||||
|
||||
.awid (cpu_awid ),
|
||||
.awaddr (cpu_awaddr ),
|
||||
.awlen (cpu_awlen ),
|
||||
.awsize (cpu_awsize ),
|
||||
.awburst (cpu_awburst ),
|
||||
.awlock (cpu_awlock ),
|
||||
.awcache (cpu_awcache ),
|
||||
.awprot (cpu_awprot ),
|
||||
.awvalid (cpu_awvalid ),
|
||||
.awready (cpu_awready ),
|
||||
|
||||
.wid (cpu_wid ),
|
||||
.wdata (cpu_wdata ),
|
||||
.wstrb (cpu_wstrb ),
|
||||
.wlast (cpu_wlast ),
|
||||
.wvalid (cpu_wvalid ),
|
||||
.wready (cpu_wready ),
|
||||
|
||||
.bid (cpu_bid ),
|
||||
.bresp (cpu_bresp ),
|
||||
.bvalid (cpu_bvalid ),
|
||||
.bready (cpu_bready ),
|
||||
|
||||
//debug interface
|
||||
.debug_wb_pc (debug_wb_pc ),
|
||||
.debug_wb_rf_wen (debug_wb_rf_wen ),
|
||||
.debug_wb_rf_wnum (debug_wb_rf_wnum ),
|
||||
.debug_wb_rf_wdata (debug_wb_rf_wdata ),
|
||||
.debug_wb1_pc (debug_wb1_pc ),
|
||||
.debug_wb1_rf_wen (debug_wb1_rf_wen ),
|
||||
.debug_wb1_rf_wnum (debug_wb1_rf_wnum ),
|
||||
.debug_wb1_rf_wdata(debug_wb1_rf_wdata),
|
||||
.debug_wb_pc_A (debug_wb_pc_A )
|
||||
);
|
||||
|
||||
localparam int unsigned TbNumMasters = 32'd1;
|
||||
localparam int unsigned TbNumSlaves = 32'd2;
|
||||
localparam int unsigned TbNumWrites = 32'd200;
|
||||
localparam int unsigned TbNumReads = 32'd200;
|
||||
localparam int unsigned TbAxiIdWidthMasters = 32'd4;
|
||||
localparam int unsigned TbAxiIdUsed = 32'd3;
|
||||
localparam int unsigned TbAxiDataWidth = 32'd32;
|
||||
localparam int unsigned TbPipeline = 32'd1;
|
||||
localparam bit TbEnAtop = 1'b0;
|
||||
localparam bit TbEnExcl = 1'b0;
|
||||
localparam bit TbUniqueIds = 1'b0;
|
||||
|
||||
// AXI configuration which is automatically derived.
|
||||
localparam int unsigned TbAxiIdWidthSlaves = TbAxiIdWidthMasters + $clog2(TbNumMasters);
|
||||
localparam int unsigned TbAxiAddrWidth = 32'd32;
|
||||
localparam int unsigned TbAxiStrbWidth = TbAxiDataWidth / 8;
|
||||
localparam int unsigned TbAxiUserWidth = 5;
|
||||
// In the bench can change this variables which are set here freely,
|
||||
localparam axi_pkg::xbar_cfg_t xbar_cfg = '{
|
||||
NoSlvPorts: TbNumMasters,
|
||||
NoMstPorts: TbNumSlaves,
|
||||
MaxMstTrans: 2,
|
||||
MaxSlvTrans: 2,
|
||||
FallThrough: 1'b0,
|
||||
LatencyMode: axi_pkg::CUT_ALL_AX,
|
||||
PipelineStages: TbPipeline,
|
||||
AxiIdWidthSlvPorts: TbAxiIdWidthMasters,
|
||||
AxiIdUsedSlvPorts: TbAxiIdUsed,
|
||||
UniqueIds: TbUniqueIds,
|
||||
AxiAddrWidth: TbAxiAddrWidth,
|
||||
AxiDataWidth: TbAxiDataWidth,
|
||||
NoAddrRules: TbNumSlaves
|
||||
};
|
||||
typedef logic [TbAxiIdWidthMasters-1:0] id_mst_t;
|
||||
typedef logic [TbAxiIdWidthSlaves-1:0] id_slv_t;
|
||||
typedef logic [TbAxiAddrWidth-1:0] addr_t;
|
||||
typedef axi_pkg::xbar_rule_32_t rule_t;
|
||||
typedef logic [TbAxiDataWidth-1:0] data_t;
|
||||
typedef logic [TbAxiStrbWidth-1:0] strb_t;
|
||||
typedef logic [TbAxiUserWidth-1:0] user_t;
|
||||
|
||||
`AXI_TYPEDEF_AW_CHAN_T(aw_chan_mst_t, addr_t, id_mst_t, user_t)
|
||||
`AXI_TYPEDEF_AW_CHAN_T(aw_chan_slv_t, addr_t, id_slv_t, user_t)
|
||||
`AXI_TYPEDEF_W_CHAN_T(w_chan_t, data_t, strb_t, user_t)
|
||||
`AXI_TYPEDEF_B_CHAN_T(b_chan_mst_t, id_mst_t, user_t)
|
||||
`AXI_TYPEDEF_B_CHAN_T(b_chan_slv_t, id_slv_t, user_t)
|
||||
|
||||
`AXI_TYPEDEF_AR_CHAN_T(ar_chan_mst_t, addr_t, id_mst_t, user_t)
|
||||
`AXI_TYPEDEF_AR_CHAN_T(ar_chan_slv_t, addr_t, id_slv_t, user_t)
|
||||
`AXI_TYPEDEF_R_CHAN_T(r_chan_mst_t, data_t, id_mst_t, user_t)
|
||||
`AXI_TYPEDEF_R_CHAN_T(r_chan_slv_t, data_t, id_slv_t, user_t)
|
||||
|
||||
`AXI_TYPEDEF_REQ_T(mst_req_t, aw_chan_mst_t, w_chan_t, ar_chan_mst_t)
|
||||
`AXI_TYPEDEF_RESP_T(mst_resp_t, b_chan_mst_t, r_chan_mst_t)
|
||||
`AXI_TYPEDEF_REQ_T(slv_req_t, aw_chan_slv_t, w_chan_t, ar_chan_slv_t)
|
||||
`AXI_TYPEDEF_RESP_T(slv_resp_t, b_chan_slv_t, r_chan_slv_t)
|
||||
|
||||
// Each slave has its own address range:
|
||||
localparam rule_t [xbar_cfg.NoAddrRules-1:0] AddrMap = addr_map_gen();
|
||||
|
||||
function rule_t [xbar_cfg.NoAddrRules-1:0] addr_map_gen ();
|
||||
// TODO: finish this mapping
|
||||
addr_map_gen[0] = rule_t'{
|
||||
idx: unsigned'(0),
|
||||
start_addr: i * 32'h0000_2000,
|
||||
end_addr: (i+1) * 32'h0000_2000,
|
||||
default: '0
|
||||
};
|
||||
addr_map_gen[1] = rule_t'{
|
||||
idx: unsigned'(2),
|
||||
start_addr: i * 32'h0000_2000,
|
||||
end_addr: (i+1) * 32'h0000_2000,
|
||||
default: '0
|
||||
};
|
||||
endfunction
|
||||
|
||||
// TODO: connect
|
||||
axi_xbar #(
|
||||
.Cfg(),
|
||||
.ATOPs(),
|
||||
.Connectivity(),
|
||||
.slv_aw_chan_t(),
|
||||
.mst_aw_chan_t(),
|
||||
.w_chan_t(),
|
||||
.slv_b_chan_t(),
|
||||
.mst_b_chan_t(),
|
||||
.slv_ar_chan_t(),
|
||||
.mst_ar_chan_t(),
|
||||
.slv_r_chan_t(),
|
||||
.mst_r_chan_t(),
|
||||
.slv_req_t(),
|
||||
.slv_resp_t(),
|
||||
.mst_req_t(),
|
||||
.mst_resp_t(),
|
||||
.rule_t(),
|
||||
) u_axi_crossbar_1x2_2 (
|
||||
.clk_i (clk),
|
||||
.rst_ni(resetn),
|
||||
.test_i(1'b0),
|
||||
|
||||
.slv_ports_req_i(),
|
||||
.slv_ports_resp_o(),
|
||||
.mst_ports_req_o(),
|
||||
.mst_ports_resp_i(),
|
||||
|
||||
.addr_map_i(),
|
||||
.en_default_mst_port_i(),
|
||||
.default_mst_port_i(),
|
||||
);
|
||||
|
||||
// TODO: delete this
|
||||
axi_crossbar u_axi_crossbar_1x2 (
|
||||
.clk ( clk ), // i, 1
|
||||
.rst ( ~resetn ), // i, 1
|
||||
|
||||
.s_axi_arid ( cpu_arid ),
|
||||
.s_axi_araddr ( cpu_araddr ),
|
||||
.s_axi_arlen ( cpu_arlen[3:0] ),
|
||||
.s_axi_arsize ( cpu_arsize ),
|
||||
.s_axi_arburst ( cpu_arburst ),
|
||||
.s_axi_arlock ( cpu_arlock ),
|
||||
.s_axi_arcache ( cpu_arcache ),
|
||||
.s_axi_arprot ( cpu_arprot ),
|
||||
.s_axi_arqos ( 4'd0 ),
|
||||
.s_axi_arvalid ( cpu_arvalid ),
|
||||
.s_axi_arready ( cpu_arready ),
|
||||
.s_axi_rid ( cpu_rid ),
|
||||
.s_axi_rdata ( cpu_rdata ),
|
||||
.s_axi_rresp ( cpu_rresp ),
|
||||
.s_axi_rlast ( cpu_rlast ),
|
||||
.s_axi_rvalid ( cpu_rvalid ),
|
||||
.s_axi_rready ( cpu_rready ),
|
||||
.s_axi_awid ( cpu_awid ),
|
||||
.s_axi_awaddr ( cpu_awaddr ),
|
||||
.s_axi_awlen ( cpu_awlen[3:0] ),
|
||||
.s_axi_awsize ( cpu_awsize ),
|
||||
.s_axi_awburst ( cpu_awburst ),
|
||||
.s_axi_awlock ( cpu_awlock ),
|
||||
.s_axi_awcache ( cpu_awcache ),
|
||||
.s_axi_awprot ( cpu_awprot ),
|
||||
.s_axi_awqos ( 4'd0 ),
|
||||
.s_axi_awvalid ( cpu_awvalid ),
|
||||
.s_axi_awready ( cpu_awready ),
|
||||
.s_axi_wid ( cpu_wid ),
|
||||
.s_axi_wdata ( cpu_wdata ),
|
||||
.s_axi_wstrb ( cpu_wstrb ),
|
||||
.s_axi_wlast ( cpu_wlast ),
|
||||
.s_axi_wvalid ( cpu_wvalid ),
|
||||
.s_axi_wready ( cpu_wready ),
|
||||
.s_axi_bid ( cpu_bid ),
|
||||
.s_axi_bresp ( cpu_bresp ),
|
||||
.s_axi_bvalid ( cpu_bvalid ),
|
||||
.s_axi_bready ( cpu_bready ),
|
||||
|
||||
.m_axi_arid ( {ram_arid , conf_arid } ),
|
||||
.m_axi_araddr ( {ram_araddr , conf_araddr } ),
|
||||
.m_axi_arlen ( {ram_arlen , conf_arlen } ),
|
||||
.m_axi_arsize ( {ram_arsize , conf_arsize } ),
|
||||
.m_axi_arburst ( {ram_arburst, conf_arburst} ),
|
||||
.m_axi_arlock ( {ram_arlock , conf_arlock } ),
|
||||
.m_axi_arcache ( {ram_arcache, conf_arcache} ),
|
||||
.m_axi_arprot ( {ram_arprot , conf_arprot } ),
|
||||
.m_axi_arqos ( ),
|
||||
.m_axi_arvalid ( {ram_arvalid, conf_arvalid} ),
|
||||
.m_axi_arready ( {ram_arready, conf_arready} ),
|
||||
.m_axi_rid ( {ram_rid , conf_rid } ),
|
||||
.m_axi_rdata ( {ram_rdata , conf_rdata } ),
|
||||
.m_axi_rresp ( {ram_rresp , conf_rresp } ),
|
||||
.m_axi_rlast ( {ram_rlast , conf_rlast } ),
|
||||
.m_axi_rvalid ( {ram_rvalid , conf_rvalid } ),
|
||||
.m_axi_rready ( {ram_rready , conf_rready } ),
|
||||
.m_axi_awid ( {ram_awid , conf_awid } ),
|
||||
.m_axi_awaddr ( {ram_awaddr , conf_awaddr } ),
|
||||
.m_axi_awlen ( {ram_awlen , conf_awlen } ),
|
||||
.m_axi_awsize ( {ram_awsize , conf_awsize } ),
|
||||
.m_axi_awburst ( {ram_awburst, conf_awburst} ),
|
||||
.m_axi_awlock ( {ram_awlock , conf_awlock } ),
|
||||
.m_axi_awcache ( {ram_awcache, conf_awcache} ),
|
||||
.m_axi_awprot ( {ram_awprot , conf_awprot } ),
|
||||
.m_axi_awqos ( ),
|
||||
.m_axi_awvalid ( {ram_awvalid, conf_awvalid} ),
|
||||
.m_axi_awready ( {ram_awready, conf_awready} ),
|
||||
.m_axi_wid ( {ram_wid , conf_wid } ),
|
||||
.m_axi_wdata ( {ram_wdata , conf_wdata } ),
|
||||
.m_axi_wstrb ( {ram_wstrb , conf_wstrb } ),
|
||||
.m_axi_wlast ( {ram_wlast , conf_wlast } ),
|
||||
.m_axi_wvalid ( {ram_wvalid , conf_wvalid } ),
|
||||
.m_axi_wready ( {ram_wready , conf_wready } ),
|
||||
.m_axi_bid ( {ram_bid , conf_bid } ),
|
||||
.m_axi_bresp ( {ram_bresp , conf_bresp } ),
|
||||
.m_axi_bvalid ( {ram_bvalid , conf_bvalid } ),
|
||||
.m_axi_bready ( {ram_bready , conf_bready } )
|
||||
);
|
||||
|
||||
//axi ram
|
||||
axi_wrap_ram u_axi_ram
|
||||
(
|
||||
.aclk ( clk ),
|
||||
.aresetn ( resetn ),
|
||||
//ar
|
||||
.axi_arid ( ram_arid ),
|
||||
.axi_araddr ( ram_araddr ),
|
||||
.axi_arlen ( ram_arlen ),
|
||||
.axi_arsize ( ram_arsize ),
|
||||
.axi_arburst ( ram_arburst ),
|
||||
.axi_arlock ( ram_arlock ),
|
||||
.axi_arcache ( ram_arcache ),
|
||||
.axi_arprot ( ram_arprot ),
|
||||
.axi_arvalid ( ram_arvalid ),
|
||||
.axi_arready ( ram_arready ),
|
||||
//r
|
||||
.axi_rid ( ram_rid ),
|
||||
.axi_rdata ( ram_rdata ),
|
||||
.axi_rresp ( ram_rresp ),
|
||||
.axi_rlast ( ram_rlast ),
|
||||
.axi_rvalid ( ram_rvalid ),
|
||||
.axi_rready ( ram_rready ),
|
||||
//aw
|
||||
.axi_awid ( ram_awid ),
|
||||
.axi_awaddr ( ram_awaddr ),
|
||||
.axi_awlen ( {4'd0, ram_awlen[3:0]} ),
|
||||
.axi_awsize ( ram_awsize ),
|
||||
.axi_awburst ( ram_awburst ),
|
||||
.axi_awlock ( ram_awlock ),
|
||||
.axi_awcache ( ram_awcache ),
|
||||
.axi_awprot ( ram_awprot ),
|
||||
.axi_awvalid ( ram_awvalid ),
|
||||
.axi_awready ( ram_awready ),
|
||||
//w
|
||||
.axi_wid ( ram_wid ),
|
||||
.axi_wdata ( ram_wdata ),
|
||||
.axi_wstrb ( ram_wstrb ),
|
||||
.axi_wlast ( ram_wlast ),
|
||||
.axi_wvalid ( ram_wvalid ),
|
||||
.axi_wready ( ram_wready ),
|
||||
//b ram
|
||||
.axi_bid ( ram_bid ),
|
||||
.axi_bresp ( ram_bresp ),
|
||||
.axi_bvalid ( ram_bvalid ),
|
||||
.axi_bready ( ram_bready ),
|
||||
|
||||
//random mask
|
||||
.ram_random_mask ( ram_random_mask )
|
||||
);
|
||||
|
||||
//confreg
|
||||
confreg #(.SIMULATION(SIMULATION)) u_confreg
|
||||
(
|
||||
.timer_clk ( clk ), // i, 1
|
||||
.aclk ( clk ), // i, 1
|
||||
.aresetn ( resetn ), // i, 1
|
||||
|
||||
.arid (conf_arid ),
|
||||
.araddr (conf_araddr ),
|
||||
.arlen (conf_arlen ),
|
||||
.arsize (conf_arsize ),
|
||||
.arburst (conf_arburst ),
|
||||
.arlock (conf_arlock ),
|
||||
.arcache (conf_arcache ),
|
||||
.arprot (conf_arprot ),
|
||||
.arvalid (conf_arvalid ),
|
||||
.arready (conf_arready ),
|
||||
.rid (conf_rid ),
|
||||
.rdata (conf_rdata ),
|
||||
.rresp (conf_rresp ),
|
||||
.rlast (conf_rlast ),
|
||||
.rvalid (conf_rvalid ),
|
||||
.rready (conf_rready ),
|
||||
.awid (conf_awid ),
|
||||
.awaddr (conf_awaddr ),
|
||||
.awlen (conf_awlen ),
|
||||
.awsize (conf_awsize ),
|
||||
.awburst (conf_awburst ),
|
||||
.awlock (conf_awlock ),
|
||||
.awcache (conf_awcache ),
|
||||
.awprot (conf_awprot ),
|
||||
.awvalid (conf_awvalid ),
|
||||
.awready (conf_awready ),
|
||||
.wid (conf_wid ),
|
||||
.wdata (conf_wdata ),
|
||||
.wstrb (conf_wstrb ),
|
||||
.wlast (conf_wlast ),
|
||||
.wvalid (conf_wvalid ),
|
||||
.wready (conf_wready ),
|
||||
.bid (conf_bid ),
|
||||
.bresp (conf_bresp ),
|
||||
.bvalid (conf_bvalid ),
|
||||
.bready (conf_bready ),
|
||||
|
||||
.ram_random_mask ( ram_random_mask ),
|
||||
.led ( led ), // o, 16
|
||||
.led_rg0 ( led_rg0 ), // o, 2
|
||||
.led_rg1 ( led_rg1 ), // o, 2
|
||||
.num_csn ( num_csn ), // o, 8
|
||||
.num_a_g ( num_a_g ), // o, 7
|
||||
.switch ( switch ), // i, 8
|
||||
.btn_key_col ( btn_key_col), // o, 4
|
||||
.btn_key_row ( btn_key_row), // i, 4
|
||||
.btn_step ( btn_step ) // i, 2
|
||||
);
|
||||
|
||||
endmodule
|
||||
|
@ -59,6 +59,7 @@ module testbench_top (
|
||||
logic [31:0] dbg_1_pc;
|
||||
logic [ 4:0] dbg_1_rf_wnum;
|
||||
logic [31:0] dbg_1_rf_wdata;
|
||||
|
||||
assign debug_wb_pc = soc_lite.debug_wb_pc;
|
||||
assign debug_wb_rf_wen = soc_lite.debug_wb_rf_wen;
|
||||
assign debug_wb_rf_wnum = soc_lite.debug_wb_rf_wnum;
|
||||
@ -91,15 +92,6 @@ module testbench_top (
|
||||
dbg_0_rf_wnum <= debug_wb_rf_wnum;
|
||||
dbg_0_rf_wdata <= debug_wb_rf_wdata;
|
||||
end
|
||||
|
||||
//if (|dbg_0_rf_wen & resetn) begin
|
||||
// $display("path0 : PC = 0x%8h, wb_rf_wnum = 0x%2h, wb_rf_wdata = 0x%8h, wen= %d",
|
||||
// dbg_0_pc, dbg_0_rf_wnum, dbg_0_rf_wdata, |dbg_0_rf_wen);
|
||||
//end
|
||||
//if (|dbg_1_rf_wen & resetn) begin
|
||||
// $display("path1 : PC = 0x%8h, wb_rf_wnum = 0x%2h, wb_rf_wdata = 0x%8h, wen= %d",
|
||||
// dbg_1_pc, dbg_1_rf_wnum, dbg_1_rf_wdata, |dbg_1_rf_wen);
|
||||
//end
|
||||
end
|
||||
|
||||
// UART
|
Loading…
Reference in New Issue
Block a user