├── 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