├── .gitignore ├── sim └── ahb3lite │ ├── run │ ├── Makefile │ └── Makefile.include │ └── bin │ ├── Makefile.riviera │ ├── Makefile.include │ └── Makefile ├── docs ├── tex │ ├── tableofcontents.tex │ ├── history.tex │ ├── references.tex │ ├── resources.tex │ ├── setup.tex │ ├── introduction.tex │ ├── configuration.tex │ ├── preamble.tex │ ├── interfaces-ahblite.tex │ └── specification.tex ├── assets │ ├── img │ │ ├── CONFIG.png │ │ ├── RoaLogicHeader.eps │ │ ├── AHB-Lite_PLIC_Worksheet.png │ │ ├── plic-if-eps-converted-to.pdf │ │ ├── plic-ports-eps-converted-to.pdf │ │ ├── Tagged_Logo-eps-converted-to.pdf │ │ ├── plic-system-eps-converted-to.pdf │ │ ├── RoaLogicHeader-eps-converted-to.pdf │ │ ├── plic-handshake-eps-converted-to.pdf │ │ └── PLIC-block-diagram-eps-converted-to.pdf │ └── csv │ │ ├── configreg.xlsx │ │ └── RegisterMapping.xlsx ├── AHB-Lite_PLIC_Datasheet.pdf ├── markdown │ ├── frontmatter.md │ ├── compile.sh │ └── lpp.pl ├── AHB-Lite_PLIC_Markdown.tex ├── AHB-Lite_PLIC_Datasheet.tex ├── pkg │ └── roalogictitle.sty └── Getting_Started.md ├── assets ├── img │ ├── CONFIG.png │ ├── Folders.png │ ├── plic-if.png │ ├── RoaLogicLogo.png │ ├── plic-ports.png │ ├── plic-system.png │ ├── plic-handshake.png │ ├── PLIC-block-diagram.png │ └── AHB-Lite_PLIC_Worksheet.png └── css │ └── style.scss ├── .gitmodules ├── _config.yml ├── rtl ├── filelist_apb4.f ├── filelist_ahb3lite.f └── verilog │ ├── LICENSE.txt │ ├── core │ ├── plic_cell.sv │ ├── plic_target.sv │ ├── plic_priority_index.sv │ ├── plic_gateway.sv │ ├── plic_core.sv │ └── plic_dynamic_registers.sv │ ├── apb4 │ └── apb4_plic_top.sv │ └── ahb3lite │ └── ahb3lite_plic_top.sv ├── README.md ├── _layouts └── default.html ├── bench └── verilog │ ├── testbench_top.sv │ ├── ahb3lite_bfm.sv │ └── test.sv └── LICENSE.md /.gitignore: -------------------------------------------------------------------------------- 1 | docs/build 2 | 3 | -------------------------------------------------------------------------------- /sim/ahb3lite/run/Makefile: -------------------------------------------------------------------------------- 1 | ../bin/Makefile -------------------------------------------------------------------------------- /docs/tex/tableofcontents.tex: -------------------------------------------------------------------------------- 1 | \tableofcontents 2 | \newpage -------------------------------------------------------------------------------- /sim/ahb3lite/run/Makefile.include: -------------------------------------------------------------------------------- 1 | ../bin/Makefile.include -------------------------------------------------------------------------------- /assets/img/CONFIG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoaLogic/plic/HEAD/assets/img/CONFIG.png -------------------------------------------------------------------------------- /assets/img/Folders.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoaLogic/plic/HEAD/assets/img/Folders.png -------------------------------------------------------------------------------- /assets/img/plic-if.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoaLogic/plic/HEAD/assets/img/plic-if.png -------------------------------------------------------------------------------- /assets/img/RoaLogicLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoaLogic/plic/HEAD/assets/img/RoaLogicLogo.png -------------------------------------------------------------------------------- /assets/img/plic-ports.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoaLogic/plic/HEAD/assets/img/plic-ports.png -------------------------------------------------------------------------------- /assets/img/plic-system.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoaLogic/plic/HEAD/assets/img/plic-system.png -------------------------------------------------------------------------------- /docs/assets/img/CONFIG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoaLogic/plic/HEAD/docs/assets/img/CONFIG.png -------------------------------------------------------------------------------- /assets/img/plic-handshake.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoaLogic/plic/HEAD/assets/img/plic-handshake.png -------------------------------------------------------------------------------- /docs/AHB-Lite_PLIC_Datasheet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoaLogic/plic/HEAD/docs/AHB-Lite_PLIC_Datasheet.pdf -------------------------------------------------------------------------------- /docs/assets/csv/configreg.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoaLogic/plic/HEAD/docs/assets/csv/configreg.xlsx -------------------------------------------------------------------------------- /assets/img/PLIC-block-diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoaLogic/plic/HEAD/assets/img/PLIC-block-diagram.png -------------------------------------------------------------------------------- /docs/assets/img/RoaLogicHeader.eps: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoaLogic/plic/HEAD/docs/assets/img/RoaLogicHeader.eps -------------------------------------------------------------------------------- /docs/assets/csv/RegisterMapping.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoaLogic/plic/HEAD/docs/assets/csv/RegisterMapping.xlsx -------------------------------------------------------------------------------- /assets/img/AHB-Lite_PLIC_Worksheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoaLogic/plic/HEAD/assets/img/AHB-Lite_PLIC_Worksheet.png -------------------------------------------------------------------------------- /docs/assets/img/AHB-Lite_PLIC_Worksheet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoaLogic/plic/HEAD/docs/assets/img/AHB-Lite_PLIC_Worksheet.png -------------------------------------------------------------------------------- /docs/assets/img/plic-if-eps-converted-to.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoaLogic/plic/HEAD/docs/assets/img/plic-if-eps-converted-to.pdf -------------------------------------------------------------------------------- /docs/assets/img/plic-ports-eps-converted-to.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoaLogic/plic/HEAD/docs/assets/img/plic-ports-eps-converted-to.pdf -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "submodules/ahb3lite_pkg"] 2 | path = submodules/ahb3lite_pkg 3 | url = https://github.com/roalogic/ahb3lite_pkg.git 4 | -------------------------------------------------------------------------------- /docs/assets/img/Tagged_Logo-eps-converted-to.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoaLogic/plic/HEAD/docs/assets/img/Tagged_Logo-eps-converted-to.pdf -------------------------------------------------------------------------------- /docs/assets/img/plic-system-eps-converted-to.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoaLogic/plic/HEAD/docs/assets/img/plic-system-eps-converted-to.pdf -------------------------------------------------------------------------------- /docs/assets/img/RoaLogicHeader-eps-converted-to.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoaLogic/plic/HEAD/docs/assets/img/RoaLogicHeader-eps-converted-to.pdf -------------------------------------------------------------------------------- /docs/assets/img/plic-handshake-eps-converted-to.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoaLogic/plic/HEAD/docs/assets/img/plic-handshake-eps-converted-to.pdf -------------------------------------------------------------------------------- /docs/assets/img/PLIC-block-diagram-eps-converted-to.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/RoaLogic/plic/HEAD/docs/assets/img/PLIC-block-diagram-eps-converted-to.pdf -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-dinky 2 | title: AHB-Lite PLIC 3 | description: RISC-V Platform Level Interrupt Controller 4 | show_downloads: true 5 | show_license: true 6 | license: BSD License 7 | -------------------------------------------------------------------------------- /docs/markdown/frontmatter.md: -------------------------------------------------------------------------------- 1 | --- 2 | Title: AHB-Lite Platform-Level Interrupt Controller (PLIC) 3 | Category: Datasheet 4 | Author: Roa Logic 5 | --- 6 | # AHB-Lite Platform-Level Interrupt Controller (PLIC) Datasheet 7 | 8 | ## Contents 9 | -------------------------------------------------------------------------------- /rtl/filelist_apb4.f: -------------------------------------------------------------------------------- 1 | verilog/core/plic_dynamic_registers.sv 2 | verilog/core/plic_priority_index.sv 3 | verilog/core/plic_cell.sv 4 | verilog/core/plic_target.sv 5 | verilog/core/plic_gateway.sv 6 | verilog/core/plic_core.sv 7 | verilog/apb4/apb4_plic_top.sv 8 | 9 | -------------------------------------------------------------------------------- /rtl/filelist_ahb3lite.f: -------------------------------------------------------------------------------- 1 | verilog/core/plic_dynamic_registers.sv 2 | verilog/core/plic_priority_index.sv 3 | verilog/core/plic_cell.sv 4 | verilog/core/plic_target.sv 5 | verilog/core/plic_gateway.sv 6 | verilog/core/plic_core.sv 7 | verilog/ahb3lite/ahb3lite_plic_top.sv 8 | 9 | -------------------------------------------------------------------------------- /docs/tex/history.tex: -------------------------------------------------------------------------------- 1 | \chapter{Revision History} 2 | 3 | \setlength\LTleft{0pt} 4 | \setlength\LTright{0pt} 5 | 6 | \begin{longtable}{@{\extracolsep{\fill}}ccp{8cm}@{}} 7 | \toprule 8 | \textbf{Date} & \textbf{Rev.} & \textbf{Comments}\\ 9 | \midrule 10 | \endhead 11 | 13-Oct-2017 & 1.0 & Initial Release\\ 12 | 01-Dec-2017 & 1.1 & RISC-V Privileged Spec v1.10 compliance\\ 13 | & & \\ 14 | & & \\ 15 | \bottomrule 16 | \caption{Revision History} 17 | \label{tab:REVS} 18 | \end{longtable} 19 | -------------------------------------------------------------------------------- /docs/AHB-Lite_PLIC_Markdown.tex: -------------------------------------------------------------------------------- 1 | \documentclass[oneside,11pt]{book} 2 | 3 | % Document Setup 4 | \input{markdown/preamble} 5 | \input{markdown/setup.tex} 6 | 7 | \begin{document} 8 | 9 | \mainmatter 10 | 11 | \input{markdown/introduction.tex} 12 | 13 | \input{markdown/specification.tex} 14 | 15 | \input{markdown/configuration.tex} 16 | 17 | \input{markdown/interfaces.tex} 18 | 19 | \input{markdown/resources.tex} 20 | 21 | \input{markdown/references.tex} 22 | 23 | \input{markdown/history.tex} 24 | 25 | \listoftodos % Temporary list of ToDo items 26 | 27 | \end{document} 28 | -------------------------------------------------------------------------------- /docs/AHB-Lite_PLIC_Datasheet.tex: -------------------------------------------------------------------------------- 1 | \documentclass[a4paper,oneside,11pt,openany]{book} 2 | 3 | % Document Setup 4 | \input{tex/preamble.tex} 5 | \input{tex/setup.tex} 6 | 7 | % \usepackage{showframe} 8 | 9 | \begin{document} 10 | 11 | %\frontmatter 12 | 13 | \maketitle 14 | %\thispagestyle{empty} 15 | 16 | %\mainmatter 17 | 18 | \tableofcontents 19 | 20 | % \listoftodos % Temporary list of ToDo items 21 | 22 | \input{tex/introduction.tex} 23 | 24 | \input{tex/specification.tex} 25 | 26 | \input{tex/configuration.tex} 27 | 28 | \input{tex/interfaces.tex} 29 | 30 | \input{tex/resources.tex} 31 | 32 | \input{tex/references.tex} 33 | 34 | \input{tex/history.tex} 35 | 36 | \end{document} 37 | -------------------------------------------------------------------------------- /docs/tex/references.tex: -------------------------------------------------------------------------------- 1 | \chapter{References} 2 | 3 | The PLIC is designed to be compliant with the following specifications, as licensed under the Creative Commons Attribution 4.0 International License: 4 | 5 | \begin{quote} 6 | ``The \href{https://github.com/riscv/riscv-isa-manual/blob/master/release/riscv-spec-v2.2.pdf}{RISC-V Instruction Set Manual, Volume I: User-Level ISA, Document 7 | Version 2.2}", Editors Andrew Waterman and Krste Asanović,RISC-V 8 | Foundation, May 2017. 9 | \end{quote} 10 | 11 | \begin{quote} 12 | ``The \href{https://github.com/riscv/riscv-isa-manual/blob/master/release/riscv-privileged-v1.10.pdf}{RISC-VInstruction Set Manual, Volume II: Privileged Architecture, 13 | Version 1.10}", Editors Andrew Waterman and Krste Asanović, RISC-V 14 | Foundation, May 2017. 15 | \end{quote} 16 | -------------------------------------------------------------------------------- /docs/tex/resources.tex: -------------------------------------------------------------------------------- 1 | \chapter{Resources} 2 | 3 | Below are some example implementations for various platforms. All implementations are push button, with no effort undertaken to reduce area or improve performance. 4 | \setlength\LTleft{0pt} 5 | \setlength\LTright{0pt} 6 | 7 | \begin{longtable}[]{@{\extracolsep{\fill}}lcccc@{}} 8 | \toprule 9 | \textbf{Platform} & \textbf{DFF} & \textbf{Logic Cells/Elements} & 10 | \textbf{Memory} & \textbf{Performance (MHz)}\tabularnewline 11 | \midrule 12 | \endhead 13 | Altera Cyclone4 & 1234 & 4470 LEs & 0 & \tabularnewline 14 | & & & &\tabularnewline 15 | & & & &\tabularnewline 16 | \bottomrule 17 | \caption{Resource Utilisation Examples} 18 | \label{tab:RESOURCES} 19 | \end{longtable} 20 | 21 | Note: This table will be updated as more examples are compiled. 22 | -------------------------------------------------------------------------------- /docs/markdown/compile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | topfile="AHB-Lite_PLIC_Markdown" 4 | 5 | # Run from markdown directory only 6 | curdir=${PWD##*/} 7 | 8 | if [ "$curdir" != "markdown" ] 9 | then 10 | echo "Must run from markdown directory" 11 | exit 12 | fi 13 | 14 | # Pre-process LaTeX Source 15 | for entry in ../tex/*.tex 16 | do 17 | base="${entry##*/}" 18 | ./lpp.pl $entry > $base 19 | done 20 | 21 | 22 | # Generate new Markdown 23 | cd .. 24 | pandoc --atx-headers \ 25 | --base-header-level=2 \ 26 | --number-sections \ 27 | --default-image-extension=png \ 28 | --file-scope \ 29 | --toc \ 30 | --toc-depth=1 \ 31 | -t markdown_github \ 32 | -B markdown/frontmatter.md \ 33 | -o ../DATASHEET.md \ 34 | $topfile.tex 35 | 36 | cd markdown 37 | 38 | # Remove Preprocessed LaTeX source 39 | rm *.tex 40 | -------------------------------------------------------------------------------- /docs/tex/setup.tex: -------------------------------------------------------------------------------- 1 | % Load Roalogic Title Page Generator 2 | \usepackage{pkg/roalogictitle} 3 | 4 | \graphicspath{ {./assets/img/} } 5 | 6 | % Document Variables 7 | 8 | \title{AHB-Lite Platform Level Interrupt Controller} 9 | \heading{AHB-Lite Platform Level Interrupt Controller} 10 | \author{Roa Logic} 11 | \date{1st December, 2017} 12 | \version{1.1} 13 | \doctype{Datasheet} 14 | \project{http://roalogic.github.io/plic} 15 | \author{Paul Hardy} 16 | 17 | % Set page headers/footer 18 | \pagestyle{fancy} 19 | \fancyhf{} 20 | \fancyhead[L]{\theheading\space(v\theversion)} 21 | \fancyhead[R]{\includegraphics[width=50px,trim=0 25px 0 0]{assets/img/RoaLogicHeader}} 22 | \fancyfoot[C]{\thepage} 23 | % \fancyhead[R]{\thepage} 24 | % \fancyhead[L]{AHB-Lite Platform Level Interrupt Controller} 25 | % \fancyfoot[C]{\textcircled{c} Roa Logic} 26 | 27 | %\newcommand*{\MARKDOWN}{}% 28 | -------------------------------------------------------------------------------- /docs/markdown/lpp.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | 3 | 4 | # print "Latex PreProcessor v0.1\n"; 5 | 6 | my @defines = qw/MARKDOWN/; 7 | my @if = qw/0/; 8 | my @skip = qw/0/; 9 | 10 | 11 | #Go through input files 12 | while (<>) { 13 | chomp; 14 | # print $_; 15 | 16 | #get rid of comments; they mess up the checks 17 | s/%.*//; 18 | 19 | 20 | #check for new define 21 | if (/\\newcommand\*{\\(\w+)}{}/) { 22 | push @defines, $1; 23 | next; 24 | } 25 | 26 | 27 | #check for if 28 | if (/\\ifdefined\\(\w+)/) { 29 | my $index = 0; 30 | ++$index until $defines[$index] == $1 or $index > $#defines; 31 | 32 | if ($index > $#defines) { 33 | #value not found 34 | unshift @skip, 1; 35 | } else { 36 | #value found 37 | unshift @skip,0; 38 | } 39 | 40 | #found an if 41 | unshift @if,1; 42 | 43 | next; 44 | } 45 | 46 | 47 | #check for else 48 | if (/\\else/) { 49 | die "ELSE without IF\n" if $if[0] == 0; 50 | 51 | if ($skip[0] == 0) { 52 | $skip[0] = 1; 53 | } else { 54 | $skip[0] = 0; 55 | } 56 | 57 | next; 58 | } 59 | 60 | 61 | #check for end-if 62 | if (/\\fi\s*$/) { 63 | die "FI without IF\n" if $if[0] == 0; 64 | 65 | shift @if; 66 | shift @skip; 67 | 68 | next; 69 | } 70 | 71 | 72 | #write string 73 | print "$_\n" unless $skip[0]; 74 | } 75 | 76 | -------------------------------------------------------------------------------- /docs/tex/introduction.tex: -------------------------------------------------------------------------------- 1 | \chapter{Product Brief} 2 | 3 | The Roa Logic AHB-Lite PLIC (Platform Level Interrupt Controller) IP is a fully parameterised soft IP implementing the Interrupt Controller defined in the \emph{\href{https://github.com/riscv/riscv-isa-manual/blob/master/release/riscv-privileged-v1.10.pdf}{RISC-V Privileged v1.10 specification}}\footnote{Full specification details are provided in the References section}. 4 | 5 | The IP features an AHB-Lite Slave interface, fully compliant with the \emph{\href{https://www.arm.com/products/system-ip/amba-specifications}{AMBA 3 AHB-Lite v1.0}} specifications. 6 | 7 | Bus address and data widths as well as the number of Interrupt Sources and Targets supported are configurable via compile-time parameters. The controller further supports user configurable priority levels and pending events, in addition to interrupt masking via programmable priority thresholds. 8 | 9 | \begin{figure}[!htb] 10 | \includegraphics{assets/img/plic-ports} 11 | \caption{PLIC Port Diagram} 12 | \label{fig:PORTDIAG} 13 | \end{figure} 14 | 15 | \section{Features} 16 | 17 | \begin{itemize} 18 | \item 19 | AHB-Lite Interface with parameterised address and data width 20 | \item 21 | User defined number of Interrupt Sources and Targets 22 | \item 23 | User defined priority level per Interrupt Source 24 | \item 25 | Interrupt masking per target via Priority Threshold support 26 | \item 27 | User defined Interrupt Pending queue depth per source 28 | \end{itemize} 29 | -------------------------------------------------------------------------------- /docs/pkg/roalogictitle.sty: -------------------------------------------------------------------------------- 1 | % Title Page generator 2 | 3 | %Logo 4 | %Title 5 | %DocType 6 | %Project 7 | %Date 8 | 9 | % Define Package 10 | \ProvidesPackage{pkg/roalogictitle}[2017/10/01 v1] 11 | \RequirePackage{graphicx} 12 | 13 | % Define new variables 14 | \newcommand*{\project}[1]{\gdef\@project{#1}% 15 | } 16 | 17 | \newcommand*{\doctype}[1]{\gdef\@doctype{#1}% 18 | } 19 | 20 | \newcommand*{\header}[1]{\gdef\@header{#1}% 21 | } 22 | 23 | \newcommand*{\version}[1]{\gdef\@version{#1}% 24 | } 25 | 26 | \newcommand*{\heading}[1]{\gdef\@heading{#1}% 27 | } 28 | 29 | \appendiargdef{\version}{% 30 | \begingroup 31 | \renewcommand{\thanks}[1]{} 32 | \protected@xdef\theversion{#1} 33 | \endgroup} 34 | 35 | \appendiargdef{\heading}{% 36 | \begingroup 37 | \renewcommand{\thanks}[1]{} 38 | \protected@xdef\theheading{#1} 39 | \endgroup} 40 | 41 | % Overload \maketitle with new layout 42 | \renewcommand*{\maketitle}{% 43 | \hypersetup{pageanchor=false} 44 | \begin{titlepage} 45 | \par 46 | \vspace{3cm} 47 | {\raggedleft% 48 | \includegraphics[width=12cm]{assets/img/Tagged_Logo.eps}\par 49 | }\vspace{1cm} 50 | \centering 51 | {\huge\bfseries\@title\unskip\strut\par} 52 | \vspace{1cm} 53 | {\LARGE\itshape\@doctype\space(v\@version)\unskip\strut\par} 54 | \vspace{1cm} 55 | {\scshape\Large\@project\unskip\strut\par} 56 | \vspace{1cm} 57 | {\large \@date\par} 58 | \vspace{7cm} 59 | {\scshape\large \copyright\space Roa Logic B.V. \par} 60 | 61 | \vfill 62 | 63 | \end{titlepage} 64 | \hypersetup{pageanchor=true} 65 | } 66 | \endinput 67 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AHB-Lite Platform-Level Interrupt Controller (PLIC) 2 | 3 | ## Overview 4 | 5 | Fully Parameterized & Programmable Platform Level Interrupt Controller (PLIC) for RISC-V based Processor Systems supporting a user-defined number of interrupt sources and targets, and featuring a single AHB-Lite Slave interface 6 | 7 | The core supports a programmable number of simultaneous pending interrupt requests per source and individual routing of those interrupt requests to each target, full interrupt prioritisation of each interrupt source and separate enables per target via a matrix of interrupt enable bits. 8 | 9 | To reduce latency, the PLIC core presents all asserted interrupts to the target in priority order, queuing them so that a software interrupt handler can service all pending interrupts without the need to restore the interrupted context. 10 | 11 | ![Example PLIC System Diagram](assets/img/plic-system.png) 12 | 13 | ## Documentation 14 | 15 | - [Datasheet](DATASHEET.md) 16 | - [PDF Format](docs/AHB-Lite_PLIC_Datasheet.pdf) 17 | - [Register Map Worksheet](docs/assets/csv/RegisterMapping.xlsx) 18 | 19 | ## Features 20 | 21 | - AHB-Lite Interface with programmable address and data width 22 | - User defined number of Interrupt Sources & Targets 23 | - User defined priority level per Interrupt Source 24 | - Interrupt masking per target via Priority Threshold support 25 | - User defined Interrupt Pending queue depth per source 26 | 27 | ## Compatibility 28 | 29 | Compliant to the [RISC-V Privilege Level 1.9, 1.9.1, 1.10 specifications](https://github.com/riscv/riscv-isa-manual/releases/tag/archive) 30 | 31 | ## Interfaces 32 | 33 | - AHB3 Lite 34 | - Dynamic Registers 35 | 36 | The PLIC core implements Dynamic Registers, which means the registers and register mapping are automatically generated based on the parameters provided to the core. The core prints the register mapping during simulation (and for some tools during synthesis). 37 | 38 | ## License 39 | 40 | Released under the RoaLogic [BSD License](/LICENSE.md) 41 | 42 | ## Dependencies 43 | Requires the Roa Logic [AHB3Lite Package](). This is included as a submodule. 44 | After cloning the git repository, perform a `git submodule init` to download the submodule. 45 | -------------------------------------------------------------------------------- /assets/css/style.scss: -------------------------------------------------------------------------------- 1 | --- 2 | --- 3 | 4 | @import "{{ site.theme }}"; 5 | 6 | body { 7 | background-color: #FFFFFF; 8 | } 9 | 10 | /* Add Roa Logic Font */ 11 | h1, h2, h3 { 12 | font-family: Montserrat, Monaco, serif; 13 | } 14 | 15 | h4, h5, h6 { 16 | font-family: Montserrat, Monaco, serif; 17 | font-weight: 700; 18 | } 19 | 20 | th { 21 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; 22 | } 23 | 24 | h1.header { 25 | font-family: Montserrat, sans-serif; 26 | } 27 | 28 | /* Roa Logic Blue for Links */ 29 | a { 30 | color: #050692; 31 | } 32 | 33 | /* Reduce left margin by 10px */ 34 | header { 35 | padding: 34px 25px 22px 40px; 36 | background-color: #159957; 37 | background-image: linear-gradient(120deg, #155799, #159957); 38 | -webkit-border-radius: 4px; 39 | -moz-border-radius: 4px; 40 | border-radius: 4px; 41 | border: 0px; 42 | margin: 30px 25px; 43 | } 44 | 45 | footer { 46 | padding-left: 40px; 47 | } 48 | 49 | /* Recolour Buttons (Roa Logic Blue) */ 50 | header li { 51 | background: #0506CF; 52 | background: -moz-linear-gradient(top, #0506CF 0%, #050692 100%); 53 | background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f8f8f8), color-stop(100%,#dddddd)); 54 | background: -webkit-linear-gradient(top, #0506CF 0%,#050692 100%); 55 | background: -o-linear-gradient(top, #0506CF 0%,#050692 100%); 56 | background: -ms-linear-gradient(top, #0506CF 0%,#050692 100%); 57 | background: linear-gradient(top, #0506CF 0%,#050692 100%); 58 | 59 | border-radius:4px; 60 | border:1px solid #0D0D0D; 61 | 62 | -webkit-box-shadow: inset 0px 1px 1px 0 rgba(0,102,204, 1); 63 | box-shadow: inset 0px 1px 1px 0 rgba(0,102,204, 1); 64 | 65 | } 66 | header li:hover { 67 | background: #0066CC; 68 | background: -moz-linear-gradient(top, #0066CC 0%, #004080 100%); 69 | background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#f8f8f8), color-stop(100%,#dddddd)); 70 | background: -webkit-linear-gradient(top, #0066CC 0%,#004080 100%); 71 | background: -o-linear-gradient(top, #0066CC 0%,#004080 100%); 72 | background: -ms-linear-gradient(top, #0066CC 0%,#004080 100%); 73 | background: linear-gradient(top, #0066CC 0%,#004080 100%); 74 | } 75 | 76 | /* Format Logo in Header */ 77 | p.logo { 78 | /*background-color: #F7F7F7; 79 | border: 1px solid #000;*/ 80 | -webkit-border-radius: 4px; 81 | -moz-border-radius: 4px; 82 | border-radius: 4px; 83 | margin: 0px 10px 10px 0px; 84 | padding: 5px; 85 | } 86 | 87 | code, pre { 88 | font-size: 12px; 89 | } 90 | -------------------------------------------------------------------------------- /rtl/verilog/LICENSE.txt: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////// 2 | // // 3 | // ██████╗ ██████╗ █████╗ // 4 | // ██╔══██╗██╔═══██╗██╔══██╗ // 5 | // ██████╔╝██║ ██║███████║ // 6 | // ██╔══██╗██║ ██║██╔══██║ // 7 | // ██║ ██║╚██████╔╝██║ ██║ // 8 | // ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝ // 9 | // ██╗ ██████╗ ██████╗ ██╗ ██████╗ // 10 | // ██║ ██╔═══██╗██╔════╝ ██║██╔════╝ // 11 | // ██║ ██║ ██║██║ ███╗██║██║ // 12 | // ██║ ██║ ██║██║ ██║██║██║ // 13 | // ███████╗╚██████╔╝╚██████╔╝██║╚██████╗ // 14 | // ╚══════╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═════╝ // 15 | // // 16 | // Technology independent (inferrable) 1RW RAM // 17 | // // 18 | ///////////////////////////////////////////////////////////////// 19 | // // 20 | // Copyright (C) 2014-2017 ROA Logic BV // 21 | // www.roalogic.com // 22 | // // 23 | // This source file may be used and distributed without // 24 | // restriction provided that this copyright statement is not // 25 | // removed from the file and that any derivative work contains // 26 | // the original copyright notice and the associated disclaimer.// 27 | // // 28 | // THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY // 29 | // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED // 30 | // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS // 31 | // FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR // 32 | // OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, // 33 | // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES // 34 | // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE // 35 | // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR // 36 | // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF // 37 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // 38 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT // 39 | // OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // 40 | // POSSIBILITY OF SUCH DAMAGE. // 41 | // // 42 | ///////////////////////////////////////////////////////////////// 43 | 44 | -------------------------------------------------------------------------------- /_layouts/default.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | {% seo %} 8 | 9 | 10 | 11 | 12 | 15 | 16 | 17 |
18 |
19 | 20 |

{{ site.title | default: site.github.repository_name }}

21 |

{{ site.description | default: site.github.project_tagline }}

22 | 23 | 30 | 31 | {% if site.show_license %} 32 |

License Terms:
{{ site.license }}

33 | {% endif %} 34 | 35 | {% if site.github.is_user_page %} 36 | 39 | {% endif %} 40 | 41 | {% if site.github.is_project_page %} 42 |

This project is maintained by:
{{ site.github.owner_name }}

43 | {% endif %} 44 | 45 |
46 | 47 |
48 | {{ content }} 49 |
50 | 51 | 56 |
57 | 58 | {% if site.google_analytics %} 59 | 67 | {% endif %} 68 | 69 | 70 | -------------------------------------------------------------------------------- /docs/Getting_Started.md: -------------------------------------------------------------------------------- 1 | # Getting Started 2 | 3 | ## Deliverables 4 | 5 | All IP is delivered as a zipped tarball, which can be unzipped with all common compression tools (like unzip, winrar, tar, …). 6 | 7 | The tarball contains a directory structure as outlined below: 8 | 9 | ![](../assets/graphics/Folders.png) 10 | 11 | The *doc* directory contains relevant documents like user guides, application notes, and datasheets. 12 | 13 | The *rtl* directory contains the actual IP design files. Depending on the license agreement the AHB-Lite PLIC is delivered as either encrypted Verilog-HDL or as plain SystemVerilog source files. Encrypted files have the extension “.enc.sv”, plain source files have the extension “.sv”. The files are encryption according to the IEEE-P1735 encryption standard. Encryption keys for Mentor Graphics (Modelsim, Questasim, Precision), Synplicity (Synplify, Synplify-Pro), and Aldec (Active-HDL, Riviera-Pro) are provided. As such there should be no issue targeting any existing FPGA technology. 14 | 15 | If any other synthesis or analysis tool is used then a plain source RTL delivery may be needed. A separate license agreement and NDA is required for such a delivery. 16 | 17 | The *bench* directory contains the (encrypted) source files for the testbench. 18 | 19 | The *sim* directory contains the files/structure to run the simulations. Section ''[Running the testbench](#running-the-testbench)'' provides for instructions on how to use the makefile. 20 | 21 | ## Running the testbench 22 | 23 | The IP comes with a dedicated testbench that tests all features of the design and finally runs a full random test. The testbench is started from a Makefile that is provided with the IP. 24 | 25 | The Makefile is located in the <*install\_dir*>/sim/rtlsim/run directory. The Makefile supports most commonly used simulators; Modelsim/Questasim, Cadence ncsim, Aldec Riviera, and Synopsys VCS. 26 | 27 | To start the simulation, enter the <*install\_dir*>/sim/rtlsim/run directory and type: **make <*simulator*>**. Where simulator is any of: msim (for modelsim/questasim), ncsim (for Cadence ncsim), riviera (for Aldec Riviera-Pro), or vcs (for Synopsys VCS). For example type **make msim** to start the testbench in Modelsim/Questasim. 28 | 29 | ### Self-checking testbench 30 | 31 | The testbenches is a self-checking testbench intended to be executed from the command line. There is no need for a GUI or a waveform viewer. Once the testbench completes it displays a summary and closes the simulator. 32 | 33 | ### Makefile setup 34 | 35 | The simulator is executed in its associated directory. Inside this directory is another Makefile that contains simulator specific commands to start and execute the simulation. The <*install\_dir*>/sim/rtlsim/run/Makefile enters the correct directory and calls the simulator specific Makefile. 36 | 37 | For example modelsim is executed in the <*install\_dir*>/sim/rtlsim/run/msim directory. Typing **make msim** loads the main Makefile, which then enters the msim sub-directory and calls its Makefile. This Makefile contains commands to compile the RTL and testbench sources with Modelsim, start the Modelsim simulator, and run the simulation. 38 | 39 | ### Makefile backup 40 | 41 | The <*install\_dir*>/sim/rtlsim/bin directory contains backups of the original Makefiles. It may be desirable to modify or extend the Makefiles or to completely clean the run directory. Use the backups to restore the original setup. 42 | 43 | ### No Makefile 44 | 45 | For users unfamiliar with Makefiles or those on systems that do not natively support make (e.g. Windows) a run.do file is provided that can be used with Modelsim/Questasim and Riviera-Pro. -------------------------------------------------------------------------------- /docs/tex/configuration.tex: -------------------------------------------------------------------------------- 1 | \chapter{Configurations} 2 | 3 | \section{Core Parameters} \label{sec:core-parameters} 4 | 5 | The size and implementation style of the PLIC module is defined via HDL parameters as specified below: 6 | 7 | \begin{longtable}[c]{@{\extracolsep{\fill}}lccl@{}} 8 | \toprule 9 | \textbf{Parameter} & \textbf{Type} & \textbf{Default} & \textbf{Description}\\ 10 | \midrule 11 | \endhead 12 | \emph{AHB Interface:}\\ 13 | \texttt{HADDR\_SIZE} & Integer & 32 & Width of AHB Address Bus\\ 14 | \texttt{HDATA\_SIZE} & Integer & 32 & Width of AHB Data Buses\\ 15 | & & & \\ 16 | \emph{PLIC Configuration:}\\ 17 | \texttt{SOURCES} & Integer & 16 & Number of Interrupt Sources\\ 18 | \texttt{TARGETS} & Integer & 4 & Number of Interrupt Targets\\ 19 | \texttt{PRIORITIES} & Integer & 8 & Number of Priority Levels\\ 20 | \texttt{MAX\_PENDING\_COUNT} & Integer & 8 & Max number of pending events\\ 21 | \texttt{HAS\_THRESHOLD} & Integer & 1 & Is Threshold Implemented\\ 22 | \texttt{HAS\_CONFIG\_REG} & Integer & 1 & Is Config Reg. Implemented\\ 23 | \bottomrule 24 | \caption{Core Parameters} 25 | \label{tab:CoreParams} 26 | \end{longtable} 27 | 28 | \section{AHB Interface Parameters} 29 | 30 | \subsection{HADDR\_SIZE} 31 | 32 | The \texttt{HADDR\_SIZE} parameter specifies the address bus size to connect to the AHB-Lite based host. Valid values are 32 and 64. The default value is 32. 33 | 34 | \subsection{HDATA\_SIZE} 35 | 36 | The \texttt{HDATA\_SIZE} parameter specifies the data bus size to connect to the AHB-Lite based host. Valid values are 32 and 64. The default value is 32 37 | 38 | \hypertarget{SOURCES}{\subsection{SOURCES}\label{sec:SOURCES}} 39 | 40 | The \texttt{SOURCES} parameter defines the number of individual 41 | interrupt sources supported by the PLIC IP. The default value is 16. The 42 | minimum value is 1. 43 | 44 | \hypertarget{TARGETS}{\subsection{TARGETS}\label{sec:TARGETS}} 45 | 46 | The \texttt{TARGETS} parameter defines the number of targets supported 47 | by the PLIC IP. The default value is 4. The minimum value is 1. 48 | 49 | \pagebreak 50 | 51 | \section{PLIC Interface Parameters} 52 | 53 | \subsection{PRIORITIES} 54 | 55 | The PLIC IP supports prioritisation of individual interrupt sources. The \texttt{PRIORITIES} parameter defines the number of priority levels supported by the PLIC IP. The default value is 8. The minimum value is 1. 56 | 57 | \subsection{MAX\_PENDING\_COUNT} 58 | 59 | An interrupt source may generate multiple edge-triggered interrupts before being fully serviced by the target. To support this the PLIC is able to queue these requests up to a user-defined limit per interrupt source. This limit is defined by the parameter \texttt{MAX\_PENDING\_COUNT}. 60 | 61 | If the number of interrupts generated by a source exceeds the value of \texttt{MAX\_PENDING\_COUNT}, those additional interrupts are silently ignored. 62 | 63 | The default value of \texttt{MAX\_PENDING\_COUNT} is 8. The minimum value is 0. 64 | 65 | \subsection{HAS\_THRESHOLD} 66 | 67 | The PLIC module supports interrupt thresholds -- the masking of individual interrupt sources based on their priority level. 68 | The \texttt{HAS\_THRESHOLD} parameter defines if this capability is enabled. 69 | 70 | The default value is enabled (`1'). To disable, this parameter should be set to `0'. 71 | 72 | \subsection{HAS\_CONFIG\_REG} 73 | 74 | The PLIC module supports an optional Configuration Register, which is documented in section 0. 75 | The \texttt{HAS\_CONFIG\_REG} parameter defines if this capability is enabled. 76 | 77 | The default value is enabled (`1'). To disable, this parameter should be set to `0'. 78 | -------------------------------------------------------------------------------- /sim/ahb3lite/bin/Makefile.riviera: -------------------------------------------------------------------------------- 1 | ##################################################################### 2 | ## ,------. ,--. ,--. ## 3 | ## | .--. ' ,---. ,--,--. | | ,---. ,---. `--' ,---. ## 4 | ## | '--'.'| .-. |' ,-. | | | | .-. | .-. |,--.| .--' ## 5 | ## | |\ \ ' '-' '\ '-' | | '--.' '-' ' '-' || |\ `--. ## 6 | ## `--' '--' `---' `--`--' `-----' `---' `- /`--' `---' ## 7 | ## `---' ## 8 | ## Riviera-Pro Simulator Command File ## 9 | ## ## 10 | ##################################################################### 11 | ## ## 12 | ## Copyright (C) 2017 ROA Logic BV ## 13 | ## www.roalogic.com ## 14 | ## ## 15 | ## This source file may be used and distributed without ## 16 | ## restriction provided that this copyright statement is not ## 17 | ## removed from the file and that any derivative work contains ## 18 | ## the original copyright notice and the associated disclaimer. ## 19 | ## ## 20 | ## THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ## 21 | ## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ## 22 | ## TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ## 23 | ## FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR OR ## 24 | ## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ## 25 | ## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ## 26 | ## NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ## 27 | ## LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ## 28 | ## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ## 29 | ## CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR ## 30 | ## OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ## 31 | ## SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ## 32 | ## ## 33 | ##################################################################### 34 | 35 | all: sim 36 | 37 | ##################################################################### 38 | # Make Targets 39 | ##################################################################### 40 | SIM_OPTS=-c -ses -O2 "-threads 4" +notimingchecks 41 | 42 | .PHONY: sim simw clean 43 | 44 | LOG = $(TOP).log 45 | 46 | sim: vlog 47 | echo "--- Running sim" 48 | vsim $(SIM_OPTS) \ 49 | -l $(LOG) $(TOP) \ 50 | -do "run -all; quit" \ 51 | $(foreach p, $(PARAMS), -g`echo $p | sed -r 's/(\w+)=([^0-9].*)/\1="\2"/'`) 52 | 53 | 54 | simw: vlog 55 | echo "--- Running sim" 56 | vsim $(SIM_OPTS) \ 57 | -l $(LOG) $(TOP) +access +r \ 58 | -do "log -mem -rec /$(TOP)/*; run -all; quit" \ 59 | $(foreach p, $(PARAMS), -g`echo $p | sed -r 's/(\w+)=([^0-9].*)/\1="\2"/'`) 60 | 61 | clean: 62 | @rm -rf work *.log 63 | 64 | 65 | 66 | ##################################################################### 67 | ## VHDL 68 | ##################################################################### 69 | 70 | 71 | ##################################################################### 72 | ## Verilog 73 | ##################################################################### 74 | .PHONY: vlog 75 | 76 | vlog: work $(VLOG) $(VLOG_LIBS) 77 | echo "--- Running vlog" 78 | vlog -work work $(VLOG) \ 79 | -sv2k9 -threads 3 \ 80 | $(foreach d,$(DEFINES),+define+$d) \ 81 | $(foreach d,$(INCDIRS),+incdir+$d) \ 82 | $(foreach l,$(wildcard $(LIBDIRS)),-y $l) \ 83 | +libext$(foreach e,$(LIBEXT),+$e) \ 84 | $(foreach l,$(wildcard $(TECHLIBS)/*.v),-v $l) 85 | echo "--- vlog done" 86 | 87 | 88 | ##################################################################### 89 | ## libraries 90 | ##################################################################### 91 | work: 92 | vlib $@ 93 | -------------------------------------------------------------------------------- /sim/ahb3lite/bin/Makefile.include: -------------------------------------------------------------------------------- 1 | ##################################################################### 2 | ## ,------. ,--. ,--. ## 3 | ## | .--. ' ,---. ,--,--. | | ,---. ,---. `--' ,---. ## 4 | ## | '--'.'| .-. |' ,-. | | | | .-. | .-. |,--.| .--' ## 5 | ## | |\ \ ' '-' '\ '-' | | '--.' '-' ' '-' || |\ `--. ## 6 | ## `--' '--' `---' `--`--' `-----' `---' `- /`--' `---' ## 7 | ## `---' ## 8 | ## RISC-V Platform-Level Interrupt Controller ## 9 | ## Simulator Include File ## 10 | ## ## 11 | ##################################################################### 12 | ## ## 13 | ## Copyright (C) 2017 ROA Logic BV ## 14 | ## www.roalogic.com ## 15 | ## ## 16 | ## This source file may be used and distributed without ## 17 | ## restriction provided that this copyright statement is not ## 18 | ## removed from the file and that any derivative work contains ## 19 | ## the original copyright notice and the associated disclaimer. ## 20 | ## ## 21 | ## THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ## 22 | ## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ## 23 | ## TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ## 24 | ## FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR OR ## 25 | ## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ## 26 | ## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ## 27 | ## NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ## 28 | ## LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ## 29 | ## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ## 30 | ## CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR ## 31 | ## OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ## 32 | ## SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ## 33 | ## ## 34 | ##################################################################### 35 | 36 | ##################################################################### 37 | # Implementation details 38 | ##################################################################### 39 | TECHNOLOGY = 40 | TARGET = 41 | busif = ahb3lite 42 | 43 | 44 | ##################################################################### 45 | # OVL checker 46 | # This can be changed on the command line 47 | ##################################################################### 48 | OVL_ASSERT = OFF 49 | OVL_INIT_MSG = ON 50 | STD_OVL_DIR = /projects/OVL/std_ovl 51 | 52 | 53 | ##################################################################### 54 | # Design constants 55 | ##################################################################### 56 | INCDIRS:= 57 | DEFINES:= 58 | 59 | 60 | ##################################################################### 61 | # Design Sources 62 | ##################################################################### 63 | DUT_SRC_DIR=$(ROOT_DIR)/rtl/verilog 64 | RTL_TOP = $(busif)_plic_top 65 | RTL_VLOG = $(ROOT_DIR)/submodules/$(busif)_pkg/rtl/verilog/$(busif)_pkg.sv \ 66 | $(DUT_SRC_DIR)/core/plic_gateway.sv \ 67 | $(DUT_SRC_DIR)/core/plic_cell.sv \ 68 | $(DUT_SRC_DIR)/core/plic_priority_index.sv \ 69 | $(DUT_SRC_DIR)/core/plic_target.sv \ 70 | $(DUT_SRC_DIR)/core/plic_dynamic_registers.sv \ 71 | $(DUT_SRC_DIR)/core/plic_core.sv \ 72 | $(DUT_SRC_DIR)/$(busif)/$(busif)_plic_top.sv 73 | RTL_VHDL = 74 | 75 | 76 | ##################################################################### 77 | # Testbench Sources 78 | ##################################################################### 79 | TB_PREREQ= 80 | TB_TOP=testbench_top 81 | TB_SRC_DIR=$(ROOT_DIR)/bench/verilog/ 82 | 83 | TB_VLOG = $(TB_SRC_DIR)/testbench_top.sv \ 84 | $(TB_SRC_DIR)/test.sv \ 85 | $(TB_SRC_DIR)/$(busif)_bfm.sv 86 | TB_VHDL = 87 | -------------------------------------------------------------------------------- /bench/verilog/testbench_top.sv: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | // ,------. ,--. ,--. // 3 | // | .--. ' ,---. ,--,--. | | ,---. ,---. `--' ,---. // 4 | // | '--'.'| .-. |' ,-. | | | | .-. | .-. |,--.| .--' // 5 | // | |\ \ ' '-' '\ '-' | | '--.' '-' ' '-' || |\ `--. // 6 | // `--' '--' `---' `--`--' `-----' `---' `- /`--' `---' // 7 | // `---' // 8 | // RISC-V Platform-Level Interrupt Controller Testbench (top) // 9 | // // 10 | ///////////////////////////////////////////////////////////////////// 11 | // // 12 | // Copyright (C) 2017 ROA Logic BV // 13 | // www.roalogic.com // 14 | // // 15 | // This source file may be used and distributed without // 16 | // restriction provided that this copyright statement is not // 17 | // removed from the file and that any derivative work contains // 18 | // the original copyright notice and the associated disclaimer. // 19 | // // 20 | // This soure file is free software; you can redistribute it // 21 | // and/or modify it under the terms of the GNU General Public // 22 | // License as published by the Free Software Foundation, // 23 | // either version 3 of the License, or (at your option) any later // 24 | // versions. The current text of the License can be found at: // 25 | // http://www.gnu.org/licenses/gpl.html // 26 | // // 27 | // This source file is distributed in the hope that it will be // 28 | // useful, but WITHOUT ANY WARRANTY; without even the implied // 29 | // warranty of MERCHANTABILITY or FITTNESS FOR A PARTICULAR // 30 | // PURPOSE. See the GNU General Public License for more details. // 31 | // // 32 | ///////////////////////////////////////////////////////////////////// 33 | 34 | module testbench_top; 35 | parameter SOURCES = 35; //Number of interrupt sources 36 | parameter TARGETS = 4; //Number of interrupt targets 37 | parameter PRIORITIES = 7; //Number of priority levels 38 | parameter MAX_PENDING_COUNT = 8; //Number of 'event' counts 39 | parameter HAS_THRESHOLD = 1; //Has 'Priority' Threshold? 40 | parameter HAS_CONFIG_REG = 1; //Has 'config' register? 41 | 42 | parameter HADDR_SIZE = 16; 43 | parameter HDATA_SIZE = 32; 44 | 45 | 46 | ///////////////////////////////////////////////////////// 47 | // 48 | // Variables 49 | // 50 | //AHB signals 51 | logic HSEL; 52 | logic [HADDR_SIZE -1:0] HADDR; 53 | logic [HDATA_SIZE -1:0] HWDATA; 54 | logic [HDATA_SIZE -1:0] HRDATA; 55 | logic HWRITE; 56 | logic [ 2:0] HSIZE; 57 | logic [ 2:0] HBURST; 58 | logic [ 3:0] HPROT; 59 | logic [ 1:0] HTRANS; 60 | logic HMASTLOCK; 61 | logic HREADY; 62 | logic HREADYOUT; 63 | logic HRESP; 64 | 65 | //Interrupt signals 66 | logic [SOURCES -1:0] src; 67 | logic [TARGETS -1:0] irq; 68 | 69 | 70 | ///////////////////////////////////////////////////////// 71 | // 72 | // Clock & Reset 73 | // 74 | bit HCLK, HRESETn; 75 | initial begin : gen_HCLK 76 | HCLK <= 1'b0; 77 | forever #10 HCLK = ~ HCLK; 78 | end : gen_HCLK 79 | 80 | initial begin : gen_HRESETn; 81 | HRESETn = 1'b1; 82 | //ensure falling edge of HRESETn 83 | #10; 84 | HRESETn = 1'b0; 85 | #32; 86 | HRESETn = 1'b1; 87 | end : gen_HRESETn; 88 | 89 | 90 | ///////////////////////////////////////////////////////// 91 | // 92 | // Instantiate the TB and DUT 93 | // 94 | test #( 95 | .HADDR_SIZE ( HADDR_SIZE ), 96 | .HDATA_SIZE ( HDATA_SIZE ), 97 | .SOURCES ( SOURCES ), 98 | .TARGETS ( TARGETS ), 99 | .PRIORITIES ( PRIORITIES ), 100 | .MAX_PENDING_COUNT ( MAX_PENDING_COUNT ), 101 | .HAS_THRESHOLD ( HAS_THRESHOLD ), 102 | .HAS_CONFIG_REG ( HAS_CONFIG_REG )) 103 | tb ( 104 | .* 105 | ); 106 | 107 | 108 | ahb3lite_plic_top #( 109 | .HADDR_SIZE ( HADDR_SIZE ), 110 | .HDATA_SIZE ( HDATA_SIZE ), 111 | 112 | .SOURCES ( SOURCES ), 113 | .TARGETS ( TARGETS ), 114 | .PRIORITIES ( PRIORITIES ), 115 | .MAX_PENDING_COUNT ( MAX_PENDING_COUNT ), 116 | .HAS_THRESHOLD ( HAS_THRESHOLD ), 117 | .HAS_CONFIG_REG ( HAS_CONFIG_REG ) 118 | ) 119 | dut ( 120 | .* 121 | ); 122 | 123 | assign HREADY = HREADYOUT; 124 | 125 | endmodule : testbench_top 126 | -------------------------------------------------------------------------------- /rtl/verilog/core/plic_cell.sv: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | // ,------. ,--. ,--. // 3 | // | .--. ' ,---. ,--,--. | | ,---. ,---. `--' ,---. // 4 | // | '--'.'| .-. |' ,-. | | | | .-. | .-. |,--.| .--' // 5 | // | |\ \ ' '-' '\ '-' | | '--.' '-' ' '-' || |\ `--. // 6 | // `--' '--' `---' `--`--' `-----' `---' `- /`--' `---' // 7 | // `---' // 8 | // RISC-V Platform-Level Interrupt Controller // 9 | // // 10 | ///////////////////////////////////////////////////////////////////// 11 | // // 12 | // Copyright (C) 2017 ROA Logic BV // 13 | // www.roalogic.com // 14 | // // 15 | // This source file may be used and distributed without // 16 | // restriction provided that this copyright statement is not // 17 | // removed from the file and that any derivative work contains // 18 | // the original copyright notice and the associated disclaimer. // 19 | // // 20 | // THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY // 21 | // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED // 22 | // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS // 23 | // FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR OR // 24 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // 25 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT // 26 | // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; // 27 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) // 28 | // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // 29 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR // 30 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // 31 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // 32 | // // 33 | ///////////////////////////////////////////////////////////////////// 34 | 35 | // +FHDR - Semiconductor Reuse Standard File Header Section ------- 36 | // FILE NAME : plic_cell.sv 37 | // DEPARTMENT : 38 | // AUTHOR : rherveille 39 | // AUTHOR'S EMAIL : 40 | // ------------------------------------------------------------------ 41 | // RELEASE HISTORY 42 | // VERSION DATE AUTHOR DESCRIPTION 43 | // 1.0 2017-07-01 rherveille initial release 44 | // ------------------------------------------------------------------ 45 | // KEYWORDS : RISC-V PLATFORM LEVEL INTERRUPT CONTROLLER - PLIC 46 | // ------------------------------------------------------------------ 47 | // PURPOSE : One source-target combination. Single cell of the 48 | // source-target matrix. 49 | // ------------------------------------------------------------------ 50 | // PARAMETERS 51 | // PARAM NAME RANGE DESCRIPTION DEFAULT UNITS 52 | // ID 1+ ID (source number) 1 53 | // SOURCES 1+ No. of interupt sources 8 54 | // PRIORITIES 1+ No. of priority levels 8 55 | // ------------------------------------------------------------------ 56 | // REUSE ISSUES 57 | // Reset Strategy : none 58 | // Clock Domains : none, asynchronous block 59 | // Critical Timing : 60 | // Test Features : 61 | // Asynchronous I/F : Fully asynchronous block 62 | // Scan Methodology : na 63 | // Instantiations : none 64 | // Synthesizable (y/n) : Yes 65 | // Other : End-points (registers) are in the 66 | // plic_target module 67 | // -FHDR------------------------------------------------------------- 68 | 69 | module plic_cell #( 70 | parameter ID = 1, 71 | parameter SOURCES = 8, 72 | parameter PRIORITIES = 7, 73 | 74 | //These should be localparams, but that's not supported by all tools yet 75 | parameter SOURCES_BITS = $clog2(SOURCES +1), //0=reserved 76 | parameter PRIORITY_BITS = $clog2(PRIORITIES) 77 | ) 78 | ( 79 | input rst_ni, //Asynchronous active low reset 80 | input clk_i, //System clock 81 | 82 | //Interrupt Request 83 | input ip_i, //Interrupt pending 84 | input ie_i, //Interrupt Enable 85 | input [PRIORITY_BITS-1:0] priority_i, //Interrupt priority 86 | 87 | output reg [SOURCES_BITS -1:0] id_o, //Pending interrupt ID 88 | output reg [PRIORITY_BITS-1:0] priority_o //Pending interrupt priority 89 | ); 90 | ////////////////////////////////////////////////////////////////// 91 | // 92 | // Module Body 93 | // 94 | 95 | always @(posedge clk_i,negedge rst_ni) 96 | if (!rst_ni ) priority_o <= 0; 97 | else if ( ip_i && ie_i) priority_o <= priority_i; 98 | else priority_o <= 0; 99 | 100 | always @(posedge clk_i,negedge rst_ni) 101 | if (!rst_ni ) id_o <= 0; 102 | else if ( ip_i && ie_i) id_o <= ID; 103 | else id_o <= 0; 104 | 105 | endmodule : plic_cell 106 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: BSD License Agreement 3 | --- 4 | # BSD License Agreement 5 | 6 | PLEASE CAREFULLY REVIEW THE FOLLOWING TERMS AND CONDITIONS BEFORE DOWNLOADING AND USING THE LICENSED MATERIALS. THIS LICENSE AGREEMENT (“AGREEMENT”) IS A LEGAL AGREEMENT BETWEEN YOU (EITHER A SINGLE INDIVIDUAL, OR A SINGLE LEGAL ENTITY) (“YOU”) AND ROA LOGIC BV (“ROA LOGIC”) COVERING THE PRODUCTS OR SERVICES YOU PURCHASE FROM ROA LOGIC. 7 | 8 | By downloading and/or using or installing products from Roa Logic you automatically agree to and are bound by the terms and conditions of this agreement. 9 | 10 | ## 1. DEFINITIONS 11 | 12 | “Intellectual Property” means any or all of the following and all rights in, arising out of, or associated with: 13 | 14 | 1. All inventions (whether patentable or not), invention disclosures, improvements, trade secrets, proprietary information, know how, technology, algorithms, techniques, methods, devices, technical data, customer lists, and all documentation embodying or evidencing any of the foregoing; 15 | 2. All computer software, source codes, object codes, firmware, development tools, files, records, data, and all media on which any of the foregoing is recorded 16 | 17 | “Product” means an Intellectual Property block consisting of, but not limited to, Verilog, VHDL, and/or SystemVerilog design files, specifications, block diagrams and documentation. 18 | 19 | “Physical Implementation” means any implementation in programmable or non-programmable technologies including, but not limited to Field Programmable Gate Arrays (FPGAs), Complex Programmable Logic Devices (CPLDs), Application Specific Integrated Circuits (ASICs), Application Specific Standard Products (ASSPs) 20 | 21 | “Silicon Device(s)” means any customer Physical Implementation containing a unique part number. 22 | 23 | “You” the opposite contract party as referred to in article 6:231, subsection c, of the Dutch Civil Code, being the party to whom an offer is made by Roa Logic, or with whom an agreement is concluded by Roa Logic, or to whom the Product is supplied. 24 | 25 | ## 2. LICENSE TO USE 26 | 27 | Roa Logic hereby grants you the following limited, non-exclusive, no-charge, and royalty-free licenses to use, modify, and distribute the Product: 28 | 29 | 1. Copyright license 30 | 2. Patent license, where such license only applies to those patent claims licensable by Roa Logic. 31 | 32 | Specifically you are allowed to: 33 | 34 | 1. Use the Product in your design to create, simulate, implement, manufacture, use, and sell a Silicon Device; 35 | 2. Distribute the Product and/or Silicon Device, provided the original disclaimer and copyright notice are retained and this Agreement is part of the distribution. 36 | 37 | ## 3. OWNERSHIP 38 | 39 | The Product, its documentation, and any associated material is owned by Roa Logic and is protected by copyright and other intellectual property right laws. 40 | 41 | Any modification or addition to the Product, documentation, and any associated materials or derivatives thereof, that You intentionally submit to Roa Logic for inclusion in the Product will become part of the Product and thus owned and copyrighted by Roa Logic. By submitting any material for inclusion you wave any ownership, copyright, and patent rights and claims for the use of the submitted material in the Product. 42 | 43 | “Submitting” means any form of electronic, verbal, or written communication sent to Roa Logic or its representatives, including, but not limited to, email, mailing lists, source repositories, and issue tracking systems for the purpose of discussing and improving the Product. 44 | 45 | You shall not remove any copyright, disclaimers, or other notices from any parts of the Product. 46 | 47 | ## 4. DISCLAIMER OF WARRANTY 48 | 49 | The Product is provided “AS IS”. Roa Logic has no obligation to provide maintenance or support services in connection with the Product. 50 | 51 | ROA LOGIC DISCLAIMS ALL WARRANTIES, CONDITIONS AND REPRESENTATIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, THOSE RELATED TO MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, SATISFACTORY QUALITY, ACCURACY OR COMPLETENESS OR RESULTS, CONFORMANCE WITH DESCRIPTION, AND NON-INFRINGEMENT. 52 | 53 | ## 5. LIMITATION OF LIABILITY 54 | 55 | TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL ROA LOGIC BE LIABLE TO YOU OR ANY THIRD PARTY FOR ANY INDIRECT, SPECIAL, CONSEQUENTIAL OR INCIDENTAL DAMAGES WHATSOEVER (INCLUDING, BUT NOT LIMITED TO, DAMAGES FOR LOSS OF PROFIT, BUSINESS INTERRUPTIONS OR LOSS OF INFORMATION) ARISING OUT OF THE USE OR INABILITY TO USE THE PRODUCT WHETHER BASED ON A CLAIM UNDER CONTRACT, TORT OR OTHER LEGAL THEORY, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 56 | 57 | ## 6. APPLICABLE LAW AND CHOICE OF FORUM 58 | 59 | All agreements and contracts between you and Roa Logic, which these conditions are applicable to, shall be governed by Dutch law with the exclusion of the uniform UN Convention on Contracts for the International Sale of Goods (CISG) and other bilateral or multilateral treaties for the purpose of unifying international sales. 60 | 61 | The competent courts in the district where Roa Logic has its registered office in the Netherlands has jurisdiction over all disputes concerning rights and obligations associated with the contractual relations. 62 | 63 | Conversion: If any clause or sentence of this agreement is held by a court of law to be illegal or unenforceable, the remaining provisions of the agreement remain in effect. The failure of Roa Logic to enforce any of the provisions in the agreement does not constitute a waiver of Roa Logic’s rights to enforce any provision of the agreement in the future. 64 | -------------------------------------------------------------------------------- /docs/tex/preamble.tex: -------------------------------------------------------------------------------- 1 | %define new document type 2 | 3 | \usepackage[utf8]{inputenc} 4 | \usepackage[english]{babel} 5 | 6 | % Define Roa Logic Colour Scheme 7 | \usepackage[table]{xcolor} 8 | \newcommand{\headlinecolor}{\normalcolor} 9 | \definecolor{rlchapter}{HTML}{3D5986} 10 | \definecolor{rlsection}{HTML}{5B80B8} 11 | \definecolor{rltable}{HTML}{D5DFED} 12 | 13 | % Load packages 14 | \usepackage{graphicx,grffile} % Graphics support 15 | \usepackage{geometry} 16 | \usepackage{array} 17 | \usepackage{xcolor} 18 | \usepackage{placeins} 19 | \usepackage{multirow} 20 | \usepackage{float} 21 | \usepackage[shadow]{todonotes} 22 | \usepackage{lmodern} % Font Library 23 | \usepackage{amssymb,amsmath} % Math Fonts 24 | \usepackage{ifxetex,ifluatex} 25 | \usepackage{longtable} % Long table supprot 26 | \usepackage{vmargin} % Margin control 27 | \usepackage{tabularx} % Table support 28 | \usepackage{booktabs} % For \toprule, \midrule and \bottomrule 29 | \usepackage{csvsimple} % Import CSV files 30 | \usepackage{layout} % Show summary of page layout 31 | \usepackage{hyperref} % Hyperlink support 32 | \usepackage{titlesec} %Headings Styliser 33 | \usepackage{fancyhdr} % Header & Footer control 34 | \usepackage{comment} 35 | \usepackage[olditem,oldenum]{paralist} 36 | \usepackage{titling} 37 | 38 | % Setup margins & page style 39 | 40 | %\setlength{\topmargin}{-0.5in} 41 | %\setlength{\textheight}{9in} 42 | %\setlength{\oddsidemargin}{0in} 43 | %\setlength{\evensidemargin}{0in} 44 | %\setlength{\textwidth}{6.5in} 45 | 46 | % Page Layout Control 47 | 48 | % Hyperlink formatting 49 | \hypersetup{ 50 | colorlinks=true, 51 | linkcolor=blue, 52 | filecolor=magenta, 53 | urlcolor=blue, 54 | } 55 | 56 | \urlstyle{same} 57 | 58 | % Font & Colour control 59 | \renewcommand{\familydefault}{\rmdefault} 60 | \renewcommand{\headlinecolor}{\color{rlcolor}} 61 | 62 | 63 | % Heading Formats 64 | \titleformat{\chapter} 65 | {\normalfont\Huge\bfseries\color{rlchapter}\sffamily}{\thechapter.}{1em}{}[{\titlerule[0.8pt]}] 66 | 67 | \titleformat{\section} 68 | {\color{rlsection}\sffamily\LARGE\bfseries}{\thesection}{1em}{} 69 | 70 | \titleformat{\subsection} 71 | {\color{rlsection}\sffamily\large\bfseries}{\thesubsection}{1em}{} 72 | 73 | \titleformat{\subsubsection} 74 | {\color{rlsection}\sffamily\large\bfseries}{\thesubsubsection}{1em}{} 75 | 76 | %\titlespacing*{\chapter} {0pt}{1.5ex plus 1ex minus .2ex}{2.3ex plus .2ex} 77 | \titlespacing*{\chapter} {0pt}{-50pt}{20pt} 78 | \titlespacing*{\section} {0pt}{1.5ex plus 1ex minus .2ex}{2.3ex plus .2ex} 79 | \titlespacing*{\subsection} {0pt}{1.25ex plus 1ex minus .2ex}{1.5ex plus .2ex} 80 | \titlespacing*{\subsubsection}{0pt}{1.25ex plus 1ex minus .2ex}{1.5ex plus .2ex} 81 | \titlespacing*{\paragraph} {0pt}{1.25ex plus 1ex minus .2ex}{0.5em} 82 | \titlespacing*{\subparagraph} {\parindent}{3.25ex plus 1ex minus .2ex}{0.5em} 83 | 84 | \setlength{\headheight}{13.6pt} % Fix spurious build warnings 85 | 86 | % Paragraph formatting 87 | %\setlength{\parindent}{1em} 88 | \setlength{\parskip}{0.5em} 89 | 90 | % Long table formatting 91 | % \newcolumntype{L}[1]{>{\raggedright\arraybackslash}p{#1}} 92 | % \newcolumntype{C}[1]{>{\centering\arraybackslash}p{#1}} 93 | % \newcolumntype{R}[1]{>{\raggedleft\arraybackslash}p{#1}} 94 | \usepackage{subfig} 95 | \captionsetup{belowskip=0pt,aboveskip=7pt} 96 | 97 | % Pad All Table Rows 98 | % \renewcommand{\arraystretch}{1.2} 99 | 100 | 101 | % Center all Floats (Figs & Tables) 102 | \makeatletter 103 | \g@addto@macro\@floatboxreset\centering 104 | \makeatother 105 | 106 | % 107 | % Custom Commands 108 | % 109 | 110 | % Define ToDo Colours 111 | \presetkeys{todonotes}{color=blue!30, backgroundcolor=white, bordercolor=black, figcolor=white}{} 112 | 113 | % Commands for register format figures. 114 | 115 | % New column types to use in tabular environment for instruction formats. 116 | % Allocate 0.18in per bit. 117 | \newcolumntype{I}{>{\centering\arraybackslash}p{0.18in}} 118 | % Two-bit centered column. 119 | \newcolumntype{W}{>{\centering\arraybackslash}p{0.36in}} 120 | % Three-bit centered column. 121 | \newcolumntype{F}{>{\centering\arraybackslash}p{0.54in}} 122 | % Four-bit centered column. 123 | \newcolumntype{Y}{>{\centering\arraybackslash}p{0.72in}} 124 | % Five-bit centered column. 125 | \newcolumntype{R}{>{\centering\arraybackslash}p{0.9in}} 126 | % Six-bit centered column. 127 | \newcolumntype{S}{>{\centering\arraybackslash}p{1.08in}} 128 | % Seven-bit centered column. 129 | \newcolumntype{O}{>{\centering\arraybackslash}p{1.26in}} 130 | % Eight-bit centered column. 131 | \newcolumntype{E}{>{\centering\arraybackslash}p{1.44in}} 132 | % Ten-bit centered column. 133 | \newcolumntype{T}{>{\centering\arraybackslash}p{1.8in}} 134 | % Twelve-bit centered column. 135 | \newcolumntype{M}{>{\centering\arraybackslash}p{2.2in}} 136 | % Sixteen-bit centered column. 137 | \newcolumntype{K}{>{\centering\arraybackslash}p{2.88in}} 138 | % Twenty-bit centered column. 139 | \newcolumntype{U}{>{\centering\arraybackslash}p{3.6in}} 140 | % Twenty-bit centered column. 141 | \newcolumntype{L}{>{\centering\arraybackslash}p{3.6in}} 142 | % Twenty-five-bit centered column. 143 | \newcolumntype{J}{>{\centering\arraybackslash}p{4in}} % RL Change 144 | 145 | \newcommand{\instbit}[1]{\mbox{\scriptsize #1}} 146 | \newcommand{\instbitrange}[2]{~\instbit{#1} \hfill \instbit{#2}~} 147 | \newcommand{\reglabel}[1]{\hfill \texttt{#1}\hfill\ } 148 | 149 | \newcommand{\wiri}{\textbf{WIRI}} 150 | \newcommand{\wpri}{\textbf{WPRI}} 151 | \newcommand{\wlrl}{\textbf{WLRL}} 152 | \newcommand{\warl}{\textbf{WARL}} 153 | 154 | 155 | -------------------------------------------------------------------------------- /rtl/verilog/core/plic_target.sv: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | // ,------. ,--. ,--. // 3 | // | .--. ' ,---. ,--,--. | | ,---. ,---. `--' ,---. // 4 | // | '--'.'| .-. |' ,-. | | | | .-. | .-. |,--.| .--' // 5 | // | |\ \ ' '-' '\ '-' | | '--.' '-' ' '-' || |\ `--. // 6 | // `--' '--' `---' `--`--' `-----' `---' `- /`--' `---' // 7 | // `---' // 8 | // RISC-V Platform-Level Interrupt Controller // 9 | // // 10 | ///////////////////////////////////////////////////////////////////// 11 | // // 12 | // Copyright (C) 2017 ROA Logic BV // 13 | // www.roalogic.com // 14 | // // 15 | // This source file may be used and distributed without // 16 | // restriction provided that this copyright statement is not // 17 | // removed from the file and that any derivative work contains // 18 | // the original copyright notice and the associated disclaimer. // 19 | // // 20 | // THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY // 21 | // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED // 22 | // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS // 23 | // FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR OR // 24 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // 25 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT // 26 | // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; // 27 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) // 28 | // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // 29 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR // 30 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // 31 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // 32 | // // 33 | ///////////////////////////////////////////////////////////////////// 34 | 35 | // +FHDR - Semiconductor Reuse Standard File Header Section ------- 36 | // FILE NAME : plic_target.sv 37 | // DEPARTMENT : 38 | // AUTHOR : rherveille 39 | // AUTHOR'S EMAIL : 40 | // ------------------------------------------------------------------ 41 | // RELEASE HISTORY 42 | // VERSION DATE AUTHOR DESCRIPTION 43 | // 1.0 2017-07-01 rherveille initial release 44 | // ------------------------------------------------------------------ 45 | // KEYWORDS : RISC-V PLATFORM LEVEL INTERRUPT CONTROLLER - PLIC 46 | // ------------------------------------------------------------------ 47 | // PURPOSE : PLIC Target 48 | // Generates Interrupt Request and ID for each target 49 | // ------------------------------------------------------------------ 50 | // PARAMETERS 51 | // PARAM NAME RANGE DESCRIPTION DEFAULT UNITS 52 | // SOURCES 1+ No. of interupt sources 8 53 | // PRIORITIES 1+ No. of priority levels 8 54 | // ------------------------------------------------------------------ 55 | // REUSE ISSUES 56 | // Reset Strategy : external asynchronous active low; rst_ni 57 | // Clock Domains : 1, clk, rising edge 58 | // Critical Timing : 59 | // Test Features : na 60 | // Asynchronous I/F : no 61 | // Scan Methodology : na 62 | // Instantiations : plic_priority_index 63 | // Synthesizable (y/n) : Yes 64 | // Other : 65 | // -FHDR------------------------------------------------------------- 66 | 67 | module plic_target #( 68 | parameter SOURCES = 8, 69 | parameter PRIORITIES = 7, 70 | 71 | //These should be localparams, but that's not supported by all tools yet 72 | parameter SOURCES_BITS = $clog2(SOURCES +1), //0=reserved 73 | parameter PRIORITY_BITS = $clog2(PRIORITIES) 74 | ) 75 | ( 76 | input rst_ni, //Active low asynchronous reset 77 | clk_i, //System clock 78 | 79 | input [SOURCES_BITS -1:0] id_i [SOURCES], //Interrupt source 80 | input [PRIORITY_BITS-1:0] priority_i [SOURCES], //Interrupt Priority 81 | 82 | input [PRIORITY_BITS-1:0] threshold_i, //Interrupt Priority Threshold 83 | 84 | output reg ireq_o, //Interrupt Request (EIP) 85 | output reg [SOURCES_BITS -1:0] id_o //Interrupt ID 86 | ); 87 | ////////////////////////////////////////////////////////////////// 88 | // 89 | // Constant 90 | // 91 | 92 | 93 | ////////////////////////////////////////////////////////////////// 94 | // 95 | // Variables 96 | // 97 | logic [SOURCES_BITS -1:0] id; 98 | logic [PRIORITY_BITS-1:0] pr; 99 | 100 | 101 | ////////////////////////////////////////////////////////////////// 102 | // 103 | // Module Body 104 | // 105 | 106 | /** Select highest priority pending interrupt 107 | */ 108 | plic_priority_index #( 109 | .SOURCES ( SOURCES ), 110 | .PRIORITIES ( PRIORITIES ), 111 | .HI ( SOURCES -1 ), 112 | .LO ( 0 ) 113 | ) 114 | priority_index_tree ( 115 | .priority_i ( priority_i ), 116 | .idx_i ( id_i ), 117 | .priority_o ( pr ), 118 | .idx_o ( id ) 119 | ); 120 | 121 | 122 | /** Generate output 123 | */ 124 | always @(posedge clk_i,negedge rst_ni) 125 | if (!rst_ni ) ireq_o <= 1'b0; 126 | else if ( pr > threshold_i) ireq_o <= 1'b1; 127 | else ireq_o <= 1'b0; 128 | 129 | always @(posedge clk_i) 130 | id_o <= id; 131 | 132 | endmodule : plic_target 133 | -------------------------------------------------------------------------------- /sim/ahb3lite/bin/Makefile: -------------------------------------------------------------------------------- 1 | ##################################################################### 2 | ## ,------. ,--. ,--. ## 3 | ## | .--. ' ,---. ,--,--. | | ,---. ,---. `--' ,---. ## 4 | ## | '--'.'| .-. |' ,-. | | | | .-. | .-. |,--.| .--' ## 5 | ## | |\ \ ' '-' '\ '-' | | '--.' '-' ' '-' || |\ `--. ## 6 | ## `--' '--' `---' `--`--' `-----' `---' `- /`--' `---' ## 7 | ## `---' ## 8 | ## Main Simulation Makefile ## 9 | ## ## 10 | ##################################################################### 11 | ## ## 12 | ## Copyright (C) 2017 ROA Logic BV ## 13 | ## www.roalogic.com ## 14 | ## ## 15 | ## This source file may be used and distributed without ## 16 | ## restriction provided that this copyright statement is not ## 17 | ## removed from the file and that any derivative work contains ## 18 | ## the original copyright notice and the associated disclaimer. ## 19 | ## ## 20 | ## THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ## 21 | ## EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ## 22 | ## TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ## 23 | ## FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR OR ## 24 | ## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, ## 25 | ## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT ## 26 | ## NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; ## 27 | ## LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ## 28 | ## HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN ## 29 | ## CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR ## 30 | ## OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS ## 31 | ## SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ## 32 | ## ## 33 | ##################################################################### 34 | 35 | all: Makefile 36 | 37 | SIMULATORS = ncsim vcs silos icarus riviera 38 | LINTERS = $(addsuffix _lint, $(SIMULATORS)) 39 | SIMWAVES = $(addsuffix _waves, $(SIMULATORS)) 40 | 41 | MS = -s 42 | 43 | ROOT_DIR=../../.. 44 | 45 | ##################################################################### 46 | # 47 | # Regression variables 48 | # 49 | ##################################################################### 50 | #add regression variables here 51 | 52 | 53 | ##################################################################### 54 | # 55 | # Sources 56 | # 57 | ##################################################################### 58 | -include Makefile.include 59 | 60 | 61 | ##################################################################### 62 | # 63 | # Misc Variables 64 | # 65 | ##################################################################### 66 | INCDIRS:=$(INCDIRS) 67 | DEFINES:=$(DEFINES) 68 | 69 | shell=/bin/sh 70 | 71 | 72 | ##################################################################### 73 | # 74 | # OVL 75 | # 76 | ##################################################################### 77 | ifeq ($(OVL_ASSERT),ON) 78 | INCDIRS +=$(STD_OVL_DIR) 79 | DEFINES +=OVL_ASSERT_ON 80 | LIBDIRS +=$(STD_OVL_DIR) 81 | LIBEXT +=.vlib 82 | 83 | ifeq ($(OVL_INIT_MSG),ON) 84 | DEFINES +=OVL_INIT_MSG 85 | endif 86 | endif 87 | 88 | 89 | ##################################################################### 90 | # 91 | # Make Targets 92 | # 93 | ##################################################################### 94 | .PHONY: $(SIMULATORS) $(LINTERS) $(SIMWAVES) 95 | $(SIMULATORS): % : %/Makefile $(TB_PREREQ) 96 | @$(MAKE) $(MS) -C $@ sim \ 97 | VLOG="$(abspath $(RTL_VLOG) $(TB_VLOG))" \ 98 | TECHLIBS="$(TECHLIBS)" \ 99 | LIBDIRS="$(LIBDIRS)" \ 100 | LIBEXT="$(LIBEXT)" \ 101 | VHDL="$(abspath $(RTL_VHDL) $(TB_VHDL))" \ 102 | INCDIRS="$(abspath $(INCDIRS))" \ 103 | DEFINES="$(DEFINES)" \ 104 | TOP=$(TB_TOP) \ 105 | LOG=$(LOG) PARAMS="$(PARAMS)" 106 | 107 | $(SIMWAVES): %_waves : %/Makefile $(TB_PREREQ) 108 | @$(MAKE) $(MS) -C $(subst _waves,,$@) simw \ 109 | VLOG="$(abspath $(RTL_VLOG) $(TB_VLOG))" \ 110 | TECHLIBS="$(TECHLIBS)" \ 111 | LIBDIRS="$(LIBDIRS)" \ 112 | LIBEXT="$(LIBEXT)" \ 113 | VHDL="$(abspath $(RTL_VHDL) $(TB_VHDL))" \ 114 | INCDIRS="$(abspath $(INCDIRS))" \ 115 | DEFINES="$(DEFINES)" \ 116 | TOP=$(TB_TOP) \ 117 | LOG=$(LOG) PARAMS="$(PARAMS)" 118 | 119 | $(LINTERS): %_lint : %/Makefile $(TB_PREREQ) 120 | @$(MAKE) $(MS) -C $(subst _lint,,$@) lint \ 121 | VLOG="$(abspath $(RTL_VLOG))" \ 122 | VHDL="$(abspath $(RTL_VHDL))" \ 123 | INCDIRS="$(abspath $(INCDIRS))" \ 124 | DEFINES="$(DEFINES)" \ 125 | TOP=$(RTL_TOP) 126 | 127 | 128 | .PHONY: bps 129 | bps: % : %/Makefile 130 | @$(MAKE) $(MS) -C $@ $@ \ 131 | VLOG="$(abspath $(RTL_VLOG))" \ 132 | VHDL="$(abspath $(RTL_VHDL))" \ 133 | TOP=$(RTL_TOP) 134 | 135 | 136 | .PHONY: clean distclean mrproper 137 | clean: 138 | @for f in $(wildcard *); do \ 139 | if test -d $$f; then $(MAKE) -C $$f clean; fi \ 140 | done 141 | 142 | distclean: 143 | @rm -rf $(SIMULATORS) Makefile.include $(TB_PREREQ) 144 | 145 | mrproper: 146 | @rm -rf * 147 | 148 | 149 | ##################################################################### 150 | # 151 | # Make simulation structure 152 | # 153 | ##################################################################### 154 | Makefile.include: 155 | @cp ../bin/Makefile.include . 156 | 157 | %/Makefile: 158 | @mkdir -p $* 159 | @cp ../bin/Makefile.$* $@ 160 | 161 | $(TB_PREREQ): 162 | @cp ../bin/$@ $@ 163 | -------------------------------------------------------------------------------- /rtl/verilog/core/plic_priority_index.sv: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | // ,------. ,--. ,--. // 3 | // | .--. ' ,---. ,--,--. | | ,---. ,---. `--' ,---. // 4 | // | '--'.'| .-. |' ,-. | | | | .-. | .-. |,--.| .--' // 5 | // | |\ \ ' '-' '\ '-' | | '--.' '-' ' '-' || |\ `--. // 6 | // `--' '--' `---' `--`--' `-----' `---' `- /`--' `---' // 7 | // `---' // 8 | // RISC-V Platform-Level Interrupt Controller // 9 | // // 10 | ///////////////////////////////////////////////////////////////////// 11 | // // 12 | // Copyright (C) 2017 ROA Logic BV // 13 | // www.roalogic.com // 14 | // // 15 | // This source file may be used and distributed without // 16 | // restriction provided that this copyright statement is not // 17 | // removed from the file and that any derivative work contains // 18 | // the original copyright notice and the associated disclaimer. // 19 | // // 20 | // THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY // 21 | // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED // 22 | // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS // 23 | // FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR OR // 24 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // 25 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT // 26 | // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; // 27 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) // 28 | // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // 29 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR // 30 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // 31 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // 32 | // // 33 | ///////////////////////////////////////////////////////////////////// 34 | 35 | // +FHDR - Semiconductor Reuse Standard File Header Section ------- 36 | // FILE NAME : plic_priority_index.sv 37 | // DEPARTMENT : 38 | // AUTHOR : rherveille 39 | // AUTHOR'S EMAIL : 40 | // ------------------------------------------------------------------ 41 | // RELEASE HISTORY 42 | // VERSION DATE AUTHOR DESCRIPTION 43 | // 1.0 2017-11-14 rherveille initial release 44 | // ------------------------------------------------------------------ 45 | // KEYWORDS : RISC-V PLATFORM LEVEL INTERRUPT CONTROLLER - PLIC 46 | // ------------------------------------------------------------------ 47 | // PURPOSE : PLIC Target - Priority Index 48 | // Builds a binary tree to search for the highest priority 49 | // and its associated ID 50 | // ------------------------------------------------------------------ 51 | // PARAMETERS 52 | // PARAM NAME RANGE DESCRIPTION DEFAULT UNITS 53 | // SOURCES 1+ No. of interupt sources 8 54 | // PRIORITIES 1+ No. of priority levels 8 55 | // ------------------------------------------------------------------ 56 | // REUSE ISSUES 57 | // Reset Strategy : none 58 | // Clock Domains : none 59 | // Critical Timing : 60 | // Test Features : na 61 | // Asynchronous I/F : yes 62 | // Scan Methodology : na 63 | // Instantiations : Itself (recursive) 64 | // Synthesizable (y/n) : Yes 65 | // Other : 66 | // -FHDR------------------------------------------------------------- 67 | 68 | module plic_priority_index #( 69 | parameter SOURCES = 16, 70 | parameter PRIORITIES = 7, 71 | parameter HI = 16, 72 | parameter LO = 0, 73 | 74 | //These should be localparams, but that's not supported by all tools yet 75 | parameter SOURCES_BITS = $clog2(SOURCES +1), //0=reserved 76 | parameter PRIORITY_BITS = $clog2(PRIORITIES) 77 | ) 78 | ( 79 | input [PRIORITY_BITS-1:0] priority_i [SOURCES], //Interrupt Priority 80 | input [SOURCES_BITS -1:0] idx_i [SOURCES], 81 | output [PRIORITY_BITS-1:0] priority_o, 82 | output [SOURCES_BITS -1:0] idx_o 83 | ); 84 | 85 | ////////////////////////////////////////////////////////////////// 86 | // 87 | // Variables 88 | // 89 | 90 | logic [PRIORITY_BITS-1:0] priority_hi, priority_lo; 91 | logic [SOURCES_BITS -1:0] idx_hi, idx_lo; 92 | 93 | //initial if (HI-LO>1) $display ("HI=%0d, LO=%0d -> hi(%0d,%0d) lo(%0d,%0d)", HI, LO, HI, HI-(HI-LO)/2, LO+(HI-LO)/2, LO); 94 | 95 | ////////////////////////////////////////////////////////////////// 96 | // 97 | // Module Body 98 | // 99 | 100 | generate 101 | if (HI - LO > 1) 102 | begin 103 | plic_priority_index #( 104 | .SOURCES ( SOURCES ), 105 | .PRIORITIES ( PRIORITIES ), 106 | .HI ( LO + (HI-LO)/2 ), 107 | .LO ( LO ) 108 | ) 109 | lo ( 110 | .priority_i ( priority_i ), 111 | .idx_i ( idx_i ), 112 | .priority_o ( priority_lo ), 113 | .idx_o ( idx_lo ) 114 | ); 115 | 116 | plic_priority_index #( 117 | .SOURCES ( SOURCES ), 118 | .PRIORITIES ( PRIORITIES ), 119 | .HI ( HI ), 120 | .LO ( HI - (HI-LO)/2 ) 121 | ) hi 122 | ( 123 | .priority_i ( priority_i ), 124 | .idx_i ( idx_i ), 125 | .priority_o ( priority_hi ), 126 | .idx_o ( idx_hi ) 127 | ); 128 | end 129 | else 130 | begin 131 | assign priority_lo = priority_i[LO]; 132 | assign priority_hi = priority_i[HI]; 133 | assign idx_lo = idx_i [LO]; 134 | assign idx_hi = idx_i [HI]; 135 | end 136 | endgenerate 137 | 138 | assign priority_o = priority_hi > priority_lo ? priority_hi : priority_lo; 139 | assign idx_o = priority_hi > priority_lo ? idx_hi : idx_lo; 140 | 141 | endmodule : plic_priority_index 142 | 143 | -------------------------------------------------------------------------------- /docs/tex/interfaces-ahblite.tex: -------------------------------------------------------------------------------- 1 | \section{AHB-Lite Interface} 2 | 3 | The AHB-Lite interface is a regular AHB-Lite slave port. All signals are 4 | supported. See the 5 | \emph{\href{https://www.arm.com/products/system-ip/amba-specifications}{AMBA 6 | 3 AHB-Lite Specification}} for a complete description of the signals. 7 | 8 | \begin{longtable}[c]{@{\extracolsep{\fill}}cccl@{}} 9 | \toprule 10 | \textbf{Port} & \textbf{Size} & \textbf{Direction} & \textbf{Description}\\ 11 | \midrule 12 | \endhead 13 | \texttt{HRESETn} & 1 & Input & Asynchronous active low reset\\ 14 | \texttt{HCLK} & 1 & Input & Clock Input\\ 15 | \texttt{HSEL} & 1 & Input & Bus Select\\ 16 | \texttt{HTRANS} & 2 & Input & Transfer Type\\ 17 | \texttt{HADDR} & \texttt{HADDR\_SIZE} & Input & Address Bus\\ 18 | \texttt{HWDATA} & \texttt{HDATA\_SIZE} & Input & Write Data Bus\\ 19 | \texttt{HRDATA} & \texttt{HDATA\_SIZE} & Output & Read Data Bus\\ 20 | \texttt{HWRITE} & 1 & Input & Write Select\\ 21 | \texttt{HSIZE} & 3 & Input & Transfer Size\\ 22 | \texttt{HBURST} & 3 & Input & Transfer Burst Size\\ 23 | \texttt{HPROT} & 4 & Input & Transfer Protection Level\\ 24 | \texttt{HREADYOUT} & 1 & Output & Transfer Ready Output\\ 25 | \texttt{HREADY} & 1 & Input & Transfer Ready Input\\ 26 | \texttt{HRESP} & 1 & Output & Transfer Response\\ 27 | \bottomrule 28 | \caption{PLIC Interface Signals} 29 | \label{tab:AHBIF} 30 | \end{longtable} 31 | 32 | \subsection{HRESETn} 33 | 34 | When the active low asynchronous \texttt{HRESETn} input is asserted 35 | (`0'), the interface is put into its initial reset state. 36 | 37 | \subsection{HCLK} 38 | 39 | \texttt{HCLK} is the interface system clock. All internal logic for the 40 | AHB-Lite interface operates at the rising edge of this system clock and 41 | AHB bus timings are related to the rising edge of \texttt{HCLK}. 42 | 43 | \subsection{HSEL} 44 | 45 | The AHB-Lite interface only responds to other signals on its bus -- with 46 | the exception of the global asynchronous reset signal \texttt{HRESETn} 47 | -- when \texttt{HSEL} is asserted (`1'). When \texttt{HSEL} is negated 48 | (`0') the interface considers the bus \texttt{IDLE}. 49 | 50 | \subsection{HTRANS} 51 | 52 | HTRANS indicates the type of the current transfer as shown in Table \ref{tab:HTRANS} 53 | \being{comment} 54 | This shows as [tab:HTRANS]: on screen (DATASHEET.md) 55 | \end{comment} 56 | 57 | 58 | \begin{longtable}[c]{@{\extracolsep{\fill}}ccp{7cm}} 59 | \toprule 60 | \textbf{HTRANS} & \textbf{Type} & \textbf{Description}\\ 61 | \midrule 62 | \endhead 63 | 00 & \texttt{IDLE} & No transfer required\\ 64 | 01 & \texttt{BUSY} & Connected master is not ready to accept data, but intents to continue the current burst.\\ 65 | 10 & \texttt{NONSEQ} & First transfer of a burst or a single transfer\\ 66 | 11 & \texttt{SEQ} & Remaining transfers of a burst\\ 67 | \bottomrule 68 | \caption{HTRANS Signal Types} 69 | \label{tab:HTRANS} 70 | \end{longtable} 71 | 72 | \subsection{HADDR} 73 | 74 | \texttt{HADDR} is the address bus. Its size is determined by the 75 | \texttt{HADDR\_SIZE} parameter and is driven to the connected 76 | peripheral. 77 | 78 | \subsection{HWDATA} 79 | 80 | \texttt{HWDATA} is the write data bus. Its size is determined by the 81 | \texttt{HDATA\_SIZE} parameter and is driven to the connected 82 | peripheral. 83 | 84 | \subsection{HRDATA} 85 | 86 | \texttt{HRDATA} is the read data bus. Its size is determined by the 87 | \texttt{HDATA\_SIZE} parameter and is sourced by the connected 88 | peripheral. 89 | 90 | \subsection{HWRITE} 91 | 92 | \texttt{HWRITE} is the read/write signal. \texttt{HWRITE} asserted (`1') 93 | indicates a write transfer. 94 | 95 | \subsection{HSIZE} 96 | 97 | \texttt{HSIZE} indicates the size of the current transfer as shown in 98 | \ifdefined\MARKDOWN 99 | Table \ref{tab:HSIZE} 100 | \else 101 | the table below: 102 | \fi 103 | 104 | \begin{longtable}[c]{@{\extracolsep{\fill}}ccl} 105 | \toprule 106 | \textbf{HSIZE} & \textbf{Size} & \textbf{Description}\\ 107 | \midrule 108 | \endhead 109 | 000 & 8 bit & Byte\\ 110 | 001 & 16 bit & Half Word\\ 111 | 010 & 32 bit & Word\\ 112 | 011 & 64 bits & Double Word\\ 113 | 100 & 128 bit &\\ 114 | 101 & 256 bit &\\ 115 | 110 & 512 bit &\\ 116 | 111 & 1024 bit &\\ 117 | \bottomrule 118 | \caption{HSIZE Values} 119 | \label{tab:HSIZE} 120 | \end{longtable} 121 | 122 | \subsection{HBURST} 123 | 124 | HBURST indicates the transaction burst type -- a single transfer or part 125 | of a burst. 126 | 127 | \begin{longtable}[c]{@{\extracolsep{\fill}}ccl} 128 | \toprule 129 | \textbf{HBURST} & \textbf{Type} & \textbf{Description}\\ 130 | \midrule 131 | \endhead 132 | 000 & \texttt{SINGLE} & Single access**\\ 133 | 001 & \texttt{INCR} & Continuous incremental burst\\ 134 | 010 & \texttt{WRAP4} & 4-beat wrapping burst\\ 135 | 011 & \texttt{INCR4} & 4-beat incrementing burst\\ 136 | 100 & \texttt{WRAP8} & 8-beat wrapping burst\\ 137 | 101 & \texttt{INCR8} & 8-beat incrementing burst\\ 138 | 110 & \texttt{WRAP16} & 16-beat wrapping burst\\ 139 | 111 & \texttt{INCR16} & 16-beat incrementing burst\\ 140 | \bottomrule 141 | \caption{HBURST Types} 142 | \label{tab:HBURST} 143 | \end{longtable} 144 | 145 | \subsection{HPROT} 146 | 147 | The \texttt{HPROT} signals provide additional information about the bus 148 | transfer and are intended to implement a level of protection. 149 | 150 | \begin{longtable}[c]{@{}lccl} 151 | \toprule 152 | & \textbf{Bit\#} & \textbf{Value} & \textbf{Description}\\ 153 | \midrule 154 | \endhead 155 | & 3 & 1 & Cacheable region addressed\\ 156 | & & 0 & Non-cacheable region addressed\\ 157 | & 2 & 1 & Bufferable\\ 158 | & 0 & Non-bufferable\\ 159 | & 1 & 1 & Privileged Access\\ 160 | & & 0 & User Access\\ 161 | & 0 & 1 & Data Access\\ 162 | & & 0 & Opcode fetch\\ 163 | \bottomrule 164 | \caption{HPROT Indicators} 165 | \label{tab:HPROT} 166 | \end{longtable} 167 | 168 | \subsection{HREADYOUT} 169 | 170 | \texttt{HREADYOUT} indicates that the current transfer has finished. 171 | Note, for the AHB-Lite PLIC this signal is constantly asserted as the 172 | core is always ready for data access. 173 | 174 | \subsection{HREADY} 175 | 176 | \texttt{HREADY} indicates whether or not the addressed peripheral is 177 | ready to transfer data. When \texttt{HREADY} is negated (`0') the 178 | peripheral is not ready, forcing wait states. When \texttt{HREADY} is 179 | asserted (`1') the peripheral is ready and the transfer completed. 180 | 181 | \subsection{HRESP} 182 | 183 | \texttt{HRESP} is the instruction transfer response and indicates OKAY 184 | (`0') or ERROR (`1'). 185 | -------------------------------------------------------------------------------- /rtl/verilog/core/plic_gateway.sv: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | // ,------. ,--. ,--. // 3 | // | .--. ' ,---. ,--,--. | | ,---. ,---. `--' ,---. // 4 | // | '--'.'| .-. |' ,-. | | | | .-. | .-. |,--.| .--' // 5 | // | |\ \ ' '-' '\ '-' | | '--.' '-' ' '-' || |\ `--. // 6 | // `--' '--' `---' `--`--' `-----' `---' `- /`--' `---' // 7 | // `---' // 8 | // RISC-V Platform-Level Interrupt Controller // 9 | // // 10 | ///////////////////////////////////////////////////////////////////// 11 | // // 12 | // Copyright (C) 2017 ROA Logic BV // 13 | // www.roalogic.com // 14 | // // 15 | // This source file may be used and distributed without // 16 | // restriction provided that this copyright statement is not // 17 | // removed from the file and that any derivative work contains // 18 | // the original copyright notice and the associated disclaimer. // 19 | // // 20 | // THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY // 21 | // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED // 22 | // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS // 23 | // FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR OR // 24 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // 25 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT // 26 | // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; // 27 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) // 28 | // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // 29 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR // 30 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // 31 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // 32 | // // 33 | ///////////////////////////////////////////////////////////////////// 34 | 35 | // +FHDR - Semiconductor Reuse Standard File Header Section ------- 36 | // FILE NAME : plic_gateway.sv 37 | // DEPARTMENT : 38 | // AUTHOR : rherveille 39 | // AUTHOR'S EMAIL : 40 | // ------------------------------------------------------------------ 41 | // RELEASE HISTORY 42 | // VERSION DATE AUTHOR DESCRIPTION 43 | // 1.0 2017-07-01 rherveille initial release 44 | // 2017-09-12 rherveille Added 'claim' and 'complete' 45 | // ------------------------------------------------------------------ 46 | // KEYWORDS : RISC-V PLATFORM LEVEL INTERRUPT CONTROLLER - PLIC 47 | // ------------------------------------------------------------------ 48 | // PURPOSE : PLIC Gateway, input section for each interrupt source 49 | // Supports edge-level triggered selection and interrupt 50 | // pending counter for events (edge triggered interrupts) 51 | // ------------------------------------------------------------------ 52 | // PARAMETERS 53 | // PARAM NAME RANGE DESCRIPTION DEFAULT UNITS 54 | // MAX_PENDING_COUNT 0+ Max. pending interrupts 0 55 | // ------------------------------------------------------------------ 56 | // REUSE ISSUES 57 | // Reset Strategy : external asynchronous active low; rst_n 58 | // Clock Domains : 1, clk, rising edge 59 | // Critical Timing : 60 | // Test Features : na 61 | // Asynchronous I/F : no 62 | // Scan Methodology : na 63 | // Instantiations : none 64 | // Synthesizable (y/n) : Yes 65 | // Other : 66 | // -FHDR------------------------------------------------------------- 67 | 68 | module plic_gateway #( 69 | parameter MAX_PENDING_COUNT = 16 70 | ) 71 | ( 72 | input rst_n, //Active low asynchronous reset 73 | clk, //System clock 74 | 75 | input src, //Interrupt source 76 | input edge_lvl, //(rising) edge or level triggered 77 | 78 | output ip, //interrupt pending 79 | input claim, //interrupt claimed 80 | input complete //interrupt handling completed 81 | ); 82 | 83 | 84 | ////////////////////////////////////////////////////////////////// 85 | // 86 | // Constants 87 | // 88 | localparam SAFE_MAX_PENDING_COUNT = (MAX_PENDING_COUNT >= 0) ? MAX_PENDING_COUNT : 0; 89 | localparam COUNT_BITS = $clog2(SAFE_MAX_PENDING_COUNT+1); 90 | localparam LEVEL = 1'b0, 91 | EDGE = 1'b1; 92 | 93 | 94 | ////////////////////////////////////////////////////////////////// 95 | // 96 | // Variables 97 | // 98 | logic src_dly, src_edge; 99 | logic [COUNT_BITS-1:0] nxt_pending_cnt, pending_cnt; 100 | logic decr_pending; 101 | logic [ 1:0] ip_state; 102 | 103 | 104 | ////////////////////////////////////////////////////////////////// 105 | // 106 | // Module Body 107 | // 108 | 109 | /** detect rising edge on interrupt source 110 | */ 111 | always @(posedge clk,negedge rst_n) 112 | if (!rst_n) 113 | begin 114 | src_dly <= 1'b0; 115 | src_edge <= 1'b0; 116 | end 117 | else 118 | begin 119 | src_dly <= src; 120 | src_edge <= src & ~src_dly; 121 | end 122 | 123 | 124 | /** generate pending-counter 125 | */ 126 | always_comb 127 | case ({decr_pending,src_edge}) 128 | 2'b00: nxt_pending_cnt = pending_cnt; //do nothing 129 | 2'b01: if (pending_cnt < SAFE_MAX_PENDING_COUNT) 130 | nxt_pending_cnt = pending_cnt +'h1; 131 | else 132 | nxt_pending_cnt = pending_cnt; 133 | 2'b10: if (pending_cnt > 0) 134 | nxt_pending_cnt = pending_cnt -'h1; 135 | else 136 | nxt_pending_cnt = pending_cnt; 137 | 2'b11: nxt_pending_cnt = pending_cnt; //do nothing 138 | endcase 139 | 140 | 141 | always @(posedge clk,negedge rst_n) 142 | if (!rst_n ) pending_cnt <= 'h0; 143 | else if ( edge_lvl != EDGE) pending_cnt <= 'h0; 144 | else pending_cnt <= nxt_pending_cnt; 145 | 146 | 147 | /** generate interrupt pending 148 | * 1. assert IP 149 | * 2. target 'claims IP' 150 | * clears IP bit 151 | * blocks IP from asserting again 152 | * 3. target 'completes' 153 | */ 154 | always @(posedge clk,negedge rst_n) 155 | if (!rst_n) 156 | begin 157 | ip_state <= 2'b00; 158 | decr_pending <= 1'b0; 159 | end 160 | else 161 | begin 162 | decr_pending <= 1'b0; //strobe signal 163 | 164 | case (ip_state) 165 | //wait for interrupt request from source 166 | 2'b00 : if ((edge_lvl == EDGE && |nxt_pending_cnt) || 167 | (edge_lvl == LEVEL && src )) 168 | begin 169 | ip_state <= 2'b01; 170 | decr_pending <= 1'b1; //decrement 171 | end 172 | 173 | //wait for 'interrupt claim' 174 | 2'b01 : if (claim ) ip_state <= 2'b10; 175 | 176 | //wait for 'interrupt completion' 177 | 2'b10 : if (complete) ip_state <= 2'b00; 178 | 179 | //oops ... 180 | default: ip_state <= 2'b00; 181 | endcase 182 | end 183 | 184 | //IP-bit is ip_state LSB 185 | assign ip = ip_state[0]; 186 | 187 | endmodule : plic_gateway 188 | -------------------------------------------------------------------------------- /docs/tex/specification.tex: -------------------------------------------------------------------------------- 1 | \chapter{Specifications} \label{specifications} 2 | 3 | \section{Overview} 4 | 5 | The AHB-Lite PLIC IP core is a fully parameterised Platform-Level Interrupt 6 | Controller, featuring a single AHB-Lite Slave interface and support for a user-defined number of both Interrupt Sources and Targets. 7 | 8 | The purpose of the PLIC core is to connect multiple interrupt sources to 9 | one or more interrupt targets. The core supports a programmable number 10 | of simultaneous pending interrupt requests per source and individual routing of those interrupt requests to each target. 11 | 12 | Per the \href{https://github.com/riscv/riscv-isa-manual/blob/master/release/riscv-privileged-v1.10.pdf}{RISC-V Privileged Architecture Instruction Set specification (v1.10)}, the core performs full interrupt prioritisation of each interrupt source; each may be assigned a separate priority and enabled per target via a matrix of interrupt enable bits. Further, an optional priority threshold per target may be defined to mask lower priority interrupts. 13 | 14 | To reduce latency, the PLIC core presents all asserted interrupts to the target in priority order, queuing them so that a software interrupt handler can service all pending interrupts without the need to restore the interrupted context. 15 | 16 | For illustration, a simplified example system using the PLIC core is shown below: 17 | 18 | \begin{figure}[htb] 19 | \includegraphics{assets/img/plic-system} 20 | \caption{PLIC System Diagram} 21 | \label{fig:SYSDIAG} 22 | \end{figure} 23 | 24 | \section{PLIC Operation} 25 | 26 | As stated in the \href{https://github.com/riscv/riscv-isa-manual/blob/master/release/riscv-privileged-v1.10.pdf}{RISC-V Privileged Architecture Instruction Set specification (v1.10)}: 27 | 28 | \begin{quote} 29 | 30 | PLIC connects global \emph{interrupt sources}, which are usually 31 | I/O devices, to \emph{interrupt targets}, which are usually \emph{hart 32 | contexts}. The PLIC contains multiple \emph{interrupt gateways}, one 33 | per interrupt source, together with a \emph{PLIC core} that performs 34 | interrupt prioritization and routing. Global interrupts are sent from 35 | their source to an \emph{interrupt gateway} that processes the 36 | interrupt signal from each source and sends a single \emph{interrupt 37 | request} to the PLIC core, which latches these in the core interrupt 38 | pending bits (IP). Each interrupt source is assigned a separate 39 | priority. The PLIC core contains a matrix of interrupt enable (IE) 40 | bits to select the interrupts that are enabled for each target. The 41 | PLIC core forwards an \emph{interrupt notification} to one or more 42 | targets if the targets have any pending interrupts enabled, and the 43 | priority of the pending interrupts exceeds a per-target threshold. 44 | When the target takes the external interrupt, it sends an \emph{ 45 | interrupt claim} request to retrieve the identifier of the 46 | highest-priority global interrupt source pending for that target from 47 | the PLIC core, which then clears the corresponding interrupt source 48 | pending bit. After the target has serviced the interrupt, it sends 49 | the associated interrupt gateway an \emph{interrupt completion} message 50 | and the interrupt gateway can now forward another interrupt request 51 | for the same source to the PLIC. 52 | 53 | \end{quote} 54 | 55 | \begin{figure}[htb] 56 | \centering 57 | \includegraphics[width=\textwidth]{assets/img/PLIC-block-diagram} 58 | \caption{Platform-Level Interrupt Controller (PLIC) conceptual block diagram.} 59 | \label{fig:plic-block-diagram} 60 | \end{figure} 61 | 62 | \ifdefined\MARKDOWN 63 | The figure above provides an overview of PLIC operation, showing the first two of potentially many interrupt sources, and the first two of potentially many interrupt targets. 64 | \else 65 | Figure~\ref{fig:plic-block-diagram} provides an overview of PLIC operation, showing the first two of potentially many interrupt sources, and the first two of potentially many interrupt targets. 66 | \fi 67 | 68 | \clearpage 69 | 70 | \section{Interrupt Handling Handshake} 71 | 72 | \subsection{Overview} 73 | 74 | \ifdefined\MARKDOWN 75 | The following figure shows the logical flow of the Interrupt Handling Handshake as implemented byt the Roa Logic PLIC core. The following sections describe the stages depicted: Interrupt Request, Interrupt Notification, Interrupt Claim Response, Processing the Interrupt and Interrupt Completion. 76 | \else 77 | Figure \ref{fig:HANDSHAKE} shows the logical flow of the Interrupt Handling Handshake as implemented byt the Roa Logic PLIC core. The following sections describe the stages depicted: Interrupt Request, Interrupt Notification, Interrupt Claim Response, Processing the Interrupt and Interrupt Completion. 78 | \fi 79 | 80 | 81 | \begin{figure}[!htb] 82 | \includegraphics{assets/img/plic-handshake} 83 | \caption{Interrupt Handling Handshake} 84 | \label{fig:HANDSHAKE} 85 | \end{figure} 86 | 87 | Prior to operation, the PLIC system must be defined and configured as follows: 88 | 89 | \begin{itemize} 90 | \item 91 | Each source must be assigned an Interrupt Identifier (\texttt{ID}) - a unique unsigned integer. This identifier will determine interrupt priority when 2 or more interrupts with the same priority level are asserted; The \emph{lower} the \texttt{ID} assigned to the source, the \emph{greater} the interrupt priority 92 | \item 93 | A matrix of Interrupt Enable vectors - one IE register per target - must be set to determine which target processes the interrupts from which source. 94 | \item 95 | Each Interrupt Source attached to the PLIC assigned a Priority Level - an unsigned integer value - that determines the relative priority of the interrupt source. Larger values have higher priority. 96 | \item 97 | Optionally, a Priority Threshold per target set to mask lower priority interrupts such that interrupts will only be presented to a target if the assigned Priority Level is greater than the Priority Threshold. 98 | \end{itemize} 99 | 100 | \subsection{Interrupt Request Stage} 101 | 102 | A source asserts an interrupt request to the PLIC. The PLIC validates 103 | the request by first checking if an interrupt enable bit is set for each 104 | target and if the priority of the interrupt source exceeds any defined 105 | Interrupt Priority Threshold. If these conditions do not hold, the 106 | Interrupt Request is deemed invalid and stalled pending updates to the interrupt enable and/or priority threshold bits. 107 | 108 | The PLIC also determines if a previous interrupt request has been made by the same source. 109 | If an interrupt is defined as level triggered and has already been asserted but not yet serviced, the request is ignored. 110 | If an interrupt is defined as edge triggered and has already been asserted but not yet serviced, the request is queued by incrementing its Interrupt Pending counter. 111 | The depth of this counter is parameterised. 112 | 113 | If the request is deemed valid the request is forwarded to the 114 | appropriate target. In the case of queued edge-triggered requests, the 115 | interrupt pending counter is decremented by one immediately upon claim of the interrupt by the target. 116 | 117 | \subsection{Interrupt Notification Stage} 118 | 119 | A target is notified of an interrupt request by asserting the IRQ output for that target. 120 | The PLIC blocks forwarding any further requests from the interrupt source until the current request is serviced. 121 | 122 | On each clock cycle the ID register is loaded with the unique identifier of the highest priority interrupt to be processed. 123 | This ensures that the Interrupt Service Routine always reads the highest pending interrupt request. 124 | 125 | \subsection{Claim Response Stage} \label{sec:claim-response} 126 | 127 | A target makes an interrupt claim response by reading the ID register, 128 | which also notifies the target of the interrupt source to service. The 129 | PLIC de-asserts the IRQ output for the target in response to the claim. 130 | unless another, lower priority, interrupt is still pending. 131 | 132 | \subsection{Interrupt Handler Stage} 133 | 134 | If the ID read is greater than zero, the target services the identified interrupt source. 135 | If the ID read is zero, this indicates no outstanding pending interrupts remain and the handler may terminate. 136 | 137 | \subsection{Interrupt Completion Stage} 138 | 139 | Once an interrupt has been serviced, completion is signalled to the PLIC by writing to the ID register. 140 | The act of writing to the register is the completion notification; the value written is irrelevant. 141 | 142 | On receiving the completion notification the PLIC will again allow interrupts to be forwarded from the corresponding source. 143 | 144 | The Interrupt Handler may then exit, however it is possible a new 145 | interrupt request may have been asserted while the handler was running. 146 | To reduce latency the handler may instead determine if a new interrupt 147 | has been received and if so again claim the interrupt (See earlier). In this 148 | way the interrupt handler can service all interrupts without the need to 149 | restore the interrupted context. 150 | -------------------------------------------------------------------------------- /rtl/verilog/core/plic_core.sv: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | // ,------. ,--. ,--. // 3 | // | .--. ' ,---. ,--,--. | | ,---. ,---. `--' ,---. // 4 | // | '--'.'| .-. |' ,-. | | | | .-. | .-. |,--.| .--' // 5 | // | |\ \ ' '-' '\ '-' | | '--.' '-' ' '-' || |\ `--. // 6 | // `--' '--' `---' `--`--' `-----' `---' `- /`--' `---' // 7 | // `---' // 8 | // RISC-V Platform-Level Interrupt Controller // 9 | // // 10 | ///////////////////////////////////////////////////////////////////// 11 | // // 12 | // Copyright (C) 2017 ROA Logic BV // 13 | // www.roalogic.com // 14 | // // 15 | // This source file may be used and distributed without // 16 | // restriction provided that this copyright statement is not // 17 | // removed from the file and that any derivative work contains // 18 | // the original copyright notice and the associated disclaimer. // 19 | // // 20 | // THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY // 21 | // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED // 22 | // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS // 23 | // FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR OR // 24 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // 25 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT // 26 | // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; // 27 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) // 28 | // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // 29 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR // 30 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // 31 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // 32 | // // 33 | ///////////////////////////////////////////////////////////////////// 34 | 35 | // +FHDR - Semiconductor Reuse Standard File Header Section ------- 36 | // FILE NAME : plic_core.sv 37 | // DEPARTMENT : 38 | // AUTHOR : rherveille 39 | // AUTHOR'S EMAIL : 40 | // ------------------------------------------------------------------ 41 | // RELEASE HISTORY 42 | // VERSION DATE AUTHOR DESCRIPTION 43 | // 1.0 2017-07-01 rherveille initial release 44 | // 2017-09-12 rherveille Added 'claim' and 'complete' 45 | // ------------------------------------------------------------------ 46 | // KEYWORDS : RISC-V PLATFORM LEVEL INTERRUPT CONTROLLER - PLIC 47 | // ------------------------------------------------------------------ 48 | // PURPOSE : PLIC Core Top Level 49 | // ------------------------------------------------------------------ 50 | // PARAMETERS 51 | // PARAM NAME RANGE DESCRIPTION DEFAULT UNITS 52 | // SOURCES 1+ No. of interupt sources 8 53 | // TARGETS 1+ No. of interrupt targets 1 54 | // PRIORITIES 1+ No. of priority levels 8 55 | // MAX_PENDING_COUNT 0+ Max. pending interrupts 0 56 | // ------------------------------------------------------------------ 57 | // REUSE ISSUES 58 | // Reset Strategy : external asynchronous active low; rst_n 59 | // Clock Domains : 1, clk, rising edge 60 | // Critical Timing : cell-array for each target 61 | // Test Features : na 62 | // Asynchronous I/F : no 63 | // Scan Methodology : na 64 | // Instantiations : plic_gateway, plic_cell, plic_target 65 | // Synthesizable (y/n) : Yes 66 | // Other : 67 | // -FHDR------------------------------------------------------------- 68 | 69 | module plic_core #( 70 | parameter SOURCES = 8, //Number of interrupt sources 71 | parameter TARGETS = 1, //Number of interrupt targets 72 | parameter PRIORITIES = 8, //Number of Priority levels 73 | parameter MAX_PENDING_COUNT = 0, 74 | 75 | //These should be localparams, but that's not supported by all tools yet 76 | parameter SOURCES_BITS = $clog2(SOURCES+1), //0=reserved 77 | parameter PRIORITY_BITS = $clog2(PRIORITIES) 78 | ) 79 | ( 80 | input rst_n, //Active low asynchronous reset 81 | clk, //System clock 82 | 83 | input [SOURCES -1:0] src, //Interrupt request from devices/sources 84 | el, //Edge/Level sensitive for each source 85 | output [SOURCES -1:0] ip, //Interrupt Pending for each source 86 | 87 | input [SOURCES -1:0] ie [TARGETS], //Interrupt enable per source, for each target 88 | input [PRIORITY_BITS-1:0] ipriority[SOURCES], //Priority for each source (priority is a reserved keyword) 89 | input [PRIORITY_BITS-1:0] threshold[TARGETS], //Priority Threshold for each target 90 | 91 | output [TARGETS -1:0] ireq, //Interrupt request for each target 92 | output [SOURCES_BITS -1:0] id [TARGETS], //Interrupt ID (1..SOURCES), for each target 93 | input [TARGETS -1:0] claim, //Interrupt claim 94 | input [TARGETS -1:0] complete //Interrupt handling complete 95 | ); 96 | ////////////////////////////////////////////////////////////////// 97 | // 98 | // Variables 99 | // 100 | genvar s, t; 101 | 102 | logic [SOURCES_BITS -1:0] id_array [TARGETS][SOURCES]; 103 | logic [PRIORITY_BITS-1:0] pr_array [TARGETS][SOURCES]; 104 | 105 | logic [SOURCES_BITS -1:0] id_claimed [TARGETS]; 106 | logic [TARGETS -1:0] claim_array [SOURCES]; 107 | logic [TARGETS -1:0] complete_array [SOURCES]; 108 | 109 | 110 | ////////////////////////////////////////////////////////////////// 111 | // 112 | // Module Body 113 | // 114 | 115 | 116 | /** Generate claim/complete per source, for each target 117 | */ 118 | generate 119 | for (s=0; s < SOURCES; s++) 120 | begin : gen_claims_source_array 121 | for (t=0; t < TARGETS; t++) 122 | begin : gen_claim_complete 123 | assign claim_array [s][t] = (id[t] == s+1) ? claim[t] : 1'b0; 124 | assign complete_array[s][t] = (id_claimed[t] == s+1) ? complete[t] : 1'b0; 125 | end 126 | end 127 | endgenerate 128 | 129 | 130 | /** Store claimed ID 131 | */ 132 | generate 133 | for (t=0; t < TARGETS; t++) 134 | begin : gen_id_claimed 135 | always @(posedge clk,negedge rst_n) 136 | if (!rst_n ) id_claimed[t] <= 'h0; 137 | else if ( claim[t]) id_claimed[t] <= id[t]; 138 | end 139 | endgenerate 140 | 141 | 142 | /** Build Gateways 143 | * 144 | * For each Interrupt Source there's a gateway 145 | */ 146 | generate 147 | for (s = 0; s < SOURCES; s++) 148 | begin : gen_gateway 149 | plic_gateway #(MAX_PENDING_COUNT) 150 | gateway_inst ( 151 | .rst_n ( rst_n ), 152 | .clk ( clk ), 153 | .src ( src [s] ), 154 | .edge_lvl ( el [s] ), 155 | .ip ( ip [s] ), 156 | .claim (|claim_array [s] ), 157 | .complete (|complete_array[s] ) 158 | ); 159 | end : gen_gateway 160 | endgenerate 161 | 162 | 163 | /** Build cell-array 164 | * 165 | * Generate array of ID/Priority cells 166 | * One cell for each source-target combination 167 | */ 168 | generate 169 | for (t=0; t < TARGETS; t++) 170 | begin : gen_cell_target_array 171 | for (s=0; s < SOURCES; s++) 172 | begin : gen_cell_source_array 173 | plic_cell #( 174 | .ID ( s +1 ), 175 | .SOURCES ( SOURCES ), 176 | .PRIORITIES ( PRIORITIES ) 177 | ) 178 | cell_inst ( 179 | .rst_ni ( rst_n ), 180 | .clk_i ( clk ), 181 | .ip_i ( ip [s] ), 182 | .ie_i ( ie [t][s] ), //bitslice from packed array 'ie' 183 | .priority_i ( ipriority [s] ), 184 | .id_o ( id_array [t][s] ), 185 | .priority_o ( pr_array [t][s] ) 186 | ); 187 | end : gen_cell_source_array 188 | end : gen_cell_target_array 189 | endgenerate 190 | 191 | 192 | /** Build output array 193 | * 194 | * Generate output array for each target 195 | */ 196 | generate 197 | for (t=0; t < TARGETS; t++) 198 | begin : gen_target 199 | plic_target #( 200 | .SOURCES ( SOURCES ), 201 | .PRIORITIES ( PRIORITIES ) 202 | ) 203 | target_inst ( 204 | .rst_ni ( rst_n ), 205 | .clk_i ( clk ), 206 | .id_i ( id_array [t] ), 207 | .priority_i ( pr_array [t] ), 208 | .threshold_i ( threshold[t] ), 209 | .id_o ( id [t] ), 210 | .ireq_o ( ireq [t] ) 211 | ); 212 | end : gen_target 213 | endgenerate 214 | 215 | endmodule : plic_core 216 | -------------------------------------------------------------------------------- /rtl/verilog/apb4/apb4_plic_top.sv: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | // ,------. ,--. ,--. // 3 | // | .--. ' ,---. ,--,--. | | ,---. ,---. `--' ,---. // 4 | // | '--'.'| .-. |' ,-. | | | | .-. | .-. |,--.| .--' // 5 | // | |\ \ ' '-' '\ '-' | | '--.' '-' ' '-' || |\ `--. // 6 | // `--' '--' `---' `--`--' `-----' `---' `- /`--' `---' // 7 | // `---' // 8 | // RISC-V Platform-Level Interrupt Controller // 9 | // // 10 | ///////////////////////////////////////////////////////////////////// 11 | // // 12 | // Copyright (C) 2017-2021 ROA Logic BV // 13 | // www.roalogic.com // 14 | // // 15 | // This source file may be used and distributed without // 16 | // restriction provided that this copyright statement is not // 17 | // removed from the file and that any derivative work contains // 18 | // the original copyright notice and the associated disclaimer. // 19 | // // 20 | // THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY // 21 | // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED // 22 | // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS // 23 | // FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR OR // 24 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // 25 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT // 26 | // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; // 27 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) // 28 | // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // 29 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR // 30 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // 31 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // 32 | // // 33 | ///////////////////////////////////////////////////////////////////// 34 | 35 | // +FHDR - Semiconductor Reuse Standard File Header Section ------- 36 | // FILE NAME : apb4_plic_top.sv 37 | // DEPARTMENT : 38 | // AUTHOR : rherveille 39 | // AUTHOR'S EMAIL : 40 | // ------------------------------------------------------------------ 41 | // RELEASE HISTORY 42 | // VERSION DATE AUTHOR DESCRIPTION 43 | // 1.0 2021-10-27 rherveille initial release 44 | // ------------------------------------------------------------------ 45 | // KEYWORDS : RISC-V PLATFORM LEVEL INTERRUPT CONTROLLER - PLIC 46 | // APB, APB4, AMBA 47 | // ------------------------------------------------------------------ 48 | // PURPOSE : APB4-Lite Top Level 49 | // ------------------------------------------------------------------ 50 | // PARAMETERS 51 | // PARAM NAME RANGE DESCRIPTION DEFAULT UNITS 52 | // PADDR_SIZE [32,64] PADDR width 32 53 | // PDATA_SIZE [32,64] PDATA width 32 54 | // SOURCES 1+ No. of interupt sources 16 55 | // TARGETS 1+ No. of interrupt targets 4 56 | // PRIORITIES 1+ No. of priority levels 8 57 | // MAX_PENDING_COUNT 0+ Max. pending events 8 58 | // HAS_THRESHOLD [0,1] Is 'threshold' impl.? 1 59 | // HAS_CONFIG_REG [0,1] Is 'config' implemented? 1 60 | // ------------------------------------------------------------------ 61 | // REUSE ISSUES 62 | // Reset Strategy : external asynchronous active low; PRESETn 63 | // Clock Domains : 1, PCLK, rising edge 64 | // Critical Timing : cell-array for each target 65 | // Test Features : na 66 | // Asynchronous I/F : no 67 | // Scan Methodology : na 68 | // Instantiations : plic_core, plic_dynamic_registers 69 | // Synthesizable (y/n) : Yes 70 | // Other : 71 | // -FHDR------------------------------------------------------------- 72 | 73 | 74 | 75 | module apb4_plic_top #( 76 | //AHB Parameters 77 | parameter PADDR_SIZE = 32, 78 | parameter PDATA_SIZE = 32, 79 | 80 | //PLIC Parameters 81 | parameter SOURCES = 64,//35, //Number of interrupt sources 82 | parameter TARGETS = 4, //Number of interrupt targets 83 | parameter PRIORITIES = 8, //Number of Priority levels 84 | parameter MAX_PENDING_COUNT = 8, //Max. number of 'pending' events 85 | parameter HAS_THRESHOLD = 1, //Is 'threshold' implemented? 86 | parameter HAS_CONFIG_REG = 1 //Is the 'configuration' register implemented? 87 | ) 88 | ( 89 | input PRESETn, 90 | PCLK, 91 | 92 | //AHB Slave Interface 93 | input PSEL, 94 | input PENABLE, 95 | input [PADDR_SIZE -1:0] PADDR, 96 | input PWRITE, 97 | input [PDATA_SIZE/8-1:0] PSTRB, 98 | input [PDATA_SIZE -1:0] PWDATA, 99 | output reg [PDATA_SIZE -1:0] PRDATA, 100 | output PREADY, 101 | output PSLVERR, 102 | 103 | input [SOURCES -1:0] src, //Interrupt sources 104 | output [TARGETS -1:0] irq //Interrupt Requests 105 | ); 106 | 107 | ////////////////////////////////////////////////////////////////// 108 | // 109 | // Constants 110 | // 111 | 112 | localparam SOURCES_BITS = $clog2(SOURCES+1); //0=reserved 113 | localparam PRIORITY_BITS = $clog2(PRIORITIES); 114 | 115 | 116 | /** Address map 117 | * Configuration (if implemented) 118 | * GateWay control 119 | * [SOURCES -1:0] el 120 | * [PRIORITY_BITS-1:0] priority [SOURCES] 121 | * 122 | * PLIC-Core 123 | * [SOURCES -1:0] ie [TARGETS] 124 | * [PRIORITY_BITS-1:0] threshold [TARGETS] (if implemented) 125 | * 126 | * Target 127 | * [SOURCES_BITS -1:0] id [TARGETS] 128 | */ 129 | 130 | ////////////////////////////////////////////////////////////////// 131 | // 132 | // Variables 133 | // 134 | 135 | //AHB write action 136 | logic apb_we, 137 | apb_re; 138 | 139 | //Decoded registers 140 | logic [SOURCES -1:0] el, 141 | ip; 142 | logic [PRIORITY_BITS-1:0] p [SOURCES]; 143 | logic [SOURCES -1:0] ie [TARGETS]; 144 | logic [PRIORITY_BITS-1:0] th [TARGETS]; 145 | logic [SOURCES_BITS -1:0] id [TARGETS]; 146 | 147 | logic [TARGETS -1:0] claim, 148 | complete; 149 | 150 | 151 | ////////////////////////////////////////////////////////////////// 152 | // 153 | // Module Body 154 | // 155 | 156 | 157 | /** APB accesses 158 | */ 159 | //The core supports zero-wait state accesses on all transfers. 160 | assign PREADY = 1'b1; //always ready 161 | assign PSLVERR = 1'b0; //Never an error 162 | 163 | 164 | /** APB Read/Write 165 | */ 166 | assign apb_re = PSEL & ~PENABLE & ~PWRITE; 167 | assign apb_we = PSEL & PENABLE & PWRITE; 168 | 169 | 170 | /** Hookup Dynamic Register block 171 | */ 172 | plic_dynamic_registers #( 173 | //Bus Interface Parameters 174 | .ADDR_SIZE ( PADDR_SIZE ), 175 | .DATA_SIZE ( PDATA_SIZE ), 176 | 177 | //PLIC Parameters 178 | .SOURCES ( SOURCES ), 179 | .TARGETS ( TARGETS ), 180 | .PRIORITIES ( PRIORITIES ), 181 | .MAX_PENDING_COUNT ( MAX_PENDING_COUNT ), 182 | .HAS_THRESHOLD ( HAS_THRESHOLD ), 183 | .HAS_CONFIG_REG ( HAS_CONFIG_REG ) 184 | ) 185 | dyn_register_inst ( 186 | .rst_n ( PRESETn ), //Active low asynchronous reset 187 | .clk ( PCLK ), //System clock 188 | 189 | .we ( apb_we ), //write cycle 190 | .re ( apb_re ), //read cycle 191 | .be ( PSTRB ), //PSTRB=byte-enables 192 | .waddr ( PADDR ), //write address 193 | .raddr ( PADDR ), //read address 194 | .wdata ( PWDATA ), //write data 195 | .rdata ( PRDATA ), //read data 196 | 197 | .el ( el ), //Edge/Level 198 | .ip ( ip ), //Interrupt Pending 199 | 200 | .ie ( ie ), //Interrupt Enable 201 | .p ( p ), //Priority 202 | .th ( th ), //Priority Threshold 203 | 204 | .id ( id ), //Interrupt ID 205 | .claim ( claim ), //Interrupt Claim 206 | .complete ( complete ) //Interrupt Complete 207 | ); 208 | 209 | 210 | /** Hookup PLIC Core 211 | */ 212 | plic_core #( 213 | .SOURCES ( SOURCES ), 214 | .TARGETS ( TARGETS ), 215 | .PRIORITIES ( PRIORITIES ), 216 | .MAX_PENDING_COUNT ( MAX_PENDING_COUNT ) 217 | ) 218 | plic_core_inst ( 219 | .rst_n ( PRESETn ), 220 | .clk ( PCLK ), 221 | 222 | .src ( src ), 223 | .el ( el ), 224 | .ip ( ip ), 225 | .ie ( ie ), 226 | .ipriority ( p ), 227 | .threshold ( th ), 228 | 229 | .ireq ( irq ), 230 | .id ( id ), 231 | .claim ( claim ), 232 | .complete ( complete ) 233 | ); 234 | 235 | endmodule : apb4_plic_top 236 | 237 | -------------------------------------------------------------------------------- /bench/verilog/ahb3lite_bfm.sv: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | // ,------. ,--. ,--. // 3 | // | .--. ' ,---. ,--,--. | | ,---. ,---. `--' ,---. // 4 | // | '--'.'| .-. |' ,-. | | | | .-. | .-. |,--.| .--' // 5 | // | |\ \ ' '-' '\ '-' | | '--.' '-' ' '-' || |\ `--. // 6 | // `--' '--' `---' `--`--' `-----' `---' `- /`--' `---' // 7 | // `---' // 8 | // RISC-V Platform-Level Interrupt Controller Testbench (Tests) // 9 | // // 10 | ///////////////////////////////////////////////////////////////////// 11 | // // 12 | // Copyright (C) 2017 ROA Logic BV // 13 | // www.roalogic.com // 14 | // // 15 | // This source file may be used and distributed without // 16 | // restriction provided that this copyright statement is not // 17 | // removed from the file and that any derivative work contains // 18 | // the original copyright notice and the associated disclaimer. // 19 | // // 20 | // This soure file is free software; you can redistribute it // 21 | // and/or modify it under the terms of the GNU General Public // 22 | // License as published by the Free Software Foundation, // 23 | // either version 3 of the License, or (at your option) any later // 24 | // versions. The current text of the License can be found at: // 25 | // http://www.gnu.org/licenses/gpl.html // 26 | // // 27 | // This source file is distributed in the hope that it will be // 28 | // useful, but WITHOUT ANY WARRANTY; without even the implied // 29 | // warranty of MERCHANTABILITY or FITTNESS FOR A PARTICULAR // 30 | // PURPOSE. See the GNU General Public License for more details. // 31 | // // 32 | ///////////////////////////////////////////////////////////////////// 33 | 34 | module ahb3lite_master_bfm #( 35 | parameter HADDR_SIZE = 16, 36 | parameter HDATA_SIZE = 32 37 | ) 38 | ( 39 | input HRESETn, 40 | HCLK, 41 | 42 | //AHB Master Interface 43 | output reg HSEL, 44 | output reg [HADDR_SIZE-1:0] HADDR, 45 | output reg [HDATA_SIZE-1:0] HWDATA, 46 | input [HDATA_SIZE-1:0] HRDATA, 47 | output reg HWRITE, 48 | output reg [ 2:0] HSIZE, 49 | output reg [ 2:0] HBURST, 50 | output reg [ 3:0] HPROT, 51 | output reg [ 1:0] HTRANS, 52 | output reg HMASTLOCK, 53 | input HREADY, 54 | input HRESP 55 | ); 56 | 57 | always @(negedge HRESETn) reset(); 58 | 59 | 60 | ////////////////////////////////////////////////////////////////// 61 | // 62 | // Constants 63 | // 64 | import ahb3lite_pkg::*; 65 | 66 | 67 | ///////////////////////////////////////////////////////// 68 | // 69 | // Tasks 70 | // 71 | task reset(); 72 | //Reset AHB Bus 73 | HSEL = 1'b0; 74 | HADDR = 'hx; 75 | HWDATA = 'hx; 76 | HWRITE = 'hx; 77 | HSIZE = 'hx; 78 | HBURST = 'hx; 79 | HPROT = 'hx; 80 | HTRANS = HTRANS_IDLE; 81 | HMASTLOCK = 'h0; 82 | 83 | @(posedge HRESETn); 84 | endtask 85 | 86 | 87 | task idle (); 88 | //Put AHB Bus in IDLE state 89 | //Call after write or read sequence 90 | wait4hready(); 91 | HSEL <= 1'b0; 92 | HTRANS <= HTRANS_IDLE; 93 | endtask 94 | 95 | 96 | task automatic write ( 97 | input [HADDR_SIZE-1:0] address, 98 | const ref [HDATA_SIZE-1:0] data[], 99 | input [ 2:0] size, 100 | input [ 2:0] burst 101 | ); 102 | int beats; 103 | 104 | beats = get_beats_per_burst(burst); 105 | if (beats < 0) beats = data.size(); 106 | 107 | fork 108 | ahb_cmd(address, size, burst, 1'b1, beats); 109 | ahb_data(address, size, burst, 1'b1, beats, data); 110 | join_any 111 | endtask 112 | 113 | 114 | task automatic read ( 115 | input [HADDR_SIZE-1:0] address, 116 | ref [HDATA_SIZE-1:0] data[], 117 | input [ 2:0] size, 118 | input [ 2:0] burst 119 | ); 120 | int beats; 121 | 122 | beats = get_beats_per_burst(burst); 123 | if (beats < 0) beats = data.size(); 124 | 125 | fork 126 | ahb_cmd(address, size, burst, 1'b0, beats); 127 | ahb_data(address, size, burst, 1'b0, beats, data); 128 | join_any 129 | endtask 130 | 131 | 132 | ///////////////////////////////////////////////////////// 133 | // 134 | // Sub-Tasks 135 | // 136 | task wait4hready; 137 | do 138 | @(posedge HCLK); 139 | while (!HREADY); 140 | endtask : wait4hready 141 | 142 | 143 | task automatic ahb_cmd ( 144 | input [HADDR_SIZE-1:0] addr, 145 | input [ 2:0] size, 146 | input [ 2:0] burst, 147 | input rw, 148 | input int beats 149 | ); 150 | wait4hready(); 151 | HSEL <= 1'b1; 152 | HADDR <= addr; 153 | HWRITE <= rw; 154 | HSIZE <= size; 155 | HBURST <= burst; 156 | HPROT <= 'hx; 157 | HTRANS <= HTRANS_NONSEQ; 158 | HMASTLOCK <= 1'b0; 159 | 160 | repeat (beats -1) 161 | begin 162 | wait4hready(); 163 | HADDR <= next_address(size,burst); 164 | HTRANS <= HTRANS_SEQ; 165 | end 166 | endtask : ahb_cmd 167 | 168 | 169 | task automatic ahb_data ( 170 | input [HADDR_SIZE-1:0] address, 171 | input [ 2:0] size, 172 | input [ 2:0] burst, 173 | input rw, 174 | input int beats, 175 | ref [HDATA_SIZE-1:0] data[] 176 | ); 177 | logic [(HDATA_SIZE+7)/8 -1:0] byte_offset; 178 | logic [HDATA_SIZE -1:0] data_copy[], 179 | tmp_var; 180 | 181 | if (!rw) 182 | begin 183 | HWDATA <= 'hx; 184 | 185 | //extra cycle for reading 186 | //read at the end of the cycle 187 | wait4hready(); 188 | end 189 | else 190 | begin 191 | //copy data, prevent it being overwritten by caller 192 | data_copy = data; 193 | end 194 | 195 | wait4hready(); 196 | 197 | //get the address offset. No checks if the offset is legal 198 | byte_offset = address % (HDATA_SIZE/8); 199 | 200 | //transfer beats 201 | for (int nbeat = 0; nbeat < beats; nbeat++) 202 | begin 203 | wait4hready(); 204 | 205 | if (rw) 206 | begin 207 | //writing ... transfer from data-buffer to AHB-HWDATA 208 | HWDATA <= 'hx; 209 | 210 | //'byte' is reserved, so use nbyte 211 | for (int nbyte = 0; nbyte < get_bytes_per_beat(size); nbyte++) 212 | HWDATA[(nbyte + byte_offset)*8 +: 8] <= data_copy[nbeat][nbyte*8 +: 8]; 213 | end 214 | else 215 | begin 216 | //reading ... transfer from AHB-HRDATA to data-buffer 217 | 218 | //'byte' is reserved, so use nbyte 219 | //Store in temporary variable. 220 | // Using data[nbeat] directly fails when calling with a multi-dimensional dynamic array. Why???? 221 | for (int nbyte = 0; nbyte < get_bytes_per_beat(size); nbyte++) 222 | tmp_var[nbyte*8 +: 8] = HRDATA[(nbyte+byte_offset)*8 +: 8]; 223 | 224 | //copy read-data 225 | data[nbeat] = tmp_var; 226 | end 227 | 228 | byte_offset += get_bytes_per_beat(size) % (HDATA_SIZE/8); 229 | end 230 | endtask : ahb_data 231 | 232 | 233 | 234 | ///////////////////////////////////////////////////////// 235 | // 236 | // Functions 237 | // 238 | function int get_bytes_per_beat(input [2:0] hsize); 239 | case (hsize) 240 | HSIZE_B8 : get_bytes_per_beat = 1; 241 | HSIZE_B16 : get_bytes_per_beat = 2; 242 | HSIZE_B32 : get_bytes_per_beat = 4; 243 | HSIZE_B64 : get_bytes_per_beat = 8; 244 | HSIZE_B128 : get_bytes_per_beat = 16; 245 | HSIZE_B256 : get_bytes_per_beat = 32; 246 | HSIZE_B512 : get_bytes_per_beat = 64; 247 | HSIZE_B1024: get_bytes_per_beat = 128; 248 | endcase 249 | endfunction : get_bytes_per_beat 250 | 251 | 252 | function int get_beats_per_burst(input [2:0] hburst); 253 | case (hburst) 254 | HBURST_SINGLE: get_beats_per_burst = 1; 255 | HBURST_INCR : get_beats_per_burst = -1; 256 | HBURST_INCR4 : get_beats_per_burst = 4; 257 | HBURST_WRAP4 : get_beats_per_burst = 4; 258 | HBURST_INCR8 : get_beats_per_burst = 8; 259 | HBURST_WRAP8 : get_beats_per_burst = 8; 260 | HBURST_INCR16: get_beats_per_burst = 16; 261 | HBURST_WRAP16: get_beats_per_burst = 16; 262 | endcase 263 | endfunction : get_beats_per_burst 264 | 265 | 266 | function [HADDR_SIZE-1:0] next_address(input [2:0] hsize, hburst); 267 | //generate address mask 268 | int beats_per_burst; 269 | logic [10:0] addr_mask; 270 | 271 | beats_per_burst = get_beats_per_burst(hburst); 272 | beats_per_burst = beats_per_burst > 0 ? beats_per_burst : 1; 273 | addr_mask = (get_bytes_per_beat(hsize) * beats_per_burst) -1; 274 | 275 | case (hburst) 276 | HBURST_WRAP4 : next_address = (HADDR & ~addr_mask) | ((HADDR + get_bytes_per_beat(hsize)) & addr_mask); 277 | HBURST_WRAP8 : next_address = (HADDR & ~addr_mask) | ((HADDR + get_bytes_per_beat(hsize)) & addr_mask); 278 | HBURST_WRAP16: next_address = (HADDR & ~addr_mask) | ((HADDR + get_bytes_per_beat(hsize)) & addr_mask); 279 | default : next_address = HADDR + get_bytes_per_beat(hsize); 280 | endcase 281 | endfunction : next_address 282 | 283 | endmodule : ahb3lite_master_bfm 284 | -------------------------------------------------------------------------------- /rtl/verilog/ahb3lite/ahb3lite_plic_top.sv: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | // ,------. ,--. ,--. // 3 | // | .--. ' ,---. ,--,--. | | ,---. ,---. `--' ,---. // 4 | // | '--'.'| .-. |' ,-. | | | | .-. | .-. |,--.| .--' // 5 | // | |\ \ ' '-' '\ '-' | | '--.' '-' ' '-' || |\ `--. // 6 | // `--' '--' `---' `--`--' `-----' `---' `- /`--' `---' // 7 | // `---' // 8 | // RISC-V Platform-Level Interrupt Controller // 9 | // // 10 | ///////////////////////////////////////////////////////////////////// 11 | // // 12 | // Copyright (C) 2017 ROA Logic BV // 13 | // www.roalogic.com // 14 | // // 15 | // This source file may be used and distributed without // 16 | // restriction provided that this copyright statement is not // 17 | // removed from the file and that any derivative work contains // 18 | // the original copyright notice and the associated disclaimer. // 19 | // // 20 | // THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY // 21 | // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED // 22 | // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS // 23 | // FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR OR // 24 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // 25 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT // 26 | // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; // 27 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) // 28 | // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // 29 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR // 30 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // 31 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // 32 | // // 33 | ///////////////////////////////////////////////////////////////////// 34 | 35 | // +FHDR - Semiconductor Reuse Standard File Header Section ------- 36 | // FILE NAME : ahb3lite_plic_top.sv 37 | // DEPARTMENT : 38 | // AUTHOR : rherveille 39 | // AUTHOR'S EMAIL : 40 | // ------------------------------------------------------------------ 41 | // RELEASE HISTORY 42 | // VERSION DATE AUTHOR DESCRIPTION 43 | // 1.0 2017-07-05 rherveille initial release 44 | // 2017-09013 rherveille Added 'claim' and 'complete' 45 | // ------------------------------------------------------------------ 46 | // KEYWORDS : RISC-V PLATFORM LEVEL INTERRUPT CONTROLLER - PLIC 47 | // AHB3-Lite, AMBA 48 | // ------------------------------------------------------------------ 49 | // PURPOSE : AHB3-Lite Top Level 50 | // ------------------------------------------------------------------ 51 | // PARAMETERS 52 | // PARAM NAME RANGE DESCRIPTION DEFAULT UNITS 53 | // HADDR_SIZE [32,64] HADDR width 32 54 | // HDATA_SIZE [32,64] HDATA width 32 55 | // SOURCES 1+ No. of interupt sources 16 56 | // TARGETS 1+ No. of interrupt targets 4 57 | // PRIORITIES 1+ No. of priority levels 8 58 | // MAX_PENDING_COUNT 0+ Max. pending events 8 59 | // HAS_THRESHOLD [0,1] Is 'threshold' impl.? 1 60 | // HAS_CONFIG_REG [0,1] Is 'config' implemented? 1 61 | // ------------------------------------------------------------------ 62 | // REUSE ISSUES 63 | // Reset Strategy : external asynchronous active low; HRESETn 64 | // Clock Domains : 1, HCLK, rising edge 65 | // Critical Timing : cell-array for each target 66 | // Test Features : na 67 | // Asynchronous I/F : no 68 | // Scan Methodology : na 69 | // Instantiations : plic_core, plic_dynamic_registers 70 | // Synthesizable (y/n) : Yes 71 | // Other : 72 | // -FHDR------------------------------------------------------------- 73 | 74 | 75 | 76 | module ahb3lite_plic_top 77 | import ahb3lite_pkg::*; 78 | #( 79 | //AHB Parameters 80 | parameter HADDR_SIZE = 32, 81 | parameter HDATA_SIZE = 32, 82 | 83 | //PLIC Parameters 84 | parameter SOURCES = 64,//35, //Number of interrupt sources 85 | parameter TARGETS = 4, //Number of interrupt targets 86 | parameter PRIORITIES = 8, //Number of Priority levels 87 | parameter MAX_PENDING_COUNT = 8, //Max. number of 'pending' events 88 | parameter HAS_THRESHOLD = 1, //Is 'threshold' implemented? 89 | parameter HAS_CONFIG_REG = 1 //Is the 'configuration' register implemented? 90 | ) 91 | ( 92 | input HRESETn, 93 | HCLK, 94 | 95 | //AHB Slave Interface 96 | input HSEL, 97 | input [HADDR_SIZE-1:0] HADDR, 98 | input [HDATA_SIZE-1:0] HWDATA, 99 | output reg [HDATA_SIZE-1:0] HRDATA, 100 | input HWRITE, 101 | input [ 2:0] HSIZE, 102 | input [ 2:0] HBURST, 103 | input [ 3:0] HPROT, 104 | input [ 1:0] HTRANS, 105 | output reg HREADYOUT, 106 | input HREADY, 107 | output HRESP, 108 | 109 | input [SOURCES -1:0] src, //Interrupt sources 110 | output [TARGETS -1:0] irq //Interrupt Requests 111 | ); 112 | 113 | ////////////////////////////////////////////////////////////////// 114 | // 115 | // Constants 116 | // 117 | localparam HDATA_BYTES = (HDATA_SIZE+7)/8; //number of bytes in HDATA 118 | localparam BE_SIZE = HDATA_BYTES; 119 | 120 | localparam SOURCES_BITS = $clog2(SOURCES+1); //0=reserved 121 | localparam PRIORITY_BITS = $clog2(PRIORITIES); 122 | 123 | 124 | /** Address map 125 | * Configuration (if implemented) 126 | * GateWay control 127 | * [SOURCES -1:0] el 128 | * [PRIORITY_BITS-1:0] priority [SOURCES] 129 | * 130 | * PLIC-Core 131 | * [SOURCES -1:0] ie [TARGETS] 132 | * [PRIORITY_BITS-1:0] threshold [TARGETS] (if implemented) 133 | * 134 | * Target 135 | * [SOURCES_BITS -1:0] id [TARGETS] 136 | */ 137 | 138 | ////////////////////////////////////////////////////////////////// 139 | // 140 | // Variables 141 | // 142 | 143 | //AHB write action 144 | logic ahb_we, 145 | ahb_re; 146 | logic [BE_SIZE -1:0] ahb_be; 147 | logic [HADDR_SIZE -1:0] ahb_waddr; 148 | 149 | //Decoded registers 150 | logic [SOURCES -1:0] el, 151 | ip; 152 | logic [PRIORITY_BITS-1:0] p [SOURCES]; 153 | logic [SOURCES -1:0] ie [TARGETS]; 154 | logic [PRIORITY_BITS-1:0] th [TARGETS]; 155 | logic [SOURCES_BITS -1:0] id [TARGETS]; 156 | 157 | logic [TARGETS -1:0] claim, 158 | complete; 159 | 160 | ////////////////////////////////////////////////////////////////// 161 | // 162 | // Functions 163 | // 164 | 165 | /** AHB Accesses 166 | */ 167 | function logic [6:0] address_offset; 168 | //returns a mask for the lesser bits of the address 169 | //meaning bits [ 0] for 16bit data 170 | // [1:0] for 32bit data 171 | // [2:0] for 64bit data 172 | //etc 173 | 174 | //default value, prevent warnings 175 | address_offset = 0; 176 | 177 | //What are the lesser bits in HADDR? 178 | case (HDATA_SIZE) 179 | 1024: address_offset = 7'b111_1111; 180 | 512: address_offset = 7'b011_1111; 181 | 256: address_offset = 7'b001_1111; 182 | 128: address_offset = 7'b000_1111; 183 | 64: address_offset = 7'b000_0111; 184 | 32: address_offset = 7'b000_0011; 185 | 16: address_offset = 7'b000_0001; 186 | default: address_offset = 7'b000_0000; 187 | endcase 188 | endfunction : address_offset 189 | 190 | 191 | function logic [6:0] address_mask; 192 | //Returns a mask for the major bits of the address 193 | //meaning bits [HADDR_SIZE-1:0] for 8bits data 194 | // [HADDR_SIZE-1:1] for 16bits data 195 | // [HADDR_SIZE-1:2] for 32bits data 196 | //etc 197 | address_mask = ~address_offset(); 198 | endfunction : address_mask 199 | 200 | 201 | function logic [BE_SIZE-1:0] gen_be; 202 | input [ 2:0] hsize; 203 | input [HADDR_SIZE-1:0] haddr; 204 | 205 | logic [127:0] full_be; 206 | logic [ 6:0] haddr_masked; 207 | 208 | //get number of active lanes for a 1024bit databus (max width) for this HSIZE 209 | case (hsize) 210 | HSIZE_B1024: full_be = 'hffff_ffff_ffff_ffff_ffff_ffff_ffff_ffff; 211 | HSIZE_B512 : full_be = 'hffff_ffff_ffff_ffff; 212 | HSIZE_B256 : full_be = 'hffff_ffff; 213 | HSIZE_B128 : full_be = 'hffff; 214 | HSIZE_DWORD: full_be = 'hff; 215 | HSIZE_WORD : full_be = 'hf; 216 | HSIZE_HWORD: full_be = 'h3; 217 | default : full_be = 'h1; 218 | endcase 219 | 220 | //generate masked address 221 | haddr_masked = haddr & address_offset(); 222 | 223 | //create byte-enable 224 | gen_be = full_be[BE_SIZE-1:0] << haddr_masked; 225 | endfunction : gen_be 226 | 227 | 228 | function logic [HDATA_SIZE-1:0] gen_wval; 229 | //Returns the new value for a register 230 | // if be[n] == '1' then gen_val[byte_n] = new_val[byte_n] 231 | // else gen_val[byte_n] = old_val[byte_n] 232 | input [HDATA_SIZE-1:0] old_val, 233 | new_val; 234 | input [BE_SIZE -1:0] be; 235 | 236 | for (int n=0; n < BE_SIZE; n++) 237 | gen_wval[n*8 +: 8] = be[n] ? new_val[n*8 +: 8] : old_val[n*8 +: 8]; 238 | endfunction : gen_wval 239 | 240 | 241 | ////////////////////////////////////////////////////////////////// 242 | // 243 | // Module Body 244 | // 245 | 246 | 247 | /** AHB accesses 248 | */ 249 | //The core supports zero-wait state accesses on all transfers. 250 | assign HREADYOUT = 1'b1; //always ready 251 | assign HRESP = HRESP_OKAY; //Never an error 252 | 253 | 254 | /** AHB Reads 255 | */ 256 | assign ahb_re = HREADY & HSEL & !HWRITE & (HTRANS != HTRANS_BUSY) & (HTRANS != HTRANS_IDLE); 257 | 258 | 259 | /** AHB Writes 260 | */ 261 | //generate internal write signal 262 | always @(posedge HCLK) 263 | if (HREADY) ahb_we <= HSEL & HWRITE & (HTRANS != HTRANS_BUSY) & (HTRANS != HTRANS_IDLE); 264 | else ahb_we <= 1'b0; 265 | 266 | //decode Byte-Enables 267 | always @(posedge HCLK) 268 | if (HREADY) ahb_be <= gen_be(HSIZE,HADDR); 269 | 270 | //store write address 271 | always @(posedge HCLK) 272 | if (HREADY) ahb_waddr <= HADDR; 273 | 274 | 275 | /** Hookup Dynamic Register block 276 | */ 277 | plic_dynamic_registers #( 278 | //Bus Interface Parameters 279 | .ADDR_SIZE ( HADDR_SIZE ), 280 | .DATA_SIZE ( HDATA_SIZE ), 281 | 282 | //PLIC Parameters 283 | .SOURCES ( SOURCES ), 284 | .TARGETS ( TARGETS ), 285 | .PRIORITIES ( PRIORITIES ), 286 | .MAX_PENDING_COUNT ( MAX_PENDING_COUNT ), 287 | .HAS_THRESHOLD ( HAS_THRESHOLD ), 288 | .HAS_CONFIG_REG ( HAS_CONFIG_REG ) 289 | ) 290 | dyn_register_inst ( 291 | .rst_n ( HRESETn ), //Active low asynchronous reset 292 | .clk ( HCLK ), //System clock 293 | 294 | .we ( HREADY & ahb_we ), //write when write-cycle and HREADY 295 | .re ( HREADY & ahb_re ), //read when HREADY 296 | .be ( ahb_be ), //stored byte-enables 297 | .waddr ( ahb_waddr ), //stored write address 298 | .raddr ( HADDR ), //read address 299 | .wdata ( HWDATA ), //write data 300 | .rdata ( HRDATA ), //read data 301 | 302 | .el ( el ), //Edge/Level 303 | .ip ( ip ), //Interrupt Pending 304 | 305 | .ie ( ie ), //Interrupt Enable 306 | .p ( p ), //Priority 307 | .th ( th ), //Priority Threshold 308 | 309 | .id ( id ), //Interrupt ID 310 | .claim ( claim ), //Interrupt Claim 311 | .complete ( complete ) //Interrupt Complete 312 | ); 313 | 314 | 315 | /** Hookup PLIC Core 316 | */ 317 | plic_core #( 318 | .SOURCES ( SOURCES ), 319 | .TARGETS ( TARGETS ), 320 | .PRIORITIES ( PRIORITIES ), 321 | .MAX_PENDING_COUNT ( MAX_PENDING_COUNT ) 322 | ) 323 | plic_core_inst ( 324 | .rst_n ( HRESETn ), 325 | .clk ( HCLK ), 326 | 327 | .src ( src ), 328 | .el ( el ), 329 | .ip ( ip ), 330 | .ie ( ie ), 331 | .ipriority ( p ), 332 | .threshold ( th ), 333 | 334 | .ireq ( irq ), 335 | .id ( id ), 336 | .claim ( claim ), 337 | .complete ( complete ) 338 | ); 339 | 340 | endmodule : ahb3lite_plic_top 341 | 342 | -------------------------------------------------------------------------------- /bench/verilog/test.sv: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | // ,------. ,--. ,--. // 3 | // | .--. ' ,---. ,--,--. | | ,---. ,---. `--' ,---. // 4 | // | '--'.'| .-. |' ,-. | | | | .-. | .-. |,--.| .--' // 5 | // | |\ \ ' '-' '\ '-' | | '--.' '-' ' '-' || |\ `--. // 6 | // `--' '--' `---' `--`--' `-----' `---' `- /`--' `---' // 7 | // `---' // 8 | // RISC-V Platform-Level Interrupt Controller Testbench (Tests) // 9 | // // 10 | ///////////////////////////////////////////////////////////////////// 11 | // // 12 | // Copyright (C) 2017 ROA Logic BV // 13 | // www.roalogic.com // 14 | // // 15 | // This source file may be used and distributed without // 16 | // restriction provided that this copyright statement is not // 17 | // removed from the file and that any derivative work contains // 18 | // the original copyright notice and the associated disclaimer. // 19 | // // 20 | // This soure file is free software; you can redistribute it // 21 | // and/or modify it under the terms of the GNU General Public // 22 | // License as published by the Free Software Foundation, // 23 | // either version 3 of the License, or (at your option) any later // 24 | // versions. The current text of the License can be found at: // 25 | // http://www.gnu.org/licenses/gpl.html // 26 | // // 27 | // This source file is distributed in the hope that it will be // 28 | // useful, but WITHOUT ANY WARRANTY; without even the implied // 29 | // warranty of MERCHANTABILITY or FITTNESS FOR A PARTICULAR // 30 | // PURPOSE. See the GNU General Public License for more details. // 31 | // // 32 | ///////////////////////////////////////////////////////////////////// 33 | 34 | module test #( 35 | parameter HADDR_SIZE = 16, 36 | parameter HDATA_SIZE = 32, 37 | 38 | parameter SOURCES = 16, //Number of interrupt sources 39 | parameter TARGETS = 4, //Number of interrupt targets 40 | parameter PRIORITIES = 7, //Number of Priority levels 41 | parameter MAX_PENDING_COUNT = 8, // 42 | parameter HAS_THRESHOLD = 1, 43 | parameter HAS_CONFIG_REG = 1 44 | ) 45 | ( 46 | input HRESETn, 47 | HCLK, 48 | 49 | output HSEL, 50 | output [HADDR_SIZE-1:0] HADDR, 51 | output [HDATA_SIZE-1:0] HWDATA, 52 | input [HDATA_SIZE-1:0] HRDATA, 53 | output HWRITE, 54 | output [ 2:0] HSIZE, 55 | output [ 2:0] HBURST, 56 | output [ 3:0] HPROT, 57 | output [ 1:0] HTRANS, 58 | output HMASTLOCK, 59 | input HREADY, 60 | input HRESP, 61 | 62 | output reg [SOURCES -1:0] src, 63 | input [TARGETS -1:0] irq 64 | ); 65 | 66 | ////////////////////////////////////////////////////////////////// 67 | // 68 | // Constants 69 | // 70 | import ahb3lite_pkg::*; 71 | 72 | localparam BE_SIZE = (HDATA_SIZE+7)/8; 73 | localparam PRIORITY_BITS = $clog2(PRIORITIES); 74 | 75 | typedef enum {CONFIG, EDGE_LEVEL, IPRIORITY, IENABLE, PTHRESHOLD, ID} registers_t; 76 | 77 | //Configuration Bits 78 | localparam MAX_SOURCES_BITS = 16; 79 | localparam MAX_TARGETS_BITS = 16; 80 | localparam MAX_PRIORITY_BITS = MAX_SOURCES_BITS; 81 | localparam HAS_THRESHOLD_BITS = 1; 82 | 83 | //How many CONFIG registers are there (only 1) 84 | localparam CONFIG_REGS = HAS_CONFIG_REG == 0 ? 0 : (MAX_SOURCES_BITS + MAX_TARGETS_BITS + MAX_PRIORITY_BITS + HAS_THRESHOLD_BITS + HDATA_SIZE -1) / HDATA_SIZE; 85 | 86 | //Amount of Edge/Level registers 87 | localparam EDGE_LEVEL_REGS = (SOURCES + HDATA_SIZE -1) / HDATA_SIZE; 88 | 89 | //Amount of Interrupt Enable registers 90 | localparam IE_REGS = EDGE_LEVEL_REGS * TARGETS; 91 | 92 | //Each PRIORITY field starts at a new nibble boundary 93 | //Get the number of nibbles in 'PRIORITY_BITS' ? 94 | localparam PRIORITY_NIBBLES = (PRIORITY_BITS +3 -1) / 4; 95 | 96 | //How many PRIORITY fields fit in 1 register? 97 | localparam PRIORITY_FIELDS_PER_REG = HDATA_SIZE / (PRIORITY_NIBBLES*4); 98 | 99 | //Amount of Priority registers 100 | localparam PRIORITY_REGS = (SOURCES + PRIORITY_FIELDS_PER_REG -1) / PRIORITY_FIELDS_PER_REG; 101 | 102 | //Amount of Threshold registers 103 | localparam PTHRESHOLD_REGS = HAS_THRESHOLD == 0 ? 0 : TARGETS; 104 | 105 | //Amount of ID registers 106 | localparam ID_REGS = TARGETS; 107 | 108 | //Total amount of registers 109 | localparam TOTAL_REGS = CONFIG_REGS + EDGE_LEVEL_REGS + IE_REGS + PRIORITY_REGS + PTHRESHOLD_REGS + ID_REGS; 110 | 111 | 112 | ////////////////////////////////////////////////////////////////// 113 | // 114 | // Functions 115 | // 116 | function automatic registers_t register_function; 117 | //return register-type for specified register 118 | input int r; 119 | 120 | int idx; 121 | idx = r; 122 | 123 | //1. Configuration Register 124 | if (idx < CONFIG_REGS ) return CONFIG; 125 | idx -= CONFIG_REGS; 126 | 127 | //2. Gateway control registers 128 | // Edge/Level 129 | // Interrupt Pending/Acknowledge 130 | if (idx < EDGE_LEVEL_REGS) return EDGE_LEVEL; 131 | idx -= EDGE_LEVEL_REGS; 132 | 133 | //3. PLIC Core fabric registers 134 | if (idx < PRIORITY_REGS) return IPRIORITY; 135 | idx -= PRIORITY_REGS; 136 | if (idx < IE_REGS ) return IENABLE; 137 | idx -= IE_REGS; 138 | 139 | //4. Target Registers 140 | if (idx < PTHRESHOLD_REGS) return PTHRESHOLD; 141 | return ID; 142 | endfunction : register_function 143 | 144 | 145 | function automatic int register_idx; 146 | //return offset in register-type 147 | input int r; 148 | 149 | int idx; 150 | idx = r; 151 | 152 | //1. Configuration registers 153 | if (idx < CONFIG_REGS ) return idx; 154 | idx -= CONFIG_REGS; 155 | 156 | //2. first Gateway control registers 157 | // Edge/Level 158 | // Interrupt Pending/Acknowledge 159 | if (idx < EDGE_LEVEL_REGS) return idx; 160 | idx -= EDGE_LEVEL_REGS; 161 | 162 | //3. PLIC Core fabric registers 163 | if (idx < PRIORITY_REGS ) return idx; 164 | idx -= PRIORITY_REGS; 165 | if (idx < IE_REGS ) return idx; 166 | idx -= IE_REGS; 167 | 168 | //4. TARGET registers 169 | if (idx < PTHRESHOLD_REGS) return idx; 170 | idx -=PTHRESHOLD_REGS; 171 | return idx; 172 | endfunction : register_idx 173 | 174 | 175 | function string register_function_name; 176 | //returns the 'string' name associated with a register type 177 | input registers_t function_number; 178 | 179 | string name_array[registers_t]; 180 | name_array[CONFIG ] = "Configuration"; 181 | name_array[EDGE_LEVEL] = "Edge/Level"; 182 | name_array[IENABLE ] = "Interrupt Enable"; 183 | name_array[IPRIORITY ] = "Interrupt Priority"; 184 | name_array[PTHRESHOLD] = "Priority Threshold"; 185 | name_array[ID ] = "ID"; 186 | 187 | return name_array[function_number]; 188 | endfunction : register_function_name 189 | 190 | 191 | ////////////////////////////////////////////////////////////////// 192 | // 193 | // Variables 194 | // 195 | int reset_watchdog, 196 | got_reset, 197 | errors; 198 | 199 | ///////////////////////////////////////////////////////// 200 | // 201 | // Instantiate the AHB-Master 202 | // 203 | ahb3lite_master_bfm #( 204 | .HADDR_SIZE ( HADDR_SIZE ), 205 | .HDATA_SIZE ( HDATA_SIZE ) 206 | ) 207 | ahb_mst_bfm ( 208 | .* 209 | ); 210 | 211 | 212 | initial 213 | begin 214 | errors = 0; 215 | reset_watchdog = 0; 216 | got_reset = 0; 217 | 218 | forever 219 | begin 220 | reset_watchdog++; 221 | @(posedge HCLK); 222 | if (!got_reset && reset_watchdog == 1000) 223 | $fatal(-1,"HRESETn not asserted\nTestbench requires an AHB reset"); 224 | end 225 | end 226 | 227 | 228 | always @(negedge HRESETn) 229 | begin 230 | //wait for reset to negate 231 | @(posedge HRESETn); 232 | got_reset = 1; 233 | 234 | welcome_text(); 235 | 236 | //check initial values 237 | test_reset_register_values(); 238 | 239 | //Test dynamic register access to EL 240 | test_el(); 241 | 242 | //Test a single interrupt source 243 | test_single(); 244 | 245 | 246 | //Finish simulation 247 | repeat (100) @(posedge HCLK); 248 | finish_text(); 249 | $finish(); 250 | end 251 | 252 | 253 | ///////////////////////////////////////////////////////// 254 | // 255 | // Tasks 256 | // 257 | task welcome_text(); 258 | $display ("------------------------------------------------------------"); 259 | $display (" ,------. ,--. ,--. "); 260 | $display (" | .--. ' ,---. ,--,--. | | ,---. ,---. `--' ,---. "); 261 | $display (" | '--'.'| .-. |' ,-. | | | | .-. | .-. |,--.| .--' "); 262 | $display (" | |\\ \\ ' '-' '\\ '-' | | '--.' '-' ' '-' || |\\ `--. "); 263 | $display (" `--' '--' `---' `--`--' `-----' `---' `- /`--' `---' "); 264 | $display (" `---' "); 265 | $display (" AHB3Lite PLIC Testbench Initialized "); 266 | $display ("------------------------------------------------------------"); 267 | endtask : welcome_text 268 | 269 | 270 | task finish_text(); 271 | if (errors>0) 272 | begin 273 | $display ("------------------------------------------------------------"); 274 | $display (" AHB3Lite PLIC Testbench failed with (%0d) errors @%0t", errors, $time); 275 | $display ("------------------------------------------------------------"); 276 | end 277 | else 278 | begin 279 | $display ("------------------------------------------------------------"); 280 | $display (" AHB3Lite PLIC Testbench finished successfully @%0t", $time); 281 | $display ("------------------------------------------------------------"); 282 | end 283 | endtask : finish_text 284 | 285 | 286 | /** test_reset_register_values 287 | * Test if all register are zero after reset 288 | */ 289 | task test_reset_register_values; 290 | int r; 291 | 292 | logic [HDATA_SIZE-1:0] rbuffer[][]; 293 | logic [ 63:0] config_reg_contents; 294 | 295 | $display ("Checking reset values ..."); 296 | 297 | //Is 'config' implemented? 298 | if (HAS_CONFIG_REG) 299 | begin 300 | //create new read-buffers (1 per transaction) 301 | rbuffer = new[CONFIG_REGS]; 302 | 303 | //read register(s) contents 304 | for (r=0; r < CONFIG_REGS; r++) 305 | begin 306 | rbuffer[r] = new[1]; 307 | ahb_mst_bfm.read (r*HDATA_SIZE/8, 308 | rbuffer[r], 309 | HDATA_SIZE == 32 ? HSIZE_WORD : HSIZE_DWORD, 310 | HBURST_SINGLE); 311 | end 312 | ahb_mst_bfm.idle(); //Idle the AHB bus 313 | wait fork; //Wait for all transactions to finish 314 | 315 | //copy contents into 'config_reg_contents' 316 | for (r=0; r= 0; 403 | hsize--) 404 | begin 405 | error = 0; 406 | 407 | case (hsize) 408 | HSIZE_DWORD: begin 409 | hburst = HBURST_SINGLE; 410 | tsize = 64; 411 | $write(" Testing dword (64bit) accesses ... "); 412 | end 413 | HSIZE_WORD : begin 414 | hburst = HBURST_SINGLE; 415 | tsize = 32; 416 | $write(" Testing word (32bit) accesses ... "); 417 | end 418 | HSIZE_HWORD: begin 419 | hburst = (HDATA_SIZE == 64) ? HBURST_INCR4 : HBURST_SINGLE; 420 | tsize = 16; 421 | $write(" Testing hword (16bit) accesses ... "); 422 | end 423 | HSIZE_BYTE : begin 424 | hburst = (HDATA_SIZE == 64) ? HBURST_INCR8 : HBURST_INCR4; 425 | tsize = 8; 426 | $write(" Testing byte burst (8bit) accesses ... "); 427 | end 428 | endcase 429 | 430 | 431 | //Write test values 432 | for (r=0; r IRQ[%0t]...", s, t); 651 | if (irq == 1 << t) 652 | begin 653 | $display ("PASSED"); 654 | end 655 | else 656 | begin 657 | $display ("FAILED"); 658 | $error ("Expected IRQ=%0x, received %h @%0t", 1 << t, irq, $time); 659 | errors++; 660 | end 661 | 662 | //check if ID is correct >> claims interrupt << 663 | ahb_mst_bfm.read ( (id_base_address + t) * HDATA_SIZE/8, 664 | rbuffer, 665 | HDATA_SIZE == 32 ? HSIZE_WORD : HSIZE_DWORD, 666 | HBURST_SINGLE); 667 | ahb_mst_bfm.idle(); //Idle the AHB bus 668 | wait fork; //Wait for all transactions to finish 669 | 670 | $write (" Checking ID/Claim Interrupt ..."); 671 | if (rbuffer[0] == s+1) 672 | begin 673 | $display ("PASSED"); 674 | end 675 | else 676 | begin 677 | $display ("FAILED"); 678 | $error ("Expected ID=%0d, received %h @%0t", s+1, rbuffer[0], $time); 679 | errors++; 680 | end 681 | 682 | //clear source 683 | src[s] = 1'b0; 684 | 685 | repeat (3) @(posedge HCLK); 686 | $write (" Checking IRQ cleared ..."); 687 | if (irq == 0) 688 | begin 689 | $display ("PASSED"); 690 | end 691 | else 692 | begin 693 | $display ("FAILED"); 694 | $error ("Expected IRQ=0, received %d @%0t", irq, $time); 695 | errors++; 696 | end 697 | 698 | //complete interrupt -- dummy write to ID 699 | $display (" Sending Interrupt Complete"); 700 | ahb_mst_bfm.write ( (id_base_address +t) * HDATA_SIZE/8, 701 | wbuffer, 702 | HDATA_SIZE == 64 ? HSIZE_DWORD : HSIZE_WORD, 703 | HBURST_SINGLE); 704 | 705 | $write (" Checking IRQ cleared ..."); 706 | if (irq == 0) 707 | begin 708 | $display ("PASSED"); 709 | end 710 | else 711 | begin 712 | $display ("FAILED"); 713 | $error ("Expected IRQ=0, received %d @%0t", irq, $time); 714 | errors++; 715 | end 716 | 717 | //disable interrupt 718 | wbuffer[0] = 0; 719 | ahb_mst_bfm.write ( (ie_base_address + (t * EDGE_LEVEL_REGS) + (s / HDATA_SIZE)) * HDATA_SIZE/8, 720 | wbuffer, 721 | HDATA_SIZE == 64 ? HSIZE_DWORD : HSIZE_WORD, 722 | HBURST_SINGLE); 723 | 724 | end //next s/t 725 | 726 | ahb_mst_bfm.idle(); //Idle the AHB bus 727 | wait fork; //Wait for all transactions to finish 728 | endtask : test_single 729 | 730 | endmodule : test 731 | -------------------------------------------------------------------------------- /rtl/verilog/core/plic_dynamic_registers.sv: -------------------------------------------------------------------------------- 1 | ///////////////////////////////////////////////////////////////////// 2 | // ,------. ,--. ,--. // 3 | // | .--. ' ,---. ,--,--. | | ,---. ,---. `--' ,---. // 4 | // | '--'.'| .-. |' ,-. | | | | .-. | .-. |,--.| .--' // 5 | // | |\ \ ' '-' '\ '-' | | '--.' '-' ' '-' || |\ `--. // 6 | // `--' '--' `---' `--`--' `-----' `---' `- /`--' `---' // 7 | // `---' // 8 | // RISC-V Platform-Level Interrupt Controller // 9 | // // 10 | ///////////////////////////////////////////////////////////////////// 11 | // // 12 | // Copyright (C) 2017 ROA Logic BV // 13 | // www.roalogic.com // 14 | // // 15 | // This source file may be used and distributed without // 16 | // restriction provided that this copyright statement is not // 17 | // removed from the file and that any derivative work contains // 18 | // the original copyright notice and the associated disclaimer. // 19 | // // 20 | // THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY // 21 | // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED // 22 | // TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS // 23 | // FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR OR // 24 | // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, // 25 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT // 26 | // NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; // 27 | // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) // 28 | // HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // 29 | // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR // 30 | // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS // 31 | // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // 32 | // // 33 | ///////////////////////////////////////////////////////////////////// 34 | 35 | // +FHDR - Semiconductor Reuse Standard File Header Section ------- 36 | // FILE NAME : plic_dynamic_registers.sv 37 | // DEPARTMENT : 38 | // AUTHOR : rherveille 39 | // AUTHOR'S EMAIL : 40 | // ------------------------------------------------------------------ 41 | // RELEASE HISTORY 42 | // VERSION DATE AUTHOR DESCRIPTION 43 | // 1.0 2017-07-18 rherveille initial release 44 | // 2017-09-13 rherveille Added 'claim' and 'complete' 45 | // ------------------------------------------------------------------ 46 | // KEYWORDS : RISC-V PLATFORM LEVEL INTERRUPT CONTROLLER - PLIC 47 | // ------------------------------------------------------------------ 48 | // PURPOSE : Dynamic Register generation for PLIC 49 | // ------------------------------------------------------------------ 50 | // PARAMETERS 51 | // PARAM NAME RANGE DESCRIPTION DEFAULT UNITS 52 | // ADDR_SIZE [32,64] read/write address width 32 53 | // DATA_SIZE [32,64] read/write data width 32 54 | // SOURCES 1+ No. of interupt sources 8 55 | // TARGETS 1+ No. of interrupt targets 1 56 | // PRIORITIES 1+ No. of priority levels 8 57 | // MAX_PENDING_COUNT 0+ Max. pending interrupts 4 58 | // HAS_THRESHOLD [0,1] Is 'threshold' impl.? 1 59 | // HAS_CONFIG_REG [0,1] Is 'config' implemented? 1 60 | // ------------------------------------------------------------------ 61 | // REUSE ISSUES 62 | // Reset Strategy : external asynchronous active low; rst_n 63 | // Clock Domains : 1, clk, rising edge 64 | // Critical Timing : na 65 | // Test Features : na 66 | // Asynchronous I/F : no 67 | // Scan Methodology : na 68 | // Instantiations : none 69 | // Synthesizable (y/n) : Yes 70 | // Other : 71 | // -FHDR------------------------------------------------------------- 72 | 73 | module plic_dynamic_registers #( 74 | //Bus Interface Parameters 75 | parameter ADDR_SIZE = 32, 76 | parameter DATA_SIZE = 32, 77 | 78 | //PLIC Parameters 79 | parameter SOURCES = 8, //Number of interrupt sources 80 | parameter TARGETS = 1, //Number of interrupt targets 81 | parameter PRIORITIES = 8, //Number of Priority levels 82 | parameter MAX_PENDING_COUNT = 4, // 83 | parameter HAS_THRESHOLD = 1, //Is 'threshold' implemented? 84 | parameter HAS_CONFIG_REG = 1, //Is 'config' implemented? 85 | 86 | //These should be 'localparam', but that's not supported by all tools yet 87 | parameter BE_SIZE = (DATA_SIZE+7)/8, 88 | parameter SOURCES_BITS = $clog2(SOURCES+1), //0=reserved 89 | parameter PRIORITY_BITS = $clog2(PRIORITIES) 90 | ) 91 | ( 92 | input rst_n, //Active low asynchronous reset 93 | clk, //System clock 94 | 95 | input we, //write enable 96 | re, //read enable 97 | input [BE_SIZE -1:0] be, //byte enable (writes only) 98 | input [ADDR_SIZE -1:0] waddr, //write address 99 | raddr, //read address 100 | input [DATA_SIZE -1:0] wdata, //write data 101 | output reg [DATA_SIZE -1:0] rdata, //read data 102 | 103 | output [SOURCES -1:0] el, //Edge/Level sensitive for each source 104 | input [SOURCES -1:0] ip, //Interrupt Pending for each source 105 | 106 | output [SOURCES -1:0] ie[TARGETS], //Interrupt enable per source, for each target 107 | output reg [PRIORITY_BITS-1:0] p [SOURCES], //Priority for each source 108 | output reg [PRIORITY_BITS-1:0] th[TARGETS], //Priority Threshold for each target 109 | 110 | input [SOURCES_BITS -1:0] id[TARGETS], //Interrupt ID for each target 111 | output reg [TARGETS -1:0] claim, //Interrupt Claim 112 | output reg [TARGETS -1:0] complete //Interrupt Complete 113 | ); 114 | 115 | ////////////////////////////////////////////////////////////////// 116 | // 117 | // Constants 118 | // 119 | localparam DATA_BYTES = BE_SIZE; //number of bytes in DATA 120 | 121 | 122 | 123 | /** Address map 124 | * Configuration 125 | * GateWay control 126 | * [SOURCES -1:0] el 127 | * [PRIORITY_BITS-1:0] priority [SOURCES] 128 | * 129 | * PLIC-Core 130 | * [SOURCES -1:0] ie [TARGETS] 131 | * [PRIORITY_BITS-1:0] threshold [TARGETS] 132 | * [SOURCES_BITS -1:0] ID [TARGETS 133 | */ 134 | 135 | /** Calculate Register amount/offset 136 | * Each register is DATA_SIZE wide 137 | */ 138 | typedef enum {CONFIG, EL, IE, PRIORITY, THRESHOLD, ID} register_types; 139 | 140 | //Configuration Bits 141 | localparam MAX_SOURCES_BITS = 16; 142 | localparam MAX_TARGETS_BITS = 16; 143 | localparam MAX_PRIORITY_BITS = MAX_SOURCES_BITS; 144 | localparam HAS_THRESHOLD_BITS = 1; 145 | 146 | //How many CONFIG registers are there (only 1) 147 | localparam CONFIG_REGS = HAS_CONFIG_REG == 0 ? 0 : (MAX_SOURCES_BITS + MAX_TARGETS_BITS + MAX_PRIORITY_BITS + HAS_THRESHOLD_BITS + DATA_SIZE -1) / DATA_SIZE; 148 | 149 | //How many Edge/Level registers are there? 150 | localparam EL_REGS = (SOURCES + DATA_SIZE -1) / DATA_SIZE; 151 | 152 | //How many IE registers are there? 153 | localparam IE_REGS = EL_REGS * TARGETS; 154 | 155 | //How many nibbles are there in 'PRIORITY_BITS' ? 156 | //Each PRIORITY starts at a new nibble boundary 157 | localparam PRIORITY_NIBBLES = (PRIORITY_BITS +3 -1) / 4; 158 | 159 | //How many PRIORITY fields fit in 1 register? 160 | localparam PRIORITY_FIELDS_PER_REG = DATA_SIZE / (PRIORITY_NIBBLES*4); 161 | 162 | //How many Priority registers are there? 163 | localparam PRIORITY_REGS = (SOURCES + PRIORITY_FIELDS_PER_REG -1) / PRIORITY_FIELDS_PER_REG; 164 | 165 | //How many Threshold registers are there? 166 | // localparam THRESHOLD_REGS = HAS_THRESHOLD == 0 ? 0 : (TARGETS + PRIORITY_FIELDS_PER_REG -1) / PRIORITY_FIELDS_PER_REG; 167 | localparam THRESHOLD_REGS = HAS_THRESHOLD == 0 ? 0 : TARGETS; 168 | 169 | //How many ID register are there? 170 | localparam ID_REGS = TARGETS; 171 | 172 | //How many registers in total? 173 | localparam TOTAL_REGS = CONFIG_REGS + EL_REGS + IE_REGS + PRIORITY_REGS + THRESHOLD_REGS + ID_REGS; 174 | 175 | 176 | ////////////////////////////////////////////////////////////////// 177 | // 178 | // Variables 179 | // 180 | 181 | //Read Variables 182 | int read_register, 183 | read_register_idx; 184 | int write_register; 185 | 186 | //Registers 187 | logic [DATA_SIZE -1:0] registers [TOTAL_REGS]; 188 | 189 | 190 | ////////////////////////////////////////////////////////////////// 191 | // 192 | // Functions 193 | // 194 | function logic [DATA_SIZE-1:0] gen_wval; 195 | //Returns the new value for a register 196 | // if be[n] == '1' then gen_val[byte_n] = new_val[byte_n] 197 | // else gen_val[byte_n] = old_val[byte_n] 198 | input [DATA_SIZE-1:0] old_val, 199 | new_val; 200 | input [BE_SIZE -1:0] be; 201 | 202 | for (int n=0; n < BE_SIZE; n++) 203 | gen_wval[n*8 +: 8] = be[n] ? new_val[n*8 +: 8] : old_val[n*8 +: 8]; 204 | endfunction : gen_wval 205 | 206 | 207 | /** Register Access calculation 208 | * Registers are created dynamically, access is determined by the 209 | * parameter settings 210 | */ 211 | function automatic register_types register_function; 212 | //return register-type for specified register 213 | input int r; 214 | 215 | int idx; 216 | idx = r; 217 | 218 | //1. Configuration Register 219 | if (idx < CONFIG_REGS ) return CONFIG; 220 | idx -= CONFIG_REGS; 221 | 222 | //2. Gateway control registers 223 | // Edge/Level 224 | if (idx < EL_REGS ) return EL; 225 | idx -= EL_REGS; 226 | 227 | //3. PLIC Core fabric registers 228 | if (idx < PRIORITY_REGS) return PRIORITY; 229 | idx -= PRIORITY_REGS; 230 | if (idx < IE_REGS ) return IE; 231 | idx -= IE_REGS; 232 | 233 | //4. Target registers 234 | if (idx < THRESHOLD_REGS) return THRESHOLD; 235 | return ID; 236 | endfunction : register_function 237 | 238 | 239 | function automatic int register_idx; 240 | //return offset in register-type 241 | input int r; 242 | 243 | int idx; 244 | idx = r; 245 | 246 | //1. Configuration registers 247 | if (idx < CONFIG_REGS ) return idx; 248 | idx -= CONFIG_REGS; 249 | 250 | //2. first Gateway control registers 251 | // Edge/Level 252 | // Interrupt Pending/Acknowledge 253 | if (idx < EL_REGS ) return idx; 254 | idx -= EL_REGS; 255 | 256 | //3. PLIC Core fabric registers 257 | if (idx < PRIORITY_REGS) return idx; 258 | idx -= PRIORITY_REGS; 259 | if (idx < IE_REGS ) return idx; 260 | idx -= IE_REGS; 261 | 262 | //4. Target registers 263 | if (idx < THRESHOLD_REGS) return idx; 264 | idx -= THRESHOLD_REGS; 265 | return idx; 266 | endfunction : register_idx 267 | 268 | 269 | function automatic int address2register; 270 | //Translate 'address' into register number 271 | input [ADDR_SIZE-1:0] address; 272 | 273 | return address / DATA_BYTES; 274 | endfunction : address2register 275 | 276 | 277 | function automatic [TARGETS-1:0] gen_claim; 278 | //generate internal 'claim' signal 279 | input re; 280 | input [ADDR_SIZE-1:0] address; 281 | 282 | int r, idx; 283 | 284 | r = address2register(address); 285 | idx = register_idx(r); 286 | 287 | if (register_function(r) == ID && re) 288 | return (1 << idx); 289 | else 290 | return {TARGETS{1'b0}}; 291 | endfunction : gen_claim 292 | 293 | 294 | function automatic [SOURCES-1:0] gen_complete; 295 | //generate internal 'complete' signal 296 | input we; 297 | input [ADDR_SIZE-1:0] address; 298 | 299 | int r, idx; 300 | 301 | r = address2register(address); 302 | idx = register_idx(r); 303 | 304 | if (register_function(r) == ID && we) 305 | return (1 << idx); 306 | else 307 | return {TARGETS{1'b0}}; 308 | endfunction : gen_complete 309 | 310 | 311 | function automatic [DATA_SIZE-1:0] encode_config; 312 | //encode 'rdata' when reading from CONFIG 313 | input int r; //which register 314 | 315 | logic [MAX_SOURCES_BITS -1:0] sources_bits; 316 | logic [MAX_TARGETS_BITS -1:0] targets_bits; 317 | logic [MAX_PRIORITY_BITS-1:0] priority_bits; 318 | logic has_th_bit; 319 | 320 | sources_bits = SOURCES; 321 | targets_bits = TARGETS; 322 | priority_bits = PRIORITIES; 323 | has_th_bit = HAS_THRESHOLD ? 1'b1 : 1'b0; 324 | 325 | if (CONFIG_REGS == 1) 326 | return {15'h0,has_th_bit,priority_bits,targets_bits,sources_bits}; 327 | else 328 | if (r == 0) 329 | return {targets_bits,sources_bits}; 330 | else 331 | return {15'h0,has_th_bit,priority_bits}; 332 | endfunction : encode_config 333 | 334 | 335 | function automatic [DATA_SIZE-1:0] encode_p; 336 | //encode 'rdata' when reading from PRIORITY 337 | input int r; //which register 338 | 339 | //clear all bits 340 | encode_p = {DATA_SIZE{1'b0}}; 341 | 342 | //move PRIORITY fields into bit-positions 343 | if ((r+1)*PRIORITY_FIELDS_PER_REG <= SOURCES) 344 | for (int n=0; n < PRIORITY_FIELDS_PER_REG; n++) 345 | encode_p |= p[r*PRIORITY_FIELDS_PER_REG +n] << (n * PRIORITY_NIBBLES*4); 346 | else 347 | for (int n=0; n < SOURCES % PRIORITY_FIELDS_PER_REG; n++) 348 | encode_p |= p[r*PRIORITY_FIELDS_PER_REG +n] << (n * PRIORITY_NIBBLES*4); 349 | endfunction : encode_p 350 | 351 | 352 | function automatic [PRIORITY_BITS-1:0] decode_p; 353 | //extract/decode 'priority' fields from PRIORITY-register 354 | input int r; //which register 355 | input int s; //which field (source) 356 | 357 | logic [DATA_SIZE-1:0] tmp; 358 | int field; 359 | 360 | field = s % PRIORITY_FIELDS_PER_REG; 361 | tmp = registers[r]; 362 | tmp = tmp >> (field * PRIORITY_NIBBLES * 4); 363 | return tmp[PRIORITY_BITS-1:0]; 364 | endfunction : decode_p 365 | 366 | 367 | function automatic [DATA_SIZE-1:0] encode_th; 368 | //encode 'rdata' when reading from THRESHOLD 369 | input int r; //which register 370 | 371 | //clear all bits 372 | encode_th = {DATA_SIZE{1'b0}}; 373 | 374 | //move THRESHOLD fields into bit-positions 375 | if ((r+1)*PRIORITY_FIELDS_PER_REG <= TARGETS) 376 | for (int n=0; n < PRIORITY_FIELDS_PER_REG; n++) 377 | encode_th |= p[r*PRIORITY_FIELDS_PER_REG +n] << (n * PRIORITY_NIBBLES*4); 378 | else 379 | for (int n=0; n < TARGETS % PRIORITY_FIELDS_PER_REG; n++) 380 | encode_th |= p[r*PRIORITY_FIELDS_PER_REG +n] << (n * PRIORITY_NIBBLES*4); 381 | endfunction : encode_th 382 | 383 | 384 | /** Display Register layout/map 385 | */ 386 | //synopsys translate_off 387 | function string register_function_name; 388 | //returns the 'string' name associated with a register type 389 | input register_types function_number; 390 | 391 | string name_array[register_types]; 392 | name_array[CONFIG ] = "Configuration"; 393 | name_array[EL ] = "Edge/Level"; 394 | name_array[IE ] = "Interrupt Enable"; 395 | name_array[PRIORITY ] = "Interrupt Priority"; 396 | name_array[THRESHOLD] = "Priority Threshold"; 397 | name_array[ID ] = "ID"; 398 | 399 | return name_array[function_number]; 400 | endfunction : register_function_name 401 | 402 | 403 | //Display IP configuration; register map 404 | task display_configuration; 405 | $display ("------------------------------------------------------------"); 406 | $display (" ,------. ,--. ,--. "); 407 | $display (" | .--. ' ,---. ,--,--. | | ,---. ,---. `--' ,---. "); 408 | $display (" | '--'.'| .-. |' ,-. | | | | .-. | .-. |,--.| .--' "); 409 | $display (" | |\\ \\ ' '-' '\\ '-' | | '--.' '-' ' '-' || |\\ `--. "); 410 | $display (" `--' '--' `---' `--`--' `-----' `---' `- /`--' `---' "); 411 | $display (" `---' "); 412 | $display (" RISC-V Platform Level Interrupt Controller "); 413 | 414 | $display ("- Configuration Report -------------------------------------"); 415 | $display (" Sources | Targets | Priority-lvl | Threshold? | Event-Cnt "); 416 | $write (" %4d |", SOURCES); 417 | $write (" %3d |", TARGETS); 418 | $write (" %5d |", PRIORITIES); 419 | $write (" %5s |", HAS_THRESHOLD ? "YES" : "NO"); 420 | $display(" %3d ", MAX_PENDING_COUNT); 421 | 422 | $display ("- Register Map ---------------------------------------------"); 423 | display_register_map(); 424 | 425 | $display ("- End Configuration Report ---------------------------------"); 426 | endtask : display_configuration 427 | 428 | task display_register_map; 429 | int address; 430 | 431 | $display (" Address Function Mapping"); 432 | for (int r=0; r < TOTAL_REGS; r++) 433 | begin 434 | //display address + function 435 | address = r * (DATA_SIZE / 8); 436 | $write (" 0x%04x %-23s", address, register_function_name(register_function(r))); 437 | 438 | //display register mapping 439 | case ( register_function(r) ) 440 | CONFIG : display_config_map ( register_idx(r) ); 441 | EL : display_el_map ( register_idx(r) ); 442 | PRIORITY : display_priority_map ( register_idx(r) ); 443 | IE : display_ie_map ( register_idx(r) ); 444 | THRESHOLD: display_threshold_map( register_idx(r) ); 445 | ID : display_id_map ( register_idx(r) ); 446 | default : $display(""); 447 | endcase 448 | end 449 | endtask : display_register_map 450 | 451 | task display_config_map; 452 | input int r; 453 | 454 | if (CONFIG_REGS == 1) 455 | $display ("15'h0,TH,PRIORITES,TARGETS,SOURCES"); 456 | else 457 | if (r == 0) 458 | $display ("TARGETS,SOURCES"); 459 | else 460 | $display ("15'h0,TH,PRIORITIES"); 461 | endtask : display_config_map 462 | 463 | task display_el_map; 464 | input int r; 465 | 466 | if ((r+1)*DATA_SIZE <= SOURCES) 467 | $display ("EL[%0d:%0d]", (r+1)*DATA_SIZE -1, r*DATA_SIZE); 468 | else 469 | $display ("%0d'h0, EL[%0d:%0d]", (r+1)*DATA_SIZE-SOURCES, SOURCES-1, r*DATA_SIZE); 470 | endtask : display_el_map 471 | 472 | task display_ie_map; 473 | input int ri; 474 | 475 | int target, r; 476 | 477 | target = ri / EL_REGS; 478 | r = ri % EL_REGS; 479 | 480 | if ((r+1)*DATA_SIZE <= SOURCES) 481 | $display ("IE[%0d][%0d:%0d]", target, (r+1)*DATA_SIZE -1, r*DATA_SIZE); 482 | else 483 | $display ("%0d'h0, IE[%0d][%0d:%0d]", (r+1)*DATA_SIZE-SOURCES, target, SOURCES-1, r*DATA_SIZE); 484 | endtask : display_ie_map 485 | 486 | task display_priority_map; 487 | input int r; 488 | 489 | if ((r+1)*PRIORITY_FIELDS_PER_REG <= SOURCES) 490 | begin 491 | for (int s=(r+1)*PRIORITY_FIELDS_PER_REG -1; s >= r*PRIORITY_FIELDS_PER_REG; s--) 492 | begin 493 | if (PRIORITY_BITS % 4) $write("%0d'b0,", 4- (PRIORITY_BITS % 4)); 494 | $write ("P[%0d][%0d:%0d]", s, PRIORITY_BITS -1, 0); 495 | if (s != r*PRIORITY_FIELDS_PER_REG) $write(","); 496 | end 497 | end 498 | else 499 | begin 500 | $write ("%0d'h0,", DATA_SIZE - (SOURCES-r*PRIORITY_FIELDS_PER_REG) * PRIORITY_NIBBLES*4); 501 | 502 | for (int s=SOURCES-1; s >= r*PRIORITY_FIELDS_PER_REG; s--) 503 | begin 504 | if (PRIORITY_BITS % 4) $write("%0d'b0,", 4- (PRIORITY_BITS % 4)); 505 | $write ("P[%0d][%0d:%0d]", s, PRIORITY_BITS -1, 0); 506 | if (s != r*PRIORITY_FIELDS_PER_REG) $write(","); 507 | end 508 | end 509 | 510 | $display(""); 511 | endtask : display_priority_map 512 | 513 | /* 514 | task display_threshold_map; 515 | input int r; 516 | 517 | if ((r+1)*PRIORITY_FIELDS_PER_REG <= TARGETS) 518 | begin 519 | for (int t=(r+1)*PRIORITY_FIELDS_PER_REG -1; t >= r*PRIORITY_FIELDS_PER_REG; t--) 520 | begin 521 | if (PRIORITY_BITS % 4) $write("%0d'b0,", 4- (PRIORITY_BITS % 4)); 522 | $write ("Th[%0d][%0d:%0d]", t, PRIORITY_BITS -1, 0); 523 | if (t != r*PRIORITY_FIELDS_PER_REG) $write(","); 524 | end 525 | end 526 | else 527 | begin 528 | $write ("%0d'h0,", DATA_SIZE - (TARGETS-r*PRIORITY_FIELDS_PER_REG) * PRIORITY_NIBBLES*4); 529 | 530 | for (int t=TARGETS-1; t >= r*PRIORITY_FIELDS_PER_REG; t--) 531 | begin 532 | if (PRIORITY_BITS % 4) $write("%0d'b0,", 4- (PRIORITY_BITS % 4)); 533 | $write ("Th[%0d][%0d:%0d]", t, PRIORITY_BITS -1, 0); 534 | if (t != r*PRIORITY_FIELDS_PER_REG) $write(","); 535 | end 536 | end 537 | 538 | $display(""); 539 | endtask : display_threshold_map 540 | */ 541 | 542 | task display_threshold_map; 543 | input int r; 544 | 545 | $display ("%0d'h0, Th[%0d][%0d:%0d]", DATA_SIZE-PRIORITY_BITS, r, PRIORITY_BITS-1, 0); 546 | endtask : display_threshold_map 547 | 548 | 549 | task display_id_map; 550 | input int r; 551 | 552 | $display ("%0d'h0, ID[%0d][%0d:%0d]", DATA_SIZE-SOURCES_BITS, r, SOURCES_BITS-1, 0); 553 | endtask : display_id_map 554 | 555 | //synopsys translate_on 556 | 557 | 558 | ////////////////////////////////////////////////////////////////// 559 | // 560 | // Module Body 561 | // 562 | //synopsys translate_off 563 | initial display_configuration(); 564 | //synopsys translate_on 565 | 566 | 567 | /** Write Registers 568 | * 569 | * This core has a dynamic array of registers, depending on the 570 | * parameter settings 571 | * Writing to the ID register generates a strobe 572 | */ 573 | assign write_register = address2register(waddr); 574 | 575 | always @(posedge clk,negedge rst_n) 576 | if (!rst_n) 577 | for (int n=0; n < TOTAL_REGS; n++) 578 | registers[n] <= 'h0; 579 | else if (we) 580 | case (register_function(write_register)) 581 | ID : ; //A write to ID generates a strobe signal 582 | default: registers[write_register] <= gen_wval( registers[write_register], wdata, be); 583 | endcase 584 | 585 | 586 | /** Claim / Complete 587 | * Special cases for Claim / Complete 588 | * A read generates a claim strobe 589 | * A write doesn't access the register, but generates a complete strobe instead 590 | */ 591 | always @(posedge clk, negedge rst_n) 592 | if (!rst_n) claim <= 0; 593 | else claim <= gen_claim(re, raddr); 594 | 595 | always @(posedge clk, negedge rst_n) 596 | if (!rst_n) complete <= 0; 597 | else complete <= gen_complete(we, waddr); 598 | 599 | 600 | /** Decode registers 601 | */ 602 | generate 603 | genvar r, t, s; 604 | 605 | for (r=0; r < TOTAL_REGS; r++) 606 | begin : decode_registers 607 | case ( register_function(r) ) 608 | //Decode EL register(s) 609 | // There are SOURCES EL-bits, spread out over 610 | // DATA_SIZE wide registers 611 | EL : begin 612 | if ( (register_idx(r)+1) * DATA_SIZE <= SOURCES ) 613 | assign el[register_idx(r) * DATA_SIZE +: DATA_SIZE] = registers[r]; 614 | else 615 | assign el[SOURCES-1:register_idx(r) * DATA_SIZE] = registers[r]; 616 | end 617 | 618 | //Decode PRIORITY register(s) 619 | // There are SOURCES priority-fields, each PRIORITY_BITS 620 | // wide, spread out over DATA_SIZE wide registers, 621 | // with each field starting at a nibble boundary 622 | // Need to use always_comb, because we're not assigning a fixed value 623 | PRIORITY : begin 624 | if ( (register_idx(r)+1) * PRIORITY_FIELDS_PER_REG <= SOURCES ) 625 | for (s = register_idx(r) * PRIORITY_FIELDS_PER_REG; 626 | s < (register_idx(r)+1) * PRIORITY_FIELDS_PER_REG; 627 | s++) 628 | begin : decode_p0 629 | always_comb p[s] = decode_p(r,s); 630 | end 631 | else 632 | for (s = register_idx(r) * PRIORITY_FIELDS_PER_REG; 633 | s < SOURCES; 634 | s++) 635 | begin : decode_p1 636 | always_comb p[s] = decode_p(r,s); 637 | end 638 | end 639 | 640 | //Decode IE register(s) 641 | // For each TARGET there's SOURCES IE-fields 642 | // Layout is the same as for the EL-registers, with each 643 | // TARGET starting at a new register 644 | IE : begin 645 | if ( ((register_idx(r) % EL_REGS)+1) * DATA_SIZE <= SOURCES ) 646 | assign ie[register_idx(r) / EL_REGS][(register_idx(r) % EL_REGS) * DATA_SIZE +: DATA_SIZE] = registers[r]; 647 | else 648 | assign ie[register_idx(r) / EL_REGS][SOURCES-1 : (register_idx(r) % EL_REGS) * DATA_SIZE] = registers[r]; 649 | end 650 | 651 | /* 652 | //Decode THRESHOLD register(s) 653 | // There are TARGETS threshold-fields, each PRIORITY_BITS 654 | // wide, spread out over DATA_SIZE wide registers, 655 | // with each field starting at a nibble boundary 656 | THRESHOLD: if (HAS_THRESHOLD) 657 | begin 658 | if ( (register_idx(r)+1) * PRIORITY_FIELDS_PER_REG <= TARGETS ) 659 | for (t = register_idx(r) * PRIORITY_FIELDS_PER_REG; 660 | t < (register_idx(r)+1) * PRIORITY_FIELDS_PER_REG; 661 | t++) 662 | begin : decode_th0 663 | always_comb 664 | begin 665 | logic [DATA_SIZE-1:0] tmp; //local variable 666 | tmp = registers[r]; 667 | tmp = tmp >> (t * PRIORITY_NIBBLES); 668 | th[t] = tmp[PRIORITY_BITS-1:0]; 669 | end 670 | end 671 | else 672 | for (t = register_idx(r) * PRIORITY_FIELDS_PER_REG; 673 | t < TARGETS; 674 | t++) 675 | begin : decode_th1 676 | always_comb 677 | begin 678 | logic [DATA_SIZE-1:0] tmp; //local variable 679 | tmp = registers[r]; 680 | tmp = tmp >> (t * PRIORITY_NIBBLES); 681 | th[t] = tmp[PRIORITY_BITS-1:0]; 682 | end 683 | end 684 | end 685 | */ 686 | 687 | THRESHOLD: if (HAS_THRESHOLD) 688 | begin 689 | assign th[register_idx(r)] = registers[r][PRIORITY_BITS-1:0]; 690 | end 691 | endcase 692 | end 693 | endgenerate 694 | 695 | 696 | /** Read Registers 697 | */ 698 | assign read_register = address2register(raddr); 699 | assign read_register_idx = register_idx(read_register); 700 | 701 | always @(posedge clk, negedge rst_n) 702 | if (!rst_n) rdata <= {$bits(rdata){1'b0}}; 703 | else if (re) 704 | case ( register_function(read_register) ) 705 | CONFIG : if (HAS_CONFIG_REG) rdata <= encode_config(read_register_idx); 706 | EL : rdata <= el >> (read_register_idx * DATA_SIZE); 707 | PRIORITY : rdata <= encode_p(read_register_idx); 708 | IE : rdata <= ie[read_register_idx / EL_REGS] >> ((read_register_idx % EL_REGS) * DATA_SIZE); 709 | // THRESHOLD: if (HAS_THRESHOLD) rdata <= encode_th(read_register_idx); 710 | THRESHOLD: if (HAS_THRESHOLD) rdata <= th[read_register_idx]; 711 | ID : rdata <= id[read_register_idx]; 712 | endcase 713 | 714 | endmodule : plic_dynamic_registers 715 | 716 | --------------------------------------------------------------------------------