Compare commits
	
		
			11 Commits
		
	
	
		
			b2b19cc822
			...
			b49f5cfa78
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| b49f5cfa78 | |||
| 700e6b640d | |||
| 12cb1c2fa5 | |||
| 7e53be49f9 | |||
| 77694a6741 | |||
| 589e9960c0 | |||
| 2707fa59a4 | |||
| 3797385a8c | |||
| 79b53cf2ae | |||
| 5bcc4e82fd | |||
| 9c06418352 | 
@@ -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,15 +94,37 @@ object PowerOnResetFPGAOnly {
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ML507 clock generation
 | 
			
		||||
//-------------------------------------------------------------------------
 | 
			
		||||
// ml507 clocks (DCM_ADV)
 | 
			
		||||
//-------------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
class ml507_sys_clock extends BlackBox {
 | 
			
		||||
  val io = new Bundle {
 | 
			
		||||
    val CLKIN_IN  = Bool(INPUT)
 | 
			
		||||
    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
 | 
			
		||||
//-------------------------------------------------------------------------
 | 
			
		||||
 
 | 
			
		||||
@@ -13,8 +13,10 @@ 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.ip.xilinx.{IBUFDS, PowerOnResetFPGAOnly, sdio_spi_bridge, ml507_sys_clock , vc707reset}
 | 
			
		||||
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
 | 
			
		||||
@@ -53,13 +55,20 @@ abstract class ML507Shell(implicit val p: Parameters) extends RawModule {
 | 
			
		||||
  //-----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  // 100Mhz sysclk
 | 
			
		||||
  val sys_clock_100        = IO(Input(Bool()))
 | 
			
		||||
  val sys_clock            = IO(Input(Clock()))
 | 
			
		||||
 | 
			
		||||
  // active high reset
 | 
			
		||||
  // 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(Vec(8, Output(Bool())))
 | 
			
		||||
  val led                  = IO(Output(Vec(8, Bool())))
 | 
			
		||||
 | 
			
		||||
  // DIP switches
 | 
			
		||||
  val dip                  = IO(Input(Vec(8, Bool())))
 | 
			
		||||
 | 
			
		||||
  // UART
 | 
			
		||||
  val uart_tx              = IO(Output(Bool()))
 | 
			
		||||
@@ -70,70 +79,76 @@ abstract class ML507Shell(implicit val p: Parameters) extends RawModule {
 | 
			
		||||
  val sdio_cmd             = IO(Analog(1.W))
 | 
			
		||||
  val sdio_dat             = IO(Analog(4.W))
 | 
			
		||||
 | 
			
		||||
  //Buttons
 | 
			
		||||
  val btn_0                = IO(Input(Bool()))
 | 
			
		||||
  val btn_1                = IO(Input(Bool()))
 | 
			
		||||
  val btn_2                = IO(Input(Bool()))
 | 
			
		||||
  val btn_3                = IO(Input(Bool()))
 | 
			
		||||
 | 
			
		||||
  //Sliding switches
 | 
			
		||||
  val sw_0                 = IO(Input(Bool()))
 | 
			
		||||
  val sw_1                 = IO(Input(Bool()))
 | 
			
		||||
  val sw_2                 = IO(Input(Bool()))
 | 
			
		||||
  val sw_3                 = IO(Input(Bool()))
 | 
			
		||||
  val sw_4                 = IO(Input(Bool()))
 | 
			
		||||
  val sw_5                 = IO(Input(Bool()))
 | 
			
		||||
  val sw_6                 = IO(Input(Bool()))
 | 
			
		||||
  val sw_7                 = IO(Input(Bool()))
 | 
			
		||||
 | 
			
		||||
  // 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
 | 
			
		||||
  //-----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  val sys_clock       = Wire(Clock())
 | 
			
		||||
  // 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 dut_ndreset     = 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 do_reset        = Wire(Bool())
 | 
			
		||||
 | 
			
		||||
  val clk_locked      = Wire(Bool())
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  //-----------------------------------------------------------------------
 | 
			
		||||
  // System clock and reset
 | 
			
		||||
  // System reset
 | 
			
		||||
  //-----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  // Clock that drives the clock generator and the MIG
 | 
			
		||||
  sys_clock := sys_clock_100.asClock()
 | 
			
		||||
 | 
			
		||||
  // Allow the debug module to reset everything. Resets the MIG
 | 
			
		||||
  sys_reset := reset | dut_ndreset
 | 
			
		||||
 | 
			
		||||
  //-----------------------------------------------------------------------
 | 
			
		||||
  // Clock Generator
 | 
			
		||||
  // Clock generators
 | 
			
		||||
  //-----------------------------------------------------------------------
 | 
			
		||||
 | 
			
		||||
  //50MHz (37.5MHz)
 | 
			
		||||
  // 80 MHz (processor clock)
 | 
			
		||||
  val ml507_sys_clock = Module(new ml507_sys_clock)
 | 
			
		||||
  ml507_sys_clock.io.CLKIN_IN := sys_clock.asUInt
 | 
			
		||||
  val clk50 = ml507_sys_clock.io.CLKFX_OUT
 | 
			
		||||
  clk_locked := ml507_sys_clock.io.LOCKED_OUT
 | 
			
		||||
  ml507_sys_clock.io.CLKIN_IN := sys_clock
 | 
			
		||||
  dut_clock := ml507_sys_clock.io.CLKFX_OUT
 | 
			
		||||
 | 
			
		||||
  // DUT clock
 | 
			
		||||
  dut_clock := clk50
 | 
			
		||||
  // 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
 | 
			
		||||
@@ -141,13 +156,15 @@ abstract class ML507Shell(implicit val p: Parameters) extends RawModule {
 | 
			
		||||
 | 
			
		||||
  do_reset             := !clk_locked || sys_reset
 | 
			
		||||
 | 
			
		||||
  // TODO: adapt for ml507?
 | 
			
		||||
  // synchronize async resets
 | 
			
		||||
  val safe_reset = Module(new vc707reset)
 | 
			
		||||
 | 
			
		||||
  safe_reset.io.areset := do_reset
 | 
			
		||||
  safe_reset.io.clock1 := dut_clock
 | 
			
		||||
  safe_reset.io.clock1 := ddr_clk0
 | 
			
		||||
  ddr_reset            := safe_reset.io.reset1
 | 
			
		||||
  safe_reset.io.clock2 := dut_clock
 | 
			
		||||
  safe_reset.io.clock3 := 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
 | 
			
		||||
 | 
			
		||||
@@ -155,6 +172,31 @@ abstract class ML507Shell(implicit val p: Parameters) extends RawModule {
 | 
			
		||||
  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
 | 
			
		||||
  //-----------------------------------------------------------------------
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user