From bc36edece29ec3152e731726773db9cf7e9de139 Mon Sep 17 00:00:00 2001 From: Matthew <106996253+Matthew-Otto@users.noreply.github.com> Date: Mon, 3 Jun 2024 22:21:02 -0500 Subject: [PATCH] clean up repo --- fpga/constraints/constraints-ArtyA7.xdc | 6 + fpga/src/fpgaTopArtyA7.sv | 9 +- src/debug/dm.sv | 777 ++++++++++++------------ src/debug/dtm.sv | 209 +++---- src/debug/ir.sv | 4 +- src/debug/jtag.sv | 170 +++--- src/hazard/hazard.sv | 30 +- src/ieu/controller.sv | 11 +- src/ieu/datapath.sv | 26 +- src/ieu/ieu.sv | 21 +- src/ifu/ifu.sv | 15 +- src/lsu/lsu.sv | 11 +- src/privileged/csr.sv | 9 +- src/privileged/csrm.sv | 6 +- src/privileged/privileged.sv | 14 +- src/wally/wallypipelinedcore.sv | 6 +- src/wally/wallypipelinedsoc.sv | 41 +- 17 files changed, 697 insertions(+), 668 deletions(-) diff --git a/fpga/constraints/constraints-ArtyA7.xdc b/fpga/constraints/constraints-ArtyA7.xdc index 6fc660e8d..39495d0be 100644 --- a/fpga/constraints/constraints-ArtyA7.xdc +++ b/fpga/constraints/constraints-ArtyA7.xdc @@ -71,6 +71,12 @@ set_property PACKAGE_PIN D9 [get_ports {south_reset}] set_property IOSTANDARD LVCMOS33 [get_ports {south_reset}] +##### JTAG Port ##### +set_property -dict {PACKAGE_PIN G13 IOSTANDARD LVCMOS33} [get_ports tck] +set_property -dict {PACKAGE_PIN B11 IOSTANDARD LVCMOS33} [get_ports tdo] +set_property -dict {PACKAGE_PIN A11 IOSTANDARD LVCMOS33} [get_ports tms] +set_property -dict {PACKAGE_PIN D12 IOSTANDARD LVCMOS33} [get_ports tdi] + ##### SD Card I/O ##### #***** may have to switch to Pmod JB or JC. diff --git a/fpga/src/fpgaTopArtyA7.sv b/fpga/src/fpgaTopArtyA7.sv index 20e8adb81..f03005f3a 100644 --- a/fpga/src/fpgaTopArtyA7.sv +++ b/fpga/src/fpgaTopArtyA7.sv @@ -58,7 +58,12 @@ module fpgaTop output [0:0] ddr3_cke, output [0:0] ddr3_cs_n, output [1:0] ddr3_dm, - output [0:0] ddr3_odt + output [0:0] ddr3_odt, + // JTAG signals + input tck, + input tdi, + input tms, + output tdo ); wire CPUCLK; @@ -490,7 +495,7 @@ module fpgaTop `include "parameter-defs.vh" wallypipelinedsoc #(P) - wallypipelinedsoc(.clk(CPUCLK), .reset_ext(bus_struct_reset), .reset(), + wallypipelinedsoc(.clk(CPUCLK), .reset_ext(bus_struct_reset), .reset(), .tck, .tdi, .tms, .tdo, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT, .HSELEXTSDC, .HCLK(HCLKOpen), .HRESETn(HRESETnOpen), .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, diff --git a/src/debug/dm.sv b/src/debug/dm.sv index 2ebc13a7e..a39bf4512 100644 --- a/src/debug/dm.sv +++ b/src/debug/dm.sv @@ -26,411 +26,412 @@ //////////////////////////////////////////////////////////////////////////////////////////////// module dm import cvw::*; #(parameter cvw_t P) ( - input logic clk, - input logic rst, // Full hardware reset signal (reset button) - + input logic clk, + input logic rst, + // External JTAG signals - input logic tck, - input logic tdi, - input logic tms, - output logic tdo, + input logic tck, + input logic tdi, + input logic tms, + output logic tdo, // Platform reset signal - output logic NdmReset, + output logic NdmReset, // Core hazard signal - output logic DebugStall, + output logic DebugStall, // Scan Chain - output logic ScanEn, - input logic ScanIn, - output logic ScanOut, - output logic GPRSel, - output logic DebugCapture, - output logic DebugGPRUpdate, + output logic ScanEn, + input logic ScanIn, + output logic ScanOut, + output logic GPRSel, + output logic DebugCapture, + output logic DebugGPRUpdate, output logic [P.E_SUPPORTED+3:0] GPRAddr, - output logic GPRScanEn, - input logic GPRScanIn, - output logic GPRScanOut + output logic GPRScanEn, + input logic GPRScanIn, + output logic GPRScanOut ); - `include "debug.vh" - // DMI Signals - logic ReqReady; - logic ReqValid; - logic [`ADDR_WIDTH-1:0] ReqAddress; - logic [31:0] ReqData; - logic [1:0] ReqOP; - logic RspReady; - logic RspValid; - logic [31:0] RspData; - logic [1:0] RspOP; - - localparam JTAG_DEVICE_ID = 32'hdeadbeef; // TODO: put JTAG device ID in parameter struct - - dtm #(`ADDR_WIDTH, JTAG_DEVICE_ID) dtm (.clk, .tck, .tdi, .tms, .tdo, - .ReqReady, .ReqValid, .ReqAddress, .ReqData, .ReqOP, .RspReady, - .RspValid, .RspData, .RspOP); - - // Core control signals - logic HaltReq; - logic ResumeReq; - logic HaltOnReset; - logic Halted; - - hartcontrol hartcontrol(.clk, .rst(rst | ~DmActive), .NdmReset, .HaltReq, - .ResumeReq, .HaltOnReset, .DebugStall, .Halted, .AllRunning, - .AnyRunning, .AllHalted, .AnyHalted, .AllResumeAck, .AnyResumeAck); - + // DMI Signals + logic ReqReady; + logic ReqValid; + logic [`ADDR_WIDTH-1:0] ReqAddress; + logic [31:0] ReqData; + logic [1:0] ReqOP; + logic RspReady; + logic RspValid; + logic [31:0] RspData; + logic [1:0] RspOP; + + localparam JTAG_DEVICE_ID = 32'hdeadbeef; // TODO: put JTAG device ID in parameter struct + + dtm #(`ADDR_WIDTH, JTAG_DEVICE_ID) dtm (.clk, .tck, .tdi, .tms, .tdo, + .ReqReady, .ReqValid, .ReqAddress, .ReqData, .ReqOP, .RspReady, + .RspValid, .RspData, .RspOP); + + // Core control signals + logic HaltReq; + logic ResumeReq; + logic HaltOnReset; + logic Halted; + + hartcontrol hartcontrol(.clk, .rst(rst || ~DmActive), .NdmReset, .HaltReq, + .ResumeReq, .HaltOnReset, .DebugStall, .Halted, .AllRunning, + .AnyRunning, .AllHalted, .AnyHalted, .AllResumeAck, .AnyResumeAck); + + enum logic [3:0] {INACTIVE, IDLE, ACK, R_DATA, W_DATA, DMSTATUS, W_DMCONTROL, R_DMCONTROL, W_ABSTRACTCS, R_ABSTRACTCS, ABST_COMMAND, R_SYSBUSCS, READ_ZERO, INVALID} State; - - enum logic [1:0] {AC_IDLE, AC_GPRUPDATE, AC_SCAN, AC_CAPTURE} AcState, NewAcState; - - // AbsCmd internal state - logic AcWrite; // Abstract Command write state - logic [P.XLEN:0] ScanReg; // The part of the debug scan chain located within DM - logic [P.XLEN-1:0] ScanNext; // New ScanReg value - logic [P.XLEN-1:0] ARMask; // Masks which bits of the ScanReg get updated - logic [P.XLEN-1:0] PackedDataReg; // Combines DataX msg registers into a single XLEN wide register - logic [P.XLEN-1:0] MaskedScanReg; // Masks which bits of the ScanReg get written to DataX - logic [9:0] ShiftCount; // Position of the selected register on the debug scan chain - logic [9:0] ScanChainLen; // Total length of currently selected scan chain - logic [9:0] Cycle; // DM's current position in the scan chain - logic InvalidRegNo; // Requested RegNo is invalid - logic RegReadOnly; // Current RegNo points to a readonly register - logic GPRRegNo; // Requested RegNo is a GPR - logic StoreScanChain; // Store current value of ScanReg into DataX - logic WriteMsgReg; // Write to DataX - logic WriteScanReg; // Insert data from DataX into ScanReg - logic [31:0] Data0Wr; // Muxed inputs to DataX regs - logic [31:0] Data1Wr; // Muxed inputs to DataX regs - logic [31:0] Data2Wr; // Muxed inputs to DataX regs - logic [31:0] Data3Wr; // Muxed inputs to DataX regs + enum logic [1:0] {AC_IDLE, AC_GPRUPDATE, AC_SCAN, AC_CAPTURE} AcState, NewAcState; + + // AbsCmd internal state + logic AcWrite; // Abstract Command write state + logic [P.XLEN:0] ScanReg; // The part of the debug scan chain located within DM + logic [P.XLEN-1:0] ScanNext; // New ScanReg value + logic [P.XLEN-1:0] ARMask; // Masks which bits of the ScanReg get updated + logic [P.XLEN-1:0] PackedDataReg; // Combines DataX msg registers into a single XLEN wide register + logic [P.XLEN-1:0] MaskedScanReg; // Masks which bits of the ScanReg get written to DataX + logic [9:0] ShiftCount; // Position of the selected register on the debug scan chain + logic [9:0] ScanChainLen; // Total length of currently selected scan chain + logic [9:0] Cycle; // DM's current position in the scan chain + logic InvalidRegNo; // Requested RegNo is invalid + logic RegReadOnly; // Current RegNo points to a readonly register + logic GPRRegNo; // Requested RegNo is a GPR + logic StoreScanChain; // Store current value of ScanReg into DataX + logic WriteMsgReg; // Write to DataX + logic WriteScanReg; // Insert data from DataX into ScanReg + logic [31:0] Data0Wr; // Muxed inputs to DataX regs + logic [31:0] Data1Wr; // Muxed inputs to DataX regs + logic [31:0] Data2Wr; // Muxed inputs to DataX regs + logic [31:0] Data3Wr; // Muxed inputs to DataX regs // message registers - logic [31:0] Data0; // 0x04 - logic [31:0] Data1; // 0x05 - logic [31:0] Data2; // 0x06 - logic [31:0] Data3; // 0x07 - - // debug module registers - logic [31:0] DMControl; // 0x10 - logic [31:0] DMStatus; // 0x11 - logic [31:0] AbstractCS; // 0x16 - logic [31:0] SysBusCS; // 0x38 - - // DM register fields - - // DMControl - logic AckUnavail; - logic DmActive; // This bit is used to (de)activate the DM. Toggling acts as reset - // DMStatus - logic StickyUnavail; - logic ImpEBreak; - logic AllResumeAck; - logic AnyResumeAck; - logic AllNonExistent; - logic AnyNonExistent; - logic AllUnavail; // TODO - logic AnyUnavail; - logic AllRunning; - logic AnyRunning; - logic AllHalted; - logic AnyHalted; - const logic Authenticated = 1; - logic AuthBusy; - const logic HasResetHaltReq = 1; - logic ConfStrPtrValid; - const logic [3:0] Version = 3; // DM Version - // AbstractCS - const logic [4:0] ProgBufSize = 0; - logic Busy; - const logic RelaxedPriv = 1; - logic [2:0] CmdErr; - const logic [3:0] DataCount = (P.XLEN/32); - - // Pack registers - assign DMControl = {2'b0, 1'b0, 2'b0, 1'b0, 10'b0, - 10'b0, 4'b0, NdmReset, DmActive}; + logic [31:0] Data0; // 0x04 + logic [31:0] Data1; // 0x05 + logic [31:0] Data2; // 0x06 + logic [31:0] Data3; // 0x07 - assign DMStatus = {7'b0, 1'b0, StickyUnavail, ImpEBreak, 2'b0, - 2'b0, AllResumeAck, AnyResumeAck, AllNonExistent, - AnyNonExistent, AllUnavail, AnyUnavail, AllRunning, AnyRunning, AllHalted, - AnyHalted, Authenticated, AuthBusy, HasResetHaltReq, ConfStrPtrValid, Version}; - - assign AbstractCS = {3'b0, ProgBufSize, 11'b0, Busy, RelaxedPriv, CmdErr, 4'b0, DataCount}; - - assign SysBusCS = 32'h20000000; // SBVersion = 1 - - assign RspValid = (State == ACK); - assign ReqReady = (State != ACK); + // debug module registers + logic [31:0] DMControl; // 0x10 + logic [31:0] DMStatus; // 0x11 + logic [31:0] AbstractCS; // 0x16 + logic [31:0] SysBusCS; // 0x38 - always_ff @(posedge clk) begin - if (rst) begin - DmActive <= 0; - State <= INACTIVE; - end else begin - case (State) - INACTIVE : begin - // Reset Values - RspData <= 0; - HaltReq <= 0; - HaltOnReset <= 0; - NdmReset <= 0; - StickyUnavail <= 0; - ImpEBreak <= 0; - AuthBusy <= 0; - ConfStrPtrValid <= 0; - CmdErr <= 0; - if (ReqValid) begin - if (ReqAddress == `DMCONTROL & ReqOP == `OP_WRITE & ReqData[`DMACTIVE]) begin - DmActive <= ReqData[`DMACTIVE]; - RspOP <= `OP_SUCCESS; - end - State <= ACK; // acknowledge all Reqs even if they don't activate DM + //// DM register fields + // DMControl + logic AckUnavail; + logic DmActive; // This bit is used to (de)activate the DM. Toggling acts as reset + // DMStatus + logic StickyUnavail; + logic ImpEBreak; + logic AllResumeAck; + logic AnyResumeAck; + logic AllNonExistent; + logic AnyNonExistent; + logic AllUnavail; // TODO + logic AnyUnavail; + logic AllRunning; + logic AnyRunning; + logic AllHalted; + logic AnyHalted; + const logic Authenticated = 1; + logic AuthBusy; + const logic HasResetHaltReq = 1; + logic ConfStrPtrValid; + const logic [3:0] Version = 3; // DM Version + // AbstractCS + const logic [4:0] ProgBufSize = 0; + logic Busy; + const logic RelaxedPriv = 1; + logic [2:0] CmdErr; + const logic [3:0] DataCount = (P.XLEN/32); + + + // Pack registers + assign DMControl = {2'b0, 1'b0, 2'b0, 1'b0, 10'b0, + 10'b0, 4'b0, NdmReset, DmActive}; + + assign DMStatus = {7'b0, 1'b0, StickyUnavail, ImpEBreak, 2'b0, + 2'b0, AllResumeAck, AnyResumeAck, AllNonExistent, + AnyNonExistent, AllUnavail, AnyUnavail, AllRunning, AnyRunning, AllHalted, + AnyHalted, Authenticated, AuthBusy, HasResetHaltReq, ConfStrPtrValid, Version}; + + assign AbstractCS = {3'b0, ProgBufSize, 11'b0, Busy, RelaxedPriv, CmdErr, 4'b0, DataCount}; + + assign SysBusCS = 32'h20000000; // SBVersion = 1 + + assign RspValid = (State == ACK); + assign ReqReady = (State != ACK); + + always_ff @(posedge clk) begin + if (rst) begin + DmActive <= 0; + State <= INACTIVE; + end else begin + case (State) + INACTIVE : begin + // Reset Values + RspData <= 0; + HaltReq <= 0; + HaltOnReset <= 0; + NdmReset <= 0; + StickyUnavail <= 0; + ImpEBreak <= 0; + AuthBusy <= 0; + ConfStrPtrValid <= 0; + CmdErr <= 0; + if (ReqValid) begin + if (ReqAddress == `DMCONTROL && ReqOP == `OP_WRITE && ReqData[`DMACTIVE]) begin + DmActive <= ReqData[`DMACTIVE]; + RspOP <= `OP_SUCCESS; + end + State <= ACK; // acknowledge all Reqs even if they don't activate DM + end + end + + ACK : begin + NewAcState <= AC_IDLE; + ResumeReq <= 0; + if (~ReqValid) + State <= ~DmActive ? INACTIVE : IDLE; + end + + IDLE : begin + if (ReqValid) + case ({ReqOP, ReqAddress}) inside + {`OP_WRITE,`DATA0} : State <= W_DATA; + {`OP_READ,`DATA0} : State <= R_DATA; + {`OP_WRITE,`DATA1} : State <= (P.XLEN >= 64) ? W_DATA : INVALID; + {`OP_READ,`DATA1} : State <= (P.XLEN >= 64) ? R_DATA : INVALID; + [{`OP_WRITE,`DATA2}:{`OP_WRITE,`DATA3}] : State <= (P.XLEN >= 128) ? W_DATA : INVALID; + [{`OP_READ,`DATA2}:{`OP_READ,`DATA3}] : State <= (P.XLEN >= 128) ? R_DATA : INVALID; + {`OP_WRITE,`DMCONTROL} : State <= W_DMCONTROL; + {`OP_READ,`DMCONTROL} : State <= R_DMCONTROL; + {`OP_READ,`DMSTATUS} : State <= DMSTATUS; + {`OP_WRITE,`ABSTRACTCS} : State <= W_ABSTRACTCS; + {`OP_READ,`ABSTRACTCS} : State <= R_ABSTRACTCS; + {`OP_WRITE,`COMMAND} : State <= ABST_COMMAND; + {`OP_READ,`COMMAND} : State <= READ_ZERO; + {`OP_WRITE,`SBCS} : State <= READ_ZERO; + {`OP_READ,`SBCS} : State <= R_SYSBUSCS; + {2'bx,`HARTINFO}, + {2'bx,`ABSTRACTAUTO}, + {2'bx,`NEXTDM} : State <= READ_ZERO; + default : State <= INVALID; + endcase + end + + R_DATA : begin + if (Busy) + CmdErr <= ~|CmdErr ? `CMDERR_BUSY : CmdErr; + case (ReqAddress) + `DATA0 : RspData <= Data0; + `DATA1 : RspData <= Data1; + `DATA2 : RspData <= Data2; + `DATA3 : RspData <= Data3; + endcase + RspOP <= `OP_SUCCESS; + State <= ACK; + end + + W_DATA : begin + if (Busy) + CmdErr <= ~|CmdErr ? `CMDERR_BUSY : CmdErr; + RspOP <= `OP_SUCCESS; + State <= ACK; + end + + W_DMCONTROL : begin + // While an abstract command is executing (busy in abstractcs is high), a debugger must not change + // hartsel, and must not write 1 to haltreq, resumereq, ackhavereset, setresethaltreq, or clrresethaltreq + if (Busy && (ReqData[`HALTREQ] || ReqData[`RESUMEREQ] || ReqData[`SETRESETHALTREQ] || ReqData[`CLRRESETHALTREQ])) + CmdErr <= ~|CmdErr ? `CMDERR_BUSY : CmdErr; + else begin + HaltReq <= ReqData[`HALTREQ]; + AckUnavail <= ReqData[`ACKUNAVAIL]; + NdmReset <= ReqData[`NDMRESET]; + DmActive <= ReqData[`DMACTIVE]; // Writing 0 here resets the DM + + // On any given write, a debugger may only write 1 to at most one of the following bits: resumereq, + // hartreset, ackhavereset, setresethaltreq, and clrresethaltreq. The others must be written 0 + case ({ReqData[`RESUMEREQ],ReqData[`SETRESETHALTREQ],ReqData[`CLRRESETHALTREQ]}) + 3'b000 :; // None + 3'b100 : ResumeReq <= 1; + 3'b010 : HaltOnReset <= 1; + 3'b001 : HaltOnReset <= 0; + default : begin // Invalid (not onehot), dont write any changes + HaltReq <= HaltReq; + AckUnavail <= AckUnavail; + NdmReset <= NdmReset; + DmActive <= DmActive; end - end - - ACK : begin - NewAcState <= AC_IDLE; - ResumeReq <= 0; - if (~ReqValid) - State <= ~DmActive ? INACTIVE : IDLE; - end - - IDLE : begin - if (ReqValid) - case ({ReqOP, ReqAddress}) inside - {`OP_WRITE,`DATA0} : State <= W_DATA; - {`OP_READ,`DATA0} : State <= R_DATA; - {`OP_WRITE,`DATA1} : State <= (P.XLEN >= 64) ? W_DATA : INVALID; - {`OP_READ,`DATA1} : State <= (P.XLEN >= 64) ? R_DATA : INVALID; - [{`OP_WRITE,`DATA2}:{`OP_WRITE,`DATA3}] : State <= (P.XLEN >= 128) ? W_DATA : INVALID; - [{`OP_READ,`DATA2}:{`OP_READ,`DATA3}] : State <= (P.XLEN >= 128) ? R_DATA : INVALID; - {`OP_WRITE,`DMCONTROL} : State <= W_DMCONTROL; - {`OP_READ,`DMCONTROL} : State <= R_DMCONTROL; - {`OP_READ,`DMSTATUS} : State <= DMSTATUS; - {`OP_WRITE,`ABSTRACTCS} : State <= W_ABSTRACTCS; - {`OP_READ,`ABSTRACTCS} : State <= R_ABSTRACTCS; - {`OP_WRITE,`COMMAND} : State <= ABST_COMMAND; - {`OP_READ,`COMMAND} : State <= READ_ZERO; - {`OP_WRITE,`SBCS} : State <= READ_ZERO; - {`OP_READ,`SBCS} : State <= R_SYSBUSCS; - {2'bx,`HARTINFO}, - {2'bx,`ABSTRACTAUTO}, - {2'bx,`NEXTDM} : State <= READ_ZERO; - default : State <= INVALID; - endcase - end - - R_DATA : begin - if (Busy) - CmdErr <= ~|CmdErr ? `CMDERR_BUSY : CmdErr; - case (ReqAddress) - `DATA0 : RspData <= Data0; - `DATA1 : RspData <= Data1; - `DATA2 : RspData <= Data2; - `DATA3 : RspData <= Data3; - endcase - RspOP <= `OP_SUCCESS; - State <= ACK; - end - - W_DATA : begin - if (Busy) - CmdErr <= ~|CmdErr ? `CMDERR_BUSY : CmdErr; - RspOP <= `OP_SUCCESS; - State <= ACK; - end - - W_DMCONTROL : begin - // While an abstract command is executing (busy in abstractcs is high), a debugger must not change - // hartsel, and must not write 1 to haltreq, resumereq, ackhavereset, setresethaltreq, or clrresethaltreq - if (Busy & (ReqData[`HALTREQ] | ReqData[`RESUMEREQ] | ReqData[`SETRESETHALTREQ] | ReqData[`CLRRESETHALTREQ])) - CmdErr <= ~|CmdErr ? `CMDERR_BUSY : CmdErr; - else begin - HaltReq <= ReqData[`HALTREQ]; - AckUnavail <= ReqData[`ACKUNAVAIL]; - NdmReset <= ReqData[`NDMRESET]; - DmActive <= ReqData[`DMACTIVE]; // Writing 0 here resets the DM - - // On any given write, a debugger may only write 1 to at most one of the following bits: resumereq, - // hartreset, ackhavereset, setresethaltreq, and clrresethaltreq. The others must be written 0 - case ({ReqData[`RESUMEREQ],ReqData[`SETRESETHALTREQ],ReqData[`CLRRESETHALTREQ]}) - 3'b000 :; // None - 3'b100 : ResumeReq <= 1; - 3'b010 : HaltOnReset <= 1; - 3'b001 : HaltOnReset <= 0; - default : begin // Invalid (not onehot), dont write any changes - HaltReq <= HaltReq; - AckUnavail <= AckUnavail; - NdmReset <= NdmReset; - DmActive <= DmActive; - end - endcase + endcase + end + + RspOP <= `OP_SUCCESS; + State <= ACK; + end + + R_DMCONTROL : begin + RspData <= DMControl; + RspOP <= `OP_SUCCESS; + State <= ACK; + end + + DMSTATUS : begin + RspData <= DMStatus; + RspOP <= `OP_SUCCESS; + State <= ACK; + end + + W_ABSTRACTCS : begin + if (Busy) + CmdErr <= ~|CmdErr ? `CMDERR_BUSY : CmdErr; + else + CmdErr <= |ReqData[`CMDERR] ? `CMDERR_NONE : CmdErr; // clear CmdErr + RspOP <= `OP_SUCCESS; + State <= ACK; + end + + R_ABSTRACTCS : begin + RspData <= AbstractCS; + RspOP <= `OP_SUCCESS; + State <= ACK; + end + + ABST_COMMAND : begin + if (CmdErr != `CMDERR_NONE); // If CmdErr, do nothing + else if (Busy) + CmdErr <= `CMDERR_BUSY; // If Busy, set CmdErr, do nothing + else if (~Halted) + CmdErr <= `CMDERR_HALTRESUME; // If not halted, set CmdErr, do nothing + else begin + case (ReqData[`CMDTYPE]) + `ACCESS_REGISTER : begin + if (ReqData[`AARSIZE] > $clog2(P.XLEN/8)) // if AARSIZE (encoded) is greater than P.XLEN, set CmdErr, do nothing + CmdErr <= `CMDERR_BUS; + else if (~ReqData[`TRANSFER]); // If not TRANSFER, do nothing + else if (InvalidRegNo) + CmdErr <= `CMDERR_EXCEPTION; // If InvalidRegNo, set CmdErr, do nothing + else if (ReqData[`AARWRITE] && RegReadOnly) + CmdErr <= `CMDERR_NOT_SUPPORTED; // If writing to a read only register, set CmdErr, do nothing + else begin + AcWrite <= ReqData[`AARWRITE]; + NewAcState <= AC_SCAN; + end end - - RspOP <= `OP_SUCCESS; - State <= ACK; - end - - R_DMCONTROL : begin - RspData <= DMControl; - RspOP <= `OP_SUCCESS; - State <= ACK; - end - - DMSTATUS : begin - RspData <= DMStatus; - RspOP <= `OP_SUCCESS; - State <= ACK; - end - - W_ABSTRACTCS : begin - if (Busy) - CmdErr <= ~|CmdErr ? `CMDERR_BUSY : CmdErr; - else - CmdErr <= |ReqData[`CMDERR] ? `CMDERR_NONE : CmdErr; // clear CmdErr - RspOP <= `OP_SUCCESS; - State <= ACK; - end - - R_ABSTRACTCS : begin - RspData <= AbstractCS; - RspOP <= `OP_SUCCESS; - State <= ACK; - end - - ABST_COMMAND : begin - if (CmdErr != `CMDERR_NONE); // If CmdErr, do nothing - else if (Busy) - CmdErr <= `CMDERR_BUSY; // If Busy, set CmdErr, do nothing - else if (~Halted) - CmdErr <= `CMDERR_HALTRESUME; // If not halted, set CmdErr, do nothing - else begin - case (ReqData[`CMDTYPE]) - `ACCESS_REGISTER : begin - if (ReqData[`AARSIZE] > $clog2(P.XLEN/8)) // if AARSIZE (encoded) is greater than P.XLEN, set CmdErr, do nothing - CmdErr <= `CMDERR_BUS; - else if (~ReqData[`TRANSFER]); // If not TRANSFER, do nothing - else if (InvalidRegNo) - CmdErr <= `CMDERR_EXCEPTION; // If InvalidRegNo, set CmdErr, do nothing - else if (ReqData[`AARWRITE] & RegReadOnly) - CmdErr <= `CMDERR_NOT_SUPPORTED; // If writing to a read only register, set CmdErr, do nothing - else begin - AcWrite <= ReqData[`AARWRITE]; - NewAcState <= AC_SCAN; - end - end - //`QUICK_ACCESS : State <= QUICK_ACCESS; - //`ACCESS_MEMORY : State <= ACCESS_MEMORY; - default : CmdErr <= `CMDERR_NOT_SUPPORTED; - endcase - end - RspOP <= `OP_SUCCESS; - State <= ACK; - end - - R_SYSBUSCS : begin - RspData <= SysBusCS; - RspOP <= `OP_SUCCESS; - State <= ACK; - end - - READ_ZERO : begin // Writes ignored, Read Zero - RspData <= 0; - RspOP <= `OP_SUCCESS; - State <= ACK; - end - - INVALID : begin - RspOP <= `OP_FAILED; - State <= ACK; - end - endcase - end - end - - // Abstract command engine - // Due to length of the register scan chain, - // abstract commands execute independently of other DM operations - always_ff @(posedge clk) begin - if (rst) - AcState <= AC_IDLE; - else begin - case (AcState) - AC_IDLE : begin - Cycle <= 0; - case (NewAcState) - AC_SCAN : AcState <= ~AcWrite ? AC_CAPTURE : AC_SCAN; - endcase - end - - AC_CAPTURE : begin - AcState <= AC_SCAN; - end - - AC_SCAN : begin - if (Cycle == ScanChainLen) - AcState <= (GPRRegNo & AcWrite) ? AC_GPRUPDATE : AC_IDLE; - else - Cycle <= Cycle + 1; - end - - AC_GPRUPDATE : begin - AcState <= AC_IDLE; - end - endcase - end - end - - assign Busy = ~(AcState == AC_IDLE); - assign DebugCapture = (AcState == AC_CAPTURE); - assign DebugGPRUpdate = (AcState == AC_GPRUPDATE); - - // Scan Chain - assign GPRSel = GPRRegNo & (AcState != AC_IDLE); - assign ScanReg[P.XLEN] = GPRSel ? GPRScanIn : ScanIn; - assign ScanOut = GPRSel ? 1'b0 : ScanReg[0]; - assign GPRScanOut = GPRSel ? ScanReg[0] : 1'b0; - assign ScanEn = ~GPRSel & (AcState == AC_SCAN); - assign GPRScanEn = GPRSel & (AcState == AC_SCAN); - - // Load data from message registers into scan chain - if (P.XLEN == 32) - assign PackedDataReg = Data0; - else if (P.XLEN == 64) - assign PackedDataReg = {Data1,Data0}; - else if (P.XLEN == 128) - assign PackedDataReg = {Data3,Data2,Data1,Data0}; - - assign WriteScanReg = AcWrite & (~GPRRegNo & (Cycle == ShiftCount) | GPRRegNo & (Cycle == 0)); - genvar i; - for (i=0; i= 64) begin - assign Data1Wr = StoreScanChain ? MaskedScanReg[63:32] : ReqData; - flopenr #(32) data1reg (.clk, .reset(rst), .en(StoreScanChain | WriteMsgReg & (ReqAddress == `DATA1)), .d(Data1Wr), .q(Data1)); - end - if (P.XLEN == 128) begin - assign Data2Wr = StoreScanChain ? MaskedScanReg[95:64] : ReqData; - assign Data3Wr = StoreScanChain ? MaskedScanReg[127:96] : ReqData; - flopenr #(32) data2reg (.clk, .reset(rst), .en(StoreScanChain | WriteMsgReg & (ReqAddress == `DATA2)), .d(Data2Wr), .q(Data2)); - flopenr #(32) data3reg (.clk, .reset(rst), .en(StoreScanChain | WriteMsgReg & (ReqAddress == `DATA3)), .d(Data3Wr), .q(Data3)); - end - - rad #(P) regnodecode(.AarSize(ReqData[`AARSIZE]),.Regno(ReqData[`REGNO]),.GPRRegNo,.ScanChainLen,.ShiftCount,.InvalidRegNo,.RegReadOnly,.GPRAddr,.ARMask); + //`QUICK_ACCESS : State <= QUICK_ACCESS; + //`ACCESS_MEMORY : State <= ACCESS_MEMORY; + default : CmdErr <= `CMDERR_NOT_SUPPORTED; + endcase + end + RspOP <= `OP_SUCCESS; + State <= ACK; + end + + R_SYSBUSCS : begin + RspData <= SysBusCS; + RspOP <= `OP_SUCCESS; + State <= ACK; + end + + READ_ZERO : begin // Writes ignored, Read Zero + RspData <= 0; + RspOP <= `OP_SUCCESS; + State <= ACK; + end + + INVALID : begin + RspOP <= `OP_FAILED; + State <= ACK; + end + endcase + end + end + + + // Abstract command engine + // Due to length of the register scan chain, + // abstract commands execute independently of other DM operations + always_ff @(posedge clk) begin + if (rst) + AcState <= AC_IDLE; + else begin + case (AcState) + AC_IDLE : begin + Cycle <= 0; + case (NewAcState) + AC_SCAN : AcState <= ~AcWrite ? AC_CAPTURE : AC_SCAN; + endcase + end + + AC_CAPTURE : begin + AcState <= AC_SCAN; + end + + AC_SCAN : begin + if (Cycle == ScanChainLen) + AcState <= (GPRRegNo && AcWrite) ? AC_GPRUPDATE : AC_IDLE; + else + Cycle <= Cycle + 1; + end + + AC_GPRUPDATE : begin + AcState <= AC_IDLE; + end + endcase + end + end + + assign Busy = ~(AcState == AC_IDLE); + assign DebugCapture = (AcState == AC_CAPTURE); + assign DebugGPRUpdate = (AcState == AC_GPRUPDATE); + + // Scan Chain + assign GPRSel = GPRRegNo && (AcState != AC_IDLE); + assign ScanReg[P.XLEN] = GPRSel ? GPRScanIn : ScanIn; + assign ScanOut = GPRSel ? 1'b0 : ScanReg[0]; + assign GPRScanOut = GPRSel ? ScanReg[0] : 1'b0; + assign ScanEn = ~GPRSel && (AcState == AC_SCAN); + assign GPRScanEn = GPRSel && (AcState == AC_SCAN); + + // Load data from message registers into scan chain + if (P.XLEN == 32) + assign PackedDataReg = Data0; + else if (P.XLEN == 64) + assign PackedDataReg = {Data1,Data0}; + else if (P.XLEN == 128) + assign PackedDataReg = {Data3,Data2,Data1,Data0}; + + assign WriteScanReg = AcWrite && (~GPRRegNo && (Cycle == ShiftCount) || GPRRegNo && (Cycle == 0)); + genvar i; + for (i=0; i= 64) begin + assign Data1Wr = StoreScanChain ? MaskedScanReg[63:32] : ReqData; + flopenr #(32) data1reg (.clk, .reset(rst), .en(StoreScanChain || WriteMsgReg && (ReqAddress == `DATA1)), .d(Data1Wr), .q(Data1)); + end + if (P.XLEN == 128) begin + assign Data2Wr = StoreScanChain ? MaskedScanReg[95:64] : ReqData; + assign Data3Wr = StoreScanChain ? MaskedScanReg[127:96] : ReqData; + flopenr #(32) data2reg (.clk, .reset(rst), .en(StoreScanChain || WriteMsgReg && (ReqAddress == `DATA2)), .d(Data2Wr), .q(Data2)); + flopenr #(32) data3reg (.clk, .reset(rst), .en(StoreScanChain || WriteMsgReg && (ReqAddress == `DATA3)), .d(Data3Wr), .q(Data3)); + end + + rad #(P) regnodecode(.AarSize(ReqData[`AARSIZE]),.Regno(ReqData[`REGNO]),.GPRRegNo,.ScanChainLen,.ShiftCount,.InvalidRegNo,.RegReadOnly,.GPRAddr,.ARMask); + endmodule diff --git a/src/debug/dtm.sv b/src/debug/dtm.sv index 2ecd1ad72..b3a7a36e8 100644 --- a/src/debug/dtm.sv +++ b/src/debug/dtm.sv @@ -51,113 +51,114 @@ module dtm #(parameter ADDR_WIDTH, parameter JTAG_DEVICE_ID) ( ); `include "debug.vh" - enum logic [1:0] {IDLE, START, WAIT, COMPLETE} DMIState; + enum logic [1:0] {IDLE, START, WAIT, COMPLETE} DMIState; - // Clock Domain Crossing - logic tcks; // Synchronized JTAG clock - logic resetn; - logic UpdateDtmcs; - logic [31:0] DtmcsIn; - logic [31:0] DtmcsOut; - logic UpdateDmi; - logic CaptureDmi; - logic [34+ADDR_WIDTH-1:0] DmiIn; - logic [34+ADDR_WIDTH-1:0] DmiOut; - - // DTMCS Register - const logic [2:0] ErrInfo = 0; - logic DtmHardReset; - logic DmiReset; - const logic [2:0] Idle = 0; - logic [1:0] DmiStat; - const logic [5:0] ABits = ADDR_WIDTH; - const logic [3:0] Version = 1; // DTM spec version 1 - - logic [31:0] ValRspData; - logic [1:0] ValRspOP; - logic Sticky; - - assign DmiOut = {ReqAddress, ValRspData, ValRspOP}; - assign DmiStat = ValRspOP; - - // Synchronize the edges of tck to the system clock - synchronizer clksync (.clk(clk), .d(tck), .q(tcks)); - - jtag #(.ADDR_WIDTH(ADDR_WIDTH), .DEVICE_ID(JTAG_DEVICE_ID)) jtag (.tck(tcks), .tdi, .tms, .tdo, + // Clock Domain Crossing + logic tcks; // Synchronized JTAG clock + logic resetn; + logic UpdateDtmcs; + logic [31:0] DtmcsIn; + logic [31:0] DtmcsOut; + logic UpdateDmi; + logic CaptureDmi; + logic [34+ADDR_WIDTH-1:0] DmiIn; + logic [34+ADDR_WIDTH-1:0] DmiOut; + + // DTMCS Register + const logic [2:0] ErrInfo = 0; + logic DtmHardReset; + logic DmiReset; + const logic [2:0] Idle = 0; + logic [1:0] DmiStat; + const logic [5:0] ABits = ADDR_WIDTH; + const logic [3:0] Version = 1; // DTM spec version 1 + + logic [31:0] ValRspData; + logic [1:0] ValRspOP; + logic Sticky; + + assign DmiOut = {ReqAddress, ValRspData, ValRspOP}; + assign DmiStat = ValRspOP; + + // Synchronize the edges of tck to the system clock + synchronizer clksync (.clk(clk), .d(tck), .q(tcks)); + + jtag #(.ADDR_WIDTH(ADDR_WIDTH), .DEVICE_ID(JTAG_DEVICE_ID)) jtag (.tck(tcks), .tdi, .tms, .tdo, .resetn, .UpdateDtmcs, .DtmcsIn, .DtmcsOut, .CaptureDmi, .UpdateDmi, .DmiIn, .DmiOut); - // DTMCS - assign DtmcsOut = {11'b0, ErrInfo, 3'b0, Idle, DmiStat, ABits, Version}; - always_ff @(posedge clk) begin - if (~resetn | DtmHardReset) begin - DtmHardReset <= 0; - DmiReset <= 0; - end else if (UpdateDtmcs) begin - DtmHardReset <= DtmcsIn[17]; - DmiReset <= DtmcsIn[16]; - end else if (DmiReset) begin - DmiReset <= 0; - end - end - - // DMI - always_ff @(posedge clk) begin - if (~resetn | DtmHardReset) begin - ValRspData <= 0; - ValRspOP <= `OP_SUCCESS; - //ErrInfo <= 4; - Sticky <= 0; - DMIState <= IDLE; - end else if (DmiReset) begin - ValRspOP <= `OP_SUCCESS; - //ErrInfo <= 4; - Sticky <= 0; - end else - case (DMIState) - IDLE : begin - if (UpdateDmi & ~Sticky & DmiIn[1:0] != `OP_NOP) begin - {ReqAddress, ReqData, ReqOP} <= DmiIn; - ReqValid <= 1; - // DmiOut is captured immediately on CaptureDmi - // this preemptively sets BUSY for next capture unless overwritten - ValRspOP <= `OP_BUSY; - DMIState <= START; - end else begin - ReqValid <= 0; - if (~Sticky) - ValRspOP <= `OP_SUCCESS; - end - end - - START : begin - if (ReqReady) begin - ReqValid <= 0; - RspReady <= 1; - DMIState <= WAIT; - end - end - - WAIT : begin - if (RspValid) begin - ValRspData <= RspData; - if (~Sticky) // update OP if it isn't currently a sticky value - ValRspOP <= RspOP; - if (RspOP == `OP_FAILED | RspOP == `OP_BUSY) - Sticky <= 1; - //if (RspOP == `OP_FAILED) - // ErrInfo <= 3; - DMIState <= COMPLETE; - end else if (CaptureDmi) - Sticky <= 1; - end - COMPLETE : begin - if (CaptureDmi) begin - RspReady <= 0; - DMIState <= IDLE; - end + // DTMCS + assign DtmcsOut = {11'b0, ErrInfo, 3'b0, Idle, DmiStat, ABits, Version}; + always_ff @(posedge clk) begin + if (~resetn | DtmHardReset) begin + DtmHardReset <= 0; + DmiReset <= 0; + end else if (UpdateDtmcs) begin + DtmHardReset <= DtmcsIn[17]; + DmiReset <= DtmcsIn[16]; + end else if (DmiReset) begin + DmiReset <= 0; + end + end + + // DMI + always_ff @(posedge clk) begin + if (~resetn | DtmHardReset) begin + ValRspData <= 0; + ValRspOP <= `OP_SUCCESS; + //ErrInfo <= 4; + Sticky <= 0; + DMIState <= IDLE; + end else if (DmiReset) begin + ValRspOP <= `OP_SUCCESS; + //ErrInfo <= 4; + Sticky <= 0; + end else + case (DMIState) + IDLE : begin + if (UpdateDmi & ~Sticky & DmiIn[1:0] != `OP_NOP) begin + {ReqAddress, ReqData, ReqOP} <= DmiIn; + ReqValid <= 1; + // DmiOut is captured immediately on CaptureDmi + // this preemptively sets BUSY for next capture unless overwritten + ValRspOP <= `OP_BUSY; + DMIState <= START; + end else begin + ReqValid <= 0; + if (~Sticky) + ValRspOP <= `OP_SUCCESS; end - endcase - end - + end + + START : begin + if (ReqReady) begin + ReqValid <= 0; + RspReady <= 1; + DMIState <= WAIT; + end + end + + WAIT : begin + if (RspValid) begin + ValRspData <= RspData; + if (~Sticky) // update OP if it isn't currently a sticky value + ValRspOP <= RspOP; + if (RspOP == `OP_FAILED | RspOP == `OP_BUSY) + Sticky <= 1; + //if (RspOP == `OP_FAILED) + // ErrInfo <= 3; + DMIState <= COMPLETE; + end else if (CaptureDmi) + Sticky <= 1; + end + + COMPLETE : begin + if (CaptureDmi) begin + RspReady <= 0; + DMIState <= IDLE; + end + end + endcase + end + endmodule diff --git a/src/debug/ir.sv b/src/debug/ir.sv index dd99c7cc1..767430884 100644 --- a/src/debug/ir.sv +++ b/src/debug/ir.sv @@ -49,12 +49,12 @@ module ir ( // Shift register always @(posedge clockIR) begin - shift_reg[0] <= shift_reg[1] | captureIR; + shift_reg[0] <= shift_reg[1] || captureIR; end genvar i; for (i = INST_REG_WIDTH; i > 1; i = i - 1) begin always @(posedge clockIR) begin - shift_reg[i-1] <= shift_reg[i] & ~captureIR; + shift_reg[i-1] <= shift_reg[i] && ~captureIR; end end diff --git a/src/debug/jtag.sv b/src/debug/jtag.sv index edb63f8f8..221f4eb40 100644 --- a/src/debug/jtag.sv +++ b/src/debug/jtag.sv @@ -47,90 +47,90 @@ module jtag #(parameter ADDR_WIDTH, parameter DEVICE_ID) ( genvar i; // Data signals - logic tdi_ir, tdi_dr; - logic tdo_ir, tdo_dr; - logic tdo_bypass; - logic tdo_idcode; - logic tdo_dtmcs; - logic tdo_dmi; - - // TAP controller logic - logic tdo_en; - logic captureIR; - logic clockIR; - logic updateIR; - logic shiftDR; - logic captureDR; - logic clockDR; - logic updateDR; - logic select; - - // Instruction signals - logic BypassInstr; - logic IDCodeInstr; - logic DtmcsIntrs; - logic DmiInstr; - - logic [32:0] DtmcsShiftReg; - logic [34+ADDR_WIDTH:0] DmiShiftReg; - - assign UpdateDtmcs = updateDR & DtmcsIntrs; - - assign CaptureDmi = captureDR & DmiInstr; - assign UpdateDmi = updateDR & DmiInstr; - - tap tap (.tck, .tms, .resetn, .tdo_en, .captureIR, - .clockIR, .updateIR, .shiftDR, .captureDR, .clockDR, .updateDR, .select); - - // IR/DR input demux - assign tdi_ir = select ? tdi : 1'bz; - assign tdi_dr = select ? 1'bz : tdi; - // IR/DR output mux - assign tdo = ~tdo_en ? 1'bz : - select ? tdo_ir : tdo_dr; - - ir ir (.clockIR, .tdi(tdi_ir), .resetn, .captureIR, .updateIR, .tdo(tdo_ir), - .BypassInstr, .IDCodeInstr, .DtmcsIntrs, .DmiInstr); - - // DR demux - always_comb begin - unique case ({BypassInstr, IDCodeInstr, DtmcsIntrs, DmiInstr}) - 4'b1000 : tdo_dr <= tdo_bypass; - 4'b0100 : tdo_dr <= tdo_idcode; - 4'b0010 : tdo_dr <= tdo_dtmcs; - 4'b0001 : tdo_dr <= tdo_dmi; - default : tdo_dr <= tdo_bypass; - endcase - end - - always_ff @(posedge UpdateDtmcs) - DtmcsIn <= DtmcsShiftReg[31:0]; - - always_ff @(posedge UpdateDmi) - DmiIn <= DmiShiftReg[34+ADDR_WIDTH-1:0]; - - assign DtmcsShiftReg[32] = tdi_dr; - assign tdo_dtmcs = DtmcsShiftReg[0]; - for (i = 0; i < 32; i = i + 1) begin - always_ff @(posedge clockDR) begin - DtmcsShiftReg[i] <= captureDR ? DtmcsOut[i] : DtmcsShiftReg[i+1]; - end - end - - assign DmiShiftReg[34+ADDR_WIDTH] = tdi_dr; - assign tdo_dmi = DmiShiftReg[0]; - for (i = 0; i < 34+ADDR_WIDTH; i = i + 1) begin - always_ff @(posedge clockDR) begin - DmiShiftReg[i] <= captureDR ? DmiOut[i] : DmiShiftReg[i+1]; - end - end + logic tdi_ir, tdi_dr; + logic tdo_ir, tdo_dr; + logic tdo_bypass; + logic tdo_idcode; + logic tdo_dtmcs; + logic tdo_dmi; + + // TAP controller logic + logic tdo_en; + logic captureIR; + logic clockIR; + logic updateIR; + logic shiftDR; + logic captureDR; + logic clockDR; + logic updateDR; + logic select; + + // Instruction signals + logic BypassInstr; + logic IDCodeInstr; + logic DtmcsIntrs; + logic DmiInstr; + + logic [32:0] DtmcsShiftReg; + logic [34+ADDR_WIDTH:0] DmiShiftReg; + + assign UpdateDtmcs = updateDR & DtmcsIntrs; + + assign CaptureDmi = captureDR & DmiInstr; + assign UpdateDmi = updateDR & DmiInstr; + + tap tap (.tck, .tms, .resetn, .tdo_en, .captureIR, + .clockIR, .updateIR, .shiftDR, .captureDR, .clockDR, .updateDR, .select); + + // IR/DR input demux + assign tdi_ir = select ? tdi : 1'bz; + assign tdi_dr = select ? 1'bz : tdi; + // IR/DR output mux + assign tdo = ~tdo_en ? 1'bz : + select ? tdo_ir : tdo_dr; + + ir ir (.clockIR, .tdi(tdi_ir), .resetn, .captureIR, .updateIR, .tdo(tdo_ir), + .BypassInstr, .IDCodeInstr, .DtmcsIntrs, .DmiInstr); + + // DR demux + always_comb begin + unique case ({BypassInstr, IDCodeInstr, DtmcsIntrs, DmiInstr}) + 4'b1000 : tdo_dr <= tdo_bypass; + 4'b0100 : tdo_dr <= tdo_idcode; + 4'b0010 : tdo_dr <= tdo_dtmcs; + 4'b0001 : tdo_dr <= tdo_dmi; + default : tdo_dr <= tdo_bypass; + endcase + end + + always_ff @(posedge UpdateDtmcs) + DtmcsIn <= DtmcsShiftReg[31:0]; + + always_ff @(posedge UpdateDmi) + DmiIn <= DmiShiftReg[34+ADDR_WIDTH-1:0]; + + assign DtmcsShiftReg[32] = tdi_dr; + assign tdo_dtmcs = DtmcsShiftReg[0]; + for (i = 0; i < 32; i = i + 1) begin + always_ff @(posedge clockDR) begin + DtmcsShiftReg[i] <= captureDR ? DtmcsOut[i] : DtmcsShiftReg[i+1]; + end + end + + assign DmiShiftReg[34+ADDR_WIDTH] = tdi_dr; + assign tdo_dmi = DmiShiftReg[0]; + for (i = 0; i < 34+ADDR_WIDTH; i = i + 1) begin + always_ff @(posedge clockDR) begin + DmiShiftReg[i] <= captureDR ? DmiOut[i] : DmiShiftReg[i+1]; + end + end + + // jtag id register + idreg #(DEVICE_ID) id (.tdi(tdi_dr), .clockDR, .captureDR, .tdo(tdo_idcode)); + + // bypass register + always_ff @(posedge clockDR) begin + tdo_bypass <= tdi_dr & shiftDR; + end - // jtag id register - idreg #(DEVICE_ID) id (.tdi(tdi_dr), .clockDR, .captureDR, .tdo(tdo_idcode)); - - // bypass register - always_ff @(posedge clockDR) begin - tdo_bypass <= tdi_dr & shiftDR; - end - endmodule diff --git a/src/hazard/hazard.sv b/src/hazard/hazard.sv index 5d2611dda..ea63fc06e 100644 --- a/src/hazard/hazard.sv +++ b/src/hazard/hazard.sv @@ -28,20 +28,21 @@ //////////////////////////////////////////////////////////////////////////////////////////////// module hazard import cvw::*; #(parameter cvw_t P) ( - input logic BPWrongE, CSRWriteFenceM, RetM, TrapM, - input logic StructuralStallD, - input logic LSUStallM, IFUStallF, - input logic FPUStallD, - input logic DivBusyE, FDivBusyE, - input logic wfiM, IntPendingM, + input logic BPWrongE, CSRWriteFenceM, RetM, TrapM, + input logic StructuralStallD, + input logic LSUStallM, IFUStallF, + input logic FPUStallD, + input logic DivBusyE, FDivBusyE, + input logic wfiM, IntPendingM, + input logic DebugStall, // Stall & flush outputs output logic StallF, StallD, StallE, StallM, StallW, output logic FlushD, FlushE, FlushM, FlushW ); - logic StallFCause, StallDCause, StallECause, StallMCause, StallWCause; - logic LatestUnstalledD, LatestUnstalledE, LatestUnstalledM, LatestUnstalledW; - logic FlushDCause, FlushECause, FlushMCause, FlushWCause; + logic StallFCause, StallDCause, StallECause, StallMCause, StallWCause; + logic LatestUnstalledD, LatestUnstalledE, LatestUnstalledM, LatestUnstalledW; + logic FlushDCause, FlushECause, FlushMCause, FlushWCause; logic WFIStallM, WFIInterruptedM; @@ -89,7 +90,7 @@ module hazard import cvw::*; #(parameter cvw_t P) ( // Need to gate IFUStallF when the equivalent FlushFCause = FlushDCause = 1. // assign StallWCause = ((IFUStallF & ~FlushDCause) | LSUStallM) & ~FlushWCause; // Because FlushWCause is a strict subset of FlushDCause, FlushWCause is factored out. - assign StallWCause = (IFUStallF & ~FlushDCause) | (LSUStallM & ~FlushWCause); + assign StallWCause = (IFUStallF & ~FlushDCause) | (LSUStallM & ~FlushWCause) | DebugStall; // Stall each stage for cause or if the next stage is stalled // coverage off: StallFCause is always 0 @@ -107,8 +108,9 @@ module hazard import cvw::*; #(parameter cvw_t P) ( assign LatestUnstalledW = ~StallW & StallM; // Each stage flushes if the previous stage is the last one stalled (for cause) or the system has reason to flush - assign FlushD = LatestUnstalledD | FlushDCause; - assign FlushE = LatestUnstalledE | FlushECause; - assign FlushM = LatestUnstalledM | FlushMCause; - assign FlushW = LatestUnstalledW | FlushWCause; + // Do not flush if halted for Debug + assign FlushD = ~DebugStall & (LatestUnstalledD | FlushDCause); + assign FlushE = ~DebugStall & (LatestUnstalledE | FlushECause); + assign FlushM = ~DebugStall & (LatestUnstalledM | FlushMCause); + assign FlushW = ~DebugStall & (LatestUnstalledW | FlushWCause); endmodule diff --git a/src/ieu/controller.sv b/src/ieu/controller.sv index cbaa918b7..54b295b6e 100644 --- a/src/ieu/controller.sv +++ b/src/ieu/controller.sv @@ -93,7 +93,11 @@ module controller import cvw::*; #(parameter cvw_t P) ( output logic CSRWriteFenceM, // CSR write or fence instruction; needs to flush the following instructions output logic [4:0] RdE, RdM, // Pipelined destination registers // Forwarding controls - output logic [4:0] RdW // Register destinations in Execute, Memory, or Writeback stage + output logic [4:0] RdW, // Register destinations in Execute, Memory, or Writeback stage + // Debug scan chain + input logic DebugScanEn, + input logic DebugScanIn, + output logic DebugScanOut ); logic [4:0] Rs1E; // pipelined register sources @@ -452,11 +456,6 @@ module controller import cvw::*; #(parameter cvw_t P) ( {RegWriteE, ResultSrcE, MemRWE, CSRReadE, CSRWriteE, PrivilegedE, Funct3E, FWriteIntE, AtomicE, InvalidateICacheE, FlushDCacheE, FenceE, InstrValidE, IntDivE, CMOpE, LSUPrefetchE}, {RegWriteM, ResultSrcM, MemRWM, CSRReadM, CSRWriteM, PrivilegedM, Funct3M, FWriteIntM, AtomicM, InvalidateICacheM, FlushDCacheM, FenceM, InstrValidM, IntDivM, CMOpM, LSUPrefetchM}); end - - // FIXME: delete once working - //flopenrc #(25) controlregM(clk, reset, FlushM, ~StallM, - // {RegWriteE, ResultSrcE, MemRWE, CSRReadE, CSRWriteE, PrivilegedE, Funct3E, FWriteIntE, AtomicE, InvalidateICacheE, FlushDCacheE, FenceE, InstrValidE, IntDivE, CMOpE, LSUPrefetchE}, - // {RegWriteM, ResultSrcM, MemRWM, CSRReadM, CSRWriteM, PrivilegedM, Funct3M, FWriteIntM, AtomicM, InvalidateICacheM, FlushDCacheM, FenceM, InstrValidM, IntDivM, CMOpM, LSUPrefetchM}); flopenrc #(5) RdMReg(clk, reset, FlushM, ~StallM, RdE, RdM); // Writeback stage pipeline control register diff --git a/src/ieu/datapath.sv b/src/ieu/datapath.sv index 6272ea615..4bddcf8cd 100644 --- a/src/ieu/datapath.sv +++ b/src/ieu/datapath.sv @@ -33,7 +33,7 @@ module datapath import cvw::*; #(parameter cvw_t P) ( // Decode stage signals input logic [2:0] ImmSrcD, // Selects type of immediate extension input logic [31:0] InstrD, // Instruction in Decode stage - input logic [4:0] Rs1D, Rs2D, Rs2E, // Source registers + input logic [4:0] Rs1D, Rs2D, Rs2E, // Source registers // Execute stage signals input logic [P.XLEN-1:0] PCE, // PC in Execute stage input logic [P.XLEN-1:0] PCLinkE, // PC + 4 (of instruction in Execute stage) @@ -74,7 +74,7 @@ module datapath import cvw::*; #(parameter cvw_t P) ( input logic [P.XLEN-1:0] FIntDivResultW, // FPU's integer divide result input logic [4:0] RdW, // Destination register // Hazard Unit signals - // Debug scan chain + // Debug scan chain input logic DebugScanEn, input logic DebugScanIn, output logic DebugScanOut, @@ -84,12 +84,12 @@ module datapath import cvw::*; #(parameter cvw_t P) ( input logic [P.E_SUPPORTED+3:0] GPRAddr, input logic GPRScanEn, input logic GPRScanIn, - output logic GPRScanOut + output logic GPRScanOut ); // Fetch stage signals // Decode stage signals - logic [4:0] DB_Rs1D; // (Debug) Muxed source register + logic [4:0] Rs1DM; // (Debug) Muxed source register logic [P.XLEN-1:0] R1D, R2D; // Read data from Rs1 (RD1), Rs2 (RD2) logic [P.XLEN-1:0] ImmExtD; // Extended immediate in Decode stage logic [4:0] RdD; // Destination register in Decode stage @@ -104,27 +104,29 @@ module datapath import cvw::*; #(parameter cvw_t P) ( // Writeback stage signals logic RegWriteWM; // (Debug) Muxed write enable logic [P.XLEN-1:0] SCResultW; // Store Conditional result - logic [P.XLEN-1:0] ResultW; // Result to write to register file + logic [P.XLEN-1:0] ResultW; + logic [P.XLEN-1:0] ResultWM; // Result to write to register file + logic [4:0] RdWM; // Muxed GPR write address logic [P.XLEN-1:0] IFResultW; // Result from either IEU or single-cycle FPU op writing an integer register logic [P.XLEN-1:0] IFCvtResultW; // Result from IEU, signle-cycle FPU op, or 2-cycle FCVT float to int logic [P.XLEN-1:0] MulDivResultW; // Multiply always comes from MDU. Divide could come from MDU or FPU (when using fdivsqrt for integer division) - // Debug signals + // Debug signals + logic DSCR; logic [P.XLEN-1:0] DebugGPRWriteD; - + // Decode stage extend #(P) ext(.InstrD(InstrD[31:7]), .ImmSrcD, .ImmExtD); + // Access GPRs from Debug Module if (P.DEBUG_SUPPORTED) begin - regfile #(P.XLEN, P.E_SUPPORTED) regf(clk, reset, RegWriteWM, DB_Rs1D, Rs2D, RdWM, ResultWM, R1D, R2D); + regfile #(P.XLEN, P.E_SUPPORTED) regf(clk, reset, RegWriteWM, Rs1DM, Rs2D, RdWM, ResultWM, R1D, R2D); assign RegWriteWM = GPRSel ? DebugGPRUpdate : RegWriteW; - assign DB_Rs1D = GPRSel ? GPRAddr : Rs1D; + assign Rs1DM = GPRSel ? GPRAddr : Rs1D; assign RdWM = GPRSel ? GPRAddr : RdW; assign ResultWM = GPRSel ? DebugGPRWriteD : ResultW; flopenrs #(P.XLEN) GPRScanReg(.clk, .reset, .en(DebugCapture), .d(R1D), .q(DebugGPRWriteD), .scan(GPRScanEn), .scanin(GPRScanIn), .scanout(GPRScanOut)); end else begin regfile #(P.XLEN, P.E_SUPPORTED) regf(clk, reset, RegWriteW, Rs1D, Rs2D, RdW, ResultW, R1D, R2D); end - // FIXME: Delete once working - // regfile #(P.XLEN, P.E_SUPPORTED) regf(clk, reset, RegWriteW, Rs1D, Rs2D, RdW, ResultW, R1D, R2D); // Execute stage pipeline register and logic flopenrc #(P.XLEN) RD1EReg(clk, reset, FlushE, ~StallE, R1D, R1E); @@ -147,8 +149,6 @@ module datapath import cvw::*; #(parameter cvw_t P) ( flopenrcs #(P.XLEN) WriteDataMReg(clk, reset, FlushM, ~StallM, ForwardedSrcBE, WriteDataM, DebugScanEn, DebugScanIn, DebugScanOut); else flopenrc #(P.XLEN) WriteDataMReg(clk, reset, FlushM, ~StallM, ForwardedSrcBE, WriteDataM); - // FIXME: Delete once working - // flopenrc #(P.XLEN) WriteDataMReg(clk, reset, FlushM, ~StallM, ForwardedSrcBE, WriteDataM); // Writeback stage pipeline register and logic flopenrc #(P.XLEN) IFResultWReg(clk, reset, FlushW, ~StallW, IFResultM, IFResultW); diff --git a/src/ieu/ieu.sv b/src/ieu/ieu.sv index 38d50e3c3..93bffd913 100644 --- a/src/ieu/ieu.sv +++ b/src/ieu/ieu.sv @@ -78,7 +78,19 @@ module ieu import cvw::*; #(parameter cvw_t P) ( output logic LoadStallD, // Structural stalls for load, sent to performance counters output logic StoreStallD, // load after store hazard output logic CSRReadM, CSRWriteM, PrivilegedM,// CSR read, CSR write, is privileged instruction - output logic CSRWriteFenceM // CSR write or fence instruction needs to flush subsequent instructions + output logic CSRWriteFenceM, // CSR write or fence instruction needs to flush subsequent instructions + // Debug scan chain + input logic DebugScanEn, + input logic DebugScanIn, + output logic DebugScanOut, + // GPR debug scan chain + input logic GPRSel, + input logic DebugCapture, + input logic DebugGPRUpdate, + input logic [P.E_SUPPORTED+3:0] GPRAddr, + input logic GPRScanEn, + input logic GPRScanIn, + output logic GPRScanOut ); logic [2:0] ImmSrcD; // Select type of immediate extension @@ -107,6 +119,8 @@ module ieu import cvw::*; #(parameter cvw_t P) ( logic MDUE; // Multiply/divide instruction logic BMUActiveE; // Bit manipulation instruction being executed logic [1:0] CZeroE; // {czero.nez, czero.eqz} instructions active + + logic DSCR; controller #(P) c( .clk, .reset, .StallD, .FlushD, .InstrD, .STATUS_FS, .ENVCFG_CBE, .ImmSrcD, @@ -120,7 +134,7 @@ module ieu import cvw::*; #(parameter cvw_t P) ( .StallM, .FlushM, .MemRWE, .MemRWM, .CSRReadM, .CSRWriteM, .PrivilegedM, .AtomicM, .Funct3M, .RegWriteM, .FlushDCacheM, .InstrValidM, .InstrValidE, .InstrValidD, .FWriteIntM, .StallW, .FlushW, .RegWriteW, .IntDivW, .ResultSrcW, .CSRWriteFenceM, .InvalidateICacheM, - .RdW, .RdE, .RdM); + .RdW, .RdE, .RdM, .DebugScanEn, .DebugScanIn, .DebugScanOut(DSCR)); datapath #(P) dp( .clk, .reset, .ImmSrcD, .InstrD, .Rs1D, .Rs2D, .Rs2E, .StallE, .FlushE, .ForwardAE, .ForwardBE, .W64E, .SubArithE, @@ -128,5 +142,6 @@ module ieu import cvw::*; #(parameter cvw_t P) ( .PCE, .PCLinkE, .FlagsE, .IEUAdrE, .ForwardedSrcAE, .ForwardedSrcBE, .BSelectE, .ZBBSelectE, .BALUControlE, .BMUActiveE, .CZeroE, .StallM, .FlushM, .FWriteIntM, .FIntResM, .SrcAM, .WriteDataM, .FCvtIntW, .StallW, .FlushW, .RegWriteW, .IntDivW, .SquashSCW, .ResultSrcW, .ReadDataW, .FCvtIntResW, - .CSRReadValW, .MDUResultW, .FIntDivResultW, .RdW); + .CSRReadValW, .MDUResultW, .FIntDivResultW, .RdW, .DebugScanEn, .DebugScanIn(DSCR), .DebugScanOut, + .GPRSel, .DebugCapture, .DebugGPRUpdate, .GPRAddr, .GPRScanEn, .GPRScanIn, .GPRScanOut); endmodule diff --git a/src/ifu/ifu.sv b/src/ifu/ifu.sv index d5d2f093f..e10658628 100644 --- a/src/ifu/ifu.sv +++ b/src/ifu/ifu.sv @@ -97,7 +97,7 @@ module ifu import cvw::*; #(parameter cvw_t P) ( output logic InstrAccessFaultF, // Instruction access fault output logic ICacheAccess, // Report I$ read to performance counters output logic ICacheMiss, // Report I$ miss to performance counters - // Debug scan chain + // Debug scan chain input logic DebugScanEn, input logic DebugScanIn, output logic DebugScanOut @@ -144,7 +144,7 @@ module ifu import cvw::*; #(parameter cvw_t P) ( logic [15:0] InstrRawE, InstrRawM; logic [LINELEN-1:0] FetchBuffer; logic [31:0] ShiftUncachedInstr; - // Debug scan chain + // Debug scan chain logic DSCR; assign PCFExt = {2'b00, PCSpillF}; @@ -418,14 +418,9 @@ module ifu import cvw::*; #(parameter cvw_t P) ( assign InstrM = '0; assign DebugScanOut = DSCR; end - - // FIXME: delete once working - // flopenr #(32) InstrMReg(clk, reset, ~StallM, NextInstrE, InstrM); - //end else assign InstrM = '0; - // PCM is only needed with CSRs or branch prediction if (P.ZICSR_SUPPORTED | P.BPRED_SUPPORTED) - if (P.DEBUG_SUPPORTED) + if (P.DEBUG_SUPPORTED) flopenrs #(P.XLEN) PCMReg(clk, reset, ~StallM, PCE, PCM, DebugScanEn, DebugScanIn, DSCR); else flopenr #(P.XLEN) PCMReg(clk, reset, ~StallM, PCE, PCM); @@ -433,10 +428,6 @@ module ifu import cvw::*; #(parameter cvw_t P) ( assign PCM = '0; assign DSCR = DebugScanIn; end - - // FIXME: delete once working - // flopenr #(P.XLEN) PCMReg(clk, reset, ~StallM, PCE, PCM); - //else assign PCM = '0; // If compressed instructions are supported, increment PCLink by 2 or 4 for a jal. Otherwise, just by 4 if (P.ZCA_SUPPORTED) begin diff --git a/src/lsu/lsu.sv b/src/lsu/lsu.sv index 0a1f14105..1fe0c5738 100644 --- a/src/lsu/lsu.sv +++ b/src/lsu/lsu.sv @@ -94,11 +94,11 @@ module lsu import cvw::*; #(parameter cvw_t P) ( output logic SelHPTW, // During a HPTW walk the effective privilege mode becomes S_MODE input var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0], // PMP configuration from privileged unit input var logic [P.PA_BITS-3:0] PMPADDR_ARRAY_REGW[P.PMP_ENTRIES-1:0], // PMP address from privileged unit - // Debug scan chain + // Debug scan chain input logic DebugCapture, input logic DebugScanEn, input logic DebugScanIn, - output logic DebugScanOut + output logic DebugScanOut ); localparam logic MISALIGN_SUPPORT = P.ZICCLSM_SUPPORTED & P.DCACHE_SUPPORTED; localparam MLEN = MISALIGN_SUPPORT ? 2*P.LLEN : P.LLEN; // widen buffer for misaligned accessess @@ -160,7 +160,7 @@ module lsu import cvw::*; #(parameter cvw_t P) ( logic [P.XLEN-1:0] WriteDataZM; logic LSULoadPageFaultM, LSUStoreAmoPageFaultM; - logic DSCR; // Debug Register Scan In + logic DSCR; ///////////////////////////////////////////////////////////////////////////////////////////// // Pipeline for IEUAdr E to M @@ -170,10 +170,7 @@ module lsu import cvw::*; #(parameter cvw_t P) ( if (P.DEBUG_SUPPORTED) flopenrcs #(P.XLEN) AddressMReg(.clk, .reset, .clear(FlushM), .en(~StallM), .d(IEUAdrE), .q(IEUAdrM), .scan(DebugScanEn), .scanin(DebugScanIn), .scanout(DSCR)); else - flopenrc #(P.XLEN) AddressMReg(.clk, .reset, .clear(FlushM), .en(~StallM), .d(IEUAdrE), .q(IEUAdrM)); - - // FIXME: delete once working - // flopenrc #(P.XLEN) AddressMReg(clk, reset, FlushM, ~StallM, IEUAdrE, IEUAdrM); + flopenrc #(P.XLEN) AddressMReg(.clk, .reset, .clear(FlushM), .en(~StallM), .d(IEUAdrE), .q(IEUAdrM)); if(MISALIGN_SUPPORT) begin : ziccslm_align logic [P.XLEN-1:0] IEUAdrSpillE, IEUAdrSpillM; align #(P) align(.clk, .reset, .StallM, .FlushM, .IEUAdrE, .IEUAdrM, .Funct3M, .FpLoadStoreM, diff --git a/src/privileged/csr.sv b/src/privileged/csr.sv index fac432251..04481f11e 100644 --- a/src/privileged/csr.sv +++ b/src/privileged/csr.sv @@ -92,7 +92,12 @@ module csr import cvw::*; #(parameter cvw_t P) ( // output logic [P.XLEN-1:0] CSRReadValW, // value read from CSR output logic IllegalCSRAccessM, // Illegal CSR access: CSR doesn't exist or is inaccessible at this privilege level - output logic BigEndianM // memory access is big-endian based on privilege mode and STATUS register endian fields + output logic BigEndianM, // memory access is big-endian based on privilege mode and STATUS register endian fields + // Debug scan chain + input logic DebugCapture, + input logic DebugScanEn, + input logic DebugScanIn, + output logic DebugScanOut ); localparam MIP = 12'h344; @@ -236,7 +241,7 @@ module csr import cvw::*; #(parameter cvw_t P) ( .MEDELEG_REGW, .MIDELEG_REGW,.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW, .MIP_REGW, .MIE_REGW, .WriteMSTATUSM, .WriteMSTATUSHM, .IllegalCSRMAccessM, .IllegalCSRMWriteReadonlyM, - .MENVCFG_REGW); + .MENVCFG_REGW, .DebugCapture, .DebugScanEn, .DebugScanIn, .DebugScanOut); if (P.S_SUPPORTED) begin:csrs diff --git a/src/privileged/csrm.sv b/src/privileged/csrm.sv index 533623141..293b918e1 100644 --- a/src/privileged/csrm.sv +++ b/src/privileged/csrm.sv @@ -50,11 +50,11 @@ module csrm import cvw::*; #(parameter cvw_t P) ( output logic WriteMSTATUSM, WriteMSTATUSHM, output logic IllegalCSRMAccessM, IllegalCSRMWriteReadonlyM, output logic [63:0] MENVCFG_REGW, - // Debug scan chain + // Debug scan chain input logic DebugCapture, input logic DebugScanEn, input logic DebugScanIn, - output logic DebugScanOut + output logic DebugScanOut ); logic [P.XLEN-1:0] MISA_REGW, MHARTID_REGW; @@ -136,7 +136,7 @@ module csrm import cvw::*; #(parameter cvw_t P) ( // MISA is hardwired. Spec says it could be written to disable features, but this is not supported by Wally assign MISA_REGW = {(P.XLEN == 32 ? 2'b01 : 2'b10), {(P.XLEN-28){1'b0}}, MISA_26[25:0]}; - // Dummy register to provide MISA read access to DM + // Dummy register to provide MISA read access to DM if (P.DEBUG_SUPPORTED) begin flopenrs #(P.XLEN) MISAScanReg (.clk, .reset, .en(DebugCapture), .d(MISA_REGW), .q(), .scan(DebugScanEn), .scanin(DebugScanIn), .scanout(DebugScanOut)); end diff --git a/src/privileged/privileged.sv b/src/privileged/privileged.sv index c0dffcaa6..9c8cc40e9 100644 --- a/src/privileged/privileged.sv +++ b/src/privileged/privileged.sv @@ -96,9 +96,14 @@ module privileged import cvw::*; #(parameter cvw_t P) ( input logic InvalidateICacheM, // fence instruction output logic BigEndianM, // Use big endian in current privilege mode // Fault outputs - output logic wfiM, IntPendingM // Stall in Memory stage for WFI until interrupt pending or timeout -); - + output logic wfiM, IntPendingM, // Stall in Memory stage for WFI until interrupt pending or timeout + // Debug scan chain + input logic DebugCapture, + input logic DebugScanEn, + input logic DebugScanIn, + output logic DebugScanOut +); + logic [3:0] CauseM; // trap cause logic [15:0] MEDELEG_REGW; // exception delegation CSR logic [11:0] MIDELEG_REGW; // interrupt delegation CSR @@ -147,7 +152,8 @@ module privileged import cvw::*; #(parameter cvw_t P) ( .SATP_REGW, .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW, .SetFflagsM, .FRM_REGW, .ENVCFG_CBE, .ENVCFG_PBMTE, .ENVCFG_ADUE, .EPCM, .TrapVectorM, - .CSRReadValW, .IllegalCSRAccessM, .BigEndianM); + .CSRReadValW, .IllegalCSRAccessM, .BigEndianM, + .DebugCapture, .DebugScanEn, .DebugScanIn, .DebugScanOut); // pipeline early-arriving trap sources privpiperegs ppr(.clk, .reset, .StallD, .StallE, .StallM, .FlushD, .FlushE, .FlushM, diff --git a/src/wally/wallypipelinedcore.sv b/src/wally/wallypipelinedcore.sv index 2f69593f2..31665e351 100644 --- a/src/wally/wallypipelinedcore.sv +++ b/src/wally/wallypipelinedcore.sv @@ -180,9 +180,9 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) ( logic DCacheStallM, ICacheStallF; logic wfiM, IntPendingM; - // Debug register scan chain interconnects + // Debug register scan chain interconnects logic [3:0] ScanReg; - + // instruction fetch unit: PC, branch prediction, instruction cache ifu #(P) ifu(.clk, .reset, .StallF, .StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW, @@ -329,7 +329,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) ( end else begin assign {CSRReadValW, PrivilegeModeW, SATP_REGW, STATUS_MXR, STATUS_SUM, STATUS_MPRV, STATUS_MPP, STATUS_FS, FRM_REGW, - // PMPCFG_ARRAY_REGW, PMPADDR_ARRAY_REGW, + // PMPCFG_ARRAY_REGW, PMPADDR_ARRAY_REGW, ENVCFG_CBE, ENVCFG_PBMTE, ENVCFG_ADUE, EPCM, TrapVectorM, RetM, TrapM, sfencevmaM, BigEndianM, wfiM, IntPendingM} = '0; diff --git a/src/wally/wallypipelinedsoc.sv b/src/wally/wallypipelinedsoc.sv index 4fc1caef3..8739a60f2 100644 --- a/src/wally/wallypipelinedsoc.sv +++ b/src/wally/wallypipelinedsoc.sv @@ -73,31 +73,31 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( logic [63:0] MTIME_CLINT; // from CLINT to CSRs logic MExtInt,SExtInt; // from PLIC - // Debug Module signals - logic NdmReset; - logic DebugStall; - logic ScanEn; - logic ScanIn; - logic ScanOut; - logic GPRSel; - logic DebugCapture; - logic DebugGPRUpdate; - logic [P.E_SUPPORTED+3:0] GPRAddr; - logic GPRScanEn; - logic GPRScanIn; - logic GPRScanOut; + // Debug Module signals + logic NdmReset; + logic DebugStall; + logic ScanEn; + logic ScanIn; + logic ScanOut; + logic GPRSel; + logic DebugCapture; + logic DebugGPRUpdate; + logic [P.E_SUPPORTED+3:0] GPRAddr; + logic GPRScanEn; + logic GPRScanIn; + logic GPRScanOut; // synchronize reset to SOC clock domain - synchronizer resetsync(.clk, .d(reset_ext), .q(reset)); + synchronizer resetsync(.clk, .d(reset_ext), .q(reset)); // instantiate processor and internal memories - wallypipelinedcore #(P) core(.clk, .reset, + wallypipelinedcore #(P) core(.clk, .reset(reset || NdmReset), .MTimerInt, .MExtInt, .SExtInt, .MSwInt, .MTIME_CLINT, .HRDATA, .HREADY, .HRESP, .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .DebugStall, .DebugScanEn(ScanEn), .DebugScanIn(ScanOut), .DebugScanOut(ScanIn), - .GPRSel, .DebugCapture, .DebugGPRUpdate, .GPRAddr, .GPRScanEn, .GPRScanIn(GPRScanOut), .GPRScanOut(GPRScanIn) - ); + .GPRSel, .DebugCapture, .DebugGPRUpdate, .GPRAddr, .GPRScanEn, .GPRScanIn(GPRScanOut), .GPRScanOut(GPRScanIn) + ); // instantiate uncore if a bus interface exists if (P.BUS_SUPPORTED) begin : uncoregen // Hack to work around Verilator bug https://github.com/verilator/verilator/issues/4769 @@ -111,12 +111,13 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) ( MTIME_CLINT, GPIOOUT, GPIOEN, UARTSout, SPIOut, SPICS} = '0; end - // instantiate debug module (dm) - if (P.DEBUG_SUPPORTED) begin + // instantiate debug module + if (P.DEBUG_SUPPORTED) begin : dm dm #(P) dm (.clk, .rst(reset), .NdmReset, .tck, .tdi, .tms, .tdo, .DebugStall, .ScanEn, .ScanIn, .ScanOut, .GPRSel, .DebugCapture, .DebugGPRUpdate, .GPRAddr, .GPRScanEn, .GPRScanIn, .GPRScanOut); end else begin assign {NdmReset, DebugStall, ScanOut, GPRSel, DebugCapture, DebugGPRUpdate, GPRAddr, GPRScanEn, GPRScanOut} = '0; - end + end + endmodule