diff --git a/src/main/scala/devices/xilinx/xilinxvc709mig/XilinxVC709MIG.scala b/src/main/scala/devices/xilinx/xilinxvc709mig/XilinxVC709MIG.scala new file mode 100644 index 00000000..bac63af0 --- /dev/null +++ b/src/main/scala/devices/xilinx/xilinxvc709mig/XilinxVC709MIG.scala @@ -0,0 +1,179 @@ +// See LICENSE for license details. +package sifive.fpgashells.devices.xilinx.xilinxvc709mig + +import Chisel._ +import chisel3.experimental.{Analog,attach} +import freechips.rocketchip.amba.axi4._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.subsystem._ +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.interrupts._ +import sifive.fpgashells.ip.xilinx.vc709mig.{VC709MIGIOClocksReset, VC709MIGIODDR, vc709mig} + +case class XilinxVC709MIGParams( + address : Seq[AddressSet] +) + +class XilinxVC709MIGPads(depth : BigInt) extends VC709MIGIODDR(depth) { + def this(c : XilinxVC709MIGParams) { + this(AddressRange.fromSets(c.address).head.size) + } +} + +class XilinxVC709MIGIO(depth : BigInt) extends VC709MIGIODDR(depth) with VC709MIGIOClocksReset + +class XilinxVC709MIGIsland(c : XilinxVC709MIGParams)(implicit p: Parameters) extends LazyModule with CrossesToOnlyOneClockDomain { + val ranges = AddressRange.fromSets(c.address) + require (ranges.size == 1, "DDR range must be contiguous") + val offset = ranges.head.base + val depth = ranges.head.size + val crossing = AsynchronousCrossing(8) + require((depth<=0x100000000L),"vc709mig supports upto 4GB depth configuraton") + + val device = new MemoryDevice + val node = AXI4SlaveNode(Seq(AXI4SlavePortParameters( + slaves = Seq(AXI4SlaveParameters( + address = c.address, + resources = device.reg, + regionType = RegionType.UNCACHED, + executable = true, + supportsWrite = TransferSizes(1, 128), + supportsRead = TransferSizes(1, 128))), + beatBytes = 8))) + + lazy val module = new LazyRawModuleImp(this) { + val io = IO(new Bundle { + val port = new XilinxVC709MIGIO(depth) + }) + + childClock := io.port.ui_clk + childReset := io.port.ui_clk_sync_rst + + //MIG black box instantiation + val blackbox = Module(new vc709mig(depth)) + val (axi_async, _) = node.in(0) + + //pins to top level + + //inouts + //#[DDR3 SODIMM 0] + attach(io.port.ddr3_dq,blackbox.io.ddr3_dq) + attach(io.port.ddr3_dqs_n,blackbox.io.ddr3_dqs_n) + attach(io.port.ddr3_dqs_p,blackbox.io.ddr3_dqs_p) + + //outputs + //#[DDR3 SODIMM 0] + io.port.ddr3_addr := blackbox.io.ddr3_addr + io.port.ddr3_ba := blackbox.io.ddr3_ba + io.port.ddr3_ras_n := blackbox.io.ddr3_ras_n + io.port.ddr3_cas_n := blackbox.io.ddr3_cas_n + io.port.ddr3_we_n := blackbox.io.ddr3_we_n + io.port.ddr3_reset_n := blackbox.io.ddr3_reset_n + io.port.ddr3_ck_p := blackbox.io.ddr3_ck_p + io.port.ddr3_ck_n := blackbox.io.ddr3_ck_n + io.port.ddr3_cke := blackbox.io.ddr3_cke + io.port.ddr3_cs_n := blackbox.io.ddr3_cs_n + io.port.ddr3_dm := blackbox.io.ddr3_dm + io.port.ddr3_odt := blackbox.io.ddr3_odt + + //inputs + //NO_BUFFER clock + blackbox.io.sys_clk_i := io.port.sys_clk_i + + //#[DDR3 SODIMM 0] + io.port.ui_clk := blackbox.io.ui_clk + io.port.ui_clk_sync_rst := blackbox.io.ui_clk_sync_rst + io.port.mmcm_locked := blackbox.io.mmcm_locked + blackbox.io.aresetn := io.port.aresetn + blackbox.io.app_sr_req := Bool(false) + blackbox.io.app_ref_req := Bool(false) + blackbox.io.app_zq_req := Bool(false) + //app_sr_active := unconnected + //app_ref_ack := unconnected + //app_zq_ack := unconnected + + val awaddr = axi_async.aw.bits.addr - UInt(offset) + val araddr = axi_async.ar.bits.addr - UInt(offset) + + // [DDR3 SODIMM 0] + //slave AXI interface write address ports + blackbox.io.s_axi_awid := axi_async.aw.bits.id + blackbox.io.s_axi_awaddr := awaddr //truncated + blackbox.io.s_axi_awlen := axi_async.aw.bits.len + blackbox.io.s_axi_awsize := axi_async.aw.bits.size + blackbox.io.s_axi_awburst := axi_async.aw.bits.burst + blackbox.io.s_axi_awlock := axi_async.aw.bits.lock + blackbox.io.s_axi_awcache := UInt("b0011") + blackbox.io.s_axi_awprot := axi_async.aw.bits.prot + blackbox.io.s_axi_awqos := axi_async.aw.bits.qos + blackbox.io.s_axi_awvalid := axi_async.aw.valid + axi_async.aw.ready := blackbox.io.s_axi_awready + + //slave interface write data ports + blackbox.io.s_axi_wdata := axi_async.w.bits.data + blackbox.io.s_axi_wstrb := axi_async.w.bits.strb + blackbox.io.s_axi_wlast := axi_async.w.bits.last + blackbox.io.s_axi_wvalid := axi_async.w.valid + axi_async.w.ready := blackbox.io.s_axi_wready + + //slave interface write response + blackbox.io.s_axi_bready := axi_async.b.ready + axi_async.b.bits.id := blackbox.io.s_axi_bid + axi_async.b.bits.resp := blackbox.io.s_axi_bresp + axi_async.b.valid := blackbox.io.s_axi_bvalid + + //slave AXI interface read address ports + blackbox.io.s_axi_arid := axi_async.ar.bits.id + blackbox.io.s_axi_araddr := araddr // truncated + blackbox.io.s_axi_arlen := axi_async.ar.bits.len + blackbox.io.s_axi_arsize := axi_async.ar.bits.size + blackbox.io.s_axi_arburst := axi_async.ar.bits.burst + blackbox.io.s_axi_arlock := axi_async.ar.bits.lock + blackbox.io.s_axi_arcache := UInt("b0011") + blackbox.io.s_axi_arprot := axi_async.ar.bits.prot + blackbox.io.s_axi_arqos := axi_async.ar.bits.qos + blackbox.io.s_axi_arvalid := axi_async.ar.valid + + axi_async.ar.ready := blackbox.io.s_axi_arready + + //slace AXI interface read data ports + blackbox.io.s_axi_rready := axi_async.r.ready + axi_async.r.bits.id := blackbox.io.s_axi_rid + axi_async.r.bits.data := blackbox.io.s_axi_rdata + axi_async.r.bits.resp := blackbox.io.s_axi_rresp + axi_async.r.bits.last := blackbox.io.s_axi_rlast + axi_async.r.valid := blackbox.io.s_axi_rvalid + + //misc + io.port.init_calib_complete := blackbox.io.init_calib_complete + + blackbox.io.sys_rst :=io.port.sys_rst + //mig.device_temp_i :- unconnected + //mig.device_temp :- unconnceted + } +} + +class XilinxVC709MIG(c : XilinxVC709MIGParams)(implicit p: Parameters) extends LazyModule { + val ranges = AddressRange.fromSets(c.address) + val depth = ranges.head.size + + // The data follows from top to down + val buffer = LazyModule(new TLBuffer) + val toaxi4 = LazyModule(new TLToAXI4(adapterName = Some("mem"))) + val indexer = LazyModule(new AXI4IdIndexer(idBits = 4)) + val deint = LazyModule(new AXI4Deinterleaver(p(CacheBlockBytes))) + val yank = LazyModule(new AXI4UserYanker) + val island = LazyModule(new XilinxVC709MIGIsland(c)) + + val node: TLInwardNode = + island.crossAXI4In(island.node) := yank.node := deint.node := indexer.node := toaxi4.node := buffer.node + + lazy val module = new LazyModuleImp(this) { + val io = IO(new Bundle { + val port = new XilinxVC709MIGIO(depth) + }) + + io.port <> island.module.io.port + } +} diff --git a/src/main/scala/devices/xilinx/xilinxvc709mig/XilinxVC709MIGPeriphery.scala b/src/main/scala/devices/xilinx/xilinxvc709mig/XilinxVC709MIGPeriphery.scala new file mode 100644 index 00000000..93f23ccd --- /dev/null +++ b/src/main/scala/devices/xilinx/xilinxvc709mig/XilinxVC709MIGPeriphery.scala @@ -0,0 +1,35 @@ +// See LICENSE for license details. +package sifive.fpgashells.devices.xilinx.xilinxvc709mig + +import Chisel._ +import freechips.rocketchip.config._ +import freechips.rocketchip.subsystem.BaseSubsystem +import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, AddressRange} + +case object MemoryXilinxDDRKey extends Field[XilinxVC709MIGParams] + +trait HasMemoryXilinxVC709MIG { this: BaseSubsystem => + val module: HasMemoryXilinxVC709MIGModuleImp + + val xilinxvc709mig = LazyModule(new XilinxVC709MIG(p(MemoryXilinxDDRKey))) + + xilinxvc709mig.node := mbus.toDRAMController(Some("xilinxvc709mig"))() +} + +trait HasMemoryXilinxVC709MIGBundle { + val xilinxvc709mig: XilinxVC709MIGIO + def connectXilinxVC709MIGToPads(pads: XilinxVC709MIGPads) { + pads <> xilinxvc709mig + } +} + +trait HasMemoryXilinxVC709MIGModuleImp extends LazyModuleImp + with HasMemoryXilinxVC709MIGBundle { + val outer: HasMemoryXilinxVC709MIG + val ranges = AddressRange.fromSets(p(MemoryXilinxDDRKey).address) + require (ranges.size == 1, "DDR range must be contiguous") + val depth = ranges.head.size + val xilinxvc709mig = IO(new XilinxVC709MIGIO(depth)) + + xilinxvc709mig <> outer.xilinxvc709mig.module.io.port +} diff --git a/src/main/scala/devices/xilinx/xilinxvc709pcie/XilinxVC709PCIe.scala b/src/main/scala/devices/xilinx/xilinxvc709pcie/XilinxVC709PCIe.scala new file mode 100644 index 00000000..d39d350f --- /dev/null +++ b/src/main/scala/devices/xilinx/xilinxvc709pcie/XilinxVC709PCIe.scala @@ -0,0 +1,76 @@ +// See LICENSE for license details. +package sifive.fpgashells.devices.xilinx.xilinxvc709pcie + +import Chisel._ +import freechips.rocketchip.amba.axi4._ +import freechips.rocketchip.config.Parameters +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.interrupts._ +import freechips.rocketchip.subsystem.{CrossesToOnlyOneClockDomain, CacheBlockBytes} +import sifive.fpgashells.ip.xilinx.vc709axi_to_pcie.{VC709AXIToPCIe, VC709AXIToPCIeIOClocksReset, VC709AXIToPCIeIOSerial} +import sifive.fpgashells.ip.xilinx.ibufds_gte2.IBUFDS_GTE2 + +trait VC709AXIToPCIeRefClk extends Bundle{ + val REFCLK_rxp = Bool(INPUT) + val REFCLK_rxn = Bool(INPUT) +} + +class XilinxVC709PCIePads extends Bundle + with VC709AXIToPCIeIOSerial + with VC709AXIToPCIeRefClk + +class XilinxVC709PCIeIO extends Bundle + with VC709AXIToPCIeRefClk + with VC709AXIToPCIeIOSerial + with VC709AXIToPCIeIOClocksReset { + val axi_ctl_aresetn = Bool(INPUT) +} + +class XilinxVC709PCIe(implicit p: Parameters, val crossing: ClockCrossingType = AsynchronousCrossing(8)) + extends LazyModule with CrossesToOnlyOneClockDomain +{ + val axi_to_pcie = LazyModule(new VC709AXIToPCIe) + + val slave: TLInwardNode = + (axi_to_pcie.slave + := AXI4Buffer() + := AXI4UserYanker() + := AXI4Deinterleaver(p(CacheBlockBytes)) + := AXI4IdIndexer(idBits=4) + := TLToAXI4(adapterName = Some("pcie-slave"))) + + val control: TLInwardNode = + (axi_to_pcie.control + := AXI4Buffer() + := AXI4UserYanker(capMaxFlight = Some(2)) + := TLToAXI4() + := TLFragmenter(4, p(CacheBlockBytes), holdFirstDeny = true)) + + val master: TLOutwardNode = + (TLWidthWidget(8) + := AXI4ToTL() + := AXI4UserYanker(capMaxFlight=Some(8)) + := AXI4Fragmenter() + := axi_to_pcie.master) + + val intnode: IntOutwardNode = axi_to_pcie.intnode + + lazy val module = new LazyRawModuleImp(this) { + val io = IO(new Bundle { + val port = new XilinxVC709PCIeIO + }) + + childClock := io.port.axi_aclk // axi_aclk_out is changed to axi_aclk + childReset := ~io.port.axi_aresetn // + + io.port <> axi_to_pcie.module.io.port + + //PCIe Reference Clock + val ibufds_gte2 = Module(new IBUFDS_GTE2) + axi_to_pcie.module.io.refclk := ibufds_gte2.io.O // REFCLK is changed to refclk + ibufds_gte2.io.CEB := UInt(0) + ibufds_gte2.io.I := io.port.REFCLK_rxp + ibufds_gte2.io.IB := io.port.REFCLK_rxn + } +} diff --git a/src/main/scala/devices/xilinx/xilinxvc709pcie/XilinxVC709PCIePeriphery.scala b/src/main/scala/devices/xilinx/xilinxvc709pcie/XilinxVC709PCIePeriphery.scala new file mode 100644 index 00000000..a0b7aafd --- /dev/null +++ b/src/main/scala/devices/xilinx/xilinxvc709pcie/XilinxVC709PCIePeriphery.scala @@ -0,0 +1,32 @@ +// See LICENSE for license details. +package sifive.fpgashells.devices.xilinx.xilinxvc709pcie + +import Chisel._ +import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, BufferParams} +import freechips.rocketchip.subsystem.BaseSubsystem +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.interrupts.IntSyncCrossingSink + +trait HasSystemXilinxVC709PCIe { this: BaseSubsystem => + val xilinxvc709pcie = LazyModule(new XilinxVC709PCIe) + private val cname = "xilinxvc709pcie" + sbus.coupleFrom(s"master_named_$cname") { _ :=* TLFIFOFixer(TLFIFOFixer.all) :=* xilinxvc709pcie.crossTLOut(xilinxvc709pcie.master) } + sbus.coupleTo(s"slave_named_$cname") { xilinxvc709pcie.crossTLIn(xilinxvc709pcie.slave) :*= TLWidthWidget(sbus.beatBytes) :*= _ } + sbus.coupleTo(s"controller_named_$cname") { xilinxvc709pcie.crossTLIn(xilinxvc709pcie.control) :*= TLWidthWidget(sbus.beatBytes) :*= _ } + ibus.fromSync := xilinxvc709pcie.crossIntOut(xilinxvc709pcie.intnode) +} + +trait HasSystemXilinxVC709PCIeBundle { + val xilinxvc709pcie: XilinxVC709PCIeIO + def connectXilinxVC709PCIeToPads(pads: XilinxVC709PCIePads) { + pads <> xilinxvc709pcie + } +} + +trait HasSystemXilinxVC709PCIeModuleImp extends LazyModuleImp + with HasSystemXilinxVC709PCIeBundle { + val outer: HasSystemXilinxVC709PCIe + val xilinxvc709pcie = IO(new XilinxVC709PCIeIO) + + xilinxvc709pcie <> outer.xilinxvc709pcie.module.io.port +} \ No newline at end of file diff --git a/src/main/scala/ip/xilinx/vc709axi_to_pcie/vc709axi_to_pcie.scala b/src/main/scala/ip/xilinx/vc709axi_to_pcie/vc709axi_to_pcie.scala new file mode 100644 index 00000000..760bbd9f --- /dev/null +++ b/src/main/scala/ip/xilinx/vc709axi_to_pcie/vc709axi_to_pcie.scala @@ -0,0 +1,378 @@ +// See LICENSE for license details. +package sifive.fpgashells.ip.xilinx.vc709axi_to_pcie + +import Chisel._ +import freechips.rocketchip.config._ +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.amba.axi4._ +import freechips.rocketchip.interrupts._ +import freechips.rocketchip.util.{ElaborationArtefacts} + +// AXI Bridge for PCI Express Gen3 Subsystem v3.0 +// Product Guide Vivado Design Suite PG194 (v3.0) July 22, 2020 +// IP VLNV: xilinx.com:customize_ip:vc709pcietoaxi:3.0 +// Black Box Signals named _exactly_ as per Vivado generated verilog +trait VC709AXIToPCIeIOSerial extends Bundle { + def NUM_LANES = 8 + // PCIe Interface + val pci_exp_txp = Bits(OUTPUT,NUM_LANES) + val pci_exp_txn = Bits(OUTPUT,NUM_LANES) + val pci_exp_rxp = Bits(INPUT,NUM_LANES) + val pci_exp_rxn = Bits(INPUT,NUM_LANES) +} + +trait VC709AXIToPCIeIOClocksReset extends Bundle { + // Global Signals + val axi_aresetn = Bool(INPUT) + val axi_aclk = Clock(OUTPUT) +} + +//scalastyle:off +//turn off linter: blackbox name must match verilog module +class vc709axi_to_pcie() extends BlackBox +{ + def AXI_ADDR_WIDTH = 32 + def AXI_DATA_WIDTH = 128 + val io = new Bundle with VC709AXIToPCIeIOSerial + with VC709AXIToPCIeIOClocksReset { + // Global Signals + val refclk = Bool(INPUT) + val interrupt_out = Bool(OUTPUT) + + // AXI Bridge for PCIe Gen3 MSI Signals + val intx_msi_request = Bool(INPUT) + val intx_msi_grant = Bool(OUTPUT) + val msi_enable = Bool(OUTPUT) + val msi_vector_width = Bits(OUTPUT,3) + val msi_vector_num = Bits(INPUT,5) + + // AXI Slave Interface + // write address + val s_axi_awid = Bits(INPUT,4) + val s_axi_awaddr = Bits(INPUT,AXI_ADDR_WIDTH) + val s_axi_awregion = Bits(INPUT,4) + val s_axi_awlen = Bits(INPUT,8) + val s_axi_awsize = Bits(INPUT,3) + val s_axi_awburst = Bits(INPUT,2) + val s_axi_awvalid = Bool(INPUT) + val s_axi_awready = Bool(OUTPUT) + // write data + val s_axi_wdata = Bits(INPUT,AXI_DATA_WIDTH) + val s_axi_wstrb = Bits(INPUT,16) + val s_axi_wlast = Bool(INPUT) + val s_axi_wvalid = Bool(INPUT) + val s_axi_wready = Bool(OUTPUT) + // write response + val s_axi_bready = Bool(INPUT) + val s_axi_bid = Bits(OUTPUT,4) + val s_axi_bresp = Bits(OUTPUT,2) + val s_axi_bvalid = Bool(OUTPUT) + // read address + val s_axi_arid = Bits(INPUT,4) + val s_axi_araddr = Bits(INPUT,AXI_ADDR_WIDTH) + val s_axi_arregion = Bits(INPUT,4) + val s_axi_arlen = Bits(INPUT,8) + val s_axi_arsize = Bits(INPUT,3) + val s_axi_arburst = Bits(INPUT,2) + val s_axi_arvalid = Bool(INPUT) + val s_axi_arready = Bool(OUTPUT) + //slave interface read data + val s_axi_rready = Bool(INPUT) + val s_axi_rid = Bits(OUTPUT,4) + val s_axi_rdata = Bits(OUTPUT,AXI_DATA_WIDTH) + val s_axi_rresp = Bits(OUTPUT,2) + val s_axi_rlast = Bool(OUTPUT) + val s_axi_rvalid = Bool(OUTPUT) + + // AXI Master Interface + // write address + val m_axi_awaddr = Bits(OUTPUT,AXI_ADDR_WIDTH) + val m_axi_awlen = Bits(OUTPUT,8) + val m_axi_awsize = Bits(OUTPUT,3) + val m_axi_awburst = Bits(OUTPUT,2) + val m_axi_awprot = Bits(OUTPUT,3) + val m_axi_awvalid = Bool(OUTPUT) + val m_axi_awlock = Bits(OUTPUT,1) + val m_axi_awcache = Bits(OUTPUT,4) + val m_axi_awready = Bool(INPUT) + // write data + val m_axi_wdata = Bits(OUTPUT,AXI_DATA_WIDTH) + val m_axi_wstrb = Bits(OUTPUT,16) + val m_axi_wlast = Bool(OUTPUT) + val m_axi_wvalid = Bool(OUTPUT) + val m_axi_wready = Bool(INPUT) + // write response + val m_axi_bready = Bool(OUTPUT) + val m_axi_bresp = Bits(INPUT,2) + val m_axi_bvalid = Bool(INPUT) + // read address + val m_axi_araddr = Bits(OUTPUT,AXI_ADDR_WIDTH) + val m_axi_arlen = Bits(OUTPUT,8) + val m_axi_arsize = Bits(OUTPUT,3) + val m_axi_arburst = Bits(OUTPUT,2) + val m_axi_arprot = Bits(OUTPUT,3) + val m_axi_arvalid = Bool(OUTPUT) + val m_axi_arlock = Bits(OUTPUT,1) + val m_axi_arcache = Bits(OUTPUT,4) + val m_axi_arready = Bool(INPUT) + // read data + val m_axi_rready = Bool(OUTPUT) + val m_axi_rdata = Bits(INPUT,AXI_DATA_WIDTH) + val m_axi_rresp = Bits(INPUT,2) + val m_axi_rlast = Bool(INPUT) + val m_axi_rvalid = Bool(INPUT) + + // AXI4-Lite Control Interface + val s_axi_ctl_awaddr = Bits(INPUT,28) + val s_axi_ctl_awvalid = Bool(INPUT) + val s_axi_ctl_awready = Bool(OUTPUT) + val s_axi_ctl_wdata = Bits(INPUT,32) + val s_axi_ctl_wstrb = Bits(INPUT,4) + val s_axi_ctl_wvalid = Bool(INPUT) + val s_axi_ctl_wready = Bool(OUTPUT) + val s_axi_ctl_bresp = Bits(OUTPUT,2) + val s_axi_ctl_bvalid = Bool(OUTPUT) + val s_axi_ctl_bready = Bool(INPUT) + val s_axi_ctl_araddr = Bits(INPUT,28) + val s_axi_ctl_arvalid = Bool(INPUT) + val s_axi_ctl_arready = Bool(OUTPUT) + val s_axi_ctl_rdata = Bits(OUTPUT,32) + val s_axi_ctl_rresp = Bits(OUTPUT,2) + val s_axi_ctl_rvalid = Bool(OUTPUT) + val s_axi_ctl_rready = Bool(INPUT) + } +} +//scalastyle:off + +//wrap vc709_axi_to_pcie black box in Nasti Bundles +// see Chipyard doc: 9.1.2 Manager Node +class VC709AXIToPCIe(implicit p:Parameters) extends LazyModule +{ + // device-tree node + val device = new SimpleDevice("pci", Seq("xlnx,axi-pcie-host-1.00.a")) { + override def describe(resources: ResourceBindings): Description = { + val Description(name, mapping) = super.describe(resources) + val intc = "pcie_intc" + def ofInt(x: Int) = Seq(ResourceInt(BigInt(x))) + def ofMap(x: Int) = Seq(0, 0, 0, x).flatMap(ofInt) ++ Seq(ResourceReference(intc)) ++ ofInt(x) + val extra = Map( + "#address-cells" -> ofInt(3), + "#size-cells" -> ofInt(2), + "#interrupt-cells" -> ofInt(1), + "device_type" -> Seq(ResourceString("pci")), + "interrupt-map-mask" -> Seq(0, 0, 0, 7).flatMap(ofInt), + "interrupt-map" -> Seq(1, 2, 3, 4).flatMap(ofMap), + "ranges" -> resources("ranges").map(x => + (x: @unchecked) match { case Binding(_, ResourceAddress(address, perms)) => + ResourceMapping(address, BigInt(0x02000000) << 64, perms) }), + "interrupt-controller" -> Seq(ResourceMap(labels = Seq(intc), value = Map( + "interrupt-controller" -> Nil, + "#address-cells" -> ofInt(0), + "#interrupt-cells" -> ofInt(1))))) + Description(name, mapping ++ extra) + } + } + + val slave = AXI4SlaveNode(Seq(AXI4SlavePortParameters( + slaves = Seq(AXI4SlaveParameters( + address = List(AddressSet(0x40000000L, 0x1fffffffL)), + resources = Seq(Resource(device, "ranges")), + executable = true, + supportsWrite = TransferSizes(1, 128), + supportsRead = TransferSizes(1, 128))), + beatBytes = 8))) + + val control = AXI4SlaveNode(Seq(AXI4SlavePortParameters( + slaves = Seq(AXI4SlaveParameters( + address = List(AddressSet(0x2000000000L, 0x3ffffffL)), // when truncated to 32-bits, is 0 + resources = device.reg("control"), + supportsWrite = TransferSizes(1, 4), + supportsRead = TransferSizes(1, 4), + interleavedId = Some(0))), // AXI4-Lite never interleaves responses + beatBytes = 4))) + + val master = AXI4MasterNode(Seq(AXI4MasterPortParameters( + masters = Seq(AXI4MasterParameters( + name = "VC709 PCIe", + id = IdRange(0, 1), + aligned = false))))) + + val intnode = IntSourceNode(IntSourcePortSimple(resources = device.int)) + + lazy val module = new LazyModuleImp(this) { + // The master on the control port must be AXI-lite + require (control.edges.in(0).master.endId == 1) + // Must have exactly the right number of idBits + require (slave.edges.in(0).bundle.idBits == 4) + + class VC709AXIToPCIeIOBundle extends Bundle with VC709AXIToPCIeIOSerial + with VC709AXIToPCIeIOClocksReset; + + val io = IO(new Bundle { + val port = new VC709AXIToPCIeIOBundle + val refclk = Bool(INPUT) // REFCLK is changed to refclk in 3.0 + }) + + val blackbox = Module(new vc709axi_to_pcie) + + val (s, _) = slave.in(0) + val (c, _) = control.in(0) + val (m, _) = master.out(0) + val (i, _) = intnode.out(0) + + //to top level + blackbox.io.axi_aresetn := io.port.axi_aresetn + io.port.axi_aclk := blackbox.io.axi_aclk + io.port.pci_exp_txp := blackbox.io.pci_exp_txp + io.port.pci_exp_txn := blackbox.io.pci_exp_txn + blackbox.io.pci_exp_rxp := io.port.pci_exp_rxp + blackbox.io.pci_exp_rxn := io.port.pci_exp_rxn + i(0) := blackbox.io.interrupt_out + blackbox.io.refclk := io.refclk + + // AXI Slave Interface + // write address + blackbox.io.s_axi_awid := s.aw.bits.id + blackbox.io.s_axi_awaddr := s.aw.bits.addr + blackbox.io.s_axi_awlen := s.aw.bits.len + blackbox.io.s_axi_awsize := s.aw.bits.size + blackbox.io.s_axi_awburst := s.aw.bits.burst + blackbox.io.s_axi_awregion := UInt(0) + blackbox.io.s_axi_awvalid := s.aw.valid + s.aw.ready := blackbox.io.s_axi_awready + // write data + blackbox.io.s_axi_wdata := s.w.bits.data + blackbox.io.s_axi_wstrb := s.w.bits.strb + blackbox.io.s_axi_wlast := s.w.bits.last + blackbox.io.s_axi_wvalid := s.w.valid + s.w.ready := blackbox.io.s_axi_wready + // write response + s.b.bits.id := blackbox.io.s_axi_bid + s.b.bits.resp := blackbox.io.s_axi_bresp + s.b.valid := blackbox.io.s_axi_bvalid + blackbox.io.s_axi_bready := s.b.ready + // read address + blackbox.io.s_axi_arid := s.ar.bits.id + blackbox.io.s_axi_araddr := s.ar.bits.addr + blackbox.io.s_axi_arlen := s.ar.bits.len + blackbox.io.s_axi_arsize := s.ar.bits.size + blackbox.io.s_axi_arburst := s.ar.bits.burst + blackbox.io.s_axi_arregion := UInt(0) + blackbox.io.s_axi_arvalid := s.ar.valid + s.ar.ready := blackbox.io.s_axi_arready + // read data + s.r.bits.id := blackbox.io.s_axi_rid + s.r.bits.data := blackbox.io.s_axi_rdata + s.r.bits.resp := blackbox.io.s_axi_rresp + s.r.bits.last := blackbox.io.s_axi_rlast + s.r.valid := blackbox.io.s_axi_rvalid + blackbox.io.s_axi_rready := s.r.ready + + // AXI4-Lite Control Interface + // write address + blackbox.io.s_axi_ctl_awaddr := c.aw.bits.addr + blackbox.io.s_axi_ctl_awvalid := c.aw.valid + c.aw.ready := blackbox.io.s_axi_ctl_awready + // write data + blackbox.io.s_axi_ctl_wdata := c.w.bits.data + blackbox.io.s_axi_ctl_wstrb := c.w.bits.strb + blackbox.io.s_axi_ctl_wvalid := c.w.valid + c.w.ready := blackbox.io.s_axi_ctl_wready + // write response + blackbox.io.s_axi_ctl_bready := c.b.ready + c.b.bits.id := UInt(0) + c.b.bits.resp := blackbox.io.s_axi_ctl_bresp + c.b.valid := blackbox.io.s_axi_ctl_bvalid + // read address + blackbox.io.s_axi_ctl_araddr := c.ar.bits.addr + blackbox.io.s_axi_ctl_arvalid := c.ar.valid + c.ar.ready := blackbox.io.s_axi_ctl_arready + // read data + blackbox.io.s_axi_ctl_rready := c.r.ready + c.r.bits.id := UInt(0) + c.r.bits.data := blackbox.io.s_axi_ctl_rdata + c.r.bits.resp := blackbox.io.s_axi_ctl_rresp + c.r.bits.last := Bool(true) + c.r.valid := blackbox.io.s_axi_ctl_rvalid + + // AXI Master Interface + // write address + m.aw.bits.id := UInt(0) + m.aw.bits.addr := blackbox.io.m_axi_awaddr + m.aw.bits.len := blackbox.io.m_axi_awlen + m.aw.bits.size := blackbox.io.m_axi_awsize + m.aw.bits.burst := blackbox.io.m_axi_awburst + m.aw.bits.prot := blackbox.io.m_axi_awprot + m.aw.bits.lock := blackbox.io.m_axi_awlock + m.aw.bits.cache := blackbox.io.m_axi_awcache + m.aw.bits.qos := UInt(0) + m.aw.valid := blackbox.io.m_axi_awvalid + blackbox.io.m_axi_awready := m.aw.ready + // write data + m.w.bits.data := blackbox.io.m_axi_wdata + m.w.bits.strb := blackbox.io.m_axi_wstrb + m.w.bits.last := blackbox.io.m_axi_wlast + m.w.valid := blackbox.io.m_axi_wvalid + blackbox.io.m_axi_wready := m.w.ready + // write response + blackbox.io.m_axi_bresp := m.b.bits.resp + blackbox.io.m_axi_bvalid := m.b.valid + m.b.ready := blackbox.io.m_axi_bready + // read address + m.ar.bits.id := UInt(0) + m.ar.bits.addr := blackbox.io.m_axi_araddr + m.ar.bits.len := blackbox.io.m_axi_arlen + m.ar.bits.size := blackbox.io.m_axi_arsize + m.ar.bits.burst := blackbox.io.m_axi_arburst + m.ar.bits.lock := blackbox.io.m_axi_arlock + m.ar.bits.cache := blackbox.io.m_axi_arcache + m.ar.bits.prot := blackbox.io.m_axi_arprot + m.ar.bits.qos := UInt(0) + m.ar.valid := blackbox.io.m_axi_arvalid + blackbox.io.m_axi_arready := m.ar.ready + // read data + blackbox.io.m_axi_rdata := m.r.bits.data + blackbox.io.m_axi_rresp := m.r.bits.resp + blackbox.io.m_axi_rlast := m.r.bits.last + blackbox.io.m_axi_rvalid := m.r.valid + m.r.ready := blackbox.io.m_axi_rready + } + + ElaborationArtefacts.add( + "vc709axi_to_pcie.vivado.tcl", + """ + create_ip -vendor xilinx.com -library ip -version 3.0 -name axi_pcie3 -module_name vc709axi_to_pcie -dir $ipdir -force + set_property -dict [list \ + CONFIG.AXIBAR2PCIEBAR_0 {0x40000000} \ + CONFIG.AXIBAR_0 {0x40000000} \ + CONFIG.AXIBAR_HIGHADDR_0 {0x5FFFFFFF} \ + CONFIG.AXIBAR_NUM {1} \ + CONFIG.BASEADDR {0x00000000} \ + CONFIG.HIGHADDR {0x03FFFFFF} \ + CONFIG.DEVICE_PORT_TYPE {Root_Port_of_PCI_Express_Root_Complex} \ + CONFIG.INCLUDE_BAROFFSET_REG {true} \ + CONFIG.PCIEBAR2AXIBAR_0 {0x00000000} \ + CONFIG.PCIE_BLK_LOCN {X0Y0} \ + CONFIG.PL_LINK_CAP_MAX_LINK_WIDTH {X8} \ + CONFIG.PL_LINK_CAP_MAX_LINK_SPEED {2.5_GT/s} \ + CONFIG.PF0_DEVICE_ID {7118} \ + CONFIG.PF0_REVISION_ID {0} \ + CONFIG.PF0_SUBSYSTEM_VENDOR_ID {10EE} \ + CONFIG.PF0_SUBSYSTEM_ID {0007} \ + CONFIG.PF0_BAR0_64BIT {true} \ + CONFIG.PF0_BAR0_ENABLED {true} \ + CONFIG.PF0_BAR0_PREFETCHABLE {false} \ + CONFIG.PF0_BAR0_SCALE {Gigabytes} \ + CONFIG.PF0_BAR0_SIZE {4} \ + CONFIG.PF0_BAR0_TYPE {Memory} \ + CONFIG.PF0_BASE_CLASS_MENU {Bridge_device} \ + CONFIG.PF0_SUB_CLASS_interface_menu {Host_bridge} \ + CONFIG.PF0_CLASS_CODE {0x060000} \ + CONFIG.COMP_TIMEOUT {50ms} \ + CONFIG.REF_CLK_FREQ {100_MHz} \ + CONFIG.AXI_ADDR_WIDTH {32} \ + CONFIG.AXI_DATA_WIDTH {128_bit} \ + CONFIG.C_S_AXI_SUPPORTS_NARROW_BURST {false} \ + CONFIG.XLNX_REF_BOARD {VC709} ] [get_ips vc709axi_to_pcie]""" + ) +} diff --git a/src/main/scala/ip/xilinx/vc709mig/vc709mig.scala b/src/main/scala/ip/xilinx/vc709mig/vc709mig.scala new file mode 100644 index 00000000..c13fe735 --- /dev/null +++ b/src/main/scala/ip/xilinx/vc709mig/vc709mig.scala @@ -0,0 +1,542 @@ +// See LICENSE for license details. +package sifive.fpgashells.ip.xilinx.vc709mig + +import Chisel._ +import chisel3.util._ +import chisel3.experimental.{Analog,attach} +import freechips.rocketchip.util.{ElaborationArtefacts} +import freechips.rocketchip.util.GenericParameterizedBundle +import freechips.rocketchip.config._ + +// IP VLNV: xilinx.com:customize_ip:vc709mig:4.1 +// Black Box + +class VC709MIGIODDR(depth : BigInt) extends GenericParameterizedBundle(depth) { + require((depth<=0x200000000L),"VC709MIGIODDR supports upto 4GB depth configuraton") + val ddr3_addr = Bits(OUTPUT,16) + val ddr3_ba = Bits(OUTPUT,3) + val ddr3_ras_n = Bool(OUTPUT) + val ddr3_cas_n = Bool(OUTPUT) + val ddr3_we_n = Bool(OUTPUT) + val ddr3_reset_n = Bool(OUTPUT) + val ddr3_ck_p = Bits(OUTPUT,1) + val ddr3_ck_n = Bits(OUTPUT,1) + val ddr3_cke = Bits(OUTPUT,1) + val ddr3_cs_n = Bits(OUTPUT,1) + val ddr3_odt = Bits(OUTPUT,1) + val ddr3_dm = Bits(OUTPUT,8) + + val ddr3_dq = Analog(64.W) + val ddr3_dqs_n = Analog(8.W) + val ddr3_dqs_p = Analog(8.W) +} + +//reused directly in io bundle for sifive.blocks.devices.xilinxvc709mig +trait VC709MIGIOClocksReset extends Bundle { + //inputs + //"NO_BUFFER" clock source (must be connected to IBUF outside of IP) + val sys_clk_i = Bool(INPUT) + //user interface signals + val ui_clk = Clock(OUTPUT) + val ui_clk_sync_rst = Bool(OUTPUT) + val mmcm_locked = Bool(OUTPUT) + val aresetn = Bool(INPUT) + //misc + val init_calib_complete = Bool(OUTPUT) + val sys_rst = Bool(INPUT) +} + +//scalastyle:off +//turn off linter: blackbox name must match verilog module +class vc709mig(depth : BigInt)(implicit val p:Parameters) extends BlackBox +{ + require((depth<=0x200000000L), "vc709mig supports upto 8GB depth configuraton") + + override def desiredName = "vc709mig_a" + + def DDR3_ADDR_WIDTH = 32 + def DDR3_DATA_WIDTH = 64 + + val io = new VC709MIGIODDR(depth) with VC709MIGIOClocksReset { + // User interface signals + val app_sr_req = Bool(INPUT) + val app_ref_req = Bool(INPUT) + val app_zq_req = Bool(INPUT) + val app_sr_active = Bool(OUTPUT) + val app_ref_ack = Bool(OUTPUT) + val app_zq_ack = Bool(OUTPUT) + //axi_s + //slave interface write address ports + val s_axi_awid = Bits(INPUT,4) + val s_axi_awaddr = Bits(INPUT,DDR3_ADDR_WIDTH) + val s_axi_awlen = Bits(INPUT,8) + val s_axi_awsize = Bits(INPUT,3) + val s_axi_awburst = Bits(INPUT,2) + val s_axi_awlock = Bits(INPUT,1) + val s_axi_awcache = Bits(INPUT,4) + val s_axi_awprot = Bits(INPUT,3) + val s_axi_awqos = Bits(INPUT,4) + val s_axi_awvalid = Bool(INPUT) + val s_axi_awready = Bool(OUTPUT) + //slave interface write data ports + val s_axi_wdata = Bits(INPUT,DDR3_DATA_WIDTH) + val s_axi_wstrb = Bits(INPUT,8) + val s_axi_wlast = Bool(INPUT) + val s_axi_wvalid = Bool(INPUT) + val s_axi_wready = Bool(OUTPUT) + //slave interface write response ports + val s_axi_bready = Bool(INPUT) + val s_axi_bid = Bits(OUTPUT,4) + val s_axi_bresp = Bits(OUTPUT,2) + val s_axi_bvalid = Bool(OUTPUT) + //slave interface read address ports + val s_axi_arid = Bits(INPUT,4) + val s_axi_araddr = Bits(INPUT,DDR3_ADDR_WIDTH) + val s_axi_arlen = Bits(INPUT,8) + val s_axi_arsize = Bits(INPUT,3) + val s_axi_arburst = Bits(INPUT,2) + val s_axi_arlock = Bits(INPUT,1) + val s_axi_arcache = Bits(INPUT,4) + val s_axi_arprot = Bits(INPUT,3) + val s_axi_arqos = Bits(INPUT,4) + val s_axi_arvalid = Bool(INPUT) + val s_axi_arready = Bool(OUTPUT) + //slave interface read data ports + val s_axi_rready = Bool(INPUT) + val s_axi_rid = Bits(OUTPUT,4) + val s_axi_rdata = Bits(OUTPUT,DDR3_DATA_WIDTH) + val s_axi_rresp = Bits(OUTPUT,2) + val s_axi_rlast = Bool(OUTPUT) + val s_axi_rvalid = Bool(OUTPUT) + //misc + val device_temp_i = Bits(INPUT,12) + // val device_temp = Bits(OUTPUT,12) + } + + val vc709mig_a = """ { + + + vc709mig_a + 1 + 1 + OFF + 1024 + ON + Disabled + xc7vx690t-ffg1761/-2 + 4.1 + No Buffer + Use System Clock + ACTIVE HIGH + FALSE + 0 + 50 Ohms + 0 + + DDR3_SDRAM/SODIMMs/MT8KTF51264HZ-1G9 + 1250 + 2.0V + 4:1 + 200 + 0 + 800 + 1.000 + 1 + 1 + 1 + 1 + 64 + 1 + 1 + Disabled + Normal + 4 + FALSE + + 16 + 10 + 3 + 1.5V + BANK_ROW_COLUMN + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 8 - Fixed + Sequential + 11 + Normal + No + Slow Exit + Enable + RZQ/7 + Disable + Enable + RZQ/6 + 0 + Disabled + Enabled + Output Buffer Enabled + Full Array + 8 + Enabled + Normal + Dynamic ODT off + AXI + + RD_PRI_REG + 32 + 64 + 4 + 0 + + + + +}""" + + val vc709mig_b = """ { + + + vc709mig_b + 1 + 1 + OFF + 1024 + ON + Disabled + xc7vx690t-ffg1761/-2 + 4.1 + No Buffer + Use System Clock + ACTIVE HIGH + FALSE + 0 + 50 Ohms + 0 + + DDR3_SDRAM/SODIMMs/MT8KTF51264HZ-1G9 + 1250 + 2.0V + 4:1 + 200 + 0 + 800 + 1.000 + 1 + 1 + 1 + 1 + 64 + 1 + 1 + Disabled + Normal + 4 + FALSE + + 16 + 10 + 3 + 1.5V + BANK_ROW_COLUMN + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 8 - Fixed + Sequential + 11 + Normal + No + Slow Exit + Enable + RZQ/7 + Disable + Enable + RZQ/6 + 0 + Disabled + Enabled + Output Buffer Enabled + Full Array + 8 + Enabled + Normal + Dynamic ODT off + AXI + + RD_PRI_REG + 32 + 64 + 4 + 0 + + + + +}""" + + def add_vc709mig(migprj : String, modulename : String) = + ElaborationArtefacts.add( + "%1$s.vivado.tcl".format(modulename), + """set migprj %1$s + set migprjfile {/%2$s.prj} + set migprjfilepath $ipdir$migprjfile + set fp [open $migprjfilepath w+] + puts $fp $migprj + close $fp + create_ip -vendor xilinx.com -library ip -name mig_7series -module_name %2$s -dir $ipdir -force + set_property CONFIG.XML_INPUT_FILE $migprjfilepath [get_ips %2$s] """.format(migprj, modulename) + ) + + add_vc709mig(vc709mig_a, "vc709mig_a") + add_vc709mig(vc709mig_b, "vc709mig_b") + + // addResource("/vsrc/vc709mig8gb.v") +} +//scalastyle:on diff --git a/src/main/scala/shell/DDROverlay.scala b/src/main/scala/shell/DDROverlay.scala index be0ed9e0..45019bbd 100644 --- a/src/main/scala/shell/DDROverlay.scala +++ b/src/main/scala/shell/DDROverlay.scala @@ -24,4 +24,4 @@ abstract class DDRPlacedOverlay[IO <: Data](val name: String, val di: DDRDesignI extends IOPlacedOverlay[IO, DDRDesignInput, DDRShellInput, DDROverlayOutput] { implicit val p = di.p -} +} \ No newline at end of file diff --git a/src/main/scala/shell/PCIeOverlay.scala b/src/main/scala/shell/PCIeOverlay.scala index 072104dd..d6ed571d 100644 --- a/src/main/scala/shell/PCIeOverlay.scala +++ b/src/main/scala/shell/PCIeOverlay.scala @@ -29,4 +29,4 @@ abstract class PCIePlacedOverlay[IO <: Data]( extends IOPlacedOverlay[IO, PCIeDesignInput, PCIeShellInput, PCIeOverlayOutput] { implicit val p = di.p -} +} \ No newline at end of file diff --git a/src/main/scala/shell/SPIOverlay.scala b/src/main/scala/shell/SPIOverlay.scala index 996d9e7b..e939cb42 100644 --- a/src/main/scala/shell/SPIOverlay.scala +++ b/src/main/scala/shell/SPIOverlay.scala @@ -11,7 +11,7 @@ import freechips.rocketchip.tilelink.TLBusWrapper import freechips.rocketchip.interrupts.IntInwardNode //This should not do the controller placement either -case class SPIShellInput() +case class SPIShellInput(index: Int = 0) case class SPIDesignInput(spiParam: SPIParams, node: BundleBridgeSource[SPIPortIO])(implicit val p: Parameters) case class SPIOverlayOutput() case object SPIOverlayKey extends Field[Seq[DesignPlacer[SPIDesignInput, SPIShellInput, SPIOverlayOutput]]](Nil) diff --git a/src/main/scala/shell/xilinx/DDR3Overlay.scala b/src/main/scala/shell/xilinx/DDR3Overlay.scala new file mode 100644 index 00000000..4203e52e --- /dev/null +++ b/src/main/scala/shell/xilinx/DDR3Overlay.scala @@ -0,0 +1,34 @@ +package sifive.fpgashells.shell.xilinx + +import chisel3._ +import chisel3.experimental.{attach, IO, withClockAndReset} +import freechips.rocketchip.config._ +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.util.SyncResetSynchronizerShiftReg +import sifive.fpgashells.clocks._ +import sifive.fpgashells.shell._ +import sifive.fpgashells.ip.xilinx._ +import sifive.blocks.devices.chiplink._ +import sifive.fpgashells.devices.xilinx.xilinxvc709mig._ + +case object VC709DDR3Size extends Field[BigInt](0x100000000L) // 4GB +case object DualVC709DDR3Size extends Field[BigInt](0x200000000L) // 8GB +abstract class DDR3XilinxPlacedOverlay(shell: VC709ShellBasicOverlays, name: String, designInput: DDRDesignInput, shellInput: DDRShellInput) + extends DDRPlacedOverlay[XilinxVC709MIGPads](name, designInput, shellInput) +{ + val size = p(VC709DDR3Size) + + val migParams = XilinxVC709MIGParams(address = AddressSet.misaligned(di.baseAddress, size)) + val mig = LazyModule(new XilinxVC709MIG(migParams)) + val ioNode = BundleBridgeSource(() => mig.module.io.cloneType) + val topIONode = shell { ioNode.makeSink() } + val ddrUI = shell { ClockSourceNode(freqMHz = 200) } + val areset = shell { ClockSinkNode(Seq(ClockSinkParameters())) } + areset := designInput.wrangler := ddrUI + + def overlayOutput = DDROverlayOutput(ddr = mig.node) + def ioFactory = new XilinxVC709MIGPads(size) + + InModuleBody { ioNode.bundle <> mig.module.io } +} \ No newline at end of file diff --git a/src/main/scala/shell/xilinx/VC707NewShell.scala b/src/main/scala/shell/xilinx/VC707NewShell.scala index dbe811af..64ef8310 100644 --- a/src/main/scala/shell/xilinx/VC707NewShell.scala +++ b/src/main/scala/shell/xilinx/VC707NewShell.scala @@ -217,15 +217,15 @@ class DDRVC707ShellPlacer(val shell: VC707Shell, val shellInput: DDRShellInput)( class PCIeVC707PlacedOverlay(val shell: VC707Shell, name: String, val designInput: PCIeDesignInput, val shellInput: PCIeShellInput) extends PCIePlacedOverlay[XilinxVC707PCIeX1Pads](name, designInput, shellInput) { - val pcie = LazyModule(new XilinxVC707PCIeX1) - val ioNode = BundleBridgeSource(() => pcie.module.io.cloneType) + val pcie = LazyModule(new XilinxVC707PCIeX1) + val ioNode = BundleBridgeSource(() => pcie.module.io.cloneType) val topIONode = shell { ioNode.makeSink() } val axiClk = shell { ClockSourceNode(freqMHz = 125) } val areset = shell { ClockSinkNode(Seq(ClockSinkParameters())) } areset := designInput.wrangler := axiClk val slaveSide = TLIdentityNode() - pcie.crossTLIn(pcie.slave) := slaveSide + pcie.crossTLIn(pcie.slave) := slaveSide pcie.crossTLIn(pcie.control) := slaveSide val node = NodeHandle(slaveSide, pcie.crossTLOut(pcie.master)) val intnode = pcie.crossIntOut(pcie.intnode) diff --git a/src/main/scala/shell/xilinx/VC709NewShell.scala b/src/main/scala/shell/xilinx/VC709NewShell.scala new file mode 100644 index 00000000..e80266df --- /dev/null +++ b/src/main/scala/shell/xilinx/VC709NewShell.scala @@ -0,0 +1,255 @@ +// See LICENSE for license details. +package sifive.fpgashells.shell.xilinx + +import chisel3._ +import chisel3.experimental.{attach, IO, withClockAndReset} +import freechips.rocketchip.config._ +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.util.SyncResetSynchronizerShiftReg +import sifive.fpgashells.clocks._ +import sifive.fpgashells.shell._ +import sifive.fpgashells.ip.xilinx._ +import sifive.blocks.devices.chiplink._ +import sifive.fpgashells.devices.xilinx.xilinxvc709mig._ +import sifive.fpgashells.devices.xilinx.xilinxvc709pcie._ + +class SysClockVC709PlacedOverlay(val shell: VC709ShellBasicOverlays, name: String, val designInput: ClockInputDesignInput, val shellInput: ClockInputShellInput) + extends LVDSClockInputXilinxPlacedOverlay(name, designInput, shellInput) +{ + val node = shell { ClockSourceNode(freqMHz = 200, jitterPS = 50)(ValName(name)) } + + shell { InModuleBody { + shell.xdc.addBoardPin(io.p, "clk_p") + shell.xdc.addBoardPin(io.n, "clk_n") + } } +} + +class SysClockVC709ShellPlacer(shell: VC709ShellBasicOverlays, val shellInput: ClockInputShellInput)(implicit val valName: ValName) + extends ClockInputShellPlacer[VC709ShellBasicOverlays] +{ + def place(designInput: ClockInputDesignInput) = new SysClockVC709PlacedOverlay(shell, valName.name, designInput, shellInput) +} + +class UARTVC709PlacedOverlay(val shell: VC709ShellBasicOverlays, name: String, val designInput: UARTDesignInput, val shellInput: UARTShellInput) + extends UARTXilinxPlacedOverlay(name, designInput, shellInput, true) +{ + shell { InModuleBody { + val packagePinsWithPackageIOs = Seq(("AR34", IOPin(io.rtsn.get)), + ("AT32", IOPin(io.ctsn.get)), + ("AU36", IOPin(io.txd)), + ("AU33", IOPin(io.rxd))) + + packagePinsWithPackageIOs foreach { case (pin, io) => { + shell.xdc.addPackagePin(io, pin) + shell.xdc.addIOStandard(io, "LVCMOS18") + shell.xdc.addIOB(io) + } } + } } +} +class UARTVC709ShellPlacer(val shell: VC709ShellBasicOverlays, val shellInput: UARTShellInput)(implicit val valName: ValName) + extends UARTShellPlacer[VC709ShellBasicOverlays] { + def place(designInput: UARTDesignInput) = new UARTVC709PlacedOverlay(shell, valName.name, designInput, shellInput) +} + +object LEDVC709PinConstraints { + val pins = Seq("AM39","AN39","AR37","AT37","AR35","AP41","AP42","AU39") +} +class LEDVC709PlacedOverlay(val shell: VC709ShellBasicOverlays, name: String, val designInput: LEDDesignInput, val shellInput: LEDShellInput) + extends LEDXilinxPlacedOverlay(name, designInput, shellInput, packagePin = Some(LEDVC709PinConstraints.pins(shellInput.number)), ioStandard = "LVCMOS18") +class LEDVC709ShellPlacer(val shell: VC709ShellBasicOverlays, val shellInput: LEDShellInput)(implicit val valName: ValName) + extends LEDShellPlacer[VC709ShellBasicOverlays] { + def place(designInput: LEDDesignInput) = new LEDVC709PlacedOverlay(shell, valName.name, designInput, shellInput) +} + +object SwitchVC709PinConstraints { + val pins = Seq("AV30","AY33","BA31","BA32","AW30","AY30","BA30","BB31") +} +class SwitchVC709PlacedOverlay(val shell: VC709ShellBasicOverlays, name: String, val designInput: SwitchDesignInput, val shellInput: SwitchShellInput) + extends SwitchXilinxPlacedOverlay(name, designInput, shellInput, packagePin = Some(SwitchVC709PinConstraints.pins(shellInput.number)), ioStandard = "LVCMOS18") +class SwitchVC709ShellPlacer(val shell: VC709ShellBasicOverlays, val shellInput: SwitchShellInput)(implicit val valName: ValName) + extends SwitchShellPlacer[VC709ShellBasicOverlays] { + def place(designInput: SwitchDesignInput) = new SwitchVC709PlacedOverlay(shell, valName.name, designInput, shellInput) +} + +object ButtonVC709PinConstraints { + val pins = Seq("AR40","AU38","AP40","AW40","AV39") +} +class ButtonVC709PlacedOverlay(val shell: VC709ShellBasicOverlays, name: String, val designInput: ButtonDesignInput, val shellInput: ButtonShellInput) + extends ButtonXilinxPlacedOverlay(name, designInput, shellInput, packagePin = Some(ButtonVC709PinConstraints.pins(shellInput.number)), ioStandard = "LVCMOS18") +class ButtonVC709ShellPlacer(val shell: VC709ShellBasicOverlays, val shellInput: ButtonShellInput)(implicit val valName: ValName) + extends ButtonShellPlacer[VC709ShellBasicOverlays] { + def place(designInput: ButtonDesignInput) = new ButtonVC709PlacedOverlay(shell, valName.name, designInput, shellInput) +} + +// TODO: JTAG is untested +class JTAGDebugVC709PlacedOverlay(val shell: VC709ShellBasicOverlays, name: String, val designInput: JTAGDebugDesignInput, val shellInput: JTAGDebugShellInput) + extends JTAGDebugXilinxPlacedOverlay(name, designInput, shellInput) +{ + shell { InModuleBody { + shell.sdc.addClock("JTCK", IOPin(io.jtag_TCK), 10) + shell.sdc.addGroup(clocks = Seq("JTCK")) + shell.xdc.clockDedicatedRouteFalse(IOPin(io.jtag_TCK)) +/* if old method + val packagePinsWithPackageIOs = Seq(("R32", IOPin(io.jtag_TCK)), + ("W36", IOPin(io.jtag_TMS)), + ("W37", IOPin(io.jtag_TDI)), + ("V40", IOPin(io.jtag_TDO))) +*/ + /* + #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 + */ + val packagePinsWithPackageIOs = Seq(("AT42", IOPin(io.jtag_TCK)), + ("AR38", IOPin(io.jtag_TMS)), + ("AR39", IOPin(io.jtag_TDI)), + ("AR42", IOPin(io.srst_n)), + ("AT40", IOPin(io.jtag_TDO))) + packagePinsWithPackageIOs foreach { case (pin, io) => { + shell.xdc.addPackagePin(io, pin) + shell.xdc.addIOStandard(io, "LVCMOS18") + shell.xdc.addPullup(io) + } } + } } +} +class JTAGDebugVC709ShellPlacer(val shell: VC709ShellBasicOverlays, val shellInput: JTAGDebugShellInput)(implicit val valName: ValName) + extends JTAGDebugShellPlacer[VC709ShellBasicOverlays] { + def place(designInput: JTAGDebugDesignInput) = new JTAGDebugVC709PlacedOverlay(shell, valName.name, designInput, shellInput) +} + +class DDR3VC709PlacedOverlay(val shell: VC709ShellBasicOverlays, name: String, val designInput: DDRDesignInput, val shellInput: DDRShellInput) + extends DDR3XilinxPlacedOverlay(shell, name, designInput, shellInput) +{ + shell { InModuleBody { + require (shell.sys_clock.get.isDefined, "Use of DDR3VC709PlacedOverlay depends on SysClockVC709PlacedOverlay") + val (sys, _) = shell.sys_clock.get.get.overlayOutput.node.out(0) + val (ui, _) = ddrUI.out(0) + val (ar, _) = areset.in(0) + val port = topIONode.bundle.port + + io <> port + + // This is modified for vc709 + ui.clock := port.ui_clk + ui.reset := !port.mmcm_locked || port.ui_clk_sync_rst + port.sys_clk_i := sys.clock.asUInt + port.sys_rst := sys.reset // pllReset + port.aresetn := !ar.reset + } } + + shell.sdc.addGroup(pins = Seq(mig.island.module.blackbox.io.ui_clk)) +} +class DDR3VC709ShellPlacer(shell: VC709ShellBasicOverlays, val shellInput: DDRShellInput)(implicit val valName: ValName) + extends DDRShellPlacer[VC709ShellBasicOverlays] { + def place(designInput: DDRDesignInput) = new DDR3VC709PlacedOverlay(shell, valName.name, designInput, shellInput) +} + +class PCIeVC709PlacedOverlay(val shell: VC709ShellBasicOverlays, name: String, val designInput: PCIeDesignInput, val shellInput: PCIeShellInput) + extends PCIePlacedOverlay[XilinxVC709PCIePads](name, designInput, shellInput) +{ + val pcie = LazyModule(new XilinxVC709PCIe) + val bridge = BundleBridgeSource(() => pcie.module.io.cloneType) + val topBridge = shell { bridge.makeSink() } + val axiClk = shell { ClockSourceNode(freqMHz = 125) } + val areset = shell { ClockSinkNode(Seq(ClockSinkParameters())) } + areset := designInput.wrangler := axiClk + + val slaveSide = TLIdentityNode() + pcie.crossTLIn(pcie.slave) := slaveSide + pcie.crossTLIn(pcie.control) := slaveSide + val masterSide = pcie.crossTLOut(pcie.master) + + val pcieNode = NodeHandle(slaveSide, masterSide) + val intNode = pcie.crossIntOut(pcie.intnode) + + def overlayOutput = PCIeOverlayOutput(pcieNode, intNode) + def ioFactory = new XilinxVC709PCIePads + + InModuleBody { bridge.bundle <> pcie.module.io } + + shell { InModuleBody { + val (axi, _) = axiClk.out(0) + val (ar, _) = areset.in(0) + val port = topBridge.bundle.port + io <> port + axi.clock := port.axi_aclk + // axi.reset := !port.mmcm_lock // mmcm_lock is removed in 3.0 + port.axi_aresetn := !ar.reset + port.axi_ctl_aresetn := !ar.reset + + def bind(io: Seq[IOPin], pad: Seq[String]) { + (io zip pad) foreach { case (io, pad) => shell.xdc.addPackagePin(io, pad) } + } + + val txn = Seq("W1", "AA1", "AC1", "AE1", "AG1", "AH3", "AJ1", "AK3") /* [0-7] */ + val txp = Seq("W2", "AA2", "AC2", "AE2", "AG2", "AH4", "AJ2", "AK4") /* [0-7] */ + val rxn = Seq("Y3", "AA5", "AB3", "AC5", "AD3", "AE5", "AF3", "AG5") /* [0-7] */ + val rxp = Seq("Y4", "AA6", "AB4", "AC6", "AD4", "AE6", "AF4", "AG6") /* [0-7] */ + + IOPin.of(io).foreach { shell.xdc.addPackagePin(_, "") } + bind(IOPin.of(io.REFCLK_rxp), Seq("AB8")) + bind(IOPin.of(io.REFCLK_rxn), Seq("AB7")) + bind(IOPin.of(io.pci_exp_rxp), rxp) + bind(IOPin.of(io.pci_exp_rxn), rxn) + bind(IOPin.of(io.pci_exp_txp), txp) + bind(IOPin.of(io.pci_exp_txn), txn) + + shell.sdc.addClock(s"${name}_ref_clk", io.REFCLK_rxp, 100) + } } + + shell.sdc.addGroup(clocks = Seq("txoutclk", "userclk1")) +} +class PCIeVC709ShellPlacer(val shell: VC709ShellBasicOverlays, val shellInput: PCIeShellInput)(implicit val valName: ValName) + extends PCIeShellPlacer[VC709ShellBasicOverlays] { + def place(designInput: PCIeDesignInput) = new PCIeVC709PlacedOverlay(shell, valName.name, designInput, shellInput) +} + +abstract class VC709ShellBasicOverlays()(implicit p: Parameters) extends Series7Shell +{ + // PLL reset causes + val pllReset = InModuleBody { Wire(Bool()) } + + // Order matters; ddr depends on sys_clock + val sys_clock = Overlay(ClockInputOverlayKey, new SysClockVC709ShellPlacer(this, ClockInputShellInput())) + val led = Seq.tabulate(8)(i => Overlay(LEDOverlayKey, new LEDVC709ShellPlacer(this, LEDShellInput(color = "red", number = i))(valName = ValName(s"led_$i")))) + val switch = Seq.tabulate(8)(i => Overlay(SwitchOverlayKey, new SwitchVC709ShellPlacer(this, SwitchShellInput(number = i))(valName = ValName(s"switch_$i")))) + val button = Seq.tabulate(5)(i => Overlay(ButtonOverlayKey, new ButtonVC709ShellPlacer(this, ButtonShellInput(number = i))(valName = ValName(s"button_$i")))) + val uart0 = Seq.tabulate(1)(i => Overlay(UARTOverlayKey, new UARTVC709ShellPlacer(this, UARTShellInput(index = i)))) + val jtag = Overlay(JTAGDebugOverlayKey, new JTAGDebugVC709ShellPlacer(this, JTAGDebugShellInput())) + val ddr0 = Overlay(DDROverlayKey, new DDR3VC709ShellPlacer(this, DDRShellInput())) + val pcie = Overlay(PCIeOverlayKey, new PCIeVC709ShellPlacer(this, PCIeShellInput())(valName = ValName(s"pcie"))) +} + +class VC709BaseShell()(implicit p: Parameters) extends VC709ShellBasicOverlays +{ + val topDesign = LazyModule(p(DesignKey)(designParameters)) + + // Place the sys_clock at the Shell if the user didn't ask for it + p(ClockInputOverlayKey).foreach(_.place(ClockInputDesignInput())) + + override lazy val module = new LazyRawModuleImp(this) { + val reset = IO(Input(Bool())) + xdc.addBoardPin(reset, "reset") + + val reset_ibuf = Module(new IBUF) + reset_ibuf.io.I := reset + + val sysclk: Clock = sys_clock.get() match { + case Some(x: SysClockVC709PlacedOverlay) => x.clock + } + val powerOnReset = PowerOnResetFPGAOnly(sysclk) + sdc.addAsyncPath(Seq(powerOnReset)) + + pllReset := + reset_ibuf.io.O || powerOnReset || false.B + } +} diff --git a/src/main/scala/shell/xilinx/XilinxShell.scala b/src/main/scala/shell/xilinx/XilinxShell.scala index 72ed6476..5a62c8e2 100644 --- a/src/main/scala/shell/xilinx/XilinxShell.scala +++ b/src/main/scala/shell/xilinx/XilinxShell.scala @@ -86,4 +86,4 @@ abstract class UltraScaleShell()(implicit p: Parameters) extends XilinxShell override def designParameters = super.designParameters.alterPartial { case PLLFactoryKey => pllFactory } -} +} \ No newline at end of file diff --git a/xilinx/common/tcl/boards.tcl b/xilinx/common/tcl/boards.tcl index af1c686b..fd73fb83 100644 --- a/xilinx/common/tcl/boards.tcl +++ b/xilinx/common/tcl/boards.tcl @@ -6,4 +6,5 @@ set ::program::boards::spec [dict create \ arty [dict create iface spix4 size 16 bitaddr 0x0 memdev {n25q128-3.3v-spi-x1_x2_x4}] \ arty_a7_100 [dict create iface spix4 size 16 bitaddr 0x0 memdev {s25fl128sxxxxxx0-spi-x1_x2_x4}] \ vc707 [dict create iface bpix16 size 128 bitaddr 0x3000000 ] \ + vc709 [dict create iface bpix16 size 128 bitaddr 0x3000000 memdev {mt28gu01gaax1e-bpi-x16}] \ vcu118 [dict create iface spix8 size 256 bitaddr 0x0 memdev {mt25qu01g-spi-x1_x2_x4_x8}]] diff --git a/xilinx/common/tcl/boot.tcl b/xilinx/common/tcl/boot.tcl new file mode 100644 index 00000000..a24e18c2 --- /dev/null +++ b/xilinx/common/tcl/boot.tcl @@ -0,0 +1,13 @@ +if {$argc < 1 || $argc > 1} { + puts $argc + puts {Error: Invalid number of arguments} + puts {Usage: boot.tcl board} + exit 1 +} +lassign $argv board + +open_hw +connect_hw_server +open_hw_target +current_hw_device [get_hw_devices $board] +boot_hw_device [lindex [get_hw_devices $board] 0] \ No newline at end of file diff --git a/xilinx/common/tcl/upload_mcs.tcl b/xilinx/common/tcl/upload_mcs.tcl new file mode 100644 index 00000000..3b2a5184 --- /dev/null +++ b/xilinx/common/tcl/upload_mcs.tcl @@ -0,0 +1,54 @@ +# Upload an MCS-format memory configuration file to the board. + +if {$argc < 3 || $argc > 3} { + puts $argc + puts {Error: Invalid number of arguments} + puts {Usage: upload_mcs.tcl board mcsfile prmfile} + exit 1 +} +lassign $argv board mcsfile prmfile + +open_hw +connect_hw_server +open_hw_target + +current_hw_device [get_hw_devices $board] +refresh_hw_device -update_hw_probes false [lindex [get_hw_devices $board] 0] +refresh_hw_device [lindex [get_hw_devices $board] 0] + +create_hw_cfgmem -hw_device [lindex [get_hw_devices $board] 0] [lindex [get_cfgmem_parts {mt28gu01gaax1e-bpi-x16}] 0] +set_property PROGRAM.BLANK_CHECK 0 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices $board] 0]] +set_property PROGRAM.ERASE 1 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices $board] 0]] +set_property PROGRAM.CFG_PROGRAM 1 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices $board] 0]] +set_property PROGRAM.VERIFY 1 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices $board] 0]] +set_property PROGRAM.CHECKSUM 0 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices $board] 0]] +refresh_hw_device [lindex [get_hw_devices $board] 0] + +set_property PROGRAM.ADDRESS_RANGE {use_file} [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices $board] 0]] +set_property PROGRAM.FILES [list $mcsfile ] [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices $board] 0]] +set_property PROGRAM.BPI_RS_PINS {none} [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices $board] 0]] +set_property PROGRAM.UNUSED_PIN_TERMINATION {pull-none} [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices $board] 0]] +set_property PROGRAM.BLANK_CHECK 0 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices $board] 0]] +set_property PROGRAM.ERASE 1 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices $board] 0]] +set_property PROGRAM.CFG_PROGRAM 1 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices $board] 0]] +set_property PROGRAM.VERIFY 1 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices $board] 0]] +set_property PROGRAM.CHECKSUM 0 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices $board] 0]] +set_property PROGRAM.PRM_FILES [list $prmfile ] [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices $board] 0]] +set_property PROGRAM.ADDRESS_RANGE {use_file} [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices $board] 0]] +set_property PROGRAM.FILES [list $mcsfile ] [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices $board] 0]] +set_property PROGRAM.PRM_FILE { $prmfile } [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices $board] 0]] +set_property PROGRAM.BPI_RS_PINS {none} [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices $board] 0]] +set_property PROGRAM.UNUSED_PIN_TERMINATION {pull-none} [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices $board] 0]] +set_property PROGRAM.BLANK_CHECK 0 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices $board] 0]] +set_property PROGRAM.ERASE 1 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices $board] 0]] +set_property PROGRAM.CFG_PROGRAM 1 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices $board] 0]] +set_property PROGRAM.VERIFY 1 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices $board] 0]] +set_property PROGRAM.CHECKSUM 0 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices $board] 0]] + +startgroup + +if {![string equal [get_property PROGRAM.HW_CFGMEM_TYPE [lindex [get_hw_devices $board] 0]] [get_property MEM_TYPE [get_property CFGMEM_PART [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices $board] 0]]]]] } { + create_hw_bitstream -hw_device [lindex [get_hw_devices $board] 0] [get_property PROGRAM.HW_CFGMEM_BITFILE [ lindex [get_hw_devices $board] 0]]; + program_hw_devices [lindex [get_hw_devices $board] 0]; +}; +program_hw_cfgmem -hw_cfgmem [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices $board] 0]] diff --git a/xilinx/common/tcl/vivado.tcl b/xilinx/common/tcl/vivado.tcl index 46f26145..5ebdc709 100644 --- a/xilinx/common/tcl/vivado.tcl +++ b/xilinx/common/tcl/vivado.tcl @@ -1,4 +1,5 @@ # See LICENSE for license details. +set_param general.maxThreads 8 # Set the variable for the directory that includes all scripts set scriptdir [file dirname [info script]] diff --git a/xilinx/vc709/constraints/vc709-master.xdc b/xilinx/vc709/constraints/vc709-master.xdc new file mode 100644 index 00000000..cdbe7437 --- /dev/null +++ b/xilinx/vc709/constraints/vc709-master.xdc @@ -0,0 +1,10 @@ +#-------------- MCS Generation ---------------------- +set_property CFGBVS GND [current_design] +set_property CONFIG_VOLTAGE 1.8 [current_design] + +set_property EXTRACT_ENABLE YES [get_cells dut_/spi_0_1/mac/phy/txd_reg*] +set_property EXTRACT_ENABLE YES [get_cells dut_/spi_0_1/mac/phy/sck_reg] + + + + diff --git a/xilinx/vc709/tcl/board.tcl b/xilinx/vc709/tcl/board.tcl new file mode 100644 index 00000000..8637a367 --- /dev/null +++ b/xilinx/vc709/tcl/board.tcl @@ -0,0 +1,4 @@ +# See LICENSE for license details. +set name {vc709} +set part_fpga {xc7vx690tffg1761-2} +set part_board {xilinx.com:vc709:part0:1.8} diff --git a/xilinx/vc709/tcl/clocks.tcl b/xilinx/vc709/tcl/clocks.tcl new file mode 100644 index 00000000..69014fcf --- /dev/null +++ b/xilinx/vc709/tcl/clocks.tcl @@ -0,0 +1,50 @@ +if { [llength [get_ports -quiet chiplink_b2c_clk]] > 0 } { + create_clock -name chiplink_b2c_clock -period 10 [get_ports chiplink_b2c_clk] + create_generated_clock -name {chiplink_c2b_clock} \ + -divide_by 1 \ + -source [ get_pins { vc709_sys_clock_mmcm0/inst/mmcm_adv_inst/CLKOUT6 } ] \ + [ get_ports { chiplink_c2b_clk } ] + + # RX side: want to latch almost anywhere except on the rising edge of the clock + # The data signals coming from Aloe have: clock - 1.2 <= transition <= clock + 0.8 + # Let's add 0.6ns of safety for trace jitter+skew on both sides: + # min = hold = - 1.2 - 0.6 + # max = period - setup = 0.8 + 0.6 + set_input_delay -min -1.8 -clock {chiplink_b2c_clock} [ get_ports { chiplink_b2c_data* chiplink_b2c_rst chiplink_b2c_send } ] + set_input_delay -max 1.4 -clock {chiplink_b2c_clock} [ get_ports { chiplink_b2c_data* chiplink_b2c_rst chiplink_b2c_send } ] + + # TX side: want to transition almost anywhere except on the rising edge of the clock + # The data signals going to Aloe must have: clock - 1.85 <= NO transition <= clock + 0.65 + # Let's add 1ns of safey for trace jitter+skew on both sides: + # min = -hold = -0.65 - 0.6 + # max = setup = 1.85 + 0.6 + set_output_delay -min -1.25 -clock {chiplink_c2b_clock} [ get_ports { chiplink_c2b_data* chiplink_c2b_rst chiplink_c2b_send } ] + set_output_delay -max 2.45 -clock {chiplink_c2b_clock} [ get_ports { chiplink_c2b_data* chiplink_c2b_rst chiplink_c2b_send } ] +} + +set group_mem [get_clocks -quiet {clk_pll_i}] +set group_sys [get_clocks -quiet {sys_diff_clk \ + clk_out*_vc709_sys_clock_mmcm1 \ + clk_out*_vc709_sys_clock_mmcm2 \ + chiplink_c2b_clock}] +set group_cl [get_clocks -quiet {chiplink_b2c_clock \ + clk_out*_vc709_sys_clock_mmcm3}] +set group_pci [get_clocks -quiet {userclk1 txoutclk}] + +set group_jtag [get_clocks -quiet {JTCK}] + +puts "group_mem: $group_mem" +puts "group_sys: $group_sys" +puts "group_pci: $group_pci" +puts "group_cl: $group_cl" +puts "group_jtag: $group_jtag" + +set groups [list] +if { [llength $group_mem] > 0 } { lappend groups -group $group_mem } +if { [llength $group_sys] > 0 } { lappend groups -group $group_sys } +if { [llength $group_pci] > 0 } { lappend groups -group $group_pci } +if { [llength $group_cl] > 0 } { lappend groups -group $group_cl } +if { [llength $group_jtag] > 0 } { lappend groups -group $group_jtag } + +puts "set_clock_groups -asynchronous $groups" +set_clock_groups -asynchronous {*}$groups diff --git a/xilinx/vc709/tcl/ios.tcl b/xilinx/vc709/tcl/ios.tcl new file mode 100644 index 00000000..4a6c1df0 --- /dev/null +++ b/xilinx/vc709/tcl/ios.tcl @@ -0,0 +1,65 @@ +#---------------Physical Constraints----------------- + +#get_port_part_pins +#clk_n clk_p dip_switches_tri_i_0 dip_switches_tri_i_1 dip_switches_tri_i_2 dip_switches_tri_i_3 dip_switches_tri_i_4 dip_switches_tri_i_5 dip_switches_tri_i_6 dip_switches_tri_i_7 iic_main_scl_i iic_main_sda_i lcd_7bits_tri_o_0 lcd_7bits_tri_o_1 lcd_7bits_tri_o_2 lcd_7bits_tri_o_3 lcd_7bits_tri_o_4 lcd_7bits_tri_o_5 lcd_7bits_tri_o_6 leds_8bits_tri_o_0 leds_8bits_tri_o_1 leds_8bits_tri_o_2 leds_8bits_tri_o_3 leds_8bits_tri_o_4 leds_8bits_tri_o_5 leds_8bits_tri_o_6 leds_8bits_tri_o_7 linear_flash_addr_1 linear_flash_addr_10 linear_flash_addr_11 linear_flash_addr_12 linear_flash_addr_13 linear_flash_addr_14 linear_flash_addr_15 linear_flash_addr_16 linear_flash_addr_17 linear_flash_addr_18 linear_flash_addr_19 linear_flash_addr_2 linear_flash_addr_20 linear_flash_addr_21 linear_flash_addr_22 linear_flash_addr_23 linear_flash_addr_24 linear_flash_addr_25 linear_flash_addr_26 linear_flash_addr_3 linear_flash_addr_4 linear_flash_addr_5 linear_flash_addr_6 linear_flash_addr_7 linear_flash_addr_8 linear_flash_addr_9 linear_flash_adv_ldn linear_flash_ce_n linear_flash_dq_i_0 linear_flash_dq_i_1 linear_flash_dq_i_10 linear_flash_dq_i_11 linear_flash_dq_i_12 linear_flash_dq_i_13 linear_flash_dq_i_14 linear_flash_dq_i_15 linear_flash_dq_i_2 linear_flash_dq_i_3 linear_flash_dq_i_4 linear_flash_dq_i_5 linear_flash_dq_i_6 linear_flash_dq_i_7 linear_flash_dq_i_8 linear_flash_dq_i_9 linear_flash_oen linear_flash_wen mdc mdio_i phy_rst_out push_buttons_5bits_tri_i_0 push_buttons_5bits_tri_i_1 push_buttons_5bits_tri_i_2 push_buttons_5bits_tri_i_3 push_buttons_5bits_tri_i_4 reset rotary_inca_push_incb_tri_i_0 rotary_inca_push_incb_tri_i_1 rotary_inca_push_incb_tri_i_2 rs232_uart_rxd rs232_uart_txd sfp_rxn sfp_rxp sfp_sgmii_txn sfp_sgmii_txp sgmii_mgt_clkn sgmii_mgt_clkp sgmii_rxn sgmii_rxp sgmii_txn sgmii_txp sma_lvds_rxn sma_lvds_rxp sma_lvds_txn sma_lvds_txp sma_mgt_clkn sma_mgt_clkp sma_sfp_rxn sma_sfp_rxp sma_sfp_txn sma_sfp_txp + +set_property BOARD_PIN {clk_p} [get_ports sys_diff_clock_clk_p] +set_property BOARD_PIN {clk_n} [get_ports sys_diff_clock_clk_n] +set_property BOARD_PIN {reset} [get_ports reset] + +create_clock -name sys_diff_clk -period 5.0 [get_ports sys_diff_clock_clk_p] +set_input_jitter [get_clocks -of_objects [get_ports sys_diff_clock_clk_p]] 0.5 + +## LED +set_property BOARD_PIN {leds_8bits_tri_o_0} [get_ports led_0] +set_property BOARD_PIN {leds_8bits_tri_o_1} [get_ports led_1] +set_property BOARD_PIN {leds_8bits_tri_o_2} [get_ports led_2] +set_property BOARD_PIN {leds_8bits_tri_o_3} [get_ports led_3] +set_property BOARD_PIN {leds_8bits_tri_o_4} [get_ports led_4] +set_property BOARD_PIN {leds_8bits_tri_o_5} [get_ports led_5] +set_property BOARD_PIN {leds_8bits_tri_o_6} [get_ports led_6] +set_property BOARD_PIN {leds_8bits_tri_o_7} [get_ports led_7] + +## BUTTON +set_property BOARD_PIN {push_buttons_5bits_tri_i_0} [get_ports btn_0] +set_property BOARD_PIN {push_buttons_5bits_tri_i_1} [get_ports btn_1] +set_property BOARD_PIN {push_buttons_5bits_tri_i_2} [get_ports btn_2] +set_property BOARD_PIN {push_buttons_5bits_tri_i_3} [get_ports btn_3] +set_property BOARD_PIN {push_buttons_5bits_tri_i_4} [get_ports btn_4] + +## SWITCH +set_property BOARD_PIN {dip_switches_tri_i_0} [get_ports sw_0] +set_property BOARD_PIN {dip_switches_tri_i_1} [get_ports sw_1] +set_property BOARD_PIN {dip_switches_tri_i_2} [get_ports sw_2] +set_property BOARD_PIN {dip_switches_tri_i_3} [get_ports sw_3] +set_property BOARD_PIN {dip_switches_tri_i_4} [get_ports sw_4] +set_property BOARD_PIN {dip_switches_tri_i_5} [get_ports sw_5] +set_property BOARD_PIN {dip_switches_tri_i_6} [get_ports sw_6] +set_property BOARD_PIN {dip_switches_tri_i_7} [get_ports sw_7] + +## UART +# RX +set_property PACKAGE_PIN AU33 [get_ports uart_rx] +set_property IOSTANDARD LVCMOS18 [get_ports uart_rx] +set_property IOB TRUE [get_cells -of_objects [all_fanout -flat -endpoints_only [get_ports uart_rx]]] +# CTSN +set_property PACKAGE_PIN AT32 [get_ports uart_ctsn] +set_property IOSTANDARD LVCMOS18 [get_ports uart_ctsn] +set_property IOB TRUE [get_ports uart_ctsn] +# TX +set_property PACKAGE_PIN AU36 [get_ports uart_tx] +set_property IOSTANDARD LVCMOS18 [get_ports uart_tx] +set_property IOB TRUE [get_cells -of_objects [all_fanin -flat -startpoints_only [get_ports uart_tx]]] +# RTSN +set_property PACKAGE_PIN AR34 [get_ports uart_rtsn] +set_property IOSTANDARD LVCMOS18 [get_ports uart_rtsn] +set_property IOB TRUE [get_ports uart_rtsn] + +## I2C +set_property PACKAGE_PIN AU32 [get_ports i2c_sda] +set_property IOSTANDARD LVCMOS18 [get_ports i2c_sda] +set_property IOB TRUE [get_cells -of_objects [all_fanout -flat -endpoints_only [get_ports i2c_sda]]] + +set_property PACKAGE_PIN AT35 [get_ports i2c_scl] +set_property IOSTANDARD LVCMOS18 [get_ports i2c_scl] +set_property IOB TRUE [get_cells -of_objects [all_fanout -flat -endpoints_only [get_ports i2c_scl]]] \ No newline at end of file diff --git a/xilinx/vc709/vsrc/vc709reset.v b/xilinx/vc709/vsrc/vc709reset.v new file mode 100644 index 00000000..4e2cc021 --- /dev/null +++ b/xilinx/vc709/vsrc/vc709reset.v @@ -0,0 +1,78 @@ +// See LICENSE for license details. +`timescale 1ns/1ps +`default_nettype none +`define RESET_SYNC 4 +`define DEBOUNCE_BITS 8 + +module vc709reset( + // Asynchronous reset input, should be held high until + // all clocks are locked and power is stable. + input wire areset, + // Clock domains are brought up in increasing order + // All clocks are reset for at least 2^DEBOUNCE_BITS * period(clock1) + input wire clock1, + output wire reset1, + input wire clock2, + output wire reset2, + input wire clock3, + output wire reset3, + input wire clock4, + output wire reset4 +); + sifive_reset_hold hold_clock0(areset, clock1, reset1); + sifive_reset_sync sync_clock2(reset1, clock2, reset2); + sifive_reset_sync sync_clock3(reset2, clock3, reset3); + sifive_reset_sync sync_clock4(reset3, clock4, reset4); +endmodule + +// Assumes that areset is held for more than one clock +// Allows areset to be deasserted asynchronously +module sifive_reset_sync( + input wire areset, + input wire clock, + output wire reset +); + reg [`RESET_SYNC-1:0] gen_reset = {`RESET_SYNC{1'b1}}; + always @(posedge clock, posedge areset) begin + if (areset) begin + gen_reset <= {`RESET_SYNC{1'b1}}; + end else begin + gen_reset <= {1'b0,gen_reset[`RESET_SYNC-1:1]}; + end + end + assign reset = gen_reset[0]; +endmodule + +module sifive_reset_hold( + input wire areset, + input wire clock, + output wire reset +); + wire raw_reset; + reg [`RESET_SYNC-1:0] sync_reset = {`RESET_SYNC{1'b1}}; + reg [`DEBOUNCE_BITS:0] debounce_reset = {`DEBOUNCE_BITS{1'b1}}; + wire out_reset; + + // Captures reset even if clock is not running + sifive_reset_sync capture(areset, clock, raw_reset); + + // Remove any glitches due to runt areset + always @(posedge clock) begin + sync_reset <= {raw_reset,sync_reset[`RESET_SYNC-1:1]}; + end + + // Debounce the reset + assign out_reset = debounce_reset[`DEBOUNCE_BITS]; + always @(posedge clock) begin + if (sync_reset[0]) begin + debounce_reset <= {(`DEBOUNCE_BITS+1){1'b1}}; + end else begin + debounce_reset <= debounce_reset - out_reset; + end + end + + assign reset = out_reset; + +endmodule + +`default_nettype wire