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