blob: 8648b9d7add9ac12d62011503c4a883b0245f434 [file] [log] [blame]
module RV32ICore(
`ifdef USE_POWER_PINS
inout vccd1, // User area 1 1.8V supply
inout vssd1, // User area 1 digital ground
`endif
input wire clk,
input wire rst,
// SRAM interface
output wire[31:0] memoryAddress,
output wire[3:0] memoryByteSelect,
output wire memoryWriteEnable,
output wire memoryReadEnable,
output wire[31:0] memoryDataWrite,
input wire[31:0] memoryDataRead,
input wire memoryBusy,
input wire memoryAccessFault,
// Management interface
input wire management_run,
input wire management_trapEnable,
input wire management_interruptEnable,
input wire management_writeEnable,
input wire[3:0] management_byteSelect,
input wire[15:0] management_address,
input wire[31:0] management_writeData,
output wire[31:0] management_readData,
// System info
input wire[7:0] coreIndex,
input wire[10:0] manufacturerID,
input wire[15:0] partID,
input wire[3:0] versionID,
input wire[25:0] extensions,
// Traps
input wire isAddressBreakpoint,
input wire[15:0] userInterrupts,
// Logic probes
output wire[1:0] probe_state,
output wire[1:0] probe_env,
output wire[31:0] probe_programCounter,
output wire[6:0] probe_opcode,
output wire[1:0] probe_errorCode,
output wire probe_isBranch,
output wire probe_takeBranch,
output wire probe_isStore,
output wire probe_isLoad,
output wire probe_isCompressed
);
localparam STATE_HALT = 2'b00;
localparam STATE_FETCH = 2'b10;
localparam STATE_EXECUTE = 2'b11;
// System registers
reg[1:0] state = STATE_HALT;
reg[1:0] currentError = 2'b0;
reg[31:0] programCounter = 32'b0;
reg[31:0] currentInstruction = 32'b0;
reg[31:0] registers [0:31];
// Management control
localparam MANAGMENT_ADDRESS_SYSTEM = 2'b00;
localparam MANAGMENT_ADDRESS_REGISTERS = 2'b01;
localparam MANAGMENT_ADDRESS_CSR = 2'b10;
wire management_selectProgramCounter = (management_address[15:14] == MANAGMENT_ADDRESS_SYSTEM) && (management_address[13:4] == 10'h000);
wire management_selectInstructionRegister = (management_address[15:14] == MANAGMENT_ADDRESS_SYSTEM) && (management_address[13:4] == 10'h001);
wire management_selectClearError = (management_address[15:14] == MANAGMENT_ADDRESS_SYSTEM) && (management_address[13:4] == 10'h002);
wire management_selectRegister = (management_address[15:14] == MANAGMENT_ADDRESS_REGISTERS) && (management_address[13:7] == 7'h00);
wire management_selectCSR = management_address[15:14] == MANAGMENT_ADDRESS_CSR;
wire management_writeValid = !management_run && management_writeEnable;
wire management_writeProgramCounter = management_writeValid && management_selectProgramCounter;
wire management_writeProgramCounter_set = management_writeProgramCounter && (management_address[3:0] == 4'h0);
wire management_writeProgramCounter_jump = management_writeProgramCounter && (management_address[3:0] == 4'h4);
wire management_writeProgramCounter_step = management_writeProgramCounter && (management_address[3:0] == 4'h8);
wire management_writeClearError = management_writeValid && management_selectClearError;
wire management_writeRegister = management_writeValid && management_selectRegister;
wire management_writeCSR = management_writeValid && management_selectCSR;
wire management_readValid = !management_run && !management_writeEnable;
wire management_readProgramCounter = management_readValid && management_selectProgramCounter;
wire management_readInstructionRegister = management_readValid && management_selectInstructionRegister;
wire management_readRegister = management_readValid && management_selectRegister;
wire management_readCSR = management_readValid && management_selectCSR;
wire management_allowInstruction = management_run || management_writeProgramCounter_step;
wire[4:0] management_registerIndex = management_address[6:2];
wire[11:0] management_csrIndex = management_address[13:2];
wire[31:0] management_jumpTarget = programCounter + management_writeData;
reg[31:0] management_dataOut;
always @(*) begin
case (1'b1)
management_readProgramCounter: management_dataOut <= programCounter;
management_readInstructionRegister : management_dataOut <= currentInstruction;
management_readRegister: management_dataOut <= !management_registerIndex ? registers[management_registerIndex] : 32'b0;
management_readCSR: management_dataOut <= csrReadData;
default: management_dataOut <= 32'b0;
endcase
end
assign management_readData = {
management_byteSelect[3] ? management_dataOut[31:24] : 8'h00,
management_byteSelect[2] ? management_dataOut[23:16] : 8'h00,
management_byteSelect[1] ? management_dataOut[15:8] : 8'h00,
management_byteSelect[0] ? management_dataOut[7:0] : 8'h00
};
// CSR interface
wire coreCSRWrite;
wire coreCSRRead;
wire[11:0] coreCSRIndex = currentInstruction[31:20];
reg[32:0] coreCSRWriteData;
wire csrWriteEnable = management_writeCSR || (management_run && coreCSRWrite && (state == STATE_EXECUTE));
wire csrReadEnable = management_readCSR || (management_run && coreCSRRead && (state == STATE_EXECUTE));
wire[11:0] csrAddress = !management_run ? management_csrIndex : coreCSRIndex;
wire[31:0] csrWriteData = !management_run ? management_writeData : coreCSRWriteData;
wire[31:0] csrReadData;
wire[31:0] trapVector;
wire[31:0] trapReturnVector;
wire inTrap;
// Immediate Decode
wire[31:0] imm_I = {currentInstruction[31] ? 21'h1F_FFFF : 21'h00_0000, currentInstruction[30:25], currentInstruction[24:21], currentInstruction[20]};
wire[31:0] imm_S = {currentInstruction[31] ? 21'h1F_FFFF : 21'h00_0000, currentInstruction[30:25], currentInstruction[11:8] , currentInstruction[7]};
wire[31:0] imm_B = {currentInstruction[31] ? 20'hF_FFFF : 20'h0_0000 , currentInstruction[7] , currentInstruction[30:25], currentInstruction[11:8] , 1'b0};
wire[31:0] imm_U = {currentInstruction[31] , currentInstruction[30:20], currentInstruction[19:12], 12'h000};
wire[31:0] imm_J = {currentInstruction[31] ? 12'hFFF : 12'h000 , currentInstruction[19:12], currentInstruction[20] , currentInstruction[30:25], currentInstruction[24:21], 1'b0};
// Instruction decode
wire[6:0] opcode = currentInstruction[6:0];
wire[4:0] rdIndex = currentInstruction[11:7];
wire[4:0] rs1Index = currentInstruction[19:15];
wire[4:0] rs2Index = currentInstruction[24:20];
wire[2:0] funct3 = currentInstruction[14:12];
wire[6:0] funct7 = currentInstruction[31:25];
wire isCompressed = opcode[1:0] != 2'b11;
// Instruction decode
wire isLUI = (opcode == 7'b0110111);
wire isAUIPC = (opcode == 7'b0010111);
wire isJAL = (opcode == 7'b1101111);
wire isJALR = (opcode == 7'b1100111) && (funct3 == 3'b000);
wire isBranch = (opcode == 7'b1100011) && (funct3 != 3'b010) && (funct3 != 3'b011);
wire isLoad = (opcode == 7'b0000011) && (funct3 == 3'b000 || funct3 == 3'b001 || funct3 == 3'b010 || funct3 == 3'b100 || funct3 == 3'b101);
wire isStore = (opcode == 7'b0100011) && (funct3 == 3'b000 || funct3 == 3'b001 || funct3 == 3'b010);
wire isALUImmBase = (opcode == 7'b0010011);
wire isALUImmNormal = isALUImmBase && funct3 != 3'b001 && funct3 != 3'b101;
wire isALUImmShift = isALUImmBase && ((funct3 == 3'b001 && funct7 == 7'b0000000) || (funct3 == 3'b101 && (funct7 == 7'b0000000 || funct7 == 7'b0100000)));
wire isALUImm = isALUImmShift || isALUImmNormal;
wire isALU = (opcode == 7'b0110011) && (funct7 == 7'b0000000 || ((funct7 == 7'b0100000) && (funct3 == 3'b000 || funct3 == 3'b101)));
wire isFENCE = (opcode == 7'b0001111) && (funct3 == 3'b000);
wire isSystem = (opcode == 7'b1110011);
// System commands
wire isCSR = isSystem && (funct3 != 3'b000);
wire isCSRIMM = isCSR && funct3[2];
wire isCSRRW = isCSR && (funct3[1:0] == 2'b01);
wire isCSRRS = isCSR && (funct3[1:0] == 2'b10);
wire isCSRRC = isCSR && (funct3[1:0] == 2'b11);
wire isECALL = isSystem && (currentInstruction[31:7] == 25'b0000000000000000000000000);
wire isEBREAK = isSystem && (currentInstruction[31:7] == 25'b0000000000010000000000000);
wire isRET = isSystem && (currentInstruction[31:7] == 25'b0011000000100000000000000);
wire validSystemCommand = isCSR || isECALL || isEBREAK || isRET;
reg invalidInstruction;
always @(*) begin
case ({ isLUI, isAUIPC, isJAL, isJALR, isBranch, isLoad, isStore, isALUImm, isALU, isFENCE, isSystem })
'b00000000001: invalidInstruction <= 1'b0;
'b00000000010: invalidInstruction <= 1'b0;
'b00000000100: invalidInstruction <= 1'b0;
'b00000001000: invalidInstruction <= 1'b0;
'b00000010000: invalidInstruction <= 1'b0;
'b00000100000: invalidInstruction <= 1'b0;
'b00001000000: invalidInstruction <= 1'b0;
'b00010000000: invalidInstruction <= 1'b0;
'b00100000000: invalidInstruction <= 1'b0;
'b01000000000: invalidInstruction <= 1'b0;
'b10000000000: invalidInstruction <= validSystemCommand;
default: invalidInstruction <= 1'b1;
endcase
end
wire isInvalidInstruction = invalidInstruction && state == STATE_EXECUTE;
// Integer Registers
wire[31:0] rs1 = |rs1Index ? registers[rs1Index] : 32'b0;
wire[31:0] rs2 = |rs2Index ? registers[rs2Index] : 32'b0;
// Setup inputs for ALU and branch control
wire[31:0] inputA = isAUIPC ? programCounter : rs1;
wire[31:0] inputB = isAUIPC ? imm_U :
isALUImm ? imm_I :
isLoad ? imm_I :
isStore ? imm_S :
rs2;
// The use of A-B for comparison is based on https://github.com/BrunoLevy/learn-fpga/tree/master/FemtoRV/TUTORIALS/FROM_BLINKER_TO_RISCV#from-blinker-to-risc-v
wire[31:0] aluAPlusB = inputA + inputB;
wire[32:0] aluACompareB = { 1'b0, inputA } - { 1'b0, inputB };
wire[31:0] aluAMinusB = aluACompareB[31:0];
wire aluAEqualsB = aluAMinusB == 32'b0;
wire aluALessThanB = inputA[31] ^ inputB[31] ? inputA[31] : aluACompareB[32];
wire aluALessThanBUnsigned = aluACompareB[32];
// Jump and branch control
reg takeBranch;
always @(*) begin
if (isBranch) begin
case (funct3)
/*BEQ*/ 3'b000: takeBranch <= aluAEqualsB;
/*BNE*/ 3'b001: takeBranch <= !aluAEqualsB;
//*None*/ 3'b010: takeBranch <= 1'b0;
//*None*/ 3'b011: takeBranch <= 1'b0;
/*BLT*/ 3'b100: takeBranch <= aluALessThanB;
/*BGE*/ 3'b101: takeBranch <= !aluALessThanB;
/*BLTU*/ 3'b110: takeBranch <= aluALessThanBUnsigned;
/*BGEU*/ 3'b111: takeBranch <= !aluALessThanBUnsigned;
default: takeBranch <= 1'b0;
endcase
end else begin
takeBranch <= 1'b0;
end
end
wire[31:0] programCounterLink = programCounter + (isCompressed ? 2 : 4);
wire[31:0] nextProgramCounterBase = isJAL ? programCounter :
isJALR ? rs1 :
takeBranch ? programCounter :
programCounterLink;
wire[31:0] nextProgramCounterOffset = isJAL ? imm_J :
isJALR ? imm_I :
takeBranch ? imm_B :
32'b0;
wire[31:0] nextProgramCounterWord = nextProgramCounterBase + nextProgramCounterOffset;
wire[31:0] nextProgramCounterCompressed = programCounterLink; // TODO: Need to implement compressed branch and jump instructions
wire[31:0] nextProgramCounterFull = isCompressed ? nextProgramCounterCompressed : nextProgramCounterWord;
wire[31:0] nextProgramCounter = { nextProgramCounterFull[31:1] , 1'b0};
wire jumpMissaligned = !isCompressed && |nextProgramCounter[1:0] && state == STATE_EXECUTE && (isJAL || isJALR || takeBranch);
// ALU
wire aluAlt = funct7 == 7'b0100000 && (isALU || isALUImmShift);
// Using only a single shifter also from https://github.com/BrunoLevy/learn-fpga/tree/master/FemtoRV/TUTORIALS/FROM_BLINKER_TO_RISCV#from-blinker-to-risc-v
// Although I feel like there is an easier way to flip bit orderings
function [31:0] flipBits32 (input [31:0] x);
flipBits32 = { x[ 0], x[ 1], x[ 2], x[ 3], x[ 4], x[ 5], x[ 6], x[ 7],
x[ 8], x[ 9], x[10], x[11], x[12], x[13], x[14], x[15],
x[16], x[17], x[18], x[19], x[20], x[21], x[22], x[23],
x[24], x[25], x[26], x[27], x[28], x[29], x[30], x[31] };
endfunction
wire isLeftShift = funct3 == 3'b001;
wire[31:0] shiftInput = isLeftShift ? flipBits32(inputA) : inputA;
wire signed[32:0] signedShiftInput = { aluAlt && shiftInput[31] && !isLeftShift, shiftInput };
wire[32:0] aluShifter = $signed(signedShiftInput >>> inputB[4:0]);
wire[31:0] rightShift = aluShifter[31:0];
wire[31:0] leftShift = flipBits32(rightShift);
reg[31:0] aluValue;
always @(*) begin
case (funct3)
/*ADD*/ 3'b000: aluValue <= aluAlt ? aluAMinusB : aluAPlusB;
/*SLL*/ 3'b001: aluValue <= leftShift;
/*SLT*/ 3'b010: aluValue <= {31'b0, aluALessThanB};
/*SLTU*/ 3'b011: aluValue <= {31'b0, aluALessThanBUnsigned};
/*XOR*/ 3'b100: aluValue <= inputA ^ inputB;
/*SRL*/ 3'b101: aluValue <= rightShift;
/*OR*/ 3'b110: aluValue <= inputA | inputB;
/*AND*/ 3'b111: aluValue <= inputA & inputB;
default: aluValue <= 32'b0;
endcase
end
// CSR data connections
assign coreCSRWrite = isCSRRW || (isCSR && |rs1Index);
assign coreCSRRead = isCSRRC || isCSRRS || (isCSR && |rdIndex);
wire[31:0] csrRS1Data = isCSRIMM ? { 27'b0, rs1Index} : rs1;
always @(*) begin
if (isCSR) begin
if (isCSRRW) coreCSRWriteData <= csrRS1Data;
else if (isCSRRS) coreCSRWriteData <= csrReadData | csrRS1Data;
else if (isCSRRC) coreCSRWriteData <= csrReadData & ~csrRS1Data;
else coreCSRWriteData <= 32'b0;
end else begin
coreCSRWriteData <= 32'b0;
end
end
// Memory connections
wire[31:0] targetMemoryAddress = state == STATE_FETCH ? programCounter :
state == STATE_EXECUTE ? aluAPlusB:
32'b0;
wire loadSigned = (funct3 == 3'b000) || (funct3 == 3'b001);
wire loadStoreByte = funct3[1:0] == 2'b00;
wire loadStoreHalf = funct3[1:0] == 2'b01;
wire loadStoreWord = funct3 == 3'b010;
reg[3:0] baseByteMask;
always @(*) begin
if (state == STATE_FETCH) baseByteMask <= 4'b1111;
else if ((isLoad || isStore) && state == STATE_EXECUTE) begin
if (loadStoreWord) baseByteMask <= 4'b1111;
else if (loadStoreHalf) baseByteMask <= 4'b0011;
else if (loadStoreByte) baseByteMask <= 4'b0001;
else baseByteMask <= 4'b0000;
end else baseByteMask <= 4'b0000;
end
reg signExtend;
always @(*) begin
if (loadSigned) begin
if (loadStoreByte) begin
case (targetMemoryAddress[1:0])
2'b00: signExtend <= memoryDataRead[7];
2'b01: signExtend <= memoryDataRead[15];
2'b10: signExtend <= memoryDataRead[23];
2'b11: signExtend <= memoryDataRead[31];
endcase
end else if (loadStoreHalf) begin
case (targetMemoryAddress[1:0])
2'b00: signExtend <= memoryDataRead[15];
2'b01: signExtend <= memoryDataRead[23];
2'b10: signExtend <= memoryDataRead[31];
2'b11: signExtend <= 1'b0;
endcase
end else begin
signExtend <= 1'b0;
end
end else begin
signExtend <= 1'b0;
end
end
wire[7:0] signExtendByte = signExtend ? 8'hFF : 8'h00;
wire[6:0] loadStoreByteMask = {3'b0, baseByteMask} << targetMemoryAddress[1:0];
wire loadStoreByteMaskValid = |(loadStoreByteMask[3:0]);
wire addressMissaligned = |loadStoreByteMask[6:4];
wire isAddressMisaligned = addressMissaligned && ((state == STATE_FETCH) || ((state == STATE_EXECUTE) && (isLoad || isStore)));
wire shouldLoad = loadStoreByteMaskValid && !addressMissaligned && ((state == STATE_FETCH) || ((state == STATE_EXECUTE) && isLoad));
wire shouldStore = loadStoreByteMaskValid && !addressMissaligned && ((state == STATE_EXECUTE) && isStore);
assign memoryAddress = shouldLoad || shouldStore ? { targetMemoryAddress[31:2], 2'b00 } : 32'b0;
assign memoryByteSelect = shouldStore || shouldLoad ? loadStoreByteMask[3:0] : 4'b0000;
wire[31:0] loadData = shouldLoad && !shouldStore ? dataIn : 32'b0;
wire[31:0] storeData = shouldStore && !shouldLoad ? rs2 : 32'b0;
reg[31:0] dataIn;
always @(*) begin
case (targetMemoryAddress[1:0])
2'b00: dataIn = {
loadStoreByteMask[3] ? memoryDataRead[31:24] : signExtendByte,
loadStoreByteMask[2] ? memoryDataRead[23:16] : signExtendByte,
loadStoreByteMask[1] ? memoryDataRead[15:8] : signExtendByte,
loadStoreByteMask[0] ? memoryDataRead[7:0] : 8'h00
};
2'b01: dataIn = {
signExtendByte,
loadStoreByteMask[3] ? memoryDataRead[31:24] : signExtendByte,
loadStoreByteMask[2] ? memoryDataRead[23:16] : signExtendByte,
loadStoreByteMask[1] ? memoryDataRead[15:8] : 8'h00
};
2'b10: dataIn = {
signExtendByte,
signExtendByte,
loadStoreByteMask[3] ? memoryDataRead[31:24] : signExtendByte,
loadStoreByteMask[2] ? memoryDataRead[23:16] : 8'h00
};
2'b11: dataIn = {
signExtendByte,
signExtendByte,
signExtendByte,
loadStoreByteMask[3] ? memoryDataRead[31:24] : 8'h00
};
endcase
end
reg[31:0] dataOut;
always @(*) begin
case (targetMemoryAddress[1:0])
2'b00: dataOut = {
baseByteMask[3] ? storeData[31:24] : 8'h00,
baseByteMask[2] ? storeData[23:16] : 8'h00,
baseByteMask[1] ? storeData[15:8] : 8'h00,
baseByteMask[0] ? storeData[7:0] : 8'h00
};
2'b01: dataOut = {
baseByteMask[2] ? storeData[23:16] : 8'h00,
baseByteMask[1] ? storeData[15:8] : 8'h00,
baseByteMask[0] ? storeData[7:0] : 8'h00,
8'h00
};
2'b10: dataOut = {
baseByteMask[1] ? storeData[15:8] : 8'h00,
baseByteMask[0] ? storeData[7:0] : 8'h00,
8'h00,
8'h00
};
2'b11: dataOut = {
baseByteMask[0] ? storeData[7:0] : 8'h00,
8'h00,
8'h00,
8'h00
};
endcase
end
assign memoryDataWrite = dataOut;
assign memoryWriteEnable = shouldStore;
assign memoryReadEnable = shouldLoad;
wire memoryReadReady = shouldLoad ? !memoryBusy : 1'b0;
wire memoryWriteDone = shouldStore ? !memoryBusy : 1'b0;
// Register Write
wire integerRegisterWriteEn = isLUI || isAUIPC || isJAL || isJALR || isALU || isALUImm || isLoad || csrReadEnable;
wire[31:0] integerRegisterWriteData = isLUI ? imm_U :
isAUIPC ? aluAPlusB :
isJAL ? programCounterLink :
isJALR ? programCounterLink :
isLoad ? loadData :
(isALU || isALUImm) ? aluValue :
csrReadEnable ? csrReadData :
32'b0;
wire progressExecute = isStore ? memoryWriteDone :
isLoad ? memoryReadReady :
1'b1;
always @(posedge clk) begin
if (rst) begin
state <= STATE_HALT;
programCounter <= 32'b0;
currentError <= 4'b0;
programCounter <= 32'b0;
currentInstruction <= 32'b0;
end else begin
case (state)
STATE_HALT: begin
if (management_allowInstruction && !(|currentError)) state <= STATE_FETCH;
else begin
if (management_writeProgramCounter_set) programCounter <= { management_writeData[31:1] , 1'b0};
else if (management_writeProgramCounter_jump) programCounter <= { management_jumpTarget[31:1] , 1'b0};
else if (management_writeRegister) registers[management_registerIndex] <= management_writeData;
else if (management_writeClearError) currentError <= 2'b0;
end
end
STATE_FETCH: begin
if (|currentError) begin
state <= STATE_HALT;
end else begin
if (inTrap) programCounter <= trapVector;
else if (memoryReadReady) begin
currentInstruction <= dataIn;
state <= STATE_EXECUTE;
end
end
end
STATE_EXECUTE: begin
if (!management_trapEnable && (isAddressMisaligned || isInvalidInstruction)) begin
currentError <= { isAddressMisaligned, isInvalidInstruction };
state <= STATE_HALT;
end else begin
if (progressExecute) begin
if (integerRegisterWriteEn && |rdIndex) registers[rdIndex] <= integerRegisterWriteData;
if (management_trapEnable) begin
if (inTrap) programCounter <= trapVector;
else if (isRET) programCounter <= trapReturnVector;
else programCounter <= nextProgramCounter;
end else begin
programCounter <= nextProgramCounter;
end
if (management_allowInstruction) state <= STATE_FETCH;
else state <= STATE_HALT;
end
end
end
default: state <= STATE_HALT;
endcase
end
end
// System commands
wire eCall = isECALL && (state == STATE_EXECUTE);
wire eBreak = isEBREAK && (state == STATE_EXECUTE);
wire trapReturn = isRET && (state == STATE_EXECUTE);
wire isMachineTimerInterrupt = 1'b0;
wire isMachineExternalInterrupt = 1'b0;
wire isMachineSoftwareInterrupt = 1'b0;
// CSRs
wire instructionCompleted = (state == STATE_EXECUTE) && progressExecute;
CSR csr(
.clk(clk),
.rst(rst),
.csrWriteEnable(csrWriteEnable),
.csrReadEnable(csrReadEnable),
.csrAddress(csrAddress),
.csrWriteData(csrWriteData),
.csrReadData(csrReadData),
.coreIndex(coreIndex),
.manufacturerID(manufacturerID),
.partID(partID),
.versionID(versionID),
.extensions(extensions),
.instructionCompleted(instructionCompleted),
.coreState(state),
.programCounter(programCounter),
.currentInstruction(currentInstruction),
.isLoad(isLoad),
.isStore(isStore),
.isMachineTimerInterrupt(isMachineTimerInterrupt),
.isMachineExternalInterrupt(isMachineExternalInterrupt),
.isMachineSoftwareInterrupt(isMachineSoftwareInterrupt),
.isAddressMisaligned(isAddressMisaligned),
.isJumpMissaligned(jumpMissaligned),
.isAccessFault(memoryAccessFault),
.isInvalidInstruction(isInvalidInstruction),
.isEBREAK(eBreak),
.isECALL(eCall),
.isAddressBreakpoint(isAddressBreakpoint),
.userInterrupts(management_interruptEnable ? userInterrupts : 16'b0),
.trapReturn(trapReturn),
.inTrap(inTrap),
.trapVector(trapVector),
.trapReturnVector(trapReturnVector));
// Debug
assign probe_state = state;
assign probe_env = { eCall, eBreak };
assign probe_programCounter = programCounter;
assign probe_opcode = opcode;
assign probe_errorCode = currentError;
assign probe_isBranch = isBranch;
assign probe_takeBranch = takeBranch;
assign probe_isStore = isStore;
assign probe_isLoad = isLoad;
assign probe_isCompressed = isCompressed;
endmodule