Merge pull request #1572 from gatecat/cva6_update

cva6: Updating the core files
This commit is contained in:
enjoy-digital 2023-01-17 15:32:03 +01:00 committed by GitHub
commit dcb54b85a0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 1866 additions and 8 deletions

View File

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

View File

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

View File

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

View File

@ -0,0 +1 @@
`define WT_DCACHE

View File

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

View File

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