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
|
||||
|
||||
[src/**/*.{sv,svh}]
|
||||
[**/*.{sv,svh}]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
@ -8,10 +8,18 @@ end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[Makefile]
|
||||
[sim/Makefile]
|
||||
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
|
||||
indent_style = tab
|
||||
indent_size = 8
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -2,4 +2,5 @@ vivado.log
|
||||
vivado.jou
|
||||
.library_mapping.xml
|
||||
.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,
|
||||
|
||||
// MMU
|
||||
input logic tlbr,
|
||||
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_i.cp0 c0
|
||||
);
|
||||
|
||||
CP0_REGS_t rf_cp0;
|
||||
CP0_REGS_t rf_cp0/*verilator split_var*/;
|
||||
logic count_lo;
|
||||
|
||||
// int comb logic
|
||||
@ -168,7 +156,7 @@ module CP0 (
|
||||
9: rf_cp0.Count = wdata;
|
||||
8: rf_cp0.BadVAddr = wdata;
|
||||
// 7: rf_cp0.HWREna = wdata;
|
||||
6: begin
|
||||
6: begin
|
||||
rf_cp0.Wired.Wired = wdata[2:0];
|
||||
rf_cp0.Random.Random = 3'b111;
|
||||
end
|
||||
@ -197,25 +185,25 @@ module CP0 (
|
||||
endcase
|
||||
end
|
||||
|
||||
if (tlbr) begin
|
||||
rf_cp0.EntryHi.VPN2 = tlb_EntryHi.VPN2;
|
||||
rf_cp0.EntryHi.ASID = tlb_EntryHi.ASID;
|
||||
if (c0.cpu_tlbr) begin
|
||||
rf_cp0.EntryHi.VPN2 = c0.tlb_EntryHi.VPN2;
|
||||
rf_cp0.EntryHi.ASID = c0.tlb_EntryHi.ASID;
|
||||
// rf_cp0.PageMask.Mask = tlb_PageMask.Mask;
|
||||
rf_cp0.EntryLo0.PFN = tlb_EntryLo0.PFN;
|
||||
rf_cp0.EntryLo0.C = tlb_EntryLo0.C;
|
||||
rf_cp0.EntryLo0.D = tlb_EntryLo0.D;
|
||||
rf_cp0.EntryLo0.V = tlb_EntryLo0.V;
|
||||
rf_cp0.EntryLo0.G = tlb_EntryLo0.G;
|
||||
rf_cp0.EntryLo1.PFN = tlb_EntryLo1.PFN;
|
||||
rf_cp0.EntryLo1.C = tlb_EntryLo1.C;
|
||||
rf_cp0.EntryLo1.D = tlb_EntryLo1.D;
|
||||
rf_cp0.EntryLo1.V = tlb_EntryLo1.V;
|
||||
rf_cp0.EntryLo1.G = tlb_EntryLo1.G;
|
||||
rf_cp0.EntryLo0.PFN = c0.tlb_EntryLo0.PFN;
|
||||
rf_cp0.EntryLo0.C = c0.tlb_EntryLo0.C;
|
||||
rf_cp0.EntryLo0.D = c0.tlb_EntryLo0.D;
|
||||
rf_cp0.EntryLo0.V = c0.tlb_EntryLo0.V;
|
||||
rf_cp0.EntryLo0.G = c0.tlb_EntryLo0.G;
|
||||
rf_cp0.EntryLo1.PFN = c0.tlb_EntryLo1.PFN;
|
||||
rf_cp0.EntryLo1.C = c0.tlb_EntryLo1.C;
|
||||
rf_cp0.EntryLo1.D = c0.tlb_EntryLo1.D;
|
||||
rf_cp0.EntryLo1.V = c0.tlb_EntryLo1.V;
|
||||
rf_cp0.EntryLo1.G = c0.tlb_EntryLo1.G;
|
||||
end
|
||||
|
||||
if (tlbp) begin
|
||||
rf_cp0.Index.P = tlb_Index.P;
|
||||
rf_cp0.Index.Index = tlb_Index.Index;
|
||||
if (c0.cpu_c0_tlbp) begin
|
||||
rf_cp0.Index.P = c0.tlb_Index.P;
|
||||
rf_cp0.Index.Index = c0.tlb_Index.Index;
|
||||
end
|
||||
|
||||
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 EBase = rf_cp0.EBase[31:12];
|
||||
|
||||
assign K0 = rf_cp0.Config.K0;
|
||||
assign Random = rf_cp0.Random;
|
||||
assign Index = rf_cp0.Index;
|
||||
assign EntryHi = rf_cp0.EntryHi;
|
||||
assign c0.cp0_K0 = rf_cp0.Config.K0;
|
||||
assign c0.cp0_Random = rf_cp0.Random;
|
||||
assign c0.cp0_Index = rf_cp0.Index;
|
||||
assign c0.cp0_EntryHi = rf_cp0.EntryHi;
|
||||
// assign PageMask = rf_cp0.PageMask;
|
||||
assign EntryLo1 = rf_cp0.EntryLo1;
|
||||
assign EntryLo0 = rf_cp0.EntryLo0;
|
||||
assign c0.cp0_EntryLo1 = rf_cp0.EntryLo1;
|
||||
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
|
||||
|
@ -1,35 +1,34 @@
|
||||
`include "defines.svh"
|
||||
|
||||
module ALU(
|
||||
input word_t a, b,
|
||||
input ALUCtrl_t aluctrl,
|
||||
output word_t aluout,
|
||||
output logic overflow);
|
||||
input word_t a, b,
|
||||
input ALUCtrl_t aluctrl,
|
||||
output word_t aluout,
|
||||
output logic overflow
|
||||
);
|
||||
|
||||
wire logic alt = aluctrl.alt;
|
||||
wire logic alt = aluctrl.alt;
|
||||
|
||||
wire logic [4:0] sa = a[4:0];
|
||||
wire logic ex = alt & b[31];
|
||||
wire word_t sl = b << sa;
|
||||
/* verilator lint_off WIDTH */
|
||||
wire word_t sr = {{31{ex}}, b} >> sa;
|
||||
/* verilator lint_on WIDTH */
|
||||
|
||||
wire word_t b2 = alt ? ~b : b;
|
||||
wire word_t sum;
|
||||
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_on WIDTH */
|
||||
assign aluout = (aluctrl.f_sl ? sl : 32'b0)
|
||||
| (aluctrl.f_sr ? sr : 32'b0)
|
||||
| (aluctrl.f_add ? sum : 32'b0)
|
||||
| (aluctrl.f_and ? a & b : 32'b0)
|
||||
| (aluctrl.f_or ? alt ? ~(a | b) : a | b : 32'b0)
|
||||
| (aluctrl.f_xor ? a ^ b : 32'b0)
|
||||
| (aluctrl.f_slt ? {31'b0, lt } : 32'b0)
|
||||
| (aluctrl.f_sltu ? {31'b0, ltu} : 32'b0)
|
||||
| (aluctrl.f_mova ? a : 32'b0);
|
||||
assign overflow = lt ^ sum[31];
|
||||
wire logic [4:0] sa = a[4:0];
|
||||
wire logic ex = alt & b[31];
|
||||
wire word_t sl = b << sa;
|
||||
/* verilator lint_off WIDTH */
|
||||
wire word_t sr = {{31{ex}}, b} >> sa;
|
||||
/* verilator lint_on WIDTH */
|
||||
wire word_t b2 = alt ? ~b : b;
|
||||
wire word_t sum;
|
||||
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_on WIDTH */
|
||||
assign aluout = (aluctrl.f_sl ? sl : 32'b0)
|
||||
| (aluctrl.f_sr ? sr : 32'b0)
|
||||
| (aluctrl.f_add ? sum : 32'b0)
|
||||
| (aluctrl.f_and ? a & b : 32'b0)
|
||||
| (aluctrl.f_or ? alt ? ~(a | b) : a | b : 32'b0)
|
||||
| (aluctrl.f_xor ? a ^ b : 32'b0)
|
||||
| (aluctrl.f_slt ? {31'b0, lt } : 32'b0)
|
||||
| (aluctrl.f_sltu ? {31'b0, ltu} : 32'b0)
|
||||
| (aluctrl.f_mova ? a : 32'b0);
|
||||
assign overflow = lt ^ sum[31];
|
||||
endmodule
|
||||
|
@ -5,7 +5,7 @@ module Controller (
|
||||
input logic eq,
|
||||
input logic ltz,
|
||||
input word_t rt,
|
||||
output Ctrl_t ctrl,
|
||||
output Ctrl_t ctrl/*verilator split_var*/,
|
||||
output word_t imm,
|
||||
output logic [4:0] sa
|
||||
);
|
||||
|
@ -10,20 +10,9 @@ module Datapath (
|
||||
InstFetch_i.cpu fetch,
|
||||
Memory_i.cpu mem,
|
||||
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_i.cpu C0,
|
||||
input logic C0_int,
|
||||
output logic [4:0] C0_addr,
|
||||
output logic [2:0] C0_sel,
|
||||
@ -34,7 +23,6 @@ module Datapath (
|
||||
input word_t C0_ERETPC,
|
||||
input logic C0_Bev,
|
||||
input logic [19:0] C0_EBase,
|
||||
input logic C0_kernel,
|
||||
|
||||
//debug interface
|
||||
output wire [31:0] debug_wb_pc,
|
||||
@ -52,12 +40,12 @@ module Datapath (
|
||||
|
||||
logic rstD, rstM;
|
||||
|
||||
PF_t PF;
|
||||
F_t F;
|
||||
D_t D;
|
||||
E_t E;
|
||||
M_t M;
|
||||
W_t W;
|
||||
PF_t PF/*verilator split_var*/;
|
||||
F_t F/*verilator split_var*/;
|
||||
D_t D/*verilator split_var*/;
|
||||
E_t E/*verilator split_var*/;
|
||||
M_t M/*verilator split_var*/;
|
||||
W_t W/*verilator split_var*/;
|
||||
|
||||
// Pre Fetch
|
||||
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.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 //
|
||||
@ -342,7 +330,7 @@ module Datapath (
|
||||
|
||||
.vinA(fetch.data_ok | F.ExcValid),
|
||||
.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]),
|
||||
.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_AddressError
|
||||
| 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_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
|
||||
@ -479,7 +467,7 @@ module Datapath (
|
||||
| D_IB_AddressError
|
||||
| D.IB.SYSCALL | D.IB.BREAK | D.IB.ERET
|
||||
| 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_REFILL = D_IB_valid & D.IB_pc[1:0] == 2'b00 & D_IB_TLBRefill;
|
||||
// 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
|
||||
// Not Arith -> LWL/LWR
|
||||
| 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
|
||||
// Hazards Related to the TLB
|
||||
| D.IA.MCtrl0.C0W & D.IB.MCtrl1.TLBR & D.IA.MCtrl0.C0D == C0_INDEX
|
||||
@ -787,7 +784,7 @@ module Datapath (
|
||||
E.en,
|
||||
E.I1.ECtrl
|
||||
);
|
||||
ffenrc #(14) E_I1_MCtrl_ff (
|
||||
ffenrc #(15) E_I1_MCtrl_ff (
|
||||
clk,
|
||||
rst | rstM,
|
||||
D.I1.MCtrl,
|
||||
@ -927,15 +924,15 @@ module Datapath (
|
||||
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 E_I1_ADDR = E_I1_ForwardS + E.I1.imm;
|
||||
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[2] ? {E_I1_ADDR[32-`DC_INDEXL-1:0], `DC_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 cache_op = E.I1.MCtrl.CACHE_OP;
|
||||
assign mem.addr = |E.I1.MCtrl.ALR ? {E_I1_ADDR[31:2], 2'b0}
|
||||
: (~cache_op.op.icache_op & ~cache_op.op.dcache_op | ~cache_op.op.index_or_hit) ? E_I1_ADDR
|
||||
: 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};
|
||||
assign mem.size = {E.I1.MCtrl.SZ[1], E.I1.MCtrl.SZ[0] & ~E.I1.MCtrl.SZ[1]};
|
||||
assign cache_op.op = E.I1.MCtrl.CACHE_OP;
|
||||
|
||||
assign E.en = E_go & M.en;
|
||||
assign E_go = ~mem.req | mem.addr_ok;
|
||||
@ -1087,7 +1084,7 @@ module Datapath (
|
||||
M.en,
|
||||
M.I1.ALUOut
|
||||
);
|
||||
ffenrc #(14) M_I1_MCtrl_ff (
|
||||
ffenrc #(15) M_I1_MCtrl_ff (
|
||||
clk,
|
||||
rst | rstM,
|
||||
E.I1.MCtrl,
|
||||
@ -1124,7 +1121,7 @@ module Datapath (
|
||||
);
|
||||
myBuffer0 #(4) dExc_buffer (
|
||||
clk, rst,
|
||||
{dTLBRefill, dTLBInvalid, dTLBModified, dAddressError},
|
||||
{C0.tlb_dTLBRefill, C0.tlb_dTLBInvalid, C0.tlb_dTLBModified, C0.tlb_dAddressError},
|
||||
dTLBExcValid,
|
||||
{dTLBRefillB, dTLBInvalidB, dTLBModifiedB, dAddressErrorB}
|
||||
);
|
||||
@ -1235,10 +1232,10 @@ module Datapath (
|
||||
assign C0_wdata = M_I0_ForwardT;
|
||||
|
||||
// M.I1.MEM
|
||||
assign tlb_tlbwi = M.I1.MCtrl.TLBWI;
|
||||
assign tlb_tlbwr = M.I1.MCtrl.TLBWR;
|
||||
assign c0_tlbr = M.I1.MCtrl.TLBR;
|
||||
assign c0_tlbp = M.I1.MCtrl.TLBP & M.en;
|
||||
assign C0.cpu_tlbwi = M.I1.MCtrl.TLBWI;
|
||||
assign C0.cpu_tlbwr = M.I1.MCtrl.TLBWR;
|
||||
assign C0.cpu_tlbr = M.I1.MCtrl.TLBR;
|
||||
assign C0.cpu_c0_tlbp = M.I1.MCtrl.TLBP & M.en;
|
||||
assign mem.wr = M.I1.MCtrl.MWR;
|
||||
memoutput M_I1_memoutput (
|
||||
.addr (M.I1.ALUOut[1:0]),
|
||||
|
@ -1,4 +1,5 @@
|
||||
module addr_virt_to_phy (
|
||||
input logic [ 2:0] K0,
|
||||
input word_t virt_addr,
|
||||
input logic [19:0] tlb_addr,
|
||||
input logic tlb_hit,
|
||||
|
@ -14,11 +14,11 @@ module bram #(
|
||||
|
||||
for(genvar i = 0; i < DATA_DEPTH; i++)
|
||||
initial ram[i] = 0;
|
||||
|
||||
|
||||
always_ff @(posedge clka) begin
|
||||
if (~rst) begin
|
||||
if(wea) ram[addra] <= dina;
|
||||
douta <= ~wea ? ram[addra] : dina;
|
||||
end
|
||||
end
|
||||
endmodule
|
||||
endmodule
|
||||
|
142
src/MU/AXI.sv
142
src/MU/AXI.sv
@ -1,48 +1,48 @@
|
||||
module AXI (
|
||||
output wire [ 3:0] arid,
|
||||
output wire [31:0] araddr,
|
||||
output wire [ 3:0] arlen,
|
||||
output wire [ 2:0] arsize,
|
||||
output wire [ 1:0] arburst,
|
||||
output wire [ 1:0] arlock,
|
||||
output wire [ 3:0] arcache,
|
||||
output wire [ 2:0] arprot,
|
||||
output wire arvalid,
|
||||
input wire arready,
|
||||
output wire logic [ 3:0] arid,
|
||||
output wire logic [31:0] araddr,
|
||||
output wire logic [ 3:0] arlen,
|
||||
output wire logic [ 2:0] arsize,
|
||||
output wire logic [ 1:0] arburst,
|
||||
output wire logic [ 1:0] arlock,
|
||||
output wire logic [ 3:0] arcache,
|
||||
output wire logic [ 2:0] arprot,
|
||||
output wire logic arvalid,
|
||||
input wire logic arready,
|
||||
|
||||
input wire [ 3:0] rid,
|
||||
input wire [31:0] rdata,
|
||||
input wire [ 1:0] rresp,
|
||||
input wire rlast,
|
||||
input wire rvalid,
|
||||
output wire rready,
|
||||
input wire logic [ 3:0] rid,
|
||||
input wire logic [31:0] rdata,
|
||||
input wire logic [ 1:0] rresp,
|
||||
input wire logic rlast,
|
||||
input wire logic rvalid,
|
||||
output wire logic rready,
|
||||
|
||||
output wire [ 3:0] awid,
|
||||
output wire [31:0] awaddr,
|
||||
output wire [ 3:0] awlen,
|
||||
output wire [ 2:0] awsize,
|
||||
output wire [ 1:0] awburst,
|
||||
output wire [ 1:0] awlock,
|
||||
output wire [ 3:0] awcache,
|
||||
output wire [ 2:0] awprot,
|
||||
output wire awvalid,
|
||||
input wire awready,
|
||||
output wire logic [ 3:0] awid,
|
||||
output wire logic [31:0] awaddr,
|
||||
output wire logic [ 3:0] awlen,
|
||||
output wire logic [ 2:0] awsize,
|
||||
output wire logic [ 1:0] awburst,
|
||||
output wire logic [ 1:0] awlock,
|
||||
output wire logic [ 3:0] awcache,
|
||||
output wire logic [ 2:0] awprot,
|
||||
output wire logic awvalid,
|
||||
input wire logic awready,
|
||||
|
||||
output wire [ 3:0] wid,
|
||||
output wire [31:0] wdata,
|
||||
output wire [ 3:0] wstrb,
|
||||
output wire wlast,
|
||||
output wire wvalid,
|
||||
input wire wready,
|
||||
output wire logic [ 3:0] wid,
|
||||
output wire logic [31:0] wdata,
|
||||
output wire logic [ 3:0] wstrb,
|
||||
output wire logic wlast,
|
||||
output wire logic wvalid,
|
||||
input wire logic wready,
|
||||
|
||||
input wire [3:0] bid,
|
||||
input wire [1:0] bresp,
|
||||
input wire bvalid,
|
||||
output wire bready,
|
||||
input wire logic [3:0] bid,
|
||||
input wire logic [1:0] bresp,
|
||||
input wire logic bvalid,
|
||||
output wire logic bready,
|
||||
|
||||
AXIRead_i.axi inst,
|
||||
AXIRead_i.axi rdata,
|
||||
AXIWrite_i.axi wdata
|
||||
AXIRead_i.axi axi_inst,
|
||||
AXIRead_i.axi axi_rdata,
|
||||
AXIWrite_i.axi axi_wdata
|
||||
);
|
||||
|
||||
// ==============================
|
||||
@ -50,19 +50,19 @@ module AXI (
|
||||
// ==============================
|
||||
|
||||
always_comb begin
|
||||
inst.rdata = rdata;
|
||||
rdata.rdata = rdata;
|
||||
axi_inst.rdata = rdata;
|
||||
axi_rdata.rdata = rdata;
|
||||
|
||||
if (rid == 0) begin
|
||||
inst.rvalid = rvalid;
|
||||
inst.data_ok = rlast;
|
||||
rdata.rvalid = 1'b0;
|
||||
rdata.data_ok = 1'b0;
|
||||
axi_inst.rvalid = rvalid;
|
||||
axi_inst.data_ok = rlast;
|
||||
axi_rdata.rvalid = 1'b0;
|
||||
axi_rdata.data_ok = 1'b0;
|
||||
end else begin
|
||||
rdata.rvalid = rvalid;
|
||||
rdata.data_ok = rlast;
|
||||
inst.rvalid = 1'b0;
|
||||
inst.data_ok = 1'b0;
|
||||
axi_rdata.rvalid = rvalid;
|
||||
axi_rdata.data_ok = rlast;
|
||||
axi_inst.rvalid = 1'b0;
|
||||
axi_inst.data_ok = 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
@ -79,22 +79,22 @@ module AXI (
|
||||
// Burst
|
||||
arburst = 2'b10; // Wrap
|
||||
|
||||
arvalid = rdata.req | inst.req;
|
||||
rdata.addr_ok = arready;
|
||||
if (rdata.req) begin
|
||||
arvalid = axi_rdata.req | axi_inst.req;
|
||||
axi_rdata.addr_ok = arready;
|
||||
if (axi_rdata.req) begin
|
||||
arid = 4'b0001;
|
||||
arprot = 3'b001;
|
||||
araddr = rdata.addr;
|
||||
arlen = rdata.len;
|
||||
arsize = rdata.size;
|
||||
inst.addr_ok = 1'b0;
|
||||
araddr = axi_rdata.addr;
|
||||
arlen = axi_rdata.len;
|
||||
arsize = axi_rdata.size;
|
||||
axi_inst.addr_ok = 1'b0;
|
||||
end else begin
|
||||
arid = 4'b0000;
|
||||
arprot = 3'b101;
|
||||
araddr = inst.addr;
|
||||
arlen = inst.len;
|
||||
arsize = inst.size;
|
||||
inst.addr_ok = arready;
|
||||
araddr = axi_inst.addr;
|
||||
arlen = axi_inst.len;
|
||||
arsize = axi_inst.size;
|
||||
axi_inst.addr_ok = arready;
|
||||
end
|
||||
|
||||
end
|
||||
@ -103,15 +103,15 @@ module AXI (
|
||||
// ======= Write Request ========
|
||||
// ==============================
|
||||
|
||||
assign wdata.data_ok = bvalid;
|
||||
assign wdata.wready = wready;
|
||||
assign axi_wdata.data_ok = bvalid;
|
||||
assign axi_wdata.wready = wready;
|
||||
|
||||
always_comb begin
|
||||
wid = 4'b1;
|
||||
wdata = wdata.wdata;
|
||||
wstrb = wdata.wstrb;
|
||||
wlast = wdata.wlast;
|
||||
wvalid = wdata.wvalid;
|
||||
wdata = axi_wdata.wdata;
|
||||
wstrb = axi_wdata.wstrb;
|
||||
wlast = axi_wdata.wlast;
|
||||
wvalid = axi_wdata.wvalid;
|
||||
end
|
||||
|
||||
always_comb begin
|
||||
@ -126,11 +126,11 @@ module AXI (
|
||||
awid = 4'b1;
|
||||
awprot = 3'b001;
|
||||
|
||||
awvalid = wdata.req;
|
||||
awaddr = wdata.addr;
|
||||
awlen = wdata.len;
|
||||
awsize = wdata.size;
|
||||
wdata.addr_ok = awready;
|
||||
awvalid = axi_wdata.req;
|
||||
awaddr = axi_wdata.addr;
|
||||
awlen = axi_wdata.len;
|
||||
awsize = axi_wdata.size;
|
||||
axi_wdata.addr_ok = awready;
|
||||
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 ============
|
||||
// ==============================
|
||||
|
||||
DCTagRAM_t TagRAM0, TagRAM1, TagRAM2, TagRAM3;
|
||||
DCDataRAM_t DataRAM0, DataRAM1, DataRAM2, DataRAM3;
|
||||
DCTagRAM_t TagRAM0/*verilator split_var*/, TagRAM1/*verilator split_var*/, TagRAM2/*verilator split_var*/, TagRAM3/*verilator split_var*/;
|
||||
DCDataRAM_t DataRAM0/*verilator split_var*/, DataRAM1/*verilator split_var*/, DataRAM2/*verilator split_var*/, DataRAM3/*verilator split_var*/;
|
||||
|
||||
(* RAM_STYLE="block" *)
|
||||
logic [3:0] LRU[128];
|
||||
@ -54,7 +54,7 @@ module DCache (
|
||||
assign hitway[1] = tag[1].valid & tag[1].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 port.hit = |{hitway};
|
||||
assign port.hit_row = (hitway[0] ? data[0] : `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));
|
||||
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));
|
||||
|
||||
|
||||
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));
|
||||
bram #(.DATA_WIDTH(`DC_DATA_LENGTH), .DATA_DEPTH(2 ** (`DC_TAGL-`DC_INDEXL)))
|
||||
|
@ -11,8 +11,8 @@ module ICache (
|
||||
// ============ Vars ============
|
||||
// ==============================
|
||||
|
||||
ICTagRAM_t TagRAM0, TagRAM1, TagRAM2, TagRAM3;
|
||||
ICDataRAM_t DataRAM0, DataRAM1, DataRAM2, DataRAM3;
|
||||
ICTagRAM_t TagRAM0/*verilator split_var*/, TagRAM1/*verilator split_var*/, TagRAM2/*verilator split_var*/, TagRAM3/*verilator split_var*/;
|
||||
ICDataRAM_t DataRAM0/*verilator split_var*/, DataRAM1/*verilator split_var*/, DataRAM2/*verilator split_var*/, DataRAM3/*verilator split_var*/;
|
||||
|
||||
(* RAM_STYLE="block" *)
|
||||
logic [3:0] LRU[64];
|
||||
@ -122,7 +122,7 @@ module ICache (
|
||||
assign DataRAM2.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));
|
||||
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));
|
||||
|
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 cpu_tlbwi;
|
||||
logic cpu_tlbwr;
|
||||
logic cpu_tlbp;
|
||||
logic cpu_c0_tlbp;
|
||||
logic cpu_tlb_tlbp;
|
||||
logic cpu_tlbr;
|
||||
Random_t cp0_Random; // TLBWR
|
||||
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_EntryLo0; // TLBWI
|
||||
Index_t cp0_Index; // TLBWI + TLBR
|
||||
EntryHi_t tlb_EntryHi;
|
||||
PageMask_t tlb_PageMask;
|
||||
// PageMask_t tlb_PageMask;
|
||||
EntryLo_t tlb_EntryLo1;
|
||||
EntryLo_t tlb_EntryLo0;
|
||||
Index_t tlb_Index; // TLBP
|
||||
@ -150,15 +152,15 @@ interface CP0_i;
|
||||
input cp0_in_kernel,
|
||||
input cpu_tlbwi,
|
||||
input cpu_tlbwr,
|
||||
input cpu_tlbp,
|
||||
input cpu_tlb_tlbp,
|
||||
input cp0_Random,
|
||||
input cp0_Index,
|
||||
input cp0_EntryHi,
|
||||
input cp0_PageMask,
|
||||
// input cp0_PageMask,
|
||||
input cp0_EntryLo1,
|
||||
input cp0_EntryLo0,
|
||||
output tlb_EntryHi,
|
||||
output tlb_PageMask,
|
||||
// output tlb_PageMask,
|
||||
output tlb_EntryLo1,
|
||||
output tlb_EntryLo0,
|
||||
output tlb_Index,
|
||||
@ -173,17 +175,16 @@ interface CP0_i;
|
||||
modport cp0(
|
||||
output cp0_K0,
|
||||
output cp0_in_kernel,
|
||||
output cpu_tlbwi,
|
||||
output cpu_tlbwr,
|
||||
output cpu_tlbp,
|
||||
input cpu_c0_tlbp,
|
||||
input cpu_tlbr,
|
||||
output cp0_Random,
|
||||
output cp0_Index,
|
||||
output cp0_EntryHi,
|
||||
output cp0_PageMask,
|
||||
// output cp0_PageMask,
|
||||
output cp0_EntryLo1,
|
||||
output cp0_EntryLo0,
|
||||
input tlb_EntryHi,
|
||||
input tlb_PageMask,
|
||||
// input tlb_PageMask,
|
||||
input tlb_EntryLo1,
|
||||
input tlb_EntryLo0,
|
||||
input tlb_Index
|
||||
@ -191,7 +192,10 @@ interface CP0_i;
|
||||
modport cpu(
|
||||
output cpu_tlbwi,
|
||||
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_iTLBInvalid,
|
||||
input tlb_iAddressError,
|
||||
@ -200,5 +204,5 @@ interface CP0_i;
|
||||
input tlb_dTLBModified,
|
||||
input tlb_dAddressError
|
||||
);
|
||||
|
||||
endinterface
|
||||
|
||||
endinterface
|
||||
|
@ -4,10 +4,11 @@
|
||||
`include "defines.svh"
|
||||
|
||||
// IC for I-Cache
|
||||
`define IC_TAGL 11
|
||||
`define IC_INDEXL 5
|
||||
`define IC_TAG_LENGTH 22 // Tag + Valid
|
||||
`define IC_TAGL 11
|
||||
`define IC_INDEXL 5
|
||||
`define IC_TAG_LENGTH 22 // Tag + Valid
|
||||
`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 [32-`IC_TAGL-1:0] ICTagL_t;
|
||||
@ -44,6 +45,7 @@ typedef struct packed {
|
||||
`define DC_INDEXL 4
|
||||
`define DC_TAG_LENGTH 23 // Tag + Valid + Dirty
|
||||
`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 [32-`DC_TAGL-1:0] DCTagL_t;
|
||||
|
@ -1,6 +1,8 @@
|
||||
`ifndef DEFINES_SVH
|
||||
`define DEFINES_SVH
|
||||
|
||||
`define XLEN 32
|
||||
|
||||
`define PCRST 32'hBFC00000
|
||||
`define Off_TRef 9'h000
|
||||
`define Off_GExc 9'h180
|
||||
@ -84,6 +86,7 @@ typedef enum logic [1:0] {
|
||||
URIGHT = 2'b10
|
||||
} ALR_t;
|
||||
|
||||
`define CACHEOP_T_LEN 4
|
||||
typedef struct packed {
|
||||
logic icache_op;
|
||||
logic dcache_op;
|
||||
|
@ -73,8 +73,9 @@ module mycpu_top (
|
||||
|
||||
InstFetch_i inst();
|
||||
Memory_i data();
|
||||
|
||||
|
||||
CacheOp_i cache_op();
|
||||
CP0_i c0;
|
||||
|
||||
logic C0_int;
|
||||
logic [4:0] C0_addr;
|
||||
@ -114,7 +115,7 @@ module mycpu_top (
|
||||
logic c0_tlbp;
|
||||
|
||||
|
||||
AXI axi (
|
||||
AXI axi (
|
||||
.arid (arid),
|
||||
.araddr (araddr),
|
||||
.arlen (arlen),
|
||||
@ -156,45 +157,23 @@ module mycpu_top (
|
||||
.bvalid(bvalid),
|
||||
.bready(bready),
|
||||
|
||||
.inst (inst_axi.axi),
|
||||
.rdata(rdata_axi.axi),
|
||||
.wdata(wdata_axi.axi)
|
||||
.axi_inst (inst_axi.axi),
|
||||
.axi_rdata(rdata_axi.axi),
|
||||
.axi_wdata(wdata_axi.axi)
|
||||
);
|
||||
|
||||
MMU mmu (
|
||||
.clk (aclk),
|
||||
.rst (~aresetn),
|
||||
.ic (icache.mu),
|
||||
.dc (dcache.mu),
|
||||
.inst (inst.mu),
|
||||
.data (data.mu),
|
||||
.cacheOp (cache_op.mu),
|
||||
.inst_axi (inst_axi.mu),
|
||||
.rdata_axi (rdata_axi.mu),
|
||||
.wdata_axi (wdata_axi.mu),
|
||||
.K0 (K0),
|
||||
.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)
|
||||
MU mmu (
|
||||
.clk (aclk),
|
||||
.rst (~aresetn),
|
||||
.icache (icache.mu),
|
||||
.dcache (dcache.mu),
|
||||
.instfetch (inst.mu),
|
||||
.memory (data.mu),
|
||||
.cacheop (cache_op.mu),
|
||||
.axiread_inst (inst_axi.mu),
|
||||
.axiread_data (rdata_axi.mu),
|
||||
.axiwrite_data (wdata_axi.mu),
|
||||
.cp0 (c0.mu)
|
||||
);
|
||||
|
||||
ICache ICache (
|
||||
@ -223,21 +202,7 @@ module mycpu_top (
|
||||
.EBase (C0_EBase),
|
||||
.ext_int (ext_int),
|
||||
.interrupt (C0_int),
|
||||
.tlbr (c0_tlbr),
|
||||
.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)
|
||||
.c0 (c0.cp0)
|
||||
);
|
||||
|
||||
Datapath datapath (
|
||||
@ -247,19 +212,7 @@ module mycpu_top (
|
||||
.mem (data.cpu),
|
||||
.cache_op(cache_op.cpu),
|
||||
|
||||
.iTLBRefill (iTLBRefill),
|
||||
.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 (c0.cpu),
|
||||
.C0_int (C0_int),
|
||||
.C0_addr (C0_addr),
|
||||
.C0_sel (C0_sel),
|
||||
@ -270,7 +223,6 @@ module mycpu_top (
|
||||
.C0_ERETPC (C0_ERETPC),
|
||||
.C0_Bev (C0_Bev),
|
||||
.C0_EBase (C0_EBase),
|
||||
.C0_kernel (in_kernel),
|
||||
|
||||
.debug_wb_pc (debug_wb_pc),
|
||||
.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()
|
||||
title = lines[0].split()
|
||||
items = [x.split() for x in lines[1:]]
|
||||
|
@ -74,11 +74,11 @@
|
||||
32'b011100???????????????00000000010 ? ? ? ? ? ? ? ? ? ? ? // MUL
|
||||
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'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'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'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'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
|
||||
|
@ -74,11 +74,11 @@
|
||||
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'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'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'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'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
|
||||
|
@ -74,11 +74,11 @@
|
||||
32'b011100???????????????00000000010 0 0 MUL? 1 0 ? PASST 0 0 0 MUL 0 1 0 // MUL
|
||||
32'b100000?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LB
|
||||
32'b100001?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LH
|
||||
32'h100010?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LWL
|
||||
32'b100010?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LWL
|
||||
32'b100011?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LW
|
||||
32'b100100?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LBU
|
||||
32'b100101?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LHU
|
||||
32'h100110?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LWR
|
||||
32'b100110?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LWR
|
||||
32'b101000?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // SB
|
||||
32'b101001?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // SH
|
||||
32'b101010?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // SWL
|
||||
|
@ -74,11 +74,11 @@
|
||||
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'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'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'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'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
|
||||
|
@ -74,11 +74,11 @@
|
||||
32'b011100???????????????00000000010 0 0 0 0 // MUL
|
||||
32'b100000?????????????????????????? 0 0 0 0 // LB
|
||||
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'b100100?????????????????????????? 0 0 0 0 // LBU
|
||||
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'b101001?????????????????????????? 0 0 0 0 // SH
|
||||
32'b101010?????????????????????????? 0 0 0 0 // SWL
|
||||
|
@ -74,11 +74,11 @@
|
||||
32'b011100???????????????00000000010 0 // MUL
|
||||
32'b100000?????????????????????????? 0 // LB
|
||||
32'b100001?????????????????????????? 0 // LH
|
||||
32'h100010?????????????????????????? 0 // LWL
|
||||
32'b100010?????????????????????????? 0 // LWL
|
||||
32'b100011?????????????????????????? 0 // LW
|
||||
32'b100100?????????????????????????? 0 // LBU
|
||||
32'b100101?????????????????????????? 0 // LHU
|
||||
32'h100110?????????????????????????? 0 // LWR
|
||||
32'b100110?????????????????????????? 0 // LWR
|
||||
32'b101000?????????????????????????? 0 // SB
|
||||
32'b101001?????????????????????????? 0 // SH
|
||||
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'b100000?????????????????????????? 0 ? ? ? // LB
|
||||
32'b100001?????????????????????????? 0 ? ? ? // LH
|
||||
32'h100010?????????????????????????? 0 ? ? ? // LWL
|
||||
32'b100010?????????????????????????? 0 ? ? ? // LWL
|
||||
32'b100011?????????????????????????? 0 ? ? ? // LW
|
||||
32'b100100?????????????????????????? 0 ? ? ? // LBU
|
||||
32'b100101?????????????????????????? 0 ? ? ? // LHU
|
||||
32'h100110?????????????????????????? 0 ? ? ? // LWR
|
||||
32'b100110?????????????????????????? 0 ? ? ? // LWR
|
||||
32'b101000?????????????????????????? 0 ? ? ? // SB
|
||||
32'b101001?????????????????????????? 0 ? ? ? // SH
|
||||
32'b101010?????????????????????????? 0 ? ? ? // SWL
|
||||
|
@ -74,11 +74,11 @@
|
||||
32'b011100???????????????00000000010 0 1 RD 0 0 // MUL
|
||||
32'b100000?????????????????????????? 0 1 RT 1 ? // LB
|
||||
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'b100100?????????????????????????? 0 1 RT 1 ? // LBU
|
||||
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'b101001?????????????????????????? 0 0 ? ? ? // SH
|
||||
32'b101010?????????????????????????? 0 0 ? ? ? // SWL
|
||||
|
Loading…
Reference in New Issue
Block a user