├── docs
├── .gitkeep
└── user_manual
│ ├── .gitignore
│ ├── source
│ ├── _static
│ │ └── css
│ │ │ └── custom.css
│ ├── preface.rst
│ ├── index.rst
│ ├── register_file.rst
│ ├── instruction_set_extensions.rst
│ ├── fencei.rst
│ ├── glossary.rst
│ ├── pmp.rst
│ ├── perf_counters.rst
│ ├── core_versions.rst
│ ├── getting_started.rst
│ └── sleep.rst
│ ├── images
│ ├── rvfi_trace.png
│ ├── CV32E40S_Pipeline.png
│ ├── image_sources
│ │ ├── wfi.tim
│ │ ├── debug_halted.tim
│ │ ├── debug_running.tim
│ │ ├── obi_data_basic.tim
│ │ ├── obi_data_back_to_back.tim
│ │ ├── obi_instruction_basic.tim
│ │ ├── obi_data_slow_response.tim
│ │ ├── obi_instruction_basic_err.tim
│ │ ├── obi_data_multiple_outstanding.tim
│ │ ├── obi_instruction_multiple_outstanding.tim
│ │ └── obi_instruction_multiple_outstanding_err.tim
│ ├── CV32E40S_Block_Diagram.png
│ ├── Events_PCCR_PCMR_PCER.png
│ ├── riscv_prefetch_buffer.png
│ ├── Basic_Memory_Transaction.png
│ ├── Back_to_Back_Memory_Transaction.png
│ └── Slow_Response_Memory_Transaction.png
│ ├── requirements.txt
│ ├── make.bat
│ └── Makefile
├── .github
├── ISSUE_TEMPLATE
│ ├── enhancement.md
│ ├── question.md
│ ├── task.md
│ ├── config.yml
│ └── bug.md
└── release.yml
├── .gitignore
├── .dir-locals.el
├── .readthedocs.yaml
├── tb
└── README.md
├── yaml
└── README.md
├── CONTRIBUTING.md
├── bhv
├── cv32e40s_sim_clock_gate.sv
├── cv32e40s_rvfi_data_obi.sv
├── cv32e40s_sim_sffr.sv
├── cv32e40s_sim_sffs.sv
├── cv32e40s_dbg_helper.sv
└── include
│ └── cv32e40s_rvfi_pkg.sv
├── rtl
├── cv32e40s_if_c_obi.sv
├── cv32e40s_alu_b_cpop.sv
├── cv32e40s_rchk_check.sv
├── cv32e40s_popcnt.sv
├── cv32e40s_pc_target.sv
├── cv32e40s_alert.sv
├── cv32e40s_lfsr.sv
├── cv32e40s_csr.sv
├── cv32e40s_write_buffer.sv
├── cv32e40s_ff_one.sv
├── cv32e40s_register_file_wrapper.sv
├── cv32e40s_pma.sv
├── cv32e40s_sleep_unit.sv
├── cv32e40s_m_decoder.sv
├── cv32e40s_int_controller.sv
├── cv32e40s_prefetch_unit.sv
├── cv32e40s_wpt.sv
├── cv32e40s_register_file.sv
└── cv32e40s_obi_integrity_fifo.sv
├── sva
├── cv32e40s_wpt_sva.sv
├── cv32e40s_div_sva.sv
├── cv32e40s_pc_check_sva.sv
├── cv32e40s_prefetch_unit_sva.sv
├── cv32e40s_lsu_response_filter_sva.sv
├── cv32e40s_dummy_instr_sva.sv
├── cv32e40s_instr_obi_interface_sva.sv
├── cv32e40s_clic_int_controller_sva.sv
├── cv32e40s_register_file_sva.sv
├── cv32e40s_sleep_unit_sva.sv
├── cv32e40s_wb_stage_sva.sv
├── cv32e40s_parameter_sva.sv
├── cv32e40s_debug_triggers_sva.sv
└── cv32e40s_data_obi_interface_sva.sv
├── README.md
└── cv32e40s_manifest.flist
/docs/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/enhancement.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/question.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | TAGS
2 | *.swp
3 | *~
4 |
--------------------------------------------------------------------------------
/docs/user_manual/.gitignore:
--------------------------------------------------------------------------------
1 | build
2 |
--------------------------------------------------------------------------------
/docs/user_manual/source/_static/css/custom.css:
--------------------------------------------------------------------------------
1 | .no-scrollbar-table td {
2 | white-space: normal !important;
3 | }
4 |
--------------------------------------------------------------------------------
/docs/user_manual/images/rvfi_trace.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openhwgroup/cv32e40s/HEAD/docs/user_manual/images/rvfi_trace.png
--------------------------------------------------------------------------------
/docs/user_manual/images/CV32E40S_Pipeline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openhwgroup/cv32e40s/HEAD/docs/user_manual/images/CV32E40S_Pipeline.png
--------------------------------------------------------------------------------
/docs/user_manual/images/image_sources/wfi.tim:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openhwgroup/cv32e40s/HEAD/docs/user_manual/images/image_sources/wfi.tim
--------------------------------------------------------------------------------
/docs/user_manual/requirements.txt:
--------------------------------------------------------------------------------
1 | sphinx
2 | sphinx-rtd-theme
3 | recommonmark
4 | sphinxcontrib-svg2pdfconverter
5 | sphinx_github_changelog
6 |
--------------------------------------------------------------------------------
/docs/user_manual/images/CV32E40S_Block_Diagram.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openhwgroup/cv32e40s/HEAD/docs/user_manual/images/CV32E40S_Block_Diagram.png
--------------------------------------------------------------------------------
/docs/user_manual/images/Events_PCCR_PCMR_PCER.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openhwgroup/cv32e40s/HEAD/docs/user_manual/images/Events_PCCR_PCMR_PCER.png
--------------------------------------------------------------------------------
/docs/user_manual/images/riscv_prefetch_buffer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openhwgroup/cv32e40s/HEAD/docs/user_manual/images/riscv_prefetch_buffer.png
--------------------------------------------------------------------------------
/docs/user_manual/images/Basic_Memory_Transaction.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openhwgroup/cv32e40s/HEAD/docs/user_manual/images/Basic_Memory_Transaction.png
--------------------------------------------------------------------------------
/docs/user_manual/images/image_sources/debug_halted.tim:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openhwgroup/cv32e40s/HEAD/docs/user_manual/images/image_sources/debug_halted.tim
--------------------------------------------------------------------------------
/docs/user_manual/images/image_sources/debug_running.tim:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openhwgroup/cv32e40s/HEAD/docs/user_manual/images/image_sources/debug_running.tim
--------------------------------------------------------------------------------
/docs/user_manual/images/image_sources/obi_data_basic.tim:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openhwgroup/cv32e40s/HEAD/docs/user_manual/images/image_sources/obi_data_basic.tim
--------------------------------------------------------------------------------
/docs/user_manual/images/Back_to_Back_Memory_Transaction.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openhwgroup/cv32e40s/HEAD/docs/user_manual/images/Back_to_Back_Memory_Transaction.png
--------------------------------------------------------------------------------
/docs/user_manual/images/Slow_Response_Memory_Transaction.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openhwgroup/cv32e40s/HEAD/docs/user_manual/images/Slow_Response_Memory_Transaction.png
--------------------------------------------------------------------------------
/docs/user_manual/images/image_sources/obi_data_back_to_back.tim:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openhwgroup/cv32e40s/HEAD/docs/user_manual/images/image_sources/obi_data_back_to_back.tim
--------------------------------------------------------------------------------
/docs/user_manual/images/image_sources/obi_instruction_basic.tim:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openhwgroup/cv32e40s/HEAD/docs/user_manual/images/image_sources/obi_instruction_basic.tim
--------------------------------------------------------------------------------
/docs/user_manual/images/image_sources/obi_data_slow_response.tim:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openhwgroup/cv32e40s/HEAD/docs/user_manual/images/image_sources/obi_data_slow_response.tim
--------------------------------------------------------------------------------
/docs/user_manual/images/image_sources/obi_instruction_basic_err.tim:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openhwgroup/cv32e40s/HEAD/docs/user_manual/images/image_sources/obi_instruction_basic_err.tim
--------------------------------------------------------------------------------
/docs/user_manual/images/image_sources/obi_data_multiple_outstanding.tim:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openhwgroup/cv32e40s/HEAD/docs/user_manual/images/image_sources/obi_data_multiple_outstanding.tim
--------------------------------------------------------------------------------
/docs/user_manual/images/image_sources/obi_instruction_multiple_outstanding.tim:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openhwgroup/cv32e40s/HEAD/docs/user_manual/images/image_sources/obi_instruction_multiple_outstanding.tim
--------------------------------------------------------------------------------
/docs/user_manual/images/image_sources/obi_instruction_multiple_outstanding_err.tim:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/openhwgroup/cv32e40s/HEAD/docs/user_manual/images/image_sources/obi_instruction_multiple_outstanding_err.tim
--------------------------------------------------------------------------------
/docs/user_manual/source/preface.rst:
--------------------------------------------------------------------------------
1 | Changelog
2 | =========
3 |
4 | .. changelog::
5 | :changelog-url: https://cv32e40s-user-manual.readthedocs.io/en/stable/#changelog
6 | :github: https://github.com/openhwgroup/cv32e40s/releases/
7 |
--------------------------------------------------------------------------------
/.github/release.yml:
--------------------------------------------------------------------------------
1 | # .github/release.yml
2 |
3 | changelog:
4 | exclude:
5 | labels:
6 | - ignore-for-release
7 | categories:
8 | - title: Documentation Changes
9 | labels:
10 | - Component:Doc
11 | - title: RTL Changes
12 | labels:
13 | - Component:RTL
14 |
--------------------------------------------------------------------------------
/.dir-locals.el:
--------------------------------------------------------------------------------
1 | ;;; Directory Local Variables
2 | ;;; For more information see (info "(emacs) Directory Variables")
3 |
4 | ((nil . ((fill-column . 80)))
5 | (verilog-mode
6 | ;; (verilog-indent-lists quote nil)
7 | ;; (verilog-auto-lineup quote all)
8 | (verilog-cexp-indent . 2)
9 | (verilog-case-indent . 2)
10 | (verilog-indent-level-behavioral . 2)
11 | (verilog-indent-level-declaration . 2)
12 | (verilog-indent-level-module . 2)
13 | (verilog-indent-level . 2)))
14 |
15 |
--------------------------------------------------------------------------------
/docs/user_manual/source/index.rst:
--------------------------------------------------------------------------------
1 | OpenHW Group |corev| User Manual
2 | =================================
3 |
4 | .. toctree::
5 | :maxdepth: 3
6 | :caption: Contents:
7 |
8 | preface
9 | intro
10 | getting_started
11 | integration
12 | pipeline
13 | instruction_fetch
14 | load_store_unit
15 | xsecure
16 | pma
17 | pmp
18 | register_file
19 | fencei
20 | sleep
21 | control_status_registers
22 | perf_counters
23 | exceptions_interrupts
24 | debug
25 | rvfi
26 | instruction_set_extensions
27 | core_versions
28 | glossary
29 |
--------------------------------------------------------------------------------
/.readthedocs.yaml:
--------------------------------------------------------------------------------
1 | # Configuration file for ReadTheDocs, used to render the CV32E40S
2 | # User Manual to https://docs.openhwgroup.org/projects/cv32e40s-user-manual.
3 | # SPDX-License-Identifier:Apache-2.0 WITH SHL-2.1
4 |
5 | version: 2
6 |
7 | build:
8 | os: "ubuntu-20.04"
9 | tools:
10 | python: "3.9"
11 |
12 | # Build from the docs/user_manual/source directory with Sphinx
13 | sphinx:
14 | configuration: docs/user_manual/source/conf.py
15 |
16 | # Explicitly set the Python requirements
17 | python:
18 | install:
19 | - requirements: docs/user_manual/requirements.txt
20 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/task.md:
--------------------------------------------------------------------------------
1 | # Template for Task Issue
2 | Tasks are defined, assigned and tracked as GitHub Issues.
3 |
4 | ## Task Title
5 | A clear and concise description of the Task. This can go in the title bar.
6 |
7 | ### Task Outcome
8 | Provide a brief description of what is expected. If necessary point to a specification document.
9 |
10 | ### Background information
11 | If necessary point to a specification in an outside document.
12 |
13 | ### Completion Criteria
14 | Answer the question: how does the Assignee know they are done?
15 |
16 | ### Additional context
17 | Add any other context about the task here.
18 |
--------------------------------------------------------------------------------
/tb/README.md:
--------------------------------------------------------------------------------
1 | Running Simulations
2 | ==================================
3 | The core repository does not contain any verification or simulation environment.
4 | This is contained in the core-v-verif repository (https://github.com/openhwgroup/core-v-verif).
5 | ----------------------------------
6 | Follow these steps to run a simulation:
7 |
8 | 1. Clone core-v-verif to desired location:
9 |
10 | git clone https://github.com/openhwgroup/core-v-verif.git
11 |
12 | 2. Go to simulation directory:
13 |
14 | cd core-v-verif/cv32/sim/uvmt_cv32
15 |
16 | 3. Run simulation and point the core path to this repository. Example:
17 |
18 | make test TEST=hello_world CV_DUT_PATH="/path/to/this/repo/cv32e40s"
19 |
20 |
--------------------------------------------------------------------------------
/yaml/README.md:
--------------------------------------------------------------------------------
1 | # Yaml
2 |
3 | This directory contains Yaml files defining features of the core.
4 |
5 |
6 | ## CSR
7 |
8 | The CSR definition file describes the CSRs supported by the core, with fields,
9 | types, legal values, etc.
10 | _(The user manual has authoritative precedence over this file.)_
11 |
12 | It is a "superset" for all supported parameters, and one can generate subset
13 | definitions for specific parameters using the script in core-v-verif,
14 | [here](https://github.com/openhwgroup/core-v-verif/blob/cv32e40s/dev/bin/gen_csr_access_test.py).
15 | Example usage shown
16 | [here](https://github.com/openhwgroup/core-v-verif/blob/cv32e40s/dev/cv32e40s/tests/programs/custom/cv32e40s_csr_access_test/README.md)
17 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 | contact_links:
3 | - name: Bug
4 | url: https://github.com/openhwgroup/cv32e40s/issues/new?template=bug.md
5 | about: For bugs in the RTL, Documentation, Verification environment or Tool and Build system.
6 | labels: "Type:Bug"
7 | - name: Task
8 | url: https://github.com/openhwgroup/cv32e40s/issues/new?template=task.md
9 | about: For any task except bug fixes.
10 | labels: "Type:Task"
11 | - name: Question
12 | url: https://github.com/openhwgroup/cv32e40s/issues/new?template=question.md
13 | about: For general questions.
14 | labels: "Type:Question"
15 | - name: Enhancement
16 | url: https://github.com/openhwgroup/cv32e40s/issues/new?template=enhancement.md
17 | about: For feature requests and enhancements.
18 | labels: "Type:Enhancement"
19 |
--------------------------------------------------------------------------------
/docs/user_manual/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=sphinx-build
9 | )
10 | set SOURCEDIR=source
11 | set BUILDDIR=build
12 |
13 | if "%1" == "" goto help
14 |
15 | %SPHINXBUILD% >NUL 2>NUL
16 | if errorlevel 9009 (
17 | echo.
18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
19 | echo.installed, then set the SPHINXBUILD environment variable to point
20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
21 | echo.may add the Sphinx directory to PATH.
22 | echo.
23 | echo.If you don't have Sphinx installed, grab it from
24 | echo.http://sphinx-doc.org/
25 | exit /b 1
26 | )
27 |
28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
29 | goto end
30 |
31 | :help
32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
33 |
34 | :end
35 | popd
36 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug.md:
--------------------------------------------------------------------------------
1 | # Template for Bug Issue
2 |
3 | Please use this template if the issue that you are reporting is a (potential) bug in CV32E40S RTL, User Manual, or associated files like constraints or assertions.
4 |
5 |
**Note**: Please file bugs related to the core-v-verif verification environment in https://github.com/openhwgroup/core-v-verif instead.
6 |
7 | ## Bug Title
8 | A clear and concise description of what the bug is.
9 |
10 | ### Component
11 | Indicate the component in which you found a problem (and we will add the appropriate label):
12 |
13 | **Component:RTL**: For issues in the RTL (e.g. for files in the rtl directory)
14 | **Component:Doc **: For issues in the Documentation (e.g. for User Manual or README.md files)
15 | **Component:Other**: For any other issues
16 |
17 | ### Steps to Reproduce
18 | Please provide:
19 | 1. git hash
20 | 2. Command line
21 | 3. Logfile and/or wave-dump info (screen shots can be useful)
22 |
--------------------------------------------------------------------------------
/docs/user_manual/source/register_file.rst:
--------------------------------------------------------------------------------
1 | .. _register-file:
2 |
3 | Register File
4 | =============
5 |
6 | Source file: :file:`rtl/cv32e40s_register_file.sv`
7 |
8 | |corev| has 31 32-bit wide registers which form registers ``x1`` to ``x31``.
9 | Register ``x0`` is statically bound to 0 and can only be read, it does not
10 | contain any sequential logic.
11 |
12 | The register file has two read ports and one write port. Register file reads are performed in the ID stage.
13 | Register file writes are performed in the WB stage.
14 |
15 | General Purpose Register File
16 | -----------------------------
17 |
18 | The general purpose register file is flip-flop-based. It uses regular, positive-edge-triggered flip-flops to implement the registers.
19 |
20 | Error Detection
21 | ---------------
22 |
23 | The register file of |corev| has integrated error detection logic and a 6-bit hamming code for each word.
24 | This ensures detection of up to two errors in each register file word. Detected errors trigger the core major alert output.
25 |
--------------------------------------------------------------------------------
/docs/user_manual/source/instruction_set_extensions.rst:
--------------------------------------------------------------------------------
1 | .. _custom-isa-extensions:
2 |
3 | CORE-V Instruction Set Extensions
4 | =================================
5 |
6 | Custom instructions
7 | -------------------
8 |
9 | |corev| supports the custom instruction(s) listed in :numref:`Custom instructions`.
10 |
11 | .. table:: Custom instructions
12 | :name: Custom instructions
13 | :widths: 10 10 80
14 | :class: no-scrollbar-table
15 |
16 | +-------------------------+-------------+--------------------------------------------------+
17 | | Custom instruction | Encoding | Description |
18 | +=========================+=============+==================================================+
19 | | ``wfe`` | 0x8C00_0073 | Wait For Event, see :ref:`wfe`. |
20 | +-------------------------+-------------+--------------------------------------------------+
21 |
22 | Custom CSRs
23 | -----------
24 |
25 | |corev| supports the custom CSRs listed in :numref:`Control and Status Register Map (additional custom CSRs)`.
26 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 | Contributors are encouraged to be a [member](https://www.openhwgroup.org/membership/) of the
3 | OpenHW Group. New members are always welcome.
4 |
5 | ## Getting Started
6 | The [OpenHW Work Flow](https://github.com/openhwgroup/core-v-docs/blob/master/verif/Common/OpenHWGroup_WorkFlow.pdf) document
7 | is required reading. You will find information about the implementation and usage of the CORE-V verification environments
8 | in the [Verification Strategy](https://github.com/openhwgroup/core-v-docs/blob/master/verif/Common/OpenHWGroup_CORE-V_Verif_Strategy.pdf).
9 |
10 | ## The Mechanics
11 | 1. From GitHub: [fork](https://help.github.com/articles/fork-a-repo/) the [cv32e40s](https://github.com/openhwgroup/cv32e40s) repository
12 | 2. Clone repository: `git clone https://github.com/[your_github_username]/cv32e40s`
13 | 3. Create your feature branch: `git checkout -b .`
Please uniquify your branch name. See the [Git Cheats](https://github.com/openhwgroup/core-v-verif/blob/master/GitCheats.md)
14 | for a useful nominclature.
15 | 4. Make your edits...
16 | 5. Commit your changes: `git commit -m 'Add some feature' -s`
...take note of that **-s**, it's important!
17 | 6. Push feature branch: `git push origin `
18 | 7. From GitHub: submit a pull request
19 |
--------------------------------------------------------------------------------
/docs/user_manual/source/fencei.rst:
--------------------------------------------------------------------------------
1 | .. _fencei:
2 |
3 | Fence.i external handshake
4 | ==========================
5 | |corev| includes an external handshake that will be exercised upon execution of the ``fence.i`` instruction.
6 | The handshake is composed of the signals ``fencei_flush_req_o`` and ``fencei_flush_ack_i`` and can for example be used to flush an externally connected cache.
7 |
8 | The ``fencei_flush_req_o`` signal will go high upon executing a ``fence.i`` instruction ([RISC-V-UNPRIV]_) once possible earlier store instructions have fully completed (including
9 | emptying of the the write buffer).
10 | The ``fencei_flush_req_o`` signal will go low again the cycle after sampling both ``fencei_flush_req_o`` and ``fencei_flush_ack_i`` high.
11 | Once ``fencei_flush_req_o`` has gone low again a branch will be taken to the instruction after the ``fence.i`` thereby flushing possibly prefetched instructions.
12 |
13 | Fence instructions are not impacted by the distinction between main and I/O regions (defined in :ref:`pma`) and execute as a conservative fence on all operations, ignoring the predecessor and successor fields.
14 |
15 | .. note::
16 |
17 | If the ``fence.i`` external handshake is not used by the environment of |corev|, then it is recommended to tie the ``fencei_flush_ack_i``
18 | to 1 in order to avoid stalling ``fence.i`` instructions indefinitely.
19 |
--------------------------------------------------------------------------------
/bhv/cv32e40s_sim_clock_gate.sv:
--------------------------------------------------------------------------------
1 | // Copyright 2017 ETH Zurich and University of Bologna.
2 | // Copyright and related rights are licensed under the Solderpad Hardware
3 | // License, Version 0.51 (the "License"); you may not use this file except in
4 | // compliance with the License. You may obtain a copy of the License at
5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
6 | // or agreed to in writing, software, hardware and materials distributed under
7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
9 | // specific language governing permissions and limitations under the License.
10 |
11 | // !!! cv32e40s_sim_clock_gate file is meant for simulation only !!!
12 | // !!! It must not be used for ASIC synthesis !!!
13 | // !!! It must not be used for FPGA synthesis !!!
14 |
15 | module cv32e40s_clock_gate
16 | #(
17 | parameter LIB = 0
18 | )
19 | (
20 | input logic clk_i,
21 | input logic en_i,
22 | input logic scan_cg_en_i,
23 | output logic clk_o
24 | );
25 |
26 | logic clk_en;
27 |
28 | always_latch
29 | begin
30 | if (clk_i == 1'b0)
31 | clk_en <= en_i | scan_cg_en_i;
32 | end
33 |
34 | assign clk_o = clk_i & clk_en;
35 |
36 | endmodule // cv32e40s_clock_gate
37 |
--------------------------------------------------------------------------------
/docs/user_manual/Makefile:
--------------------------------------------------------------------------------
1 | #
2 | # Copyright (c) 2020 OpenHW Group
3 | #
4 | # Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
5 | # you may not use this file except in compliance with the License.
6 | # You may obtain a copy of the License at
7 | #
8 | # https://solderpad.org/licenses/
9 | #
10 | # Unless required by applicable law or agreed to in writing, software
11 | # distributed under the License is distributed on an "AS IS" BASIS,
12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | # See the License for the specific language governing permissions and
14 | # limitations under the License.
15 | #
16 | # SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
17 | #
18 | ###############################################################################
19 | #
20 | # Minimal makefile for Sphinx documentation
21 | #
22 |
23 | # You can set these variables from the command line.
24 | SPHINXOPTS =
25 | SPHINXBUILD = sphinx-build
26 | SOURCEDIR = source
27 | BUILDDIR = build
28 |
29 | # Put it first so that "make" without argument is like "make help".
30 | help:
31 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
32 |
33 | .PHONY: help Makefile
34 |
35 | # Catch-all target: route all unknown targets to Sphinx using the new
36 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
37 | %: Makefile
38 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
39 |
--------------------------------------------------------------------------------
/rtl/cv32e40s_if_c_obi.sv:
--------------------------------------------------------------------------------
1 | /*
2 | Copyright 2020 Silicon Labs, Inc.
3 |
4 | This file, and derivatives thereof are licensed under the
5 | Solderpad License, Version 2.0 (the "License");
6 | Use of this file means you agree to the terms and conditions
7 | of the license and are in full compliance with the License.
8 | You may obtain a copy of the License at
9 |
10 | https://solderpad.org/licenses/SHL-2.0/
11 |
12 | Unless required by applicable law or agreed to in writing, software
13 | and hardware implementations thereof
14 | distributed under the License is distributed on an "AS IS" BASIS,
15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESSED OR IMPLIED.
16 | See the License for the specific language governing permissions and
17 | limitations under the License.
18 | */
19 |
20 |
21 | // OBI interface definition for instruction and data
22 | // The two parameters set the types for payload
23 | // as these are different for instruction and data
24 | //
25 | // The 'c' in the interface names means 'Compressed'
26 | // since this interface is a subset of the full OBI spec.
27 | interface cv32e40s_if_c_obi import cv32e40s_pkg::*;
28 | #(
29 | parameter type REQ_TYPE = obi_inst_req_t,
30 | parameter type RESP_TYPE = obi_inst_resp_t
31 | );
32 | // A channel signals
33 | obi_req_t s_req;
34 | obi_gnt_t s_gnt;
35 | REQ_TYPE req_payload;
36 | // R channel signals
37 | obi_rvalid_t s_rvalid;
38 | RESP_TYPE resp_payload;
39 |
40 | modport master
41 | (
42 | output s_req, req_payload,
43 | input s_gnt, s_rvalid, resp_payload
44 | );
45 |
46 | modport monitor
47 | (
48 | input s_req, req_payload,
49 | s_gnt, s_rvalid, resp_payload
50 | );
51 |
52 | endinterface : cv32e40s_if_c_obi
53 |
--------------------------------------------------------------------------------
/docs/user_manual/source/glossary.rst:
--------------------------------------------------------------------------------
1 | .. _glossary:
2 |
3 | Glossary
4 | ========
5 |
6 | * **ALU**: Arithmetic/Logic Unit
7 | * **ASIC**: Application-Specific Integrated Circuit
8 | * **Byte**: 8-bit data item
9 | * **CPU**: Central Processing Unit, processor
10 | * **CSR**: Control and Status Register
11 | * **Custom extension**: Non-Standard extension to the RISC-V base instruction set (RISC-V Instruction Set Manual, Volume I: User-Level ISA)
12 | * **EXE**: Instruction Execute
13 | * **FPGA**: Field Programmable Gate Array
14 | * **FPU**: Floating Point Unit
15 | * **Halfword**: 16-bit data item
16 | * **Halfword aligned address**: An address is halfword aligned if it is divisible by 2
17 | * **ID**: Instruction Decode
18 | * **IF**: Instruction Fetch (:ref:`instruction-fetch`)
19 | * **ISA**: Instruction Set Architecture
20 | * **KGE**: kilo gate equivalents (NAND2)
21 | * **LSU**: Load Store Unit (:ref:`load-store-unit`)
22 | * **M-Mode**: Machine Mode (RISC-V Instruction Set Manual, Volume II: Privileged Architecture)
23 | * **NMI**: Non-Maskable Interrupt
24 | * **OBI**: Open Bus Interface
25 | * **PC**: Program Counter
26 | * **PMA**: Physical Memory Attribution
27 | * **PMP**: Physical Memory Protection
28 | * **ePMP**: Enhanced Physical Memory Protection
29 | * **PULP platform**: Parallel Ultra Low Power Platform ()
30 | * **RV32C**: RISC-V Compressed (C extension)
31 | * **RV32F**: RISC-V Floating Point (F extension)
32 | * **SIMD**: Single Instruction/Multiple Data
33 | * **Standard extension**: Standard extension to the RISC-V base instruction set (RISC-V Instruction Set Manual, Volume I: User-Level ISA)
34 | * **WARL**: Write Any Values, Reads Legal Values
35 | * **WB**: Write Back of instruction results
36 | * **WLRL**: Write/Read Only Legal Values
37 | * **Word**: 32-bit data item
38 | * **Word aligned address**: An address is word aligned if it is divisible by 4
39 | * **WPRI**: Reserved Writes Preserve Values, Reads Ignore Values
40 |
--------------------------------------------------------------------------------
/docs/user_manual/source/pmp.rst:
--------------------------------------------------------------------------------
1 | .. _pmp:
2 |
3 | Physical Memory Protection (PMP)
4 | ================================
5 |
6 | The |corev| includes the Physical Memory Protection (PMP) unit.
7 | The PMP is both statically and dynamically configurable. The static configuration is performed through the top level
8 | parameters ``PMP_NUM_REGIONS`` and ``PMP_GRANULARITY``. The dynamic configuration is performed through the CSRs described in :ref:`cs-registers`.
9 |
10 | The ``PMP_GRANULARITY`` parameter is used to configure the minimum granularity of PMP address matching. The minimum granularity is 2 :sup:`PMP_GRANULARITY+2` bytes, so at least 4 bytes.
11 |
12 | The ``PMP_NUM_REGIONS`` parameter is used to configure the number of PMP regions, starting from the lowest numbered region. All PMP CSRs are always implemented, but CSRs (or bitfields of CSRs) related to PMP entries with number ``PMP_NUM_REGIONS`` and above are hardwired to zero.
13 |
14 | The reset value of the PMP CSR registers can be set through the top level parameters ``PMP_PMPNCFG_RV[]``, ``PMP_PMPADDR_RV[]`` and ``PMP_MSECCFG_RV``.
15 | ``PMP_PMPNCFG_RV[]`` is an array of ``PMP_NUM_REGIONS`` entries of the type ``pmpncfg_t``. Entry N determines the reset value of the ``pmpNcfg`` bitfield in the ``pmpcfg`` CSRs.
16 | ``PMP_PMPADDR_RV[]`` is an array of ``PMP_NUM_REGIONS`` entries of ``logic [31:0]``. Entry N determines the reset value of the ``pmpaddrN`` CSR.
17 | ``PMP_MSECCFG_RV`` is of the type ``mseccfg_t`` and determines the reset value of the ``mseccfg`` CSR.
18 |
19 | The PMP is compliant to [RISC-V-PRIV]_ and [RISC-V-SMEPMP]_.
20 |
21 | Debug mode
22 | ~~~~~~~~~~
23 | Accesses to the Debug Module region, as defined by the ``DM_REGION_START`` and ``DM_REGION_END`` parameters, while in debug mode are treated specially.
24 |
25 | In order for debug to always be possible, the PMP will not disallow fetches, loads, or stores in
26 | the Debug Module region when the hart is in debug mode, regardless of how the PMP is configured.
27 |
--------------------------------------------------------------------------------
/rtl/cv32e40s_alu_b_cpop.sv:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Silicon Labs, Inc.
2 | //
3 | // This file, and derivatives thereof are licensed under the
4 | // Solderpad License, Version 2.0 (the "License");
5 | // Use of this file means you agree to the terms and conditions
6 | // of the license and are in full compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // https://solderpad.org/licenses/SHL-2.0/
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // and hardware implementations thereof
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESSED OR IMPLIED.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 | ////////////////////////////////////////////////////////////////////////////////
19 | // Engineers Halfdan Bechmann - halfdan.bechmann@silabs.com //
20 | // //
21 | // Design Name: cv32e40s_alu_b_cpop //
22 | // Project Name: CV32E40S //
23 | // Language: SystemVerilog //
24 | // //
25 | // Description: CPOP for Zbb extension //
26 | // //
27 | ////////////////////////////////////////////////////////////////////////////////
28 |
29 |
30 | module cv32e40s_alu_b_cpop
31 | (input logic [31:0] operand_i,
32 | output logic [ 5:0] result_o);
33 |
34 | logic [31:0][5:0] sum;
35 |
36 | assign result_o = sum[31];
37 |
38 | generate
39 | assign sum[0] = {5'h0, operand_i[0]};
40 | for (genvar i=1; i < 32; i++) begin
41 | assign sum[i] = sum[i-1] + {5'h0, operand_i[i]};
42 | end
43 | endgenerate
44 |
45 | endmodule
46 |
--------------------------------------------------------------------------------
/docs/user_manual/source/perf_counters.rst:
--------------------------------------------------------------------------------
1 | .. _performance-counters:
2 |
3 | Performance Counters
4 | ====================
5 |
6 | |corev| implements performance counters according to [RISC-V-PRIV]_.
7 | The performance counters are placed inside the Control and Status Registers (CSRs) and can be accessed with the ``CSRRW(I)`` and ``CSRRS/C(I)`` instructions.
8 |
9 | |corev| implements the clock cycle counter ``mcycle(h)`` and the retired instruction counter ``minstret(h)``. The ``mcycle(h)`` and ``minstret(h)`` counters are always available and 64 bit wide.
10 | The event counters ``mhpmcounter3(h)`` - ``mhpmcounter31(h)`` and the corresponding event selector CSRs ``mhpmevent3`` - ``mhpmevent31`` are hard-wired to 0.
11 | The ``mcountinhibit`` CSR is used to individually enable/disable the counters.
12 |
13 | .. note::
14 |
15 | All performance counters are using the gated version of ``clk_i``. The **wfi** instruction impact the gating of ``clk_i`` as explained
16 | in :ref:`sleep_unit` and can therefore affect the counters.
17 |
18 | Controlling the counters from software
19 | --------------------------------------
20 |
21 | By default, all available counters are disabled after reset in order to provide the lowest power consumption.
22 |
23 | They can be individually enabled/disabled by overwriting the corresponding bit in the ``mcountinhibit`` CSR at address ``0x320`` as described in [RISC-V-PRIV]_.
24 | In particular, to enable/disable ``mcycle(h)``, bit 0 must be written. For ``minstret(h)``, it is bit 2.
25 |
26 | The lower 32 bits of all counters can be accessed through the base register, whereas the upper 32 bits are accessed through the ``h``-register.
27 | Reads of all these registers are non-destructive.
28 |
29 | Time Registers (``time(h)``)
30 | ----------------------------
31 |
32 | The user mode ``time(h)`` registers are not implemented. Any access to these
33 | registers will cause an illegal instruction trap. It is recommended that a software trap handler is
34 | implemented to detect access of these CSRs and convert that into access of the
35 | platform-defined ``mtime`` register (if implemented in the platform).
36 |
--------------------------------------------------------------------------------
/bhv/cv32e40s_rvfi_data_obi.sv:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2022 OpenHW Group
2 | //
3 | // Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://solderpad.org/licenses/
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | //
15 | // SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
16 |
17 | // CV32E40S RVFI data OBI interface (aligns data OBI signals to WB timing)
18 | // Note that due to complications added by the write buffer (specifically the fact that
19 | // instructions can retire before a transaction leaves the write buffer), this module
20 | // monitors transactions going in to the write buffer.
21 | // Future improvements of this module may include monitoring the OBI signals directly,
22 | // and have special handling of buffered writes.
23 | //
24 | // Contributors: Arjan Bink
25 |
26 | module cv32e40s_rvfi_data_obi import cv32e40s_pkg::*; import cv32e40s_rvfi_pkg::*;
27 | (
28 | input logic clk,
29 | input logic rst_n,
30 | input obi_data_req_t buffer_trans_i,
31 | input logic buffer_trans_valid_i,
32 | output obi_data_req_t lsu_data_trans_o,
33 | output logic lsu_data_trans_valid_o
34 | );
35 |
36 | // Intermediate rotate signal, as direct part-select not supported in all tools
37 | logic [63:0] buffer_trans_wdata_ror;
38 |
39 | // Rotate right
40 | assign buffer_trans_wdata_ror = {buffer_trans_i.wdata, buffer_trans_i.wdata} >> (8*buffer_trans_i.addr[1:0]);
41 |
42 | // Feed valid through
43 | assign lsu_data_trans_valid_o = buffer_trans_valid_i;
44 |
45 | always_comb begin
46 | lsu_data_trans_o = buffer_trans_i;
47 |
48 | // Align Memory write data
49 | lsu_data_trans_o.wdata = buffer_trans_wdata_ror[31:0];
50 | end
51 |
52 | endmodule
53 |
--------------------------------------------------------------------------------
/sva/cv32e40s_wpt_sva.sv:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Silicon Labs, Inc.
2 | //
3 | // This file, and derivatives thereof are licensed under the
4 | // Solderpad License, Version 2.0 (the "License");
5 | // Use of this file means you agree to the terms and conditions
6 | // of the license and are in full compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // https://solderpad.org/licenses/SHL-2.0/
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // and hardware implementations thereof
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESSED OR IMPLIED.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 | ////////////////////////////////////////////////////////////////////////////////
19 | // //
20 | // Authors: Oystein Knauserud - oystein.knauserud@silabs.com //
21 | // //
22 | // Description: WPT assertions //
23 | // //
24 | ////////////////////////////////////////////////////////////////////////////////
25 |
26 | module cv32e40s_wpt_sva import cv32e40s_pkg::*; import uvm_pkg::*;
27 | (
28 | input logic clk,
29 | input logic rst_n,
30 |
31 | input wpt_state_e state_q,
32 | input mpu_state_e mpu_state
33 |
34 | );
35 |
36 | // WPT and MPU cannot both wait for a response at the sime time
37 | // If they could both wait for a response, then they would need separate counters for the
38 | // "one-transaction-left" inputs - otherwise they may share the counter.
39 | a_wpt_mpu_cnt_share:
40 | assert property (@(posedge clk) disable iff (!rst_n)
41 | ((state_q == WPT_MATCH_WAIT) || (mpu_state == MPU_RE_ERR_WAIT) || (mpu_state == MPU_WR_ERR_WAIT))
42 | |->
43 | (state_q == WPT_MATCH_WAIT) != ((mpu_state == MPU_RE_ERR_WAIT) || (mpu_state == MPU_WR_ERR_WAIT)))
44 | else `uvm_error("load_store_unit", "WPT and MPU both wait for responses")
45 | endmodule
46 |
47 |
--------------------------------------------------------------------------------
/bhv/cv32e40s_sim_sffr.sv:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Silicon Labs, Inc.
2 | //
3 | // This file, and derivatives thereof are licensed under the
4 | // Solderpad License, Version 2.0 (the "License");
5 | // Use of this file means you agree to the terms and conditions
6 | // of the license and are in full compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // https://solderpad.org/licenses/SHL-2.0/
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // and hardware implementations thereof
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESSED OR IMPLIED.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 | ////////////////////////////////////////////////////////////////////////////////
19 | // Engineer: Halfdan Bechmann - halfdan.bechmann@silabs.com //
20 | // //
21 | // Design Name: cv32e40s_sffr //
22 | // Project Name: CV32E40S //
23 | // Language: SystemVerilog //
24 | // //
25 | // Description: Emulates an instantiated sffr //
26 | // This file is meant for rtl simulation only! //
27 | // It should not be used for ASIC synthesis. //
28 | // It should not be used for FPGA synthesis. //
29 | // //
30 | ////////////////////////////////////////////////////////////////////////////////
31 |
32 | module cv32e40s_sffr
33 | #(
34 | parameter LIB = 0
35 | )
36 | (
37 | input logic clk,
38 | input logic rst_n,
39 | input logic d_i,
40 | output logic q_o
41 | );
42 |
43 | always_ff @(posedge clk, negedge rst_n) begin
44 | if (rst_n == 1'b0) begin
45 | q_o <= 1'b0;
46 | end else begin
47 | q_o <= d_i;
48 | end
49 | end
50 |
51 | endmodule : cv32e40s_sffr
52 |
53 |
--------------------------------------------------------------------------------
/bhv/cv32e40s_sim_sffs.sv:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Silicon Labs, Inc.
2 | //
3 | // This file, and derivatives thereof are licensed under the
4 | // Solderpad License, Version 2.0 (the "License");
5 | // Use of this file means you agree to the terms and conditions
6 | // of the license and are in full compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // https://solderpad.org/licenses/SHL-2.0/
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // and hardware implementations thereof
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESSED OR IMPLIED.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 | ////////////////////////////////////////////////////////////////////////////////
19 | // Engineer: Halfdan Bechmann - halfdan.bechmann@silabs.com //
20 | // //
21 | // Design Name: cv32e40s_sffs //
22 | // Project Name: CV32E40S //
23 | // Language: SystemVerilog //
24 | // //
25 | // Description: Emulates an instantiated sffs //
26 | // This file is meant for rtl simulation only! //
27 | // It should not be used for ASIC synthesis. //
28 | // It should not be used for FPGA synthesis. //
29 | // //
30 | ////////////////////////////////////////////////////////////////////////////////
31 |
32 | module cv32e40s_sffs
33 | #(
34 | parameter LIB = 0
35 | )
36 | (
37 | input logic clk,
38 | input logic rst_n,
39 | input logic d_i,
40 | output logic q_o
41 | );
42 |
43 | always_ff @(posedge clk, negedge rst_n) begin
44 | if (rst_n == 1'b0) begin
45 | q_o <= 1'b1;
46 | end else begin
47 | q_o <= d_i;
48 | end
49 | end
50 |
51 | endmodule : cv32e40s_sffs
52 |
53 |
--------------------------------------------------------------------------------
/docs/user_manual/source/core_versions.rst:
--------------------------------------------------------------------------------
1 | Core Versions and RTL Freeze Rules
2 | ==================================
3 |
4 | The |corev| is defined by the ``marchid`` and ``mimpid`` tuple.
5 | The tuple identify which sets of parameters have been verified
6 | by OpenHW Group, and once RTL Freeze is achieved, no further
7 | non-logically equivalent changes are allowed on that set of parameters.
8 |
9 | The RTL Freeze version of the core is indentified by a GitHub
10 | tag with the format |corev_lc|\ _vMAJOR.MINOR.PATCH (e.g. |corev_lc|\ _v1.0.0).
11 | In addition, the release date is reported in the documentation.
12 |
13 | What happens after RTL Freeze?
14 | ------------------------------
15 |
16 | A bug is found
17 | ^^^^^^^^^^^^^^
18 |
19 | If a bug is found that affect the already frozen parameter set,
20 | the RTL changes required to fix such bug are non-logically equivalent by definition.
21 | Therefore, the RTL changes are applied only on a different ``mimpid``
22 | value and the bug and the fix must be documented.
23 | These changes are visible by software as the ``mimpid`` has a different value.
24 | Every bug or set of bugs found must be followed by another RTL Freeze release and a new GitHub tag.
25 |
26 | RTL changes on non-verified yet parameters
27 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
28 |
29 | If changes affecting the core on a non-frozen parameter set are required, then
30 | such changes must remain logically equivalent for the already frozen set of parameters (except for the required mimpid update), and they must be applied on a different ``mimpid`` value. They can be non-logically equivalent to a non-frozen set of parameters.
31 | These changes are visible by software as the ``mimpid`` has a different value.
32 | Once the new set of parameters is verified and achieved the sign-off for RTL freeze,
33 | a new GitHub tag and version of the core is released.
34 |
35 | PPA optimizations and new features
36 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
37 |
38 | Non-logically equivalent PPA optimizations and new features are not allowed on a given set
39 | of RTL frozen parameters (e.g., a faster divider).
40 | If PPA optimizations are logically-equivalent instead, they can be applied without
41 | changing the ``mimpid`` value (as such changes are not visible in software).
42 | However, a new GitHub tag should be released and changes documented.
43 |
44 | Released core versions
45 | ----------------------
46 |
47 | The verified parameter sets of the core, their implementation version, GitHub tags,
48 | and dates are reported here.
49 |
50 |
--------------------------------------------------------------------------------
/rtl/cv32e40s_rchk_check.sv:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Silicon Labs, Inc.
2 | //
3 | // This file, and derivatives thereof are licensed under the
4 | // Solderpad License, Version 2.0 (the "License").
5 | //
6 | // Use of this file means you agree to the terms and conditions
7 | // of the license and are in full compliance with the License.
8 | //
9 | // You may obtain a copy of the License at:
10 | //
11 | // https://solderpad.org/licenses/SHL-2.0/
12 | //
13 | // Unless required by applicable law or agreed to in writing, software
14 | // and hardware implementations thereof distributed under the License
15 | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
16 | // OF ANY KIND, EITHER EXPRESSED OR IMPLIED.
17 | //
18 | // See the License for the specific language governing permissions and
19 | // limitations under the License.
20 |
21 | ////////////////////////////////////////////////////////////////////////////////
22 | // Engineer: Øystein Knauserud - oystein.knauserud@silabs.com //
23 | // //
24 | // Design Name: cv32e40s_rchk_check //
25 | // Project Name: CV32E40S //
26 | // Language: SystemVerilog //
27 | // //
28 | // Description: This module will check the recomputed rchk values //
29 | // and signal an error if enabled and checksums do not match //
30 | // The enable signal is split in two, one for checking rdata //
31 | // for reads, and one to check the error bit (read and writes)//
32 | ////////////////////////////////////////////////////////////////////////////////
33 |
34 |
35 | module cv32e40s_rchk_check import cv32e40s_pkg::*;
36 | #(
37 | parameter type RESP_TYPE = obi_inst_resp_t
38 | )
39 | (
40 | input RESP_TYPE resp_i,
41 | input logic [1:0] enable_i,
42 | output logic err_o
43 | );
44 |
45 | logic [4:0] rchk_res;
46 |
47 | logic rdata_err;
48 | logic err_err;
49 |
50 | // Compute rchk from response inputs
51 | always_comb begin
52 | rchk_res = {
53 | ^{resp_i.err, 1'b0},
54 | ^{resp_i.rdata[31:24]},
55 | ^{resp_i.rdata[23:16]},
56 | ^{resp_i.rdata[15:8]},
57 | ^{resp_i.rdata[7:0]}
58 | };
59 | end
60 |
61 | assign rdata_err = (enable_i[0] && resp_i.integrity) ? (rchk_res[3:0] != resp_i.rchk[3:0]) : 1'b0;
62 | assign err_err = (enable_i[1] && resp_i.integrity) ? (rchk_res[4] != resp_i.rchk[4]) : 1'b0;
63 | assign err_o = rdata_err || err_err;
64 |
65 | endmodule
66 |
--------------------------------------------------------------------------------
/docs/user_manual/source/getting_started.rst:
--------------------------------------------------------------------------------
1 | .. _getting-started:
2 |
3 | Getting Started with |corev|
4 | =============================
5 |
6 | This page discusses initial steps and requirements to start using |corev| in your design.
7 |
8 | .. _clock-gating-cell:
9 |
10 | Clock Gating Cell
11 | -----------------
12 |
13 | |corev| requires clock gating cells.
14 | These cells are usually specific to the selected target technology and thus not provided as part of the RTL design.
15 | A simulation-only version of the clock gating cell is provided in ``cv32e40s_sim_clock_gate.sv``. This file contains
16 | a module called ``cv32e40s_clock_gate`` that has the following ports:
17 |
18 | * ``clk_i``: Clock Input
19 | * ``en_i``: Clock Enable Input
20 | * ``scan_cg_en_i``: Scan Clock Gate Enable Input (activates the clock even though ``en_i`` is not set)
21 | * ``clk_o``: Gated Clock Output
22 |
23 | And the following Parameters:
24 | * ``LIB`` : Standard cell library (semantics defined by integrator)
25 |
26 | Inside |corev|, the clock gating cell is used in ``cv32e40s_sleep_unit.sv``.
27 |
28 | The ``cv32e40s_sim_clock_gate.sv`` file is not intended for synthesis. For ASIC synthesis and FPGA synthesis the manifest
29 | should be adapted to use a customer specific file that implements the ``cv32e40s_clock_gate`` module using design primitives
30 | that are appropriate for the intended synthesis target technology.
31 |
32 |
33 | .. _register-cells:
34 |
35 | Register Cells
36 | --------------
37 | |corev| requires instantiated registers for some logically redundant security features (such as :ref:`hardened-csrs`).
38 |
39 | Like clock gating cells these are specific to the target technology and are therefore not provided as part of the RTL design.
40 | Simulation-only versions for these cells are provided in cv32e40s_sim_sffr.sv and cv32e40s_sim_sffs.sv.
41 | cv32e40s_sim_sffr.sv contains the module ``cv32e40s_sffr`` with the following ports:
42 |
43 | * ``clk`` : Clock
44 | * ``rst_n`` : Reset
45 | * ``d_i`` : Data input
46 | * ``q_o`` : Flopped data output
47 |
48 | And the following parameters:
49 | * ``LIB`` : Standard cell library (semantics defined by integrator)
50 |
51 | cv32e40s_sim_sffs.sv contains the module ``cv32e40s_sffs`` with the following ports:
52 |
53 | * ``clk`` : Clock
54 | * ``set_n`` : Set (i.e., reset value == 1)
55 | * ``d_i`` : Data input
56 | * ``q_o`` : Flopped data output
57 |
58 | And the following parameters:
59 | * ``LIB`` : Standard cell library (semantics defined by integrator)
60 |
61 | These files are not intended for synthesis.
62 | For ASIC synthesis and FPGA synthesis the manifest should be adapted
63 | to use customer specific files that implement the ``cv32e40s_sffr`` and ``cv32e40s_sffs`` modules
64 | using design primitives that are appropriate for the intended synthesis target technology.
65 |
--------------------------------------------------------------------------------
/rtl/cv32e40s_popcnt.sv:
--------------------------------------------------------------------------------
1 | // Copyright 2018 ETH Zurich and University of Bologna.
2 | // Copyright and related rights are licensed under the Solderpad Hardware
3 | // License, Version 0.51 (the "License"); you may not use this file except in
4 | // compliance with the License. You may obtain a copy of the License at
5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
6 | // or agreed to in writing, software, hardware and materials distributed under
7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
9 | // specific language governing permissions and limitations under the License.
10 |
11 | ////////////////////////////////////////////////////////////////////////////////
12 | // Engineer: Andreas Traber - atraber@student.ethz.ch //
13 | // //
14 | // Additional contributions by: //
15 | // Davide Schiavone - pschiavo@iis.ee.ethz.ch //
16 | // //
17 | // Design Name: cv32e40s_popcnt //
18 | // Project Name: RI5CY //
19 | // Language: SystemVerilog //
20 | // //
21 | // Description: Count the number of '1's in a word //
22 | // //
23 | ////////////////////////////////////////////////////////////////////////////////
24 |
25 | module cv32e40s_popcnt
26 | (
27 | input logic [31:0] in_i,
28 | output logic [5: 0] result_o
29 | );
30 |
31 | logic [15:0][1:0] cnt_l1;
32 | logic [ 7:0][2:0] cnt_l2;
33 | logic [ 3:0][3:0] cnt_l3;
34 | logic [ 1:0][4:0] cnt_l4;
35 |
36 | genvar l, m, n, p;
37 | generate for(l = 0; l < 16; l++)
38 | begin : gen_cnt_l1
39 | assign cnt_l1[l] = {1'b0, in_i[2*l]} + {1'b0, in_i[2*l + 1]};
40 | end
41 | endgenerate
42 |
43 | generate for(m = 0; m < 8; m++)
44 | begin : gen_cnt_l2
45 | assign cnt_l2[m] = {1'b0, cnt_l1[2*m]} + {1'b0, cnt_l1[2*m + 1]};
46 | end
47 | endgenerate
48 |
49 | generate for(n = 0; n < 4; n++)
50 | begin : gen_cnt_l3
51 | assign cnt_l3[n] = {1'b0, cnt_l2[2*n]} + {1'b0, cnt_l2[2*n + 1]};
52 | end
53 | endgenerate
54 |
55 | generate for(p = 0; p < 2; p++)
56 | begin : gen_cnt_l4
57 | assign cnt_l4[p] = {1'b0, cnt_l3[2*p]} + {1'b0, cnt_l3[2*p + 1]};
58 | end
59 | endgenerate
60 |
61 | assign result_o = {1'b0, cnt_l4[0]} + {1'b0, cnt_l4[1]};
62 |
63 | endmodule
64 |
--------------------------------------------------------------------------------
/rtl/cv32e40s_pc_target.sv:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Silicon Labs, Inc.
2 | //
3 | // This file, and derivatives thereof are licensed under the
4 | // Solderpad License, Version 2.0 (the "License");
5 | // Use of this file means you agree to the terms and conditions
6 | // of the license and are in full compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // https://solderpad.org/licenses/SHL-2.0/
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // and hardware implementations thereof
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESSED OR IMPLIED.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 | ////////////////////////////////////////////////////////////////////////////////
19 | // //
20 | // Authors: Øystein Knauserud - oystein.knauserud@silabs.com //
21 | // //
22 | // Description: Computes pc target for jumps and branches //
23 | // //
24 | ////////////////////////////////////////////////////////////////////////////////
25 |
26 | module cv32e40s_pc_target import cv32e40s_pkg::*;
27 | (
28 | input bch_jmp_mux_e bch_jmp_mux_sel_i,
29 | input logic [31:0] pc_id_i,
30 | input logic [31:0] imm_uj_type_i,
31 | input logic [31:0] imm_sb_type_i,
32 | input logic [31:0] imm_i_type_i,
33 | input logic [31:0] jalr_fw_i,
34 | input logic [JVT_ADDR_WIDTH-1:0] jvt_addr_i,
35 | input logic [7:0] jvt_index_i,
36 | input logic compressed_i,
37 | input logic dummy_i,
38 | output logic [31:0] bch_target_o,
39 | output logic [31:0] jmp_target_o,
40 | output logic [31:0] pc_next_o
41 | );
42 |
43 | logic [31:0] pc_target;
44 |
45 | assign bch_target_o = pc_target;
46 | assign jmp_target_o = pc_target; // Used for both regular jumps and tablejumps
47 | assign pc_next_o = pc_id_i + (dummy_i ? 32'd0 : compressed_i ? 32'd2 : 32'd4);
48 |
49 | always_comb begin : pc_target_mux
50 | unique case (bch_jmp_mux_sel_i)
51 | CT_TBLJMP: pc_target = {jvt_addr_i, {(32-JVT_ADDR_WIDTH){1'b0}}} + {22'd0, jvt_index_i, 2'b00};
52 | CT_JAL: pc_target = pc_id_i + imm_uj_type_i;
53 | CT_BCH: pc_target = pc_id_i + imm_sb_type_i;
54 | CT_JALR: pc_target = jalr_fw_i + imm_i_type_i; // Forward from WB, but only of ALU result
55 | default: pc_target = jalr_fw_i + imm_i_type_i;
56 | endcase
57 | end
58 | endmodule
59 |
--------------------------------------------------------------------------------
/sva/cv32e40s_div_sva.sv:
--------------------------------------------------------------------------------
1 | // Copyright 2018 ETH Zurich and University of Bologna.
2 | // Copyright and related rights are licensed under the Solderpad Hardware
3 | // License, Version 0.51 (the "License"); you may not use this file except in
4 | // compliance with the License. You may obtain a copy of the License at
5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
6 | // or agreed to in writing, software, hardware and materials distributed under
7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
9 | // specific language governing permissions and limitations under the License.
10 |
11 | ////////////////////////////////////////////////////////////////////////////////
12 | // //
13 | // Authors : Michael Schaffner (schaffner@iis.ee.ethz.ch) //
14 | // Andreas Traber (atraber@iis.ee.ethz.ch) //
15 | // Halfdan Bechmann - halfdan.bechmann@silabs.com //
16 | // Oivind Ekelund - oivind.ekelund@silabs.com //
17 | // //
18 | // Description: RTL assertions for the div module //
19 | // //
20 | ////////////////////////////////////////////////////////////////////////////////
21 |
22 | module cv32e40s_div_sva
23 | import uvm_pkg::*;
24 | (
25 | input logic clk,
26 | input logic rst_n,
27 |
28 | input logic valid_i,
29 | input logic ready_o,
30 |
31 | input logic ready_i,
32 | input logic valid_o,
33 |
34 | input logic data_ind_timing_i
35 | );
36 |
37 | logic [5:0] cycle_count;
38 |
39 | // Division cycle counter
40 | always_ff @(posedge clk) begin
41 | if (valid_i && $past(ready_o)) begin
42 | // Division accpted, reset counter
43 | cycle_count <= '0;
44 | end
45 | else begin
46 | cycle_count <= cycle_count + 1'b1;
47 | end
48 | end
49 |
50 | // Assert that valid_o is set in the 34th cycle
51 | // cycle_count==33 in the 34th cycle because the counter is reset in the cycle after division is accepted.
52 | a_data_ind_timing :
53 | assert property (@(posedge clk) disable iff (!rst_n)
54 | ($rose(valid_o) && data_ind_timing_i |-> cycle_count == 33))
55 | else `uvm_error("div", "Data independent cycle count failed")
56 |
57 | a_ready_o :
58 | assert property (@(posedge clk) disable iff (!rst_n)
59 | (valid_o && ready_i |-> ready_o))
60 | else `uvm_error("div", "ready_o not set in the same cycle as output is accepted")
61 |
62 | a_valid_o :
63 | assert property (@(posedge clk) disable iff (!rst_n)
64 | (valid_o |-> valid_i))
65 | else `uvm_error("div", "valid_o=1 when valid_i=0")
66 |
67 | endmodule // cv32e40s_div_sva
68 |
69 |
--------------------------------------------------------------------------------
/bhv/cv32e40s_dbg_helper.sv:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Silicon Labs, Inc.
2 | //
3 | // This file, and derivatives thereof are licensed under the
4 | // Solderpad License, Version 2.0 (the "License");
5 | // Use of this file means you agree to the terms and conditions
6 | // of the license and are in full compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // https://solderpad.org/licenses/SHL-2.0/
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // and hardware implementations thereof
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESSED OR IMPLIED.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 | ///////////////////////////////////////////////////////////////////////////////////////
19 | // //
20 | // Authors: Oivind Ekelund - oivind.ekelund@silabs.com //
21 | // //
22 | // Description: This module contains helper signals intended to aid in debugging //
23 | // //
24 | ///////////////////////////////////////////////////////////////////////////////////////
25 |
26 | module cv32e40s_dbg_helper
27 | import cv32e40s_pkg::*;
28 | #(
29 | parameter int unsigned REGFILE_NUM_READ_PORTS = 2
30 | )
31 | ( input logic [31:0] instr,
32 | input logic is_compressed,
33 | input logic [REGFILE_NUM_READ_PORTS-1:0] rf_re,
34 | input rf_addr_t rf_raddr[REGFILE_NUM_READ_PORTS],
35 | input logic rf_we,
36 | input rf_addr_t rf_waddr,
37 | input logic illegal_insn);
38 |
39 |
40 | typedef struct {
41 | logic [31:0] instr;
42 | logic is_compressed;
43 | opcode_e opcode;
44 | logic [REGFILE_NUM_READ_PORTS-1:0] rf_re;
45 | rf_addr_t [REGFILE_NUM_READ_PORTS-1:0] rf_raddr;
46 | logic rf_we;
47 | rf_addr_t rf_waddr;
48 | logic illegal_insn;
49 | } dbg_help_t;
50 |
51 | dbg_help_t dbg_help;
52 |
53 | assign dbg_help.instr = instr;
54 | assign dbg_help.is_compressed = is_compressed;
55 | assign dbg_help.opcode = opcode_e'(instr[6:0]);
56 | assign dbg_help.rf_re = rf_re;
57 | assign dbg_help.rf_we = rf_we;
58 | assign dbg_help.rf_waddr = rf_waddr;
59 | assign dbg_help.illegal_insn = illegal_insn;
60 |
61 | // Convert from unpacked to packed array (for verilator support)
62 | genvar i;
63 | generate for (i=0; i !(ctrl_flow_taken_err && compare_enable_q))
47 | else `uvm_error("pc_check", "Control flow error for taken jump/branch")
48 |
49 | a_no_flow_untaken_err:
50 | assert property (@(posedge clk) disable iff (!rst_n)
51 | 1'b1 |-> !(ctrl_flow_untaken_err && compare_enable_q))
52 | else `uvm_error("pc_check", "Control flow error for untaken jump/branch")
53 |
54 |
55 | a_no_jump_taken_err:
56 | assert property (@(posedge clk) disable iff (!rst_n)
57 | 1'b1 |-> !(jump_mret_taken_err && compare_enable_q))
58 | else `uvm_error("pc_check", "Control flow error for taken jump/branch")
59 |
60 | a_no_jump_untaken_err:
61 | assert property (@(posedge clk) disable iff (!rst_n)
62 | 1'b1 |-> !(jump_mret_untaken_err && compare_enable_q))
63 | else `uvm_error("pc_check", "Control flow error for untaken jump/branch")
64 |
65 | a_no_branch_taken_err:
66 | assert property (@(posedge clk) disable iff (!rst_n)
67 | 1'b1 |-> !(branch_taken_err && compare_enable_q))
68 | else `uvm_error("pc_check", "Control flow error for taken jump/branch")
69 |
70 | a_no_branch_untaken_err:
71 | assert property (@(posedge clk) disable iff (!rst_n)
72 | 1'b1 |-> !(branch_untaken_err && compare_enable_q))
73 | else `uvm_error("pc_check", "Control flow error for untaken jump/branch")
74 |
75 | a_no_addr_err:
76 | assert property (@(posedge clk) disable iff (!rst_n)
77 | 1'b1 |-> !(addr_err && compare_enable_q))
78 | else `uvm_error("pc_check", "PC mismatch")
79 | endmodule // cv32e40s_pc_check_sva
80 |
--------------------------------------------------------------------------------
/sva/cv32e40s_prefetch_unit_sva.sv:
--------------------------------------------------------------------------------
1 | // Copyright 2018 ETH Zurich and University of Bologna.
2 | // Copyright and related rights are licensed under the Solderpad Hardware
3 | // License, Version 0.51 (the "License"); you may not use this file except in
4 | // compliance with the License. You may obtain a copy of the License at
5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
6 | // or agreed to in writing, software, hardware and materials distributed under
7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
9 | // specific language governing permissions and limitations under the License.
10 |
11 | ////////////////////////////////////////////////////////////////////////////////
12 | // //
13 | // Authors: Andreas Traber - atraber@iis.ee.ethz.ch //
14 | // Halfdan Bechmann - halfdan.bechmann@silabs.com //
15 | // //
16 | // Description: RTL assertions for the prefetch_buffer module //
17 | // //
18 | ////////////////////////////////////////////////////////////////////////////////
19 |
20 |
21 | module cv32e40s_prefetch_unit_sva import cv32e40s_pkg::*;
22 | import uvm_pkg::*;
23 | #(
24 | parameter bit CLIC = 1'b0
25 | )
26 | (
27 | input logic clk,
28 | input logic rst_n,
29 | input ctrl_fsm_t ctrl_fsm_i,
30 | input logic fetch_valid,
31 | input logic [31:0] branch_addr_i,
32 | input logic prefetch_ready_i,
33 | input logic trans_valid_o,
34 | input logic trans_ready_i,
35 | input logic fetch_ptr_resp,
36 | input ctrl_state_e ctrl_fsm_cs,
37 | input logic debug_req_i
38 |
39 | );
40 |
41 |
42 | // Check that branch target address is half-word aligned (RV32-C)
43 | property p_branch_halfword_aligned;
44 | @(posedge clk) (ctrl_fsm_i.pc_set) |-> (branch_addr_i[0] == 1'b0);
45 | endproperty
46 |
47 | a_branch_halfword_aligned : assert property(p_branch_halfword_aligned)
48 | else `uvm_error("prefetch_buffer", "Assertion a_branch_halfword_aligned failed")
49 |
50 | // Check that a taken branch can only occur if fetching is requested
51 | // Exception while in RESET state and debug_request_i is high - in that case we want to
52 | // do a pc_set to update the IF stage PC without actually fetching anything. This is to ensure
53 | // that dpc gets the correct (boot) address when going from reset to debug.
54 | property p_branch_implies_req;
55 | @(posedge clk) (ctrl_fsm_i.pc_set) && !((ctrl_fsm_cs == RESET) && debug_req_i) |-> (ctrl_fsm_i.instr_req);
56 | endproperty
57 |
58 | a_branch_implies_req : assert property(p_branch_implies_req)
59 | else `uvm_error("prefetch_buffer", "Assertion a_branch_implies_req failed")
60 |
61 | // Shall not fetch anything between pointer fetch and the actual instruction fetch
62 | // based on the pointer.
63 | property p_single_ptr_fetch;
64 | @(posedge clk) disable iff (!rst_n)
65 | (trans_valid_o && trans_ready_i && fetch_ptr_resp) |=> !trans_valid_o until ctrl_fsm_i.pc_set;
66 | endproperty
67 |
68 | a_single_ptr_fetch:
69 | assert property(p_single_ptr_fetch)
70 | else
71 | `uvm_error("Alignment buffer SVA", "Multiple fetches for CLIC/Zc pointer")
72 |
73 |
74 | endmodule // cv32e40s_prefetch_unit
75 |
76 |
--------------------------------------------------------------------------------
/rtl/cv32e40s_csr.sv:
--------------------------------------------------------------------------------
1 | // Copyright lowRISC contributors.
2 | // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 | // SPDX-License-Identifier: Apache-2.0
4 |
5 | /**
6 | * Control / status register primitive
7 | */
8 |
9 |
10 | module cv32e40s_csr #(
11 | parameter LIB = 0,
12 | parameter int unsigned WIDTH = 32,
13 | parameter bit SHADOWCOPY = 1'b0,
14 | parameter bit [WIDTH-1:0] RESETVALUE = '0,
15 | parameter bit [WIDTH-1:0] MASK = {WIDTH{1'b1}}
16 | ) (
17 | input logic clk,
18 | input logic rst_n,
19 | input logic scan_cg_en_i,
20 |
21 | input logic [WIDTH-1:0] wr_data_i,
22 | input logic wr_en_i,
23 | output logic [WIDTH-1:0] rd_data_o,
24 |
25 | output logic rd_error_o
26 | );
27 |
28 | logic [WIDTH-1:0] rdata_q;
29 |
30 | assign rd_data_o = rdata_q;
31 |
32 | generate
33 | if (SHADOWCOPY) begin : gen_hardened
34 | logic clk_gated;
35 | logic [WIDTH-1:0] rdata_d;
36 | logic [WIDTH-1:0] shadow_d;
37 | logic [WIDTH-1:0] shadow_q;
38 |
39 | assign rdata_d = wr_data_i;
40 | assign shadow_d = ~wr_data_i;
41 | assign rd_error_o = rdata_q != ~shadow_q;
42 |
43 | cv32e40s_clock_gate
44 | #(.LIB(LIB))
45 | core_clock_gate_i
46 | (.clk_i ( clk ),
47 | .en_i ( wr_en_i ),
48 | .scan_cg_en_i ( scan_cg_en_i ),
49 | .clk_o ( clk_gated ));
50 |
51 | // The shadow registers are logically redundant and are therefore easily optimized away by most synthesis tools.
52 | // These registers are therefore implemented as instantiated cells so that they can be preserved in the synthesis script.
53 | for (genvar i = 0; i < WIDTH; i++) begin : gen_csr_hardened
54 | if (MASK[i]) begin : gen_unmasked_hardened
55 | if (RESETVALUE[i] == 1'b1) begin : gen_rv1
56 | cv32e40s_sffs #(.LIB(LIB)) sffs_rdatareg (.clk(clk_gated), .rst_n(rst_n), .d_i(rdata_d[i]), .q_o(rdata_q[i]));
57 | cv32e40s_sffr #(.LIB(LIB)) sffr_shadowreg (.clk(clk_gated), .rst_n(rst_n), .d_i(shadow_d[i]), .q_o(shadow_q[i]));
58 | end else begin : gen_rv0 // (RESETVALUE[i] == 1'b0)
59 | cv32e40s_sffr #(.LIB(LIB)) sffr_rdatareg (.clk(clk_gated), .rst_n(rst_n), .d_i(rdata_d[i]), .q_o(rdata_q[i]));
60 | cv32e40s_sffs #(.LIB(LIB)) sffs_shadowreg (.clk(clk_gated), .rst_n(rst_n), .d_i(shadow_d[i]), .q_o(shadow_q[i]));
61 | end
62 | end else begin : gen_masked_hardened
63 | if (RESETVALUE[i] == 1'b1) begin : gen_constant_1
64 | assign rdata_q[i] = 1'b1;
65 | assign shadow_q[i] = 1'b0;
66 | end else begin : gen_constant_0
67 | assign rdata_q[i] = 1'b0;
68 | assign shadow_q[i] = 1'b1;
69 | end
70 | end
71 | end
72 |
73 | end else begin : gen_unhardened
74 | for (genvar i = 0; i < WIDTH; i++) begin : gen_csr_unhardened
75 | if (MASK[i]) begin : gen_unmasked_unhardened
76 | // Bits with mask set are actual flipflops
77 | always_ff @(posedge clk or negedge rst_n) begin
78 | if (!rst_n) begin
79 | rdata_q[i] <= RESETVALUE[i];
80 | end else if (wr_en_i) begin
81 | rdata_q[i] <= wr_data_i[i];
82 | end
83 | end
84 | end else begin : gen_masked_unhardened
85 | // Bits with mask cleared are tied off to the reset value
86 | assign rdata_q[i] = RESETVALUE[i];
87 | end
88 | end // for
89 | assign rd_error_o = 1'b0;
90 | end
91 | endgenerate
92 |
93 | endmodule
94 |
--------------------------------------------------------------------------------
/sva/cv32e40s_lsu_response_filter_sva.sv:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Silicon Labs, Inc.
2 | //
3 | // This file, and derivatives thereof are licensed under the
4 | // Solderpad License, Version 2.0 (the "License");
5 | // Use of this file means you agree to the terms and conditions
6 | // of the license and are in full compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // https://solderpad.org/licenses/SHL-2.0/
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // and hardware implementations thereof
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESSED OR IMPLIED.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 | ////////////////////////////////////////////////////////////////////////////////
19 | // //
20 | // Authors: Halfdan Bechmann - Halfdan Bechmann@silabs.com //
21 | // //
22 | // Description: Response Filter Assertions //
23 | // //
24 | ////////////////////////////////////////////////////////////////////////////////
25 |
26 | module cv32e40s_lsu_response_filter_sva
27 | import cv32e40s_pkg::*;
28 | import uvm_pkg::*;
29 | #(parameter int unsigned DEPTH = 2)
30 | (input logic clk,
31 | input logic rst_n,
32 |
33 | input logic valid_i,
34 |
35 | input logic busy_o,
36 | input logic core_trans_accepted,
37 | input logic bus_trans_accepted,
38 | input logic [1:0] core_cnt_q,
39 | input logic [$clog2(DEPTH+1)-1:0] bus_cnt_q
40 | );
41 |
42 | a_no_lost_transfers :
43 | assert property (@(posedge clk) disable iff (!rst_n)
44 | (1'b1) |-> (core_cnt_q <= bus_cnt_q))
45 | else `uvm_error("Response Filter", "Lost transfer(s): More outstanding transfers on the core side than on the bus side.");
46 |
47 | a_busy_when_outstanding :
48 | assert property (@(posedge clk) disable iff (!rst_n)
49 | ((core_cnt_q != 0) || (bus_cnt_q != 0) || valid_i) |-> busy_o)
50 | else `uvm_error("Response Filter", "Has outstanding (or pending) transfer(s) but busy_o is not set.");
51 |
52 | a_no_core_cnt_overflow :
53 | assert property (@(posedge clk) disable iff (!rst_n)
54 | (1'b1) |-> (core_cnt_q <= DEPTH))
55 | else `uvm_error("Response Filter", "Core side outstanding transfers counter overflow");
56 |
57 | a_no_bus_cnt_overflow :
58 | assert property (@(posedge clk) disable iff (!rst_n)
59 | (1'b1) |-> (bus_cnt_q <= DEPTH))
60 | else `uvm_error("Response Filter", "Bus side outstanding transfers counter overflow");
61 |
62 | a_no_bus_cnt_underflow :
63 | assert property (@(posedge clk) disable iff (!rst_n)
64 | (bus_cnt_q == 0) |=> (bus_cnt_q == 0) || (bus_cnt_q == 1))
65 | else `uvm_error("Response Filter", "Bus side transfer counter underflow");
66 |
67 | a_no_core_cnt_underflow :
68 | assert property (@(posedge clk) disable iff (!rst_n)
69 | (core_cnt_q == 0) |=> (core_cnt_q == 0) || (core_cnt_q == 1))
70 | else `uvm_error("Response Filter", "Core side transfer counter underflow");
71 |
72 | a_transfers_accepted_at_the_same_time :
73 | assert property (@(posedge clk) disable iff (!rst_n)
74 | (1'b1) |-> (core_trans_accepted == bus_trans_accepted))
75 | else `uvm_error("Response Filter", "Mismatch between accepted transfers on core side and bus side");
76 |
77 | endmodule : cv32e40s_lsu_response_filter_sva
78 |
79 |
--------------------------------------------------------------------------------
/cv32e40s_manifest.flist:
--------------------------------------------------------------------------------
1 | ///////////////////////////////////////////////////////////////////////////////
2 | //
3 | // Copyright 2020 OpenHW Group
4 | //
5 | // Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
6 | // you may not use this file except in compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // https://solderpad.org/licenses/
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // distributed under the License is distributed on an "AS IS" BASIS,
13 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | // See the License for the specific language governing permissions and
15 | // limitations under the License.
16 | //
17 | ///////////////////////////////////////////////////////////////////////////////
18 | //
19 | // Manifest for the CV32E40S RTL model.
20 | // - Intended to be used by both synthesis and simulation.
21 | // - Relevent synthesis and simulation scripts/Makefiles must set the shell
22 | // ENV variable DESIGN_RTL_DIR as required.
23 | //
24 | ///////////////////////////////////////////////////////////////////////////////
25 |
26 | +incdir+${DESIGN_RTL_DIR}/include
27 | +incdir+${DESIGN_RTL_DIR}/../bhv
28 | +incdir+${DESIGN_RTL_DIR}/../bhv/include
29 | +incdir+${DESIGN_RTL_DIR}/../sva
30 |
31 | ${DESIGN_RTL_DIR}/include/cv32e40s_pkg.sv
32 | ${DESIGN_RTL_DIR}/cv32e40s_if_c_obi.sv
33 | ${DESIGN_RTL_DIR}/../bhv/include/cv32e40s_rvfi_pkg.sv
34 | ${DESIGN_RTL_DIR}/../bhv/cv32e40s_wrapper.sv
35 | ${DESIGN_RTL_DIR}/cv32e40s_dummy_instr.sv
36 | ${DESIGN_RTL_DIR}/cv32e40s_if_stage.sv
37 | ${DESIGN_RTL_DIR}/cv32e40s_csr.sv
38 | ${DESIGN_RTL_DIR}/cv32e40s_debug_triggers.sv
39 | ${DESIGN_RTL_DIR}/cv32e40s_cs_registers.sv
40 | ${DESIGN_RTL_DIR}/cv32e40s_register_file.sv
41 | ${DESIGN_RTL_DIR}/cv32e40s_register_file_ecc.sv
42 | ${DESIGN_RTL_DIR}/cv32e40s_register_file_wrapper.sv
43 | ${DESIGN_RTL_DIR}/cv32e40s_write_buffer.sv
44 | ${DESIGN_RTL_DIR}/cv32e40s_lsu_response_filter.sv
45 | ${DESIGN_RTL_DIR}/cv32e40s_load_store_unit.sv
46 | ${DESIGN_RTL_DIR}/cv32e40s_id_stage.sv
47 | ${DESIGN_RTL_DIR}/cv32e40s_i_decoder.sv
48 | ${DESIGN_RTL_DIR}/cv32e40s_m_decoder.sv
49 | ${DESIGN_RTL_DIR}/cv32e40s_b_decoder.sv
50 | ${DESIGN_RTL_DIR}/cv32e40s_decoder.sv
51 | ${DESIGN_RTL_DIR}/cv32e40s_compressed_decoder.sv
52 | ${DESIGN_RTL_DIR}/cv32e40s_sequencer.sv
53 | ${DESIGN_RTL_DIR}/cv32e40s_alignment_buffer.sv
54 | ${DESIGN_RTL_DIR}/cv32e40s_prefetch_unit.sv
55 | ${DESIGN_RTL_DIR}/cv32e40s_mult.sv
56 | ${DESIGN_RTL_DIR}/cv32e40s_int_controller.sv
57 | ${DESIGN_RTL_DIR}/cv32e40s_clic_int_controller.sv
58 | ${DESIGN_RTL_DIR}/cv32e40s_ex_stage.sv
59 | ${DESIGN_RTL_DIR}/cv32e40s_wb_stage.sv
60 | ${DESIGN_RTL_DIR}/cv32e40s_div.sv
61 | ${DESIGN_RTL_DIR}/cv32e40s_alu.sv
62 | ${DESIGN_RTL_DIR}/cv32e40s_ff_one.sv
63 | ${DESIGN_RTL_DIR}/cv32e40s_popcnt.sv
64 | ${DESIGN_RTL_DIR}/cv32e40s_alu_b_cpop.sv
65 | ${DESIGN_RTL_DIR}/cv32e40s_controller_fsm.sv
66 | ${DESIGN_RTL_DIR}/cv32e40s_controller_bypass.sv
67 | ${DESIGN_RTL_DIR}/cv32e40s_controller.sv
68 | ${DESIGN_RTL_DIR}/cv32e40s_obi_integrity_fifo.sv
69 | ${DESIGN_RTL_DIR}/cv32e40s_instr_obi_interface.sv
70 | ${DESIGN_RTL_DIR}/cv32e40s_data_obi_interface.sv
71 | ${DESIGN_RTL_DIR}/cv32e40s_prefetcher.sv
72 | ${DESIGN_RTL_DIR}/cv32e40s_sleep_unit.sv
73 | ${DESIGN_RTL_DIR}/cv32e40s_alert.sv
74 | ${DESIGN_RTL_DIR}/cv32e40s_core.sv
75 | ${DESIGN_RTL_DIR}/cv32e40s_mpu.sv
76 | ${DESIGN_RTL_DIR}/cv32e40s_pma.sv
77 | ${DESIGN_RTL_DIR}/cv32e40s_pmp.sv
78 | ${DESIGN_RTL_DIR}/cv32e40s_pc_target.sv
79 | ${DESIGN_RTL_DIR}/cv32e40s_wpt.sv
80 | ${DESIGN_RTL_DIR}/cv32e40s_pc_check.sv
81 | ${DESIGN_RTL_DIR}/cv32e40s_rchk_check.sv
82 | ${DESIGN_RTL_DIR}/cv32e40s_lfsr.sv
83 |
84 | ${DESIGN_RTL_DIR}/../bhv/cv32e40s_sim_sffr.sv
85 | ${DESIGN_RTL_DIR}/../bhv/cv32e40s_sim_sffs.sv
86 | ${DESIGN_RTL_DIR}/../bhv/cv32e40s_sim_clock_gate.sv
87 | ${DESIGN_RTL_DIR}/../bhv/cv32e40s_rvfi_instr_obi.sv
88 | ${DESIGN_RTL_DIR}/../bhv/cv32e40s_rvfi_data_obi.sv
89 | ${DESIGN_RTL_DIR}/../bhv/cv32e40s_rvfi.sv
90 | ${DESIGN_RTL_DIR}/../bhv/cv32e40s_rvfi_sim_trace.sv
91 |
--------------------------------------------------------------------------------
/sva/cv32e40s_dummy_instr_sva.sv:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Silicon Labs, Inc.
2 | //
3 | // This file, and derivatives thereof are licensed under the
4 | // Solderpad License, Version 2.0 (the "License");
5 | // Use of this file means you agree to the terms and conditions
6 | // of the license and are in full compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // https://solderpad.org/licenses/SHL-2.0/
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // and hardware implementations thereof
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESSED OR IMPLIED.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 | ////////////////////////////////////////////////////////////////////////////////
19 | // //
20 | // Authors: Halfdan Bechmann - Halfdan Bechmann@silabs.com //
21 | // //
22 | // Description: Dummy Instruction Insertion Assertions //
23 | // //
24 | ////////////////////////////////////////////////////////////////////////////////
25 |
26 | module cv32e40s_dummy_instr_sva
27 | import cv32e40s_pkg::*;
28 | import uvm_pkg::*;
29 | #(parameter MAX_DUMMY_INTERVAL = 64,
30 | parameter CNT_WIDTH = 7
31 | )
32 | (input logic clk,
33 | input logic rst_n,
34 |
35 | input logic dummy_insert_o,
36 | input xsecure_ctrl_t xsecure_ctrl_i,
37 | input logic [CNT_WIDTH-1:0] cnt_q,
38 | input logic [5:0] lfsr_cnt,
39 | input logic instr_issued_i,
40 | input logic cnt_rst,
41 | input logic if_valid_i,
42 | input logic id_ready_i,
43 | input logic hint_if_i,
44 | input logic ptr_in_if_i
45 | );
46 |
47 | // Helper logic that remembers if the last instruction from IF to ID was a hint instruction.
48 | // Hint instructions will shift LFSRs, changing the rules for allowed counter values.
49 | // Excluding any pointers, as these are not counted as instructions.
50 | logic last_ins_was_hint;
51 | always_ff @(posedge clk, negedge rst_n) begin
52 | if (rst_n == 1'b0) begin
53 | last_ins_was_hint <= 1'b0;
54 | end else begin
55 | if (if_valid_i && id_ready_i && !ptr_in_if_i) begin
56 | last_ins_was_hint <= hint_if_i;
57 | end
58 | end
59 | end
60 |
61 | // Assert that counter stopped correctly when inserting dummy instruction
62 | // When no hint is in ID, the cnt_q should be exactly lfsr_cnt + 1
63 | a_no_count_overflow_nohint :
64 | assert property (@(posedge clk) disable iff (!rst_n)
65 | dummy_insert_o && !last_ins_was_hint |-> (cnt_q == lfsr_cnt + 1))
66 | else `uvm_error("Dummy Instruction Insertion", "Counter counted further than lfsr_cnt + 1");
67 |
68 | // When a dummy is inserted and at the same time a hint is in ID, the counter value
69 | // may differ by more than one since the hint instruction did an lfsr shift, possibly changing the
70 | // dummy insertion threshold.
71 | a_no_count_overflow_hint :
72 | assert property (@(posedge clk) disable iff (!rst_n)
73 | dummy_insert_o && last_ins_was_hint |-> (cnt_q >= (lfsr_cnt + 1)))
74 | else `uvm_error("Dummy Instruction Insertion", "Counter counted further than lfsr_cnt + 1");
75 |
76 | // Assert that we never count when counter has passed the compare value
77 | a_never_count_on_overflow :
78 | assert property (@(posedge clk) disable iff (!rst_n)
79 | (cnt_q > lfsr_cnt) |=> (cnt_q <= $past(cnt_q)))
80 | else `uvm_error("Dummy Instruction Insertion", "Counted when after insert condition was met");
81 |
82 | // Counter should not reset if a dummy instruction is not yet propagated to decode (id_ready == 0)
83 | a_cnt_reset_on_dummy_issue :
84 | assert property (@(posedge clk) disable iff (!rst_n)
85 | (dummy_insert_o && if_valid_i && !id_ready_i) |-> !cnt_rst)
86 | else `uvm_error("Dummy Instruction Insertion", "Counter reset before dummy left IF");
87 |
88 |
89 | endmodule : cv32e40s_dummy_instr_sva
90 |
91 |
92 |
--------------------------------------------------------------------------------
/rtl/cv32e40s_write_buffer.sv:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Silicon Labs, Inc.
2 | //
3 | // This file, and derivatives thereof are licensed under the
4 | // Solderpad License, Version 2.0 (the "License").
5 | //
6 | // Use of this file means you agree to the terms and conditions
7 | // of the license and are in full compliance with the License.
8 | //
9 | // You may obtain a copy of the License at:
10 | //
11 | // https://solderpad.org/licenses/SHL-2.0/
12 | //
13 | // Unless required by applicable law or agreed to in writing, software
14 | // and hardware implementations thereof distributed under the License
15 | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
16 | // OF ANY KIND, EITHER EXPRESSED OR IMPLIED.
17 | //
18 | // See the License for the specific language governing permissions and
19 | // limitations under the License.
20 |
21 | ////////////////////////////////////////////////////////////////////////////////
22 | // Engineer: Halfdan Bechmann - halfdan.bechmann@silabs.com //
23 | // //
24 | // Design Name: Write Buffer //
25 | // Project Name: CV32E40S //
26 | // Language: SystemVerilog //
27 | // //
28 | // Description: Single word write buffer //
29 | // //
30 | ////////////////////////////////////////////////////////////////////////////////
31 |
32 | module cv32e40s_write_buffer import cv32e40s_pkg::*;
33 | #(
34 | parameter int PMA_NUM_REGIONS = 0,
35 | parameter pma_cfg_t PMA_CFG[PMA_NUM_REGIONS-1:0] = '{default:PMA_R_DEFAULT}
36 | )
37 | (
38 | // clock and reset
39 | input logic clk,
40 | input logic rst_n,
41 |
42 | // inputs
43 | input logic valid_i,
44 | input obi_data_req_t trans_i,
45 | input logic ready_i,
46 |
47 | // outputs
48 | output logic valid_o,
49 | output obi_data_req_t trans_o,
50 | output logic ready_o
51 | );
52 |
53 | // local signals
54 | write_buffer_state_e state, next_state;
55 | obi_data_req_t trans_q;
56 | logic push;
57 | logic bufferable;
58 |
59 | assign bufferable = trans_i.memtype[0];
60 |
61 | ///////////////////////////////////////////
62 | // FSM
63 | ///////////////////////////////////////////
64 | always_ff @(posedge clk, negedge rst_n) begin
65 | if(!rst_n) begin
66 | state <= WBUF_EMPTY;
67 | end else begin
68 | state <= next_state;
69 | end
70 | end
71 |
72 | always_comb begin
73 | next_state = state;
74 | push = 1'b0;
75 |
76 | case(state)
77 | WBUF_EMPTY: begin // buffer is empty
78 | if(bufferable && valid_i && !ready_i) begin
79 | next_state = WBUF_FULL;
80 | push = 1'b1; // push incoming data into the buffer
81 | end
82 | end
83 | WBUF_FULL: begin // buffer is full
84 | if(ready_i) begin
85 | if (bufferable && valid_i) begin
86 | next_state = WBUF_FULL;
87 | push = 1'b1; // push incoming data into the buffer
88 | end else begin
89 | next_state = WBUF_EMPTY;
90 | end
91 | end
92 | end
93 |
94 | default:;
95 | endcase // case (state)
96 | end
97 |
98 | ///////////////////////////////////////////
99 | // Buffer
100 | ///////////////////////////////////////////
101 | always_ff @(posedge clk, negedge rst_n) begin
102 | if(!rst_n) begin
103 | trans_q <= obi_data_req_t'{we: 1'b1, default: '0};
104 | end else if (push) begin
105 | trans_q <= trans_i;
106 | end
107 | end
108 |
109 | ///////////////////////////////////////////
110 | // Outputs
111 | ///////////////////////////////////////////
112 | assign ready_o = (state == WBUF_FULL) ?
113 | (bufferable && ready_i) : // A downstream ready will free up the buffer for a new bufferable transfer
114 | (bufferable || ready_i); // Ready for bufferable transfer, accept any transfer if downstream is ready
115 | assign valid_o = (state == WBUF_FULL) || valid_i;
116 | assign trans_o = (state == WBUF_FULL) ? trans_q : trans_i;
117 |
118 | endmodule
119 |
--------------------------------------------------------------------------------
/docs/user_manual/source/sleep.rst:
--------------------------------------------------------------------------------
1 | .. _sleep_unit:
2 |
3 | Sleep Unit
4 | ==========
5 |
6 | Source File: :file:`rtl/cv32e40s_sleep_unit.sv`
7 |
8 | The Sleep Unit contains and controls the instantiated clock gate, see :ref:`clock-gating-cell`, that gates ``clk_i`` and produces a gated clock
9 | for use by the other modules inside |corev|. The Sleep Unit is the only place in which ``clk_i`` itself is used; all
10 | other modules use the gated version of ``clk_i``.
11 |
12 | The clock gating in the Sleep Unit is impacted by the following:
13 |
14 | * ``rst_ni``
15 | * ``fetch_enable_i``
16 | * **wfi** instruction
17 | * **wfe** instruction
18 |
19 | :numref:`Sleep Unit interface signals` describes the Sleep Unit interface.
20 |
21 | .. table:: Sleep Unit interface signals
22 | :name: Sleep Unit interface signals
23 | :widths: 10 10 80
24 | :class: no-scrollbar-table
25 |
26 | +--------------------------------------+-----------+--------------------------------------------------+
27 | | Signal | Direction | Description |
28 | +======================================+===========+==================================================+
29 | | ``core_sleep_o`` | output | Core is sleeping because |
30 | | | | of a **wfi** or **wfe** instruction. If |
31 | | | | ``core_sleep_o`` = 1, then ``clk_i`` is gated |
32 | | | | off internally and it is allowed to gate off |
33 | | | | ``clk_i`` externally as well. See |
34 | | | | :ref:`wfi` and :ref:`wfe` for details. |
35 | +--------------------------------------+-----------+--------------------------------------------------+
36 | | ``wu_wfe_i`` | input | Wake-up signal for custom **wfe** instruction. |
37 | | | | Positive level sensitive. See :ref:`wfe` for |
38 | | | | details. |
39 | +--------------------------------------+-----------+--------------------------------------------------+
40 |
41 | Startup behavior
42 | ----------------
43 |
44 | ``clk_i`` is internally gated off (while signaling ``core_sleep_o`` = 0) during |corev| startup:
45 |
46 | * ``clk_i`` is internally gated off during ``rst_ni`` assertion
47 | * ``clk_i`` is internally gated off from ``rst_ni`` deassertion until ``fetch_enable_i`` = 1
48 |
49 | After initial assertion of ``fetch_enable_i``, the ``fetch_enable_i`` signal is ignored until after a next reset assertion.
50 |
51 | .. _wfi:
52 |
53 | WFI
54 | ---
55 |
56 | The **wfi** instruction can under certain conditions be used to enter sleep mode awaiting a locally enabled
57 | interrupt to become pending. The operation of **wfi** is unaffected by the global interrupt bits in **mstatus**.
58 |
59 | A **wfi** will not enter sleep mode, but will be executed as a regular **nop**, if any of the following conditions apply:
60 |
61 | * ``debug_req_i`` = 1 or a debug request is pending
62 | * The core is in debug mode
63 | * The core is performing single stepping (debug)
64 | * The core has a trigger match (debug)
65 |
66 | If a **wfi** causes sleep mode entry, then ``core_sleep_o`` is set to 1 and ``clk_i`` is gated off internally. ``clk_i`` is
67 | allowed to be gated off externally as well in this scenario. A wake-up can be triggered by any of the following:
68 |
69 | * A locally enabled interrupt is pending
70 | * A debug request is pending
71 | * Core is in debug mode
72 |
73 | Upon wake-up ``core_sleep_o`` is set to 0, ``clk_i`` will no longer be gated internally, must not be gated off externally, and
74 | instruction execution resumes.
75 |
76 | If one of the above wake-up conditions coincides with the **wfi** instruction, then sleep mode is not entered and ``core_sleep_o``
77 | will not become 1.
78 |
79 | :numref:`wfi-example` shows an example waveform for sleep mode entry because of a **wfi** instruction.
80 |
81 | .. figure:: ../images/wfi.svg
82 | :name: wfi-example
83 | :align: center
84 |
85 | **wfi** example
86 |
87 | .. _wfe:
88 |
89 | WFE
90 | ---
91 |
92 | The custom **wfe** instruction behaves exactly as the **wfi** instruction, except that a wake-up can additionally be triggered
93 | by asserting ``wu_wfe_i``.
94 |
95 | The **wfe** instruction is encoded as a custom SYSTEM instruction with opcode ``0x8C00_0073``.
96 |
--------------------------------------------------------------------------------
/rtl/cv32e40s_ff_one.sv:
--------------------------------------------------------------------------------
1 | // Copyright 2018 ETH Zurich and University of Bologna.
2 | // Copyright and related rights are licensed under the Solderpad Hardware
3 | // License, Version 0.51 (the "License"); you may not use this file except in
4 | // compliance with the License. You may obtain a copy of the License at
5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
6 | // or agreed to in writing, software, hardware and materials distributed under
7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
9 | // specific language governing permissions and limitations under the License.
10 |
11 | ////////////////////////////////////////////////////////////////////////////////
12 | // Engineer: Andreas Traber - atraber@student.ethz.ch //
13 | // //
14 | // Additional contributions by: //
15 | // Davide Schiavone - pschiavo@iis.ee.ethz.ch //
16 | // //
17 | // Design Name: cv32e40s_ff_one //
18 | // Project Name: RI5CY //
19 | // Language: SystemVerilog //
20 | // //
21 | // Description: Find First One //
22 | // //
23 | ////////////////////////////////////////////////////////////////////////////////
24 |
25 | module cv32e40s_ff_one
26 | #(
27 | parameter int unsigned LEN = 32
28 | )
29 | (
30 | input logic [LEN-1:0] in_i,
31 |
32 | output logic [$clog2(LEN)-1:0] first_one_o,
33 | output logic no_ones_o
34 | );
35 |
36 | localparam NUM_LEVELS = $clog2(LEN);
37 |
38 | logic [LEN-1:0] [NUM_LEVELS-1:0] index_lut;
39 | logic [2**NUM_LEVELS-1:0] sel_nodes;
40 | logic [2**NUM_LEVELS-1:0] [NUM_LEVELS-1:0] index_nodes;
41 |
42 |
43 | //////////////////////////////////////////////////////////////////////////////
44 | // generate tree structure
45 | //////////////////////////////////////////////////////////////////////////////
46 |
47 | generate
48 | genvar j;
49 | for (j = 0; j < LEN; j++) begin : gen_index_lut
50 | assign index_lut[j] = $unsigned(j);
51 | end
52 | endgenerate
53 |
54 | generate
55 | genvar k;
56 | genvar l;
57 | genvar level;
58 |
59 | assign sel_nodes[2**NUM_LEVELS-1] = 1'b0;
60 |
61 | for (level = 0; level < NUM_LEVELS; level++) begin : gen_tree
62 | //------------------------------------------------------------
63 | if (level < NUM_LEVELS-1) begin : gen_non_root_level
64 | for (l = 0; l < 2**level; l++) begin : gen_node_non_root
65 | assign sel_nodes[2**level-1+l] = sel_nodes[2**(level+1)-1+l*2] | sel_nodes[2**(level+1)-1+l*2+1];
66 | assign index_nodes[2**level-1+l] = (sel_nodes[2**(level+1)-1+l*2] == 1'b1) ?
67 | index_nodes[2**(level+1)-1+l*2] : index_nodes[2**(level+1)-1+l*2+1];
68 | end
69 | end
70 | //------------------------------------------------------------
71 | if (level == NUM_LEVELS-1) begin : gen_root_level
72 | for (k = 0; k < 2**level; k++) begin : gen_node_root
73 | // if two successive indices are still in the vector...
74 | if (k * 2 < LEN-1) begin : gen_two
75 | assign sel_nodes[2**level-1+k] = in_i[k*2] | in_i[k*2+1];
76 | assign index_nodes[2**level-1+k] = (in_i[k*2] == 1'b1) ? index_lut[k*2] : index_lut[k*2+1];
77 | end
78 | // if only the first index is still in the vector...
79 | if (k * 2 == LEN-1) begin: gen_one
80 | assign sel_nodes[2**level-1+k] = in_i[k*2];
81 | assign index_nodes[2**level-1+k] = index_lut[k*2];
82 | end
83 | // if index is out of range
84 | if (k * 2 > LEN-1) begin : gen_out_of_range
85 | assign sel_nodes[2**level-1+k] = 1'b0;
86 | assign index_nodes[2**level-1+k] = '0;
87 | end
88 | end
89 | end
90 | //------------------------------------------------------------
91 | end
92 | endgenerate
93 |
94 | //////////////////////////////////////////////////////////////////////////////
95 | // connect output
96 | //////////////////////////////////////////////////////////////////////////////
97 |
98 | assign first_one_o = index_nodes[0];
99 | assign no_ones_o = ~sel_nodes[0];
100 |
101 | endmodule
102 |
--------------------------------------------------------------------------------
/rtl/cv32e40s_register_file_wrapper.sv:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Silicon Labs, Inc.
2 | //
3 | // This file, and derivatives thereof are licensed under the
4 | // Solderpad License, Version 2.0 (the "License").
5 | //
6 | // Use of this file means you agree to the terms and conditions
7 | // of the license and are in full compliance with the License.
8 | //
9 | // You may obtain a copy of the License at:
10 | //
11 | // https://solderpad.org/licenses/SHL-2.0/
12 | //
13 | // Unless required by applicable law or agreed to in writing, software
14 | // and hardware implementations thereof distributed under the License
15 | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
16 | // OF ANY KIND, EITHER EXPRESSED OR IMPLIED.
17 | //
18 | // See the License for the specific language governing permissions and
19 | // limitations under the License.
20 |
21 | ////////////////////////////////////////////////////////////////////////////////
22 | // Engineers: Øystein Knauserud - oystein.knauserud@silabs.com //
23 | // Halfdan Bechmann - halfdan.bechmann@silabs.com //
24 | // //
25 | // Design Name: Register file wrapper //
26 | // Project Name: CV32E40S //
27 | // Language: SystemVerilog //
28 | // //
29 | // Description: Wrapper for the register file //
30 | ////////////////////////////////////////////////////////////////////////////////
31 |
32 | module cv32e40s_register_file_wrapper import cv32e40s_pkg::*;
33 | #(
34 | parameter int unsigned REGFILE_NUM_READ_PORTS = 2,
35 | parameter rv32_e RV32 = RV32I
36 | )
37 | (
38 | // Clock and Reset
39 | input logic clk,
40 | input logic rst_n,
41 |
42 | // R0 Dummy and hint instruction handling
43 | input logic hint_instr_id_i,
44 | input logic hint_instr_wb_i,
45 | input logic dummy_instr_id_i,
46 | input logic dummy_instr_wb_i,
47 |
48 | // ECC
49 | output logic ecc_err_o,
50 |
51 | // Read ports
52 | input rf_addr_t raddr_i [REGFILE_NUM_READ_PORTS],
53 | output rf_data_t rdata_o [REGFILE_NUM_READ_PORTS],
54 |
55 | // Write ports
56 | input rf_addr_t waddr_i [REGFILE_NUM_WRITE_PORTS],
57 | input rf_data_t wdata_i [REGFILE_NUM_WRITE_PORTS],
58 | input logic we_i [REGFILE_NUM_WRITE_PORTS]
59 | );
60 |
61 | // Register file data signals
62 | logic [REGFILE_WORD_WIDTH-1:0] rf_rdata[REGFILE_NUM_READ_PORTS];
63 | logic [REGFILE_WORD_WIDTH-1:0] rf_wdata[REGFILE_NUM_WRITE_PORTS];
64 |
65 | cv32e40s_register_file
66 | #(
67 | .REGFILE_NUM_READ_PORTS ( REGFILE_NUM_READ_PORTS ),
68 | .RV32 ( RV32 )
69 | )
70 | register_file_i
71 | (
72 | .clk ( clk ),
73 | .rst_n ( rst_n ),
74 |
75 | .hint_instr_id_i ( hint_instr_id_i ),
76 | .hint_instr_wb_i ( hint_instr_wb_i ),
77 | .dummy_instr_id_i ( dummy_instr_id_i ),
78 | .dummy_instr_wb_i ( dummy_instr_wb_i ),
79 |
80 | // Read ports
81 | .raddr_i ( raddr_i ),
82 | .rdata_o ( rf_rdata ),
83 |
84 | // Write ports
85 | .waddr_i ( waddr_i ),
86 | .wdata_i ( rf_wdata ),
87 | .we_i ( we_i )
88 | );
89 |
90 | generate for (genvar i = 0; i < REGFILE_NUM_READ_PORTS; i++)
91 | assign rdata_o[i] = rf_data_t'(rf_rdata[i][REGFILE_DATA_WIDTH-1:0]);
92 | endgenerate
93 |
94 | generate
95 | if (SECURE) begin
96 | cv32e40s_register_file_ecc
97 | #(
98 | .REGFILE_NUM_READ_PORTS ( REGFILE_NUM_READ_PORTS )
99 | )
100 | register_file_ecc
101 | (
102 | .clk ( clk ),
103 | .rst_n ( rst_n ),
104 |
105 | // Read ports
106 | .raddr_i ( raddr_i ),
107 | .rdata_i ( rf_rdata ),
108 |
109 | // Write ports
110 | .waddr_i ( waddr_i ),
111 | .wdata_i ( wdata_i ),
112 |
113 | // Encoded Write Data
114 | .rf_wdata_o ( rf_wdata ),
115 |
116 | // Error Output
117 | .ecc_err_o ( ecc_err_o )
118 | );
119 | end else begin // if (SECURE)
120 | assign ecc_err_o = 1'b0;
121 | assign rf_wdata = wdata_i;
122 | end
123 | endgenerate
124 |
125 | endmodule
126 |
127 |
--------------------------------------------------------------------------------
/rtl/cv32e40s_pma.sv:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Silicon Labs, Inc.
2 | //
3 | // This file, and derivatives thereof are licensed under the
4 | // Solderpad License, Version 2.0 (the "License");
5 | // Use of this file means you agree to the terms and conditions
6 | // of the license and are in full compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // https://solderpad.org/licenses/SHL-2.0/
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // and hardware implementations thereof
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESSED OR IMPLIED.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 | ////////////////////////////////////////////////////////////////////////////////
19 | // //
20 | // Authors: Oivind Ekelund - oivind.ekelund@silabs.com //
21 | // //
22 | // Description: PMA (Physical Memory Attribution) //
23 | // //
24 | ////////////////////////////////////////////////////////////////////////////////
25 |
26 | module cv32e40s_pma import cv32e40s_pkg::*;
27 | #(
28 | parameter int PMA_NUM_REGIONS = 0,
29 | parameter pma_cfg_t PMA_CFG[PMA_NUM_REGIONS-1:0] = '{default:PMA_R_DEFAULT}
30 | )
31 | (
32 | input logic [31:0] trans_addr_i,
33 | input logic trans_debug_region_i, // Transaction address is inside the debug region
34 | input logic trans_pushpop_i, // Transaction is part of a PUSH or POP sequence
35 | input logic instr_fetch_access_i, // Indicate that ongoing access is an instruction fetch
36 | input logic misaligned_access_i, // Indicate that ongoing access is part of a misaligned access
37 | input logic modified_access_i, // Indicate that ongoing access is part of a modified access
38 | input logic load_access_i, // Indicate that ongoing access is a load
39 | output logic pma_err_o,
40 | output logic pma_integrity_o,
41 | output logic pma_bufferable_o,
42 | output logic pma_cacheable_o
43 | );
44 |
45 | // Attributes for accessing the DM (DM_REGION_START:DM_REGION_END) in debug mode
46 | localparam pma_cfg_t PMA_DBG = '{word_addr_low : '0, // not used
47 | word_addr_high : '0, // not used
48 | main : 1'b1,
49 | bufferable : 1'b0,
50 | cacheable : 1'b0,
51 | integrity : 1'b0};
52 |
53 |
54 | pma_cfg_t pma_cfg;
55 | logic [31:0] word_addr;
56 |
57 | // PMA addresses are word addresses
58 | assign word_addr = {2'b00, trans_addr_i[31:2]};
59 |
60 | generate
61 | if(PMA_NUM_REGIONS == 0) begin: no_pma
62 |
63 | always_comb begin
64 | // PMA is deconfigured, use NO_PMA_R_DEFAULT as default.
65 | pma_cfg = NO_PMA_R_DEFAULT;
66 |
67 | // Debug mode transactions within the Debug Module region use PMA_DBG as attributes for the DM range
68 | if (trans_debug_region_i) begin
69 | pma_cfg = PMA_DBG;
70 | end
71 | end
72 |
73 | end
74 | else begin: pma
75 |
76 | // Identify PMA region
77 | always_comb begin
78 |
79 | // If no match, use default PMA config as default.
80 | pma_cfg = PMA_R_DEFAULT;
81 |
82 | for(int i = PMA_NUM_REGIONS-1; i >= 0; i--) begin
83 | if((word_addr >= PMA_CFG[i].word_addr_low) &&
84 | (word_addr < PMA_CFG[i].word_addr_high)) begin
85 | pma_cfg = PMA_CFG[i];
86 | end
87 | end
88 |
89 | // Debug mode transactions within the Debug Module region use PMA_DBG as attributes for the DM range
90 | if (trans_debug_region_i) begin
91 | pma_cfg = PMA_DBG;
92 | end
93 | end
94 | end
95 |
96 | endgenerate
97 |
98 | // Check transaction based on PMA region config
99 | always_comb begin
100 |
101 | pma_err_o = 1'b0;
102 |
103 | // Instruction fetches only allowed in main memory
104 | if (instr_fetch_access_i && !pma_cfg.main) begin
105 | pma_err_o = 1'b1;
106 | end
107 |
108 | // Misaligned or modified access to I/O memory
109 | if ((misaligned_access_i || modified_access_i) && !pma_cfg.main) begin
110 | pma_err_o = 1'b1;
111 | end
112 |
113 | // PUSH/POP outside of main is not allowed
114 | if (trans_pushpop_i && !pma_cfg.main) begin
115 | pma_err_o = 1'b1;
116 | end
117 | end
118 |
119 | // Set integrity based on PMA region attribute
120 | assign pma_integrity_o = pma_cfg.integrity;
121 |
122 | // Set cacheable and bufferable based on PMA region attributes
123 | // Instruction fetches and loads are never classified as bufferable
124 | assign pma_bufferable_o = pma_cfg.bufferable && !instr_fetch_access_i && !load_access_i;
125 | assign pma_cacheable_o = pma_cfg.cacheable;
126 |
127 | endmodule
128 |
--------------------------------------------------------------------------------
/rtl/cv32e40s_sleep_unit.sv:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Silicon Labs, Inc.
2 | //
3 | // This file, and derivatives thereof are licensed under the
4 | // Solderpad License, Version 2.0 (the "License").
5 | //
6 | // Use of this file means you agree to the terms and conditions
7 | // of the license and are in full compliance with the License.
8 | //
9 | // You may obtain a copy of the License at:
10 | //
11 | // https://solderpad.org/licenses/SHL-2.0/
12 | //
13 | // Unless required by applicable law or agreed to in writing, software
14 | // and hardware implementations thereof distributed under the License
15 | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
16 | // OF ANY KIND, EITHER EXPRESSED OR IMPLIED.
17 | //
18 | // See the License for the specific language governing permissions and
19 | // limitations under the License.
20 |
21 | ////////////////////////////////////////////////////////////////////////////////
22 | // Engineer: Arjan Bink - arjan.bink@silabs.com //
23 | // //
24 | // Design Name: Sleep Unit //
25 | // Project Name: CV32E40P //
26 | // Language: SystemVerilog //
27 | // //
28 | // Description: Sleep unit containing the instantiated clock gate which //
29 | // provides the gated clock (clk_gated_o) for the rest //
30 | // of the design. //
31 | // //
32 | // The clock is gated for the following scenarios: //
33 | // //
34 | // - While waiting for fetch to become enabled //
35 | // - While blocked on a WFI //
36 | // //
37 | // Sleep is signaled via core_sleep_o: //
38 | // //
39 | // - During a WFI (except in debug) //
40 | // //
41 | ////////////////////////////////////////////////////////////////////////////////
42 |
43 | module cv32e40s_sleep_unit import cv32e40s_pkg::*;
44 | #(
45 | parameter LIB = 0
46 | )
47 | (
48 | // Clock, reset interface
49 | input logic clk_ungated_i, // Free running clock
50 | input logic rst_n,
51 | output logic clk_gated_o, // Gated clock
52 | input logic scan_cg_en_i, // Enable all clock gates for testing
53 |
54 | // Core sleep
55 | output logic core_sleep_o,
56 |
57 | // Fetch enable
58 | input logic fetch_enable_i,
59 | output logic fetch_enable_o,
60 |
61 | // Core status
62 | input logic if_busy_i,
63 | input logic lsu_busy_i,
64 |
65 | input ctrl_fsm_t ctrl_fsm_i
66 | );
67 |
68 | logic fetch_enable_q; // Sticky version of fetch_enable_i
69 | logic fetch_enable_d;
70 | logic core_busy_q; // Is core still busy (and requires a clock) with what needs to finish before entering sleep?
71 | logic core_busy_d;
72 | logic clock_en; // Final clock enable
73 |
74 | //////////////////////////////////////////////////////////////////////////////
75 | // Sleep FSM
76 | //////////////////////////////////////////////////////////////////////////////
77 |
78 | // Make sticky version of fetch_enable_i
79 | assign fetch_enable_d = fetch_enable_i ? 1'b1 : fetch_enable_q;
80 |
81 | // Busy when any of the sub units is busy (typically wait for the instruction buffer to fill up)
82 | assign core_busy_d = if_busy_i || ctrl_fsm_i.ctrl_busy || lsu_busy_i;
83 |
84 | // Enable the clock only after the initial fetch enable while busy or waking up to become busy
85 | assign clock_en = fetch_enable_q && (ctrl_fsm_i.wake_from_sleep || core_busy_q);
86 |
87 | // Sleep only in response to WFI which leads to clock disable. The controller determines the
88 | // scenarios for which WFI can(not) cause sleep. WFI suppression is performed in the i_decoder
89 | // based on the debug_no_sleep signal from the controller.
90 | assign core_sleep_o = fetch_enable_q && !clock_en;
91 |
92 | always_ff @(posedge clk_ungated_i, negedge rst_n)
93 | begin
94 | if (rst_n == 1'b0) begin
95 | core_busy_q <= 1'b0;
96 | fetch_enable_q <= 1'b0;
97 | end else begin
98 | core_busy_q <= core_busy_d;
99 | fetch_enable_q <= fetch_enable_d;
100 | end
101 | end
102 |
103 | // Fetch enable for Controller
104 | assign fetch_enable_o = fetch_enable_q;
105 |
106 | // Main clock gate of CV32E40P
107 | cv32e40s_clock_gate
108 | #(.LIB (LIB))
109 | core_clock_gate_i
110 | (
111 | .clk_i ( clk_ungated_i ),
112 | .en_i ( clock_en ),
113 | .scan_cg_en_i ( scan_cg_en_i ),
114 | .clk_o ( clk_gated_o )
115 | );
116 |
117 | endmodule
118 |
--------------------------------------------------------------------------------
/sva/cv32e40s_instr_obi_interface_sva.sv:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Silicon Labs, Inc.
2 | //
3 | // This file, and derivatives thereof are licensed under the
4 | // Solderpad License, Version 2.0 (the "License");
5 | // Use of this file means you agree to the terms and conditions
6 | // of the license and are in full compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // https://solderpad.org/licenses/SHL-2.0/
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // and hardware implementations thereof
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESSED OR IMPLIED.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 | ////////////////////////////////////////////////////////////////////////////////
19 | // //
20 | // Authors: Oystein Knauserud - oystein.knauserud@silabs.com //
21 | // //
22 | // Description: RTL assertions for the instr_obi_interface module //
23 | // //
24 | ////////////////////////////////////////////////////////////////////////////////
25 |
26 | module cv32e40s_instr_obi_interface_sva
27 | import uvm_pkg::*;
28 | import cv32e40s_pkg::*;
29 | (
30 | input logic clk,
31 | input logic rst_n,
32 | cv32e40s_if_c_obi.monitor m_c_obi_instr_if,
33 | input logic gntpar_err,
34 | input logic gntpar_err_q,
35 | input obi_inst_resp_t resp_o,
36 | input logic gntpar_err_resp
37 | );
38 |
39 | // Support logic (FIFO) to track grant parity fault
40 |
41 | localparam MAX_OUTSTND_TXN = 5; // This needs to be larger (or equal) to the max outstanding transactions in IF and LSU
42 |
43 | typedef enum logic [1:0] {GNT_ERR, GNT_NOERR, GNT_NONE} gnt_err_chck_e;
44 | typedef enum logic [1:0] {INT, NOINT, INT_NONE} integrity_e;
45 | logic exp_int;
46 | logic exp_gnt_err;
47 | logic [$clog2(MAX_OUTSTND_TXN)-1:0] oldest_txn;
48 |
49 | gnt_err_chck_e [MAX_OUTSTND_TXN-1:0] gnt_fifo_q;
50 | gnt_err_chck_e [MAX_OUTSTND_TXN-1:0] gnt_fifo_n;
51 | gnt_err_chck_e [MAX_OUTSTND_TXN-1:0] gnt_fifo_tmp;
52 |
53 | integrity_e [MAX_OUTSTND_TXN-1:0] int_fifo_q;
54 | integrity_e [MAX_OUTSTND_TXN-1:0] int_fifo_n;
55 | integrity_e [MAX_OUTSTND_TXN-1:0] int_fifo_tmp;
56 |
57 | always_comb begin
58 | gnt_fifo_n = gnt_fifo_q;
59 | gnt_fifo_tmp = gnt_fifo_q;
60 | int_fifo_n = int_fifo_q;
61 | int_fifo_tmp = int_fifo_q;
62 | casez ({m_c_obi_instr_if.s_req.req, m_c_obi_instr_if.s_gnt.gnt, m_c_obi_instr_if.s_rvalid.rvalid})
63 | 3'b110: begin
64 | // Accepted address phase, add one entry to FIFO
65 | gnt_fifo_n = (gntpar_err || gntpar_err_q) ?
66 | {gnt_fifo_q[MAX_OUTSTND_TXN-2:0], GNT_ERR} :
67 | {gnt_fifo_q[MAX_OUTSTND_TXN-2:0], GNT_NOERR};
68 |
69 | int_fifo_n = m_c_obi_instr_if.req_payload.integrity ?
70 | {int_fifo_q[MAX_OUTSTND_TXN-2:0], INT} :
71 | {int_fifo_q[MAX_OUTSTND_TXN-2:0], NOINT};
72 | end
73 | 3'b0?1, 3'b?01: begin
74 | // Response phase, remove oldest entry from FIFO
75 | gnt_fifo_n[oldest_txn] = GNT_NONE;
76 |
77 | int_fifo_n[oldest_txn] = INT_NONE;
78 | end
79 | 3'b111: begin
80 | // Accepted address phase and response phase. Clear oldest transaction and add new to FIFO
81 | gnt_fifo_tmp[oldest_txn] = GNT_NONE;
82 | gnt_fifo_n = (gntpar_err || gntpar_err_q) ?
83 | {gnt_fifo_tmp[MAX_OUTSTND_TXN-2:0], GNT_ERR} :
84 | {gnt_fifo_tmp[MAX_OUTSTND_TXN-2:0], GNT_NOERR};
85 |
86 | int_fifo_tmp[oldest_txn] = INT_NONE;
87 | int_fifo_n = m_c_obi_instr_if.req_payload.integrity ?
88 | {int_fifo_tmp[MAX_OUTSTND_TXN-2:0], INT} :
89 | {int_fifo_tmp[MAX_OUTSTND_TXN-2:0], NOINT};
90 | end
91 | default; // Do nothing
92 | endcase
93 | end
94 |
95 | // FIFO
96 | always_ff @ (posedge clk, negedge rst_n) begin
97 | if (!rst_n) begin
98 | gnt_fifo_q <= {MAX_OUTSTND_TXN{GNT_NONE}};
99 | int_fifo_q <= {MAX_OUTSTND_TXN{INT_NONE}};
100 | end
101 | else begin
102 | gnt_fifo_q <= gnt_fifo_n;
103 | int_fifo_q <= int_fifo_n;
104 | end
105 | end
106 |
107 | // Locate oldest entry in FIFO
108 | // FIFOs for gnt error and integrity bit operate on the same control signals,
109 | // picking oldest index from gnt fifo.
110 | always_comb begin
111 | oldest_txn = '0;
112 | for (int i = 0; i < MAX_OUTSTND_TXN; i++) begin
113 | if (gnt_fifo_q[i] != GNT_NONE) begin
114 | oldest_txn = i;
115 | end
116 | end
117 | end
118 |
119 | // GNT error from the oldest transaction
120 | assign exp_gnt_err = (gnt_fifo_q[oldest_txn] == GNT_ERR);
121 |
122 | // Assert that grant error bit comes out in order
123 | a_instr_obi_gnt_fifo :
124 | assert property (@(posedge clk) disable iff (!rst_n)
125 | m_c_obi_instr_if.s_rvalid.rvalid |-> exp_gnt_err == gntpar_err_resp)
126 | else `uvm_error("mpu", "GNT error bit not correct")
127 |
128 |
129 | // GNT error from the oldest transaction
130 | assign exp_int = (int_fifo_q[oldest_txn] == INT);
131 |
132 | // Assert that trans integrity bit comes out in order
133 | a_instr_obi_int_fifo :
134 | assert property (@(posedge clk) disable iff (!rst_n)
135 | m_c_obi_instr_if.s_rvalid.rvalid |-> exp_int == resp_o.integrity)
136 | else `uvm_error("mpu", "Integrity bit not correct")
137 | endmodule
138 |
--------------------------------------------------------------------------------
/sva/cv32e40s_clic_int_controller_sva.sv:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Silicon Labs, Inc.
2 | //
3 | // This file, and derivatives thereof are licensed under the
4 | // Solderpad License, Version 2.0 (the "License").
5 | //
6 | // Use of this file means you agree to the terms and conditions
7 | // of the license and are in full compliance with the License.
8 | //
9 | // You may obtain a copy of the License at:
10 | //
11 | // https://solderpad.org/licenses/SHL-2.0/
12 | //
13 | // Unless required by applicable law or agreed to in writing, software
14 | // and hardware implementations thereof distributed under the License
15 | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
16 | // OF ANY KIND, EITHER EXPRESSED OR IMPLIED.
17 | //
18 | // See the License for the specific language governing permissions and
19 | // limitations under the License.
20 |
21 | ////////////////////////////////////////////////////////////////////////////////
22 | // Engineer: Øystein Knauserud - oystein.knauserud@silabs.com //
23 | // //
24 | // Design Name: cv32e40s_clic_int_controller_sva //
25 | // Project Name: CV32E40S //
26 | // Language: SystemVerilog //
27 | // //
28 | // Description: Assertions reltated to the CLIC interrupt controller //
29 | // //
30 | ////////////////////////////////////////////////////////////////////////////////
31 |
32 | module cv32e40s_clic_int_controller_sva
33 | import uvm_pkg::*;
34 | import cv32e40s_pkg::*;
35 | (
36 | input logic clk,
37 | input logic rst_n,
38 |
39 | input logic irq_req_ctrl_o,
40 | input logic clic_irq_q,
41 | input logic [7:0] clic_irq_level_q,
42 |
43 | input logic global_irq_enable,
44 | input logic irq_wu_ctrl_o,
45 |
46 | input logic ctrl_pending_interrupt,
47 | input logic ctrl_interrupt_allowed,
48 | input logic ctrl_pending_nmi,
49 | input logic ctrl_pending_async_debug,
50 | input ctrl_state_e ctrl_fsm_cs,
51 |
52 | input ctrl_fsm_t ctrl_fsm,
53 | input dcsr_t dcsr,
54 |
55 | input ex_wb_pipe_t ex_wb_pipe_i,
56 | input logic last_op_wb_i
57 | );
58 |
59 | // Check that a pending interrupt is taken as soon as possible after being enabled
60 | property p_clic_enable;
61 | @(posedge clk) disable iff (!rst_n)
62 | ( !irq_req_ctrl_o
63 | ##1
64 | irq_req_ctrl_o && $stable(clic_irq_q) && $stable(clic_irq_level_q) && !(ctrl_fsm.debug_mode || (dcsr.step && !dcsr.stepie))
65 | |->
66 | ((ctrl_pending_interrupt && ctrl_interrupt_allowed) || // Interrupt pendinding and allowed to be taken
67 | ($past(ex_wb_pipe_i.instr_valid) && $past(ex_wb_pipe_i.sys_en) && $past(ex_wb_pipe_i.sys_mret_insn) && !$past(last_op_wb_i)) &&
68 | (ctrl_pending_interrupt && !ctrl_interrupt_allowed)) // Interrupts enabled by mret mid-sequence, not allowed to be taken
69 | );
70 | endproperty;
71 |
72 | a_clic_enable: assert property(p_clic_enable)
73 | else `uvm_error("clic_int_controller", "Interrupt not taken soon enough after enabling");
74 |
75 | // Check that only NMI and external debug take presedence over interrupts after being enabled by mret or CSR writes
76 | property p_irq_pri;
77 | @(posedge clk) disable iff (!rst_n)
78 | ( !irq_req_ctrl_o // No interrupt pending
79 | ##1 // Next cycle
80 | irq_req_ctrl_o && $stable(clic_irq_q) && $stable(clic_irq_level_q) && !(ctrl_fsm.debug_mode || (dcsr.step && !dcsr.stepie)) && // Interrupt pending but irq inputs are unchanged
81 | (ctrl_fsm_cs != DEBUG_TAKEN) && // Make sure we are not handling a debug entry already (could be a single stepped mret enabling interrupts for instance)
82 | !(ctrl_pending_nmi || ctrl_pending_async_debug) && // No pending events with higher priority than interrupts are taking place
83 | ctrl_interrupt_allowed // and interrupts are allowed (mret which restarts pointer fetch may reenable interrupts before the sequence is finished)
84 | |->
85 | ctrl_fsm.irq_ack // We must take the interrupt if enabled (mret or CSR write) and no NMI or external debug is pending
86 | );
87 | endproperty;
88 |
89 | a_irq_pri: assert property(p_irq_pri)
90 | else `uvm_error("clic_int_controller", "Interrupt not taken soon enough after enabling")
91 |
92 | // Check a pending interrupt that is disabled is actually not taken
93 | property p_clic_disable;
94 | @(posedge clk) disable iff (!rst_n)
95 | ( irq_req_ctrl_o
96 | ##1
97 | !irq_req_ctrl_o && $stable(clic_irq_q) && $stable(clic_irq_level_q)
98 | |-> !(ctrl_pending_interrupt && ctrl_interrupt_allowed));
99 | endproperty;
100 |
101 | a_clic_disable: assert property(p_clic_disable)
102 | else `uvm_error("clic_int_controller", "Interrupt taken after disabling");
103 |
104 | // If an interrupt wakeup is signalled while the core is in the SLEEP state, an interrupt
105 | // request must be asserted in the next cycle if the signal global_irq_enable is set.
106 | property p_req_after_wake;
107 | @(posedge clk) disable iff (!rst_n)
108 | ( (ctrl_fsm_cs == SLEEP) && // Core is in sleep state
109 | irq_wu_ctrl_o // Wakeup requested
110 | |=>
111 | (irq_req_ctrl_o) // interrupts must be requested
112 | or
113 | (!irq_req_ctrl_o && !global_irq_enable)); // unless interrupts are not enabled
114 | endproperty;
115 |
116 | a_req_after_wake: assert property(p_req_after_wake)
117 | else `uvm_error("clic_int_controller", "No request after wakeup signal");
118 |
119 | endmodule
120 |
121 |
--------------------------------------------------------------------------------
/sva/cv32e40s_register_file_sva.sv:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Silicon Labs, Inc.
2 | //
3 | // This file, and derivatives thereof are licensed under the
4 | // Solderpad License, Version 2.0 (the "License").
5 | //
6 | // Use of this file means you agree to the terms and conditions
7 | // of the license and are in full compliance with the License.
8 | //
9 | // You may obtain a copy of the License at:
10 | //
11 | // https://solderpad.org/licenses/SHL-2.0/
12 | //
13 | // Unless required by applicable law or agreed to in writing, software
14 | // and hardware implementations thereof distributed under the License
15 | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
16 | // OF ANY KIND, EITHER EXPRESSED OR IMPLIED.
17 | //
18 | // See the License for the specific language governing permissions and
19 | // limitations under the License.
20 |
21 | ////////////////////////////////////////////////////////////////////////////////
22 | // Engineer: Halfdan Bechmann - halfdan.bechmann@silabs.com //
23 | // //
24 | // Description: RTL assertions for the register file //
25 | // //
26 | ////////////////////////////////////////////////////////////////////////////////
27 |
28 |
29 | module cv32e40s_register_file_sva
30 | import uvm_pkg::*;
31 | import cv32e40s_pkg::*;
32 | #(
33 | parameter int unsigned REGFILE_NUM_READ_PORTS = 2,
34 | parameter int unsigned REGFILE_NUM_WORDS = 32,
35 | parameter rv32_e RV32 = RV32I
36 | )
37 | (
38 | input logic clk,
39 | input logic rst_n,
40 | input rf_addr_t waddr_i [REGFILE_NUM_WRITE_PORTS],
41 | input logic we_i [REGFILE_NUM_WRITE_PORTS],
42 | input logic [REGFILE_WORD_WIDTH-1:0] wdata_i [REGFILE_NUM_WRITE_PORTS],
43 | input logic [REGFILE_WORD_WIDTH-1:0] rdata_o [REGFILE_NUM_READ_PORTS],
44 | input logic [REGFILE_WORD_WIDTH-1:0] mem_gated [REGFILE_NUM_WORDS],
45 | input logic [REGFILE_WORD_WIDTH-1:0] mem [REGFILE_NUM_WORDS],
46 | input logic dummy_instr_wb_i,
47 | input logic hint_instr_wb_i
48 | );
49 |
50 | function bit check_ecc_syndrome (logic [REGFILE_WORD_WIDTH-1:0] data);
51 | return ((1'b0 === ^(data & 38'b00_0001_0101_0110_1010_1010_1010_1101_0101_1011)) &&
52 | (1'b1 === ^(data & 38'b00_0010_1001_1011_0011_0011_0011_0110_0110_1101)) &&
53 | (1'b0 === ^(data & 38'b00_0100_1110_0011_1100_0011_1100_0111_1000_1110)) &&
54 | (1'b1 === ^(data & 38'b00_1000_0000_0011_1111_1100_0000_0111_1111_0000)) &&
55 | (1'b0 === ^(data & 38'b01_0000_0000_0011_1111_1111_1111_1000_0000_0000)) &&
56 | (1'b1 === ^(data & 38'b10_0000_1111_1100_0000_0000_0000_0000_0000_0000)) );
57 | endfunction
58 |
59 | generate
60 | if (SECURE) begin
61 | // This section contains Helper assertion for increased performance in multi-property formal solvers
62 |
63 | for (genvar rf_wp = 0; rf_wp < REGFILE_NUM_WRITE_PORTS; rf_wp++) begin
64 | // Check write port ECC
65 | a_check_wdata_ecc:
66 | assert property (@(posedge clk) disable iff (!rst_n)
67 | check_ecc_syndrome(wdata_i[rf_wp]))
68 | else `uvm_error("register_file", $sformatf("ECC error on write port %d", rf_wp))
69 | end
70 |
71 | for (genvar rf_rp = 0; rf_rp < REGFILE_NUM_READ_PORTS; rf_rp++) begin
72 | a_check_rdata_source_ecc_helper:
73 |
74 | assert property (@(posedge clk) disable iff (!rst_n)
75 | (rdata_o[rf_rp] inside {mem_gated}))
76 | else `uvm_error("register_file", "Rdata not in memory")
77 |
78 | // Check read port ECC
79 | a_check_rdata_ecc:
80 | assert property (@(posedge clk) disable iff (!rst_n)
81 | check_ecc_syndrome(rdata_o[rf_rp]))
82 | else `uvm_error("register_file", $sformatf("ECC error on read port %d", rf_rp))
83 |
84 | end
85 |
86 | a_check_reg0_mem_ecc_helper:
87 | assert property (@(posedge clk) disable iff (!rst_n)
88 | check_ecc_syndrome(mem[0]))
89 | else `uvm_error("register_file", "register 0 ecc err")
90 |
91 | // The mem side mux on mem_gated[0] is a bottelneck for solving the read port assertions
92 | a_check_reg0_mem_gated_ecc_helper:
93 | assert property (@(posedge clk) disable iff (!rst_n)
94 | (mem_gated[0] === mem[0]) |-> check_ecc_syndrome(mem_gated[0]))
95 | else `uvm_error("register_file", "register 0 ecc err")
96 |
97 | for (genvar i = 0; i < REGFILE_NUM_WORDS; i++) begin
98 | // Check ecc syndrome for all registers
99 | a_check_mem_gated_ecc:
100 | assert property (@(posedge clk) disable iff (!rst_n)
101 | check_ecc_syndrome(mem_gated[i]))
102 | else `uvm_error("register_file", $sformatf("ECC error for register word x%d", i))
103 | end
104 |
105 | // If no dummy is in WB, mem[0] shall remain stable
106 | a_stable_x0_nondummy:
107 | assert property (@(posedge clk) disable iff (!rst_n)
108 | !(dummy_instr_wb_i || hint_instr_wb_i) |=> $stable(mem[0]))
109 | else `uvm_error("register file", "mem[0] changed for non-dummy/hint instruction")
110 |
111 | end
112 |
113 | endgenerate
114 |
115 | generate
116 | if(RV32 == RV32E) begin: a_rv32e
117 |
118 | a_rf_we_illegal :
119 | assert property (@(posedge clk) disable iff (!rst_n)
120 | we_i[0] |-> waddr_i[0] <= 15)
121 | else `uvm_error("regiter_file", "Write to GPR > 15 with RV32E")
122 |
123 | end
124 | endgenerate
125 |
126 | endmodule : cv32e40s_register_file_sva
127 |
128 |
--------------------------------------------------------------------------------
/bhv/include/cv32e40s_rvfi_pkg.sv:
--------------------------------------------------------------------------------
1 | // Copyright (c) 2020 OpenHW Group
2 | //
3 | // Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License");
4 | // you may not use this file except in compliance with the License.
5 | // You may obtain a copy of the License at
6 | //
7 | // https://solderpad.org/licenses/
8 | //
9 | // Unless required by applicable law or agreed to in writing, software
10 | // distributed under the License is distributed on an "AS IS" BASIS,
11 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | // See the License for the specific language governing permissions and
13 | // limitations under the License.
14 | //
15 | // SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0
16 |
17 | // Includes to print info about the RVFI output
18 | // Contributors: Davide Schiavone
19 | // Halfdan Bechmann
20 |
21 | package cv32e40s_rvfi_pkg;
22 | import cv32e40s_pkg::*;
23 |
24 | parameter STAGE_IF = 0;
25 | parameter STAGE_ID = 1;
26 | parameter STAGE_EX = 2;
27 | parameter STAGE_WB = 3;
28 | parameter STAGE_WB_PAST = 4;
29 |
30 | parameter NMEM = 128;
31 |
32 | typedef enum logic [1:0] { // Memory error types
33 | MEM_ERR_PMP = 2'h2,
34 | MEM_ERR_ATOMIC = 2'h1,
35 | MEM_ERR_IO_ALIGN = 2'h0,
36 | MEM_ERR_ATOMIC_MISALIGN = 2'h3
37 | } mem_err_t;
38 |
39 | typedef struct packed { // Autonomously updated CSRs
40 | logic [31:0] mcycle;
41 | logic [31:0] mcycleh;
42 | logic [31:0] cycle;
43 | logic [31:0] cycleh;
44 | logic [31:0] mip;
45 | logic nmip;
46 | } rvfi_auto_csr_map_t;
47 |
48 | typedef struct packed {
49 | logic [31:0] jvt;
50 | logic [31:0] mstatus;
51 | logic [31:0] misa;
52 | logic [31:0] mie;
53 | logic [31:0] mtvec;
54 | logic [31:0] mstatush;
55 | logic [31:0] mtvt;
56 | logic [31:0] mcountinhibit;
57 | logic [31:0] [31:0] mhpmevent;
58 | logic [31:0] mscratch;
59 | logic [31:0] mepc;
60 | logic [31:0] mcause;
61 | logic [31:0] mtval;
62 | logic [31:0] mip;
63 | logic [31:0] mnxti;
64 | logic [31:0] mintstatus;
65 | logic [31:0] mintthresh;
66 | logic [31:0] mscratchcsw;
67 | logic [31:0] mscratchcswl;
68 | logic [31:0] tselect;
69 | logic [ 2:0] [31:0] tdata;
70 | logic [31:0] tinfo;
71 | logic [31:0] dcsr;
72 | logic [31:0] dpc;
73 | logic [ 1:0] [31:0] dscratch;
74 | logic [31:0] mcycle;
75 | logic [31:0] minstret;
76 | logic [31:0] [31:0] mhpmcounter;
77 | logic [31:0] mcycleh;
78 | logic [31:0] minstreth;
79 | logic [31:0] [31:0] mhpmcounterh;
80 | logic [31:0] cycle;
81 | logic [31:0] instret;
82 | logic [31:0] [31:0] hpmcounter;
83 | logic [31:0] cycleh;
84 | logic [31:0] instreth;
85 | logic [31:0] [31:0] hpmcounterh;
86 | logic [31:0] mvendorid;
87 | logic [31:0] marchid;
88 | logic [31:0] mimpid;
89 | logic [31:0] mhartid;
90 | logic [31:0] mcounteren;
91 | logic [PMP_MAX_REGIONS/4-1:0] [31:0] pmpcfg;
92 | logic [PMP_MAX_REGIONS-1:0] [31:0] pmpaddr;
93 | logic [31:0] mseccfg;
94 | logic [31:0] mseccfgh;
95 | logic [31:0] mconfigptr;
96 | logic [31:0] menvcfg;
97 | logic [31:0] menvcfgh;
98 | logic [31:0] cpuctrl;
99 | logic [31:0] secureseed0;
100 | logic [31:0] secureseed1;
101 | logic [31:0] secureseed2;
102 | logic [31:0] mstateen0;
103 | logic [31:0] mstateen1;
104 | logic [31:0] mstateen2;
105 | logic [31:0] mstateen3;
106 | logic [31:0] mstateen0h;
107 | logic [31:0] mstateen1h;
108 | logic [31:0] mstateen2h;
109 | logic [31:0] mstateen3h;
110 |
111 | } rvfi_csr_map_t;
112 |
113 | typedef struct packed {
114 | logic [10:0] cause;
115 | logic interrupt;
116 | logic exception;
117 | logic intr;
118 | } rvfi_intr_t;
119 |
120 | typedef struct packed {
121 | logic clicptr;
122 | logic [1:0] cause_type;
123 | logic [2:0] debug_cause;
124 | logic [5:0] exception_cause;
125 | logic debug;
126 | logic exception;
127 | logic trap;
128 | } rvfi_trap_t;
129 |
130 | typedef struct packed {
131 | obi_inst_req_t req_payload;
132 | inst_resp_t resp_payload;
133 | logic pmp_err;
134 | } rvfi_obi_instr_t;
135 |
136 | // Trace struct, used in cv32e40s_rvfi_sim_trace
137 | typedef struct packed {
138 | bit [32*16-1:0] c_file;
139 | bit [32*16-1:0] c_func;
140 | int c_line;
141 | logic [31:0] addr;
142 | logic [31:0] mcode;
143 | bit [32*16-1:0] asm;
144 | } trace_t;
145 |
146 | endpackage
147 |
148 |
--------------------------------------------------------------------------------
/rtl/cv32e40s_m_decoder.sv:
--------------------------------------------------------------------------------
1 | // Copyright 2018 ETH Zurich and University of Bologna.
2 | // Copyright and related rights are licensed under the Solderpad Hardware
3 | // License, Version 0.51 (the "License"); you may not use this file except in
4 | // compliance with the License. You may obtain a copy of the License at
5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
6 | // or agreed to in writing, software, hardware and materials distributed under
7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
9 | // specific language governing permissions and limitations under the License.
10 |
11 | ////////////////////////////////////////////////////////////////////////////////
12 | // Engineer Andreas Traber - atraber@iis.ee.ethz.ch //
13 | // //
14 | // Additional contributions by: //
15 | // Matthias Baer - baermatt@student.ethz.ch //
16 | // Igor Loi - igor.loi@unibo.it //
17 | // Sven Stucki - svstucki@student.ethz.ch //
18 | // Davide Schiavone - pschiavo@iis.ee.ethz.ch //
19 | // Oivind Ekelund - oivind.ekelund@silabs.com //
20 | // //
21 | // Design Name: M Decoder //
22 | // Project Name: RI5CY //
23 | // Language: SystemVerilog //
24 | // //
25 | // Description: Decoder for the RV32M extension //
26 | // //
27 | ////////////////////////////////////////////////////////////////////////////////
28 |
29 | module cv32e40s_m_decoder import cv32e40s_pkg::*;
30 | #(
31 | parameter m_ext_e M_EXT = M
32 | )
33 | (
34 | // from IF/ID pipeline
35 | input logic [31:0] instr_rdata_i,
36 | output decoder_ctrl_t decoder_ctrl_o
37 | );
38 |
39 | always_comb
40 | begin
41 |
42 | // Default assignments
43 | decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
44 | decoder_ctrl_o.illegal_insn = 1'b0;
45 |
46 | unique case (instr_rdata_i[6:0])
47 |
48 | OPCODE_OP: begin
49 |
50 | // Common signals for all MUL/DIV
51 | decoder_ctrl_o.rf_we = 1'b1;
52 | decoder_ctrl_o.rf_re[0] = 1'b1;
53 | decoder_ctrl_o.rf_re[1] = 1'b1;
54 |
55 | // Multiplier and divider has its own operand registers.
56 | // Settings will be overruled for div(u) and rem(u) which rely on ALU.
57 | decoder_ctrl_o.alu_op_a_mux_sel = OP_A_NONE;
58 | decoder_ctrl_o.alu_op_b_mux_sel = OP_B_NONE;
59 | decoder_ctrl_o.op_c_mux_sel = OP_C_NONE;
60 |
61 | unique case ({instr_rdata_i[31:25], instr_rdata_i[14:12]})
62 | // supported RV32M instructions
63 | {7'b000_0001, 3'b000}: begin // mul
64 | decoder_ctrl_o.mul_en = 1'b1;
65 | decoder_ctrl_o.mul_operator = MUL_M32;
66 | end
67 | {7'b000_0001, 3'b001}: begin // mulh
68 | decoder_ctrl_o.mul_en = 1'b1;
69 | decoder_ctrl_o.mul_signed_mode = 2'b11;
70 | decoder_ctrl_o.mul_operator = MUL_H;
71 | end
72 | {7'b000_0001, 3'b010}: begin // mulhsu
73 | decoder_ctrl_o.mul_en = 1'b1;
74 | decoder_ctrl_o.mul_signed_mode = 2'b01;
75 | decoder_ctrl_o.mul_operator = MUL_H;
76 | end
77 | {7'b000_0001, 3'b011}: begin // mulhu
78 | decoder_ctrl_o.mul_en = 1'b1;
79 | decoder_ctrl_o.mul_signed_mode = 2'b00;
80 | decoder_ctrl_o.mul_operator = MUL_H;
81 | end
82 | {7'b000_0001, 3'b100}: begin // div
83 | if (M_EXT == M) begin
84 | decoder_ctrl_o.div_en = 1'b1;
85 | decoder_ctrl_o.div_operator = DIV_DIV;
86 | decoder_ctrl_o.alu_operator = ALU_SLL;
87 | end else begin
88 | decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
89 | end
90 | end
91 | {7'b000_0001, 3'b101}: begin // divu
92 | if (M_EXT == M) begin
93 | decoder_ctrl_o.div_en = 1'b1;
94 | decoder_ctrl_o.div_operator = DIV_DIVU;
95 | decoder_ctrl_o.alu_operator = ALU_SLL;
96 | end else begin
97 | decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
98 | end
99 | end
100 | {7'b000_0001, 3'b110}: begin // rem
101 | if (M_EXT == M) begin
102 | decoder_ctrl_o.div_en = 1'b1;
103 | decoder_ctrl_o.div_operator = DIV_REM;
104 | decoder_ctrl_o.alu_operator = ALU_SLL;
105 | end else begin
106 | decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
107 | end
108 | end
109 | {7'b000_0001, 3'b111}: begin // remu
110 | if (M_EXT == M) begin
111 | decoder_ctrl_o.div_en = 1'b1;
112 | decoder_ctrl_o.div_operator = DIV_REMU;
113 | decoder_ctrl_o.alu_operator = ALU_SLL;
114 | end else begin
115 | decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
116 | end
117 | end
118 |
119 | default: begin
120 | // No match
121 | decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
122 | end
123 | endcase
124 |
125 | end // case: OPCODE_OP
126 |
127 | default: begin
128 | // No match
129 | decoder_ctrl_o = DECODER_CTRL_ILLEGAL_INSN;
130 | end
131 |
132 | endcase // unique case (instr_rdata_i[6:0])
133 |
134 | end // always_comb
135 |
136 | endmodule
137 |
--------------------------------------------------------------------------------
/sva/cv32e40s_sleep_unit_sva.sv:
--------------------------------------------------------------------------------
1 | // Copyright 2020 Silicon Labs, Inc.
2 | //
3 | // This file, and derivatives thereof are licensed under the
4 | // Solderpad License, Version 2.0 (the "License").
5 | //
6 | // Use of this file means you agree to the terms and conditions
7 | // of the license and are in full compliance with the License.
8 | //
9 | // You may obtain a copy of the License at:
10 | //
11 | // https://solderpad.org/licenses/SHL-2.0/
12 | //
13 | // Unless required by applicable law or agreed to in writing, software
14 | // and hardware implementations thereof distributed under the License
15 | // is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
16 | // OF ANY KIND, EITHER EXPRESSED OR IMPLIED.
17 | //
18 | // See the License for the specific language governing permissions and
19 | // limitations under the License.
20 |
21 | ////////////////////////////////////////////////////////////////////////////////
22 | // //
23 | // Authors: Arjan Bink - arjan.bink@silabs.com //
24 | // Halfdan Bechmann - halfdan.bechmann@silabs.com //
25 | // //
26 | // Description: RTL assertions for the sleep_unit module //
27 | // //
28 | ////////////////////////////////////////////////////////////////////////////////
29 |
30 | module cv32e40s_sleep_unit_sva
31 | import uvm_pkg::*;
32 | import cv32e40s_pkg::*;
33 | (
34 | input logic clk_ungated_i,
35 | input logic rst_n,
36 | input logic clock_en,
37 | input logic core_busy_d,
38 | input logic core_busy_q,
39 | input logic core_sleep_o,
40 | input logic fetch_enable_d,
41 | input logic fetch_enable_q,
42 | input ctrl_state_e ctrl_fsm_cs,
43 | input ctrl_state_e ctrl_fsm_ns
44 | );
45 |
46 | // Clock gate is disabled during RESET state of the controller
47 | property p_clock_en_0;
48 | @(posedge clk_ungated_i) disable iff (!rst_n)
49 | ((ctrl_fsm_cs == RESET) && (ctrl_fsm_ns == RESET)) |-> (clock_en == 1'b0);
50 | endproperty
51 |
52 | a_clock_en_0 : assert property(p_clock_en_0) else `uvm_error("sleep_unit", "Assertion a_clock_en_0 failed")
53 |
54 | // Clock gate is enabled when exit from RESET state is required
55 | property p_clock_en_1;
56 | @(posedge clk_ungated_i) disable iff (!rst_n)
57 | ((ctrl_fsm_cs == RESET) && (ctrl_fsm_ns != RESET)) |-> (clock_en == 1'b1);
58 | endproperty
59 |
60 | a_clock_en_1 : assert property(p_clock_en_1) else `uvm_error("sleep_unit", "Assertion a_clock_en_1 failed")
61 |
62 | // Clock gate is not enabled before receiving fetch_enable_i pulse
63 | property p_clock_en_2;
64 | @(posedge clk_ungated_i) disable iff (!rst_n) (fetch_enable_q == 1'b0) |-> (clock_en == 1'b0);
65 | endproperty
66 |
67 | a_clock_en_2 : assert property(p_clock_en_2) else `uvm_error("sleep_unit", "Assertion a_clock_en_2 failed")
68 |
69 |
70 |
71 | // Clock gate is only possibly disabled in RESET or SLEEP
72 | property p_clock_en_4;
73 | @(posedge clk_ungated_i) disable iff (!rst_n)
74 | (clock_en == 1'b0) -> ((ctrl_fsm_cs == RESET) || (ctrl_fsm_ns == SLEEP));
75 | endproperty
76 |
77 | a_clock_en_4 : assert property(p_clock_en_4) else `uvm_error("sleep_unit", "Assertion a_clock_en_4 failed")
78 |
79 | // Clock gate is enabled when exit from SLEEP state is required
80 | property p_clock_en_5;
81 | @(posedge clk_ungated_i) disable iff (!rst_n)
82 | ((ctrl_fsm_cs == SLEEP) && (ctrl_fsm_ns != SLEEP)) |-> (clock_en == 1'b1);
83 | endproperty
84 |
85 | a_clock_en_5 : assert property(p_clock_en_5) else `uvm_error("sleep_unit", "Assertion a_clock_en_5 failed")
86 |
87 | // Core sleep is only signaled in SLEEP state
88 | property p_core_sleep;
89 | @(posedge clk_ungated_i) disable iff (!rst_n)
90 | (core_sleep_o == 1'b1) -> ((ctrl_fsm_cs == cv32e40s_pkg::SLEEP));
91 | endproperty
92 |
93 | a_core_sleep : assert property(p_core_sleep) else `uvm_error("sleep_unit", "Assertion a_core_sleep failed")
94 |
95 | // Core can only become non-busy due to SLEEP entry
96 | property p_non_busy;
97 | @(posedge clk_ungated_i) disable iff (!rst_n)
98 | (core_busy_d == 1'b0) |-> /*(ctrl_fsm_cs == WAIT_SLEEP) ||*/ (ctrl_fsm_cs == SLEEP);
99 | endproperty
100 |
101 | a_non_busy : assert property(p_non_busy) else `uvm_error("sleep_unit", "Assertion a_non_busy failed")
102 |
103 | // During sleep it should be allowed to externally gate clk_i
104 | property p_gate_clk_i;
105 | @(posedge clk_ungated_i) disable iff (!rst_n)
106 | (core_sleep_o == 1'b1) |-> (core_busy_q == core_busy_d) && (fetch_enable_q == fetch_enable_d);
107 | endproperty
108 |
109 | a_gate_clk_i : assert property(p_gate_clk_i) else `uvm_error("sleep_unit", "Assertion a_gate_clk_i failed")
110 |
111 | // During sleep the internal clock is gated
112 | property p_gate_clock_during_sleep;
113 | @(posedge clk_ungated_i) disable iff (!rst_n)
114 | (core_sleep_o == 1'b1) |-> (clock_en == 1'b0);
115 | endproperty
116 |
117 | a_gate_clock_during_sleep : assert property(p_gate_clock_during_sleep)
118 | else `uvm_error("sleep_unit", "Assertion a_gate_clock_during_sleep failed")
119 |
120 | // Sleep mode can only be entered in response to a WFI or WFE instruction
121 | property p_only_sleep_for_wfi_wfe;
122 | @(posedge clk_ungated_i) disable iff (!rst_n)
123 | (core_sleep_o == 1'b1) |-> (wb_stage_i.ex_wb_pipe_i.instr.bus_resp.rdata == { 12'b000100000101, 13'b0, OPCODE_SYSTEM } ||
124 | (wb_stage_i.ex_wb_pipe_i.instr.bus_resp.rdata == { 6'b100011, 11'b00000000000, 3'b000, 5'b00000, OPCODE_SYSTEM }));
125 | endproperty
126 |
127 | a_only_sleep_for_wfi_wfe : assert property(p_only_sleep_for_wfi_wfe)
128 | else `uvm_error("sleep_unit", "Assertion a_only_sleep_for_wfi_wfe failed")
129 |
130 | // In sleep mode the core will not be busy (e.g. no ongoing/outstanding instruction or data transactions)
131 | property p_not_busy_during_sleep;
132 | @(posedge clk_ungated_i) disable iff (!rst_n) (core_sleep_o == 1'b1) |-> ((core_busy_q == 1'b0) && (core_busy_d == 1'b0));
133 | endproperty
134 |
135 | a_not_busy_during_sleep : assert property(p_not_busy_during_sleep)
136 | else `uvm_error("sleep_unit", "Assertion a_not_busy_during_sleep failed")
137 |
138 | endmodule // cv32e40s_sleep_unit_sva
139 |
140 |
--------------------------------------------------------------------------------
/rtl/cv32e40s_int_controller.sv:
--------------------------------------------------------------------------------
1 | // Copyright 2018 ETH Zurich and University of Bologna.
2 | // Copyright and related rights are licensed under the Solderpad Hardware
3 | // License, Version 0.51 (the "License"); you may not use this file except in
4 | // compliance with the License. You may obtain a copy of the License at
5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
6 | // or agreed to in writing, software, hardware and materials distributed under
7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
9 | // specific language governing permissions and limitations under the License.
10 |
11 | ////////////////////////////////////////////////////////////////////////////////
12 | // Engineer: Davide Schiavone - pschiavo@iis.ee.ethz.ch //
13 | // //
14 | // Additional contributions by: //
15 | // //
16 | // Design Name: Interrupt Controller //
17 | // Project Name: RI5CY //
18 | // Language: SystemVerilog //
19 | // //
20 | // Description: Basic Interrupt Controller //
21 | // //
22 | ////////////////////////////////////////////////////////////////////////////////
23 |
24 | module cv32e40s_int_controller import cv32e40s_pkg::*;
25 | (
26 | input logic clk,
27 | input logic rst_n,
28 |
29 | // External interrupt lines
30 | input logic [31:0] irq_i, // Level-triggered interrupt inputs
31 |
32 | // To controller
33 | output logic irq_req_ctrl_o,
34 | output logic [4:0] irq_id_ctrl_o,
35 | output logic irq_wu_ctrl_o,
36 |
37 | // From cs_registers
38 | input logic [31:0] mie_i, // MIE CSR
39 | input mstatus_t mstatus_i, // MSTATUS CSR
40 | input privlvl_t priv_lvl_i, // Current privilege level of core
41 |
42 | // To cs_registers
43 | output logic [31:0] mip_o // MIP CSR
44 | );
45 |
46 | logic global_irq_enable;
47 | logic [31:0] irq_local_qual;
48 | logic [31:0] irq_q;
49 |
50 | // Register all interrupt inputs (on gated clock). The wake-up logic will
51 | // observe irq_i as well, but in all other places irq_q will be used to
52 | // avoid timing paths from irq_i to instr_*_o
53 |
54 | always_ff @(posedge clk, negedge rst_n)
55 | begin
56 | if (rst_n == 1'b0) begin
57 | irq_q <= '0;
58 | end else begin
59 | irq_q <= irq_i & IRQ_MASK;
60 | end
61 | end
62 |
63 | // MIP CSR
64 | assign mip_o = irq_q;
65 |
66 | // Qualify registered IRQ with MIE CSR to compute locally enabled IRQs
67 | assign irq_local_qual = irq_q & mie_i;
68 |
69 | // Wake-up signal based on unregistered IRQ such that wake-up can be caused if no clock is present
70 | assign irq_wu_ctrl_o = |(irq_i & mie_i);
71 |
72 | // Global interrupt enable
73 | assign global_irq_enable = mstatus_i.mie || (priv_lvl_i < PRIV_LVL_M);
74 |
75 | // Request to take interrupt if there is a locally enabled interrupt while interrupts are also enabled globally
76 | assign irq_req_ctrl_o = (|irq_local_qual) && global_irq_enable;
77 |
78 | // Interrupt Encoder
79 | //
80 | // - sets correct id to request to ID
81 | // - encodes priority order
82 |
83 | always_comb
84 | begin
85 | if (irq_local_qual[31]) irq_id_ctrl_o = 5'd31; // Custom irq_i[31]
86 | else if (irq_local_qual[30]) irq_id_ctrl_o = 5'd30; // Custom irq_i[30]
87 | else if (irq_local_qual[29]) irq_id_ctrl_o = 5'd29; // Custom irq_i[29]
88 | else if (irq_local_qual[28]) irq_id_ctrl_o = 5'd28; // Custom irq_i[28]
89 | else if (irq_local_qual[27]) irq_id_ctrl_o = 5'd27; // Custom irq_i[27]
90 | else if (irq_local_qual[26]) irq_id_ctrl_o = 5'd26; // Custom irq_i[26]
91 | else if (irq_local_qual[25]) irq_id_ctrl_o = 5'd25; // Custom irq_i[25]
92 | else if (irq_local_qual[24]) irq_id_ctrl_o = 5'd24; // Custom irq_i[24]
93 | else if (irq_local_qual[23]) irq_id_ctrl_o = 5'd23; // Custom irq_i[23]
94 | else if (irq_local_qual[22]) irq_id_ctrl_o = 5'd22; // Custom irq_i[22]
95 | else if (irq_local_qual[21]) irq_id_ctrl_o = 5'd21; // Custom irq_i[21]
96 | else if (irq_local_qual[20]) irq_id_ctrl_o = 5'd20; // Custom irq_i[20]
97 | else if (irq_local_qual[19]) irq_id_ctrl_o = 5'd19; // Custom irq_i[19]
98 | else if (irq_local_qual[18]) irq_id_ctrl_o = 5'd18; // Custom irq_i[18]
99 | else if (irq_local_qual[17]) irq_id_ctrl_o = 5'd17; // Custom irq_i[17]
100 | else if (irq_local_qual[16]) irq_id_ctrl_o = 5'd16; // Custom irq_i[16]
101 |
102 | // Reserved: irq_local_qual[15], irq_id_ctrl_o = 5'd15
103 | // Reserved: irq_local_qual[14], irq_id_ctrl_o = 5'd14
104 | // Reserved: irq_local_qual[13], irq_id_ctrl_o = 5'd13
105 | // Reserved: irq_local_qual[12], irq_id_ctrl_o = 5'd12
106 |
107 | else if (irq_local_qual[CSR_MEIX_BIT]) irq_id_ctrl_o = CSR_MEIX_BIT; // MEI, irq_i[11]
108 | else if (irq_local_qual[CSR_MSIX_BIT]) irq_id_ctrl_o = CSR_MSIX_BIT; // MSI, irq_i[3]
109 | else irq_id_ctrl_o = CSR_MTIX_BIT; // MTI, irq_i[7]
110 |
111 | // Reserved: irq_local_qual[10], irq_id_ctrl_o = 5'd10
112 | // Reserved: irq_local_qual[ 2], irq_id_ctrl_o = 5'd2
113 | // Reserved: irq_local_qual[ 6], irq_id_ctrl_o = 5'd6
114 |
115 | // Reserved: irq_local_qual[ 9], irq_id_ctrl_o = 5'd9, SEI
116 | // Reserved: irq_local_qual[ 1], irq_id_ctrl_o = 5'd1, SSI
117 | // Reserved: irq_local_qual[ 5], irq_id_ctrl_o = 5'd5, STI
118 |
119 | // Reserved: irq_local_qual[ 8], irq_id_ctrl_o = 5'd8, UEI
120 | // Reserved: irq_local_qual[ 0], irq_id_ctrl_o = 5'd0, USI
121 | // Reserved: irq_local_qual[ 4], irq_id_ctrl_o = 5'd4, UTI
122 |
123 | end
124 |
125 | endmodule
126 |
--------------------------------------------------------------------------------
/sva/cv32e40s_wb_stage_sva.sv:
--------------------------------------------------------------------------------
1 | // Copyright 2021 Silicon Labs, Inc.
2 | //
3 | // This file, and derivatives thereof are licensed under the
4 | // Solderpad License, Version 2.0 (the "License");
5 | // Use of this file means you agree to the terms and conditions
6 | // of the license and are in full compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // https://solderpad.org/licenses/SHL-2.0/
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // and hardware implementations thereof
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESSED OR IMPLIED.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 | ////////////////////////////////////////////////////////////////////////////////
19 | // //
20 | // Authors: Arjan Bink - arjan.bink@silabs.com //
21 | // //
22 | // Description: RTL assertions for the wb_stage module //
23 | // //
24 | ////////////////////////////////////////////////////////////////////////////////
25 |
26 | module cv32e40s_wb_stage_sva
27 | import uvm_pkg::*;
28 | import cv32e40s_pkg::*;
29 | #(
30 | parameter bit DEBUG = 1
31 | )
32 | (
33 | input logic clk,
34 | input logic rst_n,
35 |
36 | input logic wb_ready_o,
37 | input logic wb_valid,
38 | input ctrl_fsm_t ctrl_fsm_i,
39 | input ex_wb_pipe_t ex_wb_pipe_i,
40 | input mpu_status_e lsu_mpu_status_i,
41 | input rf_addr_t rf_waddr_wb_o,
42 | input mpu_status_e lsu_mpu_status_q,
43 | input logic [31:0] lsu_wpt_match_i,
44 | input logic rf_we_wb_o,
45 | input logic lsu_valid_q,
46 | input logic [31:0] lsu_wpt_match_q,
47 | input logic lsu_valid_i
48 | );
49 |
50 | // LSU instructions should not get killed once in WB (as they commit already in EX).
51 | a_lsu_no_kill :
52 | assert property (@(posedge clk) disable iff (!rst_n)
53 | (ex_wb_pipe_i.lsu_en && ex_wb_pipe_i.instr_valid)
54 | |-> (!ctrl_fsm_i.kill_wb))
55 | else `uvm_error("wb_stage", "LSU instruction killed in WB")
56 |
57 | // Halt implies not ready and not valid
58 | a_halt :
59 | assert property (@(posedge clk) disable iff (!rst_n)
60 | (ctrl_fsm_i.halt_wb && !ctrl_fsm_i.kill_wb)
61 | |-> (!wb_ready_o && !wb_valid))
62 | else `uvm_error("wb_stage", "Halt should imply not ready and not valid")
63 |
64 | // Kill implies ready and not valid
65 | a_kill :
66 | assert property (@(posedge clk) disable iff (!rst_n)
67 | (ctrl_fsm_i.kill_wb)
68 | |-> (wb_ready_o && !wb_valid))
69 | else `uvm_error("wb_stage", "Kill should imply ready and not valid")
70 |
71 |
72 | // MPU should never signal error on non-LSU instructions
73 | a_nonlsu_error:
74 | assert property (@(posedge clk) disable iff (!rst_n)
75 | (!ex_wb_pipe_i.lsu_en)
76 | |-> (lsu_mpu_status_i == MPU_OK))
77 | else `uvm_error("wb_stage", "MPU error on non LSU instruction")
78 |
79 | // Register file shall not be written when WB is halted or killed
80 | a_rf_halt_kill:
81 | assert property (@(posedge clk) disable iff (!rst_n)
82 | (ctrl_fsm_i.kill_wb || ctrl_fsm_i.halt_wb)
83 | |-> !rf_we_wb_o)
84 | else `uvm_error("wb_stage", "Register file written while WB is halted or killed")
85 |
86 |
87 | // The WB stage will make the mpu_status sticky if wb_walid is not asserted the first cycle in WB.
88 | // In practice this should never happen as the controller will not allow any halt or kill on a LSU in WB.
89 | // The only exception to this is the watchpoints which are asserted separately.
90 | a_no_sticky_mpu_error:
91 | assert property (@(posedge clk) disable iff (!rst_n)
92 | (lsu_mpu_status_q == MPU_OK))
93 | else `uvm_error("wb_stage", "lsu_mpu_status_q should never see an error")
94 |
95 |
96 | // Any load or store without an MPU error or watchpoint trigger must signal wb_valid when rvalid arrives.
97 | // This chekcs that there is no need for sticky rdata_q bits in the wb_stage similar to the mpu_status and wpt bits.
98 | a_lsu_wb_valid:
99 | assert property (@(posedge clk) disable iff (!rst_n)
100 | lsu_valid_i &&
101 | !(|lsu_wpt_match_i || (lsu_mpu_status_i != MPU_OK))
102 | |->
103 | wb_valid)
104 | else `uvm_error("wb_stage", "wb_valid not signaled immediately upon rvalid for LSU without WPT or MPU error")
105 |
106 | generate
107 | if (DEBUG) begin
108 | // The only cause for a sticky lsu_valid is a watchpoint trigger.
109 | a_only_wpt_lsu_valid_sticky:
110 | assert property (@(posedge clk) disable iff (!rst_n)
111 | lsu_valid_q
112 | |->
113 | |lsu_wpt_match_q &&
114 | |$past(lsu_wpt_match_i))
115 | else `uvm_error("wb_stage", "LSU signal sticky for non-watchpoint cause")
116 |
117 | // A watchpoint trigger will be halted during its first cycle in WB, giving !wb_valid.
118 | // During the next cycle the controller will kill the pipeline but let wb_valid==1'b1 to let RVFI
119 | // know the core hit a watchpoint.
120 | a_wpt_wb_halt:
121 | assert property (@(posedge clk) disable iff (!rst_n)
122 | |lsu_wpt_match_i
123 | |->
124 | !wb_valid && ctrl_fsm_i.halt_wb)
125 | else `uvm_error("wb_stage", "WB stage not halted on a WPT match")
126 |
127 | a_wpt_wb_valid:
128 | assert property (@(posedge clk) disable iff (!rst_n)
129 | |lsu_wpt_match_i
130 | |=>
131 | wb_valid)
132 | else `uvm_error("wb_stage", "WB stage not setting wb_valid on a WPT")
133 |
134 | end else begin
135 | // Without debug support, sticky lsu_valid shall never be set
136 | a_never_lsu_valid_sticky:
137 | assert property (@(posedge clk) disable iff (!rst_n)
138 | !lsu_valid_q)
139 | else `uvm_error("wb_stage", "LSU signal sticky when debug support is not enabled.")
140 | end
141 | endgenerate
142 | endmodule // cv32e40s_wb_stage_sva
143 |
--------------------------------------------------------------------------------
/sva/cv32e40s_parameter_sva.sv:
--------------------------------------------------------------------------------
1 | // Copyright 2023 Silicon Labs, Inc.
2 | //
3 | // This file, and derivatives thereof are licensed under the
4 | // Solderpad License, Version 2.0 (the "License");
5 | // Use of this file means you agree to the terms and conditions
6 | // of the license and are in full compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // https://solderpad.org/licenses/SHL-2.0/
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // and hardware implementations thereof
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESSED OR IMPLIED.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 | ////////////////////////////////////////////////////////////////////////////////
19 | // //
20 | // Authors: Oivind Ekelund - oivind.ekelund@silabs.com //
21 | // //
22 | // Description: Assertions for top level parameters //
23 | // //
24 | ////////////////////////////////////////////////////////////////////////////////
25 |
26 | module cv32e40s_parameter_sva import cv32e40s_pkg::*;
27 | #(
28 | parameter int PMA_NUM_REGIONS = 0,
29 | parameter pma_cfg_t PMA_CFG[PMA_NUM_REGIONS-1:0] = '{default:PMA_R_DEFAULT},
30 | parameter logic [31:0] DM_REGION_START = 32'hF0000000,
31 | parameter logic [31:0] DM_REGION_END = 32'hF0003FFF,
32 | parameter int DBG_NUM_TRIGGERS = 1,
33 | parameter int unsigned CLIC_ID_WIDTH = 5,
34 | parameter int unsigned NUM_MHPMCOUNTERS = 1,
35 | parameter int PMP_NUM_REGIONS = 0,
36 | parameter pmpncfg_t PMP_PMPNCFG_RV[PMP_NUM_REGIONS-1:0] = '{default:PMPNCFG_DEFAULT},
37 | parameter mseccfg_t PMP_MSECCFG_RV = MSECCFG_DEFAULT,
38 | parameter int unsigned PMP_GRANULARITY = 0,
39 | parameter lfsr_cfg_t LFSR0_CFG = LFSR_CFG_DEFAULT,
40 | parameter lfsr_cfg_t LFSR1_CFG = LFSR_CFG_DEFAULT,
41 | parameter lfsr_cfg_t LFSR2_CFG = LFSR_CFG_DEFAULT
42 | )
43 | (
44 | input logic clk_i,
45 | input logic rst_ni
46 | );
47 |
48 | a_param_pma_num_regions :
49 | assert property (@(posedge clk_i) disable iff (!rst_ni)
50 | (0 <= PMA_NUM_REGIONS) && (PMA_NUM_REGIONS <= 16))
51 | else $fatal(0, "Invalid PMA_NUM_REGIONS");
52 |
53 | generate for (genvar i = 0; i < PMA_NUM_REGIONS; i++)
54 | begin : a_pma_no_illegal_configs
55 |
56 | if (!PMA_CFG[i].main) begin
57 | a_param_pma_io_noncacheable :
58 | assert property (@(posedge clk_i) disable iff (!rst_ni)
59 | !PMA_CFG[i].cacheable)
60 | else $fatal(0, "Invalid PMA region configuration: cacheable I/O region");
61 | end
62 |
63 | a_param_pma_addr_range :
64 | assert property (@(posedge clk_i) disable iff (!rst_ni)
65 | PMA_CFG[i].word_addr_high >= PMA_CFG[i].word_addr_low)
66 | else $fatal(0, "Invalid PMA region boundaries");
67 |
68 | end
69 | endgenerate
70 |
71 |
72 | a_param_dm_region :
73 | assert property (@(posedge clk_i) disable iff (!rst_ni)
74 | DM_REGION_END > DM_REGION_START)
75 | else $fatal(0, "Invalid combination of DM_REGION_START and DM_REGION_END");
76 |
77 | a_param_dbg_num_triggers :
78 | assert property (@(posedge clk_i) disable iff (!rst_ni)
79 | (0 <= DBG_NUM_TRIGGERS) && (DBG_NUM_TRIGGERS <= 4))
80 | else $fatal(0, "Invalid DBG_NUM_TRIGGERS");
81 |
82 | a_param_clic_id_width :
83 | assert property (@(posedge clk_i) disable iff (!rst_ni)
84 | (1 <= CLIC_ID_WIDTH) && (CLIC_ID_WIDTH <= 10))
85 | else $fatal(0, "Invalid CLIC_ID_WIDTH");
86 |
87 | a_param_num_mhpmcounters :
88 | assert property (@(posedge clk_i) disable iff (!rst_ni)
89 | (0 <= NUM_MHPMCOUNTERS) && (NUM_MHPMCOUNTERS <= 29))
90 | else $fatal(0, "Invalid NUM_MHPMCOUNTERS");
91 |
92 | a_param_pmp_num_regions :
93 | assert property (@(posedge clk_i) disable iff (!rst_ni)
94 | (0 <= PMP_NUM_REGIONS) && (PMP_NUM_REGIONS <= 64))
95 | else $fatal(0, "Invalid PMP_NUM_REGIONS");
96 |
97 | a_param_pmp_granularity :
98 | assert property (@(posedge clk_i) disable iff (!rst_ni)
99 | (0 <= PMP_GRANULARITY) && (PMP_GRANULARITY <= 31))
100 | else $fatal(0, "Invalid PMP_GRANULARITY");
101 |
102 | generate for (genvar i_pmp = 0; i_pmp < PMP_NUM_REGIONS; i_pmp++)
103 | begin: pmp_region_asrt
104 |
105 | // Make sure reset value of zero bitfields is zero
106 | a_param_pmpncfg_rv_zero:
107 | assert property (@(posedge clk_i) disable iff (!rst_ni)
108 | PMP_PMPNCFG_RV[i_pmp].zero0 == '0)
109 | else $fatal(0, $sformatf("PMP_PMPNCFG_RV[%2d].zero0 not equal to 0", i_pmp));
110 |
111 | // When mseccfg.mml==0, RW=01 is a reserved combination, and shall be disallowed
112 | if (!PMP_MSECCFG_RV.mml) begin
113 | a_param_pmp_no_rw_01:
114 | assert property (@(posedge clk_i) disable iff (!rst_ni)
115 | {PMP_PMPNCFG_RV[i_pmp].read, PMP_PMPNCFG_RV[i_pmp].write} != 2'b01)
116 | else $fatal(0, $sformatf("PMP_PMPNCFG_RV[%2d] illegal value: RW = 01", i_pmp));
117 |
118 | end
119 | end
120 | endgenerate
121 |
122 | a_param_mseccfg_rv_zero:
123 | assert property (@(posedge clk_i) disable iff (!rst_ni)
124 | PMP_MSECCFG_RV.zero0 == '0)
125 | else $fatal(0, "PMP_MSECCFG_RV.zero0 not equal to 0");
126 |
127 | a_param_lfsr0_cfg:
128 | assert property (@(posedge clk_i) disable iff (!rst_ni)
129 | LFSR0_CFG != LFSR_CFG_DEFAULT)
130 | else $fatal(0, "Invalid LFSR0_CFG");
131 |
132 | a_param_lfsr1_cfg:
133 | assert property (@(posedge clk_i) disable iff (!rst_ni)
134 | LFSR1_CFG != LFSR_CFG_DEFAULT)
135 | else $fatal(0, "Invalid LFSR1_CFG");
136 |
137 | a_param_lfsr2_cfg:
138 | assert property (@(posedge clk_i) disable iff (!rst_ni)
139 | LFSR2_CFG != LFSR_CFG_DEFAULT)
140 | else $fatal(0, "Invalid LFSR2_CFG");
141 |
142 | endmodule
143 |
--------------------------------------------------------------------------------
/sva/cv32e40s_debug_triggers_sva.sv:
--------------------------------------------------------------------------------
1 | // Copyright 2023 Silicon Labs, Inc.
2 | //
3 | // This file, and derivatives thereof are licensed under the
4 | // Solderpad License, Version 2.0 (the "License");
5 | // Use of this file means you agree to the terms and conditions
6 | // of the license and are in full compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // https://solderpad.org/licenses/SHL-2.0/
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // and hardware implementations thereof
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESSED OR IMPLIED.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 | ////////////////////////////////////////////////////////////////////////////////
19 | // //
20 | // Authors: Oystein Knauserud - oystein.knauserud@silabs.com //
21 | // //
22 | // Description: debug_triggers assertions //
23 | // //
24 | ////////////////////////////////////////////////////////////////////////////////
25 |
26 | module cv32e40s_debug_triggers_sva
27 | import uvm_pkg::*;
28 | import cv32e40s_pkg::*;
29 | #(
30 | parameter int DBG_NUM_TRIGGERS = 1
31 | )
32 |
33 | (
34 | input logic clk,
35 | input logic rst_n,
36 | input csr_opcode_e csr_op, // from cs_registers
37 | input logic [31:0] csr_wdata, // from cs_registers
38 | input csr_num_e csr_waddr, // from cs_registers
39 | input ex_wb_pipe_t ex_wb_pipe_i,
40 | input ctrl_fsm_t ctrl_fsm_i,
41 | input logic [31:0] tselect_q,
42 | input logic [31:0] tdata1_q[DBG_NUM_TRIGGERS],
43 | input logic [31:0] tdata2_q[DBG_NUM_TRIGGERS],
44 | input logic [31:0] trigger_match_if_wb,
45 | input logic [31:0] trigger_match_ex_wb,
46 | input logic wb_valid_i,
47 | input logic tdata1_we_i
48 | );
49 |
50 |
51 |
52 | /////////////////////////////////////////////////////////////////////////////////////////
53 | // Asserts to check that the CSR flops remain unchanged if a set/clear has all_zero rs1
54 | /////////////////////////////////////////////////////////////////////////////////////////
55 | a_set_clear_tselect_q:
56 | assert property (@(posedge clk) disable iff (!rst_n)
57 | (csr_waddr == CSR_TSELECT) &&
58 | ((csr_op == CSR_OP_SET) || (csr_op == CSR_OP_CLEAR)) &&
59 | !(|csr_wdata) &&
60 | ex_wb_pipe_i.csr_en &&
61 | !ctrl_fsm_i.kill_wb
62 | |=>
63 | $stable(tselect_q))
64 | else `uvm_error("debug_triggers", "tselect_q changed after set/clear with rs1==0")
65 |
66 | a_set_clear_tdata1_q:
67 | assert property (@(posedge clk) disable iff (!rst_n)
68 | (csr_waddr == CSR_TDATA1) &&
69 | ((csr_op == CSR_OP_SET) || (csr_op == CSR_OP_CLEAR)) &&
70 | !(|csr_wdata) &&
71 | ex_wb_pipe_i.csr_en &&
72 | !ctrl_fsm_i.kill_wb
73 | |=>
74 | $stable(tdata1_q)) // Checking stability of ALL tdata1, not just the one selected
75 | else `uvm_error("debug_triggers", "tdata1_q changed after set/clear with rs1==0")
76 |
77 | a_set_clear_tdata2_q:
78 | assert property (@(posedge clk) disable iff (!rst_n)
79 | (csr_waddr == CSR_TDATA2) &&
80 | ((csr_op == CSR_OP_SET) || (csr_op == CSR_OP_CLEAR)) &&
81 | !(|csr_wdata) &&
82 | ex_wb_pipe_i.csr_en &&
83 | !ctrl_fsm_i.kill_wb
84 | |=>
85 | $stable(tdata2_q)) // Checking stability of ALL tdata2, not just the one selected
86 | else `uvm_error("debug_triggers", "tdata2_q changed after set/clear with rs1==0")
87 |
88 | generate
89 | for (genvar i=0; i
97 | (tdata1_q[i][MCONTROL_6_HIT0] == 1'b1) &&
98 | (tdata1_q[i][MCONTROL_6_HIT1] == 1'b0))
99 | else `uvm_error("debug_triggers", "mcontrol6.hit0 not set on trigger match")
100 |
101 | // Check that trigger that did not match has stable {hit1, hit0}
102 | a_mcontrol6_not_hit_stable:
103 | assert property (@(posedge clk) disable iff (!rst_n)
104 | (tdata1_q[i][TDATA1_TTYPE_HIGH:TDATA1_TTYPE_LOW] == TTYPE_MCONTROL6) &&
105 | |(trigger_match_if_wb | trigger_match_ex_wb) && // Any trigger matched
106 | !(trigger_match_if_wb[i] || trigger_match_ex_wb[i]) && // But not this one
107 | wb_valid_i
108 | |=>
109 | ($stable(tdata1_q[i][MCONTROL_6_HIT0])) &&
110 | ($stable(tdata1_q[i][MCONTROL_6_HIT1])))
111 | else `uvm_error("debug_triggers", "mcontrol6.hit0/1 changed without a trigger match")
112 | end
113 | endgenerate
114 |
115 | // Check that SW writes to tdata1 cannot happen at the same time as the controller wants to upate hit bits in mcontrol6
116 | a_tdata1_writes_unique:
117 | assert property (@(posedge clk) disable iff (!rst_n)
118 | (tdata1_we_i || ctrl_fsm_i.debug_trigger_hit_update)
119 | |->
120 | (tdata1_we_i != ctrl_fsm_i.debug_trigger_hit_update))
121 | else `uvm_error("debug_triggers", "SW write to tdata1 at the same time as controller write.")
122 |
123 | // Check that we cannot have trigger match from both IF and EX for the same trigger
124 | a_if_ex_trig_exclusive:
125 | assert property (@(posedge clk) disable iff (!rst_n)
126 | |(trigger_match_if_wb & trigger_match_ex_wb) == 1'b0)
127 | else `uvm_error("debug_triggers", "Trigger match from both IF and EX for the same trigger should not happen")
128 |
129 | // Check that DBG_NUM_TRIGGERS is <= 32
130 | a_max_num_triggers:
131 | assert property (@(posedge clk) disable iff (!rst_n)
132 | (DBG_NUM_TRIGGERS <= 32))
133 | else `uvm_error("debug_triggers", "DBG_NUM_TRIGGERS can max have the value of 32")
134 |
135 | endmodule
136 |
137 |
--------------------------------------------------------------------------------
/rtl/cv32e40s_prefetch_unit.sv:
--------------------------------------------------------------------------------
1 | // Copyright 2018 ETH Zurich and University of Bologna.
2 | // Copyright and related rights are licensed under the Solderpad Hardware
3 | // License, Version 0.51 (the "License"); you may not use this file except in
4 | // compliance with the License. You may obtain a copy of the License at
5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
6 | // or agreed to in writing, software, hardware and materials distributed under
7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
9 | // specific language governing permissions and limitations under the License.
10 |
11 | ////////////////////////////////////////////////////////////////////////////////
12 | // Engineer: Andreas Traber - atraber@iis.ee.ethz.ch //
13 | // Øystein Knauserud - oystein.knauserud@silabs.com //
14 | // //
15 | // Design Name: Prefetcher Buffer for 32 bit memory interface //
16 | // Project Name: RI5CY //
17 | // Language: SystemVerilog //
18 | // //
19 | // Description: Prefetch unit that prefetches instructions and store them //
20 | // in a buffer that extracts compressed and uncompressed //
21 | // instructions. //
22 | // //
23 | ////////////////////////////////////////////////////////////////////////////////
24 |
25 | // input port: send address one cycle before the data
26 | // clear_i clears the FIFO for the following cycle. in_addr_i can be sent in
27 | // this cycle already
28 |
29 | module cv32e40s_prefetch_unit import cv32e40s_pkg::*;
30 | #(
31 | parameter bit CLIC = 1'b0,
32 | parameter int unsigned ALBUF_DEPTH = 3,
33 | parameter int unsigned ALBUF_CNT_WIDTH = $clog2(ALBUF_DEPTH),
34 | parameter int unsigned MAX_OUTSTANDING = 2
35 | )
36 | (
37 | input logic clk,
38 | input logic rst_n,
39 |
40 | input ctrl_fsm_t ctrl_fsm_i,
41 | input privlvlctrl_t priv_lvl_ctrl_i,
42 |
43 | input logic [31:0] branch_addr_i,
44 |
45 | input logic prefetch_ready_i,
46 | output logic prefetch_valid_o,
47 | output inst_resp_t prefetch_instr_o,
48 | output logic [31:0] prefetch_addr_o,
49 | output privlvl_t prefetch_priv_lvl_o,
50 | output logic prefetch_is_clic_ptr_o,
51 | output logic prefetch_is_mret_ptr_o,
52 | output logic prefetch_is_tbljmp_ptr_o,
53 |
54 | // Transaction interface to obi interface
55 | output logic trans_valid_o,
56 | input logic trans_ready_i,
57 | output logic [31:0] trans_addr_o,
58 |
59 | input logic resp_valid_i,
60 | input inst_resp_t resp_i,
61 |
62 | output logic one_txn_pend_n,
63 | output logic [ALBUF_CNT_WIDTH-1:0] outstnd_cnt_q_o,
64 |
65 | // Xsecure control (for parity and rchk)
66 | input xsecure_ctrl_t xsecure_ctrl_i,
67 |
68 | // Prefetch Buffer Status
69 | output logic prefetch_busy_o,
70 |
71 | output logic protocol_err_o
72 | );
73 |
74 | logic fetch_valid;
75 | logic fetch_ready;
76 |
77 | logic fetch_branch;
78 | logic [31:0] fetch_branch_addr;
79 | logic fetch_ptr_access;
80 | logic fetch_ptr_resp;
81 | privlvl_t fetch_priv_lvl_access;
82 | privlvl_t fetch_priv_lvl_resp;
83 |
84 |
85 |
86 | //////////////////////////////////////////////////////////////////////////////
87 | // Prefetcher
88 | //////////////////////////////////////////////////////////////////////////////
89 |
90 | cv32e40s_prefetcher
91 | #(
92 | .CLIC (CLIC)
93 | )
94 | prefetcher_i
95 | (
96 | .clk ( clk ),
97 | .rst_n ( rst_n ),
98 |
99 | .fetch_branch_i ( fetch_branch ),
100 | .fetch_branch_addr_i ( fetch_branch_addr ),
101 | .fetch_valid_i ( fetch_valid ),
102 | .fetch_ready_o ( fetch_ready ),
103 | .fetch_ptr_access_i ( fetch_ptr_access ),
104 | .fetch_ptr_access_o ( fetch_ptr_resp ),
105 | .fetch_priv_lvl_access_i ( fetch_priv_lvl_access),
106 | .fetch_priv_lvl_access_o ( fetch_priv_lvl_resp ),
107 | .trans_valid_o ( trans_valid_o ),
108 | .trans_ready_i ( trans_ready_i ),
109 | .trans_addr_o ( trans_addr_o )
110 | );
111 |
112 |
113 | cv32e40s_alignment_buffer
114 | #(
115 | .ALBUF_DEPTH(ALBUF_DEPTH),
116 | .ALBUF_CNT_WIDTH(ALBUF_CNT_WIDTH),
117 | .MAX_OUTSTANDING(MAX_OUTSTANDING)
118 | )
119 | alignment_buffer_i
120 | (
121 | .clk ( clk ),
122 | .rst_n ( rst_n ),
123 |
124 | .ctrl_fsm_i ( ctrl_fsm_i ),
125 | .priv_lvl_ctrl_i ( priv_lvl_ctrl_i ),
126 |
127 | .branch_addr_i ( branch_addr_i ),
128 | .prefetch_busy_o ( prefetch_busy_o ),
129 |
130 | .xsecure_ctrl_i ( xsecure_ctrl_i ),
131 |
132 | // prefetch unit
133 | .fetch_valid_o ( fetch_valid ),
134 | .fetch_ready_i ( fetch_ready ),
135 | .fetch_branch_o ( fetch_branch ),
136 | .fetch_branch_addr_o ( fetch_branch_addr ),
137 | .fetch_ptr_access_o ( fetch_ptr_access ),
138 | .fetch_ptr_access_i ( fetch_ptr_resp ),
139 | .fetch_priv_lvl_o ( fetch_priv_lvl_access ),
140 | .fetch_priv_lvl_i ( fetch_priv_lvl_resp ),
141 |
142 | .resp_valid_i ( resp_valid_i ),
143 | .resp_i ( resp_i ),
144 | .one_txn_pend_n ( one_txn_pend_n ),
145 | .outstnd_cnt_q_o ( outstnd_cnt_q_o ),
146 |
147 | // Instruction interface
148 | .instr_valid_o ( prefetch_valid_o ),
149 | .instr_ready_i ( prefetch_ready_i ),
150 | .instr_instr_o ( prefetch_instr_o ),
151 | .instr_addr_o ( prefetch_addr_o ),
152 | .instr_priv_lvl_o ( prefetch_priv_lvl_o ),
153 | .instr_is_clic_ptr_o ( prefetch_is_clic_ptr_o ),
154 | .instr_is_mret_ptr_o ( prefetch_is_mret_ptr_o ),
155 | .instr_is_tbljmp_ptr_o ( prefetch_is_tbljmp_ptr_o),
156 | .protocol_err_o ( protocol_err_o )
157 |
158 | );
159 |
160 | endmodule
161 |
--------------------------------------------------------------------------------
/rtl/cv32e40s_wpt.sv:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Silicon Labs, Inc.
2 | //
3 | // This file, and derivatives thereof are licensed under the
4 | // Solderpad License, Version 2.0 (the "License");
5 | // Use of this file means you agree to the terms and conditions
6 | // of the license and are in full compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // https://solderpad.org/licenses/SHL-2.0/
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // and hardware implementations thereof
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESSED OR IMPLIED.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 | ////////////////////////////////////////////////////////////////////////////////
19 | // //
20 | // Authors: Oystein Knauserud - oystein.knauserud@silabs.com //
21 | // //
22 | // Description: WPT //
23 | // Module blocks any trans to the MPU if a watchpoint trigger //
24 | // fires for the current address. Trigger match is reported //
25 | // with WB timing similar to how the MPU reports status. //
26 | // cv32e40s_wpt is inherited from cv32e40s_mpu and adataped //
27 | // for watchpoint triggers. //
28 | // //
29 | ////////////////////////////////////////////////////////////////////////////////
30 |
31 | module cv32e40s_wpt import cv32e40s_pkg::*;
32 | (
33 | input logic clk,
34 | input logic rst_n,
35 |
36 | // Input from debug_triggers module
37 | input logic [31:0] trigger_match_i,
38 |
39 | // Interface towards mpu interface
40 | input logic mpu_trans_ready_i,
41 | output logic mpu_trans_valid_o,
42 | output logic mpu_trans_pushpop_o,
43 | output obi_data_req_t mpu_trans_o,
44 |
45 | input logic mpu_resp_valid_i,
46 | input data_resp_t mpu_resp_i,
47 |
48 | // Interface towards core
49 | input logic core_trans_valid_i,
50 | output logic core_trans_ready_o,
51 | input logic core_trans_pushpop_i,
52 | input obi_data_req_t core_trans_i,
53 |
54 | output logic core_resp_valid_o,
55 | output data_resp_t core_resp_o,
56 |
57 | // Indication from the core that there will be one pending transaction in the next cycle
58 | input logic core_one_txn_pend_n,
59 |
60 | // Indication from the core that watchpoint triggers should be reported after all in flight transactions
61 | // are complete
62 | input logic core_wpt_wait_i,
63 |
64 | // Report watchpoint triggers to the core immediatly (used in case core_wpt_wait_i is not asserted)
65 | output logic [31:0] core_wpt_match_o
66 | );
67 |
68 | logic wpt_block_core;
69 | logic wpt_block_bus;
70 | logic wpt_trans_valid;
71 | logic wpt_trans_ready;
72 | logic [31:0] wpt_match; // 1 bit per trigger, unused bits are tied to 0 in debug_triggers
73 | wpt_state_e state_q, state_n;
74 |
75 | logic [31:0] wpt_match_n, wpt_match_q;
76 |
77 | // FSM that will "consume" transfers with firing watchpoint triggers.
78 | // Upon trigger match, this FSM will prevent the transfer from going out on the bus
79 | // and wait for all in flight bus transactions to complete while blocking new transfers.
80 | // When all in flight transactions are complete, it will respond with the correct status before
81 | // allowing new transfers to go through.
82 | // The input signal core_one_txn_pend_n indicates that there, from the core's point of view,
83 | // will be one pending transaction in the next cycle. Upon watchpoint match, this transaction
84 | // will be completed by this FSM
85 | always_comb begin
86 |
87 | state_n = state_q;
88 | wpt_block_core = 1'b0;
89 | wpt_block_bus = 1'b0;
90 | wpt_trans_valid = 1'b0;
91 | wpt_trans_ready = 1'b0;
92 | wpt_match = '0;
93 | wpt_match_n = wpt_match_q;
94 |
95 | case(state_q)
96 | WPT_IDLE: begin
97 | if (|trigger_match_i && core_trans_valid_i) begin
98 | // Remember which trigger(s) hit
99 | wpt_match_n = trigger_match_i;
100 |
101 | // Block transfer from going out on the bus.
102 | wpt_block_bus = 1'b1;
103 |
104 | // Signal to the core that the transfer was accepted (but will be consumed by the WPT)
105 | wpt_trans_ready = 1'b1;
106 |
107 | if (core_wpt_wait_i) begin
108 | state_n = core_one_txn_pend_n ? WPT_MATCH_RESP : WPT_MATCH_WAIT;
109 | end
110 |
111 | end
112 | end
113 | WPT_MATCH_WAIT: begin
114 |
115 | // Block new transfers while waiting for in flight transfers to complete
116 | wpt_block_bus = 1'b1;
117 | wpt_block_core = 1'b1;
118 |
119 | if (core_one_txn_pend_n) begin
120 | state_n = WPT_MATCH_RESP;
121 | end
122 | end
123 | WPT_MATCH_RESP: begin
124 |
125 | // Keep blocking new transfers
126 | wpt_block_bus = 1'b1;
127 | wpt_block_core = 1'b1;
128 |
129 | // Set up WPT response towards the core
130 | wpt_trans_valid = 1'b1;
131 | wpt_match = wpt_match_q;
132 |
133 | // Clear wpt_match_q
134 | wpt_match_n = '0;
135 |
136 | // Go back to IDLE uncoditionally.
137 | // The core is expected to always be ready for the response
138 | state_n = WPT_IDLE;
139 |
140 | end
141 | default: ;
142 | endcase
143 | end
144 |
145 | always_ff @(posedge clk, negedge rst_n) begin
146 | if (rst_n == 1'b0) begin
147 | state_q <= WPT_IDLE;
148 | wpt_match_q <= '0;
149 | end
150 | else begin
151 | state_q <= state_n;
152 | wpt_match_q <= wpt_match_n;
153 | end
154 | end
155 |
156 | // Forward transaction request towards MPU
157 | assign mpu_trans_valid_o = core_trans_valid_i && !wpt_block_bus;
158 | assign mpu_trans_o = core_trans_i;
159 | assign mpu_trans_pushpop_o = core_trans_pushpop_i;
160 |
161 |
162 | // Forward transaction response towards core
163 | assign core_resp_valid_o = mpu_resp_valid_i || wpt_trans_valid;
164 | assign core_resp_o.bus_resp = mpu_resp_i.bus_resp;
165 | assign core_resp_o.mpu_status = mpu_resp_i.mpu_status;
166 | assign core_resp_o.wpt_match = wpt_match;
167 |
168 |
169 | // Report WPT matches to the core immediately
170 | assign core_wpt_match_o = trigger_match_i;
171 |
172 | // Signal ready towards core
173 | assign core_trans_ready_o = (mpu_trans_ready_i && !wpt_block_core) || wpt_trans_ready;
174 |
175 |
176 |
177 | endmodule
178 |
--------------------------------------------------------------------------------
/sva/cv32e40s_data_obi_interface_sva.sv:
--------------------------------------------------------------------------------
1 | // Copyright 2022 Silicon Labs, Inc.
2 | //
3 | // This file, and derivatives thereof are licensed under the
4 | // Solderpad License, Version 2.0 (the "License");
5 | // Use of this file means you agree to the terms and conditions
6 | // of the license and are in full compliance with the License.
7 | // You may obtain a copy of the License at
8 | //
9 | // https://solderpad.org/licenses/SHL-2.0/
10 | //
11 | // Unless required by applicable law or agreed to in writing, software
12 | // and hardware implementations thereof
13 | // distributed under the License is distributed on an "AS IS" BASIS,
14 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESSED OR IMPLIED.
15 | // See the License for the specific language governing permissions and
16 | // limitations under the License.
17 |
18 | ////////////////////////////////////////////////////////////////////////////////
19 | // //
20 | // Authors: Oystein Knauserud - oystein.knauserud@silabs.com //
21 | // //
22 | // Description: RTL assertions for the data_obi_interface module //
23 | // //
24 | ////////////////////////////////////////////////////////////////////////////////
25 |
26 | module cv32e40s_data_obi_interface_sva
27 | import uvm_pkg::*;
28 | import cv32e40s_pkg::*;
29 | (
30 | input logic clk,
31 | input logic rst_n,
32 | cv32e40s_if_c_obi.monitor m_c_obi_data_if,
33 | input logic gntpar_err,
34 | input logic gntpar_err_q,
35 | input obi_data_resp_t resp_o,
36 | input obi_data_req_t trans_i,
37 | input logic gntpar_err_resp,
38 | input logic resp_is_store
39 | );
40 |
41 | // Support logic (FIFO) to track grant parity fault
42 |
43 | localparam MAX_OUTSTND_TXN = 5; // This needs to be larger (or equal) to the max outstanding transactions in IF and LSU
44 |
45 | typedef enum logic [1:0] {GNT_ERR, GNT_NOERR, GNT_NONE} gnt_err_chck_e;
46 | typedef enum logic [1:0] {INT, NOINT, INT_NONE} integrity_e;
47 | typedef enum logic [1:0] {STORE, LOAD, STORE_NONE} store_e;
48 | logic exp_int;
49 | logic exp_gnt_err;
50 | logic exp_store;
51 | logic [$clog2(MAX_OUTSTND_TXN)-1:0] oldest_txn;
52 |
53 | gnt_err_chck_e [MAX_OUTSTND_TXN-1:0] gnt_fifo_q;
54 | gnt_err_chck_e [MAX_OUTSTND_TXN-1:0] gnt_fifo_n;
55 | gnt_err_chck_e [MAX_OUTSTND_TXN-1:0] gnt_fifo_tmp;
56 |
57 | integrity_e [MAX_OUTSTND_TXN-1:0] int_fifo_q;
58 | integrity_e [MAX_OUTSTND_TXN-1:0] int_fifo_n;
59 | integrity_e [MAX_OUTSTND_TXN-1:0] int_fifo_tmp;
60 |
61 | store_e [MAX_OUTSTND_TXN-1:0] store_fifo_q;
62 | store_e [MAX_OUTSTND_TXN-1:0] store_fifo_n;
63 | store_e [MAX_OUTSTND_TXN-1:0] store_fifo_tmp;
64 |
65 | always_comb begin
66 | gnt_fifo_n = gnt_fifo_q;
67 | gnt_fifo_tmp = gnt_fifo_q;
68 | int_fifo_n = int_fifo_q;
69 | int_fifo_tmp = int_fifo_q;
70 | store_fifo_n = store_fifo_q;
71 | store_fifo_tmp = store_fifo_q;
72 | casez ({m_c_obi_data_if.s_req.req, m_c_obi_data_if.s_gnt.gnt, m_c_obi_data_if.s_rvalid.rvalid})
73 | 3'b110: begin
74 | // Accepted address phase, add one entry to FIFO
75 | gnt_fifo_n = (gntpar_err || gntpar_err_q) ?
76 | {gnt_fifo_q[MAX_OUTSTND_TXN-2:0], GNT_ERR} :
77 | {gnt_fifo_q[MAX_OUTSTND_TXN-2:0], GNT_NOERR};
78 |
79 | int_fifo_n = trans_i.integrity ?
80 | {int_fifo_q[MAX_OUTSTND_TXN-2:0], INT} :
81 | {int_fifo_q[MAX_OUTSTND_TXN-2:0], NOINT};
82 |
83 | store_fifo_n = trans_i.we ?
84 | {store_fifo_q[MAX_OUTSTND_TXN-2:0], STORE} :
85 | {store_fifo_q[MAX_OUTSTND_TXN-2:0], LOAD};
86 | end
87 | 3'b0?1, 3'b?01: begin
88 | // Response phase, remove oldest entry from FIFO
89 | gnt_fifo_n[oldest_txn] = GNT_NONE;
90 |
91 | int_fifo_n[oldest_txn] = INT_NONE;
92 |
93 | store_fifo_n[oldest_txn] = STORE_NONE;
94 | end
95 | 3'b111: begin
96 | // Accepted address phase and response phase. Clear oldest transaction and add new to FIFO
97 | gnt_fifo_tmp[oldest_txn] = GNT_NONE;
98 | gnt_fifo_n = (gntpar_err || gntpar_err_q) ?
99 | {gnt_fifo_tmp[MAX_OUTSTND_TXN-2:0], GNT_ERR} :
100 | {gnt_fifo_tmp[MAX_OUTSTND_TXN-2:0], GNT_NOERR};
101 |
102 | int_fifo_tmp[oldest_txn] = INT_NONE;
103 | int_fifo_n = trans_i.integrity ?
104 | {int_fifo_tmp[MAX_OUTSTND_TXN-2:0], INT} :
105 | {int_fifo_tmp[MAX_OUTSTND_TXN-2:0], NOINT};
106 |
107 | store_fifo_tmp[oldest_txn] = STORE_NONE;
108 | store_fifo_n = trans_i.we ?
109 | {store_fifo_tmp[MAX_OUTSTND_TXN-2:0], STORE} :
110 | {store_fifo_tmp[MAX_OUTSTND_TXN-2:0], LOAD};
111 | end
112 | default; // Do nothing
113 | endcase
114 | end
115 |
116 | // FIFO
117 | always_ff @ (posedge clk, negedge rst_n) begin
118 | if (!rst_n) begin
119 | gnt_fifo_q <= {MAX_OUTSTND_TXN{GNT_NONE}};
120 | int_fifo_q <= {MAX_OUTSTND_TXN{INT_NONE}};
121 | store_fifo_q <= {MAX_OUTSTND_TXN{STORE_NONE}};
122 | end
123 | else begin
124 | gnt_fifo_q <= gnt_fifo_n;
125 | int_fifo_q <= int_fifo_n;
126 | store_fifo_q <= store_fifo_n;
127 | end
128 | end
129 |
130 | // Locate oldest entry in FIFO
131 | // FIFOs for gnt error and integrity bit operate on the same control signals,
132 | // picking oldest index from gnt fifo.
133 | always_comb begin
134 | oldest_txn = '0;
135 | for (int i = 0; i < MAX_OUTSTND_TXN; i++) begin
136 | if (gnt_fifo_q[i] != GNT_NONE) begin
137 | oldest_txn = i;
138 | end
139 | end
140 | end
141 |
142 | // GNT error from the oldest transaction
143 | assign exp_gnt_err = (gnt_fifo_q[oldest_txn] == GNT_ERR);
144 |
145 | // Assert that grant error bit comes out in order
146 | a_data_obi_gnt_fifo :
147 | assert property (@(posedge clk) disable iff (!rst_n)
148 | m_c_obi_data_if.s_rvalid.rvalid |-> exp_gnt_err == gntpar_err_resp)
149 | else `uvm_error("mpu", "GNT error bit not correct")
150 |
151 |
152 | // GNT error from the oldest transaction
153 | assign exp_int = (int_fifo_q[oldest_txn] == INT);
154 |
155 | // Assert that trans integrity bit comes out in order
156 | a_data_obi_int_fifo :
157 | assert property (@(posedge clk) disable iff (!rst_n)
158 | m_c_obi_data_if.s_rvalid.rvalid |-> exp_int == resp_o.integrity)
159 | else `uvm_error("mpu", "Integrity bit not correct")
160 |
161 | // Store bit from the oldest transaction
162 | assign exp_store = (store_fifo_q[oldest_txn] == STORE);
163 |
164 | // Assert that trans integrity bit comes out in order
165 | a_data_obi_store_fifo :
166 | assert property (@(posedge clk) disable iff (!rst_n)
167 | m_c_obi_data_if.s_rvalid.rvalid |-> exp_store == resp_is_store)
168 | else `uvm_error("mpu", "Store bit not correct")
169 | endmodule
170 |
--------------------------------------------------------------------------------
/rtl/cv32e40s_register_file.sv:
--------------------------------------------------------------------------------
1 | // Copyright 2018 ETH Zurich and University of Bologna.
2 | // Copyright and related rights are licensed under the Solderpad Hardware
3 | // License, Version 0.51 (the "License"); you may not use this file except in
4 | // compliance with the License. You may obtain a copy of the License at
5 | // http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
6 | // or agreed to in writing, software, hardware and materials distributed under
7 | // this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
8 | // CONDITIONS OF ANY KIND, either express or implied. See the License for the
9 | // specific language governing permissions and limitations under the License.
10 |
11 | /////////////////////////////////////////////////////////////////////////////////
12 | // Engineer: Francesco Conti - f.conti@unibo.it //
13 | // //
14 | // Additional contributions by: //
15 | // Michael Gautschi - gautschi@iis.ee.ethz.ch //
16 | // Davide Schiavone - pschiavo@iis.ee.ethz.ch //
17 | // Halfdan Bechmann - halfdan.bechmann@silabs.com //
18 | // //
19 | // Design Name: RISC-V register file //
20 | // Project Name: RI5CY //
21 | // Language: SystemVerilog //
22 | // //
23 | // Description: Register file with 31x registers. Register 0 is fixed to 0. //
24 | // This register file is based on flip-flops. The register //
25 | // width is configurable to allow adding a parity bit or ECC. //
26 | // //
27 | /////////////////////////////////////////////////////////////////////////////////
28 |
29 | module cv32e40s_register_file import cv32e40s_pkg::*;
30 | #(
31 | parameter int unsigned REGFILE_NUM_READ_PORTS = 2,
32 | parameter rv32_e RV32 = RV32I
33 | )
34 | (
35 | // Clock and Reset
36 | input logic clk,
37 | input logic rst_n,
38 |
39 | input logic hint_instr_id_i,
40 | input logic hint_instr_wb_i,
41 | input logic dummy_instr_id_i,
42 | input logic dummy_instr_wb_i,
43 |
44 | // Read ports
45 | input rf_addr_t raddr_i [REGFILE_NUM_READ_PORTS],
46 | output logic [REGFILE_WORD_WIDTH-1:0] rdata_o [REGFILE_NUM_READ_PORTS],
47 |
48 | // Write ports
49 | input rf_addr_t waddr_i [REGFILE_NUM_WRITE_PORTS],
50 | input logic [REGFILE_WORD_WIDTH-1:0] wdata_i [REGFILE_NUM_WRITE_PORTS],
51 | input logic we_i [REGFILE_NUM_WRITE_PORTS]
52 | );
53 |
54 | // When implemented, reset registers with valid ECC (w/every other ecc bit inverted)
55 | localparam logic [REGFILE_WORD_WIDTH-1:0] RF_REG_RV = (SECURE) ? {6'b10_1010, 32'h0} : 32'h0;
56 |
57 | // Number of regfile integer registers
58 | localparam REGFILE_NUM_WORDS = (RV32 == RV32I) ? 32 : 16;
59 | localparam REGFILE_IMPL_ADDR_WIDTH = $clog2(REGFILE_NUM_WORDS);
60 |
61 | // integer register file
62 | logic [REGFILE_WORD_WIDTH-1:0] mem [REGFILE_NUM_WORDS];
63 | logic [REGFILE_WORD_WIDTH-1:0] mem_gated [REGFILE_NUM_WORDS];
64 |
65 | // write enable signals for all registers
66 | logic [REGFILE_NUM_WORDS-1:0] we_dec[REGFILE_NUM_WRITE_PORTS];
67 |
68 | //-----------------------------------------------------------------------------
69 | //-- READ : Read address decoder RAD
70 | //-----------------------------------------------------------------------------
71 | generate
72 | if (SECURE) begin
73 | assign mem_gated[0] = (dummy_instr_id_i || hint_instr_id_i) ? mem[0] : RF_REG_RV;
74 | for (genvar addr=1; addr < REGFILE_NUM_WORDS; addr++) begin
75 | assign mem_gated[addr] = mem[addr];
76 | end
77 | end else begin
78 | assign mem_gated = mem;
79 | end
80 | endgenerate
81 |
82 | genvar ridx;
83 | generate
84 | for (ridx=0; ridx