switch to new model

This commit is contained in:
Paul Pan 2024-01-23 17:52:05 +08:00
parent 1f1029ec07
commit d2842e7a16
21 changed files with 741 additions and 5075 deletions

3
.gitmodules vendored Normal file
View File

@ -0,0 +1,3 @@
[submodule "sim/model/axi"]
path = sim/model/axi
url = https://github.com/pulp-platform/axi

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 #

View File

@ -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

View File

@ -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

@ -0,0 +1 @@
Subproject commit fccffb5953ec8564218ba05e20adbedec845e014

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
View 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
View 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

View File

@ -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