feat: MU rewrite 1

1. ALU format
2. FIX hazard (MOVN / MOVZ)
3. verilator support
This commit is contained in:
Paul Pan 2022-07-27 15:07:16 +08:00
parent e569965556
commit 9ce588757d
52 changed files with 7403 additions and 1244 deletions

View File

@ -1,6 +1,6 @@
root = true root = true
[src/**/*.{sv,svh}] [**/*.{sv,svh}]
charset = utf-8 charset = utf-8
indent_style = space indent_style = space
indent_size = 2 indent_size = 2
@ -8,10 +8,18 @@ end_of_line = lf
insert_final_newline = true insert_final_newline = true
trim_trailing_whitespace = true trim_trailing_whitespace = true
[Makefile] [sim/Makefile]
indent_style = tab indent_style = tab
[tools/**/*.txt] [sim/**/*.{c,cpp,h,hpp}]
charset = utf-8
indent_style = space
indent_size = 4
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[tools/*.txt]
charset = utf-8 charset = utf-8
indent_style = tab indent_style = tab
indent_size = 8 indent_size = 8

3
.gitignore vendored
View File

@ -2,4 +2,5 @@ vivado.log
vivado.jou vivado.jou
.library_mapping.xml .library_mapping.xml
.project .project
.settings .settings
.vscode

166
resources/func_test/axi_wrap.v Executable file
View 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

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

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

View File

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

@ -0,0 +1 @@
obj_dir

76
sim/Makefile Normal file
View 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
View 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
View 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
View 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

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

View 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
View 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);
}

View File

@ -21,22 +21,10 @@ module CP0 (
output logic interrupt, output logic interrupt,
// MMU // MMU
input logic tlbr, CP0_i.cp0 c0
input logic tlbp,
output logic [2:0] K0,
output logic in_kernel,
output Random_t Random,
output Index_t Index,
output EntryHi_t EntryHi,
output EntryLo_t EntryLo1,
output EntryLo_t EntryLo0,
input EntryHi_t tlb_EntryHi,
input EntryLo_t tlb_EntryLo1,
input EntryLo_t tlb_EntryLo0,
input Index_t tlb_Index
); );
CP0_REGS_t rf_cp0; CP0_REGS_t rf_cp0/*verilator split_var*/;
logic count_lo; logic count_lo;
// int comb logic // int comb logic
@ -168,7 +156,7 @@ module CP0 (
9: rf_cp0.Count = wdata; 9: rf_cp0.Count = wdata;
8: rf_cp0.BadVAddr = wdata; 8: rf_cp0.BadVAddr = wdata;
// 7: rf_cp0.HWREna = wdata; // 7: rf_cp0.HWREna = wdata;
6: begin 6: begin
rf_cp0.Wired.Wired = wdata[2:0]; rf_cp0.Wired.Wired = wdata[2:0];
rf_cp0.Random.Random = 3'b111; rf_cp0.Random.Random = 3'b111;
end end
@ -197,25 +185,25 @@ module CP0 (
endcase endcase
end end
if (tlbr) begin if (c0.cpu_tlbr) begin
rf_cp0.EntryHi.VPN2 = tlb_EntryHi.VPN2; rf_cp0.EntryHi.VPN2 = c0.tlb_EntryHi.VPN2;
rf_cp0.EntryHi.ASID = tlb_EntryHi.ASID; rf_cp0.EntryHi.ASID = c0.tlb_EntryHi.ASID;
// rf_cp0.PageMask.Mask = tlb_PageMask.Mask; // rf_cp0.PageMask.Mask = tlb_PageMask.Mask;
rf_cp0.EntryLo0.PFN = tlb_EntryLo0.PFN; rf_cp0.EntryLo0.PFN = c0.tlb_EntryLo0.PFN;
rf_cp0.EntryLo0.C = tlb_EntryLo0.C; rf_cp0.EntryLo0.C = c0.tlb_EntryLo0.C;
rf_cp0.EntryLo0.D = tlb_EntryLo0.D; rf_cp0.EntryLo0.D = c0.tlb_EntryLo0.D;
rf_cp0.EntryLo0.V = tlb_EntryLo0.V; rf_cp0.EntryLo0.V = c0.tlb_EntryLo0.V;
rf_cp0.EntryLo0.G = tlb_EntryLo0.G; rf_cp0.EntryLo0.G = c0.tlb_EntryLo0.G;
rf_cp0.EntryLo1.PFN = tlb_EntryLo1.PFN; rf_cp0.EntryLo1.PFN = c0.tlb_EntryLo1.PFN;
rf_cp0.EntryLo1.C = tlb_EntryLo1.C; rf_cp0.EntryLo1.C = c0.tlb_EntryLo1.C;
rf_cp0.EntryLo1.D = tlb_EntryLo1.D; rf_cp0.EntryLo1.D = c0.tlb_EntryLo1.D;
rf_cp0.EntryLo1.V = tlb_EntryLo1.V; rf_cp0.EntryLo1.V = c0.tlb_EntryLo1.V;
rf_cp0.EntryLo1.G = tlb_EntryLo1.G; rf_cp0.EntryLo1.G = c0.tlb_EntryLo1.G;
end end
if (tlbp) begin if (c0.cpu_c0_tlbp) begin
rf_cp0.Index.P = tlb_Index.P; rf_cp0.Index.P = c0.tlb_Index.P;
rf_cp0.Index.Index = tlb_Index.Index; rf_cp0.Index.Index = c0.tlb_Index.Index;
end end
if (rf_cp0.Count == rf_cp0.Compare) rf_cp0.Cause.TI = 1; if (rf_cp0.Count == rf_cp0.Compare) rf_cp0.Cause.TI = 1;
@ -289,14 +277,14 @@ module CP0 (
assign Bev = rf_cp0.Status.Bev; assign Bev = rf_cp0.Status.Bev;
assign EBase = rf_cp0.EBase[31:12]; assign EBase = rf_cp0.EBase[31:12];
assign K0 = rf_cp0.Config.K0; assign c0.cp0_K0 = rf_cp0.Config.K0;
assign Random = rf_cp0.Random; assign c0.cp0_Random = rf_cp0.Random;
assign Index = rf_cp0.Index; assign c0.cp0_Index = rf_cp0.Index;
assign EntryHi = rf_cp0.EntryHi; assign c0.cp0_EntryHi = rf_cp0.EntryHi;
// assign PageMask = rf_cp0.PageMask; // assign PageMask = rf_cp0.PageMask;
assign EntryLo1 = rf_cp0.EntryLo1; assign c0.cp0_EntryLo1 = rf_cp0.EntryLo1;
assign EntryLo0 = rf_cp0.EntryLo0; assign c0.cp0_EntryLo0 = rf_cp0.EntryLo0;
assign in_kernel = ~rf_cp0.Status.UM | rf_cp0.Status.EXL; // currently no ERL assign c0.cp0_in_kernel = ~rf_cp0.Status.UM | rf_cp0.Status.EXL; // currently no ERL
endmodule endmodule

View File

@ -1,35 +1,34 @@
`include "defines.svh" `include "defines.svh"
module ALU( module ALU(
input word_t a, b, input word_t a, b,
input ALUCtrl_t aluctrl, input ALUCtrl_t aluctrl,
output word_t aluout, output word_t aluout,
output logic overflow); output logic overflow
);
wire logic alt = aluctrl.alt; wire logic alt = aluctrl.alt;
wire logic [4:0] sa = a[4:0]; wire logic [4:0] sa = a[4:0];
wire logic ex = alt & b[31]; wire logic ex = alt & b[31];
wire word_t sl = b << sa; wire word_t sl = b << sa;
/* verilator lint_off WIDTH */ /* verilator lint_off WIDTH */
wire word_t sr = {{31{ex}}, b} >> sa; wire word_t sr = {{31{ex}}, b} >> sa;
/* verilator lint_on WIDTH */ /* verilator lint_on WIDTH */
wire word_t b2 = alt ? ~b : b;
wire word_t b2 = alt ? ~b : b; wire word_t sum;
wire word_t sum; wire logic lt, ltu;
wire logic lt, ltu; /* verilator lint_off WIDTH */
assign {lt, ltu, sum} = {a[31], 1'b0, a} + {b2[31], 1'b1, b2} + alt; // alt for cin(CARRY4) at synthesis
/* verilator lint_off WIDTH */ /* verilator lint_on WIDTH */
assign {lt, ltu, sum} = {a[31], 1'b0, a} + {b2[31], 1'b1, b2} + alt; // alt for cin(CARRY4) at synthesis assign aluout = (aluctrl.f_sl ? sl : 32'b0)
/* verilator lint_on WIDTH */ | (aluctrl.f_sr ? sr : 32'b0)
assign aluout = (aluctrl.f_sl ? sl : 32'b0) | (aluctrl.f_add ? sum : 32'b0)
| (aluctrl.f_sr ? sr : 32'b0) | (aluctrl.f_and ? a & b : 32'b0)
| (aluctrl.f_add ? sum : 32'b0) | (aluctrl.f_or ? alt ? ~(a | b) : a | b : 32'b0)
| (aluctrl.f_and ? a & b : 32'b0) | (aluctrl.f_xor ? a ^ b : 32'b0)
| (aluctrl.f_or ? alt ? ~(a | b) : a | b : 32'b0) | (aluctrl.f_slt ? {31'b0, lt } : 32'b0)
| (aluctrl.f_xor ? a ^ b : 32'b0) | (aluctrl.f_sltu ? {31'b0, ltu} : 32'b0)
| (aluctrl.f_slt ? {31'b0, lt } : 32'b0) | (aluctrl.f_mova ? a : 32'b0);
| (aluctrl.f_sltu ? {31'b0, ltu} : 32'b0) assign overflow = lt ^ sum[31];
| (aluctrl.f_mova ? a : 32'b0);
assign overflow = lt ^ sum[31];
endmodule endmodule

View File

@ -5,7 +5,7 @@ module Controller (
input logic eq, input logic eq,
input logic ltz, input logic ltz,
input word_t rt, input word_t rt,
output Ctrl_t ctrl, output Ctrl_t ctrl/*verilator split_var*/,
output word_t imm, output word_t imm,
output logic [4:0] sa output logic [4:0] sa
); );

View File

@ -10,20 +10,9 @@ module Datapath (
InstFetch_i.cpu fetch, InstFetch_i.cpu fetch,
Memory_i.cpu mem, Memory_i.cpu mem,
CacheOp_i.cpu cache_op, CacheOp_i.cpu cache_op,
input logic iTLBRefill,
input logic iTLBInvalid,
input logic iAddressError,
input logic dTLBRefill,
input logic dTLBInvalid,
input logic dTLBModified,
input logic dAddressError,
output logic tlb_tlbwi,
output logic tlb_tlbwr,
output logic tlb_tlbp,
output logic c0_tlbr,
output logic c0_tlbp,
// CP0 // CP0
CP0_i.cpu C0,
input logic C0_int, input logic C0_int,
output logic [4:0] C0_addr, output logic [4:0] C0_addr,
output logic [2:0] C0_sel, output logic [2:0] C0_sel,
@ -34,7 +23,6 @@ module Datapath (
input word_t C0_ERETPC, input word_t C0_ERETPC,
input logic C0_Bev, input logic C0_Bev,
input logic [19:0] C0_EBase, input logic [19:0] C0_EBase,
input logic C0_kernel,
//debug interface //debug interface
output wire [31:0] debug_wb_pc, output wire [31:0] debug_wb_pc,
@ -52,12 +40,12 @@ module Datapath (
logic rstD, rstM; logic rstD, rstM;
PF_t PF; PF_t PF/*verilator split_var*/;
F_t F; F_t F/*verilator split_var*/;
D_t D; D_t D/*verilator split_var*/;
E_t E; E_t E/*verilator split_var*/;
M_t M; M_t M/*verilator split_var*/;
W_t W; W_t W/*verilator split_var*/;
// Pre Fetch // Pre Fetch
logic PF_go; logic PF_go;
@ -330,7 +318,7 @@ module Datapath (
assign F.en = PF.pc[1:0] != 2'b00 & D_IA_can_dispatch | fetch.req & fetch.addr_ok; assign F.en = PF.pc[1:0] != 2'b00 & D_IA_can_dispatch | fetch.req & fetch.addr_ok;
assign F.ExcValid = F.pc[1:0] != 2'b00 | iTLBRefill | iTLBInvalid | iAddressError; assign F.ExcValid = F.pc[1:0] != 2'b00 | C0.tlb_iTLBRefill | C0.tlb_iTLBInvalid | C0.tlb_iAddressError;
//---------------------------------------------------------------------------// //---------------------------------------------------------------------------//
// Instr Queue // // Instr Queue //
@ -342,7 +330,7 @@ module Datapath (
.vinA(fetch.data_ok | F.ExcValid), .vinA(fetch.data_ok | F.ExcValid),
.inA ({F.pc[2] ? fetch.rdata1 : fetch.rdata0, F.pc, .inA ({F.pc[2] ? fetch.rdata1 : fetch.rdata0, F.pc,
iTLBRefill, iTLBInvalid, iAddressError}), C0.tlb_iTLBRefill, C0.tlb_iTLBInvalid, C0.tlb_iAddressError}),
.vinB(fetch.data_ok & ~F.pc[2]), .vinB(fetch.data_ok & ~F.pc[2]),
.inB ({fetch.rdata1, F.pc[31:3], 3'b100, 3'b00}), .inB ({fetch.rdata1, F.pc[31:3], 3'b100, 3'b00}),
@ -462,7 +450,7 @@ module Datapath (
| D_IA_TLBRefill | D_IA_TLBInvalid | D_IA_TLBRefill | D_IA_TLBInvalid
| D_IA_AddressError | D_IA_AddressError
| D.IA.SYSCALL | D.IA.BREAK | D.IA.ERET | D.IA.SYSCALL | D.IA.BREAK | D.IA.ERET
| D.IA.PRV & ~C0_kernel); | D.IA.PRV & ~C0.cp0_in_kernel);
assign D.IA_ERET = D_IA_valid & D.IA_pc[1:0] == 2'b00 & ~D_IA_TLBRefill & ~D_IA_TLBInvalid & ~D_IA_AddressError & D_IA_iv & D.IA.ERET; assign D.IA_ERET = D_IA_valid & D.IA_pc[1:0] == 2'b00 & ~D_IA_TLBRefill & ~D_IA_TLBInvalid & ~D_IA_AddressError & D_IA_iv & D.IA.ERET;
assign D.IA_REFILL = D_IA_valid & D.IB_pc[1:0] == 2'b00 & D_IA_TLBRefill; assign D.IA_REFILL = D_IA_valid & D.IB_pc[1:0] == 2'b00 & D_IA_TLBRefill;
assign D.IA_ExcCode = D.IA_pc[1:0] != 2'b00 | D_IA_AddressError ? `EXCCODE_ADEL assign D.IA_ExcCode = D.IA_pc[1:0] != 2'b00 | D_IA_AddressError ? `EXCCODE_ADEL
@ -479,7 +467,7 @@ module Datapath (
| D_IB_AddressError | D_IB_AddressError
| D.IB.SYSCALL | D.IB.BREAK | D.IB.ERET | D.IB.SYSCALL | D.IB.BREAK | D.IB.ERET
| D.IB_Delay & D.IB.BJRJ | D.IB_Delay & D.IB.BJRJ
| D.IB.PRV & ~C0_kernel); | D.IB.PRV & ~C0.cp0_in_kernel);
assign D.IB_ERET = D_IB_valid & D.IB_pc[1:0] == 2'b00 & ~D_IB_TLBRefill & ~D_IB_TLBInvalid & ~D_IB_AddressError & D_IB_iv & D.IB.ERET & ~D.IB_Delay; assign D.IB_ERET = D_IB_valid & D.IB_pc[1:0] == 2'b00 & ~D_IB_TLBRefill & ~D_IB_TLBInvalid & ~D_IB_AddressError & D_IB_iv & D.IB.ERET & ~D.IB_Delay;
assign D.IB_REFILL = D_IB_valid & D.IB_pc[1:0] == 2'b00 & D_IB_TLBRefill; assign D.IB_REFILL = D_IB_valid & D.IB_pc[1:0] == 2'b00 & D_IB_TLBRefill;
// EXCCODE_BP and EXCCODE_SYSCALL -> exc.txt // EXCCODE_BP and EXCCODE_SYSCALL -> exc.txt
@ -534,6 +522,15 @@ module Datapath (
| D.IA.WCtrl.RW & D.IB.RT == D.IA.RD & D.IB.MCtrl1.MWR & ~D.IA.DP1 | D.IA.WCtrl.RW & D.IB.RT == D.IA.RD & D.IB.MCtrl1.MWR & ~D.IA.DP1
// Not Arith -> LWL/LWR // Not Arith -> LWL/LWR
| D.IA.WCtrl.RW & D.IB.RT == D.IA.RD & |D.IB.MCtrl1.ALR & ~D.IA.DP1 | D.IA.WCtrl.RW & D.IB.RT == D.IA.RD & |D.IB.MCtrl1.ALR & ~D.IA.DP1
// D.IA -> MOVN/MOVZ
| D.IA.WCtrl.RW & D.IB.RT == D.IA.RD & D.IB.DT
// Arith -> MOVN/MOVZ
| E.I0.WCtrl.RW & D.IB.RT == E.I0.RD & D.IB.DT
| E.I1.WCtrl.RW & D.IB.RT == E.I1.RD & D.IB.DT
// Not Arith -> MOVN/MOVZ
| M.I0.WCtrl.RW & D.IB.RT == M.I0.RD & D.IB.DT & ~M.I0.MCtrl.RS0[2]
// Load -> MOVN/MOVZ
| M.I1.WCtrl.RW & D.IB.RT == M.I1.RD & D.IB.DT & M.I1.MCtrl.MR
// CP0 Execution Hazards // CP0 Execution Hazards
// Hazards Related to the TLB // Hazards Related to the TLB
| D.IA.MCtrl0.C0W & D.IB.MCtrl1.TLBR & D.IA.MCtrl0.C0D == C0_INDEX | D.IA.MCtrl0.C0W & D.IB.MCtrl1.TLBR & D.IA.MCtrl0.C0D == C0_INDEX
@ -787,7 +784,7 @@ module Datapath (
E.en, E.en,
E.I1.ECtrl E.I1.ECtrl
); );
ffenrc #(14) E_I1_MCtrl_ff ( ffenrc #(15) E_I1_MCtrl_ff (
clk, clk,
rst | rstM, rst | rstM,
D.I1.MCtrl, D.I1.MCtrl,
@ -927,15 +924,15 @@ module Datapath (
E_I1_STRBERROR E_I1_STRBERROR
); );
assign tlb_tlbp = E.I1.MCtrl.TLBP; assign C0.cpu_tlb_tlbp = E.I1.MCtrl.TLBP;
assign mem.req = E.I1.MCtrl.MR & E_I1_goWithoutOF & M.en & ~rstM; assign mem.req = E.I1.MCtrl.MR & E_I1_goWithoutOF & M.en & ~rstM;
assign E_I1_ADDR = E_I1_ForwardS + E.I1.imm; assign E_I1_ADDR = E_I1_ForwardS + E.I1.imm;
assign mem.addr = |E.I1.MCtrl.ALR ? {E_I1_ADDR[31:2], 2'b0} assign mem.addr = |E.I1.MCtrl.ALR ? {E_I1_ADDR[31:2], 2'b0}
: (cache_op == CNOP | ~cache_op[1]) ? E_I1_ADDR : (~cache_op.op.icache_op & ~cache_op.op.dcache_op | ~cache_op.op.index_or_hit) ? E_I1_ADDR
: cache_op[2] ? {E_I1_ADDR[32-`DC_INDEXL-1:0], `DC_INDEXL'b0} : cache_op.op.dcache_op ? {E_I1_ADDR[32-`DC_INDEXL-1:0], `DC_INDEXL'b0}
: {E_I1_ADDR[32-`IC_INDEXL-1:0], `IC_INDEXL'b0}; : {E_I1_ADDR[32-`IC_INDEXL-1:0], `IC_INDEXL'b0};
assign mem.size = {E.I1.MCtrl.SZ[1], E.I1.MCtrl.SZ[0] & ~E.I1.MCtrl.SZ[1]}; assign mem.size = {E.I1.MCtrl.SZ[1], E.I1.MCtrl.SZ[0] & ~E.I1.MCtrl.SZ[1]};
assign cache_op = E.I1.MCtrl.CACHE_OP; assign cache_op.op = E.I1.MCtrl.CACHE_OP;
assign E.en = E_go & M.en; assign E.en = E_go & M.en;
assign E_go = ~mem.req | mem.addr_ok; assign E_go = ~mem.req | mem.addr_ok;
@ -1087,7 +1084,7 @@ module Datapath (
M.en, M.en,
M.I1.ALUOut M.I1.ALUOut
); );
ffenrc #(14) M_I1_MCtrl_ff ( ffenrc #(15) M_I1_MCtrl_ff (
clk, clk,
rst | rstM, rst | rstM,
E.I1.MCtrl, E.I1.MCtrl,
@ -1124,7 +1121,7 @@ module Datapath (
); );
myBuffer0 #(4) dExc_buffer ( myBuffer0 #(4) dExc_buffer (
clk, rst, clk, rst,
{dTLBRefill, dTLBInvalid, dTLBModified, dAddressError}, {C0.tlb_dTLBRefill, C0.tlb_dTLBInvalid, C0.tlb_dTLBModified, C0.tlb_dAddressError},
dTLBExcValid, dTLBExcValid,
{dTLBRefillB, dTLBInvalidB, dTLBModifiedB, dAddressErrorB} {dTLBRefillB, dTLBInvalidB, dTLBModifiedB, dAddressErrorB}
); );
@ -1235,10 +1232,10 @@ module Datapath (
assign C0_wdata = M_I0_ForwardT; assign C0_wdata = M_I0_ForwardT;
// M.I1.MEM // M.I1.MEM
assign tlb_tlbwi = M.I1.MCtrl.TLBWI; assign C0.cpu_tlbwi = M.I1.MCtrl.TLBWI;
assign tlb_tlbwr = M.I1.MCtrl.TLBWR; assign C0.cpu_tlbwr = M.I1.MCtrl.TLBWR;
assign c0_tlbr = M.I1.MCtrl.TLBR; assign C0.cpu_tlbr = M.I1.MCtrl.TLBR;
assign c0_tlbp = M.I1.MCtrl.TLBP & M.en; assign C0.cpu_c0_tlbp = M.I1.MCtrl.TLBP & M.en;
assign mem.wr = M.I1.MCtrl.MWR; assign mem.wr = M.I1.MCtrl.MWR;
memoutput M_I1_memoutput ( memoutput M_I1_memoutput (
.addr (M.I1.ALUOut[1:0]), .addr (M.I1.ALUOut[1:0]),

View File

@ -1,4 +1,5 @@
module addr_virt_to_phy ( module addr_virt_to_phy (
input logic [ 2:0] K0,
input word_t virt_addr, input word_t virt_addr,
input logic [19:0] tlb_addr, input logic [19:0] tlb_addr,
input logic tlb_hit, input logic tlb_hit,

View File

@ -14,11 +14,11 @@ module bram #(
for(genvar i = 0; i < DATA_DEPTH; i++) for(genvar i = 0; i < DATA_DEPTH; i++)
initial ram[i] = 0; initial ram[i] = 0;
always_ff @(posedge clka) begin always_ff @(posedge clka) begin
if (~rst) begin if (~rst) begin
if(wea) ram[addra] <= dina; if(wea) ram[addra] <= dina;
douta <= ~wea ? ram[addra] : dina; douta <= ~wea ? ram[addra] : dina;
end end
end end
endmodule endmodule

View File

@ -1,48 +1,48 @@
module AXI ( module AXI (
output wire [ 3:0] arid, output wire logic [ 3:0] arid,
output wire [31:0] araddr, output wire logic [31:0] araddr,
output wire [ 3:0] arlen, output wire logic [ 3:0] arlen,
output wire [ 2:0] arsize, output wire logic [ 2:0] arsize,
output wire [ 1:0] arburst, output wire logic [ 1:0] arburst,
output wire [ 1:0] arlock, output wire logic [ 1:0] arlock,
output wire [ 3:0] arcache, output wire logic [ 3:0] arcache,
output wire [ 2:0] arprot, output wire logic [ 2:0] arprot,
output wire arvalid, output wire logic arvalid,
input wire arready, input wire logic arready,
input wire [ 3:0] rid, input wire logic [ 3:0] rid,
input wire [31:0] rdata, input wire logic [31:0] rdata,
input wire [ 1:0] rresp, input wire logic [ 1:0] rresp,
input wire rlast, input wire logic rlast,
input wire rvalid, input wire logic rvalid,
output wire rready, output wire logic rready,
output wire [ 3:0] awid, output wire logic [ 3:0] awid,
output wire [31:0] awaddr, output wire logic [31:0] awaddr,
output wire [ 3:0] awlen, output wire logic [ 3:0] awlen,
output wire [ 2:0] awsize, output wire logic [ 2:0] awsize,
output wire [ 1:0] awburst, output wire logic [ 1:0] awburst,
output wire [ 1:0] awlock, output wire logic [ 1:0] awlock,
output wire [ 3:0] awcache, output wire logic [ 3:0] awcache,
output wire [ 2:0] awprot, output wire logic [ 2:0] awprot,
output wire awvalid, output wire logic awvalid,
input wire awready, input wire logic awready,
output wire [ 3:0] wid, output wire logic [ 3:0] wid,
output wire [31:0] wdata, output wire logic [31:0] wdata,
output wire [ 3:0] wstrb, output wire logic [ 3:0] wstrb,
output wire wlast, output wire logic wlast,
output wire wvalid, output wire logic wvalid,
input wire wready, input wire logic wready,
input wire [3:0] bid, input wire logic [3:0] bid,
input wire [1:0] bresp, input wire logic [1:0] bresp,
input wire bvalid, input wire logic bvalid,
output wire bready, output wire logic bready,
AXIRead_i.axi inst, AXIRead_i.axi axi_inst,
AXIRead_i.axi rdata, AXIRead_i.axi axi_rdata,
AXIWrite_i.axi wdata AXIWrite_i.axi axi_wdata
); );
// ============================== // ==============================
@ -50,19 +50,19 @@ module AXI (
// ============================== // ==============================
always_comb begin always_comb begin
inst.rdata = rdata; axi_inst.rdata = rdata;
rdata.rdata = rdata; axi_rdata.rdata = rdata;
if (rid == 0) begin if (rid == 0) begin
inst.rvalid = rvalid; axi_inst.rvalid = rvalid;
inst.data_ok = rlast; axi_inst.data_ok = rlast;
rdata.rvalid = 1'b0; axi_rdata.rvalid = 1'b0;
rdata.data_ok = 1'b0; axi_rdata.data_ok = 1'b0;
end else begin end else begin
rdata.rvalid = rvalid; axi_rdata.rvalid = rvalid;
rdata.data_ok = rlast; axi_rdata.data_ok = rlast;
inst.rvalid = 1'b0; axi_inst.rvalid = 1'b0;
inst.data_ok = 1'b0; axi_inst.data_ok = 1'b0;
end end
end end
@ -79,22 +79,22 @@ module AXI (
// Burst // Burst
arburst = 2'b10; // Wrap arburst = 2'b10; // Wrap
arvalid = rdata.req | inst.req; arvalid = axi_rdata.req | axi_inst.req;
rdata.addr_ok = arready; axi_rdata.addr_ok = arready;
if (rdata.req) begin if (axi_rdata.req) begin
arid = 4'b0001; arid = 4'b0001;
arprot = 3'b001; arprot = 3'b001;
araddr = rdata.addr; araddr = axi_rdata.addr;
arlen = rdata.len; arlen = axi_rdata.len;
arsize = rdata.size; arsize = axi_rdata.size;
inst.addr_ok = 1'b0; axi_inst.addr_ok = 1'b0;
end else begin end else begin
arid = 4'b0000; arid = 4'b0000;
arprot = 3'b101; arprot = 3'b101;
araddr = inst.addr; araddr = axi_inst.addr;
arlen = inst.len; arlen = axi_inst.len;
arsize = inst.size; arsize = axi_inst.size;
inst.addr_ok = arready; axi_inst.addr_ok = arready;
end end
end end
@ -103,15 +103,15 @@ module AXI (
// ======= Write Request ======== // ======= Write Request ========
// ============================== // ==============================
assign wdata.data_ok = bvalid; assign axi_wdata.data_ok = bvalid;
assign wdata.wready = wready; assign axi_wdata.wready = wready;
always_comb begin always_comb begin
wid = 4'b1; wid = 4'b1;
wdata = wdata.wdata; wdata = axi_wdata.wdata;
wstrb = wdata.wstrb; wstrb = axi_wdata.wstrb;
wlast = wdata.wlast; wlast = axi_wdata.wlast;
wvalid = wdata.wvalid; wvalid = axi_wdata.wvalid;
end end
always_comb begin always_comb begin
@ -126,11 +126,11 @@ module AXI (
awid = 4'b1; awid = 4'b1;
awprot = 3'b001; awprot = 3'b001;
awvalid = wdata.req; awvalid = axi_wdata.req;
awaddr = wdata.addr; awaddr = axi_wdata.addr;
awlen = wdata.len; awlen = axi_wdata.len;
awsize = wdata.size; awsize = axi_wdata.size;
wdata.addr_ok = awready; axi_wdata.addr_ok = awready;
end end

101
src/MU/AXIReader.sv Normal file
View 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
View 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

View File

@ -11,8 +11,8 @@ module DCache (
// ============ Vars ============ // ============ Vars ============
// ============================== // ==============================
DCTagRAM_t TagRAM0, TagRAM1, TagRAM2, TagRAM3; DCTagRAM_t TagRAM0/*verilator split_var*/, TagRAM1/*verilator split_var*/, TagRAM2/*verilator split_var*/, TagRAM3/*verilator split_var*/;
DCDataRAM_t DataRAM0, DataRAM1, DataRAM2, DataRAM3; DCDataRAM_t DataRAM0/*verilator split_var*/, DataRAM1/*verilator split_var*/, DataRAM2/*verilator split_var*/, DataRAM3/*verilator split_var*/;
(* RAM_STYLE="block" *) (* RAM_STYLE="block" *)
logic [3:0] LRU[128]; logic [3:0] LRU[128];
@ -54,7 +54,7 @@ module DCache (
assign hitway[1] = tag[1].valid & tag[1].tag == port.tag; assign hitway[1] = tag[1].valid & tag[1].tag == port.tag;
assign hitway[2] = tag[2].valid & tag[2].tag == port.tag; assign hitway[2] = tag[2].valid & tag[2].tag == port.tag;
assign hitway[3] = tag[3].valid & tag[3].tag == port.tag; assign hitway[3] = tag[3].valid & tag[3].tag == port.tag;
assign port.hit = |{hitway}; assign port.hit = |{hitway};
assign port.hit_row = (hitway[0] ? data[0] : `DC_DATA_LENGTH'b0) assign port.hit_row = (hitway[0] ? data[0] : `DC_DATA_LENGTH'b0)
| (hitway[1] ? data[1] : `DC_DATA_LENGTH'b0) | (hitway[1] ? data[1] : `DC_DATA_LENGTH'b0)
@ -168,7 +168,7 @@ module DCache (
tag_ram2 (.rst(rst), .addra(TagRAM2.addr), .clka(clk), .dina(TagRAM2.wdata), .douta(TagRAM2.rdata), .wea(TagRAM2.wen)); tag_ram2 (.rst(rst), .addra(TagRAM2.addr), .clka(clk), .dina(TagRAM2.wdata), .douta(TagRAM2.rdata), .wea(TagRAM2.wen));
bram #(.DATA_WIDTH(32-`DC_TAGL+2), .DATA_DEPTH(2 ** (`DC_TAGL-`DC_INDEXL))) bram #(.DATA_WIDTH(32-`DC_TAGL+2), .DATA_DEPTH(2 ** (`DC_TAGL-`DC_INDEXL)))
tag_ram3 (.rst(rst), .addra(TagRAM3.addr), .clka(clk), .dina(TagRAM3.wdata), .douta(TagRAM3.rdata), .wea(TagRAM3.wen)); tag_ram3 (.rst(rst), .addra(TagRAM3.addr), .clka(clk), .dina(TagRAM3.wdata), .douta(TagRAM3.rdata), .wea(TagRAM3.wen));
bram #(.DATA_WIDTH(`DC_DATA_LENGTH), .DATA_DEPTH(2 ** (`DC_TAGL-`DC_INDEXL))) bram #(.DATA_WIDTH(`DC_DATA_LENGTH), .DATA_DEPTH(2 ** (`DC_TAGL-`DC_INDEXL)))
data_ram0 (.rst(rst), .addra(DataRAM0.addr), .clka(clk), .dina(DataRAM0.wdata), .douta(DataRAM0.rdata), .wea(DataRAM0.wen)); data_ram0 (.rst(rst), .addra(DataRAM0.addr), .clka(clk), .dina(DataRAM0.wdata), .douta(DataRAM0.rdata), .wea(DataRAM0.wen));
bram #(.DATA_WIDTH(`DC_DATA_LENGTH), .DATA_DEPTH(2 ** (`DC_TAGL-`DC_INDEXL))) bram #(.DATA_WIDTH(`DC_DATA_LENGTH), .DATA_DEPTH(2 ** (`DC_TAGL-`DC_INDEXL)))

View File

@ -11,8 +11,8 @@ module ICache (
// ============ Vars ============ // ============ Vars ============
// ============================== // ==============================
ICTagRAM_t TagRAM0, TagRAM1, TagRAM2, TagRAM3; ICTagRAM_t TagRAM0/*verilator split_var*/, TagRAM1/*verilator split_var*/, TagRAM2/*verilator split_var*/, TagRAM3/*verilator split_var*/;
ICDataRAM_t DataRAM0, DataRAM1, DataRAM2, DataRAM3; ICDataRAM_t DataRAM0/*verilator split_var*/, DataRAM1/*verilator split_var*/, DataRAM2/*verilator split_var*/, DataRAM3/*verilator split_var*/;
(* RAM_STYLE="block" *) (* RAM_STYLE="block" *)
logic [3:0] LRU[64]; logic [3:0] LRU[64];
@ -122,7 +122,7 @@ module ICache (
assign DataRAM2.wdata = port.update_row; assign DataRAM2.wdata = port.update_row;
assign DataRAM3.wdata = port.update_row; assign DataRAM3.wdata = port.update_row;
bram #(.DATA_WIDTH(32-`IC_TAGL+1), .DATA_DEPTH(2 ** (`IC_TAGL-`IC_INDEXL))) bram #(.DATA_WIDTH(32-`IC_TAGL+1), .DATA_DEPTH(2 ** (`IC_TAGL-`IC_INDEXL)))
tag_ram0 (.rst(rst), .addra(TagRAM0.addr), .clka(clk), .dina(TagRAM0.wdata), .douta(TagRAM0.rdata), .wea(TagRAM0.wen)); tag_ram0 (.rst(rst), .addra(TagRAM0.addr), .clka(clk), .dina(TagRAM0.wdata), .douta(TagRAM0.rdata), .wea(TagRAM0.wen));
bram #(.DATA_WIDTH(32-`IC_TAGL+1), .DATA_DEPTH(2 ** (`IC_TAGL-`IC_INDEXL))) bram #(.DATA_WIDTH(32-`IC_TAGL+1), .DATA_DEPTH(2 ** (`IC_TAGL-`IC_INDEXL)))
tag_ram1 (.rst(rst), .addra(TagRAM1.addr), .clka(clk), .dina(TagRAM1.wdata), .douta(TagRAM1.rdata), .wea(TagRAM1.wen)); tag_ram1 (.rst(rst), .addra(TagRAM1.addr), .clka(clk), .dina(TagRAM1.wdata), .douta(TagRAM1.rdata), .wea(TagRAM1.wen));

File diff suppressed because it is too large Load Diff

View File

@ -125,15 +125,17 @@ interface CP0_i;
logic cp0_in_kernel; logic cp0_in_kernel;
logic cpu_tlbwi; logic cpu_tlbwi;
logic cpu_tlbwr; logic cpu_tlbwr;
logic cpu_tlbp; logic cpu_c0_tlbp;
logic cpu_tlb_tlbp;
logic cpu_tlbr;
Random_t cp0_Random; // TLBWR Random_t cp0_Random; // TLBWR
EntryHi_t cp0_EntryHi; // TLBWI + F/M(ASID) EntryHi_t cp0_EntryHi; // TLBWI + F/M(ASID)
PageMask_t cp0_PageMask; // TLBWI // PageMask_t cp0_PageMask; // TLBWI
EntryLo_t cp0_EntryLo1; // TLBWI EntryLo_t cp0_EntryLo1; // TLBWI
EntryLo_t cp0_EntryLo0; // TLBWI EntryLo_t cp0_EntryLo0; // TLBWI
Index_t cp0_Index; // TLBWI + TLBR Index_t cp0_Index; // TLBWI + TLBR
EntryHi_t tlb_EntryHi; EntryHi_t tlb_EntryHi;
PageMask_t tlb_PageMask; // PageMask_t tlb_PageMask;
EntryLo_t tlb_EntryLo1; EntryLo_t tlb_EntryLo1;
EntryLo_t tlb_EntryLo0; EntryLo_t tlb_EntryLo0;
Index_t tlb_Index; // TLBP Index_t tlb_Index; // TLBP
@ -150,15 +152,15 @@ interface CP0_i;
input cp0_in_kernel, input cp0_in_kernel,
input cpu_tlbwi, input cpu_tlbwi,
input cpu_tlbwr, input cpu_tlbwr,
input cpu_tlbp, input cpu_tlb_tlbp,
input cp0_Random, input cp0_Random,
input cp0_Index, input cp0_Index,
input cp0_EntryHi, input cp0_EntryHi,
input cp0_PageMask, // input cp0_PageMask,
input cp0_EntryLo1, input cp0_EntryLo1,
input cp0_EntryLo0, input cp0_EntryLo0,
output tlb_EntryHi, output tlb_EntryHi,
output tlb_PageMask, // output tlb_PageMask,
output tlb_EntryLo1, output tlb_EntryLo1,
output tlb_EntryLo0, output tlb_EntryLo0,
output tlb_Index, output tlb_Index,
@ -173,17 +175,16 @@ interface CP0_i;
modport cp0( modport cp0(
output cp0_K0, output cp0_K0,
output cp0_in_kernel, output cp0_in_kernel,
output cpu_tlbwi, input cpu_c0_tlbp,
output cpu_tlbwr, input cpu_tlbr,
output cpu_tlbp,
output cp0_Random, output cp0_Random,
output cp0_Index, output cp0_Index,
output cp0_EntryHi, output cp0_EntryHi,
output cp0_PageMask, // output cp0_PageMask,
output cp0_EntryLo1, output cp0_EntryLo1,
output cp0_EntryLo0, output cp0_EntryLo0,
input tlb_EntryHi, input tlb_EntryHi,
input tlb_PageMask, // input tlb_PageMask,
input tlb_EntryLo1, input tlb_EntryLo1,
input tlb_EntryLo0, input tlb_EntryLo0,
input tlb_Index input tlb_Index
@ -191,7 +192,10 @@ interface CP0_i;
modport cpu( modport cpu(
output cpu_tlbwi, output cpu_tlbwi,
output cpu_tlbwr, output cpu_tlbwr,
output cpu_tlbp, output cpu_c0_tlbp,
output cpu_tlb_tlbp,
output cpu_tlbr,
input cp0_in_kernel,
input tlb_iTLBRefill, input tlb_iTLBRefill,
input tlb_iTLBInvalid, input tlb_iTLBInvalid,
input tlb_iAddressError, input tlb_iAddressError,
@ -200,5 +204,5 @@ interface CP0_i;
input tlb_dTLBModified, input tlb_dTLBModified,
input tlb_dAddressError input tlb_dAddressError
); );
endinterface endinterface

View File

@ -4,10 +4,11 @@
`include "defines.svh" `include "defines.svh"
// IC for I-Cache // IC for I-Cache
`define IC_TAGL 11 `define IC_TAGL 11
`define IC_INDEXL 5 `define IC_INDEXL 5
`define IC_TAG_LENGTH 22 // Tag + Valid `define IC_TAG_LENGTH 22 // Tag + Valid
`define IC_DATA_LENGTH 256 // 32Bytes `define IC_DATA_LENGTH 256 // 32Bytes
`define IC_ROW_LENGTH (2 ** (`IC_INDEXL - 1) - 1)
typedef logic [`IC_DATA_LENGTH-1:0] ICData_t; typedef logic [`IC_DATA_LENGTH-1:0] ICData_t;
typedef logic [32-`IC_TAGL-1:0] ICTagL_t; typedef logic [32-`IC_TAGL-1:0] ICTagL_t;
@ -44,6 +45,7 @@ typedef struct packed {
`define DC_INDEXL 4 `define DC_INDEXL 4
`define DC_TAG_LENGTH 23 // Tag + Valid + Dirty `define DC_TAG_LENGTH 23 // Tag + Valid + Dirty
`define DC_DATA_LENGTH 128 // 16Bytes `define DC_DATA_LENGTH 128 // 16Bytes
`define DC_ROW_LENGTH (2 ** (`DC_INDEXL - 1) - 1)
typedef logic [`DC_DATA_LENGTH-1:0] DCData_t; typedef logic [`DC_DATA_LENGTH-1:0] DCData_t;
typedef logic [32-`DC_TAGL-1:0] DCTagL_t; typedef logic [32-`DC_TAGL-1:0] DCTagL_t;

View File

@ -1,6 +1,8 @@
`ifndef DEFINES_SVH `ifndef DEFINES_SVH
`define DEFINES_SVH `define DEFINES_SVH
`define XLEN 32
`define PCRST 32'hBFC00000 `define PCRST 32'hBFC00000
`define Off_TRef 9'h000 `define Off_TRef 9'h000
`define Off_GExc 9'h180 `define Off_GExc 9'h180
@ -84,6 +86,7 @@ typedef enum logic [1:0] {
URIGHT = 2'b10 URIGHT = 2'b10
} ALR_t; } ALR_t;
`define CACHEOP_T_LEN 4
typedef struct packed { typedef struct packed {
logic icache_op; logic icache_op;
logic dcache_op; logic dcache_op;

View File

@ -73,8 +73,9 @@ module mycpu_top (
InstFetch_i inst(); InstFetch_i inst();
Memory_i data(); Memory_i data();
CacheOp_i cache_op(); CacheOp_i cache_op();
CP0_i c0;
logic C0_int; logic C0_int;
logic [4:0] C0_addr; logic [4:0] C0_addr;
@ -114,7 +115,7 @@ module mycpu_top (
logic c0_tlbp; logic c0_tlbp;
AXI axi ( AXI axi (
.arid (arid), .arid (arid),
.araddr (araddr), .araddr (araddr),
.arlen (arlen), .arlen (arlen),
@ -156,45 +157,23 @@ module mycpu_top (
.bvalid(bvalid), .bvalid(bvalid),
.bready(bready), .bready(bready),
.inst (inst_axi.axi), .axi_inst (inst_axi.axi),
.rdata(rdata_axi.axi), .axi_rdata(rdata_axi.axi),
.wdata(wdata_axi.axi) .axi_wdata(wdata_axi.axi)
); );
MMU mmu ( MU mmu (
.clk (aclk), .clk (aclk),
.rst (~aresetn), .rst (~aresetn),
.ic (icache.mu), .icache (icache.mu),
.dc (dcache.mu), .dcache (dcache.mu),
.inst (inst.mu), .instfetch (inst.mu),
.data (data.mu), .memory (data.mu),
.cacheOp (cache_op.mu), .cacheop (cache_op.mu),
.inst_axi (inst_axi.mu), .axiread_inst (inst_axi.mu),
.rdata_axi (rdata_axi.mu), .axiread_data (rdata_axi.mu),
.wdata_axi (wdata_axi.mu), .axiwrite_data (wdata_axi.mu),
.K0 (K0), .cp0 (c0.mu)
.in_kernel (in_kernel),
.tlbwi (tlb_tlbwi),
.tlbwr (tlb_tlbwr),
.tlbp (tlb_tlbp),
.c0_Random (c0_Random),
.c0_Index (c0_Index),
.c0_EntryHi (c0_EntryHi),
// .c0_PageMask (c0_PageMask),
.c0_EntryLo1 (c0_EntryLo1),
.c0_EntryLo0 (c0_EntryLo0),
.EntryHi (tlb_EntryHi),
// .PageMask (tlb_PageMask),
.EntryLo1 (tlb_EntryLo1),
.EntryLo0 (tlb_EntryLo0),
.Index (tlb_Index),
.iTLBRefill (iTLBRefill),
.iTLBInvalid (iTLBInvalid),
.iAddressError(iAddressError),
.dTLBRefill (dTLBRefill),
.dTLBInvalid (dTLBInvalid),
.dTLBModified (dTLBModified),
.dAddressError(dAddressError)
); );
ICache ICache ( ICache ICache (
@ -223,21 +202,7 @@ module mycpu_top (
.EBase (C0_EBase), .EBase (C0_EBase),
.ext_int (ext_int), .ext_int (ext_int),
.interrupt (C0_int), .interrupt (C0_int),
.tlbr (c0_tlbr), .c0 (c0.cp0)
.tlbp (c0_tlbp),
.K0 (K0),
.in_kernel (in_kernel),
.Random (c0_Random),
.Index (c0_Index),
.EntryHi (c0_EntryHi),
// .PageMask (c0_PageMask),
.EntryLo1 (c0_EntryLo1),
.EntryLo0 (c0_EntryLo0),
.tlb_EntryHi (tlb_EntryHi),
// .tlb_PageMask(tlb_PageMask),
.tlb_EntryLo1(tlb_EntryLo1),
.tlb_EntryLo0(tlb_EntryLo0),
.tlb_Index (tlb_Index)
); );
Datapath datapath ( Datapath datapath (
@ -247,19 +212,7 @@ module mycpu_top (
.mem (data.cpu), .mem (data.cpu),
.cache_op(cache_op.cpu), .cache_op(cache_op.cpu),
.iTLBRefill (iTLBRefill), .C0 (c0.cpu),
.iTLBInvalid (iTLBInvalid),
.iAddressError(iAddressError),
.dTLBRefill (dTLBRefill),
.dTLBInvalid (dTLBInvalid),
.dTLBModified (dTLBModified),
.dAddressError(dAddressError),
.tlb_tlbwi (tlb_tlbwi),
.tlb_tlbwr (tlb_tlbwr),
.tlb_tlbp (tlb_tlbp),
.c0_tlbr (c0_tlbr),
.c0_tlbp (c0_tlbp),
.C0_int (C0_int), .C0_int (C0_int),
.C0_addr (C0_addr), .C0_addr (C0_addr),
.C0_sel (C0_sel), .C0_sel (C0_sel),
@ -270,7 +223,6 @@ module mycpu_top (
.C0_ERETPC (C0_ERETPC), .C0_ERETPC (C0_ERETPC),
.C0_Bev (C0_Bev), .C0_Bev (C0_Bev),
.C0_EBase (C0_EBase), .C0_EBase (C0_EBase),
.C0_kernel (in_kernel),
.debug_wb_pc (debug_wb_pc), .debug_wb_pc (debug_wb_pc),
.debug_wb_rf_wen (debug_wb_rf_wen), .debug_wb_rf_wen (debug_wb_rf_wen),

40
tools/ctrl2_maker.py Normal file
View 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')

View File

@ -1,4 +1,4 @@
with open('global.txt') as f: with open('clo.txt') as f:
lines = f.readlines() lines = f.readlines()
title = lines[0].split() title = lines[0].split()
items = [x.split() for x in lines[1:]] items = [x.split() for x in lines[1:]]

View File

@ -74,11 +74,11 @@
32'b011100???????????????00000000010 ? ? ? ? ? ? ? ? ? ? ? // MUL 32'b011100???????????????00000000010 ? ? ? ? ? ? ? ? ? ? ? // MUL
32'b100000?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // LB 32'b100000?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // LB
32'b100001?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // LH 32'b100001?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // LH
32'h100010?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // LWL 32'b100010?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // LWL
32'b100011?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // LW 32'b100011?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // LW
32'b100100?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // LBU 32'b100100?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // LBU
32'b100101?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // LHU 32'b100101?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // LHU
32'h100110?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // LWR 32'b100110?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // LWR
32'b101000?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // SB 32'b101000?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // SB
32'b101001?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // SH 32'b101001?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // SH
32'b101010?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // SWL 32'b101010?????????????????????????? ADD 0 RS 1 1 IMM 1 ? IX 0 1 // SWL

View File

@ -74,11 +74,11 @@
32'b011100???????????????00000000010 0 0 0 0 1 1 0 0 1 0 // MUL 32'b011100???????????????00000000010 0 0 0 0 1 1 0 0 1 0 // MUL
32'b100000?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // LB 32'b100000?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // LB
32'b100001?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // LH 32'b100001?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // LH
32'h100010?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // LWL 32'b100010?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // LWL
32'b100011?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // LW 32'b100011?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // LW
32'b100100?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // LBU 32'b100100?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // LBU
32'b100101?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // LHU 32'b100101?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // LHU
32'h100110?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // LWR 32'b100110?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // LWR
32'b101000?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // SB 32'b101000?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // SB
32'b101001?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // SH 32'b101001?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // SH
32'b101010?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // SWL 32'b101010?????????????????????????? 0 0 0 0 1 0 0 0 0 1 // SWL

View File

@ -74,11 +74,11 @@
32'b011100???????????????00000000010 0 0 MUL? 1 0 ? PASST 0 0 0 MUL 0 1 0 // MUL 32'b011100???????????????00000000010 0 0 MUL? 1 0 ? PASST 0 0 0 MUL 0 1 0 // MUL
32'b100000?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LB 32'b100000?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LB
32'b100001?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LH 32'b100001?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LH
32'h100010?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LWL 32'b100010?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LWL
32'b100011?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LW 32'b100011?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LW
32'b100100?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LBU 32'b100100?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LBU
32'b100101?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LHU 32'b100101?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LHU
32'h100110?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LWR 32'b100110?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // LWR
32'b101000?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // SB 32'b101000?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // SB
32'b101001?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // SH 32'b101001?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // SH
32'b101010?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // SWL 32'b101010?????????????????????????? ? ? ? 0 ? ? ? ? ? 0 ? ? ? ? // SWL

View File

@ -74,11 +74,11 @@
32'b011100???????????????00000000010 0 0 0 0 ? ? ? ? ? ? ? ? ? ? // MUL 32'b011100???????????????00000000010 0 0 0 0 ? ? ? ? ? ? ? ? ? ? // MUL
32'b100000?????????????????????????? 0 0 0 0 1 0 1 ALIGN 0 0 CNOP 0 0 0 // LB 32'b100000?????????????????????????? 0 0 0 0 1 0 1 ALIGN 0 0 CNOP 0 0 0 // LB
32'b100001?????????????????????????? 0 0 0 0 1 0 1 ALIGN 0 0 CNOP 0 0 0 // LH 32'b100001?????????????????????????? 0 0 0 0 1 0 1 ALIGN 0 0 CNOP 0 0 0 // LH
32'h100010?????????????????????????? 0 0 0 0 1 0 ? ULEFT 0 1 CNOP 0 0 0 // LWL 32'b100010?????????????????????????? 0 0 0 0 1 0 ? ULEFT 0 1 CNOP 0 0 0 // LWL
32'b100011?????????????????????????? 0 0 0 0 1 0 ? ALIGN 0 0 CNOP 0 0 0 // LW 32'b100011?????????????????????????? 0 0 0 0 1 0 ? ALIGN 0 0 CNOP 0 0 0 // LW
32'b100100?????????????????????????? 0 0 0 0 1 0 0 ALIGN 0 0 CNOP 0 0 0 // LBU 32'b100100?????????????????????????? 0 0 0 0 1 0 0 ALIGN 0 0 CNOP 0 0 0 // LBU
32'b100101?????????????????????????? 0 0 0 0 1 0 0 ALIGN 0 0 CNOP 0 0 0 // LHU 32'b100101?????????????????????????? 0 0 0 0 1 0 0 ALIGN 0 0 CNOP 0 0 0 // LHU
32'h100110?????????????????????????? 0 0 0 0 1 0 ? URIGHT 1 0 CNOP 0 0 0 // LWR 32'b100110?????????????????????????? 0 0 0 0 1 0 ? URIGHT 1 0 CNOP 0 0 0 // LWR
32'b101000?????????????????????????? 0 0 0 0 1 1 ? ALIGN 0 0 CNOP 0 0 0 // SB 32'b101000?????????????????????????? 0 0 0 0 1 1 ? ALIGN 0 0 CNOP 0 0 0 // SB
32'b101001?????????????????????????? 0 0 0 0 1 1 ? ALIGN 0 0 CNOP 0 0 0 // SH 32'b101001?????????????????????????? 0 0 0 0 1 1 ? ALIGN 0 0 CNOP 0 0 0 // SH
32'b101010?????????????????????????? 0 0 0 0 1 1 ? ULEFT 0 1 CNOP 0 0 0 // SWL 32'b101010?????????????????????????? 0 0 0 0 1 1 ? ULEFT 0 1 CNOP 0 0 0 // SWL

View File

@ -74,11 +74,11 @@
32'b011100???????????????00000000010 0 0 0 0 // MUL 32'b011100???????????????00000000010 0 0 0 0 // MUL
32'b100000?????????????????????????? 0 0 0 0 // LB 32'b100000?????????????????????????? 0 0 0 0 // LB
32'b100001?????????????????????????? 0 0 0 0 // LH 32'b100001?????????????????????????? 0 0 0 0 // LH
32'h100010?????????????????????????? 0 0 0 0 // LWL 32'b100010?????????????????????????? 0 0 0 0 // LWL
32'b100011?????????????????????????? 0 0 0 0 // LW 32'b100011?????????????????????????? 0 0 0 0 // LW
32'b100100?????????????????????????? 0 0 0 0 // LBU 32'b100100?????????????????????????? 0 0 0 0 // LBU
32'b100101?????????????????????????? 0 0 0 0 // LHU 32'b100101?????????????????????????? 0 0 0 0 // LHU
32'h100110?????????????????????????? 0 0 0 0 // LWR 32'b100110?????????????????????????? 0 0 0 0 // LWR
32'b101000?????????????????????????? 0 0 0 0 // SB 32'b101000?????????????????????????? 0 0 0 0 // SB
32'b101001?????????????????????????? 0 0 0 0 // SH 32'b101001?????????????????????????? 0 0 0 0 // SH
32'b101010?????????????????????????? 0 0 0 0 // SWL 32'b101010?????????????????????????? 0 0 0 0 // SWL

View File

@ -74,11 +74,11 @@
32'b011100???????????????00000000010 0 // MUL 32'b011100???????????????00000000010 0 // MUL
32'b100000?????????????????????????? 0 // LB 32'b100000?????????????????????????? 0 // LB
32'b100001?????????????????????????? 0 // LH 32'b100001?????????????????????????? 0 // LH
32'h100010?????????????????????????? 0 // LWL 32'b100010?????????????????????????? 0 // LWL
32'b100011?????????????????????????? 0 // LW 32'b100011?????????????????????????? 0 // LW
32'b100100?????????????????????????? 0 // LBU 32'b100100?????????????????????????? 0 // LBU
32'b100101?????????????????????????? 0 // LHU 32'b100101?????????????????????????? 0 // LHU
32'h100110?????????????????????????? 0 // LWR 32'b100110?????????????????????????? 0 // LWR
32'b101000?????????????????????????? 0 // SB 32'b101000?????????????????????????? 0 // SB
32'b101001?????????????????????????? 0 // SH 32'b101001?????????????????????????? 0 // SH
32'b101010?????????????????????????? 0 // SWL 32'b101010?????????????????????????? 0 // SWL

87
tools/test1.txt Normal file
View 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 ????? ????? ????? ????? ??????

View File

@ -74,11 +74,11 @@
32'b011100???????????????00000000010 0 ? ? ? // MUL 32'b011100???????????????00000000010 0 ? ? ? // MUL
32'b100000?????????????????????????? 0 ? ? ? // LB 32'b100000?????????????????????????? 0 ? ? ? // LB
32'b100001?????????????????????????? 0 ? ? ? // LH 32'b100001?????????????????????????? 0 ? ? ? // LH
32'h100010?????????????????????????? 0 ? ? ? // LWL 32'b100010?????????????????????????? 0 ? ? ? // LWL
32'b100011?????????????????????????? 0 ? ? ? // LW 32'b100011?????????????????????????? 0 ? ? ? // LW
32'b100100?????????????????????????? 0 ? ? ? // LBU 32'b100100?????????????????????????? 0 ? ? ? // LBU
32'b100101?????????????????????????? 0 ? ? ? // LHU 32'b100101?????????????????????????? 0 ? ? ? // LHU
32'h100110?????????????????????????? 0 ? ? ? // LWR 32'b100110?????????????????????????? 0 ? ? ? // LWR
32'b101000?????????????????????????? 0 ? ? ? // SB 32'b101000?????????????????????????? 0 ? ? ? // SB
32'b101001?????????????????????????? 0 ? ? ? // SH 32'b101001?????????????????????????? 0 ? ? ? // SH
32'b101010?????????????????????????? 0 ? ? ? // SWL 32'b101010?????????????????????????? 0 ? ? ? // SWL

View File

@ -74,11 +74,11 @@
32'b011100???????????????00000000010 0 1 RD 0 0 // MUL 32'b011100???????????????00000000010 0 1 RD 0 0 // MUL
32'b100000?????????????????????????? 0 1 RT 1 ? // LB 32'b100000?????????????????????????? 0 1 RT 1 ? // LB
32'b100001?????????????????????????? 0 1 RT 1 ? // LH 32'b100001?????????????????????????? 0 1 RT 1 ? // LH
32'h100010?????????????????????????? 0 1 RT 1 ? // LWL 32'b100010?????????????????????????? 0 1 RT 1 ? // LWL
32'b100011?????????????????????????? 0 1 RT 1 ? // LW 32'b100011?????????????????????????? 0 1 RT 1 ? // LW
32'b100100?????????????????????????? 0 1 RT 1 ? // LBU 32'b100100?????????????????????????? 0 1 RT 1 ? // LBU
32'b100101?????????????????????????? 0 1 RT 1 ? // LHU 32'b100101?????????????????????????? 0 1 RT 1 ? // LHU
32'h100110?????????????????????????? 0 1 RT 1 ? // LWR 32'b100110?????????????????????????? 0 1 RT 1 ? // LWR
32'b101000?????????????????????????? 0 0 ? ? ? // SB 32'b101000?????????????????????????? 0 0 ? ? ? // SB
32'b101001?????????????????????????? 0 0 ? ? ? // SH 32'b101001?????????????????????????? 0 0 ? ? ? // SH
32'b101010?????????????????????????? 0 0 ? ? ? // SWL 32'b101010?????????????????????????? 0 0 ? ? ? // SWL