cva6: Updating the core files
Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
parent
5760c5ba1e
commit
b3e6bacc58
|
@ -38,15 +38,20 @@ GCC_FLAGS = {
|
|||
# Helpers ------------------------------------------------------------------------------------------
|
||||
|
||||
def add_manifest_sources(platform, manifest):
|
||||
basedir = get_data_mod("cpu", "cva6").data_location
|
||||
with open(os.path.join(basedir, manifest), 'r') as f:
|
||||
cva6_dir = get_data_mod("cpu", "cva6").data_location
|
||||
lx_core_dir = os.path.abspath(os.path.dirname(__file__))
|
||||
with open(os.path.join(manifest), 'r') as f:
|
||||
for l in f:
|
||||
res = re.search('\$\{CVA6_REPO_DIR\}/(.+)', l)
|
||||
res = re.search('\$\{(CVA6_REPO_DIR|LX_CVA6_CORE_DIR)\}/(.+)', l)
|
||||
if res and not re.match('//', l):
|
||||
if re.match('\+incdir\+', l):
|
||||
platform.add_verilog_include_path(os.path.join(basedir, res.group(1)))
|
||||
if res.group(1) == "LX_CVA6_CORE_DIR":
|
||||
basedir = lx_core_dir
|
||||
else:
|
||||
platform.add_source(os.path.join(basedir, res.group(1)))
|
||||
basedir = cva6_dir
|
||||
if re.match('\+incdir\+', l):
|
||||
platform.add_verilog_include_path(os.path.join(basedir, res.group(2)))
|
||||
else:
|
||||
platform.add_source(os.path.join(basedir, res.group(2)))
|
||||
|
||||
# CVA6 ---------------------------------------------------------------------------------------------
|
||||
|
||||
|
@ -154,9 +159,14 @@ class CVA6(CPU):
|
|||
)
|
||||
|
||||
# Add Verilog sources.
|
||||
# Defines must come first
|
||||
wrapper_root = os.path.join(os.path.abspath(os.path.dirname(__file__)), "cva6_wrapper")
|
||||
platform.add_source(os.path.join(wrapper_root, "cva6_defines.sv"))
|
||||
# TODO: use Flist.cv64a6_imafdc_sv39 and Flist.cv32a6_imac_sv0 instead
|
||||
add_manifest_sources(platform, "Flist.cv64a6_imafdc_sv39")
|
||||
add_manifest_sources(platform, "Flist.cva6_wrapper")
|
||||
add_manifest_sources(platform, os.path.join(get_data_mod("cpu", "cva6").data_location,
|
||||
"core", "Flist.cv64a6_imafdc_sv39"))
|
||||
# Add wrapper sources
|
||||
add_manifest_sources(platform, os.path.join(wrapper_root, "Flist.cva6_wrapper"))
|
||||
|
||||
def add_jtag(self, pads):
|
||||
from migen.fhdl.specials import Tristate
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
${CVA6_REPO_DIR}/corev_apu/riscv-dbg/src/dm_pkg.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/riscv-dbg/debug_rom/debug_rom.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/riscv-dbg/debug_rom/debug_rom_one_scratch.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/riscv-dbg/src/dm_csrs.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/riscv-dbg/src/dm_mem.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/riscv-dbg/src/dm_top.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/riscv-dbg/src/dm_obi_top.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/riscv-dbg/src/dmi_cdc.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/riscv-dbg/src/dmi_jtag.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/riscv-dbg/src/dmi_jtag_tap.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/riscv-dbg/src/dm_sba.sv
|
||||
|
||||
+incdir+${CVA6_REPO_DIR}/corev_apu/rv_plic/rtl
|
||||
|
||||
${CVA6_REPO_DIR}/corev_apu/rv_plic/rtl/top_pkg.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/rv_plic/rtl/tlul_pkg.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/rv_plic/rtl/rv_plic_reg_pkg.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/rv_plic/rtl/plic_regmap.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/rv_plic/rtl/plic_top.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/rv_plic/rtl/prim_subreg_ext.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/rv_plic/rtl/prim_subreg.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/rv_plic/rtl/rv_plic_gateway.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/rv_plic/rtl/rv_plic_reg_top.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/rv_plic/rtl/rv_plic.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/rv_plic/rtl/rv_plic_target.sv
|
||||
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_err_slv.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_atop_filter.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_burst_splitter.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_cdc_dst.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_cdc_src.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_cdc.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_cut.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_delayer.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_demux.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_dw_converter.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_dw_downsizer.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_dw_upsizer.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_err_slv.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_id_prepend.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_id_serialize.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_intf.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_isolate.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_iw_converter.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_join.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_lite_demux.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_lite_join.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_lite_mailbox.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_lite_mux.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_lite_regs.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_lite_to_apb.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_lite_to_axi.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_lite_xbar.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_modify_address.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_multicut.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_mux.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_pkg.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_serializer.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_to_axi_lite.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_xbar.sv
|
||||
|
||||
${CVA6_REPO_DIR}/corev_apu/axi_mem_if/src/axi2mem.sv
|
||||
${CVA6_REPO_DIR}/core/axi_adapter.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/fpga/src/axi2apb/src/axi2apb_64_32.sv
|
||||
|
||||
${CVA6_REPO_DIR}/corev_apu/register_interface/src/apb_to_reg.sv
|
||||
|
||||
${CVA6_REPO_DIR}/corev_apu/fpga/src/axi_slice/src/axi_ar_buffer.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/fpga/src/axi_slice/src/axi_aw_buffer.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/fpga/src/axi_slice/src/axi_b_buffer.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/fpga/src/axi_slice/src/axi_r_buffer.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/fpga/src/axi_slice/src/axi_single_slice.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/fpga/src/axi_slice/src/axi_slice.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/fpga/src/axi_slice/src/axi_slice_wrap.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/fpga/src/axi_slice/src/axi_w_buffer.sv
|
||||
|
||||
${CVA6_REPO_DIR}/corev_apu/clint/clint.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/clint/axi_lite_interface.sv
|
||||
|
||||
${CVA6_REPO_DIR}/common/submodules/common_cells/src/deprecated/fifo_v1.sv
|
||||
${CVA6_REPO_DIR}/common/submodules/common_cells/src/deprecated/fifo_v2.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/src/tech_cells_generic/src/deprecated/pulp_clk_cells.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/src/tech_cells_generic/src/deprecated/cluster_clk_cells.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/src/tech_cells_generic/src/rtl/tc_clk.sv
|
||||
${CVA6_REPO_DIR}/corev_apu/axi/src/axi_xbar.sv
|
||||
|
||||
+incdir+${CVA6_REPO_DIR}/corev_apu/axi/include
|
||||
+incdir+${CVA6_REPO_DIR}/corev_apu/register_interface/include/
|
||||
+incdir+${LX_CVA6_CORE_DIR}/cva6_wrapper
|
||||
|
||||
${CVA6_REPO_DIR}/corev_apu/register_interface/src/reg_intf.sv
|
||||
|
||||
// ${LX_CVA6_CORE_DIR}/cva6_wrapper/ariane_pkg.sv
|
||||
${LX_CVA6_CORE_DIR}/cva6_wrapper/cva6_wrapper_pkg.sv
|
||||
${LX_CVA6_CORE_DIR}/cva6_wrapper/cva6_wrapper.sv
|
||||
|
|
@ -0,0 +1,886 @@
|
|||
/* Copyright 2018 ETH Zurich and University of Bologna.
|
||||
* Copyright and related rights are licensed under the Solderpad Hardware
|
||||
* License, Version 0.51 (the “License”); you may not use this file except in
|
||||
* compliance with the License. You may obtain a copy of the License at
|
||||
* http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
|
||||
* or agreed to in writing, software, hardware and materials distributed under
|
||||
* this License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR
|
||||
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations under the License.
|
||||
*
|
||||
* File: ariane_pkg.sv
|
||||
* Author: Florian Zaruba <zarubaf@iis.ee.ethz.ch>
|
||||
* Date: 8.4.2017
|
||||
*
|
||||
* Description: Contains all the necessary defines for Ariane
|
||||
* in one package.
|
||||
*/
|
||||
|
||||
// this is needed to propagate the
|
||||
// configuration in case Ariane is
|
||||
// instantiated in OpenPiton
|
||||
`ifdef PITON_ARIANE
|
||||
`include "l15.tmp.h"
|
||||
`endif
|
||||
|
||||
package ariane_pkg;
|
||||
|
||||
`define WT_DCACHE
|
||||
|
||||
// ---------------
|
||||
// Global Config
|
||||
// ---------------
|
||||
// This is the new user config interface system. If you need to parameterize something
|
||||
// within Ariane add a field here and assign a default value to the config. Please make
|
||||
// sure to add a propper parameter check to the `check_cfg` function.
|
||||
localparam NrMaxRules = 16;
|
||||
|
||||
typedef struct packed {
|
||||
int RASDepth;
|
||||
int BTBEntries;
|
||||
int BHTEntries;
|
||||
// PMAs
|
||||
int unsigned NrNonIdempotentRules; // Number of non idempotent rules
|
||||
logic [NrMaxRules-1:0][63:0] NonIdempotentAddrBase; // base which needs to match
|
||||
logic [NrMaxRules-1:0][63:0] NonIdempotentLength; // bit mask which bits to consider when matching the rule
|
||||
int unsigned NrExecuteRegionRules; // Number of regions which have execute property
|
||||
logic [NrMaxRules-1:0][63:0] ExecuteRegionAddrBase; // base which needs to match
|
||||
logic [NrMaxRules-1:0][63:0] ExecuteRegionLength; // bit mask which bits to consider when matching the rule
|
||||
int unsigned NrCachedRegionRules; // Number of regions which have cached property
|
||||
logic [NrMaxRules-1:0][63:0] CachedRegionAddrBase; // base which needs to match
|
||||
logic [NrMaxRules-1:0][63:0] CachedRegionLength; // bit mask which bits to consider when matching the rule
|
||||
// cache config
|
||||
bit Axi64BitCompliant; // set to 1 when using in conjunction with 64bit AXI bus adapter
|
||||
bit SwapEndianess; // set to 1 to swap endianess inside L1.5 openpiton adapter
|
||||
//
|
||||
logic [63:0] DmBaseAddress; // offset of the debug module
|
||||
int unsigned NrPMPEntries; // Number of PMP entries
|
||||
} ariane_cfg_t;
|
||||
|
||||
localparam ariane_cfg_t ArianeDefaultConfig = '{
|
||||
RASDepth: 2,
|
||||
BTBEntries: 32,
|
||||
BHTEntries: 128,
|
||||
// idempotent region
|
||||
NrNonIdempotentRules: 2,
|
||||
NonIdempotentAddrBase: {64'b0, 64'b0},
|
||||
NonIdempotentLength: {64'b0, 64'b0},
|
||||
NrExecuteRegionRules: 3,
|
||||
// DRAM, Boot ROM, Debug Module
|
||||
ExecuteRegionAddrBase: {64'h8000_0000, 64'h1_0000, 64'h0},
|
||||
ExecuteRegionLength: {64'h40000000, 64'h10000, 64'h1000},
|
||||
// cached region
|
||||
NrCachedRegionRules: 1,
|
||||
CachedRegionAddrBase: {64'h8000_0000},
|
||||
CachedRegionLength: {64'h40000000},
|
||||
// cache config
|
||||
Axi64BitCompliant: 1'b1,
|
||||
SwapEndianess: 1'b0,
|
||||
// debug
|
||||
DmBaseAddress: 64'h0,
|
||||
NrPMPEntries: 8
|
||||
};
|
||||
|
||||
// Function being called to check parameters
|
||||
function automatic void check_cfg (ariane_cfg_t Cfg);
|
||||
// pragma translate_off
|
||||
`ifndef VERILATOR
|
||||
assert(Cfg.RASDepth > 0);
|
||||
assert(2**$clog2(Cfg.BTBEntries) == Cfg.BTBEntries);
|
||||
assert(2**$clog2(Cfg.BHTEntries) == Cfg.BHTEntries);
|
||||
assert(Cfg.NrNonIdempotentRules <= NrMaxRules);
|
||||
assert(Cfg.NrExecuteRegionRules <= NrMaxRules);
|
||||
assert(Cfg.NrCachedRegionRules <= NrMaxRules);
|
||||
assert(Cfg.NrPMPEntries <= 16);
|
||||
`endif
|
||||
// pragma translate_on
|
||||
endfunction
|
||||
|
||||
function automatic logic range_check(logic[63:0] base, logic[63:0] len, logic[63:0] address);
|
||||
// if len is a power of two, and base is properly aligned, this check could be simplified
|
||||
return (address >= base) && (address < (65'(base)+len));
|
||||
endfunction : range_check
|
||||
|
||||
function automatic logic is_inside_nonidempotent_regions (ariane_cfg_t Cfg, logic[63:0] address);
|
||||
logic[NrMaxRules-1:0] pass;
|
||||
pass = '0;
|
||||
for (int unsigned k = 0; k < Cfg.NrNonIdempotentRules; k++) begin
|
||||
pass[k] = range_check(Cfg.NonIdempotentAddrBase[k], Cfg.NonIdempotentLength[k], address);
|
||||
end
|
||||
return |pass;
|
||||
endfunction : is_inside_nonidempotent_regions
|
||||
|
||||
function automatic logic is_inside_execute_regions (ariane_cfg_t Cfg, logic[63:0] address);
|
||||
// if we don't specify any region we assume everything is accessible
|
||||
logic[NrMaxRules-1:0] pass;
|
||||
pass = '0;
|
||||
for (int unsigned k = 0; k < Cfg.NrExecuteRegionRules; k++) begin
|
||||
pass[k] = range_check(Cfg.ExecuteRegionAddrBase[k], Cfg.ExecuteRegionLength[k], address);
|
||||
end
|
||||
return |pass;
|
||||
endfunction : is_inside_execute_regions
|
||||
|
||||
function automatic logic is_inside_cacheable_regions (ariane_cfg_t Cfg, logic[63:0] address);
|
||||
automatic logic[NrMaxRules-1:0] pass;
|
||||
pass = '0;
|
||||
for (int unsigned k = 0; k < Cfg.NrCachedRegionRules; k++) begin
|
||||
pass[k] = range_check(Cfg.CachedRegionAddrBase[k], Cfg.CachedRegionLength[k], address);
|
||||
end
|
||||
return |pass;
|
||||
endfunction : is_inside_cacheable_regions
|
||||
|
||||
// TODO: Slowly move those parameters to the new system.
|
||||
localparam NR_SB_ENTRIES = 8; // number of scoreboard entries
|
||||
localparam TRANS_ID_BITS = $clog2(NR_SB_ENTRIES); // depending on the number of scoreboard entries we need that many bits
|
||||
// to uniquely identify the entry in the scoreboard
|
||||
localparam ASID_WIDTH = (riscv::XLEN == 64) ? 16 : 1;
|
||||
localparam BITS_SATURATION_COUNTER = 2;
|
||||
localparam NR_COMMIT_PORTS = 2;
|
||||
|
||||
localparam ENABLE_RENAME = 1'b0;
|
||||
|
||||
localparam ISSUE_WIDTH = 1;
|
||||
// amount of pipeline registers inserted for load/store return path
|
||||
// this can be tuned to trade-off IPC vs. cycle time
|
||||
localparam int unsigned NR_LOAD_PIPE_REGS = 1;
|
||||
localparam int unsigned NR_STORE_PIPE_REGS = 0;
|
||||
|
||||
// depth of store-buffers, this needs to be a power of two
|
||||
localparam int unsigned DEPTH_SPEC = 4;
|
||||
|
||||
`ifdef WT_DCACHE
|
||||
// in this case we can use a small commit queue since we have a write buffer in the dcache
|
||||
// we could in principle do without the commit queue in this case, but the timing degrades if we do that due
|
||||
// to longer paths into the commit stage
|
||||
localparam int unsigned DEPTH_COMMIT = 4;
|
||||
`else
|
||||
// allocate more space for the commit buffer to be on the save side, this needs to be a power of two
|
||||
localparam int unsigned DEPTH_COMMIT = 8;
|
||||
`endif
|
||||
localparam bit RVC = cva6_config_pkg::CVA6ConfigCExtEn; // Is C extension configuration
|
||||
|
||||
`ifdef PITON_ARIANE
|
||||
// Floating-point extensions configuration
|
||||
localparam bit RVF = riscv::IS_XLEN64; // Is F extension enabled
|
||||
localparam bit RVD = riscv::IS_XLEN64; // Is D extension enabled
|
||||
`else
|
||||
// Floating-point extensions configuration
|
||||
localparam bit RVF = (riscv::IS_XLEN64 | riscv::IS_XLEN32) & riscv::FPU_EN; // Is F extension enabled for both 32 Bit and 64 bit CPU
|
||||
localparam bit RVD = (riscv::IS_XLEN64 ? 1:0) & riscv::FPU_EN; // Is D extension enabled for only 64 bit CPU
|
||||
`endif
|
||||
localparam bit RVA = 1'b1; // Is A extension enabled
|
||||
|
||||
// Transprecision floating-point extensions configuration
|
||||
localparam bit XF16 = 1'b0; // Is half-precision float extension (Xf16) enabled
|
||||
localparam bit XF16ALT = 1'b0; // Is alternative half-precision float extension (Xf16alt) enabled
|
||||
localparam bit XF8 = 1'b0; // Is quarter-precision float extension (Xf8) enabled
|
||||
localparam bit XFVEC = 1'b0; // Is vectorial float extension (Xfvec) enabled
|
||||
|
||||
// Transprecision float unit
|
||||
localparam int unsigned LAT_COMP_FP32 = 'd2;
|
||||
localparam int unsigned LAT_COMP_FP64 = 'd3;
|
||||
localparam int unsigned LAT_COMP_FP16 = 'd1;
|
||||
localparam int unsigned LAT_COMP_FP16ALT = 'd1;
|
||||
localparam int unsigned LAT_COMP_FP8 = 'd1;
|
||||
localparam int unsigned LAT_DIVSQRT = 'd2;
|
||||
localparam int unsigned LAT_NONCOMP = 'd1;
|
||||
localparam int unsigned LAT_CONV = 'd2;
|
||||
|
||||
// --------------------------------------
|
||||
// vvvv Don't change these by hand! vvvv
|
||||
localparam bit FP_PRESENT = RVF | RVD | XF16 | XF16ALT | XF8;
|
||||
|
||||
// Length of widest floating-point format
|
||||
localparam FLEN = RVD ? 64 : // D ext.
|
||||
RVF ? 32 : // F ext.
|
||||
XF16 ? 16 : // Xf16 ext.
|
||||
XF16ALT ? 16 : // Xf16alt ext.
|
||||
XF8 ? 8 : // Xf8 ext.
|
||||
1; // Unused in case of no FP
|
||||
|
||||
localparam bit NSX = XF16 | XF16ALT | XF8 | XFVEC; // Are non-standard extensions present?
|
||||
|
||||
localparam bit RVFVEC = RVF & XFVEC & FLEN>32; // FP32 vectors available if vectors and larger fmt enabled
|
||||
localparam bit XF16VEC = XF16 & XFVEC & FLEN>16; // FP16 vectors available if vectors and larger fmt enabled
|
||||
localparam bit XF16ALTVEC = XF16ALT & XFVEC & FLEN>16; // FP16ALT vectors available if vectors and larger fmt enabled
|
||||
localparam bit XF8VEC = XF8 & XFVEC & FLEN>8; // FP8 vectors available if vectors and larger fmt enabled
|
||||
// ^^^^ until here ^^^^
|
||||
// ---------------------
|
||||
|
||||
localparam riscv::xlen_t ARIANE_MARCHID = {{riscv::XLEN-32{1'b0}}, 32'd3};
|
||||
|
||||
localparam riscv::xlen_t ISA_CODE = (RVA << 0) // A - Atomic Instructions extension
|
||||
| (RVC << 2) // C - Compressed extension
|
||||
| (RVD << 3) // D - Double precsision floating-point extension
|
||||
| (RVF << 5) // F - Single precsision floating-point extension
|
||||
| (1 << 8) // I - RV32I/64I/128I base ISA
|
||||
| (1 << 12) // M - Integer Multiply/Divide extension
|
||||
| (0 << 13) // N - User level interrupts supported
|
||||
| (1 << 18) // S - Supervisor mode implemented
|
||||
| (1 << 20) // U - User mode implemented
|
||||
| (NSX << 23) // X - Non-standard extensions present
|
||||
| ((riscv::XLEN == 64 ? 2 : 1) << riscv::XLEN-2); // MXL
|
||||
|
||||
// 32 registers + 1 bit for re-naming = 6
|
||||
localparam REG_ADDR_SIZE = 6;
|
||||
localparam NR_WB_PORTS = 5;
|
||||
|
||||
// Read ports for general purpose register files
|
||||
localparam NR_RGPR_PORTS = 2;
|
||||
typedef logic [(NR_RGPR_PORTS == 3 ? riscv::XLEN : FLEN)-1:0] rs3_len_t;
|
||||
|
||||
// static debug hartinfo
|
||||
localparam dm::hartinfo_t DebugHartInfo = '{
|
||||
zero1: '0,
|
||||
nscratch: 2, // Debug module needs at least two scratch regs
|
||||
zero0: '0,
|
||||
dataaccess: 1'b1, // data registers are memory mapped in the debugger
|
||||
datasize: dm::DataCount,
|
||||
dataaddr: dm::DataAddr
|
||||
};
|
||||
|
||||
// enables a commit log which matches spikes commit log format for easier trace comparison
|
||||
localparam bit ENABLE_SPIKE_COMMIT_LOG = 1'b1;
|
||||
|
||||
// ------------- Dangerouse -------------
|
||||
// if set to zero a flush will not invalidate the cache-lines, in a single core environment
|
||||
// where coherence is not necessary this can improve performance. This needs to be switched on
|
||||
// when more than one core is in a system
|
||||
localparam logic INVALIDATE_ON_FLUSH = 1'b1;
|
||||
`ifdef SPIKE_TANDEM
|
||||
// enable performance cycle counter, if set to zero mcycle will be incremented
|
||||
// with instret (non RISC-V conformal)
|
||||
localparam bit ENABLE_CYCLE_COUNT = 1'b0;
|
||||
// mark WIF as nop
|
||||
localparam bit ENABLE_WFI = 1'b0;
|
||||
// Spike zeros tval on all exception except memory faults
|
||||
localparam bit ZERO_TVAL = 1'b1;
|
||||
`else
|
||||
localparam bit ENABLE_CYCLE_COUNT = 1'b1;
|
||||
localparam bit ENABLE_WFI = 1'b1;
|
||||
localparam bit ZERO_TVAL = 1'b0;
|
||||
`endif
|
||||
// read mask for SSTATUS over MMSTATUS
|
||||
localparam logic [63:0] SMODE_STATUS_READ_MASK = riscv::SSTATUS_UIE
|
||||
| riscv::SSTATUS_SIE
|
||||
| riscv::SSTATUS_SPIE
|
||||
| riscv::SSTATUS_SPP
|
||||
| riscv::SSTATUS_FS
|
||||
| riscv::SSTATUS_XS
|
||||
| riscv::SSTATUS_SUM
|
||||
| riscv::SSTATUS_MXR
|
||||
| riscv::SSTATUS_UPIE
|
||||
| riscv::SSTATUS_SPIE
|
||||
| riscv::SSTATUS_UXL
|
||||
| riscv::SSTATUS_SD;
|
||||
|
||||
localparam logic [63:0] SMODE_STATUS_WRITE_MASK = riscv::SSTATUS_SIE
|
||||
| riscv::SSTATUS_SPIE
|
||||
| riscv::SSTATUS_SPP
|
||||
| riscv::SSTATUS_FS
|
||||
| riscv::SSTATUS_SUM
|
||||
| riscv::SSTATUS_MXR;
|
||||
// ---------------
|
||||
// Fetch Stage
|
||||
// ---------------
|
||||
|
||||
// leave as is (fails with >8 entries and wider fetch width)
|
||||
localparam int unsigned FETCH_FIFO_DEPTH = 4;
|
||||
localparam int unsigned FETCH_WIDTH = 32;
|
||||
// maximum instructions we can fetch on one request (we support compressed instructions)
|
||||
localparam int unsigned INSTR_PER_FETCH = RVC == 1'b1 ? (FETCH_WIDTH / 16) : 1;
|
||||
localparam int unsigned LOG2_INSTR_PER_FETCH = RVC == 1'b1 ? 1 : $clog2(ariane_pkg::INSTR_PER_FETCH);
|
||||
|
||||
// Only use struct when signals have same direction
|
||||
// exception
|
||||
typedef struct packed {
|
||||
riscv::xlen_t cause; // cause of exception
|
||||
riscv::xlen_t tval; // additional information of causing exception (e.g.: instruction causing it),
|
||||
// address of LD/ST fault
|
||||
logic valid;
|
||||
} exception_t;
|
||||
|
||||
typedef enum logic [2:0] {
|
||||
NoCF, // No control flow prediction
|
||||
Branch, // Branch
|
||||
Jump, // Jump to address from immediate
|
||||
JumpR, // Jump to address from registers
|
||||
Return // Return Address Prediction
|
||||
} cf_t;
|
||||
|
||||
// branch-predict
|
||||
// this is the struct we get back from ex stage and we will use it to update
|
||||
// all the necessary data structures
|
||||
// bp_resolve_t
|
||||
typedef struct packed {
|
||||
logic valid; // prediction with all its values is valid
|
||||
logic [riscv::VLEN-1:0] pc; // PC of predict or mis-predict
|
||||
logic [riscv::VLEN-1:0] target_address; // target address at which to jump, or not
|
||||
logic is_mispredict; // set if this was a mis-predict
|
||||
logic is_taken; // branch is taken
|
||||
cf_t cf_type; // Type of control flow change
|
||||
} bp_resolve_t;
|
||||
|
||||
// branchpredict scoreboard entry
|
||||
// this is the struct which we will inject into the pipeline to guide the various
|
||||
// units towards the correct branch decision and resolve
|
||||
typedef struct packed {
|
||||
cf_t cf; // type of control flow prediction
|
||||
logic [riscv::VLEN-1:0] predict_address; // target address at which to jump, or not
|
||||
} branchpredict_sbe_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic valid;
|
||||
logic [riscv::VLEN-1:0] pc; // update at PC
|
||||
logic [riscv::VLEN-1:0] target_address;
|
||||
} btb_update_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic valid;
|
||||
logic [riscv::VLEN-1:0] target_address;
|
||||
} btb_prediction_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic valid;
|
||||
logic [riscv::VLEN-1:0] ra;
|
||||
} ras_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic valid;
|
||||
logic [riscv::VLEN-1:0] pc; // update at PC
|
||||
logic taken;
|
||||
} bht_update_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic valid;
|
||||
logic taken;
|
||||
} bht_prediction_t;
|
||||
|
||||
typedef enum logic[3:0] {
|
||||
NONE, // 0
|
||||
LOAD, // 1
|
||||
STORE, // 2
|
||||
ALU, // 3
|
||||
CTRL_FLOW, // 4
|
||||
MULT, // 5
|
||||
CSR, // 6
|
||||
FPU, // 7
|
||||
FPU_VEC, // 8
|
||||
CVXIF // 9
|
||||
} fu_t;
|
||||
|
||||
localparam EXC_OFF_RST = 8'h80;
|
||||
|
||||
localparam SupervisorIrq = 1;
|
||||
localparam MachineIrq = 0;
|
||||
|
||||
// All information needed to determine whether we need to associate an interrupt
|
||||
// with the corresponding instruction or not.
|
||||
typedef struct packed {
|
||||
riscv::xlen_t mie;
|
||||
riscv::xlen_t mip;
|
||||
riscv::xlen_t mideleg;
|
||||
logic sie;
|
||||
logic global_enable;
|
||||
} irq_ctrl_t;
|
||||
|
||||
// ---------------
|
||||
// Cache config
|
||||
// ---------------
|
||||
|
||||
// for usage in OpenPiton we have to propagate the openpiton L15 configuration from l15.h
|
||||
`ifdef PITON_ARIANE
|
||||
|
||||
`ifndef CONFIG_L1I_CACHELINE_WIDTH
|
||||
`define CONFIG_L1I_CACHELINE_WIDTH 128
|
||||
`endif
|
||||
|
||||
`ifndef CONFIG_L1I_ASSOCIATIVITY
|
||||
`define CONFIG_L1I_ASSOCIATIVITY 4
|
||||
`endif
|
||||
|
||||
`ifndef CONFIG_L1I_SIZE
|
||||
`define CONFIG_L1I_SIZE 16*1024
|
||||
`endif
|
||||
|
||||
`ifndef CONFIG_L1D_CACHELINE_WIDTH
|
||||
`define CONFIG_L1D_CACHELINE_WIDTH 128
|
||||
`endif
|
||||
|
||||
`ifndef CONFIG_L1D_ASSOCIATIVITY
|
||||
`define CONFIG_L1D_ASSOCIATIVITY 8
|
||||
`endif
|
||||
|
||||
`ifndef CONFIG_L1D_SIZE
|
||||
`define CONFIG_L1D_SIZE 32*1024
|
||||
`endif
|
||||
|
||||
// I$
|
||||
localparam int unsigned ICACHE_LINE_WIDTH = `CONFIG_L1I_CACHELINE_WIDTH;
|
||||
localparam int unsigned ICACHE_SET_ASSOC = `CONFIG_L1I_ASSOCIATIVITY;
|
||||
localparam int unsigned ICACHE_INDEX_WIDTH = $clog2(`CONFIG_L1I_SIZE / ICACHE_SET_ASSOC);
|
||||
localparam int unsigned ICACHE_TAG_WIDTH = riscv::PLEN - ICACHE_INDEX_WIDTH;
|
||||
// D$
|
||||
localparam int unsigned DCACHE_LINE_WIDTH = `CONFIG_L1D_CACHELINE_WIDTH;
|
||||
localparam int unsigned DCACHE_SET_ASSOC = `CONFIG_L1D_ASSOCIATIVITY;
|
||||
localparam int unsigned DCACHE_INDEX_WIDTH = $clog2(`CONFIG_L1D_SIZE / DCACHE_SET_ASSOC);
|
||||
localparam int unsigned DCACHE_TAG_WIDTH = riscv::PLEN - DCACHE_INDEX_WIDTH;
|
||||
`else
|
||||
// I$
|
||||
localparam int unsigned CONFIG_L1I_SIZE = 16*1024;
|
||||
localparam int unsigned ICACHE_SET_ASSOC = 4; // Must be between 4 to 64
|
||||
localparam int unsigned ICACHE_INDEX_WIDTH = $clog2(CONFIG_L1I_SIZE / ICACHE_SET_ASSOC); // in bit, contains also offset width
|
||||
localparam int unsigned ICACHE_TAG_WIDTH = riscv::PLEN-ICACHE_INDEX_WIDTH; // in bit
|
||||
localparam int unsigned ICACHE_LINE_WIDTH = 128; // in bit
|
||||
// D$
|
||||
localparam int unsigned CONFIG_L1D_SIZE = 32*1024;
|
||||
localparam int unsigned DCACHE_SET_ASSOC = 8; // Must be between 4 to 64
|
||||
localparam int unsigned DCACHE_INDEX_WIDTH = $clog2(CONFIG_L1D_SIZE / DCACHE_SET_ASSOC); // in bit, contains also offset width
|
||||
localparam int unsigned DCACHE_TAG_WIDTH = riscv::PLEN-DCACHE_INDEX_WIDTH; // in bit
|
||||
localparam int unsigned DCACHE_LINE_WIDTH = 128; // in bit
|
||||
`endif
|
||||
|
||||
localparam bit CVXIF_PRESENT = cva6_config_pkg::CVA6ConfigCvxifEn;
|
||||
// ---------------
|
||||
// EX Stage
|
||||
// ---------------
|
||||
typedef enum logic [6:0] { // basic ALU op
|
||||
ADD, SUB, ADDW, SUBW,
|
||||
// logic operations
|
||||
XORL, ORL, ANDL,
|
||||
// shifts
|
||||
SRA, SRL, SLL, SRLW, SLLW, SRAW,
|
||||
// comparisons
|
||||
LTS, LTU, GES, GEU, EQ, NE,
|
||||
// jumps
|
||||
JALR, BRANCH,
|
||||
// set lower than operations
|
||||
SLTS, SLTU,
|
||||
// CSR functions
|
||||
MRET, SRET, DRET, ECALL, WFI, FENCE, FENCE_I, SFENCE_VMA, CSR_WRITE, CSR_READ, CSR_SET, CSR_CLEAR,
|
||||
// LSU functions
|
||||
LD, SD, LW, LWU, SW, LH, LHU, SH, LB, SB, LBU,
|
||||
// Atomic Memory Operations
|
||||
AMO_LRW, AMO_LRD, AMO_SCW, AMO_SCD,
|
||||
AMO_SWAPW, AMO_ADDW, AMO_ANDW, AMO_ORW, AMO_XORW, AMO_MAXW, AMO_MAXWU, AMO_MINW, AMO_MINWU,
|
||||
AMO_SWAPD, AMO_ADDD, AMO_ANDD, AMO_ORD, AMO_XORD, AMO_MAXD, AMO_MAXDU, AMO_MIND, AMO_MINDU,
|
||||
// Multiplications
|
||||
MUL, MULH, MULHU, MULHSU, MULW,
|
||||
// Divisions
|
||||
DIV, DIVU, DIVW, DIVUW, REM, REMU, REMW, REMUW,
|
||||
// Floating-Point Load and Store Instructions
|
||||
FLD, FLW, FLH, FLB, FSD, FSW, FSH, FSB,
|
||||
// Floating-Point Computational Instructions
|
||||
FADD, FSUB, FMUL, FDIV, FMIN_MAX, FSQRT, FMADD, FMSUB, FNMSUB, FNMADD,
|
||||
// Floating-Point Conversion and Move Instructions
|
||||
FCVT_F2I, FCVT_I2F, FCVT_F2F, FSGNJ, FMV_F2X, FMV_X2F,
|
||||
// Floating-Point Compare Instructions
|
||||
FCMP,
|
||||
// Floating-Point Classify Instruction
|
||||
FCLASS,
|
||||
// Vectorial Floating-Point Instructions that don't directly map onto the scalar ones
|
||||
VFMIN, VFMAX, VFSGNJ, VFSGNJN, VFSGNJX, VFEQ, VFNE, VFLT, VFGE, VFLE, VFGT, VFCPKAB_S, VFCPKCD_S, VFCPKAB_D, VFCPKCD_D,
|
||||
// Offload Instructions to be directed into cv_x_if
|
||||
OFFLOAD
|
||||
} fu_op;
|
||||
|
||||
typedef struct packed {
|
||||
fu_t fu;
|
||||
fu_op operator;
|
||||
riscv::xlen_t operand_a;
|
||||
riscv::xlen_t operand_b;
|
||||
riscv::xlen_t imm;
|
||||
logic [TRANS_ID_BITS-1:0] trans_id;
|
||||
} fu_data_t;
|
||||
|
||||
function automatic logic op_is_branch (input fu_op op);
|
||||
unique case (op) inside
|
||||
EQ, NE, LTS, GES, LTU, GEU: return 1'b1;
|
||||
default : return 1'b0; // all other ops
|
||||
endcase
|
||||
endfunction
|
||||
|
||||
// -------------------------------
|
||||
// Extract Src/Dst FP Reg from Op
|
||||
// -------------------------------
|
||||
function automatic logic is_rs1_fpr (input fu_op op);
|
||||
if (FP_PRESENT) begin // makes function static for non-fp case
|
||||
unique case (op) inside
|
||||
[FMUL:FNMADD], // Computational Operations (except ADD/SUB)
|
||||
FCVT_F2I, // Float-Int Casts
|
||||
FCVT_F2F, // Float-Float Casts
|
||||
FSGNJ, // Sign Injections
|
||||
FMV_F2X, // FPR-GPR Moves
|
||||
FCMP, // Comparisons
|
||||
FCLASS, // Classifications
|
||||
[VFMIN:VFCPKCD_D] : return 1'b1; // Additional Vectorial FP ops
|
||||
default : return 1'b0; // all other ops
|
||||
endcase
|
||||
end else
|
||||
return 1'b0;
|
||||
endfunction
|
||||
|
||||
function automatic logic is_rs2_fpr (input fu_op op);
|
||||
if (FP_PRESENT) begin // makes function static for non-fp case
|
||||
unique case (op) inside
|
||||
[FSD:FSB], // FP Stores
|
||||
[FADD:FMIN_MAX], // Computational Operations (no sqrt)
|
||||
[FMADD:FNMADD], // Fused Computational Operations
|
||||
FCVT_F2F, // Vectorial F2F Conversions requrie target
|
||||
[FSGNJ:FMV_F2X], // Sign Injections and moves mapped to SGNJ
|
||||
FCMP, // Comparisons
|
||||
[VFMIN:VFCPKCD_D] : return 1'b1; // Additional Vectorial FP ops
|
||||
default : return 1'b0; // all other ops
|
||||
endcase
|
||||
end else
|
||||
return 1'b0;
|
||||
endfunction
|
||||
|
||||
// ternary operations encode the rs3 address in the imm field, also add/sub
|
||||
function automatic logic is_imm_fpr (input fu_op op);
|
||||
if (FP_PRESENT) begin // makes function static for non-fp case
|
||||
unique case (op) inside
|
||||
[FADD:FSUB], // ADD/SUB need inputs as Operand B/C
|
||||
[FMADD:FNMADD], // Fused Computational Operations
|
||||
[VFCPKAB_S:VFCPKCD_D] : return 1'b1; // Vectorial FP cast and pack ops
|
||||
default : return 1'b0; // all other ops
|
||||
endcase
|
||||
end else
|
||||
return 1'b0;
|
||||
endfunction
|
||||
|
||||
function automatic logic is_rd_fpr (input fu_op op);
|
||||
if (FP_PRESENT) begin // makes function static for non-fp case
|
||||
unique case (op) inside
|
||||
[FLD:FLB], // FP Loads
|
||||
[FADD:FNMADD], // Computational Operations
|
||||
FCVT_I2F, // Int-Float Casts
|
||||
FCVT_F2F, // Float-Float Casts
|
||||
FSGNJ, // Sign Injections
|
||||
FMV_X2F, // GPR-FPR Moves
|
||||
[VFMIN:VFSGNJX], // Vectorial MIN/MAX and SGNJ
|
||||
[VFCPKAB_S:VFCPKCD_D] : return 1'b1; // Vectorial FP cast and pack ops
|
||||
default : return 1'b0; // all other ops
|
||||
endcase
|
||||
end else
|
||||
return 1'b0;
|
||||
endfunction
|
||||
|
||||
function automatic logic is_amo (fu_op op);
|
||||
case (op) inside
|
||||
[AMO_LRW:AMO_MINDU]: begin
|
||||
return 1'b1;
|
||||
end
|
||||
default: return 1'b0;
|
||||
endcase
|
||||
endfunction
|
||||
|
||||
typedef struct packed {
|
||||
logic valid;
|
||||
logic [riscv::VLEN-1:0] vaddr;
|
||||
logic overflow;
|
||||
riscv::xlen_t data;
|
||||
logic [(riscv::XLEN/8)-1:0] be;
|
||||
fu_t fu;
|
||||
fu_op operator;
|
||||
logic [TRANS_ID_BITS-1:0] trans_id;
|
||||
} lsu_ctrl_t;
|
||||
|
||||
// ---------------
|
||||
// IF/ID Stage
|
||||
// ---------------
|
||||
// store the decompressed instruction
|
||||
typedef struct packed {
|
||||
logic [riscv::VLEN-1:0] address; // the address of the instructions from below
|
||||
logic [31:0] instruction; // instruction word
|
||||
branchpredict_sbe_t branch_predict; // this field contains branch prediction information regarding the forward branch path
|
||||
exception_t ex; // this field contains exceptions which might have happened earlier, e.g.: fetch exceptions
|
||||
} fetch_entry_t;
|
||||
|
||||
// ---------------
|
||||
// ID/EX/WB Stage
|
||||
// ---------------
|
||||
typedef struct packed {
|
||||
logic [riscv::VLEN-1:0] pc; // PC of instruction
|
||||
logic [TRANS_ID_BITS-1:0] trans_id; // this can potentially be simplified, we could index the scoreboard entry
|
||||
// with the transaction id in any case make the width more generic
|
||||
fu_t fu; // functional unit to use
|
||||
fu_op op; // operation to perform in each functional unit
|
||||
logic [REG_ADDR_SIZE-1:0] rs1; // register source address 1
|
||||
logic [REG_ADDR_SIZE-1:0] rs2; // register source address 2
|
||||
logic [REG_ADDR_SIZE-1:0] rd; // register destination address
|
||||
riscv::xlen_t result; // for unfinished instructions this field also holds the immediate,
|
||||
// for unfinished floating-point that are partly encoded in rs2, this field also holds rs2
|
||||
// for unfinished floating-point fused operations (FMADD, FMSUB, FNMADD, FNMSUB)
|
||||
// this field holds the address of the third operand from the floating-point register file
|
||||
logic valid; // is the result valid
|
||||
logic use_imm; // should we use the immediate as operand b?
|
||||
logic use_zimm; // use zimm as operand a
|
||||
logic use_pc; // set if we need to use the PC as operand a, PC from exception
|
||||
exception_t ex; // exception has occurred
|
||||
branchpredict_sbe_t bp; // branch predict scoreboard data structure
|
||||
logic is_compressed; // signals a compressed instructions, we need this information at the commit stage if
|
||||
// we want jump accordingly e.g.: +4, +2
|
||||
} scoreboard_entry_t;
|
||||
|
||||
// ---------------
|
||||
// MMU instanciation
|
||||
// ---------------
|
||||
localparam bit MMU_PRESENT = 1'b1; // MMU is present
|
||||
|
||||
// --------------------
|
||||
// Atomics
|
||||
// --------------------
|
||||
typedef enum logic [3:0] {
|
||||
AMO_NONE =4'b0000,
|
||||
AMO_LR =4'b0001,
|
||||
AMO_SC =4'b0010,
|
||||
AMO_SWAP =4'b0011,
|
||||
AMO_ADD =4'b0100,
|
||||
AMO_AND =4'b0101,
|
||||
AMO_OR =4'b0110,
|
||||
AMO_XOR =4'b0111,
|
||||
AMO_MAX =4'b1000,
|
||||
AMO_MAXU =4'b1001,
|
||||
AMO_MIN =4'b1010,
|
||||
AMO_MINU =4'b1011,
|
||||
AMO_CAS1 =4'b1100, // unused, not part of riscv spec, but provided in OpenPiton
|
||||
AMO_CAS2 =4'b1101 // unused, not part of riscv spec, but provided in OpenPiton
|
||||
} amo_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic valid; // valid flag
|
||||
logic is_2M; //
|
||||
logic is_1G; //
|
||||
logic [27-1:0] vpn; // VPN (39bits) = 27bits + 12bits offset
|
||||
logic [ASID_WIDTH-1:0] asid;
|
||||
riscv::pte_t content;
|
||||
} tlb_update_t;
|
||||
|
||||
// Bits required for representation of physical address space as 4K pages
|
||||
// (e.g. 27*4K == 39bit address space).
|
||||
localparam PPN4K_WIDTH = 38;
|
||||
|
||||
typedef struct packed {
|
||||
logic valid; // valid flag
|
||||
logic is_4M; //
|
||||
logic [20-1:0] vpn; //VPN (32bits) = 20bits + 12bits offset
|
||||
logic [9-1:0] asid; //ASID length = 9 for Sv32 mmu
|
||||
riscv::pte_sv32_t content;
|
||||
} tlb_update_sv32_t;
|
||||
|
||||
typedef enum logic [1:0] {
|
||||
FE_NONE,
|
||||
FE_INSTR_ACCESS_FAULT,
|
||||
FE_INSTR_PAGE_FAULT
|
||||
} frontend_exception_t;
|
||||
|
||||
// ----------------------
|
||||
// cache request ports
|
||||
// ----------------------
|
||||
// I$ address translation requests
|
||||
typedef struct packed {
|
||||
logic fetch_valid; // address translation valid
|
||||
logic [riscv::PLEN-1:0] fetch_paddr; // physical address in
|
||||
exception_t fetch_exception; // exception occurred during fetch
|
||||
} icache_areq_i_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic fetch_req; // address translation request
|
||||
logic [riscv::VLEN-1:0] fetch_vaddr; // virtual address out
|
||||
} icache_areq_o_t;
|
||||
|
||||
// I$ data requests
|
||||
typedef struct packed {
|
||||
logic req; // we request a new word
|
||||
logic kill_s1; // kill the current request
|
||||
logic kill_s2; // kill the last request
|
||||
logic spec; // request is speculative
|
||||
logic [riscv::VLEN-1:0] vaddr; // 1st cycle: 12 bit index is taken for lookup
|
||||
} icache_dreq_i_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic ready; // icache is ready
|
||||
logic valid; // signals a valid read
|
||||
logic [FETCH_WIDTH-1:0] data; // 2+ cycle out: tag
|
||||
logic [riscv::VLEN-1:0] vaddr; // virtual address out
|
||||
exception_t ex; // we've encountered an exception
|
||||
} icache_dreq_o_t;
|
||||
|
||||
// AMO request going to cache. this request is unconditionally valid as soon
|
||||
// as request goes high.
|
||||
// Furthermore, those signals are kept stable until the response indicates
|
||||
// completion by asserting ack.
|
||||
typedef struct packed {
|
||||
logic req; // this request is valid
|
||||
amo_t amo_op; // atomic memory operation to perform
|
||||
logic [1:0] size; // 2'b10 --> word operation, 2'b11 --> double word operation
|
||||
logic [63:0] operand_a; // address
|
||||
logic [63:0] operand_b; // data as layouted in the register
|
||||
} amo_req_t;
|
||||
|
||||
// AMO response coming from cache.
|
||||
typedef struct packed {
|
||||
logic ack; // response is valid
|
||||
logic [63:0] result; // sign-extended, result
|
||||
} amo_resp_t;
|
||||
|
||||
// D$ data requests
|
||||
typedef struct packed {
|
||||
logic [DCACHE_INDEX_WIDTH-1:0] address_index;
|
||||
logic [DCACHE_TAG_WIDTH-1:0] address_tag;
|
||||
riscv::xlen_t data_wdata;
|
||||
logic data_req;
|
||||
logic data_we;
|
||||
logic [(riscv::XLEN/8)-1:0] data_be;
|
||||
logic [1:0] data_size;
|
||||
logic kill_req;
|
||||
logic tag_valid;
|
||||
} dcache_req_i_t;
|
||||
|
||||
typedef struct packed {
|
||||
logic data_gnt;
|
||||
logic data_rvalid;
|
||||
riscv::xlen_t data_rdata;
|
||||
} dcache_req_o_t;
|
||||
|
||||
// ----------------------
|
||||
// Arithmetic Functions
|
||||
// ----------------------
|
||||
function automatic riscv::xlen_t sext32 (logic [31:0] operand);
|
||||
return {{riscv::XLEN-32{operand[31]}}, operand[31:0]};
|
||||
endfunction
|
||||
|
||||
// ----------------------
|
||||
// Immediate functions
|
||||
// ----------------------
|
||||
function automatic logic [riscv::VLEN-1:0] uj_imm (logic [31:0] instruction_i);
|
||||
return { {44+riscv::VLEN-64 {instruction_i[31]}}, instruction_i[19:12], instruction_i[20], instruction_i[30:21], 1'b0 };
|
||||
endfunction
|
||||
|
||||
function automatic logic [riscv::VLEN-1:0] i_imm (logic [31:0] instruction_i);
|
||||
return { {52+riscv::VLEN-64 {instruction_i[31]}}, instruction_i[31:20] };
|
||||
endfunction
|
||||
|
||||
function automatic logic [riscv::VLEN-1:0] sb_imm (logic [31:0] instruction_i);
|
||||
return { {51+riscv::VLEN-64 {instruction_i[31]}}, instruction_i[31], instruction_i[7], instruction_i[30:25], instruction_i[11:8], 1'b0 };
|
||||
endfunction
|
||||
|
||||
// ----------------------
|
||||
// LSU Functions
|
||||
// ----------------------
|
||||
// align data to address e.g.: shift data to be naturally 64
|
||||
function automatic riscv::xlen_t data_align (logic [2:0] addr, logic [63:0] data);
|
||||
// Set addr[2] to 1'b0 when 32bits
|
||||
logic [2:0] addr_tmp = {(addr[2] && riscv::IS_XLEN64), addr[1:0]};
|
||||
logic [63:0] data_tmp = {64{1'b0}};
|
||||
case (addr_tmp)
|
||||
3'b000: data_tmp[riscv::XLEN-1:0] = {data[riscv::XLEN-1:0]};
|
||||
3'b001: data_tmp[riscv::XLEN-1:0] = {data[riscv::XLEN-9:0], data[riscv::XLEN-1:riscv::XLEN-8]};
|
||||
3'b010: data_tmp[riscv::XLEN-1:0] = {data[riscv::XLEN-17:0], data[riscv::XLEN-1:riscv::XLEN-16]};
|
||||
3'b011: data_tmp[riscv::XLEN-1:0] = {data[riscv::XLEN-25:0], data[riscv::XLEN-1:riscv::XLEN-24]};
|
||||
3'b100: data_tmp = {data[31:0], data[63:32]};
|
||||
3'b101: data_tmp = {data[23:0], data[63:24]};
|
||||
3'b110: data_tmp = {data[15:0], data[63:16]};
|
||||
3'b111: data_tmp = {data[7:0], data[63:8]};
|
||||
endcase
|
||||
return data_tmp[riscv::XLEN-1:0];
|
||||
endfunction
|
||||
|
||||
// generate byte enable mask
|
||||
function automatic logic [7:0] be_gen(logic [2:0] addr, logic [1:0] size);
|
||||
case (size)
|
||||
2'b11: begin
|
||||
return 8'b1111_1111;
|
||||
end
|
||||
2'b10: begin
|
||||
case (addr[2:0])
|
||||
3'b000: return 8'b0000_1111;
|
||||
3'b001: return 8'b0001_1110;
|
||||
3'b010: return 8'b0011_1100;
|
||||
3'b011: return 8'b0111_1000;
|
||||
3'b100: return 8'b1111_0000;
|
||||
endcase
|
||||
end
|
||||
2'b01: begin
|
||||
case (addr[2:0])
|
||||
3'b000: return 8'b0000_0011;
|
||||
3'b001: return 8'b0000_0110;
|
||||
3'b010: return 8'b0000_1100;
|
||||
3'b011: return 8'b0001_1000;
|
||||
3'b100: return 8'b0011_0000;
|
||||
3'b101: return 8'b0110_0000;
|
||||
3'b110: return 8'b1100_0000;
|
||||
endcase
|
||||
end
|
||||
2'b00: begin
|
||||
case (addr[2:0])
|
||||
3'b000: return 8'b0000_0001;
|
||||
3'b001: return 8'b0000_0010;
|
||||
3'b010: return 8'b0000_0100;
|
||||
3'b011: return 8'b0000_1000;
|
||||
3'b100: return 8'b0001_0000;
|
||||
3'b101: return 8'b0010_0000;
|
||||
3'b110: return 8'b0100_0000;
|
||||
3'b111: return 8'b1000_0000;
|
||||
endcase
|
||||
end
|
||||
endcase
|
||||
return 8'b0;
|
||||
endfunction
|
||||
|
||||
function automatic logic [3:0] be_gen_32(logic [1:0] addr, logic [1:0] size);
|
||||
case (size)
|
||||
2'b10: begin
|
||||
return 4'b1111;
|
||||
end
|
||||
2'b01: begin
|
||||
case (addr[1:0])
|
||||
2'b00: return 4'b0011;
|
||||
2'b01: return 4'b0110;
|
||||
2'b10: return 4'b1100;
|
||||
|
||||
endcase
|
||||
end
|
||||
2'b00: begin
|
||||
case (addr[1:0])
|
||||
2'b00: return 4'b0001;
|
||||
2'b01: return 4'b0010;
|
||||
2'b10: return 4'b0100;
|
||||
2'b11: return 4'b1000;
|
||||
endcase
|
||||
end
|
||||
default: return 4'b0;
|
||||
endcase
|
||||
return 4'b0;
|
||||
endfunction
|
||||
|
||||
// ----------------------
|
||||
// Extract Bytes from Op
|
||||
// ----------------------
|
||||
function automatic logic [1:0] extract_transfer_size(fu_op op);
|
||||
case (op)
|
||||
LD, SD, FLD, FSD,
|
||||
AMO_LRD, AMO_SCD,
|
||||
AMO_SWAPD, AMO_ADDD,
|
||||
AMO_ANDD, AMO_ORD,
|
||||
AMO_XORD, AMO_MAXD,
|
||||
AMO_MAXDU, AMO_MIND,
|
||||
AMO_MINDU: begin
|
||||
return 2'b11;
|
||||
end
|
||||
LW, LWU, SW, FLW, FSW,
|
||||
AMO_LRW, AMO_SCW,
|
||||
AMO_SWAPW, AMO_ADDW,
|
||||
AMO_ANDW, AMO_ORW,
|
||||
AMO_XORW, AMO_MAXW,
|
||||
AMO_MAXWU, AMO_MINW,
|
||||
AMO_MINWU: begin
|
||||
return 2'b10;
|
||||
end
|
||||
LH, LHU, SH, FLH, FSH: return 2'b01;
|
||||
LB, LBU, SB, FLB, FSB: return 2'b00;
|
||||
default: return 2'b11;
|
||||
endcase
|
||||
endfunction
|
||||
endpackage
|
|
@ -0,0 +1 @@
|
|||
`define WT_DCACHE
|
|
@ -0,0 +1,791 @@
|
|||
`include "axi/typedef.svh"
|
||||
`include "axi/assign.svh"
|
||||
`include "register_interface/typedef.svh"
|
||||
`include "register_interface/assign.svh"
|
||||
|
||||
import cva6_wrapper_pkg::*;
|
||||
|
||||
module cva6_wrapper (
|
||||
input logic clk_i ,
|
||||
input logic rst_n ,
|
||||
|
||||
input logic [31:0] irq_sources,
|
||||
|
||||
// AXI i/f
|
||||
|
||||
//AXI write address bus ------------------------------------
|
||||
output logic [AxiIdWidthSlaves-1:0] AWID_o ,
|
||||
output logic [AxiAddrWidth-1:0] AWADDR_o ,
|
||||
output logic [ 7:0] AWLEN_o ,
|
||||
output logic [ 2:0] AWSIZE_o ,
|
||||
output logic [ 1:0] AWBURST_o ,
|
||||
output logic AWLOCK_o ,
|
||||
output logic [ 3:0] AWCACHE_o ,
|
||||
output logic [ 2:0] AWPROT_o ,
|
||||
output logic [ 3:0] AWREGION_o ,
|
||||
output logic [ AxiUserWidth-1:0] AWUSER_o ,
|
||||
output logic [ 3:0] AWQOS_o ,
|
||||
output logic AWVALID_o ,
|
||||
input logic AWREADY_i ,
|
||||
// ---------------------------------------------------------
|
||||
|
||||
//AXI write data bus ---------------------------------------
|
||||
output logic [AxiDataWidth-1:0] WDATA_o ,
|
||||
output logic [AxiDataWidth/8-1:0] WSTRB_o ,
|
||||
output logic WLAST_o ,
|
||||
output logic [AxiUserWidth-1:0] WUSER_o ,
|
||||
output logic WVALID_o ,
|
||||
input logic WREADY_i ,
|
||||
// ---------------------------------------------------------
|
||||
|
||||
//AXI write response bus -----------------------------------
|
||||
input logic [AxiIdWidthSlaves-1:0] BID_i ,
|
||||
input logic [ 1:0] BRESP_i ,
|
||||
input logic BVALID_i ,
|
||||
input logic [AxiUserWidth-1:0] BUSER_i ,
|
||||
output logic BREADY_o ,
|
||||
// ---------------------------------------------------------
|
||||
|
||||
//AXI read address bus -------------------------------------
|
||||
output logic [AxiIdWidthSlaves-1:0] ARID_o ,
|
||||
output logic [AxiAddrWidth-1:0] ARADDR_o ,
|
||||
output logic [ 7:0] ARLEN_o ,
|
||||
output logic [ 2:0] ARSIZE_o ,
|
||||
output logic [ 1:0] ARBURST_o ,
|
||||
output logic ARLOCK_o ,
|
||||
output logic [ 3:0] ARCACHE_o ,
|
||||
output logic [ 2:0] ARPROT_o ,
|
||||
output logic [ 3:0] ARREGION_o ,
|
||||
output logic [ AxiUserWidth-1:0] ARUSER_o ,
|
||||
output logic [ 3:0] ARQOS_o ,
|
||||
output logic ARVALID_o ,
|
||||
input logic ARREADY_i ,
|
||||
// ---------------------------------------------------------
|
||||
|
||||
//AXI read data bus ----------------------------------------
|
||||
input logic [AxiIdWidthSlaves-1:0] RID_i ,
|
||||
input logic [AxiDataWidth-1:0] RDATA_i ,
|
||||
input logic [ 1:0] RRESP_i ,
|
||||
input logic RLAST_i ,
|
||||
input logic [AxiUserWidth-1:0] RUSER_i ,
|
||||
input logic RVALID_i ,
|
||||
output logic RREADY_o ,
|
||||
|
||||
// common part
|
||||
input logic trst_n ,
|
||||
input logic tck ,
|
||||
input logic tms ,
|
||||
input logic tdi ,
|
||||
output wire tdo ,
|
||||
output wire tdo_oe
|
||||
);
|
||||
|
||||
`AXI_TYPEDEF_ALL(axi_slave,
|
||||
logic [ AxiAddrWidth-1:0],
|
||||
logic [AxiIdWidthSlaves-1:0],
|
||||
logic [ AxiDataWidth-1:0],
|
||||
logic [(AxiDataWidth/8)-1:0],
|
||||
logic [ AxiUserWidth-1:0])
|
||||
|
||||
AXI_BUS #(
|
||||
.AXI_ADDR_WIDTH ( AxiAddrWidth ),
|
||||
.AXI_DATA_WIDTH ( AxiDataWidth ),
|
||||
.AXI_ID_WIDTH ( AxiIdWidthMaster ),
|
||||
.AXI_USER_WIDTH ( AxiUserWidth )
|
||||
) slave[NBSlave-1:0]();
|
||||
|
||||
AXI_BUS #(
|
||||
.AXI_ADDR_WIDTH ( AxiAddrWidth ),
|
||||
.AXI_DATA_WIDTH ( AxiDataWidth ),
|
||||
.AXI_ID_WIDTH ( AxiIdWidthSlaves ),
|
||||
.AXI_USER_WIDTH ( AxiUserWidth )
|
||||
) master[NBMaster-1:0]();
|
||||
|
||||
AXI_BUS #(
|
||||
.AXI_ADDR_WIDTH ( riscv::XLEN ),
|
||||
.AXI_DATA_WIDTH ( riscv::XLEN ),
|
||||
.AXI_ID_WIDTH ( AxiIdWidthSlaves ),
|
||||
.AXI_USER_WIDTH ( AxiUserWidth )
|
||||
) master_to_dm[0:0]();
|
||||
|
||||
// disable test-enable
|
||||
logic test_en;
|
||||
logic ndmreset;
|
||||
logic ndmreset_n;
|
||||
logic debug_req_irq;
|
||||
logic timer_irq;
|
||||
logic ipi;
|
||||
|
||||
logic rtc;
|
||||
|
||||
// Debug
|
||||
logic debug_req_valid;
|
||||
logic debug_req_ready;
|
||||
dm::dmi_req_t debug_req;
|
||||
logic debug_resp_valid;
|
||||
logic debug_resp_ready;
|
||||
dm::dmi_resp_t debug_resp;
|
||||
|
||||
logic dmactive;
|
||||
|
||||
// IRQ
|
||||
logic [1:0] irq;
|
||||
assign test_en = 1'b0;
|
||||
|
||||
assign ndmreset_n = ~ndmreset;
|
||||
|
||||
// ---------------
|
||||
// AXI Xbar
|
||||
// ---------------
|
||||
|
||||
axi_pkg::xbar_rule_64_t [NBMaster-1:0] addr_map;
|
||||
|
||||
assign addr_map = '{
|
||||
'{ idx: cva6_wrapper_pkg::Debug, start_addr: cva6_wrapper_pkg::DebugBase, end_addr: cva6_wrapper_pkg::DebugBase + cva6_wrapper_pkg::DebugLength },
|
||||
'{ idx: cva6_wrapper_pkg::CLINT, start_addr: cva6_wrapper_pkg::CLINTBase, end_addr: cva6_wrapper_pkg::CLINTBase + cva6_wrapper_pkg::CLINTLength },
|
||||
'{ idx: cva6_wrapper_pkg::PLIC, start_addr: cva6_wrapper_pkg::PLICBase, end_addr: cva6_wrapper_pkg::PLICBase + cva6_wrapper_pkg::PLICLength },
|
||||
'{ idx: cva6_wrapper_pkg::External, start_addr: cva6_wrapper_pkg::ExternalBase, end_addr: cva6_wrapper_pkg::ExternalBase + cva6_wrapper_pkg::ExternalLength }
|
||||
};
|
||||
|
||||
localparam axi_pkg::xbar_cfg_t AXI_XBAR_CFG = '{
|
||||
NoSlvPorts: NBSlave,
|
||||
NoMstPorts: NBMaster,
|
||||
MaxMstTrans: 1, // Probably requires update
|
||||
MaxSlvTrans: 1, // Probably requires update
|
||||
FallThrough: 1'b0,
|
||||
LatencyMode: axi_pkg::CUT_ALL_PORTS,
|
||||
AxiIdWidthSlvPorts: AxiIdWidthMaster,
|
||||
AxiIdUsedSlvPorts: AxiIdWidthMaster,
|
||||
UniqueIds: 1'b0,
|
||||
AxiAddrWidth: AxiAddrWidth,
|
||||
AxiDataWidth: AxiDataWidth,
|
||||
NoAddrRules: NBSlave
|
||||
};
|
||||
|
||||
axi_xbar_intf #(
|
||||
.AXI_USER_WIDTH ( AxiUserWidth ),
|
||||
.Cfg ( AXI_XBAR_CFG ),
|
||||
.rule_t ( axi_pkg::xbar_rule_64_t )
|
||||
) i_axi_xbar (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( ndmreset_n ),
|
||||
.test_i ( test_en ),
|
||||
.slv_ports ( slave ),
|
||||
.mst_ports ( master ),
|
||||
.addr_map_i ( addr_map ),
|
||||
.en_default_mst_port_i ( '0 ),
|
||||
.default_mst_port_i ( '0 )
|
||||
);
|
||||
|
||||
// ---------------
|
||||
// Debug Module
|
||||
// ---------------
|
||||
dmi_jtag i_dmi_jtag (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_n ),
|
||||
.dmi_rst_no ( ), // keep open
|
||||
.testmode_i ( test_en ),
|
||||
.dmi_req_valid_o ( debug_req_valid ),
|
||||
.dmi_req_ready_i ( debug_req_ready ),
|
||||
.dmi_req_o ( debug_req ),
|
||||
.dmi_resp_valid_i ( debug_resp_valid ),
|
||||
.dmi_resp_ready_o ( debug_resp_ready ),
|
||||
.dmi_resp_i ( debug_resp ),
|
||||
.tck_i ( tck ),
|
||||
.tms_i ( tms ),
|
||||
.trst_ni ( trst_n ),
|
||||
.td_i ( tdi ),
|
||||
.td_o ( tdo ),
|
||||
.tdo_oe_o ( tdo_oe )
|
||||
);
|
||||
|
||||
ariane_axi::req_t dm_axi_m_req;
|
||||
ariane_axi::resp_t dm_axi_m_resp;
|
||||
|
||||
logic dm_slave_req;
|
||||
logic dm_slave_we;
|
||||
logic [riscv::XLEN-1:0] dm_slave_addr;
|
||||
logic [riscv::XLEN/8-1:0] dm_slave_be;
|
||||
logic [riscv::XLEN-1:0] dm_slave_wdata;
|
||||
logic [riscv::XLEN-1:0] dm_slave_rdata;
|
||||
|
||||
logic dm_master_req;
|
||||
logic [riscv::XLEN-1:0] dm_master_add;
|
||||
logic dm_master_we;
|
||||
logic [riscv::XLEN-1:0] dm_master_wdata;
|
||||
logic [riscv::XLEN/8-1:0] dm_master_be;
|
||||
logic dm_master_gnt;
|
||||
logic dm_master_r_valid;
|
||||
logic [riscv::XLEN-1:0] dm_master_r_rdata;
|
||||
|
||||
// debug module
|
||||
dm_top #(
|
||||
.NrHarts ( 1 ),
|
||||
.BusWidth ( riscv::XLEN ),
|
||||
.SelectableHarts ( 1'b1 )
|
||||
) i_dm_top (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_n ), // PoR
|
||||
.testmode_i ( test_en ),
|
||||
.ndmreset_o ( ndmreset ),
|
||||
.dmactive_o ( dmactive ), // active debug session
|
||||
.debug_req_o ( debug_req_irq ),
|
||||
.unavailable_i ( '0 ),
|
||||
.hartinfo_i ( {ariane_pkg::DebugHartInfo} ),
|
||||
.slave_req_i ( dm_slave_req ),
|
||||
.slave_we_i ( dm_slave_we ),
|
||||
.slave_addr_i ( dm_slave_addr ),
|
||||
.slave_be_i ( dm_slave_be ),
|
||||
.slave_wdata_i ( dm_slave_wdata ),
|
||||
.slave_rdata_o ( dm_slave_rdata ),
|
||||
.master_req_o ( dm_master_req ),
|
||||
.master_add_o ( dm_master_add ),
|
||||
.master_we_o ( dm_master_we ),
|
||||
.master_wdata_o ( dm_master_wdata ),
|
||||
.master_be_o ( dm_master_be ),
|
||||
.master_gnt_i ( dm_master_gnt ),
|
||||
.master_r_valid_i ( dm_master_r_valid ),
|
||||
.master_r_rdata_i ( dm_master_r_rdata ),
|
||||
.dmi_rst_ni ( rst_n ),
|
||||
.dmi_req_valid_i ( debug_req_valid ),
|
||||
.dmi_req_ready_o ( debug_req_ready ),
|
||||
.dmi_req_i ( debug_req ),
|
||||
.dmi_resp_valid_o ( debug_resp_valid ),
|
||||
.dmi_resp_ready_i ( debug_resp_ready ),
|
||||
.dmi_resp_o ( debug_resp )
|
||||
);
|
||||
|
||||
axi2mem #(
|
||||
.AXI_ID_WIDTH ( AxiIdWidthSlaves ),
|
||||
.AXI_ADDR_WIDTH ( riscv::XLEN ),
|
||||
.AXI_DATA_WIDTH ( riscv::XLEN ),
|
||||
.AXI_USER_WIDTH ( AxiUserWidth )
|
||||
) i_dm_axi2mem (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_n ),
|
||||
.slave ( master_to_dm[0] ),
|
||||
.req_o ( dm_slave_req ),
|
||||
.we_o ( dm_slave_we ),
|
||||
.addr_o ( dm_slave_addr ),
|
||||
.be_o ( dm_slave_be ),
|
||||
.data_o ( dm_slave_wdata ),
|
||||
.data_i ( dm_slave_rdata )
|
||||
);
|
||||
|
||||
if (riscv::XLEN==32 ) begin
|
||||
|
||||
assign master_to_dm[0].aw_user = '0;
|
||||
assign master_to_dm[0].w_user = '0;
|
||||
assign master_to_dm[0].ar_user = '0;
|
||||
|
||||
assign master_to_dm[0].aw_id = dm_axi_m_req.aw.id;
|
||||
assign master_to_dm[0].ar_id = dm_axi_m_req.ar.id;
|
||||
|
||||
assign master[cva6_wrapper_pkg::Debug].r_user ='0;
|
||||
assign master[cva6_wrapper_pkg::Debug].b_user ='0;
|
||||
|
||||
xlnx_axi_dwidth_converter_dm_slave i_axi_dwidth_converter_dm_slave(
|
||||
.s_axi_aclk(clk_i),
|
||||
.s_axi_aresetn(ndmreset_n),
|
||||
.s_axi_awid(master[cva6_wrapper_pkg::Debug].aw_id),
|
||||
.s_axi_awaddr(master[cva6_wrapper_pkg::Debug].aw_addr[31:0]),
|
||||
.s_axi_awlen(master[cva6_wrapper_pkg::Debug].aw_len),
|
||||
.s_axi_awsize(master[cva6_wrapper_pkg::Debug].aw_size),
|
||||
.s_axi_awburst(master[cva6_wrapper_pkg::Debug].aw_burst),
|
||||
.s_axi_awlock(master[cva6_wrapper_pkg::Debug].aw_lock),
|
||||
.s_axi_awcache(master[cva6_wrapper_pkg::Debug].aw_cache),
|
||||
.s_axi_awprot(master[cva6_wrapper_pkg::Debug].aw_prot),
|
||||
.s_axi_awregion(master[cva6_wrapper_pkg::Debug].aw_region),
|
||||
.s_axi_awqos(master[cva6_wrapper_pkg::Debug].aw_qos),
|
||||
.s_axi_awvalid(master[cva6_wrapper_pkg::Debug].aw_valid),
|
||||
.s_axi_awready(master[cva6_wrapper_pkg::Debug].aw_ready),
|
||||
.s_axi_wdata(master[cva6_wrapper_pkg::Debug].w_data),
|
||||
.s_axi_wstrb(master[cva6_wrapper_pkg::Debug].w_strb),
|
||||
.s_axi_wlast(master[cva6_wrapper_pkg::Debug].w_last),
|
||||
.s_axi_wvalid(master[cva6_wrapper_pkg::Debug].w_valid),
|
||||
.s_axi_wready(master[cva6_wrapper_pkg::Debug].w_ready),
|
||||
.s_axi_bid(master[cva6_wrapper_pkg::Debug].b_id),
|
||||
.s_axi_bresp(master[cva6_wrapper_pkg::Debug].b_resp),
|
||||
.s_axi_bvalid(master[cva6_wrapper_pkg::Debug].b_valid),
|
||||
.s_axi_bready(master[cva6_wrapper_pkg::Debug].b_ready),
|
||||
.s_axi_arid(master[cva6_wrapper_pkg::Debug].ar_id),
|
||||
.s_axi_araddr(master[cva6_wrapper_pkg::Debug].ar_addr[31:0]),
|
||||
.s_axi_arlen(master[cva6_wrapper_pkg::Debug].ar_len),
|
||||
.s_axi_arsize(master[cva6_wrapper_pkg::Debug].ar_size),
|
||||
.s_axi_arburst(master[cva6_wrapper_pkg::Debug].ar_burst),
|
||||
.s_axi_arlock(master[cva6_wrapper_pkg::Debug].ar_lock),
|
||||
.s_axi_arcache(master[cva6_wrapper_pkg::Debug].ar_cache),
|
||||
.s_axi_arprot(master[cva6_wrapper_pkg::Debug].ar_prot),
|
||||
.s_axi_arregion(master[cva6_wrapper_pkg::Debug].ar_region),
|
||||
.s_axi_arqos(master[cva6_wrapper_pkg::Debug].ar_qos),
|
||||
.s_axi_arvalid(master[cva6_wrapper_pkg::Debug].ar_valid),
|
||||
.s_axi_arready(master[cva6_wrapper_pkg::Debug].ar_ready),
|
||||
.s_axi_rid(master[cva6_wrapper_pkg::Debug].r_id),
|
||||
.s_axi_rdata(master[cva6_wrapper_pkg::Debug].r_data),
|
||||
.s_axi_rresp(master[cva6_wrapper_pkg::Debug].r_resp),
|
||||
.s_axi_rlast(master[cva6_wrapper_pkg::Debug].r_last),
|
||||
.s_axi_rvalid(master[cva6_wrapper_pkg::Debug].r_valid),
|
||||
.s_axi_rready(master[cva6_wrapper_pkg::Debug].r_ready),
|
||||
.m_axi_awaddr(master_to_dm[0].aw_addr),
|
||||
.m_axi_awlen(master_to_dm[0].aw_len),
|
||||
.m_axi_awsize(master_to_dm[0].aw_size),
|
||||
.m_axi_awburst(master_to_dm[0].aw_burst),
|
||||
.m_axi_awlock(master_to_dm[0].aw_lock),
|
||||
.m_axi_awcache(master_to_dm[0].aw_cache),
|
||||
.m_axi_awprot(master_to_dm[0].aw_prot),
|
||||
.m_axi_awregion(master_to_dm[0].aw_region),
|
||||
.m_axi_awqos(master_to_dm[0].aw_qos),
|
||||
.m_axi_awvalid(master_to_dm[0].aw_valid),
|
||||
.m_axi_awready(master_to_dm[0].aw_ready),
|
||||
.m_axi_wdata(master_to_dm[0].w_data ),
|
||||
.m_axi_wstrb(master_to_dm[0].w_strb),
|
||||
.m_axi_wlast(master_to_dm[0].w_last),
|
||||
.m_axi_wvalid(master_to_dm[0].w_valid),
|
||||
.m_axi_wready(master_to_dm[0].w_ready),
|
||||
.m_axi_bresp(master_to_dm[0].b_resp),
|
||||
.m_axi_bvalid(master_to_dm[0].b_valid),
|
||||
.m_axi_bready(master_to_dm[0].b_ready),
|
||||
.m_axi_araddr(master_to_dm[0].ar_addr),
|
||||
.m_axi_arlen(master_to_dm[0].ar_len),
|
||||
.m_axi_arsize(master_to_dm[0].ar_size),
|
||||
.m_axi_arburst(master_to_dm[0].ar_burst),
|
||||
.m_axi_arlock(master_to_dm[0].ar_lock),
|
||||
.m_axi_arcache(master_to_dm[0].ar_cache),
|
||||
.m_axi_arprot(master_to_dm[0].ar_prot),
|
||||
.m_axi_arregion(master_to_dm[0].ar_region),
|
||||
.m_axi_arqos(master_to_dm[0].ar_qos),
|
||||
.m_axi_arvalid(master_to_dm[0].ar_valid),
|
||||
.m_axi_arready(master_to_dm[0].ar_ready),
|
||||
.m_axi_rdata(master_to_dm[0].r_data),
|
||||
.m_axi_rresp(master_to_dm[0].r_resp),
|
||||
.m_axi_rlast(master_to_dm[0].r_last),
|
||||
.m_axi_rvalid(master_to_dm[0].r_valid),
|
||||
.m_axi_rready(master_to_dm[0].r_ready)
|
||||
);
|
||||
|
||||
end else begin
|
||||
|
||||
assign master[cva6_wrapper_pkg::Debug].aw_id = master_to_dm[0].aw_id;
|
||||
assign master[cva6_wrapper_pkg::Debug].aw_addr = master_to_dm[0].aw_addr;
|
||||
assign master[cva6_wrapper_pkg::Debug].aw_len = master_to_dm[0].aw_len;
|
||||
assign master[cva6_wrapper_pkg::Debug].aw_size = master_to_dm[0].aw_size;
|
||||
assign master[cva6_wrapper_pkg::Debug].aw_burst = master_to_dm[0].aw_burst;
|
||||
assign master[cva6_wrapper_pkg::Debug].aw_lock = master_to_dm[0].aw_lock;
|
||||
assign master[cva6_wrapper_pkg::Debug].aw_cache = master_to_dm[0].aw_cache;
|
||||
assign master[cva6_wrapper_pkg::Debug].aw_prot = master_to_dm[0].aw_prot;
|
||||
assign master[cva6_wrapper_pkg::Debug].aw_qos = master_to_dm[0].aw_qos;
|
||||
assign master[cva6_wrapper_pkg::Debug].aw_atop = master_to_dm[0].aw_atop;
|
||||
assign master[cva6_wrapper_pkg::Debug].aw_region = master_to_dm[0].aw_region;
|
||||
assign master[cva6_wrapper_pkg::Debug].aw_user = master_to_dm[0].aw_user;
|
||||
assign master[cva6_wrapper_pkg::Debug].aw_valid = master_to_dm[0].aw_valid;
|
||||
|
||||
assign master_to_dm[0].aw_ready =master[cva6_wrapper_pkg::Debug].aw_ready;
|
||||
|
||||
assign master[cva6_wrapper_pkg::Debug].w_data = master_to_dm[0].w_data;
|
||||
assign master[cva6_wrapper_pkg::Debug].w_strb = master_to_dm[0].w_strb;
|
||||
assign master[cva6_wrapper_pkg::Debug].w_last = master_to_dm[0].w_last;
|
||||
assign master[cva6_wrapper_pkg::Debug].w_user = master_to_dm[0].w_user;
|
||||
assign master[cva6_wrapper_pkg::Debug].w_valid = master_to_dm[0].w_valid;
|
||||
|
||||
assign master_to_dm[0].w_ready =master[cva6_wrapper_pkg::Debug].w_ready;
|
||||
|
||||
assign master_to_dm[0].b_id =master[cva6_wrapper_pkg::Debug].b_id;
|
||||
assign master_to_dm[0].b_resp =master[cva6_wrapper_pkg::Debug].b_resp;
|
||||
assign master_to_dm[0].b_user =master[cva6_wrapper_pkg::Debug].b_user;
|
||||
assign master_to_dm[0].b_valid =master[cva6_wrapper_pkg::Debug].b_valid;
|
||||
|
||||
assign master[cva6_wrapper_pkg::Debug].b_ready = master_to_dm[0].b_ready;
|
||||
|
||||
assign master[cva6_wrapper_pkg::Debug].ar_id = master_to_dm[0].ar_id;
|
||||
assign master[cva6_wrapper_pkg::Debug].ar_addr = master_to_dm[0].ar_addr;
|
||||
assign master[cva6_wrapper_pkg::Debug].ar_len = master_to_dm[0].ar_len;
|
||||
assign master[cva6_wrapper_pkg::Debug].ar_size = master_to_dm[0].ar_size;
|
||||
assign master[cva6_wrapper_pkg::Debug].ar_burst = master_to_dm[0].ar_burst;
|
||||
assign master[cva6_wrapper_pkg::Debug].ar_lock = master_to_dm[0].ar_lock;
|
||||
assign master[cva6_wrapper_pkg::Debug].ar_cache = master_to_dm[0].ar_cache;
|
||||
assign master[cva6_wrapper_pkg::Debug].ar_prot = master_to_dm[0].ar_prot;
|
||||
assign master[cva6_wrapper_pkg::Debug].ar_qos = master_to_dm[0].ar_qos;
|
||||
assign master[cva6_wrapper_pkg::Debug].ar_region = master_to_dm[0].ar_region;
|
||||
assign master[cva6_wrapper_pkg::Debug].ar_user = master_to_dm[0].ar_user;
|
||||
assign master[cva6_wrapper_pkg::Debug].ar_valid = master_to_dm[0].ar_valid;
|
||||
|
||||
assign master_to_dm[0].ar_ready =master[cva6_wrapper_pkg::Debug].ar_ready;
|
||||
|
||||
assign master_to_dm[0].r_id =master[cva6_wrapper_pkg::Debug].r_id;
|
||||
assign master_to_dm[0].r_data =master[cva6_wrapper_pkg::Debug].r_data;
|
||||
assign master_to_dm[0].r_resp =master[cva6_wrapper_pkg::Debug].r_resp;
|
||||
assign master_to_dm[0].r_last =master[cva6_wrapper_pkg::Debug].r_last;
|
||||
assign master_to_dm[0].r_user =master[cva6_wrapper_pkg::Debug].r_user;
|
||||
assign master_to_dm[0].r_valid =master[cva6_wrapper_pkg::Debug].r_valid;
|
||||
|
||||
assign master[cva6_wrapper_pkg::Debug].r_ready = master_to_dm[0].r_ready;
|
||||
|
||||
end
|
||||
|
||||
logic [1:0] axi_adapter_size;
|
||||
|
||||
assign axi_adapter_size = (riscv::XLEN == 64) ? 2'b11 : 2'b10;
|
||||
|
||||
|
||||
axi_adapter #(
|
||||
.DATA_WIDTH ( riscv::XLEN ),
|
||||
.AXI_DATA_WIDTH ( AxiDataWidth ),
|
||||
.AXI_ID_WIDTH ( AxiIdWidthSlaves ),
|
||||
.axi_req_t ( axi_slave_req_t ),
|
||||
.axi_rsp_t ( axi_slave_resp_t )
|
||||
) i_dm_axi_master (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_n ),
|
||||
.req_i ( dm_master_req ),
|
||||
.type_i ( ariane_axi::SINGLE_REQ ),
|
||||
.amo_i ( ariane_pkg::AMO_NONE ),
|
||||
.gnt_o ( dm_master_gnt ),
|
||||
.addr_i ( dm_master_add ),
|
||||
.we_i ( dm_master_we ),
|
||||
.wdata_i ( dm_master_wdata ),
|
||||
.be_i ( dm_master_be ),
|
||||
.size_i ( axi_adapter_size ),
|
||||
.id_i ( '0 ),
|
||||
.valid_o ( dm_master_r_valid ),
|
||||
.rdata_o ( dm_master_r_rdata ),
|
||||
.id_o ( ),
|
||||
.critical_word_o ( ),
|
||||
.critical_word_valid_o ( ),
|
||||
.axi_req_o ( dm_axi_m_req ),
|
||||
.axi_resp_i ( dm_axi_m_resp )
|
||||
);
|
||||
|
||||
if (riscv::XLEN==32 ) begin
|
||||
logic [31 : 0] dm_master_m_awaddr;
|
||||
logic [31 : 0] dm_master_m_araddr;
|
||||
|
||||
assign slave[1].aw_addr = {32'h0000_0000, dm_master_m_awaddr};
|
||||
assign slave[1].ar_addr = {32'h0000_0000, dm_master_m_araddr};
|
||||
|
||||
logic [31 : 0] dm_master_s_rdata;
|
||||
|
||||
assign dm_axi_m_resp.r.data = {32'h0000_0000, dm_master_s_rdata};
|
||||
|
||||
assign slave[1].aw_user = '0;
|
||||
assign slave[1].w_user = '0;
|
||||
assign slave[1].ar_user = '0;
|
||||
|
||||
assign slave[1].aw_id = dm_axi_m_req.aw.id;
|
||||
assign slave[1].ar_id = dm_axi_m_req.ar.id;
|
||||
assign slave[1].aw_atop = dm_axi_m_req.aw.atop;
|
||||
|
||||
xlnx_axi_dwidth_converter_dm_master i_axi_dwidth_converter_dm_master(
|
||||
.s_axi_aclk(clk_i),
|
||||
.s_axi_aresetn(ndmreset_n),
|
||||
.s_axi_awid(dm_axi_m_req.aw.id),
|
||||
.s_axi_awaddr(dm_axi_m_req.aw.addr[31:0]),
|
||||
.s_axi_awlen(dm_axi_m_req.aw.len),
|
||||
.s_axi_awsize(dm_axi_m_req.aw.size),
|
||||
.s_axi_awburst(dm_axi_m_req.aw.burst),
|
||||
.s_axi_awlock(dm_axi_m_req.aw.lock),
|
||||
.s_axi_awcache(dm_axi_m_req.aw.cache),
|
||||
.s_axi_awprot(dm_axi_m_req.aw.prot),
|
||||
.s_axi_awregion(dm_axi_m_req.aw.region),
|
||||
.s_axi_awqos(dm_axi_m_req.aw.qos),
|
||||
.s_axi_awvalid(dm_axi_m_req.aw_valid),
|
||||
.s_axi_awready(dm_axi_m_resp.aw_ready),
|
||||
.s_axi_wdata(dm_axi_m_req.w.data[31:0]),
|
||||
.s_axi_wstrb(dm_axi_m_req.w.strb[3:0]),
|
||||
.s_axi_wlast(dm_axi_m_req.w.last),
|
||||
.s_axi_wvalid(dm_axi_m_req.w_valid),
|
||||
.s_axi_wready(dm_axi_m_resp.w_ready),
|
||||
.s_axi_bid(dm_axi_m_resp.b.id),
|
||||
.s_axi_bresp(dm_axi_m_resp.b.resp),
|
||||
.s_axi_bvalid(dm_axi_m_resp.b_valid),
|
||||
.s_axi_bready(dm_axi_m_req.b_ready),
|
||||
.s_axi_arid(dm_axi_m_req.ar.id),
|
||||
.s_axi_araddr(dm_axi_m_req.ar.addr[31:0]),
|
||||
.s_axi_arlen(dm_axi_m_req.ar.len),
|
||||
.s_axi_arsize(dm_axi_m_req.ar.size),
|
||||
.s_axi_arburst(dm_axi_m_req.ar.burst),
|
||||
.s_axi_arlock(dm_axi_m_req.ar.lock),
|
||||
.s_axi_arcache(dm_axi_m_req.ar.cache),
|
||||
.s_axi_arprot(dm_axi_m_req.ar.prot),
|
||||
.s_axi_arregion(dm_axi_m_req.ar.region),
|
||||
.s_axi_arqos(dm_axi_m_req.ar.qos),
|
||||
.s_axi_arvalid(dm_axi_m_req.ar_valid),
|
||||
.s_axi_arready(dm_axi_m_resp.ar_ready),
|
||||
.s_axi_rid(dm_axi_m_resp.r.id),
|
||||
.s_axi_rdata(dm_master_s_rdata),
|
||||
.s_axi_rresp(dm_axi_m_resp.r.resp),
|
||||
.s_axi_rlast(dm_axi_m_resp.r.last),
|
||||
.s_axi_rvalid(dm_axi_m_resp.r_valid),
|
||||
.s_axi_rready(dm_axi_m_req.r_ready),
|
||||
.m_axi_awaddr(dm_master_m_awaddr),
|
||||
.m_axi_awlen(slave[1].aw_len),
|
||||
.m_axi_awsize(slave[1].aw_size),
|
||||
.m_axi_awburst(slave[1].aw_burst),
|
||||
.m_axi_awlock(slave[1].aw_lock),
|
||||
.m_axi_awcache(slave[1].aw_cache),
|
||||
.m_axi_awprot(slave[1].aw_prot),
|
||||
.m_axi_awregion(slave[1].aw_region),
|
||||
.m_axi_awqos(slave[1].aw_qos),
|
||||
.m_axi_awvalid(slave[1].aw_valid),
|
||||
.m_axi_awready(slave[1].aw_ready),
|
||||
.m_axi_wdata(slave[1].w_data ),
|
||||
.m_axi_wstrb(slave[1].w_strb),
|
||||
.m_axi_wlast(slave[1].w_last),
|
||||
.m_axi_wvalid(slave[1].w_valid),
|
||||
.m_axi_wready(slave[1].w_ready),
|
||||
.m_axi_bresp(slave[1].b_resp),
|
||||
.m_axi_bvalid(slave[1].b_valid),
|
||||
.m_axi_bready(slave[1].b_ready),
|
||||
.m_axi_araddr(dm_master_m_araddr),
|
||||
.m_axi_arlen(slave[1].ar_len),
|
||||
.m_axi_arsize(slave[1].ar_size),
|
||||
.m_axi_arburst(slave[1].ar_burst),
|
||||
.m_axi_arlock(slave[1].ar_lock),
|
||||
.m_axi_arcache(slave[1].ar_cache),
|
||||
.m_axi_arprot(slave[1].ar_prot),
|
||||
.m_axi_arregion(slave[1].ar_region),
|
||||
.m_axi_arqos(slave[1].ar_qos),
|
||||
.m_axi_arvalid(slave[1].ar_valid),
|
||||
.m_axi_arready(slave[1].ar_ready),
|
||||
.m_axi_rdata(slave[1].r_data),
|
||||
.m_axi_rresp(slave[1].r_resp),
|
||||
.m_axi_rlast(slave[1].r_last),
|
||||
.m_axi_rvalid(slave[1].r_valid),
|
||||
.m_axi_rready(slave[1].r_ready)
|
||||
);
|
||||
end else begin
|
||||
`AXI_ASSIGN_FROM_REQ(slave[1], dm_axi_m_req)
|
||||
`AXI_ASSIGN_TO_RESP(dm_axi_m_resp, slave[1])
|
||||
end
|
||||
|
||||
|
||||
// ---------------
|
||||
// Core
|
||||
// ---------------
|
||||
ariane_axi::req_t axi_ariane_req;
|
||||
ariane_axi::resp_t axi_ariane_resp;
|
||||
|
||||
ariane #(
|
||||
.ArianeCfg ( cva6_wrapper_pkg::CVA6Cfg )
|
||||
) i_ariane (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_n /*ndmreset_n*/ ),
|
||||
.boot_addr_i ( cva6_wrapper_pkg::ExternalBase ),
|
||||
.hart_id_i ( '0 ),
|
||||
.irq_i ( irq ),
|
||||
.ipi_i ( ipi ),
|
||||
.time_irq_i ( timer_irq ),
|
||||
.debug_req_i ( debug_req_irq ),
|
||||
.axi_req_o ( axi_ariane_req ),
|
||||
.axi_resp_i ( axi_ariane_resp )
|
||||
);
|
||||
|
||||
`AXI_ASSIGN_FROM_REQ(slave[0], axi_ariane_req)
|
||||
`AXI_ASSIGN_TO_RESP(axi_ariane_resp, slave[0])
|
||||
|
||||
// ---------------
|
||||
// CLINT
|
||||
// ---------------
|
||||
// divide clock by two
|
||||
always_ff @(posedge clk_i or negedge ndmreset_n) begin
|
||||
if (~ndmreset_n) begin
|
||||
rtc <= 0;
|
||||
end else begin
|
||||
rtc <= rtc ^ 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
axi_slave_req_t axi_clint_req;
|
||||
axi_slave_resp_t axi_clint_resp;
|
||||
|
||||
clint #(
|
||||
.AXI_ADDR_WIDTH ( AxiAddrWidth ),
|
||||
.AXI_DATA_WIDTH ( AxiDataWidth ),
|
||||
.AXI_ID_WIDTH ( AxiIdWidthSlaves ),
|
||||
.NR_CORES ( 1 ),
|
||||
.axi_req_t ( axi_slave_req_t ),
|
||||
.axi_resp_t ( axi_slave_resp_t )
|
||||
) i_clint (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( ndmreset_n ),
|
||||
.testmode_i ( test_en ),
|
||||
.axi_req_i ( axi_clint_req ),
|
||||
.axi_resp_o ( axi_clint_resp ),
|
||||
.rtc_i ( rtc ),
|
||||
.timer_irq_o ( timer_irq ),
|
||||
.ipi_o ( ipi )
|
||||
);
|
||||
|
||||
`AXI_ASSIGN_TO_REQ(axi_clint_req, master[cva6_wrapper_pkg::CLINT])
|
||||
`AXI_ASSIGN_FROM_RESP(master[cva6_wrapper_pkg::CLINT], axi_clint_resp)
|
||||
|
||||
// ---------------
|
||||
// PLIC
|
||||
// ---------------
|
||||
|
||||
REG_BUS #(
|
||||
.ADDR_WIDTH ( 32 ),
|
||||
.DATA_WIDTH ( 32 )
|
||||
) reg_bus (clk_i);
|
||||
|
||||
logic plic_penable;
|
||||
logic plic_pwrite;
|
||||
logic [31:0] plic_paddr;
|
||||
logic plic_psel;
|
||||
logic [31:0] plic_pwdata;
|
||||
logic [31:0] plic_prdata;
|
||||
logic plic_pready;
|
||||
logic plic_pslverr;
|
||||
|
||||
axi2apb_64_32 #(
|
||||
.AXI4_ADDRESS_WIDTH ( AxiAddrWidth ),
|
||||
.AXI4_RDATA_WIDTH ( AxiDataWidth ),
|
||||
.AXI4_WDATA_WIDTH ( AxiDataWidth ),
|
||||
.AXI4_ID_WIDTH ( AxiIdWidthSlaves ),
|
||||
.AXI4_USER_WIDTH ( AxiUserWidth ),
|
||||
.BUFF_DEPTH_SLAVE ( 2 ),
|
||||
.APB_ADDR_WIDTH ( 32 )
|
||||
) i_axi2apb_64_32_plic (
|
||||
.ACLK ( clk_i ),
|
||||
.ARESETn ( ndmreset_n ),
|
||||
.test_en_i ( 1'b0 ),
|
||||
.AWID_i ( master[cva6_wrapper_pkg::PLIC].aw_id ),
|
||||
.AWADDR_i ( master[cva6_wrapper_pkg::PLIC].aw_addr ),
|
||||
.AWLEN_i ( master[cva6_wrapper_pkg::PLIC].aw_len ),
|
||||
.AWSIZE_i ( master[cva6_wrapper_pkg::PLIC].aw_size ),
|
||||
.AWBURST_i ( master[cva6_wrapper_pkg::PLIC].aw_burst ),
|
||||
.AWLOCK_i ( master[cva6_wrapper_pkg::PLIC].aw_lock ),
|
||||
.AWCACHE_i ( master[cva6_wrapper_pkg::PLIC].aw_cache ),
|
||||
.AWPROT_i ( master[cva6_wrapper_pkg::PLIC].aw_prot ),
|
||||
.AWREGION_i( master[cva6_wrapper_pkg::PLIC].aw_region ),
|
||||
.AWUSER_i ( master[cva6_wrapper_pkg::PLIC].aw_user ),
|
||||
.AWQOS_i ( master[cva6_wrapper_pkg::PLIC].aw_qos ),
|
||||
.AWVALID_i ( master[cva6_wrapper_pkg::PLIC].aw_valid ),
|
||||
.AWREADY_o ( master[cva6_wrapper_pkg::PLIC].aw_ready ),
|
||||
.WDATA_i ( master[cva6_wrapper_pkg::PLIC].w_data ),
|
||||
.WSTRB_i ( master[cva6_wrapper_pkg::PLIC].w_strb ),
|
||||
.WLAST_i ( master[cva6_wrapper_pkg::PLIC].w_last ),
|
||||
.WUSER_i ( master[cva6_wrapper_pkg::PLIC].w_user ),
|
||||
.WVALID_i ( master[cva6_wrapper_pkg::PLIC].w_valid ),
|
||||
.WREADY_o ( master[cva6_wrapper_pkg::PLIC].w_ready ),
|
||||
.BID_o ( master[cva6_wrapper_pkg::PLIC].b_id ),
|
||||
.BRESP_o ( master[cva6_wrapper_pkg::PLIC].b_resp ),
|
||||
.BVALID_o ( master[cva6_wrapper_pkg::PLIC].b_valid ),
|
||||
.BUSER_o ( master[cva6_wrapper_pkg::PLIC].b_user ),
|
||||
.BREADY_i ( master[cva6_wrapper_pkg::PLIC].b_ready ),
|
||||
.ARID_i ( master[cva6_wrapper_pkg::PLIC].ar_id ),
|
||||
.ARADDR_i ( master[cva6_wrapper_pkg::PLIC].ar_addr ),
|
||||
.ARLEN_i ( master[cva6_wrapper_pkg::PLIC].ar_len ),
|
||||
.ARSIZE_i ( master[cva6_wrapper_pkg::PLIC].ar_size ),
|
||||
.ARBURST_i ( master[cva6_wrapper_pkg::PLIC].ar_burst ),
|
||||
.ARLOCK_i ( master[cva6_wrapper_pkg::PLIC].ar_lock ),
|
||||
.ARCACHE_i ( master[cva6_wrapper_pkg::PLIC].ar_cache ),
|
||||
.ARPROT_i ( master[cva6_wrapper_pkg::PLIC].ar_prot ),
|
||||
.ARREGION_i( master[cva6_wrapper_pkg::PLIC].ar_region ),
|
||||
.ARUSER_i ( master[cva6_wrapper_pkg::PLIC].ar_user ),
|
||||
.ARQOS_i ( master[cva6_wrapper_pkg::PLIC].ar_qos ),
|
||||
.ARVALID_i ( master[cva6_wrapper_pkg::PLIC].ar_valid ),
|
||||
.ARREADY_o ( master[cva6_wrapper_pkg::PLIC].ar_ready ),
|
||||
.RID_o ( master[cva6_wrapper_pkg::PLIC].r_id ),
|
||||
.RDATA_o ( master[cva6_wrapper_pkg::PLIC].r_data ),
|
||||
.RRESP_o ( master[cva6_wrapper_pkg::PLIC].r_resp ),
|
||||
.RLAST_o ( master[cva6_wrapper_pkg::PLIC].r_last ),
|
||||
.RUSER_o ( master[cva6_wrapper_pkg::PLIC].r_user ),
|
||||
.RVALID_o ( master[cva6_wrapper_pkg::PLIC].r_valid ),
|
||||
.RREADY_i ( master[cva6_wrapper_pkg::PLIC].r_ready ),
|
||||
.PENABLE ( plic_penable ),
|
||||
.PWRITE ( plic_pwrite ),
|
||||
.PADDR ( plic_paddr ),
|
||||
.PSEL ( plic_psel ),
|
||||
.PWDATA ( plic_pwdata ),
|
||||
.PRDATA ( plic_prdata ),
|
||||
.PREADY ( plic_pready ),
|
||||
.PSLVERR ( plic_pslverr )
|
||||
);
|
||||
|
||||
apb_to_reg i_apb_to_reg (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( ndmreset_n ),
|
||||
.penable_i ( plic_penable ),
|
||||
.pwrite_i ( plic_pwrite ),
|
||||
.paddr_i ( plic_paddr ),
|
||||
.psel_i ( plic_psel ),
|
||||
.pwdata_i ( plic_pwdata ),
|
||||
.prdata_o ( plic_prdata ),
|
||||
.pready_o ( plic_pready ),
|
||||
.pslverr_o ( plic_pslverr ),
|
||||
.reg_o ( reg_bus )
|
||||
);
|
||||
|
||||
// define reg type according to REG_BUS above
|
||||
`REG_BUS_TYPEDEF_ALL(plic, logic[31:0], logic[31:0], logic[3:0])
|
||||
plic_req_t plic_req;
|
||||
plic_rsp_t plic_rsp;
|
||||
|
||||
// assign REG_BUS.out to (req_t, rsp_t) pair
|
||||
`REG_BUS_ASSIGN_TO_REQ(plic_req, reg_bus)
|
||||
`REG_BUS_ASSIGN_FROM_RSP(reg_bus, plic_rsp)
|
||||
|
||||
plic_top #(
|
||||
.N_SOURCE ( cva6_wrapper_pkg::NumSources ),
|
||||
.N_TARGET ( cva6_wrapper_pkg::NumTargets ),
|
||||
.MAX_PRIO ( cva6_wrapper_pkg::MaxPriority ),
|
||||
.reg_req_t ( plic_req_t ),
|
||||
.reg_rsp_t ( plic_rsp_t )
|
||||
) i_plic (
|
||||
.clk_i,
|
||||
.rst_ni (ndmreset_n),
|
||||
.req_i ( plic_req ),
|
||||
.resp_o ( plic_rsp ),
|
||||
.le_i ( '0 ), // 0:level 1:edge
|
||||
.irq_sources_i ( irq_sources ),
|
||||
.eip_targets_o ( irq )
|
||||
);
|
||||
|
||||
// ---------------
|
||||
// AXI to the outside world
|
||||
// ---------------
|
||||
|
||||
assign AWID_o = master[cva6_wrapper_pkg::External].aw_id;
|
||||
assign AWADDR_o = master[cva6_wrapper_pkg::External].aw_addr;
|
||||
assign AWLEN_o = master[cva6_wrapper_pkg::External].aw_len;
|
||||
assign AWSIZE_o = master[cva6_wrapper_pkg::External].aw_size;
|
||||
assign AWBURST_o = master[cva6_wrapper_pkg::External].aw_burst;
|
||||
assign AWLOCK_o = master[cva6_wrapper_pkg::External].aw_lock;
|
||||
assign AWCACHE_o = master[cva6_wrapper_pkg::External].aw_cache;
|
||||
assign AWPROT_o = master[cva6_wrapper_pkg::External].aw_prot;
|
||||
assign AWREGION_o = master[cva6_wrapper_pkg::External].aw_region;
|
||||
assign AWUSER_o = '0;
|
||||
assign AWQOS_o = master[cva6_wrapper_pkg::External].aw_qos;
|
||||
assign AWVALID_o = master[cva6_wrapper_pkg::External].aw_valid;
|
||||
assign master[cva6_wrapper_pkg::External].aw_ready = AWREADY_i;
|
||||
assign WDATA_o = master[cva6_wrapper_pkg::External].w_data;
|
||||
assign WSTRB_o = master[cva6_wrapper_pkg::External].w_strb;
|
||||
assign WLAST_o = master[cva6_wrapper_pkg::External].w_last;
|
||||
assign WUSER_o = '0;
|
||||
assign WVALID_o = master[cva6_wrapper_pkg::External].w_valid;
|
||||
assign master[cva6_wrapper_pkg::External].w_ready = WREADY_i;
|
||||
assign master[cva6_wrapper_pkg::External].b_id = BID_i;
|
||||
assign master[cva6_wrapper_pkg::External].b_resp = BRESP_i;
|
||||
assign master[cva6_wrapper_pkg::External].b_valid = BVALID_i;
|
||||
assign BREADY_o = master[cva6_wrapper_pkg::External].b_ready;
|
||||
assign ARID_o = master[cva6_wrapper_pkg::External].ar_id;
|
||||
assign ARADDR_o = master[cva6_wrapper_pkg::External].ar_addr;
|
||||
assign ARLEN_o = master[cva6_wrapper_pkg::External].ar_len;
|
||||
assign ARSIZE_o = master[cva6_wrapper_pkg::External].ar_size;
|
||||
assign ARBURST_o = master[cva6_wrapper_pkg::External].ar_burst;
|
||||
assign ARLOCK_o = master[cva6_wrapper_pkg::External].ar_lock;
|
||||
assign ARCACHE_o = master[cva6_wrapper_pkg::External].ar_cache;
|
||||
assign ARPROT_o = master[cva6_wrapper_pkg::External].ar_prot;
|
||||
assign ARREGION_o = master[cva6_wrapper_pkg::External].ar_region;
|
||||
assign ARUSER_o = '0;
|
||||
assign ARQOS_o = master[cva6_wrapper_pkg::External].ar_qos;
|
||||
assign ARVALID_o = master[cva6_wrapper_pkg::External].ar_valid;
|
||||
assign master[cva6_wrapper_pkg::External].ar_ready = ARREADY_i;
|
||||
assign master[cva6_wrapper_pkg::External].r_id = RID_i;
|
||||
assign master[cva6_wrapper_pkg::External].r_data = RDATA_i;
|
||||
assign master[cva6_wrapper_pkg::External].r_resp = RRESP_i;
|
||||
assign master[cva6_wrapper_pkg::External].r_last = RLAST_i;
|
||||
assign master[cva6_wrapper_pkg::External].r_valid = RVALID_i;
|
||||
assign RREADY_o = master[cva6_wrapper_pkg::External].r_ready;
|
||||
|
||||
endmodule
|
|
@ -0,0 +1,74 @@
|
|||
// Copyright 2018 ETH Zurich and University of Bologna.
|
||||
// Copyright and related rights are licensed under the Solderpad Hardware
|
||||
// License, Version 0.51 (the "License"); you may not use this file except in
|
||||
// compliance with the License. You may obtain a copy of the License at
|
||||
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
|
||||
// or agreed to in writing, software, hardware and materials distributed under
|
||||
// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations under the License.
|
||||
|
||||
package cva6_wrapper_pkg;
|
||||
// M-Mode Hart, S-Mode Hart
|
||||
localparam int unsigned NumTargets = 2;
|
||||
// Uart, SPI, Ethernet, reserved
|
||||
localparam int unsigned NumSources = 32;
|
||||
localparam int unsigned MaxPriority = 7;
|
||||
|
||||
// 24 MByte in 8 byte words
|
||||
localparam NBSlave = 2; // debug, cva6
|
||||
localparam NBMaster = 4; // debug, plic, clint, external
|
||||
localparam AxiAddrWidth = 64;
|
||||
localparam AxiDataWidth = 64;
|
||||
localparam AxiIdWidthMaster = $clog2(NBMaster);
|
||||
localparam AxiIdWidthSlaves = AxiIdWidthMaster + $clog2(NBSlave);
|
||||
localparam AxiUserWidth = 1;
|
||||
|
||||
typedef enum int unsigned {
|
||||
External = 0,
|
||||
PLIC = 1,
|
||||
CLINT = 2,
|
||||
Debug = 3
|
||||
} axi_slaves_t;
|
||||
|
||||
localparam logic[63:0] DebugLength = 64'h1000;
|
||||
localparam logic[63:0] CLINTLength = 64'hC0000;
|
||||
localparam logic[63:0] PLICLength = 64'h3FF_FFFF;
|
||||
localparam logic[63:0] ExternalLength = 64'hEFFF_FFFF;
|
||||
|
||||
// Instantiate AXI protocol checkers
|
||||
localparam bit GenProtocolChecker = 1'b0;
|
||||
|
||||
typedef enum logic [63:0] {
|
||||
DebugBase = 64'h0000_0000,
|
||||
CLINTBase = 64'h0200_0000,
|
||||
PLICBase = 64'h0C00_0000,
|
||||
ExternalBase = 64'h1000_0000
|
||||
} soc_bus_start_t;
|
||||
|
||||
localparam NrRegion = 1;
|
||||
|
||||
localparam ariane_pkg::ariane_cfg_t CVA6Cfg = '{
|
||||
RASDepth: 2,
|
||||
BTBEntries: 32,
|
||||
BHTEntries: 128,
|
||||
// idempotent region
|
||||
NrNonIdempotentRules: 1,
|
||||
NonIdempotentAddrBase: {64'b0},
|
||||
NonIdempotentLength: {ExternalBase},
|
||||
NrExecuteRegionRules: 2,
|
||||
ExecuteRegionAddrBase: {DebugBase, ExternalBase},
|
||||
ExecuteRegionLength: {DebugLength, ExternalLength},
|
||||
// cached region
|
||||
NrCachedRegionRules: 1,
|
||||
CachedRegionAddrBase: {ExternalBase},
|
||||
CachedRegionLength: {64'h7000_0000},
|
||||
// cache config
|
||||
AxiCompliant: 1'b1,
|
||||
SwapEndianess: 1'b0,
|
||||
// debug
|
||||
DmBaseAddress: DebugBase,
|
||||
NrPMPEntries: 8
|
||||
};
|
||||
|
||||
endpackage
|
Loading…
Reference in New Issue