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}] 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 ##### ##### SD Card I/O #####
#***** may have to switch to Pmod JB or JC. #***** 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_cke,
output [0:0] ddr3_cs_n, output [0:0] ddr3_cs_n,
output [1:0] ddr3_dm, 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; wire CPUCLK;
@ -490,7 +495,7 @@ module fpgaTop
`include "parameter-defs.vh" `include "parameter-defs.vh"
wallypipelinedsoc #(P) 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, .HRDATAEXT, .HREADYEXT, .HRESPEXT, .HSELEXT,
.HSELEXTSDC, .HCLK(HCLKOpen), .HRESETn(HRESETnOpen), .HSELEXTSDC, .HCLK(HCLKOpen), .HRESETn(HRESETnOpen),
.HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT, .HADDR, .HWDATA, .HWSTRB, .HWRITE, .HSIZE, .HBURST, .HPROT,

View File

@ -26,411 +26,412 @@
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
module dm import cvw::*; #(parameter cvw_t P) ( module dm import cvw::*; #(parameter cvw_t P) (
input logic clk, input logic clk,
input logic rst, // Full hardware reset signal (reset button) input logic rst,
// External JTAG signals // External JTAG signals
input logic tck, input logic tck,
input logic tdi, input logic tdi,
input logic tms, input logic tms,
output logic tdo, output logic tdo,
// Platform reset signal // Platform reset signal
output logic NdmReset, output logic NdmReset,
// Core hazard signal // Core hazard signal
output logic DebugStall, output logic DebugStall,
// Scan Chain // Scan Chain
output logic ScanEn, output logic ScanEn,
input logic ScanIn, input logic ScanIn,
output logic ScanOut, output logic ScanOut,
output logic GPRSel, output logic GPRSel,
output logic DebugCapture, output logic DebugCapture,
output logic DebugGPRUpdate, output logic DebugGPRUpdate,
output logic [P.E_SUPPORTED+3:0] GPRAddr, output logic [P.E_SUPPORTED+3:0] GPRAddr,
output logic GPRScanEn, output logic GPRScanEn,
input logic GPRScanIn, input logic GPRScanIn,
output logic GPRScanOut output logic GPRScanOut
); );
`include "debug.vh" `include "debug.vh"
// DMI Signals // DMI Signals
logic ReqReady; logic ReqReady;
logic ReqValid; logic ReqValid;
logic [`ADDR_WIDTH-1:0] ReqAddress; logic [`ADDR_WIDTH-1:0] ReqAddress;
logic [31:0] ReqData; logic [31:0] ReqData;
logic [1:0] ReqOP; logic [1:0] ReqOP;
logic RspReady; logic RspReady;
logic RspValid; logic RspValid;
logic [31:0] RspData; logic [31:0] RspData;
logic [1:0] RspOP; 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, dtm #(`ADDR_WIDTH, JTAG_DEVICE_ID) dtm (.clk, .tck, .tdi, .tms, .tdo,
.ReqReady, .ReqValid, .ReqAddress, .ReqData, .ReqOP, .RspReady, .ReqReady, .ReqValid, .ReqAddress, .ReqData, .ReqOP, .RspReady,
.RspValid, .RspData, .RspOP); .RspValid, .RspData, .RspOP);
// Core control signals // Core control signals
logic HaltReq; logic HaltReq;
logic ResumeReq; logic ResumeReq;
logic HaltOnReset; logic HaltOnReset;
logic Halted; logic Halted;
hartcontrol hartcontrol(.clk, .rst(rst | ~DmActive), .NdmReset, .HaltReq, hartcontrol hartcontrol(.clk, .rst(rst || ~DmActive), .NdmReset, .HaltReq,
.ResumeReq, .HaltOnReset, .DebugStall, .Halted, .AllRunning, .ResumeReq, .HaltOnReset, .DebugStall, .Halted, .AllRunning,
.AnyRunning, .AllHalted, .AnyHalted, .AllResumeAck, .AnyResumeAck); .AnyRunning, .AllHalted, .AnyHalted, .AllResumeAck, .AnyResumeAck);
enum logic [3:0] {INACTIVE, IDLE, ACK, R_DATA, W_DATA, DMSTATUS, W_DMCONTROL, R_DMCONTROL, 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, W_ABSTRACTCS, R_ABSTRACTCS, ABST_COMMAND, R_SYSBUSCS, READ_ZERO,
INVALID} State; 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 // message registers
logic [31:0] Data0; // 0x04 logic [31:0] Data0; // 0x04
logic [31:0] Data1; // 0x05 logic [31:0] Data1; // 0x05
logic [31:0] Data2; // 0x06 logic [31:0] Data2; // 0x06
logic [31:0] Data3; // 0x07 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};
assign DMStatus = {7'b0, 1'b0, StickyUnavail, ImpEBreak, 2'b0, // debug module registers
2'b0, AllResumeAck, AnyResumeAck, AllNonExistent, logic [31:0] DMControl; // 0x10
AnyNonExistent, AllUnavail, AnyUnavail, AllRunning, AnyRunning, AllHalted, logic [31:0] DMStatus; // 0x11
AnyHalted, Authenticated, AuthBusy, HasResetHaltReq, ConfStrPtrValid, Version}; logic [31:0] AbstractCS; // 0x16
logic [31:0] SysBusCS; // 0x38
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 //// DM register fields
if (rst) begin // DMControl
DmActive <= 0; logic AckUnavail;
State <= INACTIVE; logic DmActive; // This bit is used to (de)activate the DM. Toggling acts as reset
end else begin // DMStatus
case (State) logic StickyUnavail;
INACTIVE : begin logic ImpEBreak;
// Reset Values logic AllResumeAck;
RspData <= 0; logic AnyResumeAck;
HaltReq <= 0; logic AllNonExistent;
HaltOnReset <= 0; logic AnyNonExistent;
NdmReset <= 0; logic AllUnavail; // TODO
StickyUnavail <= 0; logic AnyUnavail;
ImpEBreak <= 0; logic AllRunning;
AuthBusy <= 0; logic AnyRunning;
ConfStrPtrValid <= 0; logic AllHalted;
CmdErr <= 0; logic AnyHalted;
if (ReqValid) begin const logic Authenticated = 1;
if (ReqAddress == `DMCONTROL & ReqOP == `OP_WRITE & ReqData[`DMACTIVE]) begin logic AuthBusy;
DmActive <= ReqData[`DMACTIVE]; const logic HasResetHaltReq = 1;
RspOP <= `OP_SUCCESS; logic ConfStrPtrValid;
end const logic [3:0] Version = 3; // DM Version
State <= ACK; // acknowledge all Reqs even if they don't activate DM // 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
end endcase
end
ACK : begin
NewAcState <= AC_IDLE; RspOP <= `OP_SUCCESS;
ResumeReq <= 0; State <= ACK;
if (~ReqValid) end
State <= ~DmActive ? INACTIVE : IDLE;
end R_DMCONTROL : begin
RspData <= DMControl;
IDLE : begin RspOP <= `OP_SUCCESS;
if (ReqValid) State <= ACK;
case ({ReqOP, ReqAddress}) inside end
{`OP_WRITE,`DATA0} : State <= W_DATA;
{`OP_READ,`DATA0} : State <= R_DATA; DMSTATUS : begin
{`OP_WRITE,`DATA1} : State <= (P.XLEN >= 64) ? W_DATA : INVALID; RspData <= DMStatus;
{`OP_READ,`DATA1} : State <= (P.XLEN >= 64) ? R_DATA : INVALID; RspOP <= `OP_SUCCESS;
[{`OP_WRITE,`DATA2}:{`OP_WRITE,`DATA3}] : State <= (P.XLEN >= 128) ? W_DATA : INVALID; State <= ACK;
[{`OP_READ,`DATA2}:{`OP_READ,`DATA3}] : State <= (P.XLEN >= 128) ? R_DATA : INVALID; end
{`OP_WRITE,`DMCONTROL} : State <= W_DMCONTROL;
{`OP_READ,`DMCONTROL} : State <= R_DMCONTROL; W_ABSTRACTCS : begin
{`OP_READ,`DMSTATUS} : State <= DMSTATUS; if (Busy)
{`OP_WRITE,`ABSTRACTCS} : State <= W_ABSTRACTCS; CmdErr <= ~|CmdErr ? `CMDERR_BUSY : CmdErr;
{`OP_READ,`ABSTRACTCS} : State <= R_ABSTRACTCS; else
{`OP_WRITE,`COMMAND} : State <= ABST_COMMAND; CmdErr <= |ReqData[`CMDERR] ? `CMDERR_NONE : CmdErr; // clear CmdErr
{`OP_READ,`COMMAND} : State <= READ_ZERO; RspOP <= `OP_SUCCESS;
{`OP_WRITE,`SBCS} : State <= READ_ZERO; State <= ACK;
{`OP_READ,`SBCS} : State <= R_SYSBUSCS; end
{2'bx,`HARTINFO},
{2'bx,`ABSTRACTAUTO}, R_ABSTRACTCS : begin
{2'bx,`NEXTDM} : State <= READ_ZERO; RspData <= AbstractCS;
default : State <= INVALID; RspOP <= `OP_SUCCESS;
endcase State <= ACK;
end end
R_DATA : begin ABST_COMMAND : begin
if (Busy) if (CmdErr != `CMDERR_NONE); // If CmdErr, do nothing
CmdErr <= ~|CmdErr ? `CMDERR_BUSY : CmdErr; else if (Busy)
case (ReqAddress) CmdErr <= `CMDERR_BUSY; // If Busy, set CmdErr, do nothing
`DATA0 : RspData <= Data0; else if (~Halted)
`DATA1 : RspData <= Data1; CmdErr <= `CMDERR_HALTRESUME; // If not halted, set CmdErr, do nothing
`DATA2 : RspData <= Data2; else begin
`DATA3 : RspData <= Data3; case (ReqData[`CMDTYPE])
endcase `ACCESS_REGISTER : begin
RspOP <= `OP_SUCCESS; if (ReqData[`AARSIZE] > $clog2(P.XLEN/8)) // if AARSIZE (encoded) is greater than P.XLEN, set CmdErr, do nothing
State <= ACK; CmdErr <= `CMDERR_BUS;
end else if (~ReqData[`TRANSFER]); // If not TRANSFER, do nothing
else if (InvalidRegNo)
W_DATA : begin CmdErr <= `CMDERR_EXCEPTION; // If InvalidRegNo, set CmdErr, do nothing
if (Busy) else if (ReqData[`AARWRITE] && RegReadOnly)
CmdErr <= ~|CmdErr ? `CMDERR_BUSY : CmdErr; CmdErr <= `CMDERR_NOT_SUPPORTED; // If writing to a read only register, set CmdErr, do nothing
RspOP <= `OP_SUCCESS; else begin
State <= ACK; AcWrite <= ReqData[`AARWRITE];
end NewAcState <= AC_SCAN;
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
end end
//`QUICK_ACCESS : State <= QUICK_ACCESS;
RspOP <= `OP_SUCCESS; //`ACCESS_MEMORY : State <= ACCESS_MEMORY;
State <= ACK; default : CmdErr <= `CMDERR_NOT_SUPPORTED;
end endcase
end
R_DMCONTROL : begin RspOP <= `OP_SUCCESS;
RspData <= DMControl; State <= ACK;
RspOP <= `OP_SUCCESS; end
State <= ACK;
end R_SYSBUSCS : begin
RspData <= SysBusCS;
DMSTATUS : begin RspOP <= `OP_SUCCESS;
RspData <= DMStatus; State <= ACK;
RspOP <= `OP_SUCCESS; end
State <= ACK;
end READ_ZERO : begin // Writes ignored, Read Zero
RspData <= 0;
W_ABSTRACTCS : begin RspOP <= `OP_SUCCESS;
if (Busy) State <= ACK;
CmdErr <= ~|CmdErr ? `CMDERR_BUSY : CmdErr; end
else
CmdErr <= |ReqData[`CMDERR] ? `CMDERR_NONE : CmdErr; // clear CmdErr INVALID : begin
RspOP <= `OP_SUCCESS; RspOP <= `OP_FAILED;
State <= ACK; State <= ACK;
end end
endcase
R_ABSTRACTCS : begin end
RspData <= AbstractCS; end
RspOP <= `OP_SUCCESS;
State <= ACK;
end // Abstract command engine
// Due to length of the register scan chain,
ABST_COMMAND : begin // abstract commands execute independently of other DM operations
if (CmdErr != `CMDERR_NONE); // If CmdErr, do nothing always_ff @(posedge clk) begin
else if (Busy) if (rst)
CmdErr <= `CMDERR_BUSY; // If Busy, set CmdErr, do nothing AcState <= AC_IDLE;
else if (~Halted) else begin
CmdErr <= `CMDERR_HALTRESUME; // If not halted, set CmdErr, do nothing case (AcState)
else begin AC_IDLE : begin
case (ReqData[`CMDTYPE]) Cycle <= 0;
`ACCESS_REGISTER : begin case (NewAcState)
if (ReqData[`AARSIZE] > $clog2(P.XLEN/8)) // if AARSIZE (encoded) is greater than P.XLEN, set CmdErr, do nothing AC_SCAN : AcState <= ~AcWrite ? AC_CAPTURE : AC_SCAN;
CmdErr <= `CMDERR_BUS; endcase
else if (~ReqData[`TRANSFER]); // If not TRANSFER, do nothing end
else if (InvalidRegNo)
CmdErr <= `CMDERR_EXCEPTION; // If InvalidRegNo, set CmdErr, do nothing AC_CAPTURE : begin
else if (ReqData[`AARWRITE] & RegReadOnly) AcState <= AC_SCAN;
CmdErr <= `CMDERR_NOT_SUPPORTED; // If writing to a read only register, set CmdErr, do nothing end
else begin
AcWrite <= ReqData[`AARWRITE]; AC_SCAN : begin
NewAcState <= AC_SCAN; if (Cycle == ScanChainLen)
end AcState <= (GPRRegNo && AcWrite) ? AC_GPRUPDATE : AC_IDLE;
end else
//`QUICK_ACCESS : State <= QUICK_ACCESS; Cycle <= Cycle + 1;
//`ACCESS_MEMORY : State <= ACCESS_MEMORY; end
default : CmdErr <= `CMDERR_NOT_SUPPORTED;
endcase AC_GPRUPDATE : begin
end AcState <= AC_IDLE;
RspOP <= `OP_SUCCESS; end
State <= ACK; endcase
end end
end
R_SYSBUSCS : begin
RspData <= SysBusCS; assign Busy = ~(AcState == AC_IDLE);
RspOP <= `OP_SUCCESS; assign DebugCapture = (AcState == AC_CAPTURE);
State <= ACK; assign DebugGPRUpdate = (AcState == AC_GPRUPDATE);
end
// Scan Chain
READ_ZERO : begin // Writes ignored, Read Zero assign GPRSel = GPRRegNo && (AcState != AC_IDLE);
RspData <= 0; assign ScanReg[P.XLEN] = GPRSel ? GPRScanIn : ScanIn;
RspOP <= `OP_SUCCESS; assign ScanOut = GPRSel ? 1'b0 : ScanReg[0];
State <= ACK; assign GPRScanOut = GPRSel ? ScanReg[0] : 1'b0;
end assign ScanEn = ~GPRSel && (AcState == AC_SCAN);
assign GPRScanEn = GPRSel && (AcState == AC_SCAN);
INVALID : begin
RspOP <= `OP_FAILED; // Load data from message registers into scan chain
State <= ACK; if (P.XLEN == 32)
end assign PackedDataReg = Data0;
endcase else if (P.XLEN == 64)
end assign PackedDataReg = {Data1,Data0};
end else if (P.XLEN == 128)
assign PackedDataReg = {Data3,Data2,Data1,Data0};
// Abstract command engine
// Due to length of the register scan chain, assign WriteScanReg = AcWrite && (~GPRRegNo && (Cycle == ShiftCount) || GPRRegNo && (Cycle == 0));
// abstract commands execute independently of other DM operations genvar i;
always_ff @(posedge clk) begin for (i=0; i<P.XLEN; i=i+1) begin
if (rst) // ARMask is used as write enable for subword overwrites (basic mask would overwrite neighbors in the chain)
AcState <= AC_IDLE; assign ScanNext[i] = WriteScanReg && ARMask[i] ? PackedDataReg[i] : ScanReg[i+1];
else begin flopenr #(1) scanreg (.clk, .reset(rst), .en(AcState == AC_SCAN), .d(ScanNext[i]), .q(ScanReg[i]));
case (AcState) end
AC_IDLE : begin
Cycle <= 0; // Message Registers
case (NewAcState) assign MaskedScanReg = ARMask & ScanReg[P.XLEN:1];
AC_SCAN : AcState <= ~AcWrite ? AC_CAPTURE : AC_SCAN; assign WriteMsgReg = (State == W_DATA) && ~Busy;
endcase assign StoreScanChain = (AcState == AC_SCAN) && (Cycle == ShiftCount) && ~AcWrite;
end
assign Data0Wr = StoreScanChain ? MaskedScanReg[31:0] : ReqData;;
AC_CAPTURE : begin flopenr #(32) data0reg (.clk, .reset(rst), .en(StoreScanChain || WriteMsgReg && (ReqAddress == `DATA0)), .d(Data0Wr), .q(Data0));
AcState <= AC_SCAN; if (P.XLEN >= 64) begin
end assign Data1Wr = StoreScanChain ? MaskedScanReg[63:32] : ReqData;
flopenr #(32) data1reg (.clk, .reset(rst), .en(StoreScanChain || WriteMsgReg && (ReqAddress == `DATA1)), .d(Data1Wr), .q(Data1));
AC_SCAN : begin end
if (Cycle == ScanChainLen) if (P.XLEN == 128) begin
AcState <= (GPRRegNo & AcWrite) ? AC_GPRUPDATE : AC_IDLE; assign Data2Wr = StoreScanChain ? MaskedScanReg[95:64] : ReqData;
else assign Data3Wr = StoreScanChain ? MaskedScanReg[127:96] : ReqData;
Cycle <= Cycle + 1; flopenr #(32) data2reg (.clk, .reset(rst), .en(StoreScanChain || WriteMsgReg && (ReqAddress == `DATA2)), .d(Data2Wr), .q(Data2));
end flopenr #(32) data3reg (.clk, .reset(rst), .en(StoreScanChain || WriteMsgReg && (ReqAddress == `DATA3)), .d(Data3Wr), .q(Data3));
end
AC_GPRUPDATE : begin
AcState <= AC_IDLE; rad #(P) regnodecode(.AarSize(ReqData[`AARSIZE]),.Regno(ReqData[`REGNO]),.GPRRegNo,.ScanChainLen,.ShiftCount,.InvalidRegNo,.RegReadOnly,.GPRAddr,.ARMask);
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<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 endmodule

View File

@ -51,113 +51,114 @@ module dtm #(parameter ADDR_WIDTH, parameter JTAG_DEVICE_ID) (
); );
`include "debug.vh" `include "debug.vh"
enum logic [1:0] {IDLE, START, WAIT, COMPLETE} DMIState; enum logic [1:0] {IDLE, START, WAIT, COMPLETE} DMIState;
// Clock Domain Crossing // Clock Domain Crossing
logic tcks; // Synchronized JTAG clock logic tcks; // Synchronized JTAG clock
logic resetn; logic resetn;
logic UpdateDtmcs; logic UpdateDtmcs;
logic [31:0] DtmcsIn; logic [31:0] DtmcsIn;
logic [31:0] DtmcsOut; logic [31:0] DtmcsOut;
logic UpdateDmi; logic UpdateDmi;
logic CaptureDmi; logic CaptureDmi;
logic [34+ADDR_WIDTH-1:0] DmiIn; logic [34+ADDR_WIDTH-1:0] DmiIn;
logic [34+ADDR_WIDTH-1:0] DmiOut; logic [34+ADDR_WIDTH-1:0] DmiOut;
// DTMCS Register // DTMCS Register
const logic [2:0] ErrInfo = 0; const logic [2:0] ErrInfo = 0;
logic DtmHardReset; logic DtmHardReset;
logic DmiReset; logic DmiReset;
const logic [2:0] Idle = 0; const logic [2:0] Idle = 0;
logic [1:0] DmiStat; logic [1:0] DmiStat;
const logic [5:0] ABits = ADDR_WIDTH; const logic [5:0] ABits = ADDR_WIDTH;
const logic [3:0] Version = 1; // DTM spec version 1 const logic [3:0] Version = 1; // DTM spec version 1
logic [31:0] ValRspData; logic [31:0] ValRspData;
logic [1:0] ValRspOP; logic [1:0] ValRspOP;
logic Sticky; logic Sticky;
assign DmiOut = {ReqAddress, ValRspData, ValRspOP}; assign DmiOut = {ReqAddress, ValRspData, ValRspOP};
assign DmiStat = ValRspOP; assign DmiStat = ValRspOP;
// Synchronize the edges of tck to the system clock // Synchronize the edges of tck to the system clock
synchronizer clksync (.clk(clk), .d(tck), .q(tcks)); 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); .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 // DTMCS
if (CaptureDmi) begin assign DtmcsOut = {11'b0, ErrInfo, 3'b0, Idle, DmiStat, ABits, Version};
RspReady <= 0; always_ff @(posedge clk) begin
DMIState <= IDLE; if (~resetn | DtmHardReset) begin
end 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
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 endmodule

View File

@ -49,12 +49,12 @@ module ir (
// Shift register // Shift register
always @(posedge clockIR) begin always @(posedge clockIR) begin
shift_reg[0] <= shift_reg[1] | captureIR; shift_reg[0] <= shift_reg[1] || captureIR;
end end
genvar i; genvar i;
for (i = INST_REG_WIDTH; i > 1; i = i - 1) begin for (i = INST_REG_WIDTH; i > 1; i = i - 1) begin
always @(posedge clockIR) begin always @(posedge clockIR) begin
shift_reg[i-1] <= shift_reg[i] & ~captureIR; shift_reg[i-1] <= shift_reg[i] && ~captureIR;
end end
end end

View File

@ -47,90 +47,90 @@ module jtag #(parameter ADDR_WIDTH, parameter DEVICE_ID) (
genvar i; genvar i;
// Data signals // Data signals
logic tdi_ir, tdi_dr; logic tdi_ir, tdi_dr;
logic tdo_ir, tdo_dr; logic tdo_ir, tdo_dr;
logic tdo_bypass; logic tdo_bypass;
logic tdo_idcode; logic tdo_idcode;
logic tdo_dtmcs; logic tdo_dtmcs;
logic tdo_dmi; logic tdo_dmi;
// TAP controller logic // TAP controller logic
logic tdo_en; logic tdo_en;
logic captureIR; logic captureIR;
logic clockIR; logic clockIR;
logic updateIR; logic updateIR;
logic shiftDR; logic shiftDR;
logic captureDR; logic captureDR;
logic clockDR; logic clockDR;
logic updateDR; logic updateDR;
logic select; logic select;
// Instruction signals // Instruction signals
logic BypassInstr; logic BypassInstr;
logic IDCodeInstr; logic IDCodeInstr;
logic DtmcsIntrs; logic DtmcsIntrs;
logic DmiInstr; logic DmiInstr;
logic [32:0] DtmcsShiftReg; logic [32:0] DtmcsShiftReg;
logic [34+ADDR_WIDTH:0] DmiShiftReg; logic [34+ADDR_WIDTH:0] DmiShiftReg;
assign UpdateDtmcs = updateDR & DtmcsIntrs; assign UpdateDtmcs = updateDR & DtmcsIntrs;
assign CaptureDmi = captureDR & DmiInstr; assign CaptureDmi = captureDR & DmiInstr;
assign UpdateDmi = updateDR & DmiInstr; assign UpdateDmi = updateDR & DmiInstr;
tap tap (.tck, .tms, .resetn, .tdo_en, .captureIR, tap tap (.tck, .tms, .resetn, .tdo_en, .captureIR,
.clockIR, .updateIR, .shiftDR, .captureDR, .clockDR, .updateDR, .select); .clockIR, .updateIR, .shiftDR, .captureDR, .clockDR, .updateDR, .select);
// IR/DR input demux // IR/DR input demux
assign tdi_ir = select ? tdi : 1'bz; assign tdi_ir = select ? tdi : 1'bz;
assign tdi_dr = select ? 1'bz : tdi; assign tdi_dr = select ? 1'bz : tdi;
// IR/DR output mux // IR/DR output mux
assign tdo = ~tdo_en ? 1'bz : assign tdo = ~tdo_en ? 1'bz :
select ? tdo_ir : tdo_dr; select ? tdo_ir : tdo_dr;
ir ir (.clockIR, .tdi(tdi_ir), .resetn, .captureIR, .updateIR, .tdo(tdo_ir), ir ir (.clockIR, .tdi(tdi_ir), .resetn, .captureIR, .updateIR, .tdo(tdo_ir),
.BypassInstr, .IDCodeInstr, .DtmcsIntrs, .DmiInstr); .BypassInstr, .IDCodeInstr, .DtmcsIntrs, .DmiInstr);
// DR demux // DR demux
always_comb begin always_comb begin
unique case ({BypassInstr, IDCodeInstr, DtmcsIntrs, DmiInstr}) unique case ({BypassInstr, IDCodeInstr, DtmcsIntrs, DmiInstr})
4'b1000 : tdo_dr <= tdo_bypass; 4'b1000 : tdo_dr <= tdo_bypass;
4'b0100 : tdo_dr <= tdo_idcode; 4'b0100 : tdo_dr <= tdo_idcode;
4'b0010 : tdo_dr <= tdo_dtmcs; 4'b0010 : tdo_dr <= tdo_dtmcs;
4'b0001 : tdo_dr <= tdo_dmi; 4'b0001 : tdo_dr <= tdo_dmi;
default : tdo_dr <= tdo_bypass; default : tdo_dr <= tdo_bypass;
endcase endcase
end end
always_ff @(posedge UpdateDtmcs) always_ff @(posedge UpdateDtmcs)
DtmcsIn <= DtmcsShiftReg[31:0]; DtmcsIn <= DtmcsShiftReg[31:0];
always_ff @(posedge UpdateDmi) always_ff @(posedge UpdateDmi)
DmiIn <= DmiShiftReg[34+ADDR_WIDTH-1:0]; DmiIn <= DmiShiftReg[34+ADDR_WIDTH-1:0];
assign DtmcsShiftReg[32] = tdi_dr; assign DtmcsShiftReg[32] = tdi_dr;
assign tdo_dtmcs = DtmcsShiftReg[0]; assign tdo_dtmcs = DtmcsShiftReg[0];
for (i = 0; i < 32; i = i + 1) begin for (i = 0; i < 32; i = i + 1) begin
always_ff @(posedge clockDR) begin always_ff @(posedge clockDR) begin
DtmcsShiftReg[i] <= captureDR ? DtmcsOut[i] : DtmcsShiftReg[i+1]; DtmcsShiftReg[i] <= captureDR ? DtmcsOut[i] : DtmcsShiftReg[i+1];
end end
end end
assign DmiShiftReg[34+ADDR_WIDTH] = tdi_dr; assign DmiShiftReg[34+ADDR_WIDTH] = tdi_dr;
assign tdo_dmi = DmiShiftReg[0]; assign tdo_dmi = DmiShiftReg[0];
for (i = 0; i < 34+ADDR_WIDTH; i = i + 1) begin for (i = 0; i < 34+ADDR_WIDTH; i = i + 1) begin
always_ff @(posedge clockDR) begin always_ff @(posedge clockDR) begin
DmiShiftReg[i] <= captureDR ? DmiOut[i] : DmiShiftReg[i+1]; DmiShiftReg[i] <= captureDR ? DmiOut[i] : DmiShiftReg[i+1];
end end
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 endmodule

View File

@ -28,20 +28,21 @@
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
module hazard import cvw::*; #(parameter cvw_t P) ( module hazard import cvw::*; #(parameter cvw_t P) (
input logic BPWrongE, CSRWriteFenceM, RetM, TrapM, input logic BPWrongE, CSRWriteFenceM, RetM, TrapM,
input logic StructuralStallD, input logic StructuralStallD,
input logic LSUStallM, IFUStallF, input logic LSUStallM, IFUStallF,
input logic FPUStallD, input logic FPUStallD,
input logic DivBusyE, FDivBusyE, input logic DivBusyE, FDivBusyE,
input logic wfiM, IntPendingM, input logic wfiM, IntPendingM,
input logic DebugStall,
// Stall & flush outputs // Stall & flush outputs
output logic StallF, StallD, StallE, StallM, StallW, output logic StallF, StallD, StallE, StallM, StallW,
output logic FlushD, FlushE, FlushM, FlushW output logic FlushD, FlushE, FlushM, FlushW
); );
logic StallFCause, StallDCause, StallECause, StallMCause, StallWCause; logic StallFCause, StallDCause, StallECause, StallMCause, StallWCause;
logic LatestUnstalledD, LatestUnstalledE, LatestUnstalledM, LatestUnstalledW; logic LatestUnstalledD, LatestUnstalledE, LatestUnstalledM, LatestUnstalledW;
logic FlushDCause, FlushECause, FlushMCause, FlushWCause; logic FlushDCause, FlushECause, FlushMCause, FlushWCause;
logic WFIStallM, WFIInterruptedM; 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. // Need to gate IFUStallF when the equivalent FlushFCause = FlushDCause = 1.
// assign StallWCause = ((IFUStallF & ~FlushDCause) | LSUStallM) & ~FlushWCause; // assign StallWCause = ((IFUStallF & ~FlushDCause) | LSUStallM) & ~FlushWCause;
// Because FlushWCause is a strict subset of FlushDCause, FlushWCause is factored out. // 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 // Stall each stage for cause or if the next stage is stalled
// coverage off: StallFCause is always 0 // coverage off: StallFCause is always 0
@ -107,8 +108,9 @@ module hazard import cvw::*; #(parameter cvw_t P) (
assign LatestUnstalledW = ~StallW & StallM; 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 // 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; // Do not flush if halted for Debug
assign FlushE = LatestUnstalledE | FlushECause; assign FlushD = ~DebugStall & (LatestUnstalledD | FlushDCause);
assign FlushM = LatestUnstalledM | FlushMCause; assign FlushE = ~DebugStall & (LatestUnstalledE | FlushECause);
assign FlushW = LatestUnstalledW | FlushWCause; assign FlushM = ~DebugStall & (LatestUnstalledM | FlushMCause);
assign FlushW = ~DebugStall & (LatestUnstalledW | FlushWCause);
endmodule 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 CSRWriteFenceM, // CSR write or fence instruction; needs to flush the following instructions
output logic [4:0] RdE, RdM, // Pipelined destination registers output logic [4:0] RdE, RdM, // Pipelined destination registers
// Forwarding controls // 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 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}, {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}); {RegWriteM, ResultSrcM, MemRWM, CSRReadM, CSRWriteM, PrivilegedM, Funct3M, FWriteIntM, AtomicM, InvalidateICacheM, FlushDCacheM, FenceM, InstrValidM, IntDivM, CMOpM, LSUPrefetchM});
end 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); flopenrc #(5) RdMReg(clk, reset, FlushM, ~StallM, RdE, RdM);
// Writeback stage pipeline control register // Writeback stage pipeline control register

View File

@ -33,7 +33,7 @@ module datapath import cvw::*; #(parameter cvw_t P) (
// Decode stage signals // Decode stage signals
input logic [2:0] ImmSrcD, // Selects type of immediate extension input logic [2:0] ImmSrcD, // Selects type of immediate extension
input logic [31:0] InstrD, // Instruction in Decode stage 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 // Execute stage signals
input logic [P.XLEN-1:0] PCE, // PC in Execute stage 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) 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 [P.XLEN-1:0] FIntDivResultW, // FPU's integer divide result
input logic [4:0] RdW, // Destination register input logic [4:0] RdW, // Destination register
// Hazard Unit signals // Hazard Unit signals
// Debug scan chain // Debug scan chain
input logic DebugScanEn, input logic DebugScanEn,
input logic DebugScanIn, input logic DebugScanIn,
output logic DebugScanOut, 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 [P.E_SUPPORTED+3:0] GPRAddr,
input logic GPRScanEn, input logic GPRScanEn,
input logic GPRScanIn, input logic GPRScanIn,
output logic GPRScanOut output logic GPRScanOut
); );
// Fetch stage signals // Fetch stage signals
// Decode 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] R1D, R2D; // Read data from Rs1 (RD1), Rs2 (RD2)
logic [P.XLEN-1:0] ImmExtD; // Extended immediate in Decode stage logic [P.XLEN-1:0] ImmExtD; // Extended immediate in Decode stage
logic [4:0] RdD; // Destination register 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 // Writeback stage signals
logic RegWriteWM; // (Debug) Muxed write enable logic RegWriteWM; // (Debug) Muxed write enable
logic [P.XLEN-1:0] SCResultW; // Store Conditional result 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] 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] 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) 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; logic [P.XLEN-1:0] DebugGPRWriteD;
// Decode stage // Decode stage
extend #(P) ext(.InstrD(InstrD[31:7]), .ImmSrcD, .ImmExtD); extend #(P) ext(.InstrD(InstrD[31:7]), .ImmSrcD, .ImmExtD);
// Access GPRs from Debug Module
if (P.DEBUG_SUPPORTED) begin 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 RegWriteWM = GPRSel ? DebugGPRUpdate : RegWriteW;
assign DB_Rs1D = GPRSel ? GPRAddr : Rs1D; assign Rs1DM = GPRSel ? GPRAddr : Rs1D;
assign RdWM = GPRSel ? GPRAddr : RdW; assign RdWM = GPRSel ? GPRAddr : RdW;
assign ResultWM = GPRSel ? DebugGPRWriteD : ResultW; assign ResultWM = GPRSel ? DebugGPRWriteD : ResultW;
flopenrs #(P.XLEN) GPRScanReg(.clk, .reset, .en(DebugCapture), .d(R1D), .q(DebugGPRWriteD), .scan(GPRScanEn), .scanin(GPRScanIn), .scanout(GPRScanOut)); flopenrs #(P.XLEN) GPRScanReg(.clk, .reset, .en(DebugCapture), .d(R1D), .q(DebugGPRWriteD), .scan(GPRScanEn), .scanin(GPRScanIn), .scanout(GPRScanOut));
end else begin end else begin
regfile #(P.XLEN, P.E_SUPPORTED) regf(clk, reset, RegWriteW, Rs1D, Rs2D, RdW, ResultW, R1D, R2D); regfile #(P.XLEN, P.E_SUPPORTED) regf(clk, reset, RegWriteW, Rs1D, Rs2D, RdW, ResultW, R1D, R2D);
end 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 // Execute stage pipeline register and logic
flopenrc #(P.XLEN) RD1EReg(clk, reset, FlushE, ~StallE, R1D, R1E); 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); flopenrcs #(P.XLEN) WriteDataMReg(clk, reset, FlushM, ~StallM, ForwardedSrcBE, WriteDataM, DebugScanEn, DebugScanIn, DebugScanOut);
else else
flopenrc #(P.XLEN) WriteDataMReg(clk, reset, FlushM, ~StallM, ForwardedSrcBE, WriteDataM); 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 // Writeback stage pipeline register and logic
flopenrc #(P.XLEN) IFResultWReg(clk, reset, FlushW, ~StallW, IFResultM, IFResultW); 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 LoadStallD, // Structural stalls for load, sent to performance counters
output logic StoreStallD, // load after store hazard output logic StoreStallD, // load after store hazard
output logic CSRReadM, CSRWriteM, PrivilegedM,// CSR read, CSR write, is privileged instruction 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 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 MDUE; // Multiply/divide instruction
logic BMUActiveE; // Bit manipulation instruction being executed logic BMUActiveE; // Bit manipulation instruction being executed
logic [1:0] CZeroE; // {czero.nez, czero.eqz} instructions active logic [1:0] CZeroE; // {czero.nez, czero.eqz} instructions active
logic DSCR;
controller #(P) c( controller #(P) c(
.clk, .reset, .StallD, .FlushD, .InstrD, .STATUS_FS, .ENVCFG_CBE, .ImmSrcD, .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, .StallM, .FlushM, .MemRWE, .MemRWM, .CSRReadM, .CSRWriteM, .PrivilegedM, .AtomicM, .Funct3M,
.RegWriteM, .FlushDCacheM, .InstrValidM, .InstrValidE, .InstrValidD, .FWriteIntM, .RegWriteM, .FlushDCacheM, .InstrValidM, .InstrValidE, .InstrValidD, .FWriteIntM,
.StallW, .FlushW, .RegWriteW, .IntDivW, .ResultSrcW, .CSRWriteFenceM, .InvalidateICacheM, .StallW, .FlushW, .RegWriteW, .IntDivW, .ResultSrcW, .CSRWriteFenceM, .InvalidateICacheM,
.RdW, .RdE, .RdM); .RdW, .RdE, .RdM, .DebugScanEn, .DebugScanIn, .DebugScanOut(DSCR));
datapath #(P) dp( datapath #(P) dp(
.clk, .reset, .ImmSrcD, .InstrD, .Rs1D, .Rs2D, .Rs2E, .StallE, .FlushE, .ForwardAE, .ForwardBE, .W64E, .SubArithE, .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, .PCE, .PCLinkE, .FlagsE, .IEUAdrE, .ForwardedSrcAE, .ForwardedSrcBE, .BSelectE, .ZBBSelectE, .BALUControlE, .BMUActiveE, .CZeroE,
.StallM, .FlushM, .FWriteIntM, .FIntResM, .SrcAM, .WriteDataM, .FCvtIntW, .StallM, .FlushM, .FWriteIntM, .FIntResM, .SrcAM, .WriteDataM, .FCvtIntW,
.StallW, .FlushW, .RegWriteW, .IntDivW, .SquashSCW, .ResultSrcW, .ReadDataW, .FCvtIntResW, .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 endmodule

View File

@ -97,7 +97,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
output logic InstrAccessFaultF, // Instruction access fault output logic InstrAccessFaultF, // Instruction access fault
output logic ICacheAccess, // Report I$ read to performance counters output logic ICacheAccess, // Report I$ read to performance counters
output logic ICacheMiss, // Report I$ miss to performance counters output logic ICacheMiss, // Report I$ miss to performance counters
// Debug scan chain // Debug scan chain
input logic DebugScanEn, input logic DebugScanEn,
input logic DebugScanIn, input logic DebugScanIn,
output logic DebugScanOut output logic DebugScanOut
@ -144,7 +144,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
logic [15:0] InstrRawE, InstrRawM; logic [15:0] InstrRawE, InstrRawM;
logic [LINELEN-1:0] FetchBuffer; logic [LINELEN-1:0] FetchBuffer;
logic [31:0] ShiftUncachedInstr; logic [31:0] ShiftUncachedInstr;
// Debug scan chain // Debug scan chain
logic DSCR; logic DSCR;
assign PCFExt = {2'b00, PCSpillF}; assign PCFExt = {2'b00, PCSpillF};
@ -418,14 +418,9 @@ module ifu import cvw::*; #(parameter cvw_t P) (
assign InstrM = '0; assign InstrM = '0;
assign DebugScanOut = DSCR; assign DebugScanOut = DSCR;
end 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 // PCM is only needed with CSRs or branch prediction
if (P.ZICSR_SUPPORTED | P.BPRED_SUPPORTED) 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); flopenrs #(P.XLEN) PCMReg(clk, reset, ~StallM, PCE, PCM, DebugScanEn, DebugScanIn, DSCR);
else else
flopenr #(P.XLEN) PCMReg(clk, reset, ~StallM, PCE, PCM); 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 PCM = '0;
assign DSCR = DebugScanIn; assign DSCR = DebugScanIn;
end 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 compressed instructions are supported, increment PCLink by 2 or 4 for a jal. Otherwise, just by 4
if (P.ZCA_SUPPORTED) begin if (P.ZCA_SUPPORTED) begin

View File

@ -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 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 [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 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 DebugCapture,
input logic DebugScanEn, input logic DebugScanEn,
input logic DebugScanIn, input logic DebugScanIn,
output logic DebugScanOut output logic DebugScanOut
); );
localparam logic MISALIGN_SUPPORT = P.ZICCLSM_SUPPORTED & P.DCACHE_SUPPORTED; localparam logic MISALIGN_SUPPORT = P.ZICCLSM_SUPPORTED & P.DCACHE_SUPPORTED;
localparam MLEN = MISALIGN_SUPPORT ? 2*P.LLEN : P.LLEN; // widen buffer for misaligned accessess 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 [P.XLEN-1:0] WriteDataZM;
logic LSULoadPageFaultM, LSUStoreAmoPageFaultM; logic LSULoadPageFaultM, LSUStoreAmoPageFaultM;
logic DSCR; // Debug Register Scan In logic DSCR;
///////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////
// Pipeline for IEUAdr E to M // Pipeline for IEUAdr E to M
@ -170,10 +170,7 @@ module lsu import cvw::*; #(parameter cvw_t P) (
if (P.DEBUG_SUPPORTED) if (P.DEBUG_SUPPORTED)
flopenrcs #(P.XLEN) AddressMReg(.clk, .reset, .clear(FlushM), .en(~StallM), .d(IEUAdrE), .q(IEUAdrM), .scan(DebugScanEn), .scanin(DebugScanIn), .scanout(DSCR)); flopenrcs #(P.XLEN) AddressMReg(.clk, .reset, .clear(FlushM), .en(~StallM), .d(IEUAdrE), .q(IEUAdrM), .scan(DebugScanEn), .scanin(DebugScanIn), .scanout(DSCR));
else else
flopenrc #(P.XLEN) AddressMReg(.clk, .reset, .clear(FlushM), .en(~StallM), .d(IEUAdrE), .q(IEUAdrM)); 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 if(MISALIGN_SUPPORT) begin : ziccslm_align
logic [P.XLEN-1:0] IEUAdrSpillE, IEUAdrSpillM; logic [P.XLEN-1:0] IEUAdrSpillE, IEUAdrSpillM;
align #(P) align(.clk, .reset, .StallM, .FlushM, .IEUAdrE, .IEUAdrM, .Funct3M, .FpLoadStoreM, 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 [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 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; 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, .MEDELEG_REGW, .MIDELEG_REGW,.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW,
.MIP_REGW, .MIE_REGW, .WriteMSTATUSM, .WriteMSTATUSHM, .MIP_REGW, .MIE_REGW, .WriteMSTATUSM, .WriteMSTATUSHM,
.IllegalCSRMAccessM, .IllegalCSRMWriteReadonlyM, .IllegalCSRMAccessM, .IllegalCSRMWriteReadonlyM,
.MENVCFG_REGW); .MENVCFG_REGW, .DebugCapture, .DebugScanEn, .DebugScanIn, .DebugScanOut);
if (P.S_SUPPORTED) begin:csrs if (P.S_SUPPORTED) begin:csrs

View File

@ -50,11 +50,11 @@ module csrm import cvw::*; #(parameter cvw_t P) (
output logic WriteMSTATUSM, WriteMSTATUSHM, output logic WriteMSTATUSM, WriteMSTATUSHM,
output logic IllegalCSRMAccessM, IllegalCSRMWriteReadonlyM, output logic IllegalCSRMAccessM, IllegalCSRMWriteReadonlyM,
output logic [63:0] MENVCFG_REGW, output logic [63:0] MENVCFG_REGW,
// Debug scan chain // Debug scan chain
input logic DebugCapture, input logic DebugCapture,
input logic DebugScanEn, input logic DebugScanEn,
input logic DebugScanIn, input logic DebugScanIn,
output logic DebugScanOut output logic DebugScanOut
); );
logic [P.XLEN-1:0] MISA_REGW, MHARTID_REGW; 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 // 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]}; 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 if (P.DEBUG_SUPPORTED) begin
flopenrs #(P.XLEN) MISAScanReg (.clk, .reset, .en(DebugCapture), .d(MISA_REGW), .q(), .scan(DebugScanEn), .scanin(DebugScanIn), .scanout(DebugScanOut)); flopenrs #(P.XLEN) MISAScanReg (.clk, .reset, .en(DebugCapture), .d(MISA_REGW), .q(), .scan(DebugScanEn), .scanin(DebugScanIn), .scanout(DebugScanOut));
end end

View File

@ -96,9 +96,14 @@ module privileged import cvw::*; #(parameter cvw_t P) (
input logic InvalidateICacheM, // fence instruction input logic InvalidateICacheM, // fence instruction
output logic BigEndianM, // Use big endian in current privilege mode output logic BigEndianM, // Use big endian in current privilege mode
// Fault outputs // 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 [3:0] CauseM; // trap cause
logic [15:0] MEDELEG_REGW; // exception delegation CSR logic [15:0] MEDELEG_REGW; // exception delegation CSR
logic [11:0] MIDELEG_REGW; // interrupt 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, .SATP_REGW, .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW,
.SetFflagsM, .FRM_REGW, .ENVCFG_CBE, .ENVCFG_PBMTE, .ENVCFG_ADUE, .SetFflagsM, .FRM_REGW, .ENVCFG_CBE, .ENVCFG_PBMTE, .ENVCFG_ADUE,
.EPCM, .TrapVectorM, .EPCM, .TrapVectorM,
.CSRReadValW, .IllegalCSRAccessM, .BigEndianM); .CSRReadValW, .IllegalCSRAccessM, .BigEndianM,
.DebugCapture, .DebugScanEn, .DebugScanIn, .DebugScanOut);
// pipeline early-arriving trap sources // pipeline early-arriving trap sources
privpiperegs ppr(.clk, .reset, .StallD, .StallE, .StallM, .FlushD, .FlushE, .FlushM, privpiperegs ppr(.clk, .reset, .StallD, .StallE, .StallM, .FlushD, .FlushE, .FlushM,

View File

@ -180,9 +180,9 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
logic DCacheStallM, ICacheStallF; logic DCacheStallM, ICacheStallF;
logic wfiM, IntPendingM; logic wfiM, IntPendingM;
// Debug register scan chain interconnects // Debug register scan chain interconnects
logic [3:0] ScanReg; logic [3:0] ScanReg;
// instruction fetch unit: PC, branch prediction, instruction cache // instruction fetch unit: PC, branch prediction, instruction cache
ifu #(P) ifu(.clk, .reset, ifu #(P) ifu(.clk, .reset,
.StallF, .StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW, .StallF, .StallD, .StallE, .StallM, .StallW, .FlushD, .FlushE, .FlushM, .FlushW,
@ -329,7 +329,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
end else begin end else begin
assign {CSRReadValW, PrivilegeModeW, assign {CSRReadValW, PrivilegeModeW,
SATP_REGW, STATUS_MXR, STATUS_SUM, STATUS_MPRV, STATUS_MPP, STATUS_FS, FRM_REGW, 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, ENVCFG_CBE, ENVCFG_PBMTE, ENVCFG_ADUE,
EPCM, TrapVectorM, RetM, TrapM, EPCM, TrapVectorM, RetM, TrapM,
sfencevmaM, BigEndianM, wfiM, IntPendingM} = '0; sfencevmaM, BigEndianM, wfiM, IntPendingM} = '0;

View File

@ -73,31 +73,31 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) (
logic [63:0] MTIME_CLINT; // from CLINT to CSRs logic [63:0] MTIME_CLINT; // from CLINT to CSRs
logic MExtInt,SExtInt; // from PLIC logic MExtInt,SExtInt; // from PLIC
// Debug Module signals // Debug Module signals
logic NdmReset; logic NdmReset;
logic DebugStall; logic DebugStall;
logic ScanEn; logic ScanEn;
logic ScanIn; logic ScanIn;
logic ScanOut; logic ScanOut;
logic GPRSel; logic GPRSel;
logic DebugCapture; logic DebugCapture;
logic DebugGPRUpdate; logic DebugGPRUpdate;
logic [P.E_SUPPORTED+3:0] GPRAddr; logic [P.E_SUPPORTED+3:0] GPRAddr;
logic GPRScanEn; logic GPRScanEn;
logic GPRScanIn; logic GPRScanIn;
logic GPRScanOut; logic GPRScanOut;
// synchronize reset to SOC clock domain // 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 // instantiate processor and internal memories
wallypipelinedcore #(P) core(.clk, .reset, wallypipelinedcore #(P) core(.clk, .reset(reset || NdmReset),
.MTimerInt, .MExtInt, .SExtInt, .MSwInt, .MTIME_CLINT, .MTimerInt, .MExtInt, .SExtInt, .MSwInt, .MTIME_CLINT,
.HRDATA, .HREADY, .HRESP, .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB, .HRDATA, .HREADY, .HRESP, .HCLK, .HRESETn, .HADDR, .HWDATA, .HWSTRB,
.HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK, .HWRITE, .HSIZE, .HBURST, .HPROT, .HTRANS, .HMASTLOCK,
.DebugStall, .DebugScanEn(ScanEn), .DebugScanIn(ScanOut), .DebugScanOut(ScanIn), .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 // 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 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; MTIME_CLINT, GPIOOUT, GPIOEN, UARTSout, SPIOut, SPICS} = '0;
end end
// instantiate debug module (dm) // instantiate debug module
if (P.DEBUG_SUPPORTED) begin if (P.DEBUG_SUPPORTED) begin : dm
dm #(P) dm (.clk, .rst(reset), .NdmReset, .tck, .tdi, .tms, .tdo, dm #(P) dm (.clk, .rst(reset), .NdmReset, .tck, .tdi, .tms, .tdo,
.DebugStall, .ScanEn, .ScanIn, .ScanOut, .GPRSel, .DebugCapture, .DebugGPRUpdate, .DebugStall, .ScanEn, .ScanIn, .ScanOut, .GPRSel, .DebugCapture, .DebugGPRUpdate,
.GPRAddr, .GPRScanEn, .GPRScanIn, .GPRScanOut); .GPRAddr, .GPRScanEn, .GPRScanIn, .GPRScanOut);
end else begin end else begin
assign {NdmReset, DebugStall, ScanOut, GPRSel, DebugCapture, DebugGPRUpdate, GPRAddr, GPRScanEn, GPRScanOut} = '0; assign {NdmReset, DebugStall, ScanOut, GPRSel, DebugCapture, DebugGPRUpdate, GPRAddr, GPRScanEn, GPRScanOut} = '0;
end end
endmodule endmodule