2016-08-19 18:46:43 +02:00
|
|
|
package rocketchip
|
|
|
|
|
|
|
|
import Chisel._
|
|
|
|
import uncore.devices.{DebugBusIO, AsyncDebugBusTo, AsyncDebugBusFrom, DebugBusReq, DebugBusResp, DMKey}
|
|
|
|
import junctions._
|
2016-08-19 23:01:33 +02:00
|
|
|
import cde.{Parameters, Field}
|
|
|
|
|
|
|
|
case object IncludeJtagDTM extends Field[Boolean]
|
2016-08-19 18:46:43 +02:00
|
|
|
|
|
|
|
/* JTAG-based Debug Transport Module
|
|
|
|
* and synchronization logic.
|
|
|
|
*
|
|
|
|
* This implements JTAG interface described
|
|
|
|
* in the RISC-V Debug Specification
|
|
|
|
*
|
|
|
|
* This Module is currently a
|
|
|
|
* wrapper around a number of black-boxed
|
|
|
|
* modules. The black-boxing is due to the fact that
|
|
|
|
* Chisel doesn't currently support:
|
|
|
|
* - Negative Edge Clocking
|
|
|
|
* - Asynchronous Resets
|
|
|
|
* (The tristate requirements of JTAG are exported from the
|
|
|
|
* Chisel domain with the DRV_TDO signal).
|
|
|
|
*
|
|
|
|
* The AsyncDebugBus parameter here is overloaded.
|
|
|
|
* The DebugTransportModule JTAG definately needs a synchronizer,
|
|
|
|
* the parameter just currently selects whether the Chisel-generated
|
|
|
|
* crossing is used or the black-boxed crossing is used.
|
|
|
|
* Although Top is also capable of generating the
|
|
|
|
* Chisel sychnronizers, it is done here for consistency
|
|
|
|
* of keeping the synchronizers in one place when
|
|
|
|
* instantiating the DTM.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
class JtagDTMWithSync(implicit val p: Parameters) extends Module {
|
|
|
|
|
|
|
|
// IO <-> [Chisel Sync?] <-> [DebugBusIO<->UInt] <-> [Black Box Sync?] <-> DTM Black Box
|
|
|
|
|
|
|
|
val io = new Bundle {
|
|
|
|
|
|
|
|
val jtag = new JtagIO(true).flip()
|
|
|
|
val debug = new DebugBusIO()(p)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
val req_width = io.debug.req.bits.getWidth
|
|
|
|
val resp_width = io.debug.resp.bits.getWidth
|
|
|
|
|
|
|
|
val jtag_dtm = Module (new DebugTransportModuleJtag(req_width, resp_width))
|
|
|
|
|
|
|
|
jtag_dtm.io.jtag <> io.jtag
|
|
|
|
|
|
|
|
val dtm_req = Wire(new DecoupledIO(UInt(width = req_width)))
|
|
|
|
val dtm_resp = Wire(new DecoupledIO(UInt(width = resp_width)))
|
|
|
|
|
|
|
|
val io_debug_bus = Wire (new DebugBusIO)
|
|
|
|
|
|
|
|
// Optionally instantiate the Chisel synchronizers.
|
|
|
|
// These go on this side of the DebugBusIO->UInt translation
|
|
|
|
// because the Chisel synchronizers understand these data structures.
|
|
|
|
if (p(AsyncDebugBus)){
|
|
|
|
io.debug <> AsyncDebugBusFrom(io.jtag.TCK, io.jtag.TRST, io_debug_bus)
|
|
|
|
} else {
|
|
|
|
io.debug <> io_debug_bus
|
|
|
|
}
|
|
|
|
|
|
|
|
// Translate from straight 'bits' interface of the blackboxes
|
|
|
|
// into the Resp/Req data structures.
|
|
|
|
io_debug_bus.req.valid := dtm_req.valid
|
|
|
|
io_debug_bus.req.bits := new DebugBusReq(p(DMKey).nDebugBusAddrSize).fromBits(dtm_req.bits)
|
|
|
|
dtm_req.ready := io_debug_bus.req.ready
|
|
|
|
|
|
|
|
dtm_resp.valid := io_debug_bus.resp.valid
|
|
|
|
dtm_resp.bits := io_debug_bus.resp.bits.asUInt
|
|
|
|
io_debug_bus.resp.ready := dtm_resp.ready
|
|
|
|
|
|
|
|
// Optionally instantiate the black-box synchronizers
|
|
|
|
// instead of the chisel ones.
|
|
|
|
// These go on this side of the DebugBusIO->UInt translation
|
|
|
|
// because they do not understand the DebugBusIO data structures.
|
|
|
|
|
|
|
|
if (p(AsyncDebugBus)) {
|
|
|
|
dtm_req <> jtag_dtm.io.dtm_req
|
|
|
|
jtag_dtm.io.dtm_resp <> dtm_resp
|
|
|
|
} else {
|
|
|
|
val req_sync = Module (new AsyncMailbox())
|
|
|
|
val resp_sync = Module (new AsyncMailbox())
|
|
|
|
req_sync.io.enq := jtag_dtm.io.dtm_req
|
|
|
|
req_sync.io.enq_clock.get := io.jtag.TCK
|
|
|
|
req_sync.io.enq_reset.get := io.jtag.TRST
|
|
|
|
req_sync.io.deq_clock.get := clock
|
|
|
|
req_sync.io.deq_reset.get := reset
|
|
|
|
dtm_req := req_sync.io.deq
|
|
|
|
|
|
|
|
jtag_dtm.io.dtm_resp := resp_sync.io.deq
|
|
|
|
resp_sync.io.deq_clock.get := io.jtag.TCK
|
|
|
|
resp_sync.io.deq_reset.get := io.jtag.TRST
|
|
|
|
resp_sync.io.enq_clock.get := clock
|
|
|
|
resp_sync.io.enq_reset.get := reset
|
|
|
|
resp_sync.io.enq := dtm_resp
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class DebugTransportModuleJtag(reqSize : Int, respSize : Int)(implicit val p: Parameters) extends BlackBox {
|
|
|
|
|
|
|
|
val io = new Bundle {
|
|
|
|
val jtag = new JtagIO(true).flip()
|
|
|
|
|
|
|
|
val dtm_req = new DecoupledIO(UInt(width = reqSize))
|
|
|
|
|
|
|
|
val dtm_resp = new DecoupledIO(UInt(width = respSize)).flip()
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
class AsyncMailbox extends BlackBox {
|
|
|
|
|
|
|
|
// This Verilog module is parameterized, but until this is supported by Chisel,
|
|
|
|
// this mailbox just has a fixed width of 64 bits, which is enough
|
|
|
|
// for our specific purpose here.
|
|
|
|
|
|
|
|
val io = new Crossing(UInt(width=64), true, true)
|
|
|
|
|
|
|
|
}
|