mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
clean up repo
This commit is contained in:
parent
5a03fbee97
commit
bc36edece2
@ -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.
|
||||||
|
@ -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,
|
||||||
|
705
src/debug/dm.sv
705
src/debug/dm.sv
@ -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,
|
||||||
|
.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,
|
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;
|
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
|
|
||||||
|
|
||||||
|
// 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
|
// debug module registers
|
||||||
logic [31:0] DMControl; // 0x10
|
logic [31:0] DMControl; // 0x10
|
||||||
logic [31:0] DMStatus; // 0x11
|
logic [31:0] DMStatus; // 0x11
|
||||||
logic [31:0] AbstractCS; // 0x16
|
logic [31:0] AbstractCS; // 0x16
|
||||||
logic [31:0] SysBusCS; // 0x38
|
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
|
// Pack registers
|
||||||
assign DMControl = {2'b0, 1'b0, 2'b0, 1'b0, 10'b0,
|
assign DMControl = {2'b0, 1'b0, 2'b0, 1'b0, 10'b0,
|
||||||
10'b0, 4'b0, NdmReset, DmActive};
|
10'b0, 4'b0, NdmReset, DmActive};
|
||||||
|
|
||||||
assign DMStatus = {7'b0, 1'b0, StickyUnavail, ImpEBreak, 2'b0,
|
assign DMStatus = {7'b0, 1'b0, StickyUnavail, ImpEBreak, 2'b0,
|
||||||
2'b0, AllResumeAck, AnyResumeAck, AllNonExistent,
|
2'b0, AllResumeAck, AnyResumeAck, AllNonExistent,
|
||||||
AnyNonExistent, AllUnavail, AnyUnavail, AllRunning, AnyRunning, AllHalted,
|
AnyNonExistent, AllUnavail, AnyUnavail, AllRunning, AnyRunning, AllHalted,
|
||||||
AnyHalted, Authenticated, AuthBusy, HasResetHaltReq, ConfStrPtrValid, Version};
|
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 RspValid = (State == ACK);
|
||||||
assign ReqReady = (State != ACK);
|
assign ReqReady = (State != ACK);
|
||||||
|
|
||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
if (rst) begin
|
if (rst) begin
|
||||||
DmActive <= 0;
|
DmActive <= 0;
|
||||||
State <= INACTIVE;
|
State <= INACTIVE;
|
||||||
end else begin
|
end else begin
|
||||||
case (State)
|
case (State)
|
||||||
INACTIVE : begin
|
INACTIVE : begin
|
||||||
// Reset Values
|
// Reset Values
|
||||||
RspData <= 0;
|
RspData <= 0;
|
||||||
HaltReq <= 0;
|
HaltReq <= 0;
|
||||||
HaltOnReset <= 0;
|
HaltOnReset <= 0;
|
||||||
NdmReset <= 0;
|
NdmReset <= 0;
|
||||||
StickyUnavail <= 0;
|
StickyUnavail <= 0;
|
||||||
ImpEBreak <= 0;
|
ImpEBreak <= 0;
|
||||||
AuthBusy <= 0;
|
AuthBusy <= 0;
|
||||||
ConfStrPtrValid <= 0;
|
ConfStrPtrValid <= 0;
|
||||||
CmdErr <= 0;
|
CmdErr <= 0;
|
||||||
if (ReqValid) begin
|
if (ReqValid) begin
|
||||||
if (ReqAddress == `DMCONTROL & ReqOP == `OP_WRITE & ReqData[`DMACTIVE]) begin
|
if (ReqAddress == `DMCONTROL && ReqOP == `OP_WRITE && ReqData[`DMACTIVE]) begin
|
||||||
DmActive <= ReqData[`DMACTIVE];
|
DmActive <= ReqData[`DMACTIVE];
|
||||||
RspOP <= `OP_SUCCESS;
|
RspOP <= `OP_SUCCESS;
|
||||||
end
|
end
|
||||||
State <= ACK; // acknowledge all Reqs even if they don't activate DM
|
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
|
RspOP <= `OP_SUCCESS;
|
||||||
NewAcState <= AC_IDLE;
|
State <= ACK;
|
||||||
ResumeReq <= 0;
|
end
|
||||||
if (~ReqValid)
|
|
||||||
State <= ~DmActive ? INACTIVE : IDLE;
|
|
||||||
end
|
|
||||||
|
|
||||||
IDLE : begin
|
R_DMCONTROL : begin
|
||||||
if (ReqValid)
|
RspData <= DMControl;
|
||||||
case ({ReqOP, ReqAddress}) inside
|
RspOP <= `OP_SUCCESS;
|
||||||
{`OP_WRITE,`DATA0} : State <= W_DATA;
|
State <= ACK;
|
||||||
{`OP_READ,`DATA0} : State <= R_DATA;
|
end
|
||||||
{`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
|
DMSTATUS : begin
|
||||||
if (Busy)
|
RspData <= DMStatus;
|
||||||
CmdErr <= ~|CmdErr ? `CMDERR_BUSY : CmdErr;
|
RspOP <= `OP_SUCCESS;
|
||||||
case (ReqAddress)
|
State <= ACK;
|
||||||
`DATA0 : RspData <= Data0;
|
end
|
||||||
`DATA1 : RspData <= Data1;
|
|
||||||
`DATA2 : RspData <= Data2;
|
|
||||||
`DATA3 : RspData <= Data3;
|
|
||||||
endcase
|
|
||||||
RspOP <= `OP_SUCCESS;
|
|
||||||
State <= ACK;
|
|
||||||
end
|
|
||||||
|
|
||||||
W_DATA : begin
|
W_ABSTRACTCS : begin
|
||||||
if (Busy)
|
if (Busy)
|
||||||
CmdErr <= ~|CmdErr ? `CMDERR_BUSY : CmdErr;
|
CmdErr <= ~|CmdErr ? `CMDERR_BUSY : CmdErr;
|
||||||
RspOP <= `OP_SUCCESS;
|
else
|
||||||
State <= ACK;
|
CmdErr <= |ReqData[`CMDERR] ? `CMDERR_NONE : CmdErr; // clear CmdErr
|
||||||
end
|
RspOP <= `OP_SUCCESS;
|
||||||
|
State <= ACK;
|
||||||
|
end
|
||||||
|
|
||||||
W_DMCONTROL : begin
|
R_ABSTRACTCS : begin
|
||||||
// While an abstract command is executing (busy in abstractcs is high), a debugger must not change
|
RspData <= AbstractCS;
|
||||||
// hartsel, and must not write 1 to haltreq, resumereq, ackhavereset, setresethaltreq, or clrresethaltreq
|
RspOP <= `OP_SUCCESS;
|
||||||
if (Busy & (ReqData[`HALTREQ] | ReqData[`RESUMEREQ] | ReqData[`SETRESETHALTREQ] | ReqData[`CLRRESETHALTREQ]))
|
State <= ACK;
|
||||||
CmdErr <= ~|CmdErr ? `CMDERR_BUSY : CmdErr;
|
end
|
||||||
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,
|
ABST_COMMAND : begin
|
||||||
// hartreset, ackhavereset, setresethaltreq, and clrresethaltreq. The others must be written 0
|
if (CmdErr != `CMDERR_NONE); // If CmdErr, do nothing
|
||||||
case ({ReqData[`RESUMEREQ],ReqData[`SETRESETHALTREQ],ReqData[`CLRRESETHALTREQ]})
|
else if (Busy)
|
||||||
3'b000 :; // None
|
CmdErr <= `CMDERR_BUSY; // If Busy, set CmdErr, do nothing
|
||||||
3'b100 : ResumeReq <= 1;
|
else if (~Halted)
|
||||||
3'b010 : HaltOnReset <= 1;
|
CmdErr <= `CMDERR_HALTRESUME; // If not halted, set CmdErr, do nothing
|
||||||
3'b001 : HaltOnReset <= 0;
|
else begin
|
||||||
default : begin // Invalid (not onehot), dont write any changes
|
case (ReqData[`CMDTYPE])
|
||||||
HaltReq <= HaltReq;
|
`ACCESS_REGISTER : begin
|
||||||
AckUnavail <= AckUnavail;
|
if (ReqData[`AARSIZE] > $clog2(P.XLEN/8)) // if AARSIZE (encoded) is greater than P.XLEN, set CmdErr, do nothing
|
||||||
NdmReset <= NdmReset;
|
CmdErr <= `CMDERR_BUS;
|
||||||
DmActive <= DmActive;
|
else if (~ReqData[`TRANSFER]); // If not TRANSFER, do nothing
|
||||||
end
|
else if (InvalidRegNo)
|
||||||
endcase
|
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
|
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;
|
R_SYSBUSCS : begin
|
||||||
State <= ACK;
|
RspData <= SysBusCS;
|
||||||
end
|
RspOP <= `OP_SUCCESS;
|
||||||
|
State <= ACK;
|
||||||
|
end
|
||||||
|
|
||||||
R_DMCONTROL : begin
|
READ_ZERO : begin // Writes ignored, Read Zero
|
||||||
RspData <= DMControl;
|
RspData <= 0;
|
||||||
RspOP <= `OP_SUCCESS;
|
RspOP <= `OP_SUCCESS;
|
||||||
State <= ACK;
|
State <= ACK;
|
||||||
end
|
end
|
||||||
|
|
||||||
DMSTATUS : begin
|
INVALID : begin
|
||||||
RspData <= DMStatus;
|
RspOP <= `OP_FAILED;
|
||||||
RspOP <= `OP_SUCCESS;
|
State <= ACK;
|
||||||
State <= ACK;
|
end
|
||||||
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
|
// Abstract command engine
|
||||||
RspData <= AbstractCS;
|
// Due to length of the register scan chain,
|
||||||
RspOP <= `OP_SUCCESS;
|
// abstract commands execute independently of other DM operations
|
||||||
State <= ACK;
|
always_ff @(posedge clk) begin
|
||||||
end
|
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
|
AC_CAPTURE : begin
|
||||||
if (CmdErr != `CMDERR_NONE); // If CmdErr, do nothing
|
AcState <= AC_SCAN;
|
||||||
else if (Busy)
|
end
|
||||||
CmdErr <= `CMDERR_BUSY; // If Busy, set CmdErr, do nothing
|
|
||||||
else if (~Halted)
|
|
||||||
CmdErr <= `CMDERR_HALTRESUME; // If not halted, set CmdErr, do nothing
|
|
||||||
else begin
|
|
||||||
case (ReqData[`CMDTYPE])
|
|
||||||
`ACCESS_REGISTER : begin
|
|
||||||
if (ReqData[`AARSIZE] > $clog2(P.XLEN/8)) // if AARSIZE (encoded) is greater than P.XLEN, set CmdErr, do nothing
|
|
||||||
CmdErr <= `CMDERR_BUS;
|
|
||||||
else if (~ReqData[`TRANSFER]); // If not TRANSFER, do nothing
|
|
||||||
else if (InvalidRegNo)
|
|
||||||
CmdErr <= `CMDERR_EXCEPTION; // If InvalidRegNo, set CmdErr, do nothing
|
|
||||||
else if (ReqData[`AARWRITE] & RegReadOnly)
|
|
||||||
CmdErr <= `CMDERR_NOT_SUPPORTED; // If writing to a read only register, set CmdErr, do nothing
|
|
||||||
else begin
|
|
||||||
AcWrite <= ReqData[`AARWRITE];
|
|
||||||
NewAcState <= AC_SCAN;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
//`QUICK_ACCESS : State <= QUICK_ACCESS;
|
|
||||||
//`ACCESS_MEMORY : State <= ACCESS_MEMORY;
|
|
||||||
default : CmdErr <= `CMDERR_NOT_SUPPORTED;
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
RspOP <= `OP_SUCCESS;
|
|
||||||
State <= ACK;
|
|
||||||
end
|
|
||||||
|
|
||||||
R_SYSBUSCS : begin
|
AC_SCAN : begin
|
||||||
RspData <= SysBusCS;
|
if (Cycle == ScanChainLen)
|
||||||
RspOP <= `OP_SUCCESS;
|
AcState <= (GPRRegNo && AcWrite) ? AC_GPRUPDATE : AC_IDLE;
|
||||||
State <= ACK;
|
else
|
||||||
end
|
Cycle <= Cycle + 1;
|
||||||
|
end
|
||||||
|
|
||||||
READ_ZERO : begin // Writes ignored, Read Zero
|
AC_GPRUPDATE : begin
|
||||||
RspData <= 0;
|
AcState <= AC_IDLE;
|
||||||
RspOP <= `OP_SUCCESS;
|
end
|
||||||
State <= ACK;
|
endcase
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
INVALID : begin
|
assign Busy = ~(AcState == AC_IDLE);
|
||||||
RspOP <= `OP_FAILED;
|
assign DebugCapture = (AcState == AC_CAPTURE);
|
||||||
State <= ACK;
|
assign DebugGPRUpdate = (AcState == AC_GPRUPDATE);
|
||||||
end
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
// Abstract command engine
|
// Scan Chain
|
||||||
// Due to length of the register scan chain,
|
assign GPRSel = GPRRegNo && (AcState != AC_IDLE);
|
||||||
// abstract commands execute independently of other DM operations
|
assign ScanReg[P.XLEN] = GPRSel ? GPRScanIn : ScanIn;
|
||||||
always_ff @(posedge clk) begin
|
assign ScanOut = GPRSel ? 1'b0 : ScanReg[0];
|
||||||
if (rst)
|
assign GPRScanOut = GPRSel ? ScanReg[0] : 1'b0;
|
||||||
AcState <= AC_IDLE;
|
assign ScanEn = ~GPRSel && (AcState == AC_SCAN);
|
||||||
else begin
|
assign GPRScanEn = GPRSel && (AcState == AC_SCAN);
|
||||||
case (AcState)
|
|
||||||
AC_IDLE : begin
|
|
||||||
Cycle <= 0;
|
|
||||||
case (NewAcState)
|
|
||||||
AC_SCAN : AcState <= ~AcWrite ? AC_CAPTURE : AC_SCAN;
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
|
|
||||||
AC_CAPTURE : begin
|
// Load data from message registers into scan chain
|
||||||
AcState <= AC_SCAN;
|
if (P.XLEN == 32)
|
||||||
end
|
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
|
assign WriteScanReg = AcWrite && (~GPRRegNo && (Cycle == ShiftCount) || GPRRegNo && (Cycle == 0));
|
||||||
if (Cycle == ScanChainLen)
|
genvar i;
|
||||||
AcState <= (GPRRegNo & AcWrite) ? AC_GPRUPDATE : AC_IDLE;
|
for (i=0; i<P.XLEN; i=i+1) begin
|
||||||
else
|
// ARMask is used as write enable for subword overwrites (basic mask would overwrite neighbors in the chain)
|
||||||
Cycle <= Cycle + 1;
|
assign ScanNext[i] = WriteScanReg && ARMask[i] ? PackedDataReg[i] : ScanReg[i+1];
|
||||||
end
|
flopenr #(1) scanreg (.clk, .reset(rst), .en(AcState == AC_SCAN), .d(ScanNext[i]), .q(ScanReg[i]));
|
||||||
|
end
|
||||||
|
|
||||||
AC_GPRUPDATE : begin
|
// Message Registers
|
||||||
AcState <= AC_IDLE;
|
assign MaskedScanReg = ARMask & ScanReg[P.XLEN:1];
|
||||||
end
|
assign WriteMsgReg = (State == W_DATA) && ~Busy;
|
||||||
endcase
|
assign StoreScanChain = (AcState == AC_SCAN) && (Cycle == ShiftCount) && ~AcWrite;
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
assign Busy = ~(AcState == AC_IDLE);
|
assign Data0Wr = StoreScanChain ? MaskedScanReg[31:0] : ReqData;;
|
||||||
assign DebugCapture = (AcState == AC_CAPTURE);
|
flopenr #(32) data0reg (.clk, .reset(rst), .en(StoreScanChain || WriteMsgReg && (ReqAddress == `DATA0)), .d(Data0Wr), .q(Data0));
|
||||||
assign DebugGPRUpdate = (AcState == AC_GPRUPDATE);
|
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
|
rad #(P) regnodecode(.AarSize(ReqData[`AARSIZE]),.Regno(ReqData[`REGNO]),.GPRRegNo,.ScanChainLen,.ShiftCount,.InvalidRegNo,.RegReadOnly,.GPRAddr,.ARMask);
|
||||||
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
|
||||||
|
187
src/debug/dtm.sv
187
src/debug/dtm.sv
@ -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
|
// DTMCS
|
||||||
always_ff @(posedge clk) begin
|
assign DtmcsOut = {11'b0, ErrInfo, 3'b0, Idle, DmiStat, ABits, Version};
|
||||||
if (~resetn | DtmHardReset) begin
|
always_ff @(posedge clk) begin
|
||||||
ValRspData <= 0;
|
if (~resetn | DtmHardReset) begin
|
||||||
ValRspOP <= `OP_SUCCESS;
|
DtmHardReset <= 0;
|
||||||
//ErrInfo <= 4;
|
DmiReset <= 0;
|
||||||
Sticky <= 0;
|
end else if (UpdateDtmcs) begin
|
||||||
DMIState <= IDLE;
|
DtmHardReset <= DtmcsIn[17];
|
||||||
end else if (DmiReset) begin
|
DmiReset <= DtmcsIn[16];
|
||||||
ValRspOP <= `OP_SUCCESS;
|
end else if (DmiReset) begin
|
||||||
//ErrInfo <= 4;
|
DmiReset <= 0;
|
||||||
Sticky <= 0;
|
end
|
||||||
end else
|
end
|
||||||
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
|
// DMI
|
||||||
if (ReqReady) begin
|
always_ff @(posedge clk) begin
|
||||||
ReqValid <= 0;
|
if (~resetn | DtmHardReset) begin
|
||||||
RspReady <= 1;
|
ValRspData <= 0;
|
||||||
DMIState <= WAIT;
|
ValRspOP <= `OP_SUCCESS;
|
||||||
end
|
//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
|
||||||
|
end
|
||||||
|
|
||||||
WAIT : begin
|
START : begin
|
||||||
if (RspValid) begin
|
if (ReqReady) begin
|
||||||
ValRspData <= RspData;
|
ReqValid <= 0;
|
||||||
if (~Sticky) // update OP if it isn't currently a sticky value
|
RspReady <= 1;
|
||||||
ValRspOP <= RspOP;
|
DMIState <= WAIT;
|
||||||
if (RspOP == `OP_FAILED | RspOP == `OP_BUSY)
|
|
||||||
Sticky <= 1;
|
|
||||||
//if (RspOP == `OP_FAILED)
|
|
||||||
// ErrInfo <= 3;
|
|
||||||
DMIState <= COMPLETE;
|
|
||||||
end else if (CaptureDmi)
|
|
||||||
Sticky <= 1;
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
COMPLETE : begin
|
WAIT : begin
|
||||||
if (CaptureDmi) begin
|
if (RspValid) begin
|
||||||
RspReady <= 0;
|
ValRspData <= RspData;
|
||||||
DMIState <= IDLE;
|
if (~Sticky) // update OP if it isn't currently a sticky value
|
||||||
end
|
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
|
||||||
end
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
// jtag id register
|
||||||
idreg #(DEVICE_ID) id (.tdi(tdi_dr), .clockDR, .captureDR, .tdo(tdo_idcode));
|
idreg #(DEVICE_ID) id (.tdi(tdi_dr), .clockDR, .captureDR, .tdo(tdo_idcode));
|
||||||
|
|
||||||
// bypass register
|
// bypass register
|
||||||
always_ff @(posedge clockDR) begin
|
always_ff @(posedge clockDR) begin
|
||||||
tdo_bypass <= tdi_dr & shiftDR;
|
tdo_bypass <= tdi_dr & shiftDR;
|
||||||
end
|
end
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
@ -89,7 +89,7 @@ module datapath import cvw::*; #(parameter cvw_t P) (
|
|||||||
|
|
||||||
// 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);
|
||||||
|
@ -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
|
||||||
@ -108,6 +120,8 @@ module ieu import cvw::*; #(parameter cvw_t P) (
|
|||||||
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,
|
||||||
.IllegalIEUFPUInstrD, .IllegalBaseInstrD,
|
.IllegalIEUFPUInstrD, .IllegalBaseInstrD,
|
||||||
@ -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
|
||||||
|
@ -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);
|
||||||
@ -434,10 +429,6 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
|||||||
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
|
||||||
logic CompressedD; // instruction is compressed
|
logic CompressedD; // instruction is compressed
|
||||||
|
@ -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
|
||||||
@ -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));
|
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,
|
||||||
|
@ -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
|
||||||
|
@ -96,7 +96,12 @@ 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
|
||||||
@ -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,
|
||||||
|
@ -74,30 +74,30 @@ module wallypipelinedsoc import cvw::*; #(parameter cvw_t P) (
|
|||||||
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
|
||||||
|
Loading…
Reference in New Issue
Block a user