-
Notifications
You must be signed in to change notification settings - Fork 4
Interrupts Module Briefs and PLIC #41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
a9cf7e7
Add files via upload
gavinwiese 4672c35
Update plic.sv
gavinwiese e3dcd4e
Update plic.sv 2
gavinwiese 0659bba
Update clint.sv
gavinwiese 443e827
Update plic.sv
gavinwiese 3344a46
Update plic_module_brief_v0.2.md
gavinwiese 5e7936b
Update clint_module_brief_v0.2.md
gavinwiese c3603cd
Add negedge reset in clint module
Meowcaroni File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,68 @@ | ||
| # CLINT - Module Brief (v0.3) | ||
|
|
||
| **Owner:** Gavin Wiese | ||
| **RTL:** rtl/irq/clint.sv | ||
|
|
||
| ### Purpose & Role | ||
| The Core Local Interruptor (CLINT) is placed near the CPU core, as interrupts are sent directly to the core via memory. The CLINT provides two types of interrupts: **timer-based** (`timer_irq_o`) and **software-based** (`soft_irq_o`). It ensures that events from the timer or software are recognized promptly by the CPU. | ||
|
|
||
| ### Parameters | ||
|
|
||
| - Timer Width: 64 bits (`mtime` and `mtimecmp` registers) | ||
| - Software interrupt width: 1 bit (`msip`) | ||
| - Software interrupt output width: 1 bit (`soft_irq_o`) | ||
| - Timer interrupt output width: 1 bit (`timer_irq_o`) | ||
|
|
||
| ### Interfaces (Ports) | ||
|
|
||
| | **Signal** | **Dir** | **Width** | **Description** | | ||
| |----------------|---------|-----------|----------------------------------| | ||
| | mtime_o | out | 64 | Current timer value | | ||
| | timer_irq_o | out | 1 | Timer interrupt output | | ||
| | soft_irq_o | out | 1 | Software interrupt output | | ||
| | clk_i | in | 1 | System clock | | ||
| | rst_ni | in | 1 | Active-low reset | | ||
| | msip_we | in | 1 | Write enable for `msip` register | | ||
| | msip_wdata | in | 1 | Data to write to `msip` | | ||
| | mtimecmp_we | in | 1 | Write enable for `mtimecmp` register | | ||
| | mtimecmp_wdata | in | 64 | Data to write to `mtimecmp` | | ||
|
|
||
| ### Reset/Init | ||
|
|
||
| An active-low reset (`rst_ni`) is used for the CLINT. When reset is asserted (`rst_ni = 0`), all internal registers—`mtime`, `mtimecmp`, and `msip`—are cleared to 0, and output signals (`mtime_o`, `timer_irq_o`, `soft_irq_o`) reflect these reset values. All values are reset synchronously with the system clock. Once reset is deasserted (`rst_ni = 1`), the `mtime` counter begins incrementing every clock cycle, and the interrupt outputs (`timer_irq_o` and `soft_irq_o`) update according to the current register states. | ||
|
|
||
| ### Behavior and Timing | ||
|
|
||
| `mtime` increments by one on every rising edge of the system clock. When `mtime` becomes greater than or equal to `mtimecmp`, the timer interrupt output `timer_irq_o` is asserted and remains asserted until a new, greater `mtimecmp` value is written. The software interrupt output `soft_irq_o` directly reflects the state of the `msip` register. All operations are synchronous with the system clock, and outputs update on the cycle following their trigger conditions. | ||
|
|
||
| ### Programming Model | ||
|
|
||
| The CLINT exposes three memory-mapped registers: | ||
|
|
||
| - **`msip`** – Software interrupt pending. Writing a `1` to bit 0 asserts `soft_irq_o` until cleared. | ||
| - **`mtimecmp`** – Timer compare register. When the internal 64-bit counter `mtime` reaches or exceeds this value, `timer_irq_o` is asserted until a new, greater value is written. | ||
| - **`mtime`** – A 64-bit free-running counter that increments at the system clock rate. Software can read this register for timing purposes. | ||
|
|
||
| All registers are accessible via write-enable and data inputs (`*_we`, `*_wdata`). | ||
|
|
||
| ### Errors/IRQs | ||
|
|
||
| | **IRQ** | **Source** | **How it's triggered** | **How it's cleared** | | ||
| |----------------|------------|--------------------------------|------------------------------------------------| | ||
| | timer_irq_o | mtimecmp | Asserted when mtime >= mtimecmp | Cleared when a new, greater mtimecmp is written | | ||
| | soft_irq_o | msip | Reflects the value of the msip register | Cleared by writing 0 to msip | | ||
|
|
||
| The CLINT does not generate additional error signals. | ||
|
|
||
| ### Performance Targets | ||
|
|
||
| - `mtime` increments every clock cycle in sync with the system clock. | ||
| - Timer and software interrupts (`timer_irq_o` and `soft_irq_o`) are asserted within one clock cycle of their triggering condition. | ||
|
|
||
| ### Dependencies | ||
|
|
||
| The CLINT depends on `clk_i` to increment `mtime` and `rst_ni` to initialize internal registers. Write-enable (`*_we`) and write-data (`*_wdata`) inputs are required to update the `msip` and `mtimecmp` registers. It must be connected to the CPU core so software can receive the interrupt outputs. | ||
|
|
||
| ### Verification Links | ||
|
|
||
| Verification for the CLINT is planned through simulation testbenches to confirm correct behavior of the internal 64-bit timer (`mtime`), timer compare (`mtimecmp`), and software interrupt (`msip`) functionality. Testbenches will ensure that `timer_irq_o` and `soft_irq_o` assert under the correct conditions and that the module responds correctly to reset (`rst_ni`). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,69 @@ | ||
| # PLIC - Module Brief (v0.3) | ||
|
|
||
| **Owner:** Gavin Wiese | ||
| **RTL:** rtl/irq/plic.sv | ||
|
|
||
| ### Purpose & Role | ||
| The Platform-Level Interrupt Controller (PLIC) is placed near the CPU core. The PLIC manages and prioritizes external interrupt requests from up to 32 sources, forwarding only the highest-priority pending interrupt to the CPU. This allows the processor to efficiently handle asynchronous external events. | ||
|
|
||
| ### Parameters | ||
|
|
||
| - Number of interrupt sources: 32 (`NSOURCES`) | ||
| - Priority field width per source: 3 bits (`PRIO_WIDTH`) | ||
| - Interrupt ID width for claim/complete operations: `$clog2(NSOURCES)` | ||
|
|
||
| ### Interfaces (Ports) | ||
|
|
||
| | **Signal** | **Dir** | **Width** | **Description** | | ||
| |----------------------|---------|-----------|----------------------------------------------------| | ||
| | clk_i | in | 1 | System clock | | ||
| | rst_ni | in | 1 | Active-low asynchronous reset | | ||
| | src_i | in | 32 | External interrupt sources | | ||
| | priority_wdata | in | 96 | Data to write to all priority registers (32 × 3) | | ||
| | priority_we | in | 1 | Write enable for priority registers | | ||
| | enable_wdata | in | 32 | Data to write to enable register | | ||
| | enable_we | in | 1 | Write enable for enable register | | ||
| | claim_wdata | in | 5 | Claim complete input | | ||
| | claim_we | in | 1 | Write enable for claim completion | | ||
| | ext_irq_o | out | 1 | Interrupt output to the CPU core | | ||
| | claim_o | out | 5 | Current claimed interrupt ID | | ||
|
|
||
| ### Reset/Init | ||
|
|
||
| An active-low asynchronous reset (`rst_ni`) is used for the PLIC. When reset is asserted (`rst_ni = 0`), all internal registers—including `priorities`, `enable`, `pending`, and `claim`—are cleared to 0, and the output signal `ext_irq_o` is deasserted. | ||
|
|
||
| ### Behavior and Timing | ||
|
|
||
| The PLIC continuously monitors the 32 `src_i` interrupt lines. When one or more enabled interrupts are pending, the highest-priority source is selected, and `ext_irq_o` is asserted to signal the CPU core. Once the CPU completes the interrupt (signaled via `claim_we`), the pending bit for that interrupt is cleared and `ext_irq_o` deasserts. All operations are synchronous with the system clock, and `ext_irq_o` asserts one clock cycle after the conditions are met. | ||
|
|
||
| ### Programming Model | ||
|
|
||
| The PLIC provides three sets of registers controlled via simple write-enable/data inputs: | ||
|
|
||
| - **`priority`** – Stores the priority of each interrupt source. Higher values indicate higher priority. Updated via `priority_wdata` and `priority_we`. | ||
| - **`enable`** – Determines which interrupt sources are enabled. Updated via `enable_wdata` and `enable_we`. | ||
| - **`claim`** – Contains the currently claimed interrupt ID. Writing to this register with `claim_wdata` and `claim_we` signals completion, clearing the pending bit. | ||
|
|
||
| All registers are accessible through the `_we` / `_wdata` inputs in this bus-free implementation. | ||
|
|
||
| ### Errors/IRQs | ||
|
|
||
| | **IRQ** | **Source** | **Trigger** | **Clear** | | ||
| |------------|-----------|----------------------------------|-------------------------------------| | ||
| | ext_irq_o | src_i | One or more enabled interrupts pending | Cleared when CPU signals completion via claim input | | ||
|
|
||
| The PLIC does not generate additional internal error signals; all interrupts come from external sources. | ||
|
|
||
| ### Performance Targets | ||
|
|
||
| - `ext_irq_o` asserts within one clock cycle of a pending, enabled interrupt being detected. | ||
| - All internal registers (priority, enable, claim/complete, pending) update synchronously with the system clock. | ||
| - The PLIC can handle all 32 external sources without loss of pending interrupts. | ||
|
|
||
| ### Dependencies | ||
|
|
||
| The PLIC depends on `clk_i` to update internal registers and monitor interrupt sources, and on `rst_ni` to initialize registers. External interrupt lines (`src_i`) provide input events, and the PLIC drives the single interrupt output (`ext_irq_o`) to the CPU core. Register updates are controlled via `_we` / `_wdata` inputs. | ||
|
|
||
| ### Verification Links | ||
|
|
||
| Verification for the PLIC is planned through simulation testbenches to confirm correct behavior of priority handling, enable bits, and the claim/complete mechanism. Testbenches will ensure that `ext_irq_o` asserts for the highest-priority pending interrupt, that pending bits are cleared after a claim/complete operation, and that the module responds correctly to reset (`rst_ni`). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,25 @@ | ||
| module clint( | ||
| input logic clk_i, | ||
| input logic rst_ni, | ||
| output logic Timer_irq_o, | ||
| input logic [63:0] user_time, // | ||
| output logic [63:0] mtime_o, // | ||
| output logic msip | ||
| ); | ||
| logic [63:0] mtimecmp; | ||
|
|
||
| always_ff @(posedge clk_i or negedge rst_ni) begin | ||
| if (!rst_ni) begin | ||
| mtime_o <= 16'd0; | ||
| mtimecmp <= 16'd0; | ||
| Timer_irq_o <= 1'b0; | ||
| msip <= 1'b0; | ||
| end else begin | ||
| mtime_o <= mtime_o + 1; | ||
| mtimecmp <= user_time; | ||
| Timer_irq_o <= (mtime_o >= mtimecmp); | ||
| msip <= Timer_irq_o; | ||
| end | ||
| end | ||
| endmodule | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,105 @@ | ||
| module plic #( | ||
| parameter NSOURCES = 32, | ||
| parameter PRIO_WIDTH = 3 | ||
| )( | ||
| input logic clk_i, | ||
| input logic rst_ni, | ||
| input logic [NSOURCES-1:0] src_i, // External interrupt sources | ||
|
|
||
| // Simple register interface (bus-free) | ||
| input logic [NSOURCES*PRIO_WIDTH-1:0] priority_wdata, | ||
| input logic priority_we, | ||
| input logic [NSOURCES-1:0] enable_wdata, | ||
| input logic enable_we, | ||
| input logic [$clog2(NSOURCES)-1:0] claim_wdata, | ||
| input logic claim_we, | ||
|
|
||
| output logic ext_irq_o, | ||
| output logic [$clog2(NSOURCES)-1:0] claim_o | ||
| ); | ||
|
|
||
| // ------------------------- | ||
| // Registers / Internal state | ||
| // ------------------------- | ||
| logic [NSOURCES*PRIO_WIDTH-1:0] priorities; // Interrupt priorities | ||
| logic [NSOURCES-1:0] enable; // Enable bits for sources | ||
| logic [$clog2(NSOURCES)-1:0] claim; // Claim register | ||
| logic [NSOURCES-1:0] pending; // Pending interrupts | ||
| logic [$clog2(NSOURCES)-1:0] highestPriorIndex; | ||
| logic [PRIO_WIDTH-1:0] tempHighestValue; | ||
| logic activeClaim; | ||
|
|
||
| assign claim_o = claim; | ||
|
|
||
| // ------------------------- | ||
| // Active low reset | ||
| // ------------------------- | ||
| always_ff @(negedge rst_ni) begin | ||
| if (!rst_ni) begin | ||
| priorities <= 0; | ||
| enable <= 0; | ||
| claim <= 0; | ||
| pending <= 0; | ||
| highestPriorIndex <= 0; | ||
| tempHighestValue <= 0; | ||
| activeClaim <= 0; | ||
| end | ||
| end | ||
|
|
||
| // ------------------------- | ||
| // Simple register writes | ||
| // ------------------------- | ||
| always_ff @(posedge clk_i) begin | ||
| if (priority_we) begin | ||
| priorities <= priority_wdata; | ||
| end | ||
| if (enable_we) begin | ||
| enable <= enable_wdata; | ||
| end | ||
| if (claim_we) begin | ||
| activeClaim <= 0; // Claim complete | ||
| end | ||
| end | ||
|
|
||
| // ------------------------- | ||
| // Pending interrupt latching | ||
| // ------------------------- | ||
| always_ff @(posedge clk_i) begin | ||
| for (int i = 0; i < NSOURCES; i++) begin | ||
| pending[i] <= pending[i] | (src_i[i] & enable[i]); | ||
| end | ||
| end | ||
|
|
||
| // ------------------------- | ||
| // Priority selector | ||
| // ------------------------- | ||
| always_ff @(posedge clk_i) begin | ||
| tempHighestValue <= 0; | ||
| highestPriorIndex <= 0; | ||
| for (int i = 0; i < NSOURCES; i++) begin | ||
| if (pending[i] && priorities[i*PRIO_WIDTH +: PRIO_WIDTH] > tempHighestValue) begin | ||
| tempHighestValue <= priorities[i*PRIO_WIDTH +: PRIO_WIDTH]; | ||
| highestPriorIndex <= i[$clog2(NSOURCES)-1:0]; | ||
| end | ||
| end | ||
| end | ||
|
|
||
| // ------------------------- | ||
| // Claim logic | ||
| // ------------------------- | ||
| always_ff @(posedge clk_i) begin | ||
| if (!activeClaim && tempHighestValue != 0) begin | ||
| claim <= highestPriorIndex; | ||
| pending[highestPriorIndex] <= 0; | ||
| activeClaim <= 1; | ||
| end | ||
| end | ||
|
|
||
| // ------------------------- | ||
| // IRQ output | ||
| // ------------------------- | ||
| always_ff @(posedge clk_i) begin | ||
| ext_irq_o <= activeClaim; | ||
| end | ||
|
|
||
| endmodule | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.