336 lines
12 KiB
Scala
336 lines
12 KiB
Scala
// See LICENSE for license details.
|
|
package sifive.fpgashells.shell.xilinx.vc707shell
|
|
|
|
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}
|
|
|
|
import sifive.blocks.devices.gpio._
|
|
import sifive.blocks.devices.spi._
|
|
import sifive.blocks.devices.uart._
|
|
|
|
import sifive.fpgashells.devices.xilinx.xilinxvc707mig._
|
|
import sifive.fpgashells.devices.xilinx.xilinxvc707pciex1._
|
|
import sifive.fpgashells.ip.xilinx.{IBUFDS, PowerOnResetFPGAOnly, sdio_spi_bridge, vc707_sys_clock_mmcm0,
|
|
vc707_sys_clock_mmcm1, vc707_sys_clock_mmcm2 , vc707reset}
|
|
|
|
//-------------------------------------------------------------------------
|
|
// VC707Shell
|
|
//-------------------------------------------------------------------------
|
|
|
|
trait HasDDR3 { this: VC707Shell =>
|
|
|
|
require(!p.lift(MemoryXilinxDDRKey).isEmpty)
|
|
val ddr = IO(new XilinxVC707MIGPads(p(MemoryXilinxDDRKey)))
|
|
|
|
def connectMIG(dut: HasMemoryXilinxVC707MIGModuleImp): Unit = {
|
|
// Clock & Reset
|
|
dut.xilinxvc707mig.sys_clk_i := sys_clock.asUInt
|
|
mig_clock := dut.xilinxvc707mig.ui_clk
|
|
mig_sys_reset := dut.xilinxvc707mig.ui_clk_sync_rst
|
|
mig_mmcm_locked := dut.xilinxvc707mig.mmcm_locked
|
|
dut.xilinxvc707mig.aresetn := mig_resetn
|
|
dut.xilinxvc707mig.sys_rst := sys_reset
|
|
|
|
ddr <> dut.xilinxvc707mig
|
|
}
|
|
}
|
|
|
|
trait HasPCIe { this: VC707Shell =>
|
|
val pcie = IO(new XilinxVC707PCIeX1Pads)
|
|
|
|
def connectPCIe(dut: HasSystemXilinxVC707PCIeX1ModuleImp): Unit = {
|
|
// Clock & Reset
|
|
dut.xilinxvc707pcie.axi_aresetn := pcie_dat_resetn
|
|
pcie_dat_clock := dut.xilinxvc707pcie.axi_aclk_out
|
|
pcie_cfg_clock := dut.xilinxvc707pcie.axi_ctl_aclk_out
|
|
mmcm_lock_pcie := dut.xilinxvc707pcie.mmcm_lock
|
|
dut.xilinxvc707pcie.axi_ctl_aresetn := pcie_dat_resetn
|
|
|
|
pcie <> dut.xilinxvc707pcie
|
|
}
|
|
}
|
|
|
|
trait HasDebugJTAG { this: VC707Shell =>
|
|
// 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 VC707Shell(implicit val p: Parameters) extends RawModule {
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Interface
|
|
//-----------------------------------------------------------------------
|
|
|
|
// 200Mhz differential sysclk
|
|
val sys_diff_clock_clk_n = IO(Input(Bool()))
|
|
val sys_diff_clock_clk_p = 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())
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Differential clock
|
|
//-----------------------------------------------------------------------
|
|
|
|
val sys_clk_ibufds = Module(new IBUFDS)
|
|
sys_clk_ibufds.io.I := sys_diff_clock_clk_p
|
|
sys_clk_ibufds.io.IB := sys_diff_clock_clk_n
|
|
|
|
//-----------------------------------------------------------------------
|
|
// System clock and reset
|
|
//-----------------------------------------------------------------------
|
|
|
|
// Clock that drives the clock generator and the MIG
|
|
sys_clock := sys_clk_ibufds.io.O.asClock
|
|
|
|
// Allow the debug module to reset everything. Resets the MIG
|
|
sys_reset := reset | dut_ndreset
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Clock Generator
|
|
//-----------------------------------------------------------------------
|
|
|
|
//25MHz and multiples
|
|
val vc707_sys_clock_mmcm0 = Module(new vc707_sys_clock_mmcm2)
|
|
vc707_sys_clock_mmcm0.io.clk_in1 := sys_clock.asUInt
|
|
vc707_sys_clock_mmcm0.io.reset := reset
|
|
val clk12_5 = vc707_sys_clock_mmcm0.io.clk_out1
|
|
val clk25 = vc707_sys_clock_mmcm0.io.clk_out2
|
|
val clk37_5 = vc707_sys_clock_mmcm0.io.clk_out3
|
|
val clk50 = vc707_sys_clock_mmcm0.io.clk_out4
|
|
val clk100 = vc707_sys_clock_mmcm0.io.clk_out5
|
|
val clk150 = vc707_sys_clock_mmcm0.io.clk_out6
|
|
val clk75 = vc707_sys_clock_mmcm0.io.clk_out7
|
|
val clk100_180 = vc707_sys_clock_mmcm0.io.clk_out7
|
|
val vc707_sys_clock_mmcm0_locked = vc707_sys_clock_mmcm0.io.locked
|
|
|
|
//65MHz and multiples
|
|
val vc707_sys_clock_mmcm1 = Module(new vc707_sys_clock_mmcm1)
|
|
vc707_sys_clock_mmcm1.io.clk_in1 := sys_clock.asUInt
|
|
vc707_sys_clock_mmcm1.io.reset := reset
|
|
val clk32_5 = vc707_sys_clock_mmcm1.io.clk_out1
|
|
val clk65 = vc707_sys_clock_mmcm1.io.clk_out2
|
|
val vc707_sys_clock_mmcm1_locked = vc707_sys_clock_mmcm1.io.locked
|
|
|
|
// DUT clock
|
|
dut_clock := clk37_5
|
|
|
|
//-----------------------------------------------------------------------
|
|
// System reset
|
|
//-----------------------------------------------------------------------
|
|
|
|
do_reset := !mig_mmcm_locked || !mmcm_lock_pcie || mig_sys_reset || !vc707_sys_clock_mmcm0_locked ||
|
|
!vc707_sys_clock_mmcm1_locked
|
|
mig_resetn := !mig_reset
|
|
dut_resetn := !dut_reset
|
|
pcie_dat_resetn := !pcie_dat_reset
|
|
pcie_cfg_resetn := !pcie_cfg_reset
|
|
|
|
|
|
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
|
|
}
|
|
|
|
}
|