/////////////////////////////////////////// // 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, // Machine CSRs MVENDORID = 12'hF11, MARCHID = 12'hF12, MIMPID = 12'hF13, MHARTID = 12'hF14, MCONFIGPTR = 12'hF15, MSTATUS = 12'h300, MISA_ADR = 12'h301, MEDELEG = 12'h302, MIDELEG = 12'h303, MIE = 12'h304, MTVEC = 12'h305, MCOUNTEREN = 12'h306, MSTATUSH = 12'h310, MCOUNTINHIBIT = 12'h320, MSCRATCH = 12'h340, MEPC = 12'h341, MCAUSE = 12'h342, MTVAL = 12'h343, MIP = 12'h344, MTINST = 12'h34A, PMPCFG0 = 12'h3A0, // .. up to 15 more at consecutive addresses PMPADDR0 = 12'h3B0, // ... up to 63 more at consecutive addresses TSELECT = 12'h7A0, TDATA1 = 12'h7A1, TDATA2 = 12'h7A2, TDATA3 = 12'h7A3, DCSR = 12'h7B0, DPC = 12'h7B1, DSCRATCH0 = 12'h7B2, DSCRATCH1 = 12'h7B3, // Constants ZERO = {(P.XLEN){1'b0}}, MEDELEG_MASK = 16'hB3FF, MIDELEG_MASK = 12'h222 // we choose to not make machine interrupts delegable ) ( 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 ); logic [P.XLEN-1:0] MISA_REGW, MHARTID_REGW; logic [P.XLEN-1:0] MSCRATCH_REGW, MTVAL_REGW, MCAUSE_REGW; logic WriteMTVECM, WriteMEDELEGM, WriteMIDELEGM; logic WriteMSCRATCHM, WriteMEPCM, WriteMCAUSEM, WriteMTVALM; logic WriteMCOUNTERENM, WriteMCOUNTINHIBITM; // 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: CSRMReadValM = MSTATUSH_REGW; 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; MTINST: CSRMReadValM = 0; // implemented as trivial zero MCOUNTEREN:CSRMReadValM = {{(P.XLEN-32){1'b0}}, MCOUNTEREN_REGW}; MCOUNTINHIBIT:CSRMReadValM = {{(P.XLEN-32){1'b0}}, MCOUNTINHIBIT_REGW}; default: begin CSRMReadValM = 0; IllegalCSRMAccessM = 1; end endcase end // verilator lint_on WIDTH endmodule