feat: MU rewrite 1
1. ALU format 2. FIX hazard (MOVN / MOVZ) 3. verilator support
This commit is contained in:
parent
e569965556
commit
9ce588757d
@ -1,6 +1,6 @@
|
|||||||
root = true
|
root = true
|
||||||
|
|
||||||
[src/**/*.{sv,svh}]
|
[**/*.{sv,svh}]
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
indent_style = space
|
indent_style = space
|
||||||
indent_size = 2
|
indent_size = 2
|
||||||
@ -8,10 +8,18 @@ end_of_line = lf
|
|||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
[Makefile]
|
[sim/Makefile]
|
||||||
indent_style = tab
|
indent_style = tab
|
||||||
|
|
||||||
[tools/**/*.txt]
|
[sim/**/*.{c,cpp,h,hpp}]
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
end_of_line = lf
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[tools/*.txt]
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
indent_style = tab
|
indent_style = tab
|
||||||
indent_size = 8
|
indent_size = 8
|
||||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -2,4 +2,5 @@ vivado.log
|
|||||||
vivado.jou
|
vivado.jou
|
||||||
.library_mapping.xml
|
.library_mapping.xml
|
||||||
.project
|
.project
|
||||||
.settings
|
.settings
|
||||||
|
.vscode
|
||||||
|
166
resources/func_test/axi_wrap.v
Executable file
166
resources/func_test/axi_wrap.v
Executable file
@ -0,0 +1,166 @@
|
|||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
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
|
293
resources/func_test/axi_wrap_ram.v
Executable file
293
resources/func_test/axi_wrap_ram.v
Executable file
@ -0,0 +1,293 @@
|
|||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
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
|
837
resources/func_test/confreg.v
Executable file
837
resources/func_test/confreg.v
Executable file
@ -0,0 +1,837 @@
|
|||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
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.
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
//*************************************************************************
|
||||||
|
// > File Name : confreg.v
|
||||||
|
// > Description : Control module of
|
||||||
|
// 16 red leds, 2 green/red leds,
|
||||||
|
// 7-segment display,
|
||||||
|
// switchs,
|
||||||
|
// key board,
|
||||||
|
// bottom STEP,
|
||||||
|
// timer.
|
||||||
|
//
|
||||||
|
// > Author : LOONGSON
|
||||||
|
// > Date : 2017-08-04
|
||||||
|
//*************************************************************************
|
||||||
|
`define RANDOM_SEED {7'b1010101,16'h00FF}
|
||||||
|
|
||||||
|
`define CR0_ADDR 16'h8000 //32'hbfaf_8000
|
||||||
|
`define CR1_ADDR 16'h8004 //32'hbfaf_8004
|
||||||
|
`define CR2_ADDR 16'h8008 //32'hbfaf_8008
|
||||||
|
`define CR3_ADDR 16'h800c //32'hbfaf_800c
|
||||||
|
`define CR4_ADDR 16'h8010 //32'hbfaf_8010
|
||||||
|
`define CR5_ADDR 16'h8014 //32'hbfaf_8014
|
||||||
|
`define CR6_ADDR 16'h8018 //32'hbfaf_8018
|
||||||
|
`define CR7_ADDR 16'h801c //32'hbfaf_801c
|
||||||
|
|
||||||
|
`define LED_ADDR 16'hf000 //32'hbfaf_f000
|
||||||
|
`define LED_RG0_ADDR 16'hf004 //32'hbfaf_f004
|
||||||
|
`define LED_RG1_ADDR 16'hf008 //32'hbfaf_f008
|
||||||
|
`define NUM_ADDR 16'hf010 //32'hbfaf_f010
|
||||||
|
`define SWITCH_ADDR 16'hf020 //32'hbfaf_f020
|
||||||
|
`define BTN_KEY_ADDR 16'hf024 //32'hbfaf_f024
|
||||||
|
`define BTN_STEP_ADDR 16'hf028 //32'hbfaf_f028
|
||||||
|
`define SW_INTER_ADDR 16'hf02c //32'hbfaf_f02c
|
||||||
|
`define TIMER_ADDR 16'he000 //32'hbfaf_e000
|
||||||
|
|
||||||
|
`define IO_SIMU_ADDR 16'hffec //32'hbfaf_ffec
|
||||||
|
`define VIRTUAL_UART_ADDR 16'hfff0 //32'hbfaf_fff0
|
||||||
|
`define SIMU_FLAG_ADDR 16'hfff4 //32'hbfaf_fff4
|
||||||
|
`define OPEN_TRACE_ADDR 16'hfff8 //32'hbfaf_fff8
|
||||||
|
`define NUM_MONITOR_ADDR 16'hfffc //32'hbfaf_fffc
|
||||||
|
module confreg
|
||||||
|
#(parameter SIMULATION=1'b0)
|
||||||
|
(
|
||||||
|
input aclk,
|
||||||
|
input timer_clk,
|
||||||
|
input aresetn,
|
||||||
|
// read and write from cpu
|
||||||
|
//ar
|
||||||
|
input [3 :0] arid ,
|
||||||
|
input [31:0] araddr ,
|
||||||
|
input [7 :0] arlen ,
|
||||||
|
input [2 :0] arsize ,
|
||||||
|
input [1 :0] arburst,
|
||||||
|
input [1 :0] arlock ,
|
||||||
|
input [3 :0] arcache,
|
||||||
|
input [2 :0] arprot ,
|
||||||
|
input arvalid,
|
||||||
|
output arready,
|
||||||
|
//r
|
||||||
|
output [3 :0] rid ,
|
||||||
|
output [31:0] rdata ,
|
||||||
|
output [1 :0] rresp ,
|
||||||
|
output rlast ,
|
||||||
|
output rvalid ,
|
||||||
|
input rready ,
|
||||||
|
//aw
|
||||||
|
input [3 :0] awid ,
|
||||||
|
input [31:0] awaddr ,
|
||||||
|
input [7 :0] awlen ,
|
||||||
|
input [2 :0] awsize ,
|
||||||
|
input [1 :0] awburst,
|
||||||
|
input [1 :0] awlock ,
|
||||||
|
input [3 :0] awcache,
|
||||||
|
input [2 :0] awprot ,
|
||||||
|
input awvalid,
|
||||||
|
output awready,
|
||||||
|
//w
|
||||||
|
input [3 :0] wid ,
|
||||||
|
input [31:0] wdata ,
|
||||||
|
input [3 :0] wstrb ,
|
||||||
|
input wlast ,
|
||||||
|
input wvalid ,
|
||||||
|
output wready ,
|
||||||
|
//b
|
||||||
|
output [3 :0] bid ,
|
||||||
|
output [1 :0] bresp ,
|
||||||
|
output bvalid ,
|
||||||
|
input bready ,
|
||||||
|
|
||||||
|
//for lab6
|
||||||
|
output [4 :0] ram_random_mask ,
|
||||||
|
|
||||||
|
// read and write to device on board
|
||||||
|
output [15:0] led,
|
||||||
|
output [1 :0] led_rg0,
|
||||||
|
output [1 :0] led_rg1,
|
||||||
|
output reg [7 :0] num_csn,
|
||||||
|
output reg [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
|
||||||
|
);
|
||||||
|
reg [31:0] cr0;
|
||||||
|
reg [31:0] cr1;
|
||||||
|
reg [31:0] cr2;
|
||||||
|
reg [31:0] cr3;
|
||||||
|
reg [31:0] cr4;
|
||||||
|
reg [31:0] cr5;
|
||||||
|
reg [31:0] cr6;
|
||||||
|
reg [31:0] cr7;
|
||||||
|
|
||||||
|
reg [31:0] led_data;
|
||||||
|
reg [31:0] led_rg0_data;
|
||||||
|
reg [31:0] led_rg1_data;
|
||||||
|
reg [31:0] num_data;
|
||||||
|
wire [31:0] switch_data;
|
||||||
|
wire [31:0] sw_inter_data; //switch interleave
|
||||||
|
wire [31:0] btn_key_data;
|
||||||
|
wire [31:0] btn_step_data;
|
||||||
|
reg [31:0] timer_r2;
|
||||||
|
reg [31:0] simu_flag;
|
||||||
|
reg [31:0] io_simu;
|
||||||
|
reg [7 :0] virtual_uart_data;
|
||||||
|
reg open_trace;
|
||||||
|
reg num_monitor;
|
||||||
|
|
||||||
|
//--------------------------{axi interface}begin-------------------------//
|
||||||
|
reg busy,write,R_or_W;
|
||||||
|
reg s_wready;
|
||||||
|
|
||||||
|
wire ar_enter = arvalid & arready;
|
||||||
|
wire r_retire = rvalid & rready & rlast;
|
||||||
|
wire aw_enter = awvalid & awready;
|
||||||
|
wire w_enter = wvalid & wready & wlast;
|
||||||
|
wire b_retire = bvalid & bready;
|
||||||
|
|
||||||
|
assign arready = ~busy & (!R_or_W| !awvalid);
|
||||||
|
assign awready = ~busy & ( R_or_W| !arvalid);
|
||||||
|
|
||||||
|
reg [3 :0] buf_id;
|
||||||
|
reg [31:0] buf_addr;
|
||||||
|
reg [7 :0] buf_len;
|
||||||
|
reg [2 :0] buf_size;
|
||||||
|
|
||||||
|
always @(posedge aclk)
|
||||||
|
begin
|
||||||
|
if(~aresetn) busy <= 1'b0;
|
||||||
|
else if(ar_enter|aw_enter) busy <= 1'b1;
|
||||||
|
else if(r_retire|b_retire) busy <= 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(posedge aclk)
|
||||||
|
begin
|
||||||
|
if(~aresetn)
|
||||||
|
begin
|
||||||
|
R_or_W <= 1'b0;
|
||||||
|
buf_id <= 4'b0;
|
||||||
|
buf_addr <= 32'b0;
|
||||||
|
buf_len <= 8'b0;
|
||||||
|
buf_size <= 3'b0;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if(ar_enter | aw_enter)
|
||||||
|
begin
|
||||||
|
R_or_W <= ar_enter;
|
||||||
|
buf_id <= ar_enter ? arid : awid ;
|
||||||
|
buf_addr <= ar_enter ? araddr : awaddr ;
|
||||||
|
buf_len <= ar_enter ? arlen : awlen ;
|
||||||
|
buf_size <= ar_enter ? arsize : awsize ;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
reg conf_wready_reg;
|
||||||
|
assign wready = conf_wready_reg;
|
||||||
|
always@(posedge aclk)
|
||||||
|
begin
|
||||||
|
if (~aresetn ) conf_wready_reg <= 1'b0;
|
||||||
|
else if(aw_enter ) conf_wready_reg <= 1'b1;
|
||||||
|
else if(w_enter & wlast) conf_wready_reg <= 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
|
// read data has one cycle delay
|
||||||
|
reg [31:0] conf_rdata_reg;
|
||||||
|
reg conf_rvalid_reg;
|
||||||
|
reg conf_rlast_reg;
|
||||||
|
assign rdata = conf_rdata_reg;
|
||||||
|
assign rvalid = conf_rvalid_reg;
|
||||||
|
assign rlast = conf_rlast_reg;
|
||||||
|
always @(posedge aclk)
|
||||||
|
begin
|
||||||
|
if(~aresetn)
|
||||||
|
begin
|
||||||
|
conf_rdata_reg <= 32'd0;
|
||||||
|
conf_rvalid_reg <= 1'd0;
|
||||||
|
conf_rlast_reg <= 1'd0;
|
||||||
|
end
|
||||||
|
else if(busy & R_or_W & !r_retire)
|
||||||
|
begin
|
||||||
|
conf_rvalid_reg <= 1'd1;
|
||||||
|
conf_rlast_reg <= 1'd1;
|
||||||
|
case (buf_addr[15:0])
|
||||||
|
`CR0_ADDR : conf_rdata_reg <= cr0 ;
|
||||||
|
`CR1_ADDR : conf_rdata_reg <= cr1 ;
|
||||||
|
`CR2_ADDR : conf_rdata_reg <= cr2 ;
|
||||||
|
`CR3_ADDR : conf_rdata_reg <= cr3 ;
|
||||||
|
`CR4_ADDR : conf_rdata_reg <= cr4 ;
|
||||||
|
`CR5_ADDR : conf_rdata_reg <= cr5 ;
|
||||||
|
`CR6_ADDR : conf_rdata_reg <= cr6 ;
|
||||||
|
`CR7_ADDR : conf_rdata_reg <= cr7 ;
|
||||||
|
`LED_ADDR : conf_rdata_reg <= led_data ;
|
||||||
|
`LED_RG0_ADDR : conf_rdata_reg <= led_rg0_data ;
|
||||||
|
`LED_RG1_ADDR : conf_rdata_reg <= led_rg1_data ;
|
||||||
|
`NUM_ADDR : conf_rdata_reg <= num_data ;
|
||||||
|
`SWITCH_ADDR : conf_rdata_reg <= switch_data ;
|
||||||
|
`BTN_KEY_ADDR : conf_rdata_reg <= btn_key_data ;
|
||||||
|
`BTN_STEP_ADDR : conf_rdata_reg <= btn_step_data;
|
||||||
|
`SW_INTER_ADDR : conf_rdata_reg <= sw_inter_data;
|
||||||
|
`TIMER_ADDR : conf_rdata_reg <= timer_r2 ;
|
||||||
|
`SIMU_FLAG_ADDR: conf_rdata_reg <= simu_flag ;
|
||||||
|
`IO_SIMU_ADDR : conf_rdata_reg <= io_simu ;
|
||||||
|
`VIRTUAL_UART_ADDR : conf_rdata_reg <= {24'd0,virtual_uart_data} ;
|
||||||
|
`OPEN_TRACE_ADDR : conf_rdata_reg <= {31'd0,open_trace} ;
|
||||||
|
`NUM_MONITOR_ADDR: conf_rdata_reg <= {31'd0,num_monitor} ;
|
||||||
|
default : conf_rdata_reg <= 32'd0;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
else if(r_retire)
|
||||||
|
begin
|
||||||
|
conf_rvalid_reg <= 1'b0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
//conf write, only support a word write
|
||||||
|
wire conf_we;
|
||||||
|
wire [31:0] conf_addr;
|
||||||
|
wire [31:0] conf_wdata;
|
||||||
|
assign conf_we = w_enter;
|
||||||
|
assign conf_addr = buf_addr;
|
||||||
|
assign conf_wdata= wdata;
|
||||||
|
|
||||||
|
reg conf_bvalid_reg;
|
||||||
|
assign bvalid = conf_bvalid_reg;
|
||||||
|
always @(posedge aclk)
|
||||||
|
begin
|
||||||
|
if (~aresetn) conf_bvalid_reg <= 1'b0;
|
||||||
|
else if(w_enter ) conf_bvalid_reg <= 1'b1;
|
||||||
|
else if(b_retire) conf_bvalid_reg <= 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
|
assign rid = buf_id;
|
||||||
|
assign bid = buf_id;
|
||||||
|
assign bresp = 2'b0;
|
||||||
|
assign rresp = 2'b0;
|
||||||
|
//---------------------------{axi interface}end--------------------------//
|
||||||
|
|
||||||
|
//-------------------------{confreg register}begin-----------------------//
|
||||||
|
wire write_cr0 = conf_we & (conf_addr[15:0]==`CR0_ADDR);
|
||||||
|
wire write_cr1 = conf_we & (conf_addr[15:0]==`CR1_ADDR);
|
||||||
|
wire write_cr2 = conf_we & (conf_addr[15:0]==`CR2_ADDR);
|
||||||
|
wire write_cr3 = conf_we & (conf_addr[15:0]==`CR3_ADDR);
|
||||||
|
wire write_cr4 = conf_we & (conf_addr[15:0]==`CR4_ADDR);
|
||||||
|
wire write_cr5 = conf_we & (conf_addr[15:0]==`CR5_ADDR);
|
||||||
|
wire write_cr6 = conf_we & (conf_addr[15:0]==`CR6_ADDR);
|
||||||
|
wire write_cr7 = conf_we & (conf_addr[15:0]==`CR7_ADDR);
|
||||||
|
always @(posedge aclk)
|
||||||
|
begin
|
||||||
|
cr0 <= !aresetn ? 32'd0 :
|
||||||
|
write_cr0 ? conf_wdata : cr0;
|
||||||
|
cr1 <= !aresetn ? 32'd0 :
|
||||||
|
write_cr1 ? conf_wdata : cr1;
|
||||||
|
cr2 <= !aresetn ? 32'd0 :
|
||||||
|
write_cr2 ? conf_wdata : cr2;
|
||||||
|
cr3 <= !aresetn ? 32'd0 :
|
||||||
|
write_cr3 ? conf_wdata : cr3;
|
||||||
|
cr4 <= !aresetn ? 32'd0 :
|
||||||
|
write_cr4 ? conf_wdata : cr4;
|
||||||
|
cr5 <= !aresetn ? 32'd0 :
|
||||||
|
write_cr5 ? conf_wdata : cr5;
|
||||||
|
cr6 <= !aresetn ? 32'd0 :
|
||||||
|
write_cr6 ? conf_wdata : cr6;
|
||||||
|
cr7 <= !aresetn ? 32'd0 :
|
||||||
|
write_cr7 ? conf_wdata : cr7;
|
||||||
|
end
|
||||||
|
//--------------------------{confreg register}end------------------------//
|
||||||
|
|
||||||
|
//-------------------------------{timer}begin----------------------------//
|
||||||
|
reg write_timer_begin,write_timer_begin_r1, write_timer_begin_r2,write_timer_begin_r3;
|
||||||
|
reg write_timer_end_r1, write_timer_end_r2;
|
||||||
|
reg [31:0] conf_wdata_r, conf_wdata_r1,conf_wdata_r2;
|
||||||
|
|
||||||
|
reg [31:0] timer_r1;
|
||||||
|
reg [31:0] timer;
|
||||||
|
|
||||||
|
wire write_timer = conf_we & (conf_addr[15:0]==`TIMER_ADDR);
|
||||||
|
always @(posedge aclk)
|
||||||
|
begin
|
||||||
|
if (!aresetn)
|
||||||
|
begin
|
||||||
|
write_timer_begin <= 1'b0;
|
||||||
|
end
|
||||||
|
else if (write_timer)
|
||||||
|
begin
|
||||||
|
write_timer_begin <= 1'b1;
|
||||||
|
conf_wdata_r <= conf_wdata;
|
||||||
|
end
|
||||||
|
else if (write_timer_end_r2)
|
||||||
|
begin
|
||||||
|
write_timer_begin <= 1'b0;
|
||||||
|
end
|
||||||
|
|
||||||
|
write_timer_end_r1 <= write_timer_begin_r2;
|
||||||
|
write_timer_end_r2 <= write_timer_end_r1;
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(posedge timer_clk)
|
||||||
|
begin
|
||||||
|
write_timer_begin_r1 <= write_timer_begin;
|
||||||
|
write_timer_begin_r2 <= write_timer_begin_r1;
|
||||||
|
write_timer_begin_r3 <= write_timer_begin_r2;
|
||||||
|
conf_wdata_r1 <= conf_wdata_r;
|
||||||
|
conf_wdata_r2 <= conf_wdata_r1;
|
||||||
|
|
||||||
|
if(!aresetn)
|
||||||
|
begin
|
||||||
|
timer <= 32'd0;
|
||||||
|
end
|
||||||
|
else if (write_timer_begin_r2 && !write_timer_begin_r3)
|
||||||
|
begin
|
||||||
|
timer <= conf_wdata_r2[31:0];
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
timer <= timer + 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(posedge aclk)
|
||||||
|
begin
|
||||||
|
timer_r1 <= timer;
|
||||||
|
timer_r2 <= timer_r1;
|
||||||
|
end
|
||||||
|
//--------------------------------{timer}end-----------------------------//
|
||||||
|
|
||||||
|
//--------------------------{simulation flag}begin-----------------------//
|
||||||
|
always @(posedge aclk)
|
||||||
|
begin
|
||||||
|
if(!aresetn)
|
||||||
|
begin
|
||||||
|
simu_flag <= {32{SIMULATION}};
|
||||||
|
end
|
||||||
|
end
|
||||||
|
//---------------------------{simulation flag}end------------------------//
|
||||||
|
|
||||||
|
//---------------------------{io simulation}begin------------------------//
|
||||||
|
wire write_io_simu = conf_we & (conf_addr[15:0]==`IO_SIMU_ADDR);
|
||||||
|
always @(posedge aclk)
|
||||||
|
begin
|
||||||
|
if(!aresetn)
|
||||||
|
begin
|
||||||
|
io_simu <= 32'd0;
|
||||||
|
end
|
||||||
|
else if(write_io_simu)
|
||||||
|
begin
|
||||||
|
io_simu <= {conf_wdata[15:0],conf_wdata[31:16]};
|
||||||
|
end
|
||||||
|
end
|
||||||
|
//----------------------------{io simulation}end-------------------------//
|
||||||
|
|
||||||
|
//-----------------------------{open trace}begin-------------------------//
|
||||||
|
wire write_open_trace = conf_we & (conf_addr[15:0]==`OPEN_TRACE_ADDR);
|
||||||
|
always @(posedge aclk)
|
||||||
|
begin
|
||||||
|
if(!aresetn)
|
||||||
|
begin
|
||||||
|
open_trace <= 1'b1;
|
||||||
|
end
|
||||||
|
else if(write_open_trace)
|
||||||
|
begin
|
||||||
|
open_trace <= |conf_wdata;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
//-----------------------------{open trace}end---------------------------//
|
||||||
|
|
||||||
|
//----------------------------{num monitor}begin-------------------------//
|
||||||
|
wire write_num_monitor = conf_we & (conf_addr[15:0]==`NUM_MONITOR_ADDR);
|
||||||
|
always @(posedge aclk)
|
||||||
|
begin
|
||||||
|
if(!aresetn)
|
||||||
|
begin
|
||||||
|
num_monitor <= 1'b1;
|
||||||
|
end
|
||||||
|
else if(write_num_monitor)
|
||||||
|
begin
|
||||||
|
num_monitor <= conf_wdata[0];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
//----------------------------{num monitor}end---------------------------//
|
||||||
|
|
||||||
|
//---------------------------{virtual uart}begin-------------------------//
|
||||||
|
wire [7:0] write_uart_data;
|
||||||
|
wire write_uart_valid = conf_we & (conf_addr[15:0]==`VIRTUAL_UART_ADDR);
|
||||||
|
assign write_uart_data = conf_wdata[7:0];
|
||||||
|
always @(posedge aclk)
|
||||||
|
begin
|
||||||
|
if(!aresetn)
|
||||||
|
begin
|
||||||
|
virtual_uart_data <= 8'd0;
|
||||||
|
end
|
||||||
|
else if(write_uart_valid)
|
||||||
|
begin
|
||||||
|
virtual_uart_data <= write_uart_data;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
//----------------------------{virtual uart}end--------------------------//
|
||||||
|
|
||||||
|
//--------------------------{axirandom mask}begin------------------------//
|
||||||
|
wire [15:0] switch_led;
|
||||||
|
wire [15:0] led_r_n;
|
||||||
|
assign led_r_n = ~switch_led;
|
||||||
|
|
||||||
|
reg [22:0] pseudo_random_23;
|
||||||
|
reg no_mask; //if led_r_n is all 1, no mask
|
||||||
|
reg short_delay; //memory long delay
|
||||||
|
always @ (posedge aclk)
|
||||||
|
begin
|
||||||
|
if (!aresetn)
|
||||||
|
pseudo_random_23 <= simu_flag[0] ? `RANDOM_SEED : {7'b1010101,led_r_n};
|
||||||
|
else
|
||||||
|
pseudo_random_23 <= {pseudo_random_23[21:0],pseudo_random_23[22] ^ pseudo_random_23[17]};
|
||||||
|
|
||||||
|
if(!aresetn)
|
||||||
|
no_mask <= pseudo_random_23[15:0]==16'h00FF;
|
||||||
|
|
||||||
|
if(!aresetn)
|
||||||
|
short_delay <= pseudo_random_23[7:0]==8'hFF;
|
||||||
|
end
|
||||||
|
assign ram_random_mask[0] = (pseudo_random_23[10]&pseudo_random_23[20]) & (short_delay|(pseudo_random_23[11]^pseudo_random_23[5]))
|
||||||
|
| no_mask;
|
||||||
|
assign ram_random_mask[1] = (pseudo_random_23[ 9]&pseudo_random_23[17]) & (short_delay|(pseudo_random_23[12]^pseudo_random_23[4]))
|
||||||
|
| no_mask;
|
||||||
|
assign ram_random_mask[2] = (pseudo_random_23[ 8]^pseudo_random_23[22]) & (short_delay|(pseudo_random_23[13]^pseudo_random_23[3]))
|
||||||
|
| no_mask;
|
||||||
|
assign ram_random_mask[3] = (pseudo_random_23[ 7]&pseudo_random_23[19]) & (short_delay|(pseudo_random_23[14]^pseudo_random_23[2]))
|
||||||
|
| no_mask;
|
||||||
|
assign ram_random_mask[4] = (pseudo_random_23[ 6]^pseudo_random_23[16]) & (short_delay|(pseudo_random_23[15]^pseudo_random_23[1]))
|
||||||
|
| no_mask;
|
||||||
|
|
||||||
|
//---------------------------{axirandom mask}end-------------------------//
|
||||||
|
|
||||||
|
//--------------------------------{led}begin-----------------------------//
|
||||||
|
//led display
|
||||||
|
//led_data[31:0]
|
||||||
|
wire write_led = conf_we & (conf_addr[15:0]==`LED_ADDR);
|
||||||
|
|
||||||
|
assign led = led_data[15:0];
|
||||||
|
|
||||||
|
assign switch_led = {{2{switch[7]}},{2{switch[6]}},{2{switch[5]}},{2{switch[4]}},
|
||||||
|
{2{switch[3]}},{2{switch[2]}},{2{switch[1]}},{2{switch[0]}}};
|
||||||
|
always @(posedge aclk)
|
||||||
|
begin
|
||||||
|
if(!aresetn)
|
||||||
|
begin
|
||||||
|
led_data <= {16'h0,switch_led};
|
||||||
|
end
|
||||||
|
else if(write_led)
|
||||||
|
begin
|
||||||
|
led_data <= conf_wdata[31:0];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
//---------------------------------{led}end------------------------------//
|
||||||
|
|
||||||
|
//-------------------------------{switch}begin---------------------------//
|
||||||
|
//switch data
|
||||||
|
//switch_data[7:0]
|
||||||
|
assign switch_data = {24'd0,switch};
|
||||||
|
assign sw_inter_data = {16'd0,
|
||||||
|
switch[7],1'b0,switch[6],1'b0,
|
||||||
|
switch[5],1'b0,switch[4],1'b0,
|
||||||
|
switch[3],1'b0,switch[2],1'b0,
|
||||||
|
switch[1],1'b0,switch[0],1'b0};
|
||||||
|
//--------------------------------{switch}end----------------------------//
|
||||||
|
|
||||||
|
//------------------------------{btn key}begin---------------------------//
|
||||||
|
//btn key data
|
||||||
|
reg [15:0] btn_key_r;
|
||||||
|
assign btn_key_data = {16'd0,btn_key_r};
|
||||||
|
|
||||||
|
//state machine
|
||||||
|
reg [2:0] state;
|
||||||
|
wire [2:0] next_state;
|
||||||
|
|
||||||
|
//eliminate jitter
|
||||||
|
reg key_flag;
|
||||||
|
reg [19:0] key_count;
|
||||||
|
reg [ 3:0] state_count;
|
||||||
|
wire key_start = (state==3'b000) && !(&btn_key_row);
|
||||||
|
wire key_end = (state==3'b111) && (&btn_key_row);
|
||||||
|
wire key_sample= key_count[19];
|
||||||
|
always @(posedge aclk)
|
||||||
|
begin
|
||||||
|
if(!aresetn)
|
||||||
|
begin
|
||||||
|
key_flag <= 1'd0;
|
||||||
|
end
|
||||||
|
else if (key_sample && state_count[3])
|
||||||
|
begin
|
||||||
|
key_flag <= 1'b0;
|
||||||
|
end
|
||||||
|
else if( key_start || key_end )
|
||||||
|
begin
|
||||||
|
key_flag <= 1'b1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if(!aresetn || !key_flag)
|
||||||
|
begin
|
||||||
|
key_count <= 20'd0;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
key_count <= key_count + 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(posedge aclk)
|
||||||
|
begin
|
||||||
|
if(!aresetn || state_count[3])
|
||||||
|
begin
|
||||||
|
state_count <= 4'd0;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
state_count <= state_count + 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(posedge aclk)
|
||||||
|
begin
|
||||||
|
if(!aresetn)
|
||||||
|
begin
|
||||||
|
state <= 3'b000;
|
||||||
|
end
|
||||||
|
else if (state_count[3])
|
||||||
|
begin
|
||||||
|
state <= next_state;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign next_state = (state == 3'b000) ? ( (key_sample && !(&btn_key_row)) ? 3'b001 : 3'b000 ) :
|
||||||
|
(state == 3'b001) ? ( !(&btn_key_row) ? 3'b111 : 3'b010 ) :
|
||||||
|
(state == 3'b010) ? ( !(&btn_key_row) ? 3'b111 : 3'b011 ) :
|
||||||
|
(state == 3'b011) ? ( !(&btn_key_row) ? 3'b111 : 3'b100 ) :
|
||||||
|
(state == 3'b100) ? ( !(&btn_key_row) ? 3'b111 : 3'b000 ) :
|
||||||
|
(state == 3'b111) ? ( (key_sample && (&btn_key_row)) ? 3'b000 : 3'b111 ) :
|
||||||
|
3'b000;
|
||||||
|
assign btn_key_col = (state == 3'b000) ? 4'b0000:
|
||||||
|
(state == 3'b001) ? 4'b1110:
|
||||||
|
(state == 3'b010) ? 4'b1101:
|
||||||
|
(state == 3'b011) ? 4'b1011:
|
||||||
|
(state == 3'b100) ? 4'b0111:
|
||||||
|
4'b0000;
|
||||||
|
wire [15:0] btn_key_tmp;
|
||||||
|
always @(posedge aclk) begin
|
||||||
|
if(!aresetn) begin
|
||||||
|
btn_key_r <= 16'd0;
|
||||||
|
end
|
||||||
|
else if(next_state==3'b000)
|
||||||
|
begin
|
||||||
|
btn_key_r <=16'd0;
|
||||||
|
end
|
||||||
|
else if(next_state == 3'b111 && state != 3'b111) begin
|
||||||
|
btn_key_r <= btn_key_tmp;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
assign btn_key_tmp = (state == 3'b001)&(btn_key_row == 4'b1110) ? 16'h0001:
|
||||||
|
(state == 3'b001)&(btn_key_row == 4'b1101) ? 16'h0010:
|
||||||
|
(state == 3'b001)&(btn_key_row == 4'b1011) ? 16'h0100:
|
||||||
|
(state == 3'b001)&(btn_key_row == 4'b0111) ? 16'h1000:
|
||||||
|
(state == 3'b010)&(btn_key_row == 4'b1110) ? 16'h0002:
|
||||||
|
(state == 3'b010)&(btn_key_row == 4'b1101) ? 16'h0020:
|
||||||
|
(state == 3'b010)&(btn_key_row == 4'b1011) ? 16'h0200:
|
||||||
|
(state == 3'b010)&(btn_key_row == 4'b0111) ? 16'h2000:
|
||||||
|
(state == 3'b011)&(btn_key_row == 4'b1110) ? 16'h0004:
|
||||||
|
(state == 3'b011)&(btn_key_row == 4'b1101) ? 16'h0040:
|
||||||
|
(state == 3'b011)&(btn_key_row == 4'b1011) ? 16'h0400:
|
||||||
|
(state == 3'b011)&(btn_key_row == 4'b0111) ? 16'h4000:
|
||||||
|
(state == 3'b100)&(btn_key_row == 4'b1110) ? 16'h0008:
|
||||||
|
(state == 3'b100)&(btn_key_row == 4'b1101) ? 16'h0080:
|
||||||
|
(state == 3'b100)&(btn_key_row == 4'b1011) ? 16'h0800:
|
||||||
|
(state == 3'b100)&(btn_key_row == 4'b0111) ? 16'h8000:16'h0000;
|
||||||
|
//-------------------------------{btn key}end----------------------------//
|
||||||
|
|
||||||
|
//-----------------------------{btn step}begin---------------------------//
|
||||||
|
//btn step data
|
||||||
|
reg btn_step0_r; //0:press
|
||||||
|
reg btn_step1_r; //0:press
|
||||||
|
assign btn_step_data = {30'd0,~btn_step0_r,~btn_step1_r}; //1:press
|
||||||
|
|
||||||
|
//-----step0
|
||||||
|
//eliminate jitter
|
||||||
|
reg step0_flag;
|
||||||
|
reg [19:0] step0_count;
|
||||||
|
wire step0_start = btn_step0_r && !btn_step[0];
|
||||||
|
wire step0_end = !btn_step0_r && btn_step[0];
|
||||||
|
wire step0_sample= step0_count[19];
|
||||||
|
always @(posedge aclk)
|
||||||
|
begin
|
||||||
|
if(!aresetn)
|
||||||
|
begin
|
||||||
|
step0_flag <= 1'd0;
|
||||||
|
end
|
||||||
|
else if (step0_sample)
|
||||||
|
begin
|
||||||
|
step0_flag <= 1'b0;
|
||||||
|
end
|
||||||
|
else if( step0_start || step0_end )
|
||||||
|
begin
|
||||||
|
step0_flag <= 1'b1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if(!aresetn || !step0_flag)
|
||||||
|
begin
|
||||||
|
step0_count <= 20'd0;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
step0_count <= step0_count + 1'b1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if(!aresetn)
|
||||||
|
begin
|
||||||
|
btn_step0_r <= 1'b1;
|
||||||
|
end
|
||||||
|
else if(step0_sample)
|
||||||
|
begin
|
||||||
|
btn_step0_r <= btn_step[0];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
//-----step1
|
||||||
|
//eliminate jitter
|
||||||
|
reg step1_flag;
|
||||||
|
reg [19:0] step1_count;
|
||||||
|
wire step1_start = btn_step1_r && !btn_step[1];
|
||||||
|
wire step1_end = !btn_step1_r && btn_step[1];
|
||||||
|
wire step1_sample= step1_count[19];
|
||||||
|
always @(posedge aclk)
|
||||||
|
begin
|
||||||
|
if(!aresetn)
|
||||||
|
begin
|
||||||
|
step1_flag <= 1'd0;
|
||||||
|
end
|
||||||
|
else if (step1_sample)
|
||||||
|
begin
|
||||||
|
step1_flag <= 1'b0;
|
||||||
|
end
|
||||||
|
else if( step1_start || step1_end )
|
||||||
|
begin
|
||||||
|
step1_flag <= 1'b1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if(!aresetn || !step1_flag)
|
||||||
|
begin
|
||||||
|
step1_count <= 20'd0;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
step1_count <= step1_count + 1'b1;
|
||||||
|
end
|
||||||
|
|
||||||
|
if(!aresetn)
|
||||||
|
begin
|
||||||
|
btn_step1_r <= 1'b1;
|
||||||
|
end
|
||||||
|
else if(step1_sample)
|
||||||
|
begin
|
||||||
|
btn_step1_r <= btn_step[1];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
//------------------------------{btn step}end----------------------------//
|
||||||
|
|
||||||
|
//-------------------------------{led rg}begin---------------------------//
|
||||||
|
//led_rg0_data[31:0] led_rg0_data[31:0]
|
||||||
|
//bfd0_f010 bfd0_f014
|
||||||
|
wire write_led_rg0 = conf_we & (conf_addr[15:0]==`LED_RG0_ADDR);
|
||||||
|
wire write_led_rg1 = conf_we & (conf_addr[15:0]==`LED_RG1_ADDR);
|
||||||
|
assign led_rg0 = led_rg0_data[1:0];
|
||||||
|
assign led_rg1 = led_rg1_data[1:0];
|
||||||
|
always @(posedge aclk)
|
||||||
|
begin
|
||||||
|
if(!aresetn)
|
||||||
|
begin
|
||||||
|
led_rg0_data <= 32'h0;
|
||||||
|
end
|
||||||
|
else if(write_led_rg0)
|
||||||
|
begin
|
||||||
|
led_rg0_data <= conf_wdata[31:0];
|
||||||
|
end
|
||||||
|
|
||||||
|
if(!aresetn)
|
||||||
|
begin
|
||||||
|
led_rg1_data <= 32'h0;
|
||||||
|
end
|
||||||
|
else if(write_led_rg1)
|
||||||
|
begin
|
||||||
|
led_rg1_data <= conf_wdata[31:0];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
//--------------------------------{led rg}end----------------------------//
|
||||||
|
|
||||||
|
//---------------------------{digital number}begin-----------------------//
|
||||||
|
//digital number display
|
||||||
|
//num_data[31:0]
|
||||||
|
wire write_num = conf_we & (conf_addr[15:0]==`NUM_ADDR);
|
||||||
|
always @(posedge aclk)
|
||||||
|
begin
|
||||||
|
if(!aresetn)
|
||||||
|
begin
|
||||||
|
num_data <= 32'h0;
|
||||||
|
end
|
||||||
|
else if(write_num)
|
||||||
|
begin
|
||||||
|
num_data <= conf_wdata[31:0];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
reg [19:0] count;
|
||||||
|
always @(posedge aclk)
|
||||||
|
begin
|
||||||
|
if(!aresetn)
|
||||||
|
begin
|
||||||
|
count <= 20'd0;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
count <= count + 1'b1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
//scan data
|
||||||
|
reg [3:0] scan_data;
|
||||||
|
always @ ( posedge aclk )
|
||||||
|
begin
|
||||||
|
if ( !aresetn )
|
||||||
|
begin
|
||||||
|
scan_data <= 32'd0;
|
||||||
|
num_csn <= 8'b1111_1111;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
case(count[19:17])
|
||||||
|
3'b000 : scan_data <= num_data[31:28];
|
||||||
|
3'b001 : scan_data <= num_data[27:24];
|
||||||
|
3'b010 : scan_data <= num_data[23:20];
|
||||||
|
3'b011 : scan_data <= num_data[19:16];
|
||||||
|
3'b100 : scan_data <= num_data[15:12];
|
||||||
|
3'b101 : scan_data <= num_data[11: 8];
|
||||||
|
3'b110 : scan_data <= num_data[7 : 4];
|
||||||
|
3'b111 : scan_data <= num_data[3 : 0];
|
||||||
|
endcase
|
||||||
|
|
||||||
|
case(count[19:17])
|
||||||
|
3'b000 : num_csn <= 8'b0111_1111;
|
||||||
|
3'b001 : num_csn <= 8'b1011_1111;
|
||||||
|
3'b010 : num_csn <= 8'b1101_1111;
|
||||||
|
3'b011 : num_csn <= 8'b1110_1111;
|
||||||
|
3'b100 : num_csn <= 8'b1111_0111;
|
||||||
|
3'b101 : num_csn <= 8'b1111_1011;
|
||||||
|
3'b110 : num_csn <= 8'b1111_1101;
|
||||||
|
3'b111 : num_csn <= 8'b1111_1110;
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
always @(posedge aclk)
|
||||||
|
begin
|
||||||
|
if ( !aresetn )
|
||||||
|
begin
|
||||||
|
num_a_g <= 7'b0000000;
|
||||||
|
end
|
||||||
|
else
|
||||||
|
begin
|
||||||
|
case ( scan_data )
|
||||||
|
4'd0 : num_a_g <= 7'b1111110; //0
|
||||||
|
4'd1 : num_a_g <= 7'b0110000; //1
|
||||||
|
4'd2 : num_a_g <= 7'b1101101; //2
|
||||||
|
4'd3 : num_a_g <= 7'b1111001; //3
|
||||||
|
4'd4 : num_a_g <= 7'b0110011; //4
|
||||||
|
4'd5 : num_a_g <= 7'b1011011; //5
|
||||||
|
4'd6 : num_a_g <= 7'b1011111; //6
|
||||||
|
4'd7 : num_a_g <= 7'b1110000; //7
|
||||||
|
4'd8 : num_a_g <= 7'b1111111; //8
|
||||||
|
4'd9 : num_a_g <= 7'b1111011; //9
|
||||||
|
4'd10: num_a_g <= 7'b1110111; //a
|
||||||
|
4'd11: num_a_g <= 7'b0011111; //b
|
||||||
|
4'd12: num_a_g <= 7'b1001110; //c
|
||||||
|
4'd13: num_a_g <= 7'b0111101; //d
|
||||||
|
4'd14: num_a_g <= 7'b1001111; //e
|
||||||
|
4'd15: num_a_g <= 7'b1000111; //f
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
end
|
||||||
|
//----------------------------{digital number}end------------------------//
|
||||||
|
endmodule
|
689
resources/func_test/soc_axi_lite_top.v
Executable file
689
resources/func_test/soc_axi_lite_top.v
Executable file
@ -0,0 +1,689 @@
|
|||||||
|
/*------------------------------------------------------------------------------
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
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.
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
------------------------------------------------------------------------------*/
|
||||||
|
`timescale 1ns / 1ps
|
||||||
|
//*************************************************************************
|
||||||
|
// > File Name : soc_top.v
|
||||||
|
// > Description : SoC, included cpu, 2 x 3 bridge,
|
||||||
|
// inst ram, confreg, data ram
|
||||||
|
//
|
||||||
|
// -------------------------
|
||||||
|
// | cpu |
|
||||||
|
// -------------------------
|
||||||
|
// | axi
|
||||||
|
// |
|
||||||
|
// ---------------------
|
||||||
|
// | 1 x 2 bridge |
|
||||||
|
// ---------------------
|
||||||
|
// | |
|
||||||
|
// | |
|
||||||
|
// ----------- -----------
|
||||||
|
// | axi ram | | confreg |
|
||||||
|
// ----------- -----------
|
||||||
|
//
|
||||||
|
// > Author : LOONGSON
|
||||||
|
// > Date : 2017-08-04
|
||||||
|
//*************************************************************************
|
||||||
|
|
||||||
|
//for simulation:
|
||||||
|
//1. if define SIMU_USE_PLL = 1, will use clk_pll to generate cpu_clk/sys_clk,
|
||||||
|
// and simulation will be very slow.
|
||||||
|
//2. usually, please define SIMU_USE_PLL=0 to speed up simulation by assign
|
||||||
|
// cpu_clk=clk, sys_clk = clk.
|
||||||
|
// at this time, frequency of cpu_clk is 91MHz.
|
||||||
|
`define SIMU_USE_PLL 0 //set 0 to speed up simulation
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
//clk and resetn
|
||||||
|
wire cpu_clk;
|
||||||
|
wire sys_clk;
|
||||||
|
reg cpu_resetn_t, cpu_resetn;
|
||||||
|
reg sys_resetn_t, sys_resetn;
|
||||||
|
always @(posedge cpu_clk)
|
||||||
|
begin
|
||||||
|
cpu_resetn_t <= resetn;
|
||||||
|
cpu_resetn <= cpu_resetn_t;
|
||||||
|
end
|
||||||
|
always @(posedge sys_clk)
|
||||||
|
begin
|
||||||
|
sys_resetn_t <= resetn;
|
||||||
|
sys_resetn <= sys_resetn_t;
|
||||||
|
end
|
||||||
|
//simulation clk.
|
||||||
|
assign cpu_clk = clk;
|
||||||
|
assign sys_clk = clk;
|
||||||
|
|
||||||
|
//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_aclk ;
|
||||||
|
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 ;
|
||||||
|
//cpu axi sync
|
||||||
|
wire [3 :0] cpu_sync_arid ;
|
||||||
|
wire [31:0] cpu_sync_araddr ;
|
||||||
|
wire [3 :0] cpu_sync_arlen ;
|
||||||
|
wire [2 :0] cpu_sync_arsize ;
|
||||||
|
wire [1 :0] cpu_sync_arburst;
|
||||||
|
wire [1 :0] cpu_sync_arlock ;
|
||||||
|
wire [3 :0] cpu_sync_arcache;
|
||||||
|
wire [2 :0] cpu_sync_arprot ;
|
||||||
|
wire cpu_sync_arvalid;
|
||||||
|
wire cpu_sync_arready;
|
||||||
|
wire [3 :0] cpu_sync_rid ;
|
||||||
|
wire [31:0] cpu_sync_rdata ;
|
||||||
|
wire [1 :0] cpu_sync_rresp ;
|
||||||
|
wire cpu_sync_rlast ;
|
||||||
|
wire cpu_sync_rvalid ;
|
||||||
|
wire cpu_sync_rready ;
|
||||||
|
wire [3 :0] cpu_sync_awid ;
|
||||||
|
wire [31:0] cpu_sync_awaddr ;
|
||||||
|
wire [3 :0] cpu_sync_awlen ;
|
||||||
|
wire [2 :0] cpu_sync_awsize ;
|
||||||
|
wire [1 :0] cpu_sync_awburst;
|
||||||
|
wire [1 :0] cpu_sync_awlock ;
|
||||||
|
wire [3 :0] cpu_sync_awcache;
|
||||||
|
wire [2 :0] cpu_sync_awprot ;
|
||||||
|
wire cpu_sync_awvalid;
|
||||||
|
wire cpu_sync_awready;
|
||||||
|
wire [3 :0] cpu_sync_wid ;
|
||||||
|
wire [31:0] cpu_sync_wdata ;
|
||||||
|
wire [3 :0] cpu_sync_wstrb ;
|
||||||
|
wire cpu_sync_wlast ;
|
||||||
|
wire cpu_sync_wvalid ;
|
||||||
|
wire cpu_sync_wready ;
|
||||||
|
wire [3 :0] cpu_sync_bid ;
|
||||||
|
wire [1 :0] cpu_sync_bresp ;
|
||||||
|
wire cpu_sync_bvalid ;
|
||||||
|
wire cpu_sync_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
|
||||||
|
//debug_*
|
||||||
|
mycpu_top u_cpu(
|
||||||
|
.ext_int (6'd0 ), //high active
|
||||||
|
|
||||||
|
.aclk (cpu_clk ),
|
||||||
|
.aresetn (cpu_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 ( cpu_clk ),
|
||||||
|
.m_aresetn ( cpu_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 )
|
||||||
|
);
|
||||||
|
|
||||||
|
//clock sync: from CPU to AXI_Crossbar (nothing)
|
||||||
|
|
||||||
|
assign cpu_sync_awid = cpu_wrap_awid ;
|
||||||
|
assign cpu_sync_awaddr = cpu_wrap_awaddr ;
|
||||||
|
assign cpu_sync_awlen = cpu_wrap_awlen ;
|
||||||
|
assign cpu_sync_awsize = cpu_wrap_awsize ;
|
||||||
|
assign cpu_sync_awburst = cpu_wrap_awburst;
|
||||||
|
assign cpu_sync_awlock = cpu_wrap_awlock ;
|
||||||
|
assign cpu_sync_awcache = cpu_wrap_awcache;
|
||||||
|
assign cpu_sync_awprot = cpu_wrap_awprot ;
|
||||||
|
assign cpu_sync_awvalid = cpu_wrap_awvalid;
|
||||||
|
assign cpu_wrap_awready = cpu_sync_awready;
|
||||||
|
|
||||||
|
assign cpu_sync_wid = cpu_wrap_wid ;
|
||||||
|
assign cpu_sync_wdata = cpu_wrap_wdata ;
|
||||||
|
assign cpu_sync_wstrb = cpu_wrap_wstrb ;
|
||||||
|
assign cpu_sync_wlast = cpu_wrap_wlast ;
|
||||||
|
assign cpu_sync_wvalid = cpu_wrap_wvalid;
|
||||||
|
assign cpu_wrap_wready = cpu_sync_wready;
|
||||||
|
|
||||||
|
assign cpu_wrap_bid = cpu_sync_bid ;
|
||||||
|
assign cpu_wrap_bresp = cpu_sync_bresp ;
|
||||||
|
assign cpu_wrap_bvalid = cpu_sync_bvalid;
|
||||||
|
assign cpu_sync_bready = cpu_wrap_bready;
|
||||||
|
|
||||||
|
assign cpu_sync_arid = cpu_wrap_arid ;
|
||||||
|
assign cpu_sync_araddr = cpu_wrap_araddr ;
|
||||||
|
assign cpu_sync_arlen = cpu_wrap_arlen ;
|
||||||
|
assign cpu_sync_arsize = cpu_wrap_arsize ;
|
||||||
|
assign cpu_sync_arburst = cpu_wrap_arburst;
|
||||||
|
assign cpu_sync_arlock = cpu_wrap_arlock ;
|
||||||
|
assign cpu_sync_arcache = cpu_wrap_arcache;
|
||||||
|
assign cpu_sync_arprot = cpu_wrap_arprot ;
|
||||||
|
assign cpu_sync_arvalid = cpu_wrap_arvalid;
|
||||||
|
assign cpu_wrap_arready = cpu_sync_arready;
|
||||||
|
|
||||||
|
assign cpu_wrap_rid = cpu_sync_rid ;
|
||||||
|
assign cpu_wrap_rdata = cpu_sync_rdata ;
|
||||||
|
assign cpu_wrap_rresp = cpu_sync_rresp ;
|
||||||
|
assign cpu_wrap_rlast = cpu_sync_rlast ;
|
||||||
|
assign cpu_wrap_rvalid = cpu_sync_rvalid;
|
||||||
|
assign cpu_sync_rready = cpu_wrap_rready;
|
||||||
|
|
||||||
|
axi_crossbar u_axi_crossbar_1x2(
|
||||||
|
.clk ( sys_clk ), // i, 1
|
||||||
|
.rst ( ~sys_resetn ), // i, 1
|
||||||
|
|
||||||
|
.s_axi_arid ( cpu_sync_arid ),
|
||||||
|
.s_axi_araddr ( cpu_sync_araddr ),
|
||||||
|
.s_axi_arlen ( cpu_sync_arlen[3:0] ),
|
||||||
|
.s_axi_arsize ( cpu_sync_arsize ),
|
||||||
|
.s_axi_arburst ( cpu_sync_arburst ),
|
||||||
|
.s_axi_arlock ( cpu_sync_arlock ),
|
||||||
|
.s_axi_arcache ( cpu_sync_arcache ),
|
||||||
|
.s_axi_arprot ( cpu_sync_arprot ),
|
||||||
|
.s_axi_arqos ( 4'd0 ),
|
||||||
|
.s_axi_arvalid ( cpu_sync_arvalid ),
|
||||||
|
.s_axi_arready ( cpu_sync_arready ),
|
||||||
|
.s_axi_rid ( cpu_sync_rid ),
|
||||||
|
.s_axi_rdata ( cpu_sync_rdata ),
|
||||||
|
.s_axi_rresp ( cpu_sync_rresp ),
|
||||||
|
.s_axi_rlast ( cpu_sync_rlast ),
|
||||||
|
.s_axi_rvalid ( cpu_sync_rvalid ),
|
||||||
|
.s_axi_rready ( cpu_sync_rready ),
|
||||||
|
.s_axi_awid ( cpu_sync_awid ),
|
||||||
|
.s_axi_awaddr ( cpu_sync_awaddr ),
|
||||||
|
.s_axi_awlen ( cpu_sync_awlen[3:0] ),
|
||||||
|
.s_axi_awsize ( cpu_sync_awsize ),
|
||||||
|
.s_axi_awburst ( cpu_sync_awburst ),
|
||||||
|
.s_axi_awlock ( cpu_sync_awlock ),
|
||||||
|
.s_axi_awcache ( cpu_sync_awcache ),
|
||||||
|
.s_axi_awprot ( cpu_sync_awprot ),
|
||||||
|
.s_axi_awqos ( 4'd0 ),
|
||||||
|
.s_axi_awvalid ( cpu_sync_awvalid ),
|
||||||
|
.s_axi_awready ( cpu_sync_awready ),
|
||||||
|
//.s_axi_wid ( cpu_sync_wid ),
|
||||||
|
.s_axi_wdata ( cpu_sync_wdata ),
|
||||||
|
.s_axi_wstrb ( cpu_sync_wstrb ),
|
||||||
|
.s_axi_wlast ( cpu_sync_wlast ),
|
||||||
|
.s_axi_wvalid ( cpu_sync_wvalid ),
|
||||||
|
.s_axi_wready ( cpu_sync_wready ),
|
||||||
|
.s_axi_bid ( cpu_sync_bid ),
|
||||||
|
.s_axi_bresp ( cpu_sync_bresp ),
|
||||||
|
.s_axi_bvalid ( cpu_sync_bvalid ),
|
||||||
|
.s_axi_bready ( cpu_sync_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 ( sys_clk ),
|
||||||
|
.aresetn ( sys_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 ( sys_clk ), // i, 1
|
||||||
|
.aclk ( sys_clk ), // i, 1
|
||||||
|
.aresetn ( sys_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
|
||||||
|
|
172
resources/tb.sv
Normal file
172
resources/tb.sv
Normal file
@ -0,0 +1,172 @@
|
|||||||
|
`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 (
|
||||||
|
input clk,
|
||||||
|
input resetn,
|
||||||
|
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
|
||||||
|
);
|
||||||
|
//gpio
|
||||||
|
logic [ 7:0] switch;
|
||||||
|
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 = 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 cpu_clk;
|
||||||
|
logic sys_clk;
|
||||||
|
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 cpu_clk = soc_lite.cpu_clk;
|
||||||
|
assign sys_clk = soc_lite.sys_clk;
|
||||||
|
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 cpu_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) 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) 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 sys_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 sys_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;
|
||||||
|
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;
|
||||||
|
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 cpu_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),
|
||||||
|
.btn_key_col(btn_key_col),
|
||||||
|
.btn_key_row(btn_key_row),
|
||||||
|
.btn_step (btn_step)
|
||||||
|
);
|
||||||
|
|
||||||
|
endmodule
|
308
resources/tb2.sv
308
resources/tb2.sv
@ -1,308 +0,0 @@
|
|||||||
`timescale 1ns / 1ps
|
|
||||||
|
|
||||||
`define SIMULATION_PC
|
|
||||||
`define TRACE_REF_FILE "../../../../../../../cpu132_gettrace/golden_trace.txt"
|
|
||||||
`define CONFREG_NUM_REG soc_lite.u_confreg.num_data
|
|
||||||
//`define CONFREG_OPEN_TRACE soc_lite.u_confreg.open_trace
|
|
||||||
`define CONFREG_OPEN_TRACE 1'b0
|
|
||||||
`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 tb2_top ();
|
|
||||||
logic resetn;
|
|
||||||
logic clk;
|
|
||||||
|
|
||||||
//goio
|
|
||||||
logic [15:0] led;
|
|
||||||
logic [1:0] led_rg0;
|
|
||||||
logic [1:0] led_rg1;
|
|
||||||
logic [7:0] num_csn;
|
|
||||||
logic [6:0] num_a_g;
|
|
||||||
logic [7:0] switch;
|
|
||||||
logic [3:0] btn_key_col;
|
|
||||||
logic [3:0] btn_key_row;
|
|
||||||
logic [1:0] btn_step;
|
|
||||||
assign switch = 8'hff;
|
|
||||||
assign btn_key_row = 4'd0;
|
|
||||||
assign btn_step = 2'd3;
|
|
||||||
|
|
||||||
initial begin
|
|
||||||
// $dumpfile("dump.vcd");
|
|
||||||
// $dumpvars();
|
|
||||||
|
|
||||||
resetn = 1'b0;
|
|
||||||
#2000;
|
|
||||||
resetn = 1'b1;
|
|
||||||
end
|
|
||||||
|
|
||||||
initial begin
|
|
||||||
clk = 1'b0;
|
|
||||||
forever begin
|
|
||||||
#5 clk = ~clk;
|
|
||||||
end
|
|
||||||
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),
|
|
||||||
.btn_key_col(btn_key_col),
|
|
||||||
.btn_key_row(btn_key_row),
|
|
||||||
.btn_step (btn_step)
|
|
||||||
);
|
|
||||||
|
|
||||||
//"cpu_clk" means cpu core clk
|
|
||||||
//"sys_clk" means system clk
|
|
||||||
//"wb" means write-back stage in pipeline
|
|
||||||
//"rf" means regfiles in cpu
|
|
||||||
//"w" in "wen/wnum/wdata" means writing
|
|
||||||
logic cpu_clk;
|
|
||||||
logic sys_clk;
|
|
||||||
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;
|
|
||||||
|
|
||||||
assign cpu_clk = soc_lite.cpu_clk;
|
|
||||||
assign sys_clk = soc_lite.sys_clk;
|
|
||||||
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;
|
|
||||||
|
|
||||||
// open the trace file;
|
|
||||||
integer trace_ref;
|
|
||||||
initial begin
|
|
||||||
trace_ref = $fopen(`TRACE_REF_FILE, "r");
|
|
||||||
end
|
|
||||||
|
|
||||||
//get reference result in falling edge
|
|
||||||
logic debug_end;
|
|
||||||
|
|
||||||
logic trace_cmp_flag;
|
|
||||||
logic [31:0] ref_wb_pc;
|
|
||||||
logic [4:0] ref_wb_rf_wnum;
|
|
||||||
logic [31:0] ref_wb_rf_wdata;
|
|
||||||
|
|
||||||
typedef struct packed {
|
|
||||||
logic trace_cmp_flag;
|
|
||||||
logic [31:0] ref_wb_pc;
|
|
||||||
logic [4:0] ref_wb_rf_wnum;
|
|
||||||
logic [31:0] ref_wb_rf_wdata;
|
|
||||||
logic [31:0] lineno;
|
|
||||||
} TRACE_INFO;
|
|
||||||
|
|
||||||
TRACE_INFO ref_trace[$];
|
|
||||||
logic [31:0] lineno;
|
|
||||||
|
|
||||||
initial begin
|
|
||||||
lineno = 0;
|
|
||||||
while (!$feof(
|
|
||||||
trace_ref
|
|
||||||
)) begin
|
|
||||||
lineno = lineno + 1;
|
|
||||||
$fscanf(trace_ref, "%h %h %h %h", trace_cmp_flag, ref_wb_pc, ref_wb_rf_wnum, ref_wb_rf_wdata);
|
|
||||||
if (trace_cmp_flag == 1) begin
|
|
||||||
ref_trace.push_back({trace_cmp_flag, ref_wb_pc, ref_wb_rf_wnum, ref_wb_rf_wdata, lineno});
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
//compare result in rsing edge
|
|
||||||
logic debug_wb_err;
|
|
||||||
|
|
||||||
logic 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 dbg_1_rf_wen;
|
|
||||||
logic [31:0] dbg_1_pc;
|
|
||||||
logic [ 4:0] dbg_1_rf_wnum;
|
|
||||||
logic [31:0] dbg_1_rf_wdata;
|
|
||||||
|
|
||||||
always @(posedge cpu_clk) begin
|
|
||||||
#2;
|
|
||||||
if (!resetn) begin
|
|
||||||
debug_wb_err <= 1'b0;
|
|
||||||
end else if (!debug_end) 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 && `CONFREG_OPEN_TRACE) begin
|
|
||||||
$display("mycpu0 : 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 && `CONFREG_OPEN_TRACE) begin
|
|
||||||
$display("mycpu1 : 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
|
|
||||||
|
|
||||||
if (|dbg_0_rf_wen && dbg_0_rf_wnum != 5'd0 && `CONFREG_OPEN_TRACE) begin
|
|
||||||
if ( (dbg_0_pc !== ref_trace[0].ref_wb_pc )
|
|
||||||
|| (dbg_0_rf_wnum !== ref_trace[0].ref_wb_rf_wnum )
|
|
||||||
|| (dbg_0_rf_wdata !== ref_trace[0].ref_wb_rf_wdata)
|
|
||||||
)
|
|
||||||
begin
|
|
||||||
$display("--------------------------------------------------------------");
|
|
||||||
$display("[%t] Error!!!", $time);
|
|
||||||
$display(" reference: PC = 0x%8h, wb_rf_wnum = 0x%2h, wb_rf_wdata = 0x%8h, lineno = %d",
|
|
||||||
ref_trace[0].ref_wb_pc, ref_trace[0].ref_wb_rf_wnum,
|
|
||||||
ref_trace[0].ref_wb_rf_wdata, ref_trace[0].lineno);
|
|
||||||
$display(" mycpu0 : PC = 0x%8h, wb_rf_wnum = 0x%2h, wb_rf_wdata = 0x%8h", dbg_0_pc,
|
|
||||||
dbg_0_rf_wnum, dbg_0_rf_wdata);
|
|
||||||
$display(" mycpu1 : PC = 0x%8h, wb_rf_wnum = 0x%2h, wb_rf_wdata = 0x%8h", dbg_1_pc,
|
|
||||||
dbg_1_rf_wnum, dbg_1_rf_wdata);
|
|
||||||
$display("--------------------------------------------------------------");
|
|
||||||
debug_wb_err <= 1'b1;
|
|
||||||
#40;
|
|
||||||
$finish;
|
|
||||||
end else ref_trace.pop_front();
|
|
||||||
end
|
|
||||||
if (|dbg_1_rf_wen && dbg_1_rf_wnum != 5'd0 && `CONFREG_OPEN_TRACE) begin
|
|
||||||
if ( (dbg_1_pc !== ref_trace[0].ref_wb_pc )
|
|
||||||
|| (dbg_1_rf_wnum !== ref_trace[0].ref_wb_rf_wnum )
|
|
||||||
|| (dbg_1_rf_wdata !== ref_trace[0].ref_wb_rf_wdata)
|
|
||||||
)
|
|
||||||
begin
|
|
||||||
$display("--------------------------------------------------------------");
|
|
||||||
$display("[%t] Error!!!", $time);
|
|
||||||
$display(" reference: PC = 0x%8h, wb_rf_wnum = 0x%2h, wb_rf_wdata = 0x%8h, lineno = %d",
|
|
||||||
ref_trace[0].ref_wb_pc, ref_trace[0].ref_wb_rf_wnum,
|
|
||||||
ref_trace[0].ref_wb_rf_wdata, ref_trace[0].lineno);
|
|
||||||
$display(" mycpu0 : PC = 0x%8h, wb_rf_wnum = 0x%2h, wb_rf_wdata = 0x%8h", dbg_0_pc,
|
|
||||||
dbg_0_rf_wnum, dbg_0_rf_wdata);
|
|
||||||
$display(" mycpu1 : PC = 0x%8h, wb_rf_wnum = 0x%2h, wb_rf_wdata = 0x%8h", dbg_1_pc,
|
|
||||||
dbg_1_rf_wnum, dbg_1_rf_wdata);
|
|
||||||
$display("--------------------------------------------------------------");
|
|
||||||
debug_wb_err <= 1'b1;
|
|
||||||
#40;
|
|
||||||
$finish;
|
|
||||||
end else ref_trace.pop_front();
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
//monitor numeric display
|
|
||||||
logic [ 7:0] err_count;
|
|
||||||
wire [31:0] confreg_num_reg = `CONFREG_NUM_REG;
|
|
||||||
logic [31:0] confreg_num_reg_r;
|
|
||||||
always_ff @(posedge sys_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("--------------------------------------------------------------");
|
|
||||||
$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
|
|
||||||
|
|
||||||
//monitor test
|
|
||||||
initial begin
|
|
||||||
$timeformat(-9, 0, " ns", 10);
|
|
||||||
while (!resetn) #5;
|
|
||||||
$display("==============================================================");
|
|
||||||
$display("Test begin!");
|
|
||||||
|
|
||||||
#10000;
|
|
||||||
while (`CONFREG_NUM_MONITOR) begin
|
|
||||||
#10000;
|
|
||||||
$display(" [%t] Test is running, dbg_0_pc = 0x%8h, dbg_1_pc = 0x%8h", $time, dbg_0_pc,
|
|
||||||
dbg_1_pc);
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
// Uart Display
|
|
||||||
logic uart_display;
|
|
||||||
logic [7:0] uart_data;
|
|
||||||
assign uart_display = `CONFREG_UART_DISPLAY;
|
|
||||||
assign uart_data = `CONFREG_UART_DATA;
|
|
||||||
|
|
||||||
always_ff @(posedge sys_clk) begin
|
|
||||||
if (uart_display) begin
|
|
||||||
if (uart_data == 8'hff) begin
|
|
||||||
; //$finish;
|
|
||||||
end else begin
|
|
||||||
$write("%c", uart_data);
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
//test end
|
|
||||||
wire global_err = debug_wb_err || (err_count != 8'd0);
|
|
||||||
wire test_end = (dbg_0_pc == `END_PC) || (dbg_1_pc == `END_PC) || (uart_display && uart_data == 8'hff);
|
|
||||||
always @(posedge cpu_clk) begin
|
|
||||||
if (!resetn) begin
|
|
||||||
debug_end <= 1'b0;
|
|
||||||
end else if (test_end && !debug_end) begin
|
|
||||||
debug_end <= 1'b1;
|
|
||||||
$display("==============================================================");
|
|
||||||
$display("Test end!");
|
|
||||||
#40;
|
|
||||||
$fclose(trace_ref);
|
|
||||||
if (global_err) begin
|
|
||||||
$display("Fail!!!Total %d errors!", err_count);
|
|
||||||
end else begin
|
|
||||||
$display("----PASS!!!");
|
|
||||||
end
|
|
||||||
$finish;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
endmodule
|
|
1
sim/.gitignore
vendored
Normal file
1
sim/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
obj_dir
|
76
sim/Makefile
Normal file
76
sim/Makefile
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
####################
|
||||||
|
# Program #
|
||||||
|
####################
|
||||||
|
VERILATOR = verilator
|
||||||
|
VERILATOR_COVERAGE = verilator_coverage
|
||||||
|
|
||||||
|
|
||||||
|
####################
|
||||||
|
# Flags #
|
||||||
|
####################
|
||||||
|
VERILATOR_BUILD_FLAGS =
|
||||||
|
# Generate C++ in executable form
|
||||||
|
VERILATOR_BUILD_FLAGS += -cc --exe
|
||||||
|
# Generate makefile dependencies (not shown as complicates the Makefile)
|
||||||
|
VERILATOR_BUILD_FLAGS += -MMD
|
||||||
|
# Optimize
|
||||||
|
VERILATOR_BUILD_FLAGS += -O3 -x-assign 0
|
||||||
|
# Warn abount lint issues; may not want this on less solid designs
|
||||||
|
VERILATOR_BUILD_FLAGS += -Wall
|
||||||
|
# Make waveforms
|
||||||
|
VERILATOR_BUILD_FLAGS += --trace
|
||||||
|
# Check SystemVerilog assertions
|
||||||
|
VERILATOR_BUILD_FLAGS += --assert
|
||||||
|
# Generate coverage analysis
|
||||||
|
VERILATOR_BUILD_FLAGS += --coverage
|
||||||
|
# Run make to compile model, with as many CPUs as are free
|
||||||
|
VERILATOR_BUILD_FLAGS += --build -j
|
||||||
|
|
||||||
|
# Simulation Defines
|
||||||
|
VERILATOR_FLAGS += -DSIMULATION_PC
|
||||||
|
|
||||||
|
# Create annotated source
|
||||||
|
VERILATOR_COV_FLAGS += --annotate logs/annotated
|
||||||
|
# A single coverage hit is considered good enough
|
||||||
|
VERILATOR_COV_FLAGS += --annotate-min 1
|
||||||
|
# Create LCOV info
|
||||||
|
VERILATOR_COV_FLAGS += --write-info logs/coverage.info
|
||||||
|
# Input file from Verilator
|
||||||
|
VERILATOR_COV_FLAGS += logs/coverage.dat
|
||||||
|
|
||||||
|
####################
|
||||||
|
# Sources #
|
||||||
|
####################
|
||||||
|
SOURCE = ./config.vlt $(wildcard ./model/*.v ./model/*.sv ../src/*.v ../src/*.sv ../src/**/*.v ../src/**/*.sv)
|
||||||
|
INCLUDE = $(addprefix -I, $(dir $(wildcard ../src/*/. ../src/**/*/.)))
|
||||||
|
VERILATOR_INPUT = -top testbench_top sim_main.cpp
|
||||||
|
|
||||||
|
FUNC_SOURCE = $(wildcard ../resources/tb.sv ../resources/func_test/*.v ../resources/func_test/**/*.v)
|
||||||
|
|
||||||
|
####################
|
||||||
|
# Targets #
|
||||||
|
####################
|
||||||
|
.phony: test func_test func_coverage run clean
|
||||||
|
|
||||||
|
default: run
|
||||||
|
|
||||||
|
test:
|
||||||
|
@echo $(SOURCE)
|
||||||
|
|
||||||
|
lint:
|
||||||
|
$(VERILATOR) --lint-only $(VERILATOR_FLAGS) $(INCLUDE) $(SOURCE) -top mycpu_top
|
||||||
|
|
||||||
|
func_test:
|
||||||
|
$(VERILATOR) $(VERILATOR_FLAGS) $(VERILATOR_BUILD_FLAGS) $(INCLUDE) $(SOURCE) $(FUNC_SOURCE) $(VERILATOR_INPUT)
|
||||||
|
|
||||||
|
func_coverage: func_test
|
||||||
|
@rm -rf logs/annotated
|
||||||
|
$(VERILATOR_COVERAGE) $(VERILATOR_COV_FLAGS)
|
||||||
|
|
||||||
|
run: func_test
|
||||||
|
@rm -rf logs
|
||||||
|
@mkdir -p logs
|
||||||
|
obj_dir/Vmycpu_top
|
||||||
|
|
||||||
|
clean:
|
||||||
|
-rm -rf obj_dir logs *.log *.dmp *.vpd core
|
9
sim/config.vlt
Normal file
9
sim/config.vlt
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
`verilator_config
|
||||||
|
lint_off -rule TIMESCALEMOD
|
||||||
|
lint_off -rule DECLFILENAME
|
||||||
|
|
||||||
|
lint_off -file "model/*.v"
|
||||||
|
lint_off -file "../resources/func_test/*.v"
|
||||||
|
|
||||||
|
lint_off -rule BLKSEQ -file "../src/CP0/CP0.sv"
|
||||||
|
lint_off -rule PINCONNECTEMPTY -file "../src/MU/MU.sv"
|
154
sim/model/arbiter.v
Normal file
154
sim/model/arbiter.v
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
/*
|
||||||
|
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
|
386
sim/model/axi_crossbar.v
Normal file
386
sim/model/axi_crossbar.v
Normal file
@ -0,0 +1,386 @@
|
|||||||
|
/*
|
||||||
|
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 = 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_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'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}},
|
||||||
|
// 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 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}},
|
||||||
|
// 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_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
|
413
sim/model/axi_crossbar_addr.v
Normal file
413
sim/model/axi_crossbar_addr.v
Normal file
@ -0,0 +1,413 @@
|
|||||||
|
/*
|
||||||
|
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
|
564
sim/model/axi_crossbar_rd.v
Normal file
564
sim/model/axi_crossbar_rd.v
Normal file
@ -0,0 +1,564 @@
|
|||||||
|
/*
|
||||||
|
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
|
673
sim/model/axi_crossbar_wr.v
Normal file
673
sim/model/axi_crossbar_wr.v
Normal file
@ -0,0 +1,673 @@
|
|||||||
|
/*
|
||||||
|
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
|
362
sim/model/axi_ram.v
Normal file
362
sim/model/axi_ram.v
Normal file
@ -0,0 +1,362 @@
|
|||||||
|
/*
|
||||||
|
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 = 16,
|
||||||
|
// 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];
|
||||||
|
|
||||||
|
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
|
530
sim/model/axi_register_rd.v
Normal file
530
sim/model/axi_register_rd.v
Normal file
@ -0,0 +1,530 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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
|
691
sim/model/axi_register_wr.v
Normal file
691
sim/model/axi_register_wr.v
Normal file
@ -0,0 +1,691 @@
|
|||||||
|
/*
|
||||||
|
|
||||||
|
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
|
24
sim/model/div_signed.sv
Normal file
24
sim/model/div_signed.sv
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
`include "defines.svh"
|
||||||
|
|
||||||
|
module div_signed(
|
||||||
|
input logic aclk,
|
||||||
|
input logic s_axis_dividend_tvalid,
|
||||||
|
input logic [31:0] s_axis_dividend_tdata,
|
||||||
|
input logic s_axis_divisor_tvalid,
|
||||||
|
input logic [31:0] s_axis_divisor_tdata,
|
||||||
|
output logic m_axis_dout_tvalid,
|
||||||
|
output logic [63:0] m_axis_dout_tdata
|
||||||
|
);
|
||||||
|
|
||||||
|
always_ff @(posedge aclk)
|
||||||
|
if (s_axis_dividend_tvalid & s_axis_divisor_tvalid) begin
|
||||||
|
m_axis_dout_tvalid <= 1'b1;
|
||||||
|
m_axis_dout_tdata[63:32] <= $signed(s_axis_dividend_tdata) / $signed(s_axis_divisor_tdata);
|
||||||
|
m_axis_dout_tdata[31: 0] <= $signed(s_axis_dividend_tdata) % $signed(s_axis_divisor_tdata);
|
||||||
|
end else begin
|
||||||
|
m_axis_dout_tvalid <= 0;
|
||||||
|
m_axis_dout_tdata <= 0;
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
endmodule
|
24
sim/model/div_unsigned.sv
Normal file
24
sim/model/div_unsigned.sv
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
`include "defines.svh"
|
||||||
|
|
||||||
|
module div_unsigned(
|
||||||
|
input logic aclk,
|
||||||
|
input logic s_axis_dividend_tvalid,
|
||||||
|
input logic [31:0] s_axis_dividend_tdata,
|
||||||
|
input logic s_axis_divisor_tvalid,
|
||||||
|
input logic [31:0] s_axis_divisor_tdata,
|
||||||
|
output logic m_axis_dout_tvalid,
|
||||||
|
output logic [63:0] m_axis_dout_tdata
|
||||||
|
);
|
||||||
|
|
||||||
|
always_ff @(posedge aclk)
|
||||||
|
if (s_axis_dividend_tvalid & s_axis_divisor_tvalid) begin
|
||||||
|
m_axis_dout_tvalid <= 1'b1;
|
||||||
|
m_axis_dout_tdata[63:32] <= $unsigned(s_axis_dividend_tdata) / $unsigned(s_axis_divisor_tdata);
|
||||||
|
m_axis_dout_tdata[31: 0] <= $unsigned(s_axis_dividend_tdata) % $unsigned(s_axis_divisor_tdata);
|
||||||
|
end else begin
|
||||||
|
m_axis_dout_tvalid <= 0;
|
||||||
|
m_axis_dout_tdata <= 0;
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
endmodule
|
14
sim/model/mul_signed.sv
Normal file
14
sim/model/mul_signed.sv
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
`include "defines.svh"
|
||||||
|
|
||||||
|
module mul_signed(
|
||||||
|
input logic CLK,
|
||||||
|
input logic [31:0] A,
|
||||||
|
input logic [31:0] B,
|
||||||
|
output logic [63:0] P
|
||||||
|
);
|
||||||
|
|
||||||
|
always_ff @(posedge CLK)
|
||||||
|
P <= $signed(A) * $signed(B);
|
||||||
|
|
||||||
|
|
||||||
|
endmodule
|
14
sim/model/mul_unsigned.sv
Normal file
14
sim/model/mul_unsigned.sv
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
`include "defines.svh"
|
||||||
|
|
||||||
|
module mul_unsigned(
|
||||||
|
input logic CLK,
|
||||||
|
input logic [31:0] A,
|
||||||
|
input logic [31:0] B,
|
||||||
|
output logic [63:0] P
|
||||||
|
);
|
||||||
|
|
||||||
|
always_ff @(posedge CLK)
|
||||||
|
P <= $unsigned(A) * $unsigned(B);
|
||||||
|
|
||||||
|
|
||||||
|
endmodule
|
87
sim/model/priority_encoder.v
Normal file
87
sim/model/priority_encoder.v
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
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
|
45
sim/sim_main.cpp
Normal file
45
sim/sim_main.cpp
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#include <verilated.h>
|
||||||
|
|
||||||
|
#include "Vtestbench_top.h"
|
||||||
|
|
||||||
|
vluint64_t main_time = 0;
|
||||||
|
double sc_time_stamp() {
|
||||||
|
return main_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv, char **env) {
|
||||||
|
Verilated::debug(0);
|
||||||
|
Verilated::randReset(2);
|
||||||
|
Verilated::traceEverOn(true);
|
||||||
|
Verilated::commandArgs(argc, argv);
|
||||||
|
Verilated::mkdir("logs");
|
||||||
|
|
||||||
|
const int reset_time = 10;
|
||||||
|
|
||||||
|
Vtestbench_top *top = new Vtestbench_top; // Or use a const unique_ptr, or the VL_UNIQUE_PTR wrapper
|
||||||
|
|
||||||
|
top->clk = 0;
|
||||||
|
while (!Verilated::gotFinish()) {
|
||||||
|
++main_time;
|
||||||
|
top->clk = !top->clk;
|
||||||
|
top->resetn = (main_time < reset_time) ? 1 : 0;
|
||||||
|
if (main_time < reset_time) {
|
||||||
|
// Zero coverage if still early in reset, otherwise toggles there may
|
||||||
|
// falsely indicate a signal is covered
|
||||||
|
VerilatedCov::zero();
|
||||||
|
}
|
||||||
|
top->eval();
|
||||||
|
}
|
||||||
|
|
||||||
|
top->final();
|
||||||
|
|
||||||
|
// Coverage analysis (since test passed)
|
||||||
|
#if VM_COVERAGE
|
||||||
|
Verilated::mkdir("logs");
|
||||||
|
VerilatedCov::write("logs/coverage.dat");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
delete top;
|
||||||
|
top = NULL;
|
||||||
|
exit(0);
|
||||||
|
}
|
@ -21,22 +21,10 @@ module CP0 (
|
|||||||
output logic interrupt,
|
output logic interrupt,
|
||||||
|
|
||||||
// MMU
|
// MMU
|
||||||
input logic tlbr,
|
CP0_i.cp0 c0
|
||||||
input logic tlbp,
|
|
||||||
output logic [2:0] K0,
|
|
||||||
output logic in_kernel,
|
|
||||||
output Random_t Random,
|
|
||||||
output Index_t Index,
|
|
||||||
output EntryHi_t EntryHi,
|
|
||||||
output EntryLo_t EntryLo1,
|
|
||||||
output EntryLo_t EntryLo0,
|
|
||||||
input EntryHi_t tlb_EntryHi,
|
|
||||||
input EntryLo_t tlb_EntryLo1,
|
|
||||||
input EntryLo_t tlb_EntryLo0,
|
|
||||||
input Index_t tlb_Index
|
|
||||||
);
|
);
|
||||||
|
|
||||||
CP0_REGS_t rf_cp0;
|
CP0_REGS_t rf_cp0/*verilator split_var*/;
|
||||||
logic count_lo;
|
logic count_lo;
|
||||||
|
|
||||||
// int comb logic
|
// int comb logic
|
||||||
@ -168,7 +156,7 @@ module CP0 (
|
|||||||
9: rf_cp0.Count = wdata;
|
9: rf_cp0.Count = wdata;
|
||||||
8: rf_cp0.BadVAddr = wdata;
|
8: rf_cp0.BadVAddr = wdata;
|
||||||
// 7: rf_cp0.HWREna = wdata;
|
// 7: rf_cp0.HWREna = wdata;
|
||||||
6: begin
|
6: begin
|
||||||
rf_cp0.Wired.Wired = wdata[2:0];
|
rf_cp0.Wired.Wired = wdata[2:0];
|
||||||
rf_cp0.Random.Random = 3'b111;
|
rf_cp0.Random.Random = 3'b111;
|
||||||
end
|
end
|
||||||
@ -197,25 +185,25 @@ module CP0 (
|
|||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
if (tlbr) begin
|
if (c0.cpu_tlbr) begin
|
||||||
rf_cp0.EntryHi.VPN2 = tlb_EntryHi.VPN2;
|
rf_cp0.EntryHi.VPN2 = c0.tlb_EntryHi.VPN2;
|
||||||
rf_cp0.EntryHi.ASID = tlb_EntryHi.ASID;
|
rf_cp0.EntryHi.ASID = c0.tlb_EntryHi.ASID;
|
||||||
// rf_cp0.PageMask.Mask = tlb_PageMask.Mask;
|
// rf_cp0.PageMask.Mask = tlb_PageMask.Mask;
|
||||||
rf_cp0.EntryLo0.PFN = tlb_EntryLo0.PFN;
|
rf_cp0.EntryLo0.PFN = c0.tlb_EntryLo0.PFN;
|
||||||
rf_cp0.EntryLo0.C = tlb_EntryLo0.C;
|
rf_cp0.EntryLo0.C = c0.tlb_EntryLo0.C;
|
||||||
rf_cp0.EntryLo0.D = tlb_EntryLo0.D;
|
rf_cp0.EntryLo0.D = c0.tlb_EntryLo0.D;
|
||||||
rf_cp0.EntryLo0.V = tlb_EntryLo0.V;
|
rf_cp0.EntryLo0.V = c0.tlb_EntryLo0.V;
|
||||||
rf_cp0.EntryLo0.G = tlb_EntryLo0.G;
|
rf_cp0.EntryLo0.G = c0.tlb_EntryLo0.G;
|
||||||
rf_cp0.EntryLo1.PFN = tlb_EntryLo1.PFN;
|
rf_cp0.EntryLo1.PFN = c0.tlb_EntryLo1.PFN;
|
||||||
rf_cp0.EntryLo1.C = tlb_EntryLo1.C;
|
rf_cp0.EntryLo1.C = c0.tlb_EntryLo1.C;
|
||||||
rf_cp0.EntryLo1.D = tlb_EntryLo1.D;
|
rf_cp0.EntryLo1.D = c0.tlb_EntryLo1.D;
|
||||||
rf_cp0.EntryLo1.V = tlb_EntryLo1.V;
|
rf_cp0.EntryLo1.V = c0.tlb_EntryLo1.V;
|
||||||
rf_cp0.EntryLo1.G = tlb_EntryLo1.G;
|
rf_cp0.EntryLo1.G = c0.tlb_EntryLo1.G;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (tlbp) begin
|
if (c0.cpu_c0_tlbp) begin
|
||||||
rf_cp0.Index.P = tlb_Index.P;
|
rf_cp0.Index.P = c0.tlb_Index.P;
|
||||||
rf_cp0.Index.Index = tlb_Index.Index;
|
rf_cp0.Index.Index = c0.tlb_Index.Index;
|
||||||
end
|
end
|
||||||
|
|
||||||
if (rf_cp0.Count == rf_cp0.Compare) rf_cp0.Cause.TI = 1;
|
if (rf_cp0.Count == rf_cp0.Compare) rf_cp0.Cause.TI = 1;
|
||||||
@ -289,14 +277,14 @@ module CP0 (
|
|||||||
assign Bev = rf_cp0.Status.Bev;
|
assign Bev = rf_cp0.Status.Bev;
|
||||||
assign EBase = rf_cp0.EBase[31:12];
|
assign EBase = rf_cp0.EBase[31:12];
|
||||||
|
|
||||||
assign K0 = rf_cp0.Config.K0;
|
assign c0.cp0_K0 = rf_cp0.Config.K0;
|
||||||
assign Random = rf_cp0.Random;
|
assign c0.cp0_Random = rf_cp0.Random;
|
||||||
assign Index = rf_cp0.Index;
|
assign c0.cp0_Index = rf_cp0.Index;
|
||||||
assign EntryHi = rf_cp0.EntryHi;
|
assign c0.cp0_EntryHi = rf_cp0.EntryHi;
|
||||||
// assign PageMask = rf_cp0.PageMask;
|
// assign PageMask = rf_cp0.PageMask;
|
||||||
assign EntryLo1 = rf_cp0.EntryLo1;
|
assign c0.cp0_EntryLo1 = rf_cp0.EntryLo1;
|
||||||
assign EntryLo0 = rf_cp0.EntryLo0;
|
assign c0.cp0_EntryLo0 = rf_cp0.EntryLo0;
|
||||||
|
|
||||||
assign in_kernel = ~rf_cp0.Status.UM | rf_cp0.Status.EXL; // currently no ERL
|
assign c0.cp0_in_kernel = ~rf_cp0.Status.UM | rf_cp0.Status.EXL; // currently no ERL
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -1,35 +1,34 @@
|
|||||||
`include "defines.svh"
|
`include "defines.svh"
|
||||||
|
|
||||||
module ALU(
|
module ALU(
|
||||||
input word_t a, b,
|
input word_t a, b,
|
||||||
input ALUCtrl_t aluctrl,
|
input ALUCtrl_t aluctrl,
|
||||||
output word_t aluout,
|
output word_t aluout,
|
||||||
output logic overflow);
|
output logic overflow
|
||||||
|
);
|
||||||
|
|
||||||
wire logic alt = aluctrl.alt;
|
wire logic alt = aluctrl.alt;
|
||||||
|
|
||||||
wire logic [4:0] sa = a[4:0];
|
wire logic [4:0] sa = a[4:0];
|
||||||
wire logic ex = alt & b[31];
|
wire logic ex = alt & b[31];
|
||||||
wire word_t sl = b << sa;
|
wire word_t sl = b << sa;
|
||||||
/* verilator lint_off WIDTH */
|
/* verilator lint_off WIDTH */
|
||||||
wire word_t sr = {{31{ex}}, b} >> sa;
|
wire word_t sr = {{31{ex}}, b} >> sa;
|
||||||
/* verilator lint_on WIDTH */
|
/* verilator lint_on WIDTH */
|
||||||
|
wire word_t b2 = alt ? ~b : b;
|
||||||
wire word_t b2 = alt ? ~b : b;
|
wire word_t sum;
|
||||||
wire word_t sum;
|
wire logic lt, ltu;
|
||||||
wire logic lt, ltu;
|
/* verilator lint_off WIDTH */
|
||||||
|
assign {lt, ltu, sum} = {a[31], 1'b0, a} + {b2[31], 1'b1, b2} + alt; // alt for cin(CARRY4) at synthesis
|
||||||
/* verilator lint_off WIDTH */
|
/* verilator lint_on WIDTH */
|
||||||
assign {lt, ltu, sum} = {a[31], 1'b0, a} + {b2[31], 1'b1, b2} + alt; // alt for cin(CARRY4) at synthesis
|
assign aluout = (aluctrl.f_sl ? sl : 32'b0)
|
||||||
/* verilator lint_on WIDTH */
|
| (aluctrl.f_sr ? sr : 32'b0)
|
||||||
assign aluout = (aluctrl.f_sl ? sl : 32'b0)
|
| (aluctrl.f_add ? sum : 32'b0)
|
||||||
| (aluctrl.f_sr ? sr : 32'b0)
|
| (aluctrl.f_and ? a & b : 32'b0)
|
||||||
| (aluctrl.f_add ? sum : 32'b0)
|
| (aluctrl.f_or ? alt ? ~(a | b) : a | b : 32'b0)
|
||||||
| (aluctrl.f_and ? a & b : 32'b0)
|
| (aluctrl.f_xor ? a ^ b : 32'b0)
|
||||||
| (aluctrl.f_or ? alt ? ~(a | b) : a | b : 32'b0)
|
| (aluctrl.f_slt ? {31'b0, lt } : 32'b0)
|
||||||
| (aluctrl.f_xor ? a ^ b : 32'b0)
|
| (aluctrl.f_sltu ? {31'b0, ltu} : 32'b0)
|
||||||
| (aluctrl.f_slt ? {31'b0, lt } : 32'b0)
|
| (aluctrl.f_mova ? a : 32'b0);
|
||||||
| (aluctrl.f_sltu ? {31'b0, ltu} : 32'b0)
|
assign overflow = lt ^ sum[31];
|
||||||
| (aluctrl.f_mova ? a : 32'b0);
|
|
||||||
assign overflow = lt ^ sum[31];
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -5,7 +5,7 @@ module Controller (
|
|||||||
input logic eq,
|
input logic eq,
|
||||||
input logic ltz,
|
input logic ltz,
|
||||||
input word_t rt,
|
input word_t rt,
|
||||||
output Ctrl_t ctrl,
|
output Ctrl_t ctrl/*verilator split_var*/,
|
||||||
output word_t imm,
|
output word_t imm,
|
||||||
output logic [4:0] sa
|
output logic [4:0] sa
|
||||||
);
|
);
|
||||||
|
@ -10,20 +10,9 @@ module Datapath (
|
|||||||
InstFetch_i.cpu fetch,
|
InstFetch_i.cpu fetch,
|
||||||
Memory_i.cpu mem,
|
Memory_i.cpu mem,
|
||||||
CacheOp_i.cpu cache_op,
|
CacheOp_i.cpu cache_op,
|
||||||
input logic iTLBRefill,
|
|
||||||
input logic iTLBInvalid,
|
|
||||||
input logic iAddressError,
|
|
||||||
input logic dTLBRefill,
|
|
||||||
input logic dTLBInvalid,
|
|
||||||
input logic dTLBModified,
|
|
||||||
input logic dAddressError,
|
|
||||||
output logic tlb_tlbwi,
|
|
||||||
output logic tlb_tlbwr,
|
|
||||||
output logic tlb_tlbp,
|
|
||||||
output logic c0_tlbr,
|
|
||||||
output logic c0_tlbp,
|
|
||||||
|
|
||||||
// CP0
|
// CP0
|
||||||
|
CP0_i.cpu C0,
|
||||||
input logic C0_int,
|
input logic C0_int,
|
||||||
output logic [4:0] C0_addr,
|
output logic [4:0] C0_addr,
|
||||||
output logic [2:0] C0_sel,
|
output logic [2:0] C0_sel,
|
||||||
@ -34,7 +23,6 @@ module Datapath (
|
|||||||
input word_t C0_ERETPC,
|
input word_t C0_ERETPC,
|
||||||
input logic C0_Bev,
|
input logic C0_Bev,
|
||||||
input logic [19:0] C0_EBase,
|
input logic [19:0] C0_EBase,
|
||||||
input logic C0_kernel,
|
|
||||||
|
|
||||||
//debug interface
|
//debug interface
|
||||||
output wire [31:0] debug_wb_pc,
|
output wire [31:0] debug_wb_pc,
|
||||||
@ -52,12 +40,12 @@ module Datapath (
|
|||||||
|
|
||||||
logic rstD, rstM;
|
logic rstD, rstM;
|
||||||
|
|
||||||
PF_t PF;
|
PF_t PF/*verilator split_var*/;
|
||||||
F_t F;
|
F_t F/*verilator split_var*/;
|
||||||
D_t D;
|
D_t D/*verilator split_var*/;
|
||||||
E_t E;
|
E_t E/*verilator split_var*/;
|
||||||
M_t M;
|
M_t M/*verilator split_var*/;
|
||||||
W_t W;
|
W_t W/*verilator split_var*/;
|
||||||
|
|
||||||
// Pre Fetch
|
// Pre Fetch
|
||||||
logic PF_go;
|
logic PF_go;
|
||||||
@ -330,7 +318,7 @@ module Datapath (
|
|||||||
|
|
||||||
assign F.en = PF.pc[1:0] != 2'b00 & D_IA_can_dispatch | fetch.req & fetch.addr_ok;
|
assign F.en = PF.pc[1:0] != 2'b00 & D_IA_can_dispatch | fetch.req & fetch.addr_ok;
|
||||||
|
|
||||||
assign F.ExcValid = F.pc[1:0] != 2'b00 | iTLBRefill | iTLBInvalid | iAddressError;
|
assign F.ExcValid = F.pc[1:0] != 2'b00 | C0.tlb_iTLBRefill | C0.tlb_iTLBInvalid | C0.tlb_iAddressError;
|
||||||
|
|
||||||
//---------------------------------------------------------------------------//
|
//---------------------------------------------------------------------------//
|
||||||
// Instr Queue //
|
// Instr Queue //
|
||||||
@ -342,7 +330,7 @@ module Datapath (
|
|||||||
|
|
||||||
.vinA(fetch.data_ok | F.ExcValid),
|
.vinA(fetch.data_ok | F.ExcValid),
|
||||||
.inA ({F.pc[2] ? fetch.rdata1 : fetch.rdata0, F.pc,
|
.inA ({F.pc[2] ? fetch.rdata1 : fetch.rdata0, F.pc,
|
||||||
iTLBRefill, iTLBInvalid, iAddressError}),
|
C0.tlb_iTLBRefill, C0.tlb_iTLBInvalid, C0.tlb_iAddressError}),
|
||||||
|
|
||||||
.vinB(fetch.data_ok & ~F.pc[2]),
|
.vinB(fetch.data_ok & ~F.pc[2]),
|
||||||
.inB ({fetch.rdata1, F.pc[31:3], 3'b100, 3'b00}),
|
.inB ({fetch.rdata1, F.pc[31:3], 3'b100, 3'b00}),
|
||||||
@ -462,7 +450,7 @@ module Datapath (
|
|||||||
| D_IA_TLBRefill | D_IA_TLBInvalid
|
| D_IA_TLBRefill | D_IA_TLBInvalid
|
||||||
| D_IA_AddressError
|
| D_IA_AddressError
|
||||||
| D.IA.SYSCALL | D.IA.BREAK | D.IA.ERET
|
| D.IA.SYSCALL | D.IA.BREAK | D.IA.ERET
|
||||||
| D.IA.PRV & ~C0_kernel);
|
| D.IA.PRV & ~C0.cp0_in_kernel);
|
||||||
assign D.IA_ERET = D_IA_valid & D.IA_pc[1:0] == 2'b00 & ~D_IA_TLBRefill & ~D_IA_TLBInvalid & ~D_IA_AddressError & D_IA_iv & D.IA.ERET;
|
assign D.IA_ERET = D_IA_valid & D.IA_pc[1:0] == 2'b00 & ~D_IA_TLBRefill & ~D_IA_TLBInvalid & ~D_IA_AddressError & D_IA_iv & D.IA.ERET;
|
||||||
assign D.IA_REFILL = D_IA_valid & D.IB_pc[1:0] == 2'b00 & D_IA_TLBRefill;
|
assign D.IA_REFILL = D_IA_valid & D.IB_pc[1:0] == 2'b00 & D_IA_TLBRefill;
|
||||||
assign D.IA_ExcCode = D.IA_pc[1:0] != 2'b00 | D_IA_AddressError ? `EXCCODE_ADEL
|
assign D.IA_ExcCode = D.IA_pc[1:0] != 2'b00 | D_IA_AddressError ? `EXCCODE_ADEL
|
||||||
@ -479,7 +467,7 @@ module Datapath (
|
|||||||
| D_IB_AddressError
|
| D_IB_AddressError
|
||||||
| D.IB.SYSCALL | D.IB.BREAK | D.IB.ERET
|
| D.IB.SYSCALL | D.IB.BREAK | D.IB.ERET
|
||||||
| D.IB_Delay & D.IB.BJRJ
|
| D.IB_Delay & D.IB.BJRJ
|
||||||
| D.IB.PRV & ~C0_kernel);
|
| D.IB.PRV & ~C0.cp0_in_kernel);
|
||||||
assign D.IB_ERET = D_IB_valid & D.IB_pc[1:0] == 2'b00 & ~D_IB_TLBRefill & ~D_IB_TLBInvalid & ~D_IB_AddressError & D_IB_iv & D.IB.ERET & ~D.IB_Delay;
|
assign D.IB_ERET = D_IB_valid & D.IB_pc[1:0] == 2'b00 & ~D_IB_TLBRefill & ~D_IB_TLBInvalid & ~D_IB_AddressError & D_IB_iv & D.IB.ERET & ~D.IB_Delay;
|
||||||
assign D.IB_REFILL = D_IB_valid & D.IB_pc[1:0] == 2'b00 & D_IB_TLBRefill;
|
assign D.IB_REFILL = D_IB_valid & D.IB_pc[1:0] == 2'b00 & D_IB_TLBRefill;
|
||||||
// EXCCODE_BP and EXCCODE_SYSCALL -> exc.txt
|
// EXCCODE_BP and EXCCODE_SYSCALL -> exc.txt
|
||||||
@ -534,6 +522,15 @@ module Datapath (
|
|||||||
| D.IA.WCtrl.RW & D.IB.RT == D.IA.RD & D.IB.MCtrl1.MWR & ~D.IA.DP1
|
| D.IA.WCtrl.RW & D.IB.RT == D.IA.RD & D.IB.MCtrl1.MWR & ~D.IA.DP1
|
||||||
// Not Arith -> LWL/LWR
|
// Not Arith -> LWL/LWR
|
||||||
| D.IA.WCtrl.RW & D.IB.RT == D.IA.RD & |D.IB.MCtrl1.ALR & ~D.IA.DP1
|
| D.IA.WCtrl.RW & D.IB.RT == D.IA.RD & |D.IB.MCtrl1.ALR & ~D.IA.DP1
|
||||||
|
// D.IA -> MOVN/MOVZ
|
||||||
|
| D.IA.WCtrl.RW & D.IB.RT == D.IA.RD & D.IB.DT
|
||||||
|
// Arith -> MOVN/MOVZ
|
||||||
|
| E.I0.WCtrl.RW & D.IB.RT == E.I0.RD & D.IB.DT
|
||||||
|
| E.I1.WCtrl.RW & D.IB.RT == E.I1.RD & D.IB.DT
|
||||||
|
// Not Arith -> MOVN/MOVZ
|
||||||
|
| M.I0.WCtrl.RW & D.IB.RT == M.I0.RD & D.IB.DT & ~M.I0.MCtrl.RS0[2]
|
||||||
|
// Load -> MOVN/MOVZ
|
||||||
|
| M.I1.WCtrl.RW & D.IB.RT == M.I1.RD & D.IB.DT & M.I1.MCtrl.MR
|
||||||
// CP0 Execution Hazards
|
// CP0 Execution Hazards
|
||||||
// Hazards Related to the TLB
|
// Hazards Related to the TLB
|
||||||
| D.IA.MCtrl0.C0W & D.IB.MCtrl1.TLBR & D.IA.MCtrl0.C0D == C0_INDEX
|
| D.IA.MCtrl0.C0W & D.IB.MCtrl1.TLBR & D.IA.MCtrl0.C0D == C0_INDEX
|
||||||
@ -787,7 +784,7 @@ module Datapath (
|
|||||||
E.en,
|
E.en,
|
||||||
E.I1.ECtrl
|
E.I1.ECtrl
|
||||||
);
|
);
|
||||||
ffenrc #(14) E_I1_MCtrl_ff (
|
ffenrc #(15) E_I1_MCtrl_ff (
|
||||||
clk,
|
clk,
|
||||||
rst | rstM,
|
rst | rstM,
|
||||||
D.I1.MCtrl,
|
D.I1.MCtrl,
|
||||||
@ -927,15 +924,15 @@ module Datapath (
|
|||||||
E_I1_STRBERROR
|
E_I1_STRBERROR
|
||||||
);
|
);
|
||||||
|
|
||||||
assign tlb_tlbp = E.I1.MCtrl.TLBP;
|
assign C0.cpu_tlb_tlbp = E.I1.MCtrl.TLBP;
|
||||||
assign mem.req = E.I1.MCtrl.MR & E_I1_goWithoutOF & M.en & ~rstM;
|
assign mem.req = E.I1.MCtrl.MR & E_I1_goWithoutOF & M.en & ~rstM;
|
||||||
assign E_I1_ADDR = E_I1_ForwardS + E.I1.imm;
|
assign E_I1_ADDR = E_I1_ForwardS + E.I1.imm;
|
||||||
assign mem.addr = |E.I1.MCtrl.ALR ? {E_I1_ADDR[31:2], 2'b0}
|
assign mem.addr = |E.I1.MCtrl.ALR ? {E_I1_ADDR[31:2], 2'b0}
|
||||||
: (cache_op == CNOP | ~cache_op[1]) ? E_I1_ADDR
|
: (~cache_op.op.icache_op & ~cache_op.op.dcache_op | ~cache_op.op.index_or_hit) ? E_I1_ADDR
|
||||||
: cache_op[2] ? {E_I1_ADDR[32-`DC_INDEXL-1:0], `DC_INDEXL'b0}
|
: cache_op.op.dcache_op ? {E_I1_ADDR[32-`DC_INDEXL-1:0], `DC_INDEXL'b0}
|
||||||
: {E_I1_ADDR[32-`IC_INDEXL-1:0], `IC_INDEXL'b0};
|
: {E_I1_ADDR[32-`IC_INDEXL-1:0], `IC_INDEXL'b0};
|
||||||
assign mem.size = {E.I1.MCtrl.SZ[1], E.I1.MCtrl.SZ[0] & ~E.I1.MCtrl.SZ[1]};
|
assign mem.size = {E.I1.MCtrl.SZ[1], E.I1.MCtrl.SZ[0] & ~E.I1.MCtrl.SZ[1]};
|
||||||
assign cache_op = E.I1.MCtrl.CACHE_OP;
|
assign cache_op.op = E.I1.MCtrl.CACHE_OP;
|
||||||
|
|
||||||
assign E.en = E_go & M.en;
|
assign E.en = E_go & M.en;
|
||||||
assign E_go = ~mem.req | mem.addr_ok;
|
assign E_go = ~mem.req | mem.addr_ok;
|
||||||
@ -1087,7 +1084,7 @@ module Datapath (
|
|||||||
M.en,
|
M.en,
|
||||||
M.I1.ALUOut
|
M.I1.ALUOut
|
||||||
);
|
);
|
||||||
ffenrc #(14) M_I1_MCtrl_ff (
|
ffenrc #(15) M_I1_MCtrl_ff (
|
||||||
clk,
|
clk,
|
||||||
rst | rstM,
|
rst | rstM,
|
||||||
E.I1.MCtrl,
|
E.I1.MCtrl,
|
||||||
@ -1124,7 +1121,7 @@ module Datapath (
|
|||||||
);
|
);
|
||||||
myBuffer0 #(4) dExc_buffer (
|
myBuffer0 #(4) dExc_buffer (
|
||||||
clk, rst,
|
clk, rst,
|
||||||
{dTLBRefill, dTLBInvalid, dTLBModified, dAddressError},
|
{C0.tlb_dTLBRefill, C0.tlb_dTLBInvalid, C0.tlb_dTLBModified, C0.tlb_dAddressError},
|
||||||
dTLBExcValid,
|
dTLBExcValid,
|
||||||
{dTLBRefillB, dTLBInvalidB, dTLBModifiedB, dAddressErrorB}
|
{dTLBRefillB, dTLBInvalidB, dTLBModifiedB, dAddressErrorB}
|
||||||
);
|
);
|
||||||
@ -1235,10 +1232,10 @@ module Datapath (
|
|||||||
assign C0_wdata = M_I0_ForwardT;
|
assign C0_wdata = M_I0_ForwardT;
|
||||||
|
|
||||||
// M.I1.MEM
|
// M.I1.MEM
|
||||||
assign tlb_tlbwi = M.I1.MCtrl.TLBWI;
|
assign C0.cpu_tlbwi = M.I1.MCtrl.TLBWI;
|
||||||
assign tlb_tlbwr = M.I1.MCtrl.TLBWR;
|
assign C0.cpu_tlbwr = M.I1.MCtrl.TLBWR;
|
||||||
assign c0_tlbr = M.I1.MCtrl.TLBR;
|
assign C0.cpu_tlbr = M.I1.MCtrl.TLBR;
|
||||||
assign c0_tlbp = M.I1.MCtrl.TLBP & M.en;
|
assign C0.cpu_c0_tlbp = M.I1.MCtrl.TLBP & M.en;
|
||||||
assign mem.wr = M.I1.MCtrl.MWR;
|
assign mem.wr = M.I1.MCtrl.MWR;
|
||||||
memoutput M_I1_memoutput (
|
memoutput M_I1_memoutput (
|
||||||
.addr (M.I1.ALUOut[1:0]),
|
.addr (M.I1.ALUOut[1:0]),
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
module addr_virt_to_phy (
|
module addr_virt_to_phy (
|
||||||
|
input logic [ 2:0] K0,
|
||||||
input word_t virt_addr,
|
input word_t virt_addr,
|
||||||
input logic [19:0] tlb_addr,
|
input logic [19:0] tlb_addr,
|
||||||
input logic tlb_hit,
|
input logic tlb_hit,
|
||||||
|
@ -14,11 +14,11 @@ module bram #(
|
|||||||
|
|
||||||
for(genvar i = 0; i < DATA_DEPTH; i++)
|
for(genvar i = 0; i < DATA_DEPTH; i++)
|
||||||
initial ram[i] = 0;
|
initial ram[i] = 0;
|
||||||
|
|
||||||
always_ff @(posedge clka) begin
|
always_ff @(posedge clka) begin
|
||||||
if (~rst) begin
|
if (~rst) begin
|
||||||
if(wea) ram[addra] <= dina;
|
if(wea) ram[addra] <= dina;
|
||||||
douta <= ~wea ? ram[addra] : dina;
|
douta <= ~wea ? ram[addra] : dina;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
142
src/MU/AXI.sv
142
src/MU/AXI.sv
@ -1,48 +1,48 @@
|
|||||||
module AXI (
|
module AXI (
|
||||||
output wire [ 3:0] arid,
|
output wire logic [ 3:0] arid,
|
||||||
output wire [31:0] araddr,
|
output wire logic [31:0] araddr,
|
||||||
output wire [ 3:0] arlen,
|
output wire logic [ 3:0] arlen,
|
||||||
output wire [ 2:0] arsize,
|
output wire logic [ 2:0] arsize,
|
||||||
output wire [ 1:0] arburst,
|
output wire logic [ 1:0] arburst,
|
||||||
output wire [ 1:0] arlock,
|
output wire logic [ 1:0] arlock,
|
||||||
output wire [ 3:0] arcache,
|
output wire logic [ 3:0] arcache,
|
||||||
output wire [ 2:0] arprot,
|
output wire logic [ 2:0] arprot,
|
||||||
output wire arvalid,
|
output wire logic arvalid,
|
||||||
input wire arready,
|
input wire logic arready,
|
||||||
|
|
||||||
input wire [ 3:0] rid,
|
input wire logic [ 3:0] rid,
|
||||||
input wire [31:0] rdata,
|
input wire logic [31:0] rdata,
|
||||||
input wire [ 1:0] rresp,
|
input wire logic [ 1:0] rresp,
|
||||||
input wire rlast,
|
input wire logic rlast,
|
||||||
input wire rvalid,
|
input wire logic rvalid,
|
||||||
output wire rready,
|
output wire logic rready,
|
||||||
|
|
||||||
output wire [ 3:0] awid,
|
output wire logic [ 3:0] awid,
|
||||||
output wire [31:0] awaddr,
|
output wire logic [31:0] awaddr,
|
||||||
output wire [ 3:0] awlen,
|
output wire logic [ 3:0] awlen,
|
||||||
output wire [ 2:0] awsize,
|
output wire logic [ 2:0] awsize,
|
||||||
output wire [ 1:0] awburst,
|
output wire logic [ 1:0] awburst,
|
||||||
output wire [ 1:0] awlock,
|
output wire logic [ 1:0] awlock,
|
||||||
output wire [ 3:0] awcache,
|
output wire logic [ 3:0] awcache,
|
||||||
output wire [ 2:0] awprot,
|
output wire logic [ 2:0] awprot,
|
||||||
output wire awvalid,
|
output wire logic awvalid,
|
||||||
input wire awready,
|
input wire logic awready,
|
||||||
|
|
||||||
output wire [ 3:0] wid,
|
output wire logic [ 3:0] wid,
|
||||||
output wire [31:0] wdata,
|
output wire logic [31:0] wdata,
|
||||||
output wire [ 3:0] wstrb,
|
output wire logic [ 3:0] wstrb,
|
||||||
output wire wlast,
|
output wire logic wlast,
|
||||||
output wire wvalid,
|
output wire logic wvalid,
|
||||||
input wire wready,
|
input wire logic wready,
|
||||||
|
|
||||||
input wire [3:0] bid,
|
input wire logic [3:0] bid,
|
||||||
input wire [1:0] bresp,
|
input wire logic [1:0] bresp,
|
||||||
input wire bvalid,
|
input wire logic bvalid,
|
||||||
output wire bready,
|
output wire logic bready,
|
||||||
|
|
||||||
AXIRead_i.axi inst,
|
AXIRead_i.axi axi_inst,
|
||||||
AXIRead_i.axi rdata,
|
AXIRead_i.axi axi_rdata,
|
||||||
AXIWrite_i.axi wdata
|
AXIWrite_i.axi axi_wdata
|
||||||
);
|
);
|
||||||
|
|
||||||
// ==============================
|
// ==============================
|
||||||
@ -50,19 +50,19 @@ module AXI (
|
|||||||
// ==============================
|
// ==============================
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
inst.rdata = rdata;
|
axi_inst.rdata = rdata;
|
||||||
rdata.rdata = rdata;
|
axi_rdata.rdata = rdata;
|
||||||
|
|
||||||
if (rid == 0) begin
|
if (rid == 0) begin
|
||||||
inst.rvalid = rvalid;
|
axi_inst.rvalid = rvalid;
|
||||||
inst.data_ok = rlast;
|
axi_inst.data_ok = rlast;
|
||||||
rdata.rvalid = 1'b0;
|
axi_rdata.rvalid = 1'b0;
|
||||||
rdata.data_ok = 1'b0;
|
axi_rdata.data_ok = 1'b0;
|
||||||
end else begin
|
end else begin
|
||||||
rdata.rvalid = rvalid;
|
axi_rdata.rvalid = rvalid;
|
||||||
rdata.data_ok = rlast;
|
axi_rdata.data_ok = rlast;
|
||||||
inst.rvalid = 1'b0;
|
axi_inst.rvalid = 1'b0;
|
||||||
inst.data_ok = 1'b0;
|
axi_inst.data_ok = 1'b0;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -79,22 +79,22 @@ module AXI (
|
|||||||
// Burst
|
// Burst
|
||||||
arburst = 2'b10; // Wrap
|
arburst = 2'b10; // Wrap
|
||||||
|
|
||||||
arvalid = rdata.req | inst.req;
|
arvalid = axi_rdata.req | axi_inst.req;
|
||||||
rdata.addr_ok = arready;
|
axi_rdata.addr_ok = arready;
|
||||||
if (rdata.req) begin
|
if (axi_rdata.req) begin
|
||||||
arid = 4'b0001;
|
arid = 4'b0001;
|
||||||
arprot = 3'b001;
|
arprot = 3'b001;
|
||||||
araddr = rdata.addr;
|
araddr = axi_rdata.addr;
|
||||||
arlen = rdata.len;
|
arlen = axi_rdata.len;
|
||||||
arsize = rdata.size;
|
arsize = axi_rdata.size;
|
||||||
inst.addr_ok = 1'b0;
|
axi_inst.addr_ok = 1'b0;
|
||||||
end else begin
|
end else begin
|
||||||
arid = 4'b0000;
|
arid = 4'b0000;
|
||||||
arprot = 3'b101;
|
arprot = 3'b101;
|
||||||
araddr = inst.addr;
|
araddr = axi_inst.addr;
|
||||||
arlen = inst.len;
|
arlen = axi_inst.len;
|
||||||
arsize = inst.size;
|
arsize = axi_inst.size;
|
||||||
inst.addr_ok = arready;
|
axi_inst.addr_ok = arready;
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@ -103,15 +103,15 @@ module AXI (
|
|||||||
// ======= Write Request ========
|
// ======= Write Request ========
|
||||||
// ==============================
|
// ==============================
|
||||||
|
|
||||||
assign wdata.data_ok = bvalid;
|
assign axi_wdata.data_ok = bvalid;
|
||||||
assign wdata.wready = wready;
|
assign axi_wdata.wready = wready;
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
wid = 4'b1;
|
wid = 4'b1;
|
||||||
wdata = wdata.wdata;
|
wdata = axi_wdata.wdata;
|
||||||
wstrb = wdata.wstrb;
|
wstrb = axi_wdata.wstrb;
|
||||||
wlast = wdata.wlast;
|
wlast = axi_wdata.wlast;
|
||||||
wvalid = wdata.wvalid;
|
wvalid = axi_wdata.wvalid;
|
||||||
end
|
end
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
@ -126,11 +126,11 @@ module AXI (
|
|||||||
awid = 4'b1;
|
awid = 4'b1;
|
||||||
awprot = 3'b001;
|
awprot = 3'b001;
|
||||||
|
|
||||||
awvalid = wdata.req;
|
awvalid = axi_wdata.req;
|
||||||
awaddr = wdata.addr;
|
awaddr = axi_wdata.addr;
|
||||||
awlen = wdata.len;
|
awlen = axi_wdata.len;
|
||||||
awsize = wdata.size;
|
awsize = axi_wdata.size;
|
||||||
wdata.addr_ok = awready;
|
axi_wdata.addr_ok = awready;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
101
src/MU/AXIReader.sv
Normal file
101
src/MU/AXIReader.sv
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
`include "defines.svh"
|
||||||
|
|
||||||
|
module AXIReader #(parameter DATA_LEN = 8)
|
||||||
|
(
|
||||||
|
input clk,
|
||||||
|
input rst,
|
||||||
|
|
||||||
|
input AXIRead_i axi,
|
||||||
|
|
||||||
|
input call,
|
||||||
|
input word_t addr,
|
||||||
|
input [3:0] len,
|
||||||
|
input [2:0] size,
|
||||||
|
|
||||||
|
output done,
|
||||||
|
output reg [DATA_LEN-1:0] buffer
|
||||||
|
);
|
||||||
|
word_t stored_addr;
|
||||||
|
logic [3:0] stored_len;
|
||||||
|
logic [2:0] stored_size;
|
||||||
|
logic [DATA_LEN-1:0] nxt_buffer;
|
||||||
|
|
||||||
|
ffen #(`XLEN) addr_store (.*, .d(addr), .en(call), .q(stored_addr));
|
||||||
|
ffen #(4) len_store (.*, .d(len), .en(call), .q(stored_len));
|
||||||
|
ffen #(3) size_store (.*, .d(size), .en(call), .q(stored_size));
|
||||||
|
|
||||||
|
typedef enum bit [1:0] { IDLE, WAIT_ADDR, DATA } state_t;
|
||||||
|
state_t cur_state;
|
||||||
|
state_t nxt_state;
|
||||||
|
|
||||||
|
always_comb begin
|
||||||
|
nxt_state = cur_state;
|
||||||
|
nxt_buffer = buffer;
|
||||||
|
|
||||||
|
done = 0;
|
||||||
|
|
||||||
|
axi.req = 0;
|
||||||
|
axi.addr = call ? addr : stored_addr;
|
||||||
|
axi.len = call ? len : stored_len;
|
||||||
|
axi.size = call ? size : stored_size;
|
||||||
|
|
||||||
|
case (cur_state)
|
||||||
|
IDLE: begin
|
||||||
|
if (call) begin
|
||||||
|
// axi control
|
||||||
|
axi.req = 1'b1;
|
||||||
|
|
||||||
|
// check addr_ok
|
||||||
|
if (~axi.addr_ok)
|
||||||
|
nxt_state = WAIT_ADDR;
|
||||||
|
else
|
||||||
|
nxt_state = DATA;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
WAIT_ADDR: begin
|
||||||
|
// axi control
|
||||||
|
axi.req = 1'b1;
|
||||||
|
|
||||||
|
// check addr_ok
|
||||||
|
if (~axi.addr_ok)
|
||||||
|
nxt_state = WAIT_ADDR;
|
||||||
|
// check received data
|
||||||
|
else if (axi.rvalid) begin
|
||||||
|
nxt_buffer = {axi.rdata, buffer[DATA_LEN-1:`XLEN]};
|
||||||
|
if (axi.data_ok) begin
|
||||||
|
nxt_state = IDLE;
|
||||||
|
done = 1'b1;
|
||||||
|
end else
|
||||||
|
nxt_state = DATA;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
DATA: begin
|
||||||
|
if (axi.rvalid) begin
|
||||||
|
nxt_buffer = {axi.rdata, buffer[DATA_LEN-1:`XLEN]};
|
||||||
|
if (axi.data_ok) begin
|
||||||
|
nxt_state = IDLE;
|
||||||
|
done = 1'b1;
|
||||||
|
|
||||||
|
// TODO: immediately receive next request
|
||||||
|
// $assert (done & call);
|
||||||
|
end else
|
||||||
|
nxt_state = DATA;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
default: begin end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (rst) begin
|
||||||
|
cur_state <= IDLE;
|
||||||
|
buffer <= 0;
|
||||||
|
end else begin
|
||||||
|
cur_state <= nxt_state;
|
||||||
|
buffer <= nxt_buffer;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
126
src/MU/AXIWriter.sv
Normal file
126
src/MU/AXIWriter.sv
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
`include "defines.svh"
|
||||||
|
|
||||||
|
module AXIWriter #(parameter DATA_LEN = 8)
|
||||||
|
(
|
||||||
|
input clk,
|
||||||
|
input rst,
|
||||||
|
|
||||||
|
input AXIWrite_i axi,
|
||||||
|
|
||||||
|
input call,
|
||||||
|
input word_t addr,
|
||||||
|
input [3:0] len,
|
||||||
|
input [2:0] size,
|
||||||
|
input [3:0] wstrb,
|
||||||
|
input [DATA_LEN-1:0] data,
|
||||||
|
|
||||||
|
output done
|
||||||
|
);
|
||||||
|
word_t stored_addr;
|
||||||
|
logic [3:0] stored_len;
|
||||||
|
logic [2:0] stored_size;
|
||||||
|
logic [3:0] stored_wstrb;
|
||||||
|
logic [DATA_LEN-1:0] stored_data;
|
||||||
|
|
||||||
|
ffen #(`XLEN) addr_store (.*, .d(addr), .en(call), .q(stored_addr));
|
||||||
|
ffen #(4) len_store (.*, .d(len), .en(call), .q(stored_len));
|
||||||
|
ffen #(3) size_store (.*, .d(size), .en(call), .q(stored_size));
|
||||||
|
ffen #(4) wstrb_store (.*, .d(wstrb), .en(call), .q(stored_wstrb));
|
||||||
|
ffen #(DATA_LEN) data_store (.*, .d(data), .en(call), .q(stored_data));
|
||||||
|
|
||||||
|
logic shift;
|
||||||
|
logic [3:0] data_cntr;
|
||||||
|
logic [DATA_LEN-1:0] data_select;
|
||||||
|
|
||||||
|
ffen #(4) cntr_ff (.*, .d(call ? len : data_cntr - 1) , .en(shift | call), .q(data_cntr));
|
||||||
|
assign data_select = call ? data : stored_data;
|
||||||
|
|
||||||
|
typedef enum bit [1:0] { DIDLE, DATA } data_state_t;
|
||||||
|
typedef enum bit [1:0] { AIDLE, ADDR } addr_state_t;
|
||||||
|
data_state_t cur_data_state;
|
||||||
|
data_state_t nxt_data_state;
|
||||||
|
addr_state_t cur_addr_state;
|
||||||
|
addr_state_t nxt_addr_state;
|
||||||
|
|
||||||
|
// TODO: check whether it's correct
|
||||||
|
assign done = axi.data_ok;
|
||||||
|
|
||||||
|
// data
|
||||||
|
always_comb begin
|
||||||
|
nxt_data_state = cur_data_state;
|
||||||
|
|
||||||
|
shift = 0;
|
||||||
|
|
||||||
|
axi.wstrb = call ? wstrb : stored_wstrb;
|
||||||
|
axi.wdata = data_select[data_cntr * 32 +: 32];
|
||||||
|
axi.wvalid = 0;
|
||||||
|
axi.wlast = (call ? len : data_cntr) == 0;
|
||||||
|
|
||||||
|
case (cur_data_state)
|
||||||
|
DIDLE: begin
|
||||||
|
if (call) begin
|
||||||
|
// axi.wstrb
|
||||||
|
// axi.wdata
|
||||||
|
axi.wvalid = 1'b1;
|
||||||
|
// axi.wlast
|
||||||
|
|
||||||
|
if (axi.wready) shift = 1'b1;
|
||||||
|
if (~axi.wlast | ~axi.wready)
|
||||||
|
nxt_data_state = DATA;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
DATA: begin
|
||||||
|
// axi.wstrb
|
||||||
|
// axi.wdata
|
||||||
|
axi.wvalid = 1'b1;
|
||||||
|
// axi.wlast
|
||||||
|
|
||||||
|
if (axi.wready) shift = 1'b1;
|
||||||
|
if (axi.wlast & axi.wready) nxt_data_state = DIDLE;
|
||||||
|
end
|
||||||
|
|
||||||
|
default: begin end
|
||||||
|
endcase
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
// addr
|
||||||
|
always_comb begin
|
||||||
|
nxt_addr_state = cur_addr_state;
|
||||||
|
|
||||||
|
axi.req = 0;
|
||||||
|
|
||||||
|
axi.addr = call ? addr : stored_addr;
|
||||||
|
axi.len = call ? len : stored_len;
|
||||||
|
axi.size = call ? size : stored_size;
|
||||||
|
|
||||||
|
case (cur_addr_state)
|
||||||
|
AIDLE: begin
|
||||||
|
if (call) begin
|
||||||
|
axi.req = 1'b1;
|
||||||
|
if (~axi.addr_ok) nxt_addr_state = ADDR;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
ADDR: begin
|
||||||
|
axi.req = 1'b1;
|
||||||
|
if (axi.addr_ok) nxt_addr_state = AIDLE;
|
||||||
|
end
|
||||||
|
|
||||||
|
default: begin end
|
||||||
|
endcase
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
always_ff @(posedge clk) begin
|
||||||
|
if (rst) begin
|
||||||
|
cur_data_state <= DIDLE;
|
||||||
|
cur_addr_state <= AIDLE;
|
||||||
|
end else begin
|
||||||
|
cur_data_state <= nxt_data_state;
|
||||||
|
cur_addr_state <= nxt_addr_state;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
@ -11,8 +11,8 @@ module DCache (
|
|||||||
// ============ Vars ============
|
// ============ Vars ============
|
||||||
// ==============================
|
// ==============================
|
||||||
|
|
||||||
DCTagRAM_t TagRAM0, TagRAM1, TagRAM2, TagRAM3;
|
DCTagRAM_t TagRAM0/*verilator split_var*/, TagRAM1/*verilator split_var*/, TagRAM2/*verilator split_var*/, TagRAM3/*verilator split_var*/;
|
||||||
DCDataRAM_t DataRAM0, DataRAM1, DataRAM2, DataRAM3;
|
DCDataRAM_t DataRAM0/*verilator split_var*/, DataRAM1/*verilator split_var*/, DataRAM2/*verilator split_var*/, DataRAM3/*verilator split_var*/;
|
||||||
|
|
||||||
(* RAM_STYLE="block" *)
|
(* RAM_STYLE="block" *)
|
||||||
logic [3:0] LRU[128];
|
logic [3:0] LRU[128];
|
||||||
@ -54,7 +54,7 @@ module DCache (
|
|||||||
assign hitway[1] = tag[1].valid & tag[1].tag == port.tag;
|
assign hitway[1] = tag[1].valid & tag[1].tag == port.tag;
|
||||||
assign hitway[2] = tag[2].valid & tag[2].tag == port.tag;
|
assign hitway[2] = tag[2].valid & tag[2].tag == port.tag;
|
||||||
assign hitway[3] = tag[3].valid & tag[3].tag == port.tag;
|
assign hitway[3] = tag[3].valid & tag[3].tag == port.tag;
|
||||||
|
|
||||||
assign port.hit = |{hitway};
|
assign port.hit = |{hitway};
|
||||||
assign port.hit_row = (hitway[0] ? data[0] : `DC_DATA_LENGTH'b0)
|
assign port.hit_row = (hitway[0] ? data[0] : `DC_DATA_LENGTH'b0)
|
||||||
| (hitway[1] ? data[1] : `DC_DATA_LENGTH'b0)
|
| (hitway[1] ? data[1] : `DC_DATA_LENGTH'b0)
|
||||||
@ -168,7 +168,7 @@ module DCache (
|
|||||||
tag_ram2 (.rst(rst), .addra(TagRAM2.addr), .clka(clk), .dina(TagRAM2.wdata), .douta(TagRAM2.rdata), .wea(TagRAM2.wen));
|
tag_ram2 (.rst(rst), .addra(TagRAM2.addr), .clka(clk), .dina(TagRAM2.wdata), .douta(TagRAM2.rdata), .wea(TagRAM2.wen));
|
||||||
bram #(.DATA_WIDTH(32-`DC_TAGL+2), .DATA_DEPTH(2 ** (`DC_TAGL-`DC_INDEXL)))
|
bram #(.DATA_WIDTH(32-`DC_TAGL+2), .DATA_DEPTH(2 ** (`DC_TAGL-`DC_INDEXL)))
|
||||||
tag_ram3 (.rst(rst), .addra(TagRAM3.addr), .clka(clk), .dina(TagRAM3.wdata), .douta(TagRAM3.rdata), .wea(TagRAM3.wen));
|
tag_ram3 (.rst(rst), .addra(TagRAM3.addr), .clka(clk), .dina(TagRAM3.wdata), .douta(TagRAM3.rdata), .wea(TagRAM3.wen));
|
||||||
|
|
||||||
bram #(.DATA_WIDTH(`DC_DATA_LENGTH), .DATA_DEPTH(2 ** (`DC_TAGL-`DC_INDEXL)))
|
bram #(.DATA_WIDTH(`DC_DATA_LENGTH), .DATA_DEPTH(2 ** (`DC_TAGL-`DC_INDEXL)))
|
||||||
data_ram0 (.rst(rst), .addra(DataRAM0.addr), .clka(clk), .dina(DataRAM0.wdata), .douta(DataRAM0.rdata), .wea(DataRAM0.wen));
|
data_ram0 (.rst(rst), .addra(DataRAM0.addr), .clka(clk), .dina(DataRAM0.wdata), .douta(DataRAM0.rdata), .wea(DataRAM0.wen));
|
||||||
bram #(.DATA_WIDTH(`DC_DATA_LENGTH), .DATA_DEPTH(2 ** (`DC_TAGL-`DC_INDEXL)))
|
bram #(.DATA_WIDTH(`DC_DATA_LENGTH), .DATA_DEPTH(2 ** (`DC_TAGL-`DC_INDEXL)))
|
||||||
|
@ -11,8 +11,8 @@ module ICache (
|
|||||||
// ============ Vars ============
|
// ============ Vars ============
|
||||||
// ==============================
|
// ==============================
|
||||||
|
|
||||||
ICTagRAM_t TagRAM0, TagRAM1, TagRAM2, TagRAM3;
|
ICTagRAM_t TagRAM0/*verilator split_var*/, TagRAM1/*verilator split_var*/, TagRAM2/*verilator split_var*/, TagRAM3/*verilator split_var*/;
|
||||||
ICDataRAM_t DataRAM0, DataRAM1, DataRAM2, DataRAM3;
|
ICDataRAM_t DataRAM0/*verilator split_var*/, DataRAM1/*verilator split_var*/, DataRAM2/*verilator split_var*/, DataRAM3/*verilator split_var*/;
|
||||||
|
|
||||||
(* RAM_STYLE="block" *)
|
(* RAM_STYLE="block" *)
|
||||||
logic [3:0] LRU[64];
|
logic [3:0] LRU[64];
|
||||||
@ -122,7 +122,7 @@ module ICache (
|
|||||||
assign DataRAM2.wdata = port.update_row;
|
assign DataRAM2.wdata = port.update_row;
|
||||||
assign DataRAM3.wdata = port.update_row;
|
assign DataRAM3.wdata = port.update_row;
|
||||||
|
|
||||||
bram #(.DATA_WIDTH(32-`IC_TAGL+1), .DATA_DEPTH(2 ** (`IC_TAGL-`IC_INDEXL)))
|
bram #(.DATA_WIDTH(32-`IC_TAGL+1), .DATA_DEPTH(2 ** (`IC_TAGL-`IC_INDEXL)))
|
||||||
tag_ram0 (.rst(rst), .addra(TagRAM0.addr), .clka(clk), .dina(TagRAM0.wdata), .douta(TagRAM0.rdata), .wea(TagRAM0.wen));
|
tag_ram0 (.rst(rst), .addra(TagRAM0.addr), .clka(clk), .dina(TagRAM0.wdata), .douta(TagRAM0.rdata), .wea(TagRAM0.wen));
|
||||||
bram #(.DATA_WIDTH(32-`IC_TAGL+1), .DATA_DEPTH(2 ** (`IC_TAGL-`IC_INDEXL)))
|
bram #(.DATA_WIDTH(32-`IC_TAGL+1), .DATA_DEPTH(2 ** (`IC_TAGL-`IC_INDEXL)))
|
||||||
tag_ram1 (.rst(rst), .addra(TagRAM1.addr), .clka(clk), .dina(TagRAM1.wdata), .douta(TagRAM1.rdata), .wea(TagRAM1.wen));
|
tag_ram1 (.rst(rst), .addra(TagRAM1.addr), .clka(clk), .dina(TagRAM1.wdata), .douta(TagRAM1.rdata), .wea(TagRAM1.wen));
|
||||||
|
1224
src/MU/MU.sv
1224
src/MU/MU.sv
File diff suppressed because it is too large
Load Diff
@ -125,15 +125,17 @@ interface CP0_i;
|
|||||||
logic cp0_in_kernel;
|
logic cp0_in_kernel;
|
||||||
logic cpu_tlbwi;
|
logic cpu_tlbwi;
|
||||||
logic cpu_tlbwr;
|
logic cpu_tlbwr;
|
||||||
logic cpu_tlbp;
|
logic cpu_c0_tlbp;
|
||||||
|
logic cpu_tlb_tlbp;
|
||||||
|
logic cpu_tlbr;
|
||||||
Random_t cp0_Random; // TLBWR
|
Random_t cp0_Random; // TLBWR
|
||||||
EntryHi_t cp0_EntryHi; // TLBWI + F/M(ASID)
|
EntryHi_t cp0_EntryHi; // TLBWI + F/M(ASID)
|
||||||
PageMask_t cp0_PageMask; // TLBWI
|
// PageMask_t cp0_PageMask; // TLBWI
|
||||||
EntryLo_t cp0_EntryLo1; // TLBWI
|
EntryLo_t cp0_EntryLo1; // TLBWI
|
||||||
EntryLo_t cp0_EntryLo0; // TLBWI
|
EntryLo_t cp0_EntryLo0; // TLBWI
|
||||||
Index_t cp0_Index; // TLBWI + TLBR
|
Index_t cp0_Index; // TLBWI + TLBR
|
||||||
EntryHi_t tlb_EntryHi;
|
EntryHi_t tlb_EntryHi;
|
||||||
PageMask_t tlb_PageMask;
|
// PageMask_t tlb_PageMask;
|
||||||
EntryLo_t tlb_EntryLo1;
|
EntryLo_t tlb_EntryLo1;
|
||||||
EntryLo_t tlb_EntryLo0;
|
EntryLo_t tlb_EntryLo0;
|
||||||
Index_t tlb_Index; // TLBP
|
Index_t tlb_Index; // TLBP
|
||||||
@ -150,15 +152,15 @@ interface CP0_i;
|
|||||||
input cp0_in_kernel,
|
input cp0_in_kernel,
|
||||||
input cpu_tlbwi,
|
input cpu_tlbwi,
|
||||||
input cpu_tlbwr,
|
input cpu_tlbwr,
|
||||||
input cpu_tlbp,
|
input cpu_tlb_tlbp,
|
||||||
input cp0_Random,
|
input cp0_Random,
|
||||||
input cp0_Index,
|
input cp0_Index,
|
||||||
input cp0_EntryHi,
|
input cp0_EntryHi,
|
||||||
input cp0_PageMask,
|
// input cp0_PageMask,
|
||||||
input cp0_EntryLo1,
|
input cp0_EntryLo1,
|
||||||
input cp0_EntryLo0,
|
input cp0_EntryLo0,
|
||||||
output tlb_EntryHi,
|
output tlb_EntryHi,
|
||||||
output tlb_PageMask,
|
// output tlb_PageMask,
|
||||||
output tlb_EntryLo1,
|
output tlb_EntryLo1,
|
||||||
output tlb_EntryLo0,
|
output tlb_EntryLo0,
|
||||||
output tlb_Index,
|
output tlb_Index,
|
||||||
@ -173,17 +175,16 @@ interface CP0_i;
|
|||||||
modport cp0(
|
modport cp0(
|
||||||
output cp0_K0,
|
output cp0_K0,
|
||||||
output cp0_in_kernel,
|
output cp0_in_kernel,
|
||||||
output cpu_tlbwi,
|
input cpu_c0_tlbp,
|
||||||
output cpu_tlbwr,
|
input cpu_tlbr,
|
||||||
output cpu_tlbp,
|
|
||||||
output cp0_Random,
|
output cp0_Random,
|
||||||
output cp0_Index,
|
output cp0_Index,
|
||||||
output cp0_EntryHi,
|
output cp0_EntryHi,
|
||||||
output cp0_PageMask,
|
// output cp0_PageMask,
|
||||||
output cp0_EntryLo1,
|
output cp0_EntryLo1,
|
||||||
output cp0_EntryLo0,
|
output cp0_EntryLo0,
|
||||||
input tlb_EntryHi,
|
input tlb_EntryHi,
|
||||||
input tlb_PageMask,
|
// input tlb_PageMask,
|
||||||
input tlb_EntryLo1,
|
input tlb_EntryLo1,
|
||||||
input tlb_EntryLo0,
|
input tlb_EntryLo0,
|
||||||
input tlb_Index
|
input tlb_Index
|
||||||
@ -191,7 +192,10 @@ interface CP0_i;
|
|||||||
modport cpu(
|
modport cpu(
|
||||||
output cpu_tlbwi,
|
output cpu_tlbwi,
|
||||||
output cpu_tlbwr,
|
output cpu_tlbwr,
|
||||||
output cpu_tlbp,
|
output cpu_c0_tlbp,
|
||||||
|
output cpu_tlb_tlbp,
|
||||||
|
output cpu_tlbr,
|
||||||
|
input cp0_in_kernel,
|
||||||
input tlb_iTLBRefill,
|
input tlb_iTLBRefill,
|
||||||
input tlb_iTLBInvalid,
|
input tlb_iTLBInvalid,
|
||||||
input tlb_iAddressError,
|
input tlb_iAddressError,
|
||||||
@ -200,5 +204,5 @@ interface CP0_i;
|
|||||||
input tlb_dTLBModified,
|
input tlb_dTLBModified,
|
||||||
input tlb_dAddressError
|
input tlb_dAddressError
|
||||||
);
|
);
|
||||||
|
|
||||||
endinterface
|
endinterface
|
||||||
|
@ -4,10 +4,11 @@
|
|||||||
`include "defines.svh"
|
`include "defines.svh"
|
||||||
|
|
||||||
// IC for I-Cache
|
// IC for I-Cache
|
||||||
`define IC_TAGL 11
|
`define IC_TAGL 11
|
||||||
`define IC_INDEXL 5
|
`define IC_INDEXL 5
|
||||||
`define IC_TAG_LENGTH 22 // Tag + Valid
|
`define IC_TAG_LENGTH 22 // Tag + Valid
|
||||||
`define IC_DATA_LENGTH 256 // 32Bytes
|
`define IC_DATA_LENGTH 256 // 32Bytes
|
||||||
|
`define IC_ROW_LENGTH (2 ** (`IC_INDEXL - 1) - 1)
|
||||||
|
|
||||||
typedef logic [`IC_DATA_LENGTH-1:0] ICData_t;
|
typedef logic [`IC_DATA_LENGTH-1:0] ICData_t;
|
||||||
typedef logic [32-`IC_TAGL-1:0] ICTagL_t;
|
typedef logic [32-`IC_TAGL-1:0] ICTagL_t;
|
||||||
@ -44,6 +45,7 @@ typedef struct packed {
|
|||||||
`define DC_INDEXL 4
|
`define DC_INDEXL 4
|
||||||
`define DC_TAG_LENGTH 23 // Tag + Valid + Dirty
|
`define DC_TAG_LENGTH 23 // Tag + Valid + Dirty
|
||||||
`define DC_DATA_LENGTH 128 // 16Bytes
|
`define DC_DATA_LENGTH 128 // 16Bytes
|
||||||
|
`define DC_ROW_LENGTH (2 ** (`DC_INDEXL - 1) - 1)
|
||||||
|
|
||||||
typedef logic [`DC_DATA_LENGTH-1:0] DCData_t;
|
typedef logic [`DC_DATA_LENGTH-1:0] DCData_t;
|
||||||
typedef logic [32-`DC_TAGL-1:0] DCTagL_t;
|
typedef logic [32-`DC_TAGL-1:0] DCTagL_t;
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
`ifndef DEFINES_SVH
|
`ifndef DEFINES_SVH
|
||||||
`define DEFINES_SVH
|
`define DEFINES_SVH
|
||||||
|
|
||||||
|
`define XLEN 32
|
||||||
|
|
||||||
`define PCRST 32'hBFC00000
|
`define PCRST 32'hBFC00000
|
||||||
`define Off_TRef 9'h000
|
`define Off_TRef 9'h000
|
||||||
`define Off_GExc 9'h180
|
`define Off_GExc 9'h180
|
||||||
@ -84,6 +86,7 @@ typedef enum logic [1:0] {
|
|||||||
URIGHT = 2'b10
|
URIGHT = 2'b10
|
||||||
} ALR_t;
|
} ALR_t;
|
||||||
|
|
||||||
|
`define CACHEOP_T_LEN 4
|
||||||
typedef struct packed {
|
typedef struct packed {
|
||||||
logic icache_op;
|
logic icache_op;
|
||||||
logic dcache_op;
|
logic dcache_op;
|
||||||
|
@ -73,8 +73,9 @@ module mycpu_top (
|
|||||||
|
|
||||||
InstFetch_i inst();
|
InstFetch_i inst();
|
||||||
Memory_i data();
|
Memory_i data();
|
||||||
|
|
||||||
CacheOp_i cache_op();
|
CacheOp_i cache_op();
|
||||||
|
CP0_i c0;
|
||||||
|
|
||||||
logic C0_int;
|
logic C0_int;
|
||||||
logic [4:0] C0_addr;
|
logic [4:0] C0_addr;
|
||||||
@ -114,7 +115,7 @@ module mycpu_top (
|
|||||||
logic c0_tlbp;
|
logic c0_tlbp;
|
||||||
|
|
||||||
|
|
||||||
AXI axi (
|
AXI axi (
|
||||||
.arid (arid),
|
.arid (arid),
|
||||||
.araddr (araddr),
|
.araddr (araddr),
|
||||||
.arlen (arlen),
|
.arlen (arlen),
|
||||||
@ -156,45 +157,23 @@ module mycpu_top (
|
|||||||
.bvalid(bvalid),
|
.bvalid(bvalid),
|
||||||
.bready(bready),
|
.bready(bready),
|
||||||
|
|
||||||
.inst (inst_axi.axi),
|
.axi_inst (inst_axi.axi),
|
||||||
.rdata(rdata_axi.axi),
|
.axi_rdata(rdata_axi.axi),
|
||||||
.wdata(wdata_axi.axi)
|
.axi_wdata(wdata_axi.axi)
|
||||||
);
|
);
|
||||||
|
|
||||||
MMU mmu (
|
MU mmu (
|
||||||
.clk (aclk),
|
.clk (aclk),
|
||||||
.rst (~aresetn),
|
.rst (~aresetn),
|
||||||
.ic (icache.mu),
|
.icache (icache.mu),
|
||||||
.dc (dcache.mu),
|
.dcache (dcache.mu),
|
||||||
.inst (inst.mu),
|
.instfetch (inst.mu),
|
||||||
.data (data.mu),
|
.memory (data.mu),
|
||||||
.cacheOp (cache_op.mu),
|
.cacheop (cache_op.mu),
|
||||||
.inst_axi (inst_axi.mu),
|
.axiread_inst (inst_axi.mu),
|
||||||
.rdata_axi (rdata_axi.mu),
|
.axiread_data (rdata_axi.mu),
|
||||||
.wdata_axi (wdata_axi.mu),
|
.axiwrite_data (wdata_axi.mu),
|
||||||
.K0 (K0),
|
.cp0 (c0.mu)
|
||||||
.in_kernel (in_kernel),
|
|
||||||
.tlbwi (tlb_tlbwi),
|
|
||||||
.tlbwr (tlb_tlbwr),
|
|
||||||
.tlbp (tlb_tlbp),
|
|
||||||
.c0_Random (c0_Random),
|
|
||||||
.c0_Index (c0_Index),
|
|
||||||
.c0_EntryHi (c0_EntryHi),
|
|
||||||
// .c0_PageMask (c0_PageMask),
|
|
||||||
.c0_EntryLo1 (c0_EntryLo1),
|
|
||||||
.c0_EntryLo0 (c0_EntryLo0),
|
|
||||||
.EntryHi (tlb_EntryHi),
|
|
||||||
// .PageMask (tlb_PageMask),
|
|
||||||
.EntryLo1 (tlb_EntryLo1),
|
|
||||||
.EntryLo0 (tlb_EntryLo0),
|
|
||||||
.Index (tlb_Index),
|
|
||||||
.iTLBRefill (iTLBRefill),
|
|
||||||
.iTLBInvalid (iTLBInvalid),
|
|
||||||
.iAddressError(iAddressError),
|
|
||||||
.dTLBRefill (dTLBRefill),
|
|
||||||
.dTLBInvalid (dTLBInvalid),
|
|
||||||
.dTLBModified (dTLBModified),
|
|
||||||
.dAddressError(dAddressError)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
ICache ICache (
|
ICache ICache (
|
||||||
@ -223,21 +202,7 @@ module mycpu_top (
|
|||||||
.EBase (C0_EBase),
|
.EBase (C0_EBase),
|
||||||
.ext_int (ext_int),
|
.ext_int (ext_int),
|
||||||
.interrupt (C0_int),
|
.interrupt (C0_int),
|
||||||
.tlbr (c0_tlbr),
|
.c0 (c0.cp0)
|
||||||
.tlbp (c0_tlbp),
|
|
||||||
.K0 (K0),
|
|
||||||
.in_kernel (in_kernel),
|
|
||||||
.Random (c0_Random),
|
|
||||||
.Index (c0_Index),
|
|
||||||
.EntryHi (c0_EntryHi),
|
|
||||||
// .PageMask (c0_PageMask),
|
|
||||||
.EntryLo1 (c0_EntryLo1),
|
|
||||||
.EntryLo0 (c0_EntryLo0),
|
|
||||||
.tlb_EntryHi (tlb_EntryHi),
|
|
||||||
// .tlb_PageMask(tlb_PageMask),
|
|
||||||
.tlb_EntryLo1(tlb_EntryLo1),
|
|
||||||
.tlb_EntryLo0(tlb_EntryLo0),
|
|
||||||
.tlb_Index (tlb_Index)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Datapath datapath (
|
Datapath datapath (
|
||||||
@ -247,19 +212,7 @@ module mycpu_top (
|
|||||||
.mem (data.cpu),
|
.mem (data.cpu),
|
||||||
.cache_op(cache_op.cpu),
|
.cache_op(cache_op.cpu),
|
||||||
|
|
||||||
.iTLBRefill (iTLBRefill),
|
.C0 (c0.cpu),
|
||||||
.iTLBInvalid (iTLBInvalid),
|
|
||||||
.iAddressError(iAddressError),
|
|
||||||
.dTLBRefill (dTLBRefill),
|
|
||||||
.dTLBInvalid (dTLBInvalid),
|
|
||||||
.dTLBModified (dTLBModified),
|
|
||||||
.dAddressError(dAddressError),
|
|
||||||
.tlb_tlbwi (tlb_tlbwi),
|
|
||||||
.tlb_tlbwr (tlb_tlbwr),
|
|
||||||
.tlb_tlbp (tlb_tlbp),
|
|
||||||
.c0_tlbr (c0_tlbr),
|
|
||||||
.c0_tlbp (c0_tlbp),
|
|
||||||
|
|
||||||
.C0_int (C0_int),
|
.C0_int (C0_int),
|
||||||
.C0_addr (C0_addr),
|
.C0_addr (C0_addr),
|
||||||
.C0_sel (C0_sel),
|
.C0_sel (C0_sel),
|
||||||
@ -270,7 +223,6 @@ module mycpu_top (
|
|||||||
.C0_ERETPC (C0_ERETPC),
|
.C0_ERETPC (C0_ERETPC),
|
||||||
.C0_Bev (C0_Bev),
|
.C0_Bev (C0_Bev),
|
||||||
.C0_EBase (C0_EBase),
|
.C0_EBase (C0_EBase),
|
||||||
.C0_kernel (in_kernel),
|
|
||||||
|
|
||||||
.debug_wb_pc (debug_wb_pc),
|
.debug_wb_pc (debug_wb_pc),
|
||||||
.debug_wb_rf_wen (debug_wb_rf_wen),
|
.debug_wb_rf_wen (debug_wb_rf_wen),
|
||||||
|
40
tools/ctrl2_maker.py
Normal file
40
tools/ctrl2_maker.py
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
from curses.ascii import isdigit
|
||||||
|
|
||||||
|
from zeroconf import instance_name_from_service_info
|
||||||
|
|
||||||
|
|
||||||
|
file_list = [('ectrl.txt', '.ECtrl'),
|
||||||
|
('exc.txt', ''),
|
||||||
|
('global.txt', ''),
|
||||||
|
('mctrl0.txt', '.MCtrl0'),
|
||||||
|
('mctrl1.txt', '.MCtrl1'),
|
||||||
|
('pcs.txt', ''),
|
||||||
|
('privilege.txt', ''),
|
||||||
|
('trap.txt', '.Trap'),
|
||||||
|
('wctrl.txt', '.WCtrl')]
|
||||||
|
mp = {}
|
||||||
|
inst_name = {}
|
||||||
|
for fi, subname in file_list:
|
||||||
|
with open(fi) as f:
|
||||||
|
lines = f.readlines()
|
||||||
|
title = lines[0].split()
|
||||||
|
items = [item.split() for item in lines[1:]]
|
||||||
|
for item in items:
|
||||||
|
for i in range(1, len(title)):
|
||||||
|
if title[i][-1].isdigit() and title[i] not in ['RS0', 'DP0', 'DP1']:
|
||||||
|
continue
|
||||||
|
if item[i] == '?':
|
||||||
|
continue
|
||||||
|
inst = item[0]
|
||||||
|
inst_name[inst] = ' '.join(item[len(title)+1:])
|
||||||
|
signal_name = 'ctrl' + subname + '.' + title[i]
|
||||||
|
if inst not in mp:
|
||||||
|
mp[inst] = [(signal_name, item[i])]
|
||||||
|
else:
|
||||||
|
mp[inst].append((signal_name, item[i]))
|
||||||
|
|
||||||
|
for inst in mp:
|
||||||
|
print(f'case {inst}: begin /* {inst_name[inst]} */')
|
||||||
|
for sig in mp[inst]:
|
||||||
|
print(f' {sig[0]} = {sig[1]}')
|
||||||
|
print('end')
|
@ -1,4 +1,4 @@
|
|||||||
with open('global.txt') as f:
|
with open('clo.txt') as f:
|
||||||
lines = f.readlines()
|
lines = f.readlines()
|
||||||
title = lines[0].split()
|
title = lines[0].split()
|
||||||
items = [x.split() for x in lines[1:]]
|
items = [x.split() for x in lines[1:]]
|
||||||
|
@ -74,11 +74,11 @@
|
|||||||
32'b011100???????????????00000000010 ? ? ? ? ? ? ? ? ? ? ? // MUL
|
32'b011100???????????????00000000010 ? ? ? ? ? ? ? ? ? ? ? // MUL
|
||||||
32'b100000?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // LB
|
32'b100000?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // LB
|
||||||
32'b100001?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // LH
|
32'b100001?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // LH
|
||||||
32'h100010?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // LWL
|
32'b100010?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // LWL
|
||||||
32'b100011?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // LW
|
32'b100011?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // LW
|
||||||
32'b100100?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // LBU
|
32'b100100?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // LBU
|
||||||
32'b100101?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // LHU
|
32'b100101?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // LHU
|
||||||
32'h100110?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // LWR
|
32'b100110?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // LWR
|
||||||
32'b101000?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // SB
|
32'b101000?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // SB
|
||||||
32'b101001?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // SH
|
32'b101001?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // SH
|
||||||
32'b101010?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // SWL
|
32'b101010?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // SWL
|
||||||
|
@ -74,11 +74,11 @@
|
|||||||
32'b011100???????????????00000000010 0 0 0 0 1 1 0 0 1 0 // MUL
|
32'b011100???????????????00000000010 0 0 0 0 1 1 0 0 1 0 // MUL
|
||||||
32'b100000?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // LB
|
32'b100000?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // LB
|
||||||
32'b100001?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // LH
|
32'b100001?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // LH
|
||||||
32'h100010?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // LWL
|
32'b100010?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // LWL
|
||||||
32'b100011?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // LW
|
32'b100011?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // LW
|
||||||
32'b100100?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // LBU
|
32'b100100?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // LBU
|
||||||
32'b100101?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // LHU
|
32'b100101?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // LHU
|
||||||
32'h100110?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // LWR
|
32'b100110?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // LWR
|
||||||
32'b101000?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // SB
|
32'b101000?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // SB
|
||||||
32'b101001?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // SH
|
32'b101001?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // SH
|
||||||
32'b101010?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // SWL
|
32'b101010?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // SWL
|
||||||
|
@ -74,11 +74,11 @@
|
|||||||
32'b011100???????????????00000000010 0 0 MUL? 1 0 ? PASST 0 0 0 MUL 0 1 0 // MUL
|
32'b011100???????????????00000000010 0 0 MUL? 1 0 ? PASST 0 0 0 MUL 0 1 0 // MUL
|
||||||
32'b100000?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LB
|
32'b100000?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LB
|
||||||
32'b100001?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LH
|
32'b100001?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LH
|
||||||
32'h100010?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LWL
|
32'b100010?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LWL
|
||||||
32'b100011?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LW
|
32'b100011?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LW
|
||||||
32'b100100?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LBU
|
32'b100100?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LBU
|
||||||
32'b100101?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LHU
|
32'b100101?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LHU
|
||||||
32'h100110?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LWR
|
32'b100110?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LWR
|
||||||
32'b101000?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // SB
|
32'b101000?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // SB
|
||||||
32'b101001?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // SH
|
32'b101001?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // SH
|
||||||
32'b101010?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // SWL
|
32'b101010?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // SWL
|
||||||
|
@ -74,11 +74,11 @@
|
|||||||
32'b011100???????????????00000000010 0 0 0 0 ? ? ? ? ? ? ? ? ? ? // MUL
|
32'b011100???????????????00000000010 0 0 0 0 ? ? ? ? ? ? ? ? ? ? // MUL
|
||||||
32'b100000?????????????????????????? 0 0 0 0 1 0 1 ALIGN 0 0 CNOP 0 0 0 // LB
|
32'b100000?????????????????????????? 0 0 0 0 1 0 1 ALIGN 0 0 CNOP 0 0 0 // LB
|
||||||
32'b100001?????????????????????????? 0 0 0 0 1 0 1 ALIGN 0 0 CNOP 0 0 0 // LH
|
32'b100001?????????????????????????? 0 0 0 0 1 0 1 ALIGN 0 0 CNOP 0 0 0 // LH
|
||||||
32'h100010?????????????????????????? 0 0 0 0 1 0 ? ULEFT 0 1 CNOP 0 0 0 // LWL
|
32'b100010?????????????????????????? 0 0 0 0 1 0 ? ULEFT 0 1 CNOP 0 0 0 // LWL
|
||||||
32'b100011?????????????????????????? 0 0 0 0 1 0 ? ALIGN 0 0 CNOP 0 0 0 // LW
|
32'b100011?????????????????????????? 0 0 0 0 1 0 ? ALIGN 0 0 CNOP 0 0 0 // LW
|
||||||
32'b100100?????????????????????????? 0 0 0 0 1 0 0 ALIGN 0 0 CNOP 0 0 0 // LBU
|
32'b100100?????????????????????????? 0 0 0 0 1 0 0 ALIGN 0 0 CNOP 0 0 0 // LBU
|
||||||
32'b100101?????????????????????????? 0 0 0 0 1 0 0 ALIGN 0 0 CNOP 0 0 0 // LHU
|
32'b100101?????????????????????????? 0 0 0 0 1 0 0 ALIGN 0 0 CNOP 0 0 0 // LHU
|
||||||
32'h100110?????????????????????????? 0 0 0 0 1 0 ? URIGHT 1 0 CNOP 0 0 0 // LWR
|
32'b100110?????????????????????????? 0 0 0 0 1 0 ? URIGHT 1 0 CNOP 0 0 0 // LWR
|
||||||
32'b101000?????????????????????????? 0 0 0 0 1 1 ? ALIGN 0 0 CNOP 0 0 0 // SB
|
32'b101000?????????????????????????? 0 0 0 0 1 1 ? ALIGN 0 0 CNOP 0 0 0 // SB
|
||||||
32'b101001?????????????????????????? 0 0 0 0 1 1 ? ALIGN 0 0 CNOP 0 0 0 // SH
|
32'b101001?????????????????????????? 0 0 0 0 1 1 ? ALIGN 0 0 CNOP 0 0 0 // SH
|
||||||
32'b101010?????????????????????????? 0 0 0 0 1 1 ? ULEFT 0 1 CNOP 0 0 0 // SWL
|
32'b101010?????????????????????????? 0 0 0 0 1 1 ? ULEFT 0 1 CNOP 0 0 0 // SWL
|
||||||
|
@ -74,11 +74,11 @@
|
|||||||
32'b011100???????????????00000000010 0 0 0 0 // MUL
|
32'b011100???????????????00000000010 0 0 0 0 // MUL
|
||||||
32'b100000?????????????????????????? 0 0 0 0 // LB
|
32'b100000?????????????????????????? 0 0 0 0 // LB
|
||||||
32'b100001?????????????????????????? 0 0 0 0 // LH
|
32'b100001?????????????????????????? 0 0 0 0 // LH
|
||||||
32'h100010?????????????????????????? 0 0 0 0 // LWL
|
32'b100010?????????????????????????? 0 0 0 0 // LWL
|
||||||
32'b100011?????????????????????????? 0 0 0 0 // LW
|
32'b100011?????????????????????????? 0 0 0 0 // LW
|
||||||
32'b100100?????????????????????????? 0 0 0 0 // LBU
|
32'b100100?????????????????????????? 0 0 0 0 // LBU
|
||||||
32'b100101?????????????????????????? 0 0 0 0 // LHU
|
32'b100101?????????????????????????? 0 0 0 0 // LHU
|
||||||
32'h100110?????????????????????????? 0 0 0 0 // LWR
|
32'b100110?????????????????????????? 0 0 0 0 // LWR
|
||||||
32'b101000?????????????????????????? 0 0 0 0 // SB
|
32'b101000?????????????????????????? 0 0 0 0 // SB
|
||||||
32'b101001?????????????????????????? 0 0 0 0 // SH
|
32'b101001?????????????????????????? 0 0 0 0 // SH
|
||||||
32'b101010?????????????????????????? 0 0 0 0 // SWL
|
32'b101010?????????????????????????? 0 0 0 0 // SWL
|
||||||
|
@ -74,11 +74,11 @@
|
|||||||
32'b011100???????????????00000000010 0 // MUL
|
32'b011100???????????????00000000010 0 // MUL
|
||||||
32'b100000?????????????????????????? 0 // LB
|
32'b100000?????????????????????????? 0 // LB
|
||||||
32'b100001?????????????????????????? 0 // LH
|
32'b100001?????????????????????????? 0 // LH
|
||||||
32'h100010?????????????????????????? 0 // LWL
|
32'b100010?????????????????????????? 0 // LWL
|
||||||
32'b100011?????????????????????????? 0 // LW
|
32'b100011?????????????????????????? 0 // LW
|
||||||
32'b100100?????????????????????????? 0 // LBU
|
32'b100100?????????????????????????? 0 // LBU
|
||||||
32'b100101?????????????????????????? 0 // LHU
|
32'b100101?????????????????????????? 0 // LHU
|
||||||
32'h100110?????????????????????????? 0 // LWR
|
32'b100110?????????????????????????? 0 // LWR
|
||||||
32'b101000?????????????????????????? 0 // SB
|
32'b101000?????????????????????????? 0 // SB
|
||||||
32'b101001?????????????????????????? 0 // SH
|
32'b101001?????????????????????????? 0 // SH
|
||||||
32'b101010?????????????????????????? 0 // SWL
|
32'b101010?????????????????????????? 0 // SWL
|
||||||
|
87
tools/test1.txt
Normal file
87
tools/test1.txt
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
000000 00000 ????? ????? ????? 000000
|
||||||
|
000000 ????? 00000 00000 00000 001000
|
||||||
|
000000 00000 00000 00000 ????? 001111
|
||||||
|
000000 00000 00000 ????? 00000 010000
|
||||||
|
000000 ????? 00000 00000 00000 010001
|
||||||
|
000000 00000 00000 ????? 00000 010010
|
||||||
|
000000 ????? 00000 00000 00000 010011
|
||||||
|
000000 ????? 00000 ????? 00000 001001
|
||||||
|
000000 ????? ????? 00000 00000 011000
|
||||||
|
000000 ????? ????? 00000 00000 011001
|
||||||
|
000000 ????? ????? 00000 00000 011010
|
||||||
|
000000 ????? ????? 00000 00000 011011
|
||||||
|
000000 00000 ????? ????? ????? 000010
|
||||||
|
000000 00000 ????? ????? ????? 000011
|
||||||
|
000000 ????? ????? ????? 00000 000100
|
||||||
|
000000 ????? ????? ????? 00000 000110
|
||||||
|
000000 ????? ????? ????? 00000 000111
|
||||||
|
000000 ????? ????? ????? 00000 001010
|
||||||
|
000000 ????? ????? ????? 00000 001011
|
||||||
|
000000 ????? ????? ????? 00000 100000
|
||||||
|
000000 ????? ????? ????? 00000 100001
|
||||||
|
000000 ????? ????? ????? 00000 100010
|
||||||
|
000000 ????? ????? ????? 00000 100011
|
||||||
|
000000 ????? ????? ????? 00000 100100
|
||||||
|
000000 ????? ????? ????? 00000 100101
|
||||||
|
000000 ????? ????? ????? 00000 100110
|
||||||
|
000000 ????? ????? ????? 00000 100111
|
||||||
|
000000 ????? ????? ????? 00000 101010
|
||||||
|
000000 ????? ????? ????? 00000 101011
|
||||||
|
000000 ????? ????? ????? ????? 001100
|
||||||
|
000000 ????? ????? ????? ????? 001101
|
||||||
|
000000 ????? ????? ????? ????? 110000
|
||||||
|
000000 ????? ????? ????? ????? 110001
|
||||||
|
000000 ????? ????? ????? ????? 110010
|
||||||
|
000000 ????? ????? ????? ????? 110011
|
||||||
|
000000 ????? ????? ????? ????? 110100
|
||||||
|
000000 ????? ????? ????? ????? 110110
|
||||||
|
000001 ????? 00000 ????? ????? ??????
|
||||||
|
000001 ????? 00001 ????? ????? ??????
|
||||||
|
000001 ????? 01000 ????? ????? ??????
|
||||||
|
000001 ????? 01001 ????? ????? ??????
|
||||||
|
000001 ????? 01010 ????? ????? ??????
|
||||||
|
000001 ????? 01011 ????? ????? ??????
|
||||||
|
000001 ????? 01100 ????? ????? ??????
|
||||||
|
000001 ????? 01110 ????? ????? ??????
|
||||||
|
000001 ????? 10000 ????? ????? ??????
|
||||||
|
000001 ????? 10001 ????? ????? ??????
|
||||||
|
000010 ????? ????? ????? ????? ??????
|
||||||
|
000011 ????? ????? ????? ????? ??????
|
||||||
|
000100 ????? ????? ????? ????? ??????
|
||||||
|
000101 ????? ????? ????? ????? ??????
|
||||||
|
000110 ????? 00000 ????? ????? ??????
|
||||||
|
000111 ????? 00000 ????? ????? ??????
|
||||||
|
001000 ????? ????? ????? ????? ??????
|
||||||
|
001001 ????? ????? ????? ????? ??????
|
||||||
|
001010 ????? ????? ????? ????? ??????
|
||||||
|
001011 ????? ????? ????? ????? ??????
|
||||||
|
001100 ????? ????? ????? ????? ??????
|
||||||
|
001101 ????? ????? ????? ????? ??????
|
||||||
|
001110 ????? ????? ????? ????? ??????
|
||||||
|
001111 00000 ????? ????? ????? ??????
|
||||||
|
010000 00000 ????? ????? 00000 000???
|
||||||
|
010000 00100 ????? ????? 00000 000???
|
||||||
|
010000 10000 00000 00000 00000 000001
|
||||||
|
010000 10000 00000 00000 00000 000010
|
||||||
|
010000 10000 00000 00000 00000 000110
|
||||||
|
010000 10000 00000 00000 00000 001000
|
||||||
|
010000 10000 00000 00000 00000 011000
|
||||||
|
011100 ????? ????? 00000 00000 000000
|
||||||
|
011100 ????? ????? 00000 00000 000001
|
||||||
|
011100 ????? ????? 00000 00000 000100
|
||||||
|
011100 ????? ????? 00000 00000 000101
|
||||||
|
011100 ????? ????? ????? 00000 000010
|
||||||
|
100000 ????? ????? ????? ????? ??????
|
||||||
|
100001 ????? ????? ????? ????? ??????
|
||||||
|
100010 ????? ????? ????? ????? ??????
|
||||||
|
100011 ????? ????? ????? ????? ??????
|
||||||
|
100100 ????? ????? ????? ????? ??????
|
||||||
|
100101 ????? ????? ????? ????? ??????
|
||||||
|
100110 ????? ????? ????? ????? ??????
|
||||||
|
101000 ????? ????? ????? ????? ??????
|
||||||
|
101001 ????? ????? ????? ????? ??????
|
||||||
|
101010 ????? ????? ????? ????? ??????
|
||||||
|
101011 ????? ????? ????? ????? ??????
|
||||||
|
101110 ????? ????? ????? ????? ??????
|
||||||
|
101111 ????? ????? ????? ????? ??????
|
||||||
|
110011 ????? ????? ????? ????? ??????
|
@ -74,11 +74,11 @@
|
|||||||
32'b011100???????????????00000000010 0 ? ? ? // MUL
|
32'b011100???????????????00000000010 0 ? ? ? // MUL
|
||||||
32'b100000?????????????????????????? 0 ? ? ? // LB
|
32'b100000?????????????????????????? 0 ? ? ? // LB
|
||||||
32'b100001?????????????????????????? 0 ? ? ? // LH
|
32'b100001?????????????????????????? 0 ? ? ? // LH
|
||||||
32'h100010?????????????????????????? 0 ? ? ? // LWL
|
32'b100010?????????????????????????? 0 ? ? ? // LWL
|
||||||
32'b100011?????????????????????????? 0 ? ? ? // LW
|
32'b100011?????????????????????????? 0 ? ? ? // LW
|
||||||
32'b100100?????????????????????????? 0 ? ? ? // LBU
|
32'b100100?????????????????????????? 0 ? ? ? // LBU
|
||||||
32'b100101?????????????????????????? 0 ? ? ? // LHU
|
32'b100101?????????????????????????? 0 ? ? ? // LHU
|
||||||
32'h100110?????????????????????????? 0 ? ? ? // LWR
|
32'b100110?????????????????????????? 0 ? ? ? // LWR
|
||||||
32'b101000?????????????????????????? 0 ? ? ? // SB
|
32'b101000?????????????????????????? 0 ? ? ? // SB
|
||||||
32'b101001?????????????????????????? 0 ? ? ? // SH
|
32'b101001?????????????????????????? 0 ? ? ? // SH
|
||||||
32'b101010?????????????????????????? 0 ? ? ? // SWL
|
32'b101010?????????????????????????? 0 ? ? ? // SWL
|
||||||
|
@ -74,11 +74,11 @@
|
|||||||
32'b011100???????????????00000000010 0 1 RD 0 0 // MUL
|
32'b011100???????????????00000000010 0 1 RD 0 0 // MUL
|
||||||
32'b100000?????????????????????????? 0 1 RT 1 ? // LB
|
32'b100000?????????????????????????? 0 1 RT 1 ? // LB
|
||||||
32'b100001?????????????????????????? 0 1 RT 1 ? // LH
|
32'b100001?????????????????????????? 0 1 RT 1 ? // LH
|
||||||
32'h100010?????????????????????????? 0 1 RT 1 ? // LWL
|
32'b100010?????????????????????????? 0 1 RT 1 ? // LWL
|
||||||
32'b100011?????????????????????????? 0 1 RT 1 ? // LW
|
32'b100011?????????????????????????? 0 1 RT 1 ? // LW
|
||||||
32'b100100?????????????????????????? 0 1 RT 1 ? // LBU
|
32'b100100?????????????????????????? 0 1 RT 1 ? // LBU
|
||||||
32'b100101?????????????????????????? 0 1 RT 1 ? // LHU
|
32'b100101?????????????????????????? 0 1 RT 1 ? // LHU
|
||||||
32'h100110?????????????????????????? 0 1 RT 1 ? // LWR
|
32'b100110?????????????????????????? 0 1 RT 1 ? // LWR
|
||||||
32'b101000?????????????????????????? 0 0 ? ? ? // SB
|
32'b101000?????????????????????????? 0 0 ? ? ? // SB
|
||||||
32'b101001?????????????????????????? 0 0 ? ? ? // SH
|
32'b101001?????????????????????????? 0 0 ? ? ? // SH
|
||||||
32'b101010?????????????????????????? 0 0 ? ? ? // SWL
|
32'b101010?????????????????????????? 0 0 ? ? ? // SWL
|
||||||
|
Loading…
Reference in New Issue
Block a user