[rtl] Add a new top level plus wiring

This commit creates a new top level wrapping the core, register file and
icache RAMs. The tracing top level is also renamed to ibex_top_tracing
to match. This new top level is intended to enable a dual core lockstep
implementation of Ibex.

There are no functional changes in this commit, only wiring.

Signed-off-by: Tom Roberts <tomroberts@lowrisc.org>
This commit is contained in:
Tom Roberts 2021-03-22 14:13:08 +00:00 committed by Tom Roberts
parent b106001d82
commit 6a3200929b
34 changed files with 980 additions and 304 deletions

View file

@ -14,19 +14,19 @@ steps:
displayName: Test and display fusesoc config for ${{ config }}
- bash: |
fusesoc --cores-root . run --target=lint --tool=verilator lowrisc:ibex:ibex_core_tracing $IBEX_CONFIG_OPTS
fusesoc --cores-root . run --target=lint --tool=verilator lowrisc:ibex:ibex_top_tracing $IBEX_CONFIG_OPTS
if [ $? != 0 ]; then
echo -n "##vso[task.logissue type=error]"
echo "Verilog lint failed. Run 'fusesoc --cores-root . run --target=lint --tool=verilator lowrisc:ibex:ibex_core_tracing $IBEX_CONFIG_OPTS' to check and fix all errors."
echo "Verilog lint failed. Run 'fusesoc --cores-root . run --target=lint --tool=verilator lowrisc:ibex:ibex_top_tracing $IBEX_CONFIG_OPTS' to check and fix all errors."
exit 1
fi
displayName: Lint Verilog source files with Verilator for ${{ config }}
- bash: |
fusesoc --cores-root . run --target=lint --tool=veriblelint lowrisc:ibex:ibex_core_tracing $IBEX_CONFIG_OPTS
fusesoc --cores-root . run --target=lint --tool=veriblelint lowrisc:ibex:ibex_top_tracing $IBEX_CONFIG_OPTS
if [ $? != 0 ]; then
echo -n "##vso[task.logissue type=error]"
echo "Verilog lint failed. Run 'fusesoc --cores-root . run --target=lint --tool=veriblelint lowrisc:ibex:ibex_core_tracing $IBEX_CONFIG_OPTS' to check and fix all errors."
echo "Verilog lint failed. Run 'fusesoc --cores-root . run --target=lint --tool=veriblelint lowrisc:ibex:ibex_top_tracing $IBEX_CONFIG_OPTS' to check and fix all errors."
exit 1
fi
displayName: Lint Verilog source files with Verible Verilog Lint for ${{ config }}

View file

@ -3,7 +3,7 @@
Core Integration
================
The main module is named ``ibex_core`` and can be found in ``ibex_core.sv``.
The main module is named ``ibex_top`` and can be found in ``ibex_top.sv``.
Below, the instantiation template is given and the parameters and interfaces are described.
Instantiation Template
@ -11,7 +11,7 @@ Instantiation Template
.. code-block:: verilog
ibex_core #(
ibex_top #(
.PMPEnable ( 0 ),
.PMPGranularity ( 0 ),
.PMPNumRegions ( 4 ),
@ -28,7 +28,7 @@ Instantiation Template
.DbgTriggerEn ( 0 ),
.DmHaltAddr ( 32'h1A110800 ),
.DmExceptionAddr ( 32'h1A110808 )
) u_core (
) u_top (
// Clock and reset
.clk_i (),
.rst_ni (),

View file

@ -204,7 +204,7 @@ This isn't an attempt to describe the cache's performance characteristics.
The I$ has a single clock (``clk_i``) and asynchronous reset (``rst_ni``).
Data is requested from the instruction memory with the ports prefixed by ``instr_``. These work as described in :ref:`instruction-fetch`.
Note that there's one extra port on the I$, which doesn't appear at the ``ibex_core`` top-level.
Note that there's one extra port on the I$, which doesn't appear at the ``ibex_top`` top-level.
This is ``instr_pmp_err_i``.
If the PMP block disallows a fetch for a certain address, it will squash the outgoing memory request entirely and set ``instr_pmp_err_i``.
If that happens, the cache drops ``instr_req_o`` and stops making any further requests for that cache line.

View file

@ -4,7 +4,7 @@ Tracer
======
The module ``ibex_tracer`` can be used to create a log of the executed instructions.
It is used by ``ibex_core_tracing`` which forwards the `RVFI signals <https://github.com/SymbioticEDA/riscv-formal/blob/master/docs/rvfi.md>`_ to the tracer (see also :ref:`rvfi`).
It is used by ``ibex_top_tracing`` which forwards the `RVFI signals <https://github.com/SymbioticEDA/riscv-formal/blob/master/docs/rvfi.md>`_ to the tracer (see also :ref:`rvfi`).
Output file
-----------

View file

@ -9,7 +9,7 @@ filesets:
depend:
- lowrisc:dv_verilator:memutil_verilator
- lowrisc:dv_verilator:simutil_verilator
- lowrisc:ibex:ibex_core_tracing
- lowrisc:ibex:ibex_top_tracing
- lowrisc:ibex:sim_shared
files:

View file

@ -112,7 +112,7 @@ module ibex_riscv_compliance (
.cfg_device_addr_mask
);
ibex_core_tracing #(
ibex_top_tracing #(
.PMPEnable (PMPEnable ),
.PMPGranularity (PMPGranularity ),
.PMPNumRegions (PMPNumRegions ),
@ -127,7 +127,7 @@ module ibex_riscv_compliance (
.BranchPredictor (BranchPredictor ),
.DmHaltAddr (32'h00000000 ),
.DmExceptionAddr (32'h00000000 )
) u_core (
) u_top (
.clk_i (clk_sys ),
.rst_ni (rst_sys_n ),

View file

@ -63,7 +63,8 @@ ${PRJ_DIR}/rtl/ibex_register_file_fpga.sv
${PRJ_DIR}/rtl/ibex_register_file_latch.sv
${PRJ_DIR}/rtl/ibex_pmp.sv
${PRJ_DIR}/rtl/ibex_core.sv
${PRJ_DIR}/rtl/ibex_core_tracing.sv
${PRJ_DIR}/rtl/ibex_top.sv
${PRJ_DIR}/rtl/ibex_top_tracing.sv
// Core DV files
${PRJ_DIR}/vendor/google_riscv-dv/src/riscv_signature_pkg.sv

View file

@ -58,7 +58,7 @@ module core_ibex_tb_top;
parameter bit ICacheECC = 1'b0;
parameter bit BranchPredictor = 1'b0;
ibex_core_tracing #(
ibex_top_tracing #(
.DmHaltAddr (32'h`BOOT_ADDR + 'h0 ),
.DmExceptionAddr (32'h`BOOT_ADDR + 'h4 ),
.PMPEnable (PMPEnable ),
@ -78,7 +78,7 @@ module core_ibex_tb_top;
.rst_ni (rst_n ),
.test_en_i (1'b0 ),
.ram_cfg_i (1'b0 ),
.ram_cfg_i ('b0 ),
.hart_id_i (32'b0 ),
.boot_addr_i (32'h`BOOT_ADDR ), // align with spike boot address
@ -145,31 +145,31 @@ module core_ibex_tb_top;
// Irq interface connections
assign irq_vif.reset = ~rst_n;
// Dut_if interface connections
assign dut_if.ecall = dut.u_ibex_core.id_stage_i.controller_i.ecall_insn;
assign dut_if.wfi = dut.u_ibex_core.id_stage_i.controller_i.wfi_insn;
assign dut_if.ebreak = dut.u_ibex_core.id_stage_i.controller_i.ebrk_insn;
assign dut_if.illegal_instr = dut.u_ibex_core.id_stage_i.controller_i.illegal_insn_d;
assign dut_if.dret = dut.u_ibex_core.id_stage_i.controller_i.dret_insn;
assign dut_if.mret = dut.u_ibex_core.id_stage_i.controller_i.mret_insn;
assign dut_if.ecall = dut.u_ibex_top.u_ibex_core.id_stage_i.controller_i.ecall_insn;
assign dut_if.wfi = dut.u_ibex_top.u_ibex_core.id_stage_i.controller_i.wfi_insn;
assign dut_if.ebreak = dut.u_ibex_top.u_ibex_core.id_stage_i.controller_i.ebrk_insn;
assign dut_if.illegal_instr = dut.u_ibex_top.u_ibex_core.id_stage_i.controller_i.illegal_insn_d;
assign dut_if.dret = dut.u_ibex_top.u_ibex_core.id_stage_i.controller_i.dret_insn;
assign dut_if.mret = dut.u_ibex_top.u_ibex_core.id_stage_i.controller_i.mret_insn;
assign dut_if.reset = ~rst_n;
assign dut_if.priv_mode = dut.u_ibex_core.priv_mode_id;
assign dut_if.priv_mode = dut.u_ibex_top.u_ibex_core.priv_mode_id;
// Instruction monitor connections
assign instr_monitor_if.valid_id = dut.u_ibex_core.id_stage_i.instr_valid_i;
assign instr_monitor_if.err_id = dut.u_ibex_core.id_stage_i.controller_i.instr_fetch_err;
assign instr_monitor_if.is_compressed_id = dut.u_ibex_core.id_stage_i.instr_is_compressed_i;
assign instr_monitor_if.instr_compressed_id = dut.u_ibex_core.id_stage_i.instr_rdata_c_i;
assign instr_monitor_if.instr_id = dut.u_ibex_core.id_stage_i.instr_rdata_i;
assign instr_monitor_if.pc_id = dut.u_ibex_core.pc_id;
assign instr_monitor_if.branch_taken_id = dut.u_ibex_core.id_stage_i.controller_i.branch_set_i;
assign instr_monitor_if.branch_target_id = dut.u_ibex_core.branch_target_ex;
assign instr_monitor_if.stall_id = dut.u_ibex_core.id_stage_i.stall_id;
assign instr_monitor_if.jump_set_id = dut.u_ibex_core.id_stage_i.jump_set;
assign instr_monitor_if.valid_id = dut.u_ibex_top.u_ibex_core.id_stage_i.instr_valid_i;
assign instr_monitor_if.err_id = dut.u_ibex_top.u_ibex_core.id_stage_i.controller_i.instr_fetch_err;
assign instr_monitor_if.is_compressed_id = dut.u_ibex_top.u_ibex_core.id_stage_i.instr_is_compressed_i;
assign instr_monitor_if.instr_compressed_id = dut.u_ibex_top.u_ibex_core.id_stage_i.instr_rdata_c_i;
assign instr_monitor_if.instr_id = dut.u_ibex_top.u_ibex_core.id_stage_i.instr_rdata_i;
assign instr_monitor_if.pc_id = dut.u_ibex_top.u_ibex_core.pc_id;
assign instr_monitor_if.branch_taken_id = dut.u_ibex_top.u_ibex_core.id_stage_i.controller_i.branch_set_i;
assign instr_monitor_if.branch_target_id = dut.u_ibex_top.u_ibex_core.branch_target_ex;
assign instr_monitor_if.stall_id = dut.u_ibex_top.u_ibex_core.id_stage_i.stall_id;
assign instr_monitor_if.jump_set_id = dut.u_ibex_top.u_ibex_core.id_stage_i.jump_set;
// CSR interface connections
assign csr_if.csr_access = dut.u_ibex_core.csr_access;
assign csr_if.csr_addr = dut.u_ibex_core.csr_addr;
assign csr_if.csr_wdata = dut.u_ibex_core.csr_wdata;
assign csr_if.csr_rdata = dut.u_ibex_core.csr_rdata;
assign csr_if.csr_op = dut.u_ibex_core.csr_op;
assign csr_if.csr_access = dut.u_ibex_top.u_ibex_core.csr_access;
assign csr_if.csr_addr = dut.u_ibex_top.u_ibex_core.csr_addr;
assign csr_if.csr_wdata = dut.u_ibex_top.u_ibex_core.csr_wdata;
assign csr_if.csr_rdata = dut.u_ibex_top.u_ibex_core.csr_rdata;
assign csr_if.csr_op = dut.u_ibex_top.u_ibex_core.csr_op;
initial begin
// Drive the clock and reset lines. Reset everything and start the clock at the beginning of

View file

@ -8,6 +8,9 @@ filesets:
files_rtl:
depend:
- lowrisc:ibex:ibex_icache:0.1
files:
- tb/ic_top.sv
file_type: systemVerilogSource
files_dv:
depend:

View file

@ -0,0 +1,131 @@
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
module ic_top import ibex_pkg::*; #(parameter bit ICacheECC = 1'b0) (
input logic clk_i,
input logic rst_ni,
input logic req_i,
input logic branch_i,
input logic branch_spec_i,
input logic predicted_branch_i,
input logic branch_mispredict_i,
input logic [31:0] addr_i,
input logic ready_i,
output logic valid_o,
output logic [31:0] rdata_o,
output logic [31:0] addr_o,
output logic err_o,
output logic err_plus2_o,
output logic instr_req_o,
input logic instr_gnt_i,
output logic [31:0] instr_addr_o,
input logic [BUS_SIZE-1:0] instr_rdata_i,
input logic instr_err_i,
input logic instr_pmp_err_i,
input logic instr_rvalid_i,
input logic icache_enable_i,
input logic icache_inval_i,
output logic busy_o
);
localparam int unsigned BusSizeECC = ICacheECC ? (BUS_SIZE + 7) : BUS_SIZE;
localparam int unsigned LineSizeECC = BusSizeECC * IC_LINE_BEATS;
localparam int unsigned TagSizeECC = ICacheECC ? (IC_TAG_SIZE + 6) : IC_TAG_SIZE;
// RAM IO
logic [IC_NUM_WAYS-1:0] ic_tag_req;
logic ic_tag_write;
logic [IC_INDEX_W-1:0] ic_tag_addr;
logic [TagSizeECC-1:0] ic_tag_wdata;
logic [TagSizeECC-1:0] ic_tag_rdata [IC_NUM_WAYS];
logic [IC_NUM_WAYS-1:0] ic_data_req;
logic ic_data_write;
logic [IC_INDEX_W-1:0] ic_data_addr;
logic [LineSizeECC-1:0] ic_data_wdata;
logic [LineSizeECC-1:0] ic_data_rdata [IC_NUM_WAYS];
// DUT
ibex_icache #(
.ICacheECC (ICacheECC),
.BusSizeECC (BusSizeECC),
.TagSizeECC (TagSizeECC),
.LineSizeECC (LineSizeECC)
) icache_i (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.req_i ( req_i ),
.branch_i ( branch_i ),
.branch_spec_i ( branch_spec_i ),
.predicted_branch_i ( predicted_branch_i ),
.branch_mispredict_i ( branch_mispredict_i ),
.addr_i ( addr_i ),
.ready_i ( ready_i ),
.valid_o ( valid_o ),
.rdata_o ( rdata_o ),
.addr_o ( addr_o ),
.err_o ( err_o ),
.err_plus2_o ( err_plus2_o ),
.instr_req_o ( instr_req_o ),
.instr_addr_o ( instr_addr_o ),
.instr_gnt_i ( instr_gnt_i ),
.instr_rvalid_i ( instr_rvalid_i ),
.instr_rdata_i ( instr_rdata_i ),
.instr_err_i ( instr_err_i ),
.instr_pmp_err_i ( instr_pmp_err_i ),
.ic_tag_req_o ( ic_tag_req ),
.ic_tag_write_o ( ic_tag_write ),
.ic_tag_addr_o ( ic_tag_addr ),
.ic_tag_wdata_o ( ic_tag_wdata ),
.ic_tag_rdata_i ( ic_tag_rdata ),
.ic_data_req_o ( ic_data_req ),
.ic_data_write_o ( ic_data_write ),
.ic_data_addr_o ( ic_data_addr ),
.ic_data_wdata_o ( ic_data_wdata ),
.ic_data_rdata_i ( ic_data_rdata ),
.icache_enable_i ( icache_enable_i ),
.icache_inval_i ( icache_inval_i ),
.busy_o ( busy_o )
);
// RAMs
for (genvar way = 0; way < IC_NUM_WAYS; way++) begin : gen_rams
// Tag RAM instantiation
prim_ram_1p #(
.Width (TagSizeECC),
.Depth (IC_NUM_LINES),
.DataBitsPerMask (TagSizeECC)
) tag_bank (
.clk_i (clk_i),
.req_i (ic_tag_req[way]),
.cfg_i ('0),
.write_i (ic_tag_write),
.wmask_i ({TagSizeECC{1'b1}}),
.addr_i (ic_tag_addr),
.wdata_i (ic_tag_wdata),
.rdata_o (ic_tag_rdata[way])
);
// Data RAM instantiation
prim_ram_1p #(
.Width (LineSizeECC),
.Depth (IC_NUM_LINES),
.DataBitsPerMask (LineSizeECC)
) data_bank (
.clk_i (clk_i),
.req_i (ic_data_req[way]),
.cfg_i ('0),
.write_i (ic_data_write),
.wmask_i ({LineSizeECC{1'b1}}),
.addr_i (ic_data_addr),
.wdata_i (ic_data_wdata),
.rdata_o (ic_data_rdata[way])
);
end
endmodule

View file

@ -22,7 +22,7 @@ module tb #(parameter bit ICacheECC = 1'b0);
ibex_icache_mem_if mem_if (.clk(clk), .rst_n(rst_n));
// dut
ibex_icache #(
ic_top #(
.ICacheECC (ICacheECC)
) dut (
.clk_i (clk),
@ -41,7 +41,6 @@ module tb #(parameter bit ICacheECC = 1'b0);
.addr_o (core_if.addr),
.err_o (core_if.err),
.err_plus2_o (core_if.err_plus2),
.ram_cfg_i ('0),
.icache_enable_i (core_if.enable),
.icache_inval_i (core_if.invalidate),
.busy_o (core_if.busy),

View file

@ -42,11 +42,11 @@ module top_artya7 (
logic [31:0] mem_rdata;
ibex_core #(
ibex_top #(
.RegFile(ibex_pkg::RegFileFPGA),
.DmHaltAddr(32'h00000000),
.DmExceptionAddr(32'h00000000)
) u_core (
) u_top (
.clk_i (clk_sys),
.rst_ni (rst_sys_n),

View file

@ -7,7 +7,7 @@ description: "Ibex example toplevel for Arty A7 boards (both, -35 and -100)"
filesets:
files_rtl_artya7:
depend:
- lowrisc:ibex:ibex_core
- lowrisc:ibex:ibex_top
- lowrisc:ibex:fpga_xilinx_shared
files:
- rtl/top_artya7.sv

View file

@ -7,7 +7,7 @@ description: "Generic simple system for running binaries on ibex using verilator
filesets:
files_sim:
depend:
- lowrisc:ibex:ibex_core_tracing
- lowrisc:ibex:ibex_top_tracing
- lowrisc:ibex:sim_shared
files:
- rtl/ibex_simple_system.sv

View file

@ -161,7 +161,7 @@ module ibex_simple_system (
.cfg_device_addr_mask
);
ibex_core_tracing #(
ibex_top_tracing #(
.SecureIbex ( SecureIbex ),
.PMPEnable ( PMPEnable ),
.PMPGranularity ( PMPGranularity ),
@ -178,7 +178,7 @@ module ibex_simple_system (
.BranchPredictor ( BranchPredictor ),
.DmHaltAddr ( 32'h00100000 ),
.DmExceptionAddr ( 32'h00100000 )
) u_core (
) u_top (
.clk_i (clk_sys),
.rst_ni (rst_sys_n),
@ -282,7 +282,7 @@ module ibex_simple_system (
export "DPI-C" function mhpmcounter_get;
function automatic longint unsigned mhpmcounter_get(int index);
return u_core.u_ibex_core.cs_registers_i.mhpmcounter[index];
return u_top.u_ibex_top.u_ibex_core.cs_registers_i.mhpmcounter[index];
endfunction
endmodule

View file

@ -3,7 +3,7 @@ CAPI=2:
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
name: "lowrisc:ibex:ibex_core:0.1"
description: "Ibex, a small RV32 CPU core"
description: "Ibex CPU Core Components"
filesets:
files_rtl:
@ -34,9 +34,6 @@ filesets:
- rtl/ibex_pmp.sv
- rtl/ibex_wb_stage.sv
- rtl/ibex_dummy_instr.sv
- rtl/ibex_register_file_ff.sv # generic FF-based
- rtl/ibex_register_file_fpga.sv # FPGA
- rtl/ibex_register_file_latch.sv # ASIC
- rtl/ibex_core.sv
file_type: systemVerilogSource

160
ibex_top.core Normal file
View file

@ -0,0 +1,160 @@
CAPI=2:
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
name: "lowrisc:ibex:ibex_top:0.1"
description: "Ibex, a small RV32 CPU core"
filesets:
files_rtl:
depend:
- lowrisc:ibex:ibex_pkg
- lowrisc:ibex:ibex_core
files:
- rtl/ibex_register_file_ff.sv # generic FF-based
- rtl/ibex_register_file_fpga.sv # FPGA
- rtl/ibex_register_file_latch.sv # ASIC
- rtl/ibex_top.sv
file_type: systemVerilogSource
files_lint_verilator:
files:
- lint/verilator_waiver.vlt: {file_type: vlt}
files_lint_verible:
files:
- lint/verible_waiver.vbw: {file_type: veribleLintWaiver}
files_check_tool_requirements:
depend:
- lowrisc:tool:check_tool_requirements
parameters:
RVFI:
datatype: bool
paramtype: vlogdefine
SYNTHESIS:
datatype: bool
paramtype: vlogdefine
FPGA_XILINX:
datatype: bool
description: Identifies Xilinx FPGA targets to set DSP pragmas for performance counters.
default: false
paramtype: vlogdefine
RV32E:
datatype: int
default: 0
paramtype: vlogparam
RV32M:
datatype: str
default: ibex_pkg::RV32MFast
paramtype: vlogdefine
description: "RV32M implementation parameter enum. See the ibex_pkg::rv32m_e enum in ibex_pkg.sv for permitted values."
RV32B:
datatype: str
default: ibex_pkg::RV32BNone
paramtype: vlogdefine
description: "Bitmanip implementation parameter enum. See the ibex_pkg::rv32b_e enum in ibex_pkg.sv for permitted values."
RegFile:
datatype: str
default: ibex_pkg::RegFileFF
paramtype: vlogdefine
description: "Register file implementation parameter enum. See the ibex_pkg::regfile_e enum in ibex_pkg.sv for permitted values."
ICache:
datatype: int
default: 0
paramtype: vlogparam
description: "Enable instruction cache"
ICacheECC:
datatype: int
default: 0
paramtype: vlogparam
description: "Enable ECC protection in instruction cache"
BranchTargetALU:
datatype: int
default: 0
paramtype: vlogparam
description: "Enables separate branch target ALU (increasing branch performance EXPERIMENTAL) [0/1]"
WritebackStage:
datatype: int
default: 0
paramtype: vlogparam
description: "Enables third pipeline stage (EXPERIMENTAL) [0/1]"
BranchPredictor:
datatype: int
paramtype: vlogparam
default: 0
description: "Enables static branch prediction (EXPERIMENTAL)"
SecureIbex:
datatype: int
default: 0
paramtype: vlogparam
description: "Enables security hardening features (EXPERIMENTAL) [0/1]"
PMPEnable:
datatype: int
default: 0
paramtype: vlogparam
description: "Enable PMP"
PMPGranularity:
datatype: int
default: 0
paramtype: vlogparam
description: "Granularity of NAPOT range, 0 = 4 byte, 1 = byte, 2 = 16 byte, 3 = 32 byte etc"
PMPNumRegions:
datatype: int
default: 4
paramtype: vlogparam
description: "Number of PMP regions"
targets:
default: &default_target
filesets:
- tool_verilator ? (files_lint_verilator)
- tool_veriblelint ? (files_lint_verible)
- files_rtl
- files_check_tool_requirements
toplevel: ibex_top
parameters:
- tool_vivado ? (FPGA_XILINX=true)
lint:
<<: *default_target
parameters:
- SYNTHESIS=true
- RVFI=true
default_tool: verilator
tools:
verilator:
mode: lint-only
verilator_options:
- "-Wall"
# RAM primitives wider than 64bit (required for ECC) fail to build in
# Verilator without increasing the unroll count (see Verilator#1266)
- "--unroll-count 72"
format:
filesets:
- files_rtl
parameters:
- SYNTHESIS=true
- RVFI=true
default_tool: veribleformat
toplevel: ibex_top
tools:
veribleformat:
verible_format_args:
- "--inplace"

View file

@ -2,15 +2,15 @@ CAPI=2:
# Copyright lowRISC contributors.
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
name: "lowrisc:ibex:ibex_core_tracing:0.1"
name: "lowrisc:ibex:ibex_top_tracing:0.1"
description: "Ibex, a small RV32 CPU core with tracing enabled"
filesets:
files_rtl:
depend:
- lowrisc:ibex:ibex_core
- lowrisc:ibex:ibex_top
- lowrisc:ibex:ibex_tracer
files:
- rtl/ibex_core_tracing.sv
- rtl/ibex_top_tracing.sv
file_type: systemVerilogSource
parameters:
@ -107,7 +107,7 @@ targets:
- files_rtl
parameters:
- RVFI=true
toplevel: ibex_core_tracing
toplevel: ibex_top_tracing
lint:
<<: *default_target
@ -143,7 +143,7 @@ targets:
- SYNTHESIS=true
- RVFI=true
default_tool: veribleformat
toplevel: ibex_core
toplevel: ibex_top_tracing
tools:
veribleformat:
verible_format_args:

View file

@ -23,13 +23,13 @@ lint_off -rule PINCONNECTEMPTY
// matches when you set a 1-bit value to a literal 1, so it won't hide
// silly mistakes like setting it to 2.
//
lint_off -rule WIDTH -file "*/rtl/ibex_core_tracing.sv"
lint_off -rule WIDTH -file "*/rtl/ibex_top_tracing.sv"
-match "*expects 1 bits*Initial value's CONST '32'h1'*"
// Operator expects 1 bit on initial value but initial value's CONST generates
// 32 bits, need a specific RV32B waiver as it uses enums so the above catch-all
// waiver doesn't work.
lint_off -rule WIDTH -file "*/rtl/ibex_core_tracing.sv" -match "*'RV32B'*"
lint_off -rule WIDTH -file "*/rtl/ibex_top_tracing.sv" -match "*'RV32B'*"
// Bits of signal are not used: be_i[3:1]
// Bits of signal are not used: addr_i[31:10,1:0]

View file

@ -12,34 +12,36 @@
/**
* Top level module of the ibex RISC-V core
*/
module ibex_core #(
parameter bit PMPEnable = 1'b0,
parameter int unsigned PMPGranularity = 0,
parameter int unsigned PMPNumRegions = 4,
parameter int unsigned MHPMCounterNum = 0,
parameter int unsigned MHPMCounterWidth = 40,
parameter bit RV32E = 1'b0,
parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast,
parameter ibex_pkg::rv32b_e RV32B = ibex_pkg::RV32BNone,
parameter ibex_pkg::regfile_e RegFile = ibex_pkg::RegFileFF,
parameter bit BranchTargetALU = 1'b0,
parameter bit WritebackStage = 1'b0,
parameter bit ICache = 1'b0,
parameter bit ICacheECC = 1'b0,
parameter bit BranchPredictor = 1'b0,
parameter bit DbgTriggerEn = 1'b0,
parameter int unsigned DbgHwBreakNum = 1,
parameter bit SecureIbex = 1'b0,
parameter int unsigned DmHaltAddr = 32'h1A110800,
parameter int unsigned DmExceptionAddr = 32'h1A110808
module ibex_core import ibex_pkg::*; #(
parameter bit PMPEnable = 1'b0,
parameter int unsigned PMPGranularity = 0,
parameter int unsigned PMPNumRegions = 4,
parameter int unsigned MHPMCounterNum = 0,
parameter int unsigned MHPMCounterWidth = 40,
parameter bit RV32E = 1'b0,
parameter rv32m_e RV32M = RV32MFast,
parameter rv32b_e RV32B = RV32BNone,
parameter bit BranchTargetALU = 1'b0,
parameter bit WritebackStage = 1'b0,
parameter bit ICache = 1'b0,
parameter bit ICacheECC = 1'b0,
parameter int unsigned BusSizeECC = BUS_SIZE,
parameter int unsigned TagSizeECC = IC_TAG_SIZE,
parameter int unsigned LineSizeECC = IC_LINE_SIZE,
parameter bit BranchPredictor = 1'b0,
parameter bit DbgTriggerEn = 1'b0,
parameter int unsigned DbgHwBreakNum = 1,
parameter bit SecureIbex = 1'b0,
parameter bit DummyInstructions = 1'b0,
parameter bit RegFileECC = 1'b0,
parameter int unsigned RegFileDataWidth = 32,
parameter int unsigned DmHaltAddr = 32'h1A110800,
parameter int unsigned DmExceptionAddr = 32'h1A110808
) (
// Clock and Reset
input logic clk_i,
input logic rst_ni,
input logic test_en_i, // enable all clock gates for testing
input prim_ram_1p_pkg::ram_1p_cfg_t ram_cfg_i,
input logic [31:0] hart_id_i,
input logic [31:0] boot_addr_i,
@ -62,16 +64,39 @@ module ibex_core #(
input logic [31:0] data_rdata_i,
input logic data_err_i,
// Register file interface
output logic dummy_instr_id_o,
output logic [4:0] rf_raddr_a_o,
output logic [4:0] rf_raddr_b_o,
output logic [4:0] rf_waddr_wb_o,
output logic rf_we_wb_o,
output logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc_o,
input logic [RegFileDataWidth-1:0] rf_rdata_a_ecc_i,
input logic [RegFileDataWidth-1:0] rf_rdata_b_ecc_i,
// RAMs interface
output logic [IC_NUM_WAYS-1:0] ic_tag_req_o,
output logic ic_tag_write_o,
output logic [IC_INDEX_W-1:0] ic_tag_addr_o,
output logic [TagSizeECC-1:0] ic_tag_wdata_o,
input logic [TagSizeECC-1:0] ic_tag_rdata_i [IC_NUM_WAYS],
output logic [IC_NUM_WAYS-1:0] ic_data_req_o,
output logic ic_data_write_o,
output logic [IC_INDEX_W-1:0] ic_data_addr_o,
output logic [LineSizeECC-1:0] ic_data_wdata_o,
input logic [LineSizeECC-1:0] ic_data_rdata_i [IC_NUM_WAYS],
// Interrupt inputs
input logic irq_software_i,
input logic irq_timer_i,
input logic irq_external_i,
input logic [14:0] irq_fast_i,
input logic irq_nm_i, // non-maskeable interrupt
output logic irq_pending_o,
// Debug Interface
input logic debug_req_i,
output ibex_pkg::crash_dump_t crash_dump_o,
output crash_dump_t crash_dump_o,
// RISC-V Formal Interface
// Does not comply with the coding standards of _i/_o suffixes, but follows
@ -103,17 +128,13 @@ module ibex_core #(
`endif
// CPU Control Signals
input logic fetch_enable_i,
output logic alert_minor_o,
output logic alert_major_o,
output logic core_sleep_o
output logic core_busy_o
);
import ibex_pkg::*;
localparam int unsigned PMP_NUM_CHAN = 2;
localparam bit DataIndTiming = SecureIbex;
localparam bit DummyInstructions = SecureIbex;
localparam bit PCIncrCheck = SecureIbex;
localparam bit ShadowCSR = SecureIbex;
// Speculative branch option, trades-off performance against timing.
@ -121,8 +142,6 @@ module ibex_core #(
// by ~3% (based on CoreMark/MHz score).
// Set by default in the max PMP config which has the tightest budget for branch target timing.
localparam bit SpecBranch = PMPEnable & (PMPNumRegions == 16);
localparam bit RegFileECC = SecureIbex;
localparam int unsigned RegFileDataWidth = RegFileECC ? 32 + 7 : 32;
// IF/ID signals
logic dummy_instr_id;
@ -179,7 +198,6 @@ module ibex_core #(
logic ctrl_busy;
logic if_busy;
logic lsu_busy;
logic core_busy_d, core_busy_q;
// Register File
logic [4:0] rf_raddr_a;
@ -196,6 +214,7 @@ module ibex_core #(
logic [31:0] rf_wdata_lsu;
logic rf_we_wb;
logic rf_we_lsu;
logic rf_ecc_err_comb;
logic [4:0] rf_waddr_id;
logic [31:0] rf_wdata_id;
@ -263,7 +282,6 @@ module ibex_core #(
logic outstanding_store_wb;
// Interrupts
logic irq_pending;
logic nmi_mode;
irqs_t irqs;
logic csr_mstatus_mie;
@ -358,43 +376,9 @@ module ibex_core #(
// Clock management //
//////////////////////
logic clk;
logic clock_en;
// Before going to sleep, wait for I- and D-side
// interfaces to finish ongoing operations.
assign core_busy_d = ctrl_busy | if_busy | lsu_busy;
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
core_busy_q <= 1'b0;
end else begin
core_busy_q <= core_busy_d;
end
end
// capture fetch_enable_i in fetch_enable_q, once for ever
logic fetch_enable_q;
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
fetch_enable_q <= 1'b0;
end else if (fetch_enable_i) begin
fetch_enable_q <= 1'b1;
end
end
assign clock_en = fetch_enable_q & (core_busy_q | debug_req_i | irq_pending | irq_nm_i);
assign core_sleep_o = ~clock_en;
// main clock gate of the core
// generates all clocks except the one for the debug unit which is
// independent
prim_clock_gating core_clock_gate_i (
.clk_i ( clk_i ),
.en_i ( clock_en ),
.test_en_i ( test_en_i ),
.clk_o ( clk )
);
assign core_busy_o = ctrl_busy | if_busy | lsu_busy;
//////////////
// IF stage //
@ -406,13 +390,15 @@ module ibex_core #(
.DummyInstructions ( DummyInstructions ),
.ICache ( ICache ),
.ICacheECC ( ICacheECC ),
.BusSizeECC ( BusSizeECC ),
.TagSizeECC ( TagSizeECC ),
.LineSizeECC ( LineSizeECC ),
.PCIncrCheck ( PCIncrCheck ),
.BranchPredictor ( BranchPredictor )
) if_stage_i (
.clk_i ( clk ),
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.ram_cfg_i ( ram_cfg_i ),
.boot_addr_i ( boot_addr_i ),
.req_i ( instr_req_int ), // instruction request control
@ -425,6 +411,17 @@ module ibex_core #(
.instr_err_i ( instr_err_i ),
.instr_pmp_err_i ( pmp_req_err[PMP_I] ),
.ic_tag_req_o ( ic_tag_req_o ),
.ic_tag_write_o ( ic_tag_write_o ),
.ic_tag_addr_o ( ic_tag_addr_o ),
.ic_tag_wdata_o ( ic_tag_wdata_o ),
.ic_tag_rdata_i ( ic_tag_rdata_i ),
.ic_data_req_o ( ic_data_req_o ),
.ic_data_write_o ( ic_data_write_o ),
.ic_data_addr_o ( ic_data_addr_o ),
.ic_data_wdata_o ( ic_data_wdata_o ),
.ic_data_rdata_i ( ic_data_rdata_i ),
// outputs to ID stage
.instr_valid_id_o ( instr_valid_id ),
.instr_new_id_o ( instr_new_id ),
@ -492,7 +489,7 @@ module ibex_core #(
.WritebackStage ( WritebackStage ),
.BranchPredictor ( BranchPredictor )
) id_stage_i (
.clk_i ( clk ),
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
// Processor Enable
@ -586,7 +583,7 @@ module ibex_core #(
// Interrupt Signals
.csr_mstatus_mie_i ( csr_mstatus_mie ),
.irq_pending_i ( irq_pending ),
.irq_pending_i ( irq_pending_o ),
.irqs_i ( irqs ),
.irq_nm_i ( irq_nm_i ),
.nmi_mode_o ( nmi_mode ),
@ -646,7 +643,7 @@ module ibex_core #(
.RV32B ( RV32B ),
.BranchTargetALU ( BranchTargetALU )
) ex_block_i (
.clk_i ( clk ),
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
// ALU signal from ID stage
@ -694,7 +691,7 @@ module ibex_core #(
assign lsu_resp_err = lsu_load_err | lsu_store_err;
ibex_load_store_unit load_store_unit_i (
.clk_i ( clk ),
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
// data interface
@ -742,7 +739,7 @@ module ibex_core #(
ibex_wb_stage #(
.WritebackStage ( WritebackStage )
) wb_stage_i (
.clk_i ( clk ),
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.en_wb_i ( en_wb ),
.instr_type_wb_i ( instr_type_wb ),
@ -777,14 +774,15 @@ module ibex_core #(
.instr_done_wb_o ( instr_done_wb )
);
///////////////////////
// Register file ECC //
///////////////////////
/////////////////////////////
// Register file interface //
/////////////////////////////
logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc;
logic [RegFileDataWidth-1:0] rf_rdata_a_ecc;
logic [RegFileDataWidth-1:0] rf_rdata_b_ecc;
logic rf_ecc_err_comb;
assign dummy_instr_id_o = dummy_instr_id;
assign rf_raddr_a_o = rf_raddr_a;
assign rf_waddr_wb_o = rf_waddr_wb;
assign rf_we_wb_o = rf_we_wb;
assign rf_raddr_b_o = rf_raddr_b;
if (RegFileECC) begin : gen_regfile_ecc
@ -794,26 +792,26 @@ module ibex_core #(
// ECC checkbit generation for regiter file wdata
prim_secded_39_32_enc regfile_ecc_enc (
.in (rf_wdata_wb),
.out (rf_wdata_wb_ecc)
.out (rf_wdata_wb_ecc_o)
);
// ECC checking on register file rdata
prim_secded_39_32_dec regfile_ecc_dec_a (
.in (rf_rdata_a_ecc),
.in (rf_rdata_a_ecc_i),
.d_o (),
.syndrome_o (),
.err_o (rf_ecc_err_a)
);
prim_secded_39_32_dec regfile_ecc_dec_b (
.in (rf_rdata_b_ecc),
.in (rf_rdata_b_ecc_i),
.d_o (),
.syndrome_o (),
.err_o (rf_ecc_err_b)
);
// Assign read outputs - no error correction, just trigger an alert
assign rf_rdata_a = rf_rdata_a_ecc[31:0];
assign rf_rdata_b = rf_rdata_b_ecc[31:0];
assign rf_rdata_a = rf_rdata_a_ecc_i[31:0];
assign rf_rdata_b = rf_rdata_b_ecc_i[31:0];
// Calculate errors - qualify with WB forwarding to avoid xprop into the alert signal
assign rf_ecc_err_a_id = |rf_ecc_err_a & rf_ren_a & ~rf_rd_a_wb_match;
@ -830,73 +828,12 @@ module ibex_core #(
assign unused_rf_ren_b = rf_ren_b;
assign unused_rf_rd_a_wb_match = rf_rd_a_wb_match;
assign unused_rf_rd_b_wb_match = rf_rd_b_wb_match;
assign rf_wdata_wb_ecc = rf_wdata_wb;
assign rf_rdata_a = rf_rdata_a_ecc;
assign rf_rdata_b = rf_rdata_b_ecc;
assign rf_wdata_wb_ecc_o = rf_wdata_wb;
assign rf_rdata_a = rf_rdata_a_ecc_i;
assign rf_rdata_b = rf_rdata_b_ecc_i;
assign rf_ecc_err_comb = 1'b0;
end
if (RegFile == RegFileFF) begin : gen_regfile_ff
ibex_register_file_ff #(
.RV32E ( RV32E ),
.DataWidth ( RegFileDataWidth ),
.DummyInstructions ( DummyInstructions )
) register_file_i (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.test_en_i ( test_en_i ),
.dummy_instr_id_i ( dummy_instr_id ),
.raddr_a_i ( rf_raddr_a ),
.rdata_a_o ( rf_rdata_a_ecc ),
.raddr_b_i ( rf_raddr_b ),
.rdata_b_o ( rf_rdata_b_ecc ),
.waddr_a_i ( rf_waddr_wb ),
.wdata_a_i ( rf_wdata_wb_ecc ),
.we_a_i ( rf_we_wb )
);
end else if (RegFile == RegFileFPGA) begin : gen_regfile_fpga
ibex_register_file_fpga #(
.RV32E ( RV32E ),
.DataWidth ( RegFileDataWidth ),
.DummyInstructions ( DummyInstructions )
) register_file_i (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.test_en_i ( test_en_i ),
.dummy_instr_id_i ( dummy_instr_id ),
.raddr_a_i ( rf_raddr_a ),
.rdata_a_o ( rf_rdata_a_ecc ),
.raddr_b_i ( rf_raddr_b ),
.rdata_b_o ( rf_rdata_b_ecc ),
.waddr_a_i ( rf_waddr_wb ),
.wdata_a_i ( rf_wdata_wb_ecc ),
.we_a_i ( rf_we_wb )
);
end else if (RegFile == RegFileLatch) begin : gen_regfile_latch
ibex_register_file_latch #(
.RV32E ( RV32E ),
.DataWidth ( RegFileDataWidth ),
.DummyInstructions ( DummyInstructions )
) register_file_i (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
.test_en_i ( test_en_i ),
.dummy_instr_id_i ( dummy_instr_id ),
.raddr_a_i ( rf_raddr_a ),
.rdata_a_o ( rf_rdata_a_ecc ),
.raddr_b_i ( rf_raddr_b ),
.rdata_b_o ( rf_rdata_b_ecc ),
.waddr_a_i ( rf_waddr_wb ),
.wdata_a_i ( rf_wdata_wb_ecc ),
.we_a_i ( rf_we_wb )
);
end
///////////////////////
// Crash dump output //
@ -993,7 +930,7 @@ module ibex_core #(
.RV32M ( RV32M ),
.RV32B ( RV32B )
) cs_registers_i (
.clk_i ( clk ),
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
// Hart ID from outside
@ -1021,7 +958,7 @@ module ibex_core #(
.irq_external_i ( irq_external_i ),
.irq_fast_i ( irq_fast_i ),
.nmi_mode_i ( nmi_mode ),
.irq_pending_o ( irq_pending ),
.irq_pending_o ( irq_pending_o ),
.irqs_o ( irqs ),
.csr_mstatus_mie_o ( csr_mstatus_mie ),
.csr_mstatus_tw_o ( csr_mstatus_tw ),
@ -1104,7 +1041,7 @@ module ibex_core #(
.PMPNumChan ( PMP_NUM_CHAN ),
.PMPNumRegions ( PMPNumRegions )
) pmp_i (
.clk_i ( clk ),
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
// Interface to CSRs
.csr_pmp_cfg_i ( csr_pmp_cfg ),
@ -1212,7 +1149,7 @@ module ibex_core #(
assign rvfi_instr_new_wb = rvfi_instr_new_wb_q;
always_ff @(posedge clk or negedge rst_ni) begin
always_ff @(posedge clk_i or negedge rst_ni) begin
if (~rst_ni) begin
rvfi_instr_new_wb_q <= 0;
end else begin
@ -1229,7 +1166,7 @@ module ibex_core #(
end
for (genvar i = 0;i < RVFI_STAGES; i = i + 1) begin : g_rvfi_stages
always_ff @(posedge clk or negedge rst_ni) begin
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
rvfi_stage_halt[i] <= '0;
rvfi_stage_trap[i] <= '0;
@ -1338,7 +1275,7 @@ module ibex_core #(
end
end
always_ff @(posedge clk or negedge rst_ni) begin
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
rvfi_mem_addr_q <= '0;
rvfi_mem_rdata_q <= '0;
@ -1386,7 +1323,7 @@ module ibex_core #(
rvfi_rs3_addr_d = rf_raddr_a;
end
end
always_ff @(posedge clk or negedge rst_ni) begin
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
rvfi_rs1_data_q <= '0;
rvfi_rs1_addr_q <= '0;
@ -1425,7 +1362,7 @@ module ibex_core #(
// RD write register is refreshed only once per cycle and
// then it is kept stable for the cycle.
always_ff @(posedge clk or negedge rst_ni) begin
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
rvfi_rd_addr_q <= '0;
rvfi_rd_wdata_q <= '0;
@ -1453,7 +1390,7 @@ module ibex_core #(
end
end
always_ff @(posedge clk or negedge rst_ni) begin
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
rvfi_set_trap_pc_q <= 1'b0;
rvfi_intr_q <= 1'b0;

View file

@ -10,9 +10,12 @@
`include "prim_assert.sv"
module ibex_icache #(
module ibex_icache import ibex_pkg::*; #(
parameter bit BranchPredictor = 1'b0,
parameter bit ICacheECC = 1'b0,
parameter int unsigned BusSizeECC = BUS_SIZE,
parameter int unsigned TagSizeECC = IC_TAG_SIZE,
parameter int unsigned LineSizeECC = IC_LINE_SIZE,
// Only cache branch targets
parameter bit BranchCache = 1'b0
) (
@ -42,28 +45,33 @@ module ibex_icache #(
output logic instr_req_o,
input logic instr_gnt_i,
output logic [31:0] instr_addr_o,
input logic [ibex_pkg::BUS_WIDTH-1:0] instr_rdata_i,
input logic [BUS_SIZE-1:0] instr_rdata_i,
input logic instr_err_i,
input logic instr_pmp_err_i,
input logic instr_rvalid_i,
// RAM IO
output logic [IC_NUM_WAYS-1:0] ic_tag_req_o,
output logic ic_tag_write_o,
output logic [IC_INDEX_W-1:0] ic_tag_addr_o,
output logic [TagSizeECC-1:0] ic_tag_wdata_o,
input logic [TagSizeECC-1:0] ic_tag_rdata_i [IC_NUM_WAYS],
output logic [IC_NUM_WAYS-1:0] ic_data_req_o,
output logic ic_data_write_o,
output logic [IC_INDEX_W-1:0] ic_data_addr_o,
output logic [LineSizeECC-1:0] ic_data_wdata_o,
input logic [LineSizeECC-1:0] ic_data_rdata_i [IC_NUM_WAYS],
// Cache status
input prim_ram_1p_pkg::ram_1p_cfg_t ram_cfg_i,
input logic icache_enable_i,
input logic icache_inval_i,
output logic busy_o
);
import ibex_pkg::*;
// Number of fill buffers (must be >= 2)
localparam int unsigned NUM_FB = 4;
// Request throttling threshold
localparam int unsigned FB_THRESHOLD = NUM_FB - 2;
// Derived parameters
localparam int unsigned BUS_SIZE_ECC = ICacheECC ? (BUS_WIDTH + 7) : BUS_WIDTH;
localparam int unsigned LINE_SIZE_ECC = BUS_SIZE_ECC * IC_LINE_BEATS;
localparam int unsigned TAG_SIZE_ECC = ICacheECC ? (IC_TAG_SIZE + 6) : IC_TAG_SIZE;
// Prefetch signals
logic [ADDR_W-1:0] lookup_addr_aligned;
@ -88,16 +96,16 @@ module ibex_icache #(
logic [IC_INDEX_W-1:0] tag_index_ic0;
logic [IC_NUM_WAYS-1:0] tag_banks_ic0;
logic tag_write_ic0;
logic [TAG_SIZE_ECC-1:0] tag_wdata_ic0;
logic [TagSizeECC-1:0] tag_wdata_ic0;
logic data_req_ic0;
logic [IC_INDEX_W-1:0] data_index_ic0;
logic [IC_NUM_WAYS-1:0] data_banks_ic0;
logic data_write_ic0;
logic [LINE_SIZE_ECC-1:0] data_wdata_ic0;
logic [LineSizeECC-1:0] data_wdata_ic0;
// Cache pipelipe IC1 signals
logic [TAG_SIZE_ECC-1:0] tag_rdata_ic1 [IC_NUM_WAYS];
logic [LINE_SIZE_ECC-1:0] data_rdata_ic1 [IC_NUM_WAYS];
logic [LINE_SIZE_ECC-1:0] hit_data_ecc_ic1;
logic [TagSizeECC-1:0] tag_rdata_ic1 [IC_NUM_WAYS];
logic [LineSizeECC-1:0] data_rdata_ic1 [IC_NUM_WAYS];
logic [LineSizeECC-1:0] hit_data_ecc_ic1;
logic [IC_LINE_SIZE-1:0] hit_data_ic1;
logic lookup_valid_ic1;
logic [ADDR_W-1:IC_INDEX_HI+1] lookup_addr_ic1;
@ -307,8 +315,8 @@ module ibex_icache #(
// Dataram ECC
for (genvar bank = 0; bank < IC_LINE_BEATS; bank++) begin : gen_ecc_banks
prim_secded_39_32_enc data_ecc_enc (
.in (fill_wdata_ic0[bank*BUS_WIDTH+:BUS_WIDTH]),
.out (data_wdata_ic0[bank*BUS_SIZE_ECC+:BUS_SIZE_ECC])
.in (fill_wdata_ic0[bank*BUS_SIZE+:BUS_SIZE]),
.out (data_wdata_ic0[bank*BusSizeECC+:BusSizeECC])
);
end
@ -321,38 +329,23 @@ module ibex_icache #(
// IC0 -> IC1 //
////////////////
for (genvar way = 0; way < IC_NUM_WAYS; way++) begin : gen_rams
// Tag RAM instantiation
prim_ram_1p #(
.Width (TAG_SIZE_ECC),
.Depth (IC_NUM_LINES),
.DataBitsPerMask (TAG_SIZE_ECC)
) tag_bank (
.clk_i (clk_i),
.req_i (tag_req_ic0 & tag_banks_ic0[way]),
.cfg_i (ram_cfg_i),
.write_i (tag_write_ic0),
.wmask_i ({TAG_SIZE_ECC{1'b1}}),
.addr_i (tag_index_ic0),
.wdata_i (tag_wdata_ic0),
.rdata_o (tag_rdata_ic1[way])
);
// Data RAM instantiation
prim_ram_1p #(
.Width (LINE_SIZE_ECC),
.Depth (IC_NUM_LINES),
.DataBitsPerMask (LINE_SIZE_ECC)
) data_bank (
.clk_i (clk_i),
.req_i (data_req_ic0 & data_banks_ic0[way]),
.cfg_i (ram_cfg_i),
.write_i (data_write_ic0),
.wmask_i ({LINE_SIZE_ECC{1'b1}}),
.addr_i (data_index_ic0),
.wdata_i (data_wdata_ic0),
.rdata_o (data_rdata_ic1[way])
);
end
// Tag RAMs outputs
assign ic_tag_req_o = {IC_NUM_WAYS{tag_req_ic0}} & tag_banks_ic0;
assign ic_tag_write_o = tag_write_ic0;
assign ic_tag_addr_o = tag_index_ic0;
assign ic_tag_wdata_o = tag_wdata_ic0;
// Tag RAMs inputs
assign tag_rdata_ic1 = ic_tag_rdata_i;
// Data RAMs outputs
assign ic_data_req_o = {IC_NUM_WAYS{data_req_ic0}} & data_banks_ic0;
assign ic_data_write_o = data_write_ic0;
assign ic_data_addr_o = data_index_ic0;
assign ic_data_wdata_o = data_wdata_ic0;
// Data RAMs inputs
assign data_rdata_ic1 = ic_data_rdata_i;
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
@ -427,7 +420,7 @@ module ibex_icache #(
logic [27:0] tag_rdata_padded_ic1;
// Expand the tag rdata with extra padding if the tag size is less than the maximum
assign tag_rdata_padded_ic1 = {tag_rdata_ic1[way][TAG_SIZE_ECC-1-:6],
assign tag_rdata_padded_ic1 = {tag_rdata_ic1[way][TagSizeECC-1-:6],
{22-IC_TAG_SIZE{1'b0}},
tag_rdata_ic1[way][IC_TAG_SIZE-1:0]};
@ -444,14 +437,14 @@ module ibex_icache #(
// Note - could generate for all ways and mux after
for (genvar bank = 0; bank < IC_LINE_BEATS; bank++) begin : gen_ecc_banks
prim_secded_39_32_dec data_ecc_dec (
.in (hit_data_ecc_ic1[bank*BUS_SIZE_ECC+:BUS_SIZE_ECC]),
.in (hit_data_ecc_ic1[bank*BusSizeECC+:BusSizeECC]),
.d_o (),
.syndrome_o (),
.err_o (data_err_ic1[bank*2+:2])
);
assign hit_data_ic1[bank*BUS_WIDTH+:BUS_WIDTH] =
hit_data_ecc_ic1[bank*BUS_SIZE_ECC+:BUS_WIDTH];
assign hit_data_ic1[bank*BUS_SIZE+:BUS_SIZE] =
hit_data_ecc_ic1[bank*BusSizeECC+:BUS_SIZE];
end
@ -817,7 +810,7 @@ module ibex_icache #(
always_ff @(posedge clk_i) begin
if (fill_data_en[fb][b]) begin
fill_data_q[fb][b*BUS_WIDTH+:BUS_WIDTH] <= fill_data_d[fb][b*BUS_WIDTH+:BUS_WIDTH];
fill_data_q[fb][b*BUS_SIZE+:BUS_SIZE] <= fill_data_d[fb][b*BUS_SIZE+:BUS_SIZE];
end
end
@ -983,7 +976,7 @@ module ibex_icache #(
end
end
// Mux the data from BUS_WIDTH to halfword
// Mux the data from BUS_SIZE to halfword
// This muxing realigns data when instruction words are split across BUS_W e.g.
// word 1 |----|*h1*|
// word 0 |*h0*|----| --> |*h1*|*h0*|
@ -1061,7 +1054,7 @@ module ibex_icache #(
// ECC primitives will need to be changed for different sizes
`ASSERT_INIT(ecc_tag_param_legal, (IC_TAG_SIZE <= 27))
`ASSERT_INIT(ecc_data_param_legal, !ICacheECC || (BUS_WIDTH == 32))
`ASSERT_INIT(ecc_data_param_legal, !ICacheECC || (BUS_SIZE == 32))
// Lookups in the tag ram should always give a known result
`ASSERT_KNOWN(TagHitKnown, lookup_valid_ic1 & tag_hit_ic1)

View file

@ -12,19 +12,21 @@
`include "prim_assert.sv"
module ibex_if_stage #(
module ibex_if_stage import ibex_pkg::*; #(
parameter int unsigned DmHaltAddr = 32'h1A110800,
parameter int unsigned DmExceptionAddr = 32'h1A110808,
parameter bit DummyInstructions = 1'b0,
parameter bit ICache = 1'b0,
parameter bit ICacheECC = 1'b0,
parameter int unsigned BusSizeECC = BUS_SIZE,
parameter int unsigned TagSizeECC = IC_TAG_SIZE,
parameter int unsigned LineSizeECC = IC_LINE_SIZE,
parameter bit PCIncrCheck = 1'b0,
parameter bit BranchPredictor = 1'b0
) (
input logic clk_i,
input logic rst_ni,
input prim_ram_1p_pkg::ram_1p_cfg_t ram_cfg_i,
input logic [31:0] boot_addr_i, // also used for mtvec
input logic req_i, // instruction request control
@ -37,6 +39,18 @@ module ibex_if_stage #(
input logic instr_err_i,
input logic instr_pmp_err_i,
// ICache RAM IO
output logic [IC_NUM_WAYS-1:0] ic_tag_req_o,
output logic ic_tag_write_o,
output logic [IC_INDEX_W-1:0] ic_tag_addr_o,
output logic [TagSizeECC-1:0] ic_tag_wdata_o,
input logic [TagSizeECC-1:0] ic_tag_rdata_i [IC_NUM_WAYS],
output logic [IC_NUM_WAYS-1:0] ic_data_req_o,
output logic ic_data_write_o,
output logic [IC_INDEX_W-1:0] ic_data_addr_o,
output logic [LineSizeECC-1:0] ic_data_wdata_o,
input logic [LineSizeECC-1:0] ic_data_rdata_i [IC_NUM_WAYS],
// output of ID stage
output logic instr_valid_id_o, // instr in IF-ID is valid
output logic instr_new_id_o, // instr in IF-ID is new
@ -45,7 +59,7 @@ module ibex_if_stage #(
// to reduce fan-out
output logic [15:0] instr_rdata_c_id_o, // compressed instr for ID stage
// (mtval), meaningful only if
// instr_is_compressed_id_o = 1'b1
// instr_is_compressed_id_o = 1'b1
output logic instr_is_compressed_id_o, // compressed decoder thinks this
// is a compressed instr
output logic instr_bp_taken_o, // instruction was predicted to be
@ -62,11 +76,11 @@ module ibex_if_stage #(
input logic instr_valid_clear_i, // clear instr valid bit in IF-ID
input logic pc_set_i, // set the PC to a new value
input logic pc_set_spec_i,
input ibex_pkg::pc_sel_e pc_mux_i, // selector for PC multiplexer
input pc_sel_e pc_mux_i, // selector for PC multiplexer
input logic nt_branch_mispredict_i, // Not-taken branch in ID/EX was
// mispredicted (predicted taken)
input ibex_pkg::exc_pc_sel_e exc_pc_mux_i, // selects ISR address
input ibex_pkg::exc_cause_e exc_cause, // selects ISR address for
input exc_pc_sel_e exc_pc_mux_i, // selects ISR address
input exc_cause_e exc_cause, // selects ISR address for
// vectorized interrupt lines
input logic dummy_instr_en_i,
input logic [2:0] dummy_instr_mask_i,
@ -94,8 +108,6 @@ module ibex_if_stage #(
output logic if_busy_o // IF stage is busy fetching instr
);
import ibex_pkg::*;
logic instr_valid_id_d, instr_valid_id_q;
logic instr_new_id_d, instr_new_id_q;
@ -186,7 +198,10 @@ module ibex_if_stage #(
// Full I-Cache option
ibex_icache #(
.BranchPredictor (BranchPredictor),
.ICacheECC (ICacheECC)
.ICacheECC (ICacheECC),
.BusSizeECC (BusSizeECC),
.TagSizeECC (TagSizeECC),
.LineSizeECC (LineSizeECC)
) icache_i (
.clk_i ( clk_i ),
.rst_ni ( rst_ni ),
@ -214,7 +229,17 @@ module ibex_if_stage #(
.instr_err_i ( instr_err_i ),
.instr_pmp_err_i ( instr_pmp_err_i ),
.ram_cfg_i ( ram_cfg_i ),
.ic_tag_req_o ( ic_tag_req_o ),
.ic_tag_write_o ( ic_tag_write_o ),
.ic_tag_addr_o ( ic_tag_addr_o ),
.ic_tag_wdata_o ( ic_tag_wdata_o ),
.ic_tag_rdata_i ( ic_tag_rdata_i ),
.ic_data_req_o ( ic_data_req_o ),
.ic_data_write_o ( ic_data_write_o ),
.ic_data_addr_o ( ic_data_addr_o ),
.ic_data_wdata_o ( ic_data_wdata_o ),
.ic_data_rdata_i ( ic_data_rdata_i ),
.icache_enable_i ( icache_enable_i ),
.icache_inval_i ( icache_inval_i ),
.busy_o ( prefetch_busy )
@ -253,11 +278,21 @@ module ibex_if_stage #(
.busy_o ( prefetch_busy )
);
// ICache tieoffs
logic unused_icen, unused_icinv;
prim_ram_1p_pkg::ram_1p_cfg_t unused_ram_cfg;
assign unused_icen = icache_enable_i;
assign unused_icinv = icache_inval_i;
assign unused_ram_cfg = ram_cfg_i;
logic unused_icen, unused_icinv;
logic [TagSizeECC-1:0] unused_tag_ram_input [IC_NUM_WAYS];
logic [LineSizeECC-1:0] unused_data_ram_input [IC_NUM_WAYS];
assign unused_icen = icache_enable_i;
assign unused_icinv = icache_inval_i;
assign unused_tag_ram_input = ic_tag_rdata_i;
assign unused_data_ram_input = ic_data_rdata_i;
assign ic_tag_req_o = 'b0;
assign ic_tag_write_o = 'b0;
assign ic_tag_addr_o = 'b0;
assign ic_tag_wdata_o = 'b0;
assign ic_data_req_o = 'b0;
assign ic_data_write_o = 'b0;
assign ic_data_addr_o = 'b0;
assign ic_data_wdata_o = 'b0;
end
assign unused_fetch_addr_n0 = fetch_addr_n[0];

View file

@ -19,6 +19,14 @@ typedef struct packed {
logic [31:0] exception_addr;
} crash_dump_t;
typedef struct packed {
logic dummy_instr_id;
logic [4:0] raddr_a;
logic [4:0] waddr_a;
logic we_a;
logic [4:0] raddr_b;
} core2rf_t;
/////////////////////
// Parameter Enums //
/////////////////////

411
rtl/ibex_top.sv Normal file
View file

@ -0,0 +1,411 @@
// Copyright lowRISC contributors.
// Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
`ifdef RISCV_FORMAL
`define RVFI
`endif
/**
* Top level module of the ibex RISC-V core
*/
module ibex_top #(
parameter bit PMPEnable = 1'b0,
parameter int unsigned PMPGranularity = 0,
parameter int unsigned PMPNumRegions = 4,
parameter int unsigned MHPMCounterNum = 0,
parameter int unsigned MHPMCounterWidth = 40,
parameter bit RV32E = 1'b0,
parameter ibex_pkg::rv32m_e RV32M = ibex_pkg::RV32MFast,
parameter ibex_pkg::rv32b_e RV32B = ibex_pkg::RV32BNone,
parameter ibex_pkg::regfile_e RegFile = ibex_pkg::RegFileFF,
parameter bit BranchTargetALU = 1'b0,
parameter bit WritebackStage = 1'b0,
parameter bit ICache = 1'b0,
parameter bit ICacheECC = 1'b0,
parameter bit BranchPredictor = 1'b0,
parameter bit DbgTriggerEn = 1'b0,
parameter int unsigned DbgHwBreakNum = 1,
parameter bit SecureIbex = 1'b0,
parameter int unsigned DmHaltAddr = 32'h1A110800,
parameter int unsigned DmExceptionAddr = 32'h1A110808
) (
// Clock and Reset
input logic clk_i,
input logic rst_ni,
input logic test_en_i, // enable all clock gates for testing
input prim_ram_1p_pkg::ram_1p_cfg_t ram_cfg_i,
input logic [31:0] hart_id_i,
input logic [31:0] boot_addr_i,
// Instruction memory interface
output logic instr_req_o,
input logic instr_gnt_i,
input logic instr_rvalid_i,
output logic [31:0] instr_addr_o,
input logic [31:0] instr_rdata_i,
input logic instr_err_i,
// Data memory interface
output logic data_req_o,
input logic data_gnt_i,
input logic data_rvalid_i,
output logic data_we_o,
output logic [3:0] data_be_o,
output logic [31:0] data_addr_o,
output logic [31:0] data_wdata_o,
input logic [31:0] data_rdata_i,
input logic data_err_i,
// Interrupt inputs
input logic irq_software_i,
input logic irq_timer_i,
input logic irq_external_i,
input logic [14:0] irq_fast_i,
input logic irq_nm_i, // non-maskeable interrupt
// Debug Interface
input logic debug_req_i,
output ibex_pkg::crash_dump_t crash_dump_o,
// RISC-V Formal Interface
// Does not comply with the coding standards of _i/_o suffixes, but follows
// the convention of RISC-V Formal Interface Specification.
`ifdef RVFI
output logic rvfi_valid,
output logic [63:0] rvfi_order,
output logic [31:0] rvfi_insn,
output logic rvfi_trap,
output logic rvfi_halt,
output logic rvfi_intr,
output logic [ 1:0] rvfi_mode,
output logic [ 1:0] rvfi_ixl,
output logic [ 4:0] rvfi_rs1_addr,
output logic [ 4:0] rvfi_rs2_addr,
output logic [ 4:0] rvfi_rs3_addr,
output logic [31:0] rvfi_rs1_rdata,
output logic [31:0] rvfi_rs2_rdata,
output logic [31:0] rvfi_rs3_rdata,
output logic [ 4:0] rvfi_rd_addr,
output logic [31:0] rvfi_rd_wdata,
output logic [31:0] rvfi_pc_rdata,
output logic [31:0] rvfi_pc_wdata,
output logic [31:0] rvfi_mem_addr,
output logic [ 3:0] rvfi_mem_rmask,
output logic [ 3:0] rvfi_mem_wmask,
output logic [31:0] rvfi_mem_rdata,
output logic [31:0] rvfi_mem_wdata,
`endif
// CPU Control Signals
input logic fetch_enable_i,
output logic alert_minor_o,
output logic alert_major_o,
output logic core_sleep_o
);
import ibex_pkg::*;
localparam bit DummyInstructions = SecureIbex;
localparam bit RegFileECC = SecureIbex;
localparam int unsigned RegFileDataWidth = RegFileECC ? 32 + 7 : 32;
// Icache parameters
localparam int unsigned BusSizeECC = ICacheECC ? (BUS_SIZE + 7) : BUS_SIZE;
localparam int unsigned LineSizeECC = BusSizeECC * IC_LINE_BEATS;
localparam int unsigned TagSizeECC = ICacheECC ? (IC_TAG_SIZE + 6) : IC_TAG_SIZE;
// Clock signals
logic clk;
logic core_busy_d, core_busy_q;
logic fetch_enable_q;
logic clock_en;
logic irq_pending;
// Core <-> Register file signals
logic dummy_instr_id;
logic [4:0] rf_raddr_a;
logic [4:0] rf_raddr_b;
logic [4:0] rf_waddr_wb;
logic rf_we_wb;
logic [RegFileDataWidth-1:0] rf_wdata_wb_ecc;
logic [RegFileDataWidth-1:0] rf_rdata_a_ecc;
logic [RegFileDataWidth-1:0] rf_rdata_b_ecc;
// Core <-> RAMs signals
logic [IC_NUM_WAYS-1:0] ic_tag_req;
logic ic_tag_write;
logic [IC_INDEX_W-1:0] ic_tag_addr;
logic [TagSizeECC-1:0] ic_tag_wdata;
logic [TagSizeECC-1:0] ic_tag_rdata [IC_NUM_WAYS];
logic [IC_NUM_WAYS-1:0] ic_data_req;
logic ic_data_write;
logic [IC_INDEX_W-1:0] ic_data_addr;
logic [LineSizeECC-1:0] ic_data_wdata;
logic [LineSizeECC-1:0] ic_data_rdata [IC_NUM_WAYS];
/////////////////////
// Main clock gate //
/////////////////////
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
core_busy_q <= 1'b0;
end else begin
core_busy_q <= core_busy_d;
end
end
// capture fetch_enable_i in fetch_enable_q, once for ever
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
fetch_enable_q <= 1'b0;
end else if (fetch_enable_i) begin
fetch_enable_q <= 1'b1;
end
end
assign clock_en = fetch_enable_q & (core_busy_q | debug_req_i | irq_pending | irq_nm_i);
assign core_sleep_o = ~clock_en;
prim_clock_gating core_clock_gate_i (
.clk_i ( clk_i ),
.en_i ( clock_en ),
.test_en_i ( test_en_i ),
.clk_o ( clk )
);
////////////////////////
// Core instantiation //
////////////////////////
ibex_core #(
.PMPEnable ( PMPEnable ),
.PMPGranularity ( PMPGranularity ),
.PMPNumRegions ( PMPNumRegions ),
.MHPMCounterNum ( MHPMCounterNum ),
.MHPMCounterWidth ( MHPMCounterWidth ),
.RV32E ( RV32E ),
.RV32M ( RV32M ),
.RV32B ( RV32B ),
.BranchTargetALU ( BranchTargetALU ),
.ICache ( ICache ),
.ICacheECC ( ICacheECC ),
.BusSizeECC ( BusSizeECC ),
.TagSizeECC ( TagSizeECC ),
.LineSizeECC ( LineSizeECC ),
.BranchPredictor ( BranchPredictor ),
.DbgTriggerEn ( DbgTriggerEn ),
.DbgHwBreakNum ( DbgHwBreakNum ),
.WritebackStage ( WritebackStage ),
.SecureIbex ( SecureIbex ),
.DummyInstructions ( DummyInstructions ),
.RegFileECC ( RegFileECC ),
.RegFileDataWidth ( RegFileDataWidth ),
.DmHaltAddr ( DmHaltAddr ),
.DmExceptionAddr ( DmExceptionAddr )
) u_ibex_core (
.clk_i (clk),
.rst_ni,
.hart_id_i,
.boot_addr_i,
.instr_req_o,
.instr_gnt_i,
.instr_rvalid_i,
.instr_addr_o,
.instr_rdata_i,
.instr_err_i,
.data_req_o,
.data_gnt_i,
.data_rvalid_i,
.data_we_o,
.data_be_o,
.data_addr_o,
.data_wdata_o,
.data_rdata_i,
.data_err_i,
.dummy_instr_id_o (dummy_instr_id),
.rf_raddr_a_o (rf_raddr_a),
.rf_raddr_b_o (rf_raddr_b),
.rf_waddr_wb_o (rf_waddr_wb),
.rf_we_wb_o (rf_we_wb),
.rf_wdata_wb_ecc_o (rf_wdata_wb_ecc),
.rf_rdata_a_ecc_i (rf_rdata_a_ecc),
.rf_rdata_b_ecc_i (rf_rdata_b_ecc),
.ic_tag_req_o (ic_tag_req),
.ic_tag_write_o (ic_tag_write),
.ic_tag_addr_o (ic_tag_addr),
.ic_tag_wdata_o (ic_tag_wdata),
.ic_tag_rdata_i (ic_tag_rdata),
.ic_data_req_o (ic_data_req),
.ic_data_write_o (ic_data_write),
.ic_data_addr_o (ic_data_addr),
.ic_data_wdata_o (ic_data_wdata),
.ic_data_rdata_i (ic_data_rdata),
.irq_software_i,
.irq_timer_i,
.irq_external_i,
.irq_fast_i,
.irq_nm_i,
.irq_pending_o (irq_pending),
.debug_req_i,
.crash_dump_o,
`ifdef RVFI
.rvfi_valid,
.rvfi_order,
.rvfi_insn,
.rvfi_trap,
.rvfi_halt,
.rvfi_intr,
.rvfi_mode,
.rvfi_ixl,
.rvfi_rs1_addr,
.rvfi_rs2_addr,
.rvfi_rs3_addr,
.rvfi_rs1_rdata,
.rvfi_rs2_rdata,
.rvfi_rs3_rdata,
.rvfi_rd_addr,
.rvfi_rd_wdata,
.rvfi_pc_rdata,
.rvfi_pc_wdata,
.rvfi_mem_addr,
.rvfi_mem_rmask,
.rvfi_mem_wmask,
.rvfi_mem_rdata,
.rvfi_mem_wdata,
`endif
.alert_minor_o,
.alert_major_o,
.core_busy_o (core_busy_d)
);
/////////////////////////////////
// Register file Instantiation //
/////////////////////////////////
if (RegFile == RegFileFF) begin : gen_regfile_ff
ibex_register_file_ff #(
.RV32E ( RV32E ),
.DataWidth ( RegFileDataWidth ),
.DummyInstructions ( DummyInstructions )
) register_file_i (
.clk_i ( clk ),
.rst_ni ( rst_ni ),
.test_en_i ( test_en_i ),
.dummy_instr_id_i ( dummy_instr_id ),
.raddr_a_i ( rf_raddr_a ),
.rdata_a_o ( rf_rdata_a_ecc ),
.raddr_b_i ( rf_raddr_b ),
.rdata_b_o ( rf_rdata_b_ecc ),
.waddr_a_i ( rf_waddr_wb ),
.wdata_a_i ( rf_wdata_wb_ecc ),
.we_a_i ( rf_we_wb )
);
end else if (RegFile == RegFileFPGA) begin : gen_regfile_fpga
ibex_register_file_fpga #(
.RV32E ( RV32E ),
.DataWidth ( RegFileDataWidth ),
.DummyInstructions ( DummyInstructions )
) register_file_i (
.clk_i ( clk ),
.rst_ni ( rst_ni ),
.test_en_i ( test_en_i ),
.dummy_instr_id_i ( dummy_instr_id ),
.raddr_a_i ( rf_raddr_a ),
.rdata_a_o ( rf_rdata_a_ecc ),
.raddr_b_i ( rf_raddr_b ),
.rdata_b_o ( rf_rdata_b_ecc ),
.waddr_a_i ( rf_waddr_wb ),
.wdata_a_i ( rf_wdata_wb_ecc ),
.we_a_i ( rf_we_wb )
);
end else if (RegFile == RegFileLatch) begin : gen_regfile_latch
ibex_register_file_latch #(
.RV32E ( RV32E ),
.DataWidth ( RegFileDataWidth ),
.DummyInstructions ( DummyInstructions )
) register_file_i (
.clk_i ( clk ),
.rst_ni ( rst_ni ),
.test_en_i ( test_en_i ),
.dummy_instr_id_i ( dummy_instr_id ),
.raddr_a_i ( rf_raddr_a ),
.rdata_a_o ( rf_rdata_a_ecc ),
.raddr_b_i ( rf_raddr_b ),
.rdata_b_o ( rf_rdata_b_ecc ),
.waddr_a_i ( rf_waddr_wb ),
.wdata_a_i ( rf_wdata_wb_ecc ),
.we_a_i ( rf_we_wb )
);
end
////////////////////////
// Rams Instantiation //
////////////////////////
if (ICache) begin : gen_rams
for (genvar way = 0; way < IC_NUM_WAYS; way++) begin : gen_rams
// Tag RAM instantiation
prim_ram_1p #(
.Width (TagSizeECC),
.Depth (IC_NUM_LINES),
.DataBitsPerMask (TagSizeECC)
) tag_bank (
.clk_i (clk_i),
.req_i (ic_tag_req[way]),
.cfg_i (ram_cfg_i),
.write_i (ic_tag_write),
.wmask_i ({TagSizeECC{1'b1}}),
.addr_i (ic_tag_addr),
.wdata_i (ic_tag_wdata),
.rdata_o (ic_tag_rdata[way])
);
// Data RAM instantiation
prim_ram_1p #(
.Width (LineSizeECC),
.Depth (IC_NUM_LINES),
.DataBitsPerMask (LineSizeECC)
) data_bank (
.clk_i (clk_i),
.req_i (ic_data_req[way]),
.cfg_i (ram_cfg_i),
.write_i (ic_data_write),
.wmask_i ({LineSizeECC{1'b1}}),
.addr_i (ic_data_addr),
.wdata_i (ic_data_wdata),
.rdata_o (ic_data_rdata[way])
);
end
end else begin : gen_norams
prim_ram_1p_pkg::ram_1p_cfg_t unused_ram_cfg;
logic unused_ram_inputs;
assign unused_ram_cfg = ram_cfg_i;
assign unused_ram_inputs = 1'b0 & (|ic_tag_req) & ic_tag_write & (|ic_tag_addr) &
(|ic_tag_wdata) & (|ic_data_req) & ic_data_write & (|ic_data_addr) &
(|ic_data_wdata);
assign ic_tag_rdata = '{default:'b0};
assign ic_data_rdata = '{default:'b0};
end
endmodule

View file

@ -6,7 +6,7 @@
* Top level module of the ibex RISC-V core with tracing enabled
*/
module ibex_core_tracing #(
module ibex_top_tracing #(
parameter bit PMPEnable = 1'b0,
parameter int unsigned PMPGranularity = 0,
parameter int unsigned PMPNumRegions = 4,
@ -107,7 +107,7 @@ module ibex_core_tracing #(
logic [31:0] rvfi_mem_rdata;
logic [31:0] rvfi_mem_wdata;
ibex_core #(
ibex_top #(
.PMPEnable ( PMPEnable ),
.PMPGranularity ( PMPGranularity ),
.PMPNumRegions ( PMPNumRegions ),
@ -127,7 +127,7 @@ module ibex_core_tracing #(
.SecureIbex ( SecureIbex ),
.DmHaltAddr ( DmHaltAddr ),
.DmExceptionAddr ( DmExceptionAddr )
) u_ibex_core (
) u_ibex_top (
.clk_i,
.rst_ni,

View file

@ -72,10 +72,10 @@ flow. All outputs are placed under the `syn/syn_out` directory with the prefix
- sta.log - Log of the OpenSTA run
- `generated`
- *.v - Ibex RTL after sv2v processing
- ibex_core.pre_map.v - Pre-mapping synthesis netlists
- ibex_core_netlist.v - Post-synthesis netlist
- ibex_core_netlist.sta.v - Post-synthesis netlist usable by OpenSTA
- ibex_core.[library-name].out.sdc - Generated .sdc timing constraints
- ibex_top.pre_map.v - Pre-mapping synthesis netlists
- ibex_top_netlist.v - Post-synthesis netlist
- ibex_top_netlist.sta.v - Post-synthesis netlist usable by OpenSTA
- ibex_top.[library-name].out.sdc - Generated .sdc timing constraints
file
If you wish to change the results directory naming or location edit
@ -86,7 +86,7 @@ If you wish to change the results directory naming or location edit
Two files specify the timing constraints and timing related settings for the
flow. These are used to generate a single .sdc file
* `ibex_core_lr_synth_core.tcl` - This specifies the constraints on all inputs
* `ibex_top_lr_synth_core.tcl` - This specifies the constraints on all inputs
and outputs as a fraction of a clock cycle, the names of the clock and reset
inputs and the desired clock period in ps
* `ibex.[library-name].sdc` - Header to include in generated .sdc file. Settings

View file

@ -23,7 +23,7 @@
#-------------------------------------------------------------------------
rm -Rf build lec_out
fusesoc --cores-root .. run --tool=icarus --target=lint \
--setup "lowrisc:ibex:ibex_core" > /dev/null 2>&1
--setup "lowrisc:ibex:ibex_top" > /dev/null 2>&1
# copy all files to lec_out
mkdir lec_out

View file

@ -47,8 +47,9 @@ for file in ../rtl/*.sv; do
sv2v \
--define=SYNTHESIS \
../rtl/*_pkg.sv \
../vendor/lowrisc_ip/ip/prim/rtl/prim_ram_1p_pkg.sv \
-I../vendor/lowrisc_ip/ip/prim/rtl \
-I../dv/fcov \
-I../vendor/lowrisc_ip/dv/sv/dv_utils \
$file \
> $LR_SYNTH_OUT_DIR/generated/${module}.v
done

View file

@ -5,7 +5,7 @@
puts "=================== Flow Vars ==================="
set_flow_var cell_library_path "cmos_cells.lib" "Path to cell library"
set_flow_var top_module "ibex_core" "top module"
set_flow_var top_module "ibex_top" "top module"
set_flow_var out_dir "syn_out" "Output directory for synthesis"
set_flow_var pre_map_out "./${lr_synth_out_dir}/generated/${lr_synth_top_module}.pre_map.v" "Pre-mapping netlist out"
set_flow_var netlist_out "./${lr_synth_out_dir}/generated/${lr_synth_top_module}_netlist.v" "netlist out"

View file

@ -17,18 +17,18 @@ if { $lr_synth_timing_run } {
yosys "read_verilog -sv ./rtl/prim_clock_gating.v $lr_synth_out_dir/generated/*.v"
if { $lr_synth_ibex_branch_target_alu } {
yosys "chparam -set BranchTargetALU 1 ibex_core"
yosys "chparam -set BranchTargetALU 1 $lr_synth_top_module"
}
if { $lr_synth_ibex_writeback_stage } {
yosys "chparam -set WritebackStage 1 ibex_core"
yosys "chparam -set WritebackStage 1 $lr_synth_top_module"
}
yosys "chparam -set RV32B $lr_synth_ibex_bitmanip ibex_core"
yosys "chparam -set RV32B $lr_synth_ibex_bitmanip $lr_synth_top_module"
yosys "chparam -set RV32M $lr_synth_ibex_multiplier ibex_core"
yosys "chparam -set RV32M $lr_synth_ibex_multiplier $lr_synth_top_module"
yosys "chparam -set RegFile $lr_synth_ibex_regfile ibex_core"
yosys "chparam -set RegFile $lr_synth_ibex_regfile $lr_synth_top_module"
yosys "synth $flatten_opt -top $lr_synth_top_module"
yosys "opt -purge"

View file

@ -4,7 +4,7 @@
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
# SPDX-License-Identifier: Apache-2.0
./python/build_translated_names.py ibex_core ./$LR_SYNTH_OUT_DIR/generated ./$LR_SYNTH_OUT_DIR/reports/timing/*.csv.rpt
./python/build_translated_names.py ibex_top ./$LR_SYNTH_OUT_DIR/generated ./$LR_SYNTH_OUT_DIR/reports/timing/*.csv.rpt
for file in ./$LR_SYNTH_OUT_DIR/reports/timing/*.csv.rpt; do
./python/translate_timing_csv.py $file ./$LR_SYNTH_OUT_DIR/generated