Compare commits
	
		
			19 Commits
		
	
	
		
			master
			...
			b49f5cfa78
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| b49f5cfa78 | |||
| 700e6b640d | |||
| 12cb1c2fa5 | |||
| 7e53be49f9 | |||
| 77694a6741 | |||
| 589e9960c0 | |||
| 2707fa59a4 | |||
| 3797385a8c | |||
| 79b53cf2ae | |||
| 5bcc4e82fd | |||
| 9c06418352 | |||
| b2b19cc822 | |||
| 5db71d11c2 | |||
| f4ae1d469f | |||
| 0b421d5645 | |||
| 8329b232e2 | |||
| 2ff28e6af6 | |||
| 41362a1cb5 | |||
| e9625bf8ee | 
| @@ -0,0 +1,199 @@ | ||||
| // See LICENSE.SiFive for license details. | ||||
|  | ||||
| package sifive.fpgashells.devices.xilinx.xilinxml507mig | ||||
|  | ||||
| import Chisel._ | ||||
| import chisel3.core.{Input, Output} | ||||
| import freechips.rocketchip.config.Parameters | ||||
| import freechips.rocketchip.diplomacy._ | ||||
| import freechips.rocketchip.subsystem.{AsynchronousCrossing, HasCrossing} | ||||
| import freechips.rocketchip.tilelink._ | ||||
| import freechips.rocketchip.util._ | ||||
|  | ||||
| case class XilinxML507MIGParams( | ||||
|     address: Seq[AddressSet] | ||||
| ) | ||||
|  | ||||
| class MemoryController extends BlackBox { | ||||
|     val io = IO(new Bundle { | ||||
|         val sys = new MemorySysIO | ||||
|         val ddr2 = new MemoryDDR2IO | ||||
|  | ||||
|         val request_addr = Input(UInt(28.W)) | ||||
|         val request_type = Input(Bool()) | ||||
|         val request_data = Input(UInt(256.W)) | ||||
|         val request_mask = Input(UInt(32.W)) | ||||
|         val request_valid = Input(Bool()) | ||||
|         val request_ready = Output(Bool()) | ||||
|  | ||||
|         val response_data = Output(UInt(256.W)) | ||||
|         val response_valid = Output(Bool()) | ||||
|         // no ready, as the mig does not wait | ||||
|     }) | ||||
|  | ||||
|     override def desiredName: String = "memory_controller" | ||||
| } | ||||
|  | ||||
| class ResponseQueueIO extends Bundle { | ||||
|     val read = Bool() | ||||
|     val source = UInt() | ||||
|     val size = UInt() | ||||
| } | ||||
|  | ||||
| class XilinxML507MIGToTL(c: XilinxML507MIGParams)(implicit p: Parameters) extends LazyModule with HasCrossing { | ||||
|     // Corresponds to MIG interface with 64 bit width and a burst length of 4 | ||||
|     val width = 256 | ||||
|     val beatBytes = width/8 // 32 byte (half a cache-line, fragmented) | ||||
|  | ||||
|     val address_range = AddressRange.fromSets(c.address).head | ||||
|     require(log2Ceil(address_range.size) == 28, "Max 256MiB DIMMs supported") | ||||
|     val crossing = AsynchronousCrossing(1) | ||||
|  | ||||
|     val device = new MemoryDevice | ||||
|     val node = TLManagerNode( | ||||
|         Seq(TLManagerPortParameters( | ||||
|             Seq(TLManagerParameters( | ||||
|                 address         = c.address, | ||||
|                 resources       = device.reg, | ||||
|                 regionType      = RegionType.UNCACHED, | ||||
|                 executable      = true, | ||||
|                 supportsGet     = TransferSizes(1, beatBytes), | ||||
|                 supportsPutFull = TransferSizes(1, beatBytes), | ||||
|                 fifoId          = Some(0) // in-order | ||||
|             )), | ||||
|             beatBytes = beatBytes | ||||
|         )) | ||||
|     ) | ||||
|     // We could possibly also support supportsPutPartial, as we need support | ||||
|     // for masks anyway because of the possibility of transfers smaller that | ||||
|     // the data width (size signal, see below). | ||||
|     // Seems we can: TL$7.3 | ||||
|  | ||||
|     lazy val module = new LazyModuleImp(this) { | ||||
|         val io = IO(new Bundle { | ||||
|             val port_sys = new MemorySysIO | ||||
|             val port_ddr2 = new MemoryDDR2IO | ||||
|         }) | ||||
|  | ||||
|         val controller = Module(new MemoryController) | ||||
|         io.port_sys <> controller.io.sys | ||||
|         io.port_ddr2 <> controller.io.ddr2 | ||||
|  | ||||
|         // in: TLBundle, edge: TLEdgeIn | ||||
|         val (in, edge) = node.in(0) | ||||
|  | ||||
|         // Due to the TLFragmenter defined below, all messages are 32 bytes or | ||||
|         // smaller. The data signal of the TL channels is also 32 bytes, so | ||||
|         // all messages will be transfered in a single beat. | ||||
|         // Also, TL guarantees (see TL$4.6) that the payload of a data message | ||||
|         // is always aligned to the width of the beat, e.g. in case of a 32 | ||||
|         // byte data signal, data[7:0] will always have address 0x***00000 and | ||||
|         // data[255:247] address 0x***11111. It is also guaranteed that the | ||||
|         // mask bits always correctly reflect the active bytes inside the beat | ||||
|         // with respect to the size and address. So we can directly forward | ||||
|         // the mask, (relative) address and data to the MIG interface. | ||||
|  | ||||
|         // An AddressSet is always aligned, so we don't need to subtract the | ||||
|         // base address, we can just take the lower bits. The lowest 5 bits | ||||
|         // are used for indexing the 32 byte word of the MIG. | ||||
|         val address = in.a.bits.address(27, 0) & "hFFFFFE0".U | ||||
|  | ||||
|         // Save the source, size and type of the requests in a queue so we | ||||
|         // can synthesize the right responses in fifo order. The length also | ||||
|         // determines the maximum number of in-flight requests. | ||||
|         val ack_queue = Module(new Queue(new ResponseQueueIO, 2)) | ||||
|  | ||||
|         // Pass data directly to the controller | ||||
|         controller.io.request_addr := address | ||||
|         controller.io.request_type := !edge.hasData(in.a.bits) | ||||
|         controller.io.request_data := in.a.bits.data | ||||
|         // TL uses high to indicate valid data while mig uses low | ||||
|         controller.io.request_mask := ~ in.a.bits.mask | ||||
|  | ||||
|         ack_queue.io.enq.bits.read   := !edge.hasData(in.a.bits) | ||||
|         ack_queue.io.enq.bits.source := in.a.bits.source | ||||
|         ack_queue.io.enq.bits.size   := in.a.bits.size | ||||
|  | ||||
|         // We are ready when the controller and the queue input are ready | ||||
|         in.a.ready := controller.io.request_ready && ack_queue.io.enq.ready | ||||
|         // Both queues only latch data if the other is ready, so that data | ||||
|         // is latched into both queues or not at all | ||||
|         controller.io.request_valid := in.a.valid && ack_queue.io.enq.ready | ||||
|         ack_queue.io.enq.valid      := in.a.valid && controller.io.request_ready | ||||
|  | ||||
|  | ||||
|         // We have to buffer the responses from the MIG as it has no internal | ||||
|         // buffer and will output its read responses only for one cycle. To | ||||
|         // avoid losing any responses, this queue *must* be at least as wide | ||||
|         // as the ack queue, so that we can catch all responses, even if the | ||||
|         // ack queue is completely filled with read requests. | ||||
|         val response_queue = Module(new Queue(controller.io.response_data, 2)) | ||||
|  | ||||
|         response_queue.io.enq.bits  := controller.io.response_data | ||||
|         response_queue.io.enq.valid := controller.io.response_valid | ||||
|         // MIG does not support delaying a response, so we ignore enq.ready. | ||||
|         // This will result in lost reads and returning wrong data in further | ||||
|         // AccessAckData messages, so this must be avoided (see above). | ||||
|  | ||||
|         // Acks may or may not contain data depending on the request, but we | ||||
|         // can always pass the data, even if it is invalid in the write case, | ||||
|         // because it is ignored for AccessAck responses | ||||
|         val response_read = ack_queue.io.deq.bits.read | ||||
|         in.d.bits.opcode := Mux(response_read, TLMessages.AccessAckData, TLMessages.AccessAck) | ||||
|         in.d.bits.param  := UInt(0) // reserved, must be 0 | ||||
|         in.d.bits.size   := ack_queue.io.deq.bits.size | ||||
|         in.d.bits.source := ack_queue.io.deq.bits.source | ||||
|         in.d.bits.sink   := UInt(0) // ignored | ||||
|         in.d.bits.data   := response_queue.io.deq.bits | ||||
|         in.d.bits.error  := Bool(false) | ||||
|  | ||||
|         // The data is valid when the ack queue data is valid (write case) or | ||||
|         // when the ack *and* response queues are valid (read case) | ||||
|         in.d.valid       := ack_queue.io.deq.valid && (!response_read || | ||||
|                             response_queue.io.deq.valid) | ||||
|         // Let the ack queue dequeue when the master is ready (write case) or | ||||
|         // when the master is ready *and* there is a valid response (read case) | ||||
|         ack_queue.io.deq.ready      := in.d.ready && (!response_read || | ||||
|                                        response_queue.io.deq.valid) | ||||
|         // Let the response queue dequeue when the master is ready and there | ||||
|         // is a valid read ack waiting | ||||
|         response_queue.io.deq.ready := in.d.ready && response_read && | ||||
|                                        ack_queue.io.deq.valid | ||||
|  | ||||
|  | ||||
|         // Tie off unused channels | ||||
|         in.b.valid := Bool(false) | ||||
|         in.c.ready := Bool(true) | ||||
|         in.e.ready := Bool(true) | ||||
|     } | ||||
| } | ||||
|  | ||||
| class XilinxML507MIG(c : XilinxML507MIGParams)(implicit p: Parameters) extends LazyModule { | ||||
|     // The Fragmenter will not fragment messages <= 32 bytes, so all | ||||
|     // slaves have to support this size. 64 byte specifies the maximum | ||||
|     // supported transfer size that the slave side of the fragmenter supports | ||||
|     // against the master (here the main memory bus). Specifying alwaysMin as | ||||
|     // true results in all messages being fragmented to the minimal size | ||||
|     // (32 byte). In TL1 terms, slaves correspond roughly to managers and | ||||
|     // masters to clients (confusingly…). | ||||
|     val fragmenter = LazyModule(new TLFragmenter(32, 64, alwaysMin=true)) | ||||
|     val island = LazyModule(new XilinxML507MIGToTL(c)) | ||||
|  | ||||
|     val node: TLInwardNode = | ||||
|         island.node := island.crossTLIn := fragmenter.node | ||||
|  | ||||
|     lazy val module = new LazyModuleImp(this) { | ||||
|         val io = IO(new Bundle { | ||||
|             val port_sys = new MemorySysIO | ||||
|             val port_ddr2 = new MemoryDDR2IO | ||||
|         }) | ||||
|  | ||||
|         io.port_sys <> island.module.io.port_sys | ||||
|         io.port_ddr2 <> island.module.io.port_ddr2 | ||||
|  | ||||
|         // The MIGToTL module lives in a separate clock domain together with | ||||
|         // the MIG, which is why it is called "island". | ||||
|         island.module.clock := io.port_sys.clk0 | ||||
|         island.module.reset := io.port_sys.reset | ||||
|     } | ||||
| } | ||||
| @@ -0,0 +1,58 @@ | ||||
| // See LICENSE.SiFive for license details. | ||||
|  | ||||
| package sifive.fpgashells.devices.xilinx.xilinxml507mig | ||||
|  | ||||
| import Chisel._ | ||||
| import chisel3.core.{Input, Output} | ||||
| import chisel3.experimental.Analog | ||||
| import freechips.rocketchip.config.Field | ||||
| import freechips.rocketchip.diplomacy._ | ||||
| import freechips.rocketchip.subsystem.BaseSubsystem | ||||
|  | ||||
| case object MemoryML507Key extends Field[XilinxML507MIGParams] | ||||
|  | ||||
| trait HasMemoryML507 { this: BaseSubsystem => | ||||
|     val memory = LazyModule(new XilinxML507MIG(p(MemoryML507Key))) | ||||
|  | ||||
|     memory.node := memBuses.head.toDRAMController(Some("xilinxml507mig"))() | ||||
| } | ||||
|  | ||||
| class MemorySysIO extends Bundle { | ||||
|     val clk0 = Input(Clock()) | ||||
|     val clk90 = Input(Clock()) | ||||
|     val clkdiv0 = Input(Clock()) | ||||
|     val clk_locked = Input(Bool()) | ||||
|     val clk_idelay = Input(Clock()) | ||||
|     val reset = Input(Bool()) | ||||
| } | ||||
|  | ||||
| class MemoryDDR2IO extends Bundle { | ||||
|     val dq = Analog(64.W) | ||||
|     val a = Output(Bits(13.W)) | ||||
|     val ba = Output(Bits(2.W)) | ||||
|     val ras_n = Output(Bits(1.W)) | ||||
|     val cas_n = Output(Bits(1.W)) | ||||
|     val we_n = Output(Bits(1.W)) | ||||
|     val cs_n = Output(Bits(1.W)) | ||||
|     val odt = Output(Bits(1.W)) | ||||
|     val cke = Output(Bits(1.W)) | ||||
|     val dm = Output(Bits(8.W)) | ||||
|     val dqs = Analog(8.W) | ||||
|     val dqs_n = Analog(8.W) | ||||
|     val ck = Output(Bits(2.W)) | ||||
|     val ck_n = Output(Bits(2.W)) | ||||
| } | ||||
|  | ||||
| trait HasMemoryML507Bundle { | ||||
|     val ddr_sys: MemorySysIO | ||||
|     val ddr2: MemoryDDR2IO | ||||
| } | ||||
|  | ||||
| trait HasMemoryML507ModuleImp extends LazyModuleImp with HasMemoryML507Bundle { | ||||
|     val outer: HasMemoryML507 | ||||
|     val ddr_sys = IO(new MemorySysIO) | ||||
|     val ddr2 = IO(new MemoryDDR2IO) | ||||
|  | ||||
|     ddr_sys <> outer.memory.module.io.port_sys | ||||
|     ddr2 <> outer.memory.module.io.port_ddr2 | ||||
| } | ||||
| @@ -94,6 +94,37 @@ object PowerOnResetFPGAOnly { | ||||
|   } | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------- | ||||
| // ml507 clocks (DCM_ADV) | ||||
| //------------------------------------------------------------------------- | ||||
|  | ||||
| class ml507_sys_clock extends BlackBox { | ||||
|   val io = new Bundle { | ||||
|     val CLKIN_IN  = Clock(INPUT) | ||||
|     val CLKFX_OUT = Clock(OUTPUT) | ||||
|     val LOCKED_OUT = Bool(OUTPUT) | ||||
|   } | ||||
| } | ||||
|  | ||||
| class ml507_dvi_clock extends BlackBox { | ||||
|   val io = new Bundle { | ||||
|     val CLKIN_IN  = Clock(INPUT) | ||||
|     val CLKFX_OUT = Clock(OUTPUT) | ||||
|     val LOCKED_OUT = Bool(OUTPUT) | ||||
|   } | ||||
| } | ||||
|  | ||||
| class ml507_ddr2_clock extends BlackBox { | ||||
|   val io = new Bundle { | ||||
|     val CLKIN_P_IN = Clock(INPUT) | ||||
|     val CLKIN_N_IN = Clock(INPUT) | ||||
|     val CLK0_OUT   = Clock(OUTPUT) | ||||
|     val CLK90_OUT  = Clock(OUTPUT) | ||||
|     val CLKDV_OUT  = Clock(OUTPUT) | ||||
|     val LOCKED_OUT = Bool(OUTPUT) | ||||
|   } | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------- | ||||
| // vc707_sys_clock_mmcm | ||||
| //------------------------------------------------------------------------- | ||||
|   | ||||
							
								
								
									
										249
									
								
								src/main/scala/shell/xilinx/ML507Shell.scala
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										249
									
								
								src/main/scala/shell/xilinx/ML507Shell.scala
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,249 @@ | ||||
| // See LICENSE for license details. | ||||
| package sifive.fpgashells.shell.xilinx.ml507shell | ||||
|  | ||||
| import Chisel._ | ||||
| import chisel3.core.{Input, Output, attach} | ||||
| import chisel3.experimental.{RawModule, Analog, withClockAndReset} | ||||
|  | ||||
| import freechips.rocketchip.config._ | ||||
| import freechips.rocketchip.devices.debug._ | ||||
| import freechips.rocketchip.util.{SyncResetSynchronizerShiftReg, ElaborationArtefacts, HeterogeneousBag} | ||||
|  | ||||
| import sifive.blocks.devices.gpio._ | ||||
| import sifive.blocks.devices.spi._ | ||||
| import sifive.blocks.devices.uart._ | ||||
| import sifive.blocks.devices.chiplink._ | ||||
| import sifive.blocks.devices.terminal._ | ||||
|  | ||||
| import sifive.fpgashells.devices.xilinx.xilinxml507mig._ | ||||
| import sifive.fpgashells.ip.xilinx.{PowerOnResetFPGAOnly, sdio_spi_bridge, ml507_ddr2_clock, ml507_dvi_clock, ml507_sys_clock, vc707reset} | ||||
|  | ||||
| //------------------------------------------------------------------------- | ||||
| // ML507Shell | ||||
| //------------------------------------------------------------------------- | ||||
|  | ||||
| // TODO: trait HasDDR2 { … } | ||||
|  | ||||
| trait HasDebugJTAG { this: ML507Shell => | ||||
|   // JTAG | ||||
|   val jtag_TCK             = IO(Input(Clock())) | ||||
|   val jtag_TMS             = IO(Input(Bool())) | ||||
|   val jtag_TDI             = IO(Input(Bool())) | ||||
|   val jtag_TDO             = IO(Output(Bool())) | ||||
|  | ||||
|   def connectDebugJTAG(dut: HasPeripheryDebugModuleImp, fmcxm105: Boolean = true): SystemJTAGIO = { | ||||
|     val djtag     = dut.debug.systemjtag.get | ||||
|  | ||||
|     djtag.jtag.TCK := jtag_TCK | ||||
|     djtag.jtag.TMS := jtag_TMS | ||||
|     djtag.jtag.TDI := jtag_TDI | ||||
|     jtag_TDO       := djtag.jtag.TDO.data | ||||
|  | ||||
|     djtag.mfr_id   := p(JtagDTMKey).idcodeManufId.U(11.W) | ||||
|  | ||||
|     djtag.reset    := PowerOnResetFPGAOnly(dut_clock) | ||||
|     dut_ndreset    := dut.debug.ndreset | ||||
|     djtag | ||||
|   } | ||||
| } | ||||
|  | ||||
|  | ||||
| abstract class ML507Shell(implicit val p: Parameters) extends RawModule { | ||||
|  | ||||
|   //----------------------------------------------------------------------- | ||||
|   // Interface | ||||
|   //----------------------------------------------------------------------- | ||||
|  | ||||
|   // 100Mhz sysclk | ||||
|   val sys_clock            = IO(Input(Clock())) | ||||
|  | ||||
|   // 200MHz ddrclk | ||||
|   val ddr_clock_p          = IO(Input(Clock())) | ||||
|   val ddr_clock_n          = IO(Input(Clock())) | ||||
|  | ||||
|   // active high async reset | ||||
|   val reset                = IO(Input(Bool())) | ||||
|  | ||||
|   // LED | ||||
|   val led                  = IO(Output(Vec(8, Bool()))) | ||||
|  | ||||
|   // DIP switches | ||||
|   val dip                  = IO(Input(Vec(8, Bool()))) | ||||
|  | ||||
|   // UART | ||||
|   val uart_tx              = IO(Output(Bool())) | ||||
|   val uart_rx              = IO(Input(Bool())) | ||||
|  | ||||
|   // SDIO | ||||
|   val sdio_clk             = IO(Output(Bool())) | ||||
|   val sdio_cmd             = IO(Analog(1.W)) | ||||
|   val sdio_dat             = IO(Analog(4.W)) | ||||
|  | ||||
|   // Feedback | ||||
|   val clock_led            = IO(Output(Clock())) | ||||
|   val reset_led            = IO(Output(Bool())) | ||||
|  | ||||
|   val dvi                  = IO(new TerminalDVIIO) | ||||
|   val ddr2                 = IO(new MemoryDDR2IO) | ||||
|  | ||||
|   //----------------------------------------------------------------------- | ||||
|   // Wire declrations | ||||
|   //----------------------------------------------------------------------- | ||||
|  | ||||
|   // async resets | ||||
|   val sys_reset       = Wire(Bool()) | ||||
|   val do_reset        = Wire(Bool()) | ||||
|   val dut_ndreset     = Wire(Bool()) | ||||
|  | ||||
|   val dut_clock       = Wire(Clock()) | ||||
|   val dut_reset       = Wire(Bool()) | ||||
|  | ||||
|   val dvi_clock       = Wire(Clock()) | ||||
|   val dvi_reset       = Wire(Bool()) | ||||
|  | ||||
|   val ddr_clk0        = Wire(Clock()) | ||||
|   val ddr_clk90       = Wire(Clock()) | ||||
|   val ddr_clkdiv0     = Wire(Clock()) | ||||
|   val ddr_clk_locked  = Wire(Bool()) | ||||
|   val ddr_reset       = Wire(Bool()) | ||||
|  | ||||
|   val sd_spi_sck      = Wire(Bool()) | ||||
|   val sd_spi_cs       = Wire(Bool()) | ||||
|   val sd_spi_dq_i     = Wire(Vec(4, Bool())) | ||||
|   val sd_spi_dq_o     = Wire(Vec(4, Bool())) | ||||
|  | ||||
|   val clk_locked      = Wire(Bool()) | ||||
|  | ||||
|  | ||||
|   //----------------------------------------------------------------------- | ||||
|   // System reset | ||||
|   //----------------------------------------------------------------------- | ||||
|  | ||||
|   // Allow the debug module to reset everything. Resets the MIG | ||||
|   sys_reset := reset | dut_ndreset | ||||
|  | ||||
|   //----------------------------------------------------------------------- | ||||
|   // Clock generators | ||||
|   //----------------------------------------------------------------------- | ||||
|  | ||||
|   // 80 MHz (processor clock) | ||||
|   val ml507_sys_clock = Module(new ml507_sys_clock) | ||||
|   ml507_sys_clock.io.CLKIN_IN := sys_clock | ||||
|   dut_clock := ml507_sys_clock.io.CLKFX_OUT | ||||
|  | ||||
|   // 48 MHz (DVI pixel clock for SDR 640x480x60) | ||||
|   val ml507_dvi_clock = Module(new ml507_dvi_clock) | ||||
|   ml507_dvi_clock.io.CLKIN_IN := sys_clock | ||||
|   dvi_clock := ml507_dvi_clock.io.CLKFX_OUT | ||||
|  | ||||
|   // 200 MHz (DDR2 and IDELAY clock) | ||||
|   val ml507_ddr2_clock = Module(new ml507_ddr2_clock) | ||||
|   ml507_ddr2_clock.io.CLKIN_P_IN := ddr_clock_p | ||||
|   ml507_ddr2_clock.io.CLKIN_N_IN := ddr_clock_n | ||||
|   ddr_clk0 := ml507_ddr2_clock.io.CLK0_OUT | ||||
|   ddr_clk90 := ml507_ddr2_clock.io.CLK90_OUT | ||||
|   ddr_clkdiv0 := ml507_ddr2_clock.io.CLKDV_OUT | ||||
|   ddr_clk_locked := ml507_ddr2_clock.io.LOCKED_OUT | ||||
|  | ||||
|   // Clocks locked? | ||||
|   clk_locked := ml507_sys_clock.io.LOCKED_OUT & | ||||
|                 ml507_dvi_clock.io.LOCKED_OUT & | ||||
|                 ddr_clk_locked | ||||
|  | ||||
|   //----------------------------------------------------------------------- | ||||
|   // System reset | ||||
|   //----------------------------------------------------------------------- | ||||
|  | ||||
|   do_reset             := !clk_locked || sys_reset | ||||
|  | ||||
|   // synchronize async resets | ||||
|   val safe_reset = Module(new vc707reset) | ||||
|  | ||||
|   safe_reset.io.areset := do_reset | ||||
|   safe_reset.io.clock1 := ddr_clk0 | ||||
|   ddr_reset            := safe_reset.io.reset1 | ||||
|   safe_reset.io.clock2 := dut_clock | ||||
|   safe_reset.io.clock3 := dvi_clock | ||||
|   dvi_reset            := safe_reset.io.reset3 | ||||
|   safe_reset.io.clock4 := dut_clock | ||||
|   dut_reset            := safe_reset.io.reset4 | ||||
|  | ||||
|   // Setup feedback | ||||
|   clock_led := dut_clock | ||||
|   reset_led := dut_reset | ||||
|  | ||||
|   //----------------------------------------------------------------------- | ||||
|   // Terminal | ||||
|   //----------------------------------------------------------------------- | ||||
|  | ||||
|   def connectTerminal(dut: HasPeripheryTerminalModuleImp): Unit = { | ||||
|     dvi <> dut.dvi | ||||
|     dut.terminal.clk := dvi_clock | ||||
|     dut.terminal.reset := dvi_reset | ||||
|   } | ||||
|  | ||||
|   //----------------------------------------------------------------------- | ||||
|   // Memory controller | ||||
|   //----------------------------------------------------------------------- | ||||
|  | ||||
|   def connectDDRMemory(dut: HasMemoryML507ModuleImp): Unit = { | ||||
|     ddr2 <> dut.ddr2 | ||||
|  | ||||
|     dut.ddr_sys.clk0 := ddr_clk0 | ||||
|     dut.ddr_sys.clk90 := ddr_clk90 | ||||
|     dut.ddr_sys.clkdiv0 := ddr_clkdiv0 | ||||
|     dut.ddr_sys.clk_locked := ddr_clk_locked | ||||
|     dut.ddr_sys.clk_idelay := ddr_clk0 | ||||
|     dut.ddr_sys.reset := ddr_reset | ||||
|   } | ||||
|  | ||||
|   //----------------------------------------------------------------------- | ||||
|   // UART | ||||
|   //----------------------------------------------------------------------- | ||||
|  | ||||
|   def connectUART(dut: HasPeripheryUARTModuleImp): Unit = { | ||||
|     val uartParams = p(PeripheryUARTKey) | ||||
|     if (!uartParams.isEmpty) { | ||||
|       // uart connections | ||||
|       dut.uart(0).rxd := SyncResetSynchronizerShiftReg(uart_rx, 2, init = Bool(true), name=Some("uart_rxd_sync")) | ||||
|       uart_tx         := dut.uart(0).txd | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   //----------------------------------------------------------------------- | ||||
|   // SPI | ||||
|   //----------------------------------------------------------------------- | ||||
|  | ||||
|   def connectSPI(dut: HasPeripherySPIModuleImp): Unit = { | ||||
|     // SPI | ||||
|     sd_spi_sck := dut.spi(0).sck | ||||
|     sd_spi_cs  := dut.spi(0).cs(0) | ||||
|  | ||||
|     dut.spi(0).dq.zipWithIndex.foreach { | ||||
|       case(pin, idx) => | ||||
|         sd_spi_dq_o(idx) := pin.o | ||||
|         pin.i            := sd_spi_dq_i(idx) | ||||
|     } | ||||
|  | ||||
|     //------------------------------------------------------------------- | ||||
|     // SDIO <> SPI Bridge | ||||
|     //------------------------------------------------------------------- | ||||
|  | ||||
|     val ip_sdio_spi = Module(new sdio_spi_bridge()) | ||||
|  | ||||
|     ip_sdio_spi.io.clk   := dut_clock | ||||
|     ip_sdio_spi.io.reset := dut_reset | ||||
|  | ||||
|     // SDIO | ||||
|     attach(sdio_dat, ip_sdio_spi.io.sd_dat) | ||||
|     attach(sdio_cmd, ip_sdio_spi.io.sd_cmd) | ||||
|     sdio_clk := ip_sdio_spi.io.spi_sck | ||||
|  | ||||
|     // SPI | ||||
|     ip_sdio_spi.io.spi_sck  := sd_spi_sck | ||||
|     ip_sdio_spi.io.spi_cs   := sd_spi_cs | ||||
|     sd_spi_dq_i             := ip_sdio_spi.io.spi_dq_i.toBools | ||||
|     ip_sdio_spi.io.spi_dq_o := sd_spi_dq_o.asUInt | ||||
|   } | ||||
|  | ||||
| } | ||||
		Reference in New Issue
	
	Block a user