/////////////////////////////////////////// // csrm.sv // // Written: David_Harris@hmc.edu 9 January 2021 // Modified: // dottolia@hmc.edu 7 April 2021 // // Purpose: Machine-Mode Control and Status Registers // See RISC-V Privileged Mode Specification 20190608 // Note: the CSRs do not support the following optional features // - Disabling portions of the instruction set with bits of the MISA register // - Changing from RV64 to RV32 by writing the SXL/UXL bits of the STATUS register // // Documentation: RISC-V System on Chip Design Chapter 5 // // A component of the CORE-V-WALLY configurable RISC-V project. // // Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University // // SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1 // // Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file // except in compliance with the License, or, at your option, the Apache License version 2.0. You // may obtain a copy of the License at // // https://solderpad.org/licenses/SHL-2.1/ // // Unless required by applicable law or agreed to in writing, any work distributed under the // License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, // either express or implied. See the License for the specific language governing permissions // and limitations under the License. //////////////////////////////////////////////////////////////////////////////////////////////// module csrm import cvw::*; #(parameter cvw_t P) ( input logic clk, reset, input logic UngatedCSRMWriteM, CSRMWriteM, MTrapM, input logic [11:0] CSRAdrM, input logic [P.XLEN-1:0] NextEPCM, NextMtvalM, MSTATUS_REGW, MSTATUSH_REGW, input logic [4:0] NextCauseM, input logic [P.XLEN-1:0] CSRWriteValM, input logic [11:0] MIP_REGW, MIE_REGW, output logic [P.XLEN-1:0] CSRMReadValM, MTVEC_REGW, output logic [P.XLEN-1:0] MEPC_REGW, output logic [31:0] MCOUNTEREN_REGW, MCOUNTINHIBIT_REGW, output logic [15:0] MEDELEG_REGW, output logic [11:0] MIDELEG_REGW, output var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0], output var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW [P.PMP_ENTRIES-1:0], output logic WriteMSTATUSM, WriteMSTATUSHM, output logic IllegalCSRMAccessM, IllegalCSRMWriteReadonlyM, output logic [63:0] MENVCFG_REGW ); logic [P.XLEN-1:0] MISA_REGW, MHARTID_REGW; logic [P.XLEN-1:0] MSCRATCH_REGW, MTVAL_REGW, MCAUSE_REGW; logic [P.XLEN-1:0] MENVCFGH_REGW; logic WriteMTVECM, WriteMEDELEGM, WriteMIDELEGM; logic WriteMSCRATCHM, WriteMEPCM, WriteMCAUSEM, WriteMTVALM; logic WriteMCOUNTERENM, WriteMCOUNTINHIBITM; // Machine CSRs localparam MVENDORID = 12'hF11; localparam MARCHID = 12'hF12; localparam MIMPID = 12'hF13; localparam MHARTID = 12'hF14; localparam MCONFIGPTR = 12'hF15; localparam MSTATUS = 12'h300; localparam MISA_ADR = 12'h301; localparam MEDELEG = 12'h302; localparam MIDELEG = 12'h303; localparam MIE = 12'h304; localparam MTVEC = 12'h305; localparam MCOUNTEREN = 12'h306; localparam MENVCFG = 12'h30A; localparam MSTATUSH = 12'h310; localparam MENVCFGH = 12'h31A; localparam MCOUNTINHIBIT = 12'h320; localparam MSCRATCH = 12'h340; localparam MEPC = 12'h341; localparam MCAUSE = 12'h342; localparam MTVAL = 12'h343; localparam MIP = 12'h344; localparam PMPCFG0 = 12'h3A0; // .. up to 15 more at consecutive addresses localparam PMPADDR0 = 12'h3B0; // ... up to 63 more at consecutive addresses localparam TSELECT = 12'h7A0; localparam TDATA1 = 12'h7A1; localparam TDATA2 = 12'h7A2; localparam TDATA3 = 12'h7A3; localparam DCSR = 12'h7B0; localparam DPC = 12'h7B1; localparam DSCRATCH0 = 12'h7B2; localparam DSCRATCH1 = 12'h7B3; // Constants localparam ZERO = {(P.XLEN){1'b0}}; localparam MEDELEG_MASK = 16'hB3FF; localparam MIDELEG_MASK = 12'h222; // we choose to not make machine interrupts delegable // There are PMP_ENTRIES = 0, 16, or 64 PMPADDR registers, each of which has its own flop genvar i; if (P.PMP_ENTRIES > 0) begin:pmp logic [P.PMP_ENTRIES-1:0] WritePMPCFGM; logic [P.PMP_ENTRIES-1:0] WritePMPADDRM ; logic [P.PMP_ENTRIES-1:0] ADDRLocked, CFGLocked; for(i=0; i= PMPCFG0 & CSRAdrM < PMPCFG0 + P.PMP_ENTRIES/4 & (P.XLEN==32 | CSRAdrM[0] == 0)) begin // only odd-numbered PMPCFG entries exist in RV64 if (P.XLEN==64) begin entry = ({CSRAdrM[11:1], 1'b0} - PMPCFG0)*4; // disregard odd entries in RV64 CSRMReadValM = {PMPCFG_ARRAY_REGW[entry+7],PMPCFG_ARRAY_REGW[entry+6],PMPCFG_ARRAY_REGW[entry+5],PMPCFG_ARRAY_REGW[entry+4], PMPCFG_ARRAY_REGW[entry+3],PMPCFG_ARRAY_REGW[entry+2],PMPCFG_ARRAY_REGW[entry+1],PMPCFG_ARRAY_REGW[entry]}; end else begin entry = (CSRAdrM - PMPCFG0)*4; CSRMReadValM = {PMPCFG_ARRAY_REGW[entry+3],PMPCFG_ARRAY_REGW[entry+2],PMPCFG_ARRAY_REGW[entry+1],PMPCFG_ARRAY_REGW[entry]}; end end else case (CSRAdrM) MISA_ADR: CSRMReadValM = MISA_REGW; MVENDORID: CSRMReadValM = 0; MARCHID: CSRMReadValM = 0; MIMPID: CSRMReadValM = {{P.XLEN-12{1'b0}}, 12'h100}; // pipelined implementation MHARTID: CSRMReadValM = MHARTID_REGW; // hardwired to 0 MCONFIGPTR: CSRMReadValM = 0; // hardwired to 0 MSTATUS: CSRMReadValM = MSTATUS_REGW; MSTATUSH: if (P.XLEN==32) CSRMReadValM = MSTATUSH_REGW; else IllegalCSRMAccessM = 1; MTVEC: CSRMReadValM = MTVEC_REGW; MEDELEG: CSRMReadValM = {{(P.XLEN-16){1'b0}}, MEDELEG_REGW}; MIDELEG: CSRMReadValM = {{(P.XLEN-12){1'b0}}, MIDELEG_REGW}; MIP: CSRMReadValM = {{(P.XLEN-12){1'b0}}, MIP_REGW}; MIE: CSRMReadValM = {{(P.XLEN-12){1'b0}}, MIE_REGW}; MSCRATCH: CSRMReadValM = MSCRATCH_REGW; MEPC: CSRMReadValM = MEPC_REGW; MCAUSE: CSRMReadValM = MCAUSE_REGW; MTVAL: CSRMReadValM = MTVAL_REGW; MCOUNTEREN: CSRMReadValM = {{(P.XLEN-32){1'b0}}, MCOUNTEREN_REGW}; MENVCFG: if (P.U_SUPPORTED) CSRMReadValM = MENVCFG_REGW[P.XLEN-1:0]; else IllegalCSRMAccessM = 1; MENVCFGH: if (P.U_SUPPORTED & P.XLEN==32) CSRMReadValM = MENVCFGH_REGW; else IllegalCSRMAccessM = 1; MCOUNTINHIBIT: CSRMReadValM = {{(P.XLEN-32){1'b0}}, MCOUNTINHIBIT_REGW}; default: IllegalCSRMAccessM = 1; endcase end // verilator lint_on WIDTH endmodule