clean up repo

This commit is contained in:
Matthew 2024-06-03 22:21:02 -05:00
parent 5a03fbee97
commit bc36edece2
17 changed files with 697 additions and 668 deletions

View File

@ -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.

View File

@ -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,

View File

@ -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;
// 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
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);
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;
// 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);
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
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
// 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
//// 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);
// 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};
// 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 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 AbstractCS = {3'b0, ProgBufSize, 11'b0, Busy, RelaxedPriv, CmdErr, 4'b0, DataCount};
assign SysBusCS = 32'h20000000; // SBVersion = 1
assign SysBusCS = 32'h20000000; // SBVersion = 1
assign RspValid = (State == ACK);
assign ReqReady = (State != ACK);
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
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
endcase
end
ACK : begin
NewAcState <= AC_IDLE;
ResumeReq <= 0;
if (~ReqValid)
State <= ~DmActive ? INACTIVE : IDLE;
end
RspOP <= `OP_SUCCESS;
State <= ACK;
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_DMCONTROL : begin
RspData <= DMControl;
RspOP <= `OP_SUCCESS;
State <= ACK;
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
DMSTATUS : begin
RspData <= DMStatus;
RspOP <= `OP_SUCCESS;
State <= ACK;
end
W_DATA : begin
if (Busy)
CmdErr <= ~|CmdErr ? `CMDERR_BUSY : CmdErr;
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
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
R_ABSTRACTCS : begin
RspData <= AbstractCS;
RspOP <= `OP_SUCCESS;
State <= ACK;
end
// 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
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
RspOP <= `OP_SUCCESS;
State <= ACK;
end
R_SYSBUSCS : begin
RspData <= SysBusCS;
RspOP <= `OP_SUCCESS;
State <= ACK;
end
R_DMCONTROL : begin
RspData <= DMControl;
RspOP <= `OP_SUCCESS;
State <= ACK;
end
READ_ZERO : begin // Writes ignored, Read Zero
RspData <= 0;
RspOP <= `OP_SUCCESS;
State <= ACK;
end
DMSTATUS : begin
RspData <= DMStatus;
RspOP <= `OP_SUCCESS;
State <= ACK;
end
INVALID : begin
RspOP <= `OP_FAILED;
State <= ACK;
end
endcase
end
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
// 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
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
AC_CAPTURE : begin
AcState <= AC_SCAN;
end
R_SYSBUSCS : begin
RspData <= SysBusCS;
RspOP <= `OP_SUCCESS;
State <= ACK;
end
AC_SCAN : begin
if (Cycle == ScanChainLen)
AcState <= (GPRRegNo && AcWrite) ? AC_GPRUPDATE : AC_IDLE;
else
Cycle <= Cycle + 1;
end
READ_ZERO : begin // Writes ignored, Read Zero
RspData <= 0;
RspOP <= `OP_SUCCESS;
State <= ACK;
end
AC_GPRUPDATE : begin
AcState <= AC_IDLE;
end
endcase
end
end
INVALID : begin
RspOP <= `OP_FAILED;
State <= ACK;
end
endcase
end
end
assign Busy = ~(AcState == AC_IDLE);
assign DebugCapture = (AcState == AC_CAPTURE);
assign DebugGPRUpdate = (AcState == AC_GPRUPDATE);
// 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
// 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);
AC_CAPTURE : begin
AcState <= AC_SCAN;
end
// 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};
AC_SCAN : begin
if (Cycle == ScanChainLen)
AcState <= (GPRRegNo & AcWrite) ? AC_GPRUPDATE : AC_IDLE;
else
Cycle <= Cycle + 1;
end
assign WriteScanReg = AcWrite && (~GPRRegNo && (Cycle == ShiftCount) || GPRRegNo && (Cycle == 0));
genvar i;
for (i=0; i<P.XLEN; i=i+1) begin
// ARMask is used as write enable for subword overwrites (basic mask would overwrite neighbors in the chain)
assign ScanNext[i] = WriteScanReg && ARMask[i] ? PackedDataReg[i] : ScanReg[i+1];
flopenr #(1) scanreg (.clk, .reset(rst), .en(AcState == AC_SCAN), .d(ScanNext[i]), .q(ScanReg[i]));
end
AC_GPRUPDATE : begin
AcState <= AC_IDLE;
end
endcase
end
end
// Message Registers
assign MaskedScanReg = ARMask & ScanReg[P.XLEN:1];
assign WriteMsgReg = (State == W_DATA) && ~Busy;
assign StoreScanChain = (AcState == AC_SCAN) && (Cycle == ShiftCount) && ~AcWrite;
assign Busy = ~(AcState == AC_IDLE);
assign DebugCapture = (AcState == AC_CAPTURE);
assign DebugGPRUpdate = (AcState == AC_GPRUPDATE);
assign Data0Wr = StoreScanChain ? MaskedScanReg[31:0] : ReqData;;
flopenr #(32) data0reg (.clk, .reset(rst), .en(StoreScanChain || WriteMsgReg && (ReqAddress == `DATA0)), .d(Data0Wr), .q(Data0));
if (P.XLEN >= 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
// 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);
rad #(P) regnodecode(.AarSize(ReqData[`AARSIZE]),.Regno(ReqData[`REGNO]),.GPRRegNo,.ScanChainLen,.ShiftCount,.InvalidRegNo,.RegReadOnly,.GPRAddr,.ARMask);
// 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<P.XLEN; i=i+1) begin
// ARMask is used as write enable for subword overwrites (basic mask would overwrite neighbors in the chain)
assign ScanNext[i] = WriteScanReg & ARMask[i] ? PackedDataReg[i] : ScanReg[i+1];
flopenr #(1) scanreg (.clk, .reset(rst), .en(AcState == AC_SCAN), .d(ScanNext[i]), .q(ScanReg[i]));
end
// Message Registers
assign MaskedScanReg = ARMask & ScanReg[P.XLEN:1];
assign WriteMsgReg = (State == W_DATA) & ~Busy;
assign StoreScanChain = (AcState == AC_SCAN) & (Cycle == ShiftCount) & ~AcWrite;
assign Data0Wr = StoreScanChain ? MaskedScanReg[31:0] : ReqData;;
flopenr #(32) data0reg (.clk, .reset(rst), .en(StoreScanChain | WriteMsgReg & (ReqAddress == `DATA0)), .d(Data0Wr), .q(Data0));
if (P.XLEN >= 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

View File

@ -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;
// 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
// 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;
logic [31:0] ValRspData;
logic [1:0] ValRspOP;
logic Sticky;
assign DmiOut = {ReqAddress, ValRspData, ValRspOP};
assign DmiStat = ValRspOP;
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));
// 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,
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
// 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
START : begin
if (ReqReady) begin
ReqValid <= 0;
RspReady <= 1;
DMIState <= WAIT;
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
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;
START : begin
if (ReqReady) begin
ReqValid <= 0;
RspReady <= 1;
DMIState <= WAIT;
end
end
COMPLETE : begin
if (CaptureDmi) begin
RspReady <= 0;
DMIState <= IDLE;
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
endcase
end
end
endcase
end
endmodule

View File

@ -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

View File

@ -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;
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;
// 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;
// Instruction signals
logic BypassInstr;
logic IDCodeInstr;
logic DtmcsIntrs;
logic DmiInstr;
logic [32:0] DtmcsShiftReg;
logic [34+ADDR_WIDTH:0] DmiShiftReg;
logic [32:0] DtmcsShiftReg;
logic [34+ADDR_WIDTH:0] DmiShiftReg;
assign UpdateDtmcs = updateDR & DtmcsIntrs;
assign UpdateDtmcs = updateDR & DtmcsIntrs;
assign CaptureDmi = captureDR & DmiInstr;
assign UpdateDmi = updateDR & DmiInstr;
assign CaptureDmi = captureDR & DmiInstr;
assign UpdateDmi = updateDR & DmiInstr;
tap tap (.tck, .tms, .resetn, .tdo_en, .captureIR,
.clockIR, .updateIR, .shiftDR, .captureDR, .clockDR, .updateDR, .select);
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/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);
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
// 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 UpdateDtmcs)
DtmcsIn <= DtmcsShiftReg[31:0];
always_ff @(posedge UpdateDmi)
DmiIn <= DmiShiftReg[34+ADDR_WIDTH-1: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 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
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));
// 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
// bypass register
always_ff @(posedge clockDR) begin
tdo_bypass <= tdi_dr & shiftDR;
end
endmodule

View File

@ -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

View File

@ -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

View File

@ -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)
@ -89,7 +89,7 @@ module datapath import cvw::*; #(parameter cvw_t P) (
// 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
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);

View File

@ -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
@ -108,6 +120,8 @@ module ieu import cvw::*; #(parameter cvw_t P) (
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,
.IllegalIEUFPUInstrD, .IllegalBaseInstrD,
@ -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

View File

@ -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);
@ -434,10 +429,6 @@ module ifu import cvw::*; #(parameter cvw_t P) (
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
logic CompressedD; // instruction is compressed

View File

@ -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
@ -171,9 +171,6 @@ module lsu import cvw::*; #(parameter cvw_t P) (
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);
if(MISALIGN_SUPPORT) begin : ziccslm_align
logic [P.XLEN-1:0] IEUAdrSpillE, IEUAdrSpillM;
align #(P) align(.clk, .reset, .StallM, .FlushM, .IEUAdrE, .IEUAdrM, .Funct3M, .FpLoadStoreM,

View File

@ -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

View File

@ -96,7 +96,12 @@ 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
@ -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,

View File

@ -74,30 +74,30 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) (
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;
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));
// 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)
);
);
// 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
endmodule