mirror of
https://github.com/openhwgroup/cve2.git
synced 2025-04-22 13:07:46 -04:00
[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:
parent
b106001d82
commit
6a3200929b
34 changed files with 980 additions and 304 deletions
|
@ -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 }}
|
||||
|
|
|
@ -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 (),
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
-----------
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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 ),
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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:
|
||||
|
|
131
dv/uvm/icache/dv/tb/ic_top.sv
Normal file
131
dv/uvm/icache/dv/tb/ic_top.sv
Normal 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
|
|
@ -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),
|
||||
|
|
|
@ -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),
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
160
ibex_top.core
Normal 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"
|
||||
|
|
@ -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:
|
|
@ -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]
|
||||
|
|
257
rtl/ibex_core.sv
257
rtl/ibex_core.sv
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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
411
rtl/ibex_top.sv
Normal 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
|
|
@ -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,
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue