From e9625bf8ee21c467a8bb6df3f9304c17411c93b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Klemens=20Sch=C3=B6lhorn?= Date: Thu, 12 Apr 2018 00:42:46 +0200 Subject: [PATCH] Add initial ML507Shell stub based on VC707Shell --- src/main/scala/ip/xilinx/Xilinx.scala | 8 + src/main/scala/shell/xilinx/ML507Shell.scala | 275 +++++++++++++++++++ 2 files changed, 283 insertions(+) create mode 100644 src/main/scala/shell/xilinx/ML507Shell.scala diff --git a/src/main/scala/ip/xilinx/Xilinx.scala b/src/main/scala/ip/xilinx/Xilinx.scala index db8a965..779335c 100644 --- a/src/main/scala/ip/xilinx/Xilinx.scala +++ b/src/main/scala/ip/xilinx/Xilinx.scala @@ -94,6 +94,14 @@ object PowerOnResetFPGAOnly { } } +// ML507 clock generation +class ml507_sys_clock extends BlackBox { + val io = new Bundle { + val CLKIN_IN = Bool(INPUT) + val CLKFX_OUT = Clock(OUTPUT) + } +} + //------------------------------------------------------------------------- // vc707_sys_clock_mmcm //------------------------------------------------------------------------- diff --git a/src/main/scala/shell/xilinx/ML507Shell.scala b/src/main/scala/shell/xilinx/ML507Shell.scala new file mode 100644 index 0000000..158c422 --- /dev/null +++ b/src/main/scala/shell/xilinx/ML507Shell.scala @@ -0,0 +1,275 @@ +// 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.fpgashells.ip.xilinx.{IBUFDS, PowerOnResetFPGAOnly, sdio_spi_bridge, 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 = { + + ElaborationArtefacts.add( + """debugjtag.vivado.tcl""", + """set vc707debugjtag_vivado_tcl_dir [file dirname [file normalize [info script]]] + add_files -fileset [current_fileset -constrset] [glob -directory $vc707debugjtag_vivado_tcl_dir {*.vc707debugjtag.xdc}]""" + ) + + if(fmcxm105) { + //VC707 constraints for Xilinx FMC XM105 Debug Card + ElaborationArtefacts.add( + """vc707debugjtag.xdc""", + """set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets jtag_TCK_IBUF] + set_property -dict { PACKAGE_PIN R32 IOSTANDARD LVCMOS18 PULLUP TRUE } [get_ports {jtag_TCK}] + set_property -dict { PACKAGE_PIN W36 IOSTANDARD LVCMOS18 PULLUP TRUE } [get_ports {jtag_TMS}] + set_property -dict { PACKAGE_PIN W37 IOSTANDARD LVCMOS18 PULLUP TRUE } [get_ports {jtag_TDI}] + set_property -dict { PACKAGE_PIN V40 IOSTANDARD LVCMOS18 PULLUP TRUE } [get_ports {jtag_TDO}] """ + ) + } else { + //VC707 constraints for Olimex connect to LCD panel header + ElaborationArtefacts.add( + """vc707debugjtag.xdc""", + """ + #Olimex Pin Olimex Function LCD Pin LCD Function FPGA Pin + #1 VREF 14 5V + #3 TTRST_N 1 LCD_DB7 AN40 + #5 TTDI 2 LCD_DB6 AR39 + #7 TTMS 3 LCD_DB5 AR38 + #9 TTCK 4 LCD_DB4 AT42 + #11 TRTCK NC NC NC + #13 TTDO 9 LCD_E AT40 + #15 TSRST_N 10 LCD_RW AR42 + #2 VREF 14 5V + #18 GND 13 GND + set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets jtag_TCK_IBUF] + set_property -dict { PACKAGE_PIN AT42 IOSTANDARD LVCMOS18 PULLUP TRUE } [get_ports {jtag_TCK}] + set_property -dict { PACKAGE_PIN AR38 IOSTANDARD LVCMOS18 PULLUP TRUE } [get_ports {jtag_TMS}] + set_property -dict { PACKAGE_PIN AR39 IOSTANDARD LVCMOS18 PULLUP TRUE } [get_ports {jtag_TDI}] + set_property -dict { PACKAGE_PIN AT40 IOSTANDARD LVCMOS18 PULLUP TRUE } [get_ports {jtag_TDO}] """ + ) + } + + 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_100 = IO(Input(Bool())) + + // active high reset + val reset = IO(Input(Bool())) + + // LED + val led = IO(Vec(8, Output(Bool()))) + + // UART + val uart_tx = IO(Output(Bool())) + val uart_rx = IO(Input(Bool())) + val uart_rtsn = IO(Output(Bool())) + val uart_ctsn = IO(Input(Bool())) + + // SDIO + val sdio_clk = IO(Output(Bool())) + val sdio_cmd = IO(Analog(1.W)) + val sdio_dat = IO(Analog(4.W)) + + //Buttons + val btn_0 = IO(Analog(1.W)) + val btn_1 = IO(Analog(1.W)) + val btn_2 = IO(Analog(1.W)) + val btn_3 = IO(Analog(1.W)) + + //Sliding switches + val sw_0 = IO(Analog(1.W)) + val sw_1 = IO(Analog(1.W)) + val sw_2 = IO(Analog(1.W)) + val sw_3 = IO(Analog(1.W)) + val sw_4 = IO(Analog(1.W)) + val sw_5 = IO(Analog(1.W)) + val sw_6 = IO(Analog(1.W)) + val sw_7 = IO(Analog(1.W)) + + + //----------------------------------------------------------------------- + // Wire declrations + //----------------------------------------------------------------------- + + val sys_clock = Wire(Clock()) + val sys_reset = Wire(Bool()) + + val dut_clock = Wire(Clock()) + val dut_reset = Wire(Bool()) + val dut_resetn = Wire(Bool()) + + val dut_ndreset = 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 mig_mmcm_locked = Wire(Bool()) + val mig_sys_reset = Wire(Bool()) + + val mig_clock = Wire(Clock()) + val mig_reset = Wire(Bool()) + val mig_resetn = Wire(Bool()) + + val pcie_dat_reset = Wire(Bool()) + val pcie_dat_resetn = Wire(Bool()) + val pcie_cfg_reset = Wire(Bool()) + val pcie_cfg_resetn = Wire(Bool()) + val pcie_dat_clock = Wire(Clock()) + val pcie_cfg_clock = Wire(Clock()) + val mmcm_lock_pcie = Wire(Bool()) + + + //----------------------------------------------------------------------- + // System clock and 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 + //----------------------------------------------------------------------- + + //50MHz (37.5MHz) + 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 + + // DUT clock + dut_clock := clk50 + + //----------------------------------------------------------------------- + // System reset + //----------------------------------------------------------------------- + + do_reset := !mig_mmcm_locked || !mmcm_lock_pcie || mig_sys_reset + mig_resetn := !mig_reset + dut_resetn := !dut_reset + pcie_dat_resetn := !pcie_dat_reset + pcie_cfg_resetn := !pcie_cfg_reset + + // TODO: adapt for ml507? + val safe_reset = Module(new vc707reset) + + safe_reset.io.areset := do_reset + safe_reset.io.clock1 := mig_clock + mig_reset := safe_reset.io.reset1 + safe_reset.io.clock2 := pcie_dat_clock + pcie_dat_reset := safe_reset.io.reset2 + safe_reset.io.clock3 := pcie_cfg_clock + pcie_cfg_reset := safe_reset.io.reset3 + safe_reset.io.clock4 := dut_clock + dut_reset := safe_reset.io.reset4 + + //overrided in connectMIG and connect PCIe + //provide defaults to allow above reset sequencing logic to work without both + mig_clock := dut_clock + pcie_dat_clock := dut_clock + pcie_cfg_clock := dut_clock + mig_mmcm_locked := UInt("b1") + mmcm_lock_pcie := UInt("b1") + + + + //----------------------------------------------------------------------- + // UART + //----------------------------------------------------------------------- + + uart_rtsn := false.B + + 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 + } + +}