From 548d79cf8bb56f4d470df9f5e1dfd543d94208e2 Mon Sep 17 00:00:00 2001 From: Boran Car Date: Mon, 11 Feb 2019 01:48:37 +0000 Subject: [PATCH] Modify E300 to X300 Modifications: - Increase clock to 65 MHz - Enable user mode - Increase HW breakpoints to 8 - Add 2 perf counters, hpmcounter3 and hpmcounter4 - Add Xilinx EthernetLite core for Arty - Make icache 4-way set associative - Map ITIM at 0x0800_0000 - Expand DTIM to 64k - Add 3 local interrupts and map GPIO BTN0-BTN2 to them - Add temporary PMOD JA remaps for robotic arm --- Makefile.x300artydevkit | 11 +- README.md | 73 ++++++ build.sbt | 13 +- .../XilinxEthernetLite.scala | 41 ++++ .../XilinxEthernetLitePeriphery.scala | 25 +++ .../src/main/scala/ip/xilinx/Xilinx.scala | 2 + .../ip/xilinx/ethernetlite/ethernetlite.scala | 210 ++++++++++++++++++ .../main/scala/shell/xilinx/ArtyShell.scala | 31 ++- .../xilinx/arty/constraints/arty-master.xdc | 55 ++--- fpga-shells/xilinx/arty/tcl/ip.tcl | 21 +- .../src/main/scala/devices/gpio/GPIO.scala | 7 + src/main/scala/x300artydevkit/Config.scala | 80 +++++-- src/main/scala/x300artydevkit/FPGAChip.scala | 57 +++-- src/main/scala/x300artydevkit/Platform.scala | 60 ++++- src/main/scala/x300artydevkit/System.scala | 50 ++++- 15 files changed, 637 insertions(+), 99 deletions(-) create mode 100644 README.md create mode 100644 fpga-shells/src/main/scala/devices/xilinx/xilinxethernetlite/XilinxEthernetLite.scala create mode 100644 fpga-shells/src/main/scala/devices/xilinx/xilinxethernetlite/XilinxEthernetLitePeriphery.scala create mode 100644 fpga-shells/src/main/scala/ip/xilinx/ethernetlite/ethernetlite.scala diff --git a/Makefile.x300artydevkit b/Makefile.x300artydevkit index 110c08ae..45c282b8 100644 --- a/Makefile.x300artydevkit +++ b/Makefile.x300artydevkit @@ -1,11 +1,12 @@ # See LICENSE for license details. +# Modifications copyright (C) 2019 Hex-Five base_dir := $(patsubst %/,%,$(dir $(abspath $(lastword $(MAKEFILE_LIST))))) -BUILD_DIR := $(base_dir)/builds/e300artydevkit +BUILD_DIR := $(base_dir)/builds/x300artydevkit FPGA_DIR := $(base_dir)/fpga-shells/xilinx -MODEL := E300ArtyDevKitFPGAChip -PROJECT := sifive.freedom.everywhere.e300artydevkit -export CONFIG_PROJECT := sifive.freedom.everywhere.e300artydevkit -export CONFIG := E300ArtyDevKitConfig +MODEL := X300ArtyDevKitFPGAChip +PROJECT := hexfive.x300artydevkit +export CONFIG_PROJECT := hexfive.x300artydevkit +export CONFIG := X300ArtyDevKitConfig export BOARD := arty export BOOTROM_DIR := $(base_dir)/bootrom/xip diff --git a/README.md b/README.md new file mode 100644 index 00000000..646a10fd --- /dev/null +++ b/README.md @@ -0,0 +1,73 @@ +# X300 + +This repository contains the X300, a modified version of [SiFive's Freedom E300 +Platform](https://github.com/sifive/freedom/tree/3624efff1819e52cec30c72f9085158189f8b53f) +to support [MultiZone](https://hex-five.com/products/) and IoT applications. +Here's a comparison between the E300 and the X300: + +| E300 | X300 | +| ---------------- | -------------------------------------------- | +| RV32ACIM | RV32ACIMU | +| 32.5 MHz clock | 65 MHz clock | +| 2 HW breakpoints | 8 HW breakpoints | +| no Ethernet core | Xilinx EthernetLite Ethernet core | +| 1-way icache | 4-way icache | +| no ITIM | ITIM at 0x0800\_0000 | +| 16 kB DTIM | 64 kB DTIM | +| no perf counters | 2 perf counters, hpmcounter3 and hpmcounter4 | +| no CLICs | 3 CLICs (BTN0, BTN1 and BTN2) | + +Like the Freedom E300 Arty FPGA Dev Kit, the X300 is designed to be mapped onto +an [Arty FPGA Evaluation +Kit](https://www.xilinx.com/products/boards-and-kits/arty.html). + +### Bootrom + +The default bootrom consists of a program that immediately jumps to address +0x20400000, which is 0x00400000 bytes into the SPI flash memory on the Arty +board. + +## Requirements + +### Vivado 2017.1 (or later) + +You'll need Vivado to synthesize the bistream for the Arty FPGA. You should +have received a single node license and instructions how to install Vivado with +your Arty FPGA Dev Kit. + +### RISC-V Toolchain + +To compile the bootloader for the X300, the RISC-V software toolchain must be +installed locally and the $(RISCV) environment variable must point to the +location of where the RISC-V toolchains are installed. We recommend you build +the toolchain yourself from +[riscv/riscv-gnu-toolchain](https://github.com/riscv/riscv-gnu-toolchain/tree/411d1345507e5313c3575720f128be9e6c0ed941) + +Run the following commands to clone the repository and get started: + +```sh +$ git clone https://github.com/hex-five/multizone-fpga.git +$ cd multizone-fpga +$ git submodule update --init --recursive +``` + +## Building + +To compile the bistream, run + +```sh +$ make -f Makefile.x300artydevkit mcs +``` + +These will place the files under `builds/x300artydevkit/obj`. + +Note that in order to run the `mcs` target, you need to have the `vivado` +executable on your `PATH`. + +## Running + +For instructions for getting the generated image onto an FPGA and programming +it with software using the [Freedom E +SDK](https://github.com/sifive/freedom-e-sdk), please see the [Freedom E310 +Arty FPGA Dev Kit Getting Started +Guide](https://www.sifive.com/documentation/freedom-soc/freedom-e300-arty-fpga-dev-kit-getting-started-guide/). diff --git a/build.sbt b/build.sbt index a87bc508..b8b2c126 100644 --- a/build.sbt +++ b/build.sbt @@ -1,6 +1,7 @@ // See LICENSE for license details. -organization := "com.sifive" -name := "freedom" +// Modifications copyright (C) 2019 Hex-Five +organization := "com.hex-five" +name := "x300" version := "0.1.0" lazy val commonSettings = Seq( @@ -25,14 +26,10 @@ lazy val sifiveBlocks = (project in file("sifive-blocks")). dependsOn(rocketChip). settings(commonSettings: _*) -lazy val nvdlaBlocks = (project in file("nvidia-dla-blocks")). - dependsOn(rocketChip). - settings(commonSettings: _*) - lazy val fpgaShells = (project in file("fpga-shells")). dependsOn(rocketChip, sifiveBlocks). settings(commonSettings: _*) -lazy val freedomPlatforms = (project in file(".")). - dependsOn(rocketChip, sifiveBlocks, nvdlaBlocks, fpgaShells). +lazy val x300 = (project in file(".")). + dependsOn(rocketChip, sifiveBlocks, fpgaShells). settings(commonSettings: _*) diff --git a/fpga-shells/src/main/scala/devices/xilinx/xilinxethernetlite/XilinxEthernetLite.scala b/fpga-shells/src/main/scala/devices/xilinx/xilinxethernetlite/XilinxEthernetLite.scala new file mode 100644 index 00000000..b3d35b82 --- /dev/null +++ b/fpga-shells/src/main/scala/devices/xilinx/xilinxethernetlite/XilinxEthernetLite.scala @@ -0,0 +1,41 @@ +// See LICENSE for license details. +// Copyright (C) 2018-2019 Hex-Five +package sifive.fpgashells.devices.xilinx.xilinxethernetlite + +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.ethernetlite.{EthernetLite, PhyPort, MdioPort} + +class XilinxEthernetLite(implicit p: Parameters, val crossing: ClockCrossingType = NoCrossing) + extends LazyModule with CrossesToOnlyOneClockDomain +{ + val ethernetlite = LazyModule(new EthernetLite) + + val slave: TLInwardNode = + (ethernetlite.slave + := AXI4Buffer() + := AXI4UserYanker() + := AXI4Deinterleaver(p(CacheBlockBytes)) + := AXI4IdIndexer(idBits=1) + := TLToAXI4(adapterName = Some("ethernetlite"))) + + val intnode: IntOutwardNode = ethernetlite.intnode + + lazy val module = new LazyModuleImp(this) { + val io = IO(new Bundle { + val port = new Bundle with PhyPort + with MdioPort { + } + }) + + ethernetlite.module.io.clockreset.s_axi_aclk := clock + ethernetlite.module.io.clockreset.s_axi_aresetn := ~reset + + io.port <> ethernetlite.module.io.port + } +} diff --git a/fpga-shells/src/main/scala/devices/xilinx/xilinxethernetlite/XilinxEthernetLitePeriphery.scala b/fpga-shells/src/main/scala/devices/xilinx/xilinxethernetlite/XilinxEthernetLitePeriphery.scala new file mode 100644 index 00000000..c3428578 --- /dev/null +++ b/fpga-shells/src/main/scala/devices/xilinx/xilinxethernetlite/XilinxEthernetLitePeriphery.scala @@ -0,0 +1,25 @@ +// See LICENSE for license details. +// Copyright (C) 2018-2019 Hex-Five +package sifive.fpgashells.devices.xilinx.xilinxethernetlite + +import Chisel._ +import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp, BufferParams} +import freechips.rocketchip.subsystem.BaseSubsystem +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.interrupts.IntSyncCrossingSink + +import sifive.fpgashells.ip.xilinx.ethernetlite.{PhyPort, MdioPort} + +trait HasSystemXilinxEthernetLite { this: BaseSubsystem => + val xilinxethernetlite = LazyModule(new XilinxEthernetLite) + private val cname = "xilinxethernetlite" + sbus.coupleTo(s"slave_named_$cname") { xilinxethernetlite.crossTLIn(xilinxethernetlite.slave) :*= TLWidthWidget(sbus.beatBytes) :*= _ } + ibus.fromSync := xilinxethernetlite.crossIntOut(xilinxethernetlite.intnode) +} + +trait HasSystemXilinxEthernetLiteModuleImp extends LazyModuleImp { + val outer: HasSystemXilinxEthernetLite + val phy = IO(new Bundle with PhyPort with MdioPort {}) + + phy <> outer.xilinxethernetlite.module.io.port +} diff --git a/fpga-shells/src/main/scala/ip/xilinx/Xilinx.scala b/fpga-shells/src/main/scala/ip/xilinx/Xilinx.scala index 1e8d3e45..0d4a35ae 100644 --- a/fpga-shells/src/main/scala/ip/xilinx/Xilinx.scala +++ b/fpga-shells/src/main/scala/ip/xilinx/Xilinx.scala @@ -1,4 +1,5 @@ // See LICENSE for license details. +// Modifications copyright (C) 2018-2019 Hex-Five package sifive.fpgashells.ip.xilinx import Chisel._ @@ -25,6 +26,7 @@ class mmcm extends BlackBox { val clk_out1 = Output(Clock()) val clk_out2 = Output(Clock()) val clk_out3 = Output(Clock()) + val clk_out4 = Output(Clock()) val resetn = Input(Bool()) val locked = Output(Bool()) } diff --git a/fpga-shells/src/main/scala/ip/xilinx/ethernetlite/ethernetlite.scala b/fpga-shells/src/main/scala/ip/xilinx/ethernetlite/ethernetlite.scala new file mode 100644 index 00000000..971ab4d0 --- /dev/null +++ b/fpga-shells/src/main/scala/ip/xilinx/ethernetlite/ethernetlite.scala @@ -0,0 +1,210 @@ +// See LICENSE for license details. +// Copyright (C) 2018-2019 Hex-Five +package sifive.fpgashells.ip.xilinx.ethernetlite + +import Chisel._ +import freechips.rocketchip.config._ +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.amba.axi4._ +import freechips.rocketchip.interrupts._ +import freechips.rocketchip.util.{ElaborationArtefacts} + +trait PhyPort extends Bundle { + val phy_tx_clk = Clock(INPUT) + val phy_rx_clk = Clock(INPUT) + val phy_rx_data = Bits(INPUT, 4) + val phy_tx_data = Bits(OUTPUT, 4) + val phy_dv = Bool(INPUT) + val phy_rx_er = Bool(INPUT) + val phy_tx_en = Bool(OUTPUT) + val phy_crs = Bool(INPUT) + val phy_col = Bool(INPUT) + val phy_rst_n = Bool(OUTPUT) +} + +trait MdioPort extends Bundle { + val phy_mdc = Bool(OUTPUT) + val phy_mdio_i = Bool(INPUT) + val phy_mdio_o = Bool(OUTPUT) + val phy_mdio_t = Bool(OUTPUT) +} + +//scalastyle:off +//turn off linter: blackbox name must match verilog module +class axiethernetlite() extends BlackBox { + + val io = new Bundle { + val s_axi_aclk = Clock(INPUT) + val s_axi_aresetn = Bool(INPUT) + + //interrupt + val ip2intc_irpt = Bool(OUTPUT) + + //axi + val s_axi_awid = Bits(INPUT,1) + val s_axi_awaddr = Bits(INPUT,13) + val s_axi_awlen = Bits(INPUT,8) + val s_axi_awsize = Bits(INPUT,3) + val s_axi_awburst = Bits(INPUT,2) + val s_axi_awcache = Bits(INPUT,4) + val s_axi_awvalid = Bool(INPUT) + val s_axi_awready = Bool(OUTPUT) + val s_axi_wdata = Bits(INPUT,32) + val s_axi_wstrb = Bits(INPUT, 4) + val s_axi_wlast = Bool(INPUT) + val s_axi_wvalid = Bool(INPUT) + val s_axi_wready = Bool(OUTPUT) + val s_axi_bid = Bits(OUTPUT,1) + val s_axi_bresp = Bits(OUTPUT,2) + val s_axi_bvalid = Bool(OUTPUT) + val s_axi_bready = Bool(INPUT) + val s_axi_arid = Bits(INPUT,1) + val s_axi_araddr = Bits(INPUT,13) + val s_axi_arlen = Bits(INPUT,8) + val s_axi_arsize = Bits(INPUT,3) + val s_axi_arburst = Bits(INPUT,2) + val s_axi_arcache = Bits(INPUT,4) + val s_axi_arvalid = Bool(INPUT) + val s_axi_arready = Bool(OUTPUT) + val s_axi_rid = Bits(OUTPUT,1) + val s_axi_rdata = Bits(OUTPUT,32) + val s_axi_rresp = Bits(OUTPUT,2) + val s_axi_rlast = Bool(OUTPUT) + val s_axi_rvalid = Bool(OUTPUT) + val s_axi_rready = Bool(INPUT) + + //phy + val phy_tx_clk = Clock(INPUT) + val phy_rx_clk = Clock(INPUT) + val phy_crs = Bool(INPUT) + val phy_dv = Bool(INPUT) + val phy_rx_data = Bits(INPUT,4) + val phy_col = Bool(INPUT) + val phy_rx_er = Bool(INPUT) + val phy_rst_n = Bool(OUTPUT) + val phy_tx_en = Bool(OUTPUT) + val phy_tx_data = Bits(OUTPUT,4) + + //mdio + val phy_mdio_i = Bool(INPUT) + val phy_mdio_o = Bool(OUTPUT) + val phy_mdio_t = Bool(OUTPUT) + val phy_mdc = Bool(OUTPUT) + } +} + +class EthernetLite(implicit p:Parameters) extends LazyModule +{ + val device = new SimpleDevice("ethernet", Seq("xlnx,axi-ethernet-lite-1.00.a")) + + val slave = AXI4SlaveNode(Seq(AXI4SlavePortParameters( + slaves = Seq(AXI4SlaveParameters( + address = List(AddressSet(0x60000000L, 0x1fff)), + resources = Seq(Resource(device, "ranges")), + executable = false, + supportsWrite = TransferSizes(1, 64), + supportsRead = TransferSizes(1, 64))), + beatBytes = 4))) + + val intnode = IntSourceNode(IntSourcePortSimple()) + + lazy val module = new LazyRawModuleImp(this) { + val blackbox = Module(new axiethernetlite) + + val (s, _) = slave.in(0) + val (i, _) = intnode.out(0) + + val io = IO(new Bundle { + val clockreset = new Bundle { + val s_axi_aclk = Clock(INPUT) + val s_axi_aresetn = Bool(INPUT) + } + + val port = new Bundle with PhyPort + with MdioPort { + val s_axi_aclk = Clock(INPUT) + val s_axi_aresetn = Bool(INPUT) + } + }) + + //to top level + blackbox.io.phy_tx_clk := io.port.phy_tx_clk + blackbox.io.phy_rx_clk := io.port.phy_rx_clk + blackbox.io.phy_rx_data := io.port.phy_rx_data + io.port.phy_tx_data := blackbox.io.phy_tx_data + blackbox.io.phy_dv := io.port.phy_dv + blackbox.io.phy_rx_er := io.port.phy_rx_er + io.port.phy_tx_en := blackbox.io.phy_tx_en + blackbox.io.phy_crs := io.port.phy_crs + blackbox.io.phy_col := io.port.phy_col + io.port.phy_rst_n := blackbox.io.phy_rst_n + + io.port.phy_mdc := blackbox.io.phy_mdc + blackbox.io.phy_mdio_i := io.port.phy_mdio_i + io.port.phy_mdio_o := blackbox.io.phy_mdio_o + io.port.phy_mdio_t := blackbox.io.phy_mdio_t + + i(0) := blackbox.io.ip2intc_irpt + + blackbox.io.s_axi_aclk := io.clockreset.s_axi_aclk + blackbox.io.s_axi_aresetn := io.clockreset.s_axi_aresetn + + //s + //AXI4 signals ordered as per AXI4 Specification (Release D) Section A.2 + //-{lock, cache, prot, qos} + //-{aclk, aresetn, awuser, wid, wuser, buser, ruser} + //global signals + //blackbox.io.s_axi_aclk := s.aw.aclk + //blackbox.io.s_axi_aresetn := s.aw.aresetn + //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_awlock := s.aw.bits.lock + blackbox.io.s_axi_awcache := s.aw.bits.cache + //blackbox.io.s_axi_awprot := s.aw.bits.prot + //blackbox.io.s_axi_awqos := s.aw.bits.qos + //blackbox.io.s_axi_awregion := UInt(0) + //blackbox.io.awuser := s.aw.bits.user + blackbox.io.s_axi_awvalid := s.aw.valid + s.aw.ready := blackbox.io.s_axi_awready + //slave interface write data ports + //blackbox.io.s_axi_wid := s.w.bits.id + 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_wuser := s.w.bits.user + blackbox.io.s_axi_wvalid := s.w.valid + s.w.ready := blackbox.io.s_axi_wready + //slave interface write response + s.b.bits.id := blackbox.io.s_axi_bid + s.b.bits.resp := blackbox.io.s_axi_bresp + //s.b.bits.user := blackbox.io.s_axi_buser + s.b.valid := blackbox.io.s_axi_bvalid + blackbox.io.s_axi_bready := s.b.ready + //slave AXI interface read address ports + 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_arlock := s.ar.bits.lock + blackbox.io.s_axi_arcache := s.ar.bits.cache + //blackbox.io.s_axi_arprot := s.ar.bits.prot + //blackbox.io.s_axi_arqos := s.ar.bits.qos + //blackbox.io.s_axi_arregion := UInt(0) + //blackbox.io.s_axi_aruser := s.ar.bits.user + blackbox.io.s_axi_arvalid := s.ar.valid + s.ar.ready := blackbox.io.s_axi_arready + //slave AXI interface read data ports + 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.bits.ruser := blackbox.io.s_axi_ruser + s.r.valid := blackbox.io.s_axi_rvalid + blackbox.io.s_axi_rready := s.r.ready + } +} diff --git a/fpga-shells/src/main/scala/shell/xilinx/ArtyShell.scala b/fpga-shells/src/main/scala/shell/xilinx/ArtyShell.scala index 132403fc..7aa61ec4 100644 --- a/fpga-shells/src/main/scala/shell/xilinx/ArtyShell.scala +++ b/fpga-shells/src/main/scala/shell/xilinx/ArtyShell.scala @@ -1,4 +1,5 @@ // See LICENSE for license details. +// Modifications copyright (C) 2018-2019 Hex-Five package sifive.fpgashells.shell.xilinx.artyshell import Chisel._ @@ -70,6 +71,21 @@ abstract class ArtyShell(implicit val p: Parameters) extends RawModule { val uart_rxd_out = IO(Analog(1.W)) val uart_txd_in = IO(Analog(1.W)) + // PHY0 + val eth_col = IO(Analog(1.W)) + val eth_crs = IO(Analog(1.W)) + val eth_mdc = IO(Analog(1.W)) + val eth_mdio = IO(Analog(1.W)) + val eth_ref_clk = IO(Analog(1.W)) + val eth_rstn = IO(Analog(1.W)) + val eth_rx_clk = IO(Analog(1.W)) + val eth_rx_dv = IO(Analog(1.W)) + val eth_rxd = IO(Vec(4, Analog(1.W))) + val eth_rxerr = IO(Analog(1.W)) + val eth_tx_clk = IO(Analog(1.W)) + val eth_tx_en = IO(Analog(1.W)) + val eth_txd = IO(Vec(4, Analog(1.W))) + // JA (Used for more generic GPIOs) val ja_0 = IO(Analog(1.W)) val ja_1 = IO(Analog(1.W)) @@ -105,6 +121,7 @@ abstract class ArtyShell(implicit val p: Parameters) extends RawModule { val clock_8MHz = Wire(Clock()) val clock_32MHz = Wire(Clock()) val clock_65MHz = Wire(Clock()) + val clock_25MHz = Wire(Clock()) val mmcm_locked = Wire(Bool()) @@ -131,12 +148,19 @@ abstract class ArtyShell(implicit val p: Parameters) extends RawModule { val ip_mmcm = Module(new mmcm()) ip_mmcm.io.clk_in1 := CLK100MHZ - clock_8MHz := ip_mmcm.io.clk_out1 // 8.388 MHz = 32.768 kHz * 256 - clock_65MHz := ip_mmcm.io.clk_out2 // 65 Mhz - clock_32MHz := ip_mmcm.io.clk_out3 // 65/2 Mhz + clock_25MHz := ip_mmcm.io.clk_out1 // 25 Mhz + clock_8MHz := ip_mmcm.io.clk_out2 // 8.388 MHz = 32.768 kHz * 256 + clock_65MHz := ip_mmcm.io.clk_out3 // 65 Mhz + clock_32MHz := ip_mmcm.io.clk_out4 // 65/2 Mhz ip_mmcm.io.resetn := ck_rst mmcm_locked := ip_mmcm.io.locked + //----------------------------------------------------------------------- + // Drive external clocks + //----------------------------------------------------------------------- + // PHY chip needs 25 MHz + IOBUF(eth_ref_clk, clock_25MHz.asUInt.toBool) + //----------------------------------------------------------------------- // System Reset //----------------------------------------------------------------------- @@ -243,5 +267,4 @@ abstract class ArtyShell(implicit val p: Parameters) extends RawModule { dut.uart(0).rxd := IOBUF(uart_txd_in) } } - } diff --git a/fpga-shells/xilinx/arty/constraints/arty-master.xdc b/fpga-shells/xilinx/arty/constraints/arty-master.xdc index be9ff378..85e93c59 100644 --- a/fpga-shells/xilinx/arty/constraints/arty-master.xdc +++ b/fpga-shells/xilinx/arty/constraints/arty-master.xdc @@ -189,25 +189,28 @@ set_property -dict { PACKAGE_PIN C2 IOSTANDARD LVCMOS33 } [get_ports { ck_rst ##SMSC Ethernet PHY -#set_property -dict { PACKAGE_PIN D17 IOSTANDARD LVCMOS33 } [get_ports { eth_col }]; #IO_L16N_T2_A27_15 Sch=eth_col -#set_property -dict { PACKAGE_PIN G14 IOSTANDARD LVCMOS33 } [get_ports { eth_crs }]; #IO_L15N_T2_DQS_ADV_B_15 Sch=eth_crs -#set_property -dict { PACKAGE_PIN F16 IOSTANDARD LVCMOS33 } [get_ports { eth_mdc }]; #IO_L14N_T2_SRCC_15 Sch=eth_mdc -#set_property -dict { PACKAGE_PIN K13 IOSTANDARD LVCMOS33 } [get_ports { eth_mdio }]; #IO_L17P_T2_A26_15 Sch=eth_mdio -#set_property -dict { PACKAGE_PIN G18 IOSTANDARD LVCMOS33 } [get_ports { eth_ref_clk }]; #IO_L22P_T3_A17_15 Sch=eth_ref_clk -#set_property -dict { PACKAGE_PIN C16 IOSTANDARD LVCMOS33 } [get_ports { eth_rstn }]; #IO_L20P_T3_A20_15 Sch=eth_rstn -#set_property -dict { PACKAGE_PIN F15 IOSTANDARD LVCMOS33 } [get_ports { eth_rx_clk }]; #IO_L14P_T2_SRCC_15 Sch=eth_rx_clk -#set_property -dict { PACKAGE_PIN G16 IOSTANDARD LVCMOS33 } [get_ports { eth_rx_dv }]; #IO_L13N_T2_MRCC_15 Sch=eth_rx_dv -#set_property -dict { PACKAGE_PIN D18 IOSTANDARD LVCMOS33 } [get_ports { eth_rxd[0] }]; #IO_L21N_T3_DQS_A18_15 Sch=eth_rxd[0] -#set_property -dict { PACKAGE_PIN E17 IOSTANDARD LVCMOS33 } [get_ports { eth_rxd[1] }]; #IO_L16P_T2_A28_15 Sch=eth_rxd[1] -#set_property -dict { PACKAGE_PIN E18 IOSTANDARD LVCMOS33 } [get_ports { eth_rxd[2] }]; #IO_L21P_T3_DQS_15 Sch=eth_rxd[2] -#set_property -dict { PACKAGE_PIN G17 IOSTANDARD LVCMOS33 } [get_ports { eth_rxd[3] }]; #IO_L18N_T2_A23_15 Sch=eth_rxd[3] -#set_property -dict { PACKAGE_PIN C17 IOSTANDARD LVCMOS33 } [get_ports { eth_rxerr }]; #IO_L20N_T3_A19_15 Sch=eth_rxerr -#set_property -dict { PACKAGE_PIN H16 IOSTANDARD LVCMOS33 } [get_ports { eth_tx_clk }]; #IO_L13P_T2_MRCC_15 Sch=eth_tx_clk -#set_property -dict { PACKAGE_PIN H15 IOSTANDARD LVCMOS33 } [get_ports { eth_tx_en }]; #IO_L19N_T3_A21_VREF_15 Sch=eth_tx_en -#set_property -dict { PACKAGE_PIN H14 IOSTANDARD LVCMOS33 } [get_ports { eth_txd[0] }]; #IO_L15P_T2_DQS_15 Sch=eth_txd[0] -#set_property -dict { PACKAGE_PIN J14 IOSTANDARD LVCMOS33 } [get_ports { eth_txd[1] }]; #IO_L19P_T3_A22_15 Sch=eth_txd[1] -#set_property -dict { PACKAGE_PIN J13 IOSTANDARD LVCMOS33 } [get_ports { eth_txd[2] }]; #IO_L17N_T2_A25_15 Sch=eth_txd[2] -#set_property -dict { PACKAGE_PIN H17 IOSTANDARD LVCMOS33 } [get_ports { eth_txd[3] }]; #IO_L18P_T2_A24_15 Sch=eth_txd[3] +set_property -dict { PACKAGE_PIN D17 IOSTANDARD LVCMOS33 } [get_ports { eth_col }]; #IO_L16N_T2_A27_15 Sch=eth_col +set_property -dict { PACKAGE_PIN G14 IOSTANDARD LVCMOS33 } [get_ports { eth_crs }]; #IO_L15N_T2_DQS_ADV_B_15 Sch=eth_crs +set_property -dict { PACKAGE_PIN F16 IOSTANDARD LVCMOS33 } [get_ports { eth_mdc }]; #IO_L14N_T2_SRCC_15 Sch=eth_mdc +set_property -dict { PACKAGE_PIN K13 IOSTANDARD LVCMOS33 } [get_ports { eth_mdio }]; #IO_L17P_T2_A26_15 Sch=eth_mdio +set_property -dict { PACKAGE_PIN G18 IOSTANDARD LVCMOS33 } [get_ports { eth_ref_clk }]; #IO_L22P_T3_A17_15 Sch=eth_ref_clk +set_property -dict { PACKAGE_PIN C16 IOSTANDARD LVCMOS33 } [get_ports { eth_rstn }]; #IO_L20P_T3_A20_15 Sch=eth_rstn +set_property -dict { PACKAGE_PIN F15 IOSTANDARD LVCMOS33 } [get_ports { eth_rx_clk }]; #IO_L14P_T2_SRCC_15 Sch=eth_rx_clk +set_property -dict { PACKAGE_PIN G16 IOSTANDARD LVCMOS33 } [get_ports { eth_rx_dv }]; #IO_L13N_T2_MRCC_15 Sch=eth_rx_dv +set_property -dict { PACKAGE_PIN D18 IOSTANDARD LVCMOS33 } [get_ports { eth_rxd_0 }]; #IO_L21N_T3_DQS_A18_15 Sch=eth_rxd[0] +set_property -dict { PACKAGE_PIN E17 IOSTANDARD LVCMOS33 } [get_ports { eth_rxd_1 }]; #IO_L16P_T2_A28_15 Sch=eth_rxd[1] +set_property -dict { PACKAGE_PIN E18 IOSTANDARD LVCMOS33 } [get_ports { eth_rxd_2 }]; #IO_L21P_T3_DQS_15 Sch=eth_rxd[2] +set_property -dict { PACKAGE_PIN G17 IOSTANDARD LVCMOS33 } [get_ports { eth_rxd_3 }]; #IO_L18N_T2_A23_15 Sch=eth_rxd[3] +set_property -dict { PACKAGE_PIN C17 IOSTANDARD LVCMOS33 } [get_ports { eth_rxerr }]; #IO_L20N_T3_A19_15 Sch=eth_rxerr +set_property -dict { PACKAGE_PIN H16 IOSTANDARD LVCMOS33 } [get_ports { eth_tx_clk }]; #IO_L13P_T2_MRCC_15 Sch=eth_tx_clk +set_property -dict { PACKAGE_PIN H15 IOSTANDARD LVCMOS33 } [get_ports { eth_tx_en }]; #IO_L19N_T3_A21_VREF_15 Sch=eth_tx_en +set_property -dict { PACKAGE_PIN H14 IOSTANDARD LVCMOS33 } [get_ports { eth_txd_0 }]; #IO_L15P_T2_DQS_15 Sch=eth_txd[0] +set_property -dict { PACKAGE_PIN J14 IOSTANDARD LVCMOS33 } [get_ports { eth_txd_1 }]; #IO_L19P_T3_A22_15 Sch=eth_txd[1] +set_property -dict { PACKAGE_PIN J13 IOSTANDARD LVCMOS33 } [get_ports { eth_txd_2 }]; #IO_L17N_T2_A25_15 Sch=eth_txd[2] +set_property -dict { PACKAGE_PIN H17 IOSTANDARD LVCMOS33 } [get_ports { eth_txd_3 }]; #IO_L18P_T2_A24_15 Sch=eth_txd[3] + +create_clock -add -name eth_rx_clk_pin -period 40.00 -waveform {0 20} [get_ports {eth_rx_clk}]; +create_clock -add -name eth_tx_clk_pin -period 40.00 -waveform {0 20} [get_ports {eth_tx_clk}]; ##Quad SPI Flash @@ -231,10 +234,10 @@ set_property -dict { PACKAGE_PIN M14 IOSTANDARD LVCMOS33 IOB TRUE PULLUP TRU #set_property -dict { PACKAGE_PIN A15 IOSTANDARD LVCMOS33 } [get_ports { isns0v95_p }]; #IO_L8P_T1_AD10P_15 Sch=ad_p[10] set_clock_groups -asynchronous \ - -group [list \ - [get_clocks -include_generated_clocks -of_objects [get_ports jd_2]]] \ - -group [list \ - [get_clocks -of_objects [get_pins ip_mmcm/inst/mmcm_adv_inst/CLKOUT0]]] \ - -group [list \ - [get_clocks -of_objects [get_pins ip_mmcm/inst/mmcm_adv_inst/CLKOUT1]] \ - [get_clocks -of_objects [get_pins ip_mmcm/inst/mmcm_adv_inst/CLKOUT2]]] + -group [get_clocks -include_generated_clocks -of_objects [get_ports jd_2]] \ + -group [get_clocks -include_generated_clocks -of_objects [get_ports eth_rx_clk]] \ + -group [get_clocks -include_generated_clocks -of_objects [get_ports eth_tx_clk]] \ + -group [get_clocks -include_generated_clocks -of_objects [get_nets ip_mmcm/inst/clk_out1_mmcm]] \ + -group [get_clocks -include_generated_clocks -of_objects [get_nets ip_mmcm/inst/clk_out2_mmcm]] \ + -group [get_clocks -include_generated_clocks -of_objects [get_nets ip_mmcm/inst/clk_out3_mmcm]] \ + -group [get_clocks -include_generated_clocks -of_objects [get_nets ip_mmcm/inst/clk_out4_mmcm]] diff --git a/fpga-shells/xilinx/arty/tcl/ip.tcl b/fpga-shells/xilinx/arty/tcl/ip.tcl index fe07c37e..a0e88d61 100644 --- a/fpga-shells/xilinx/arty/tcl/ip.tcl +++ b/fpga-shells/xilinx/arty/tcl/ip.tcl @@ -1,4 +1,5 @@ # See LICENSE for license details. +# Modifications copyright (C) 2018-2019 Hex-Five create_ip -vendor xilinx.com -library ip -name clk_wiz -module_name mmcm -dir $ipdir -force set_property -dict [list \ @@ -7,9 +8,11 @@ set_property -dict [list \ CONFIG.CLKOUT1_USED {true} \ CONFIG.CLKOUT2_USED {true} \ CONFIG.CLKOUT3_USED {true} \ - CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {8.388} \ - CONFIG.CLKOUT2_REQUESTED_OUT_FREQ {65.000} \ - CONFIG.CLKOUT3_REQUESTED_OUT_FREQ {32.500} \ + CONFIG.CLKOUT4_USED {true} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {25.00} \ + CONFIG.CLKOUT2_REQUESTED_OUT_FREQ {8.388} \ + CONFIG.CLKOUT3_REQUESTED_OUT_FREQ {65.000} \ + CONFIG.CLKOUT4_REQUESTED_OUT_FREQ {32.500} \ ] [get_ips mmcm] create_ip -vendor xilinx.com -library ip -name proc_sys_reset -module_name reset_sys -dir $ipdir -force @@ -42,3 +45,15 @@ set_property -dict [list \ CONFIG.C_PROBE14_WIDTH {97} \ ] [get_ips ila] +create_ip -vendor xilinx.com -library ip -name axi_ethernetlite -module_name axiethernetlite -dir $ipdir -force +set_property -dict [list \ + CONFIG.C_S_AXI_PROTOCOL {AXI4} \ + CONFIG.AXI_ACLK_FREQ_MHZ {65} \ + CONFIG.C_DUPLEX {1} \ + CONFIG.C_TX_PING_PONG {1} \ + CONFIG.C_RX_PING_PONG {1} \ + CONFIG.C_INCLUDE_INTERNAL_LOOPBACK {0} \ + CONFIG.C_INCLUDE_GLOBAL_BUFFERS {0} \ + CONFIG.C_INCLUDE_MDIO {1} \ + CONFIG.C_S_AXI_ID_WIDTH {1} \ + ] [get_ips axiethernetlite] diff --git a/sifive-blocks/src/main/scala/devices/gpio/GPIO.scala b/sifive-blocks/src/main/scala/devices/gpio/GPIO.scala index 128a4f22..2d0ee2fc 100644 --- a/sifive-blocks/src/main/scala/devices/gpio/GPIO.scala +++ b/sifive-blocks/src/main/scala/devices/gpio/GPIO.scala @@ -1,4 +1,5 @@ // See LICENSE for license details. +// Modifications copyright (C) 2018-2019 Hex-Five package sifive.blocks.devices.gpio import Chisel._ @@ -148,6 +149,8 @@ abstract class GPIO(busWidthBytes: Int, c: GPIOParams)(implicit p: Parameters) val iofCtrl = Wire(Vec(c.width, new IOFCtrl())) val iofPlusSwPinCtrl = Wire(Vec(c.width, new EnhancedPinCtrl())) + val lip = IO(Vec(c.width, Bool(OUTPUT))) + for (pin <- 0 until c.width) { // Software Pin Control @@ -192,6 +195,10 @@ abstract class GPIO(busWidthBytes: Int, c: GPIOParams)(implicit p: Parameters) (fallIpReg(pin) & fallIeReg(pin)) | (highIpReg(pin) & highIeReg(pin)) | (lowIpReg(pin) & lowIeReg(pin)) + lip(pin) := (riseIpReg(pin) & riseIeReg(pin)) | + (fallIpReg(pin) & fallIeReg(pin)) | + (highIpReg(pin) & highIeReg(pin)) | + (lowIpReg(pin) & lowIeReg(pin)) if (c.includeIOF) { // Send Value to all consumers diff --git a/src/main/scala/x300artydevkit/Config.scala b/src/main/scala/x300artydevkit/Config.scala index 45f83036..57abab89 100644 --- a/src/main/scala/x300artydevkit/Config.scala +++ b/src/main/scala/x300artydevkit/Config.scala @@ -1,5 +1,6 @@ // See LICENSE for license details. -package sifive.freedom.everywhere.e300artydevkit +// Modifications copyright (C) 2018-2019 Hex-Five +package hexfive.x300artydevkit import freechips.rocketchip.config._ import freechips.rocketchip.subsystem._ @@ -16,16 +17,46 @@ import sifive.blocks.devices.spi._ import sifive.blocks.devices.uart._ import sifive.blocks.devices.i2c._ -// Default FreedomEConfig -class DefaultFreedomEConfig extends Config ( - new WithNBreakpoints(2) ++ - new WithNExtTopInterrupts(0) ++ - new WithJtagDTM ++ - new TinyConfig -) +class WithITIMAddr(addr: BigInt) extends Config((site, here, up) => +{ + case RocketTilesKey => up(RocketTilesKey, site) map { r => + r.copy(icache = r.icache.map(_.copy(itimAddr = Some(addr)))) } +}) + +class WithUserMode() extends Config((site, here, up) => +{ + case RocketTilesKey => up(RocketTilesKey, site) map { r => + r.copy(core = r.core.copy(useUser = true)) } +}) + +class WithLocalInterrupts(nLocalInterrupts: Int) extends Config((site, here, up) => +{ + case RocketTilesKey => up(RocketTilesKey, site) map { r => + r.copy(core = r.core.copy(nLocalInterrupts = nLocalInterrupts)) } +}) + +class WithPerfCounters(nPerfCounters: Int) extends Config((site, here, up) => +{ + case RocketTilesKey => up(RocketTilesKey, site) map { r => + r.copy(core = r.core.copy(nPerfCounters = nPerfCounters)) } +}) + +class WithDTSTimebase(timebase: Int) extends Config((site, here, up) => +{ + case DTSTimebase => BigInt(timebase) +}) + +class WithJtagDTMConfig(idcodeVersion: Int, idcodePartNum: Int, idcodeManufId: Int, debugIdleCycles: Int) extends Config((site, here, up) => +{ + case JtagDTMKey => new JtagDTMConfig ( + idcodeVersion = idcodeVersion, + idcodePartNum = idcodePartNum, + idcodeManufId = idcodeManufId, + debugIdleCycles = debugIdleCycles) +}) -// Freedom E300 Arty Dev Kit Peripherals -class E300DevKitPeripherals extends Config((site, here, up) => { +// X300ArtyDevKit Peripherals +class X300ArtyDevKitPeripherals extends Config((site, here, up) => { case PeripheryGPIOKey => List( GPIOParams(address = 0x10012000, width = 32, includeIOF = true)) case PeripheryPWMKey => List( @@ -51,15 +82,28 @@ class E300DevKitPeripherals extends Config((site, here, up) => { MaskROMParams(address = 0x10000, name = "BootROM")) }) -// Freedom E300 Arty Dev Kit Peripherals -class E300ArtyDevKitConfig extends Config( - new E300DevKitPeripherals ++ - new DefaultFreedomEConfig().alter((site,here,up) => { - case DTSTimebase => BigInt(32768) - case JtagDTMKey => new JtagDTMConfig ( +// X300ArtyDevKit Config +class X300ArtyDevKitConfig extends Config( + new X300ArtyDevKitPeripherals ++ + new WithDTSTimebase(32768) ++ + new WithJtagDTMConfig( idcodeVersion = 2, idcodePartNum = 0x000, idcodeManufId = 0x489, - debugIdleCycles = 5) - }) + debugIdleCycles = 5) ++ + new WithNBreakpoints(8) ++ + new WithNExtTopInterrupts(0) ++ + new WithJtagDTM ++ + new WithNoMemPort ++ + new WithNoMMIOPort ++ + new WithNMemoryChannels(0) ++ + new WithNBanks(0) ++ + new WithL1ICacheWays(4) ++ + new WithL1DCacheSets(1024) ++ + new WithUserMode ++ + new WithITIMAddr(0x08000000) ++ + new WithLocalInterrupts(3) ++ + new WithPerfCounters(2) ++ + new With1TinyCore ++ + new BaseConfig ) diff --git a/src/main/scala/x300artydevkit/FPGAChip.scala b/src/main/scala/x300artydevkit/FPGAChip.scala index e0b0634c..c739652a 100644 --- a/src/main/scala/x300artydevkit/FPGAChip.scala +++ b/src/main/scala/x300artydevkit/FPGAChip.scala @@ -1,5 +1,6 @@ // See LICENSE for license details. -package sifive.freedom.everywhere.e300artydevkit +// Modifications copyright (C) 2018-2019 Hex-Five +package hexfive.x300artydevkit import Chisel._ import chisel3.core.{attach} @@ -12,13 +13,13 @@ import sifive.blocks.devices.gpio._ import sifive.blocks.devices.spi._ import sifive.fpgashells.shell.xilinx.artyshell.{ArtyShell} -import sifive.fpgashells.ip.xilinx.{IBUFG, IOBUF, PULLUP, PowerOnResetFPGAOnly} +import sifive.fpgashells.ip.xilinx.{IBUFG, IBUF, IOBUF, PULLUP, PowerOnResetFPGAOnly} //------------------------------------------------------------------------- -// E300ArtyDevKitFPGAChip +// X300ArtyDevKitFPGAChip //------------------------------------------------------------------------- -class E300ArtyDevKitFPGAChip(implicit override val p: Parameters) extends ArtyShell { +class X300ArtyDevKitFPGAChip(implicit override val p: Parameters) extends ArtyShell { //----------------------------------------------------------------------- // Clock divider @@ -33,12 +34,34 @@ class E300ArtyDevKitFPGAChip(implicit override val p: Parameters) extends ArtySh slow_clock := clockToggleReg } - //----------------------------------------------------------------------- - // DUT - //----------------------------------------------------------------------- + withClockAndReset(clock_65MHz, ck_rst) { + //----------------------------------------------------------------------- + // DUT + //----------------------------------------------------------------------- + val dut = Module(new X300ArtyDevKitPlatform) - withClockAndReset(clock_32MHz, ck_rst) { - val dut = Module(new E300ArtyDevKitPlatform) + //--------------------------------------------------------------------- + // PHY IOBUFs + //--------------------------------------------------------------------- + + IOBUF(eth_tx_clk, dut.io.pins.phy.phy_tx_clk) + IOBUF(eth_rx_clk, dut.io.pins.phy.phy_rx_clk) + IOBUF(eth_txd(0), dut.io.pins.phy.phy_tx_data(0)) + IOBUF(eth_txd(1), dut.io.pins.phy.phy_tx_data(1)) + IOBUF(eth_txd(2), dut.io.pins.phy.phy_tx_data(2)) + IOBUF(eth_txd(3), dut.io.pins.phy.phy_tx_data(3)) + IOBUF(eth_rxd(0), dut.io.pins.phy.phy_rx_data(0)) + IOBUF(eth_rxd(1), dut.io.pins.phy.phy_rx_data(1)) + IOBUF(eth_rxd(2), dut.io.pins.phy.phy_rx_data(2)) + IOBUF(eth_rxd(3), dut.io.pins.phy.phy_rx_data(3)) + IOBUF(eth_rx_dv, dut.io.pins.phy.phy_dv) + IOBUF(eth_rxerr, dut.io.pins.phy.phy_rx_er) + IOBUF(eth_tx_en, dut.io.pins.phy.phy_tx_en) + IOBUF(eth_crs, dut.io.pins.phy.phy_crs) + IOBUF(eth_col, dut.io.pins.phy.phy_col) + IOBUF(eth_mdc, dut.io.pins.phy.phy_mdc) + IOBUF(eth_mdio, dut.io.pins.phy.phy_mdio) + IOBUF(eth_rstn, dut.io.pins.phy.phy_rst_n) //--------------------------------------------------------------------- // SPI flash IOBUFs @@ -71,7 +94,7 @@ class E300ArtyDevKitFPGAChip(implicit override val p: Parameters) extends ArtySh PULLUP(jd_6) // jtag reset - val jtag_power_on_reset = PowerOnResetFPGAOnly(clock_32MHz) + val jtag_power_on_reset = PowerOnResetFPGAOnly(clock_65MHz) dut.io.jtag_reset := jtag_power_on_reset // debug reset @@ -123,13 +146,14 @@ class E300ArtyDevKitFPGAChip(implicit override val p: Parameters) extends ArtySh dut.io.pins.gpio.pins(6).i.ival := 0.U dut.io.pins.gpio.pins(7).i.ival := 0.U - dut.io.pins.gpio.pins(8).i.ival := 0.U + + IOBUF(ja_0, dut.io.pins.gpio.pins(8)) + IOBUF(ja_1, dut.io.pins.gpio.pins(9)) + IOBUF(ja_2, dut.io.pins.gpio.pins(10)) + IOBUF(ja_3, dut.io.pins.gpio.pins(11)) // Header row 3: A0-A5 (we don't support using them as analog inputs) // just treat them as regular digital GPIOs - IOBUF(ck_io(15), dut.io.pins.gpio.pins(9)) // A1 = CS(2) - IOBUF(ck_io(16), dut.io.pins.gpio.pins(10)) // A2 = CS(3) / PWM2(0) - IOBUF(ck_io(17), dut.io.pins.gpio.pins(11)) // A3 = PWM2(1) IOBUF(ck_io(18), dut.io.pins.gpio.pins(12)) // A4 = PWM2(2) / SDA IOBUF(ck_io(19), dut.io.pins.gpio.pins(13)) // A5 = PWM2(3) / SCL @@ -146,7 +170,6 @@ class E300ArtyDevKitFPGAChip(implicit override val p: Parameters) extends ArtySh IOBUF(led1_b, dut.io.pins.gpio.pins(22)) // and RGB LED2 R,G,B inputs = PWM2(1,2,3) when iof_1 is active - IOBUF(led2_r, dut.io.pins.gpio.pins(11)) IOBUF(led2_g, dut.io.pins.gpio.pins(12)) IOBUF(led2_b, dut.io.pins.gpio.pins(13)) @@ -164,10 +187,6 @@ class E300ArtyDevKitFPGAChip(implicit override val p: Parameters) extends ArtySh attach(btn_3, iobuf_btn_3.io.IO) dut.io.pins.aon.pmu.dwakeup_n.i.ival := ~iobuf_btn_3.io.O & dut.io.pins.aon.pmu.dwakeup_n.o.ie - // UART1 RX/TX pins are assigned to PMOD_D connector pins 0/1 - IOBUF(ja_0, dut.io.pins.gpio.pins(25)) // UART1 TX - IOBUF(ja_1, dut.io.pins.gpio.pins(24)) // UART1 RX - // SPI2 pins mapped to 6 pin ICSP connector (standard on later // arduinos) These are connected to some extra GPIO pins not connected // on the HiFive1 board diff --git a/src/main/scala/x300artydevkit/Platform.scala b/src/main/scala/x300artydevkit/Platform.scala index 6e7003ef..874d88cb 100644 --- a/src/main/scala/x300artydevkit/Platform.scala +++ b/src/main/scala/x300artydevkit/Platform.scala @@ -1,5 +1,6 @@ // See LICENSE for license details. -package sifive.freedom.everywhere.e300artydevkit +// Modifications copyright (C) 2018-2019 Hex-Five +package hexfive.x300artydevkit import Chisel._ @@ -8,6 +9,8 @@ import freechips.rocketchip.subsystem._ import freechips.rocketchip.devices.debug._ import freechips.rocketchip.devices.tilelink._ import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.amba.axi4._ +import freechips.rocketchip.util.HeterogeneousBag import freechips.rocketchip.util.ResetCatchAndSync import freechips.rocketchip.system._ @@ -20,6 +23,8 @@ import sifive.blocks.devices.uart._ import sifive.blocks.devices.i2c._ import sifive.blocks.devices.pinctrl._ +import sifive.fpgashells.ip.xilinx.ethernetlite.{PhyPort, MdioPort} + //------------------------------------------------------------------------- // PinGen //------------------------------------------------------------------------- @@ -31,28 +36,45 @@ object PinGen { } } +class PhyPins[T <: Pin](pingen: () => T) extends Bundle { + val phy_tx_clk = pingen() + val phy_rx_clk = pingen() + val phy_rx_data = Vec(4, pingen()) + val phy_tx_data = Vec(4, pingen()) + val phy_dv = pingen() + val phy_rx_er = pingen() + val phy_tx_en = pingen() + val phy_crs = pingen() + val phy_col = pingen() + val phy_rst_n = pingen() + val phy_mdc = pingen() + val phy_mdio = pingen() +} + //------------------------------------------------------------------------- -// E300ArtyDevKitPlatformIO +// X300ArtyDevKitPlatformIO //------------------------------------------------------------------------- -class E300ArtyDevKitPlatformIO(implicit val p: Parameters) extends Bundle { +class X300ArtyDevKitPlatformIO(implicit val p: Parameters) extends Bundle { val pins = new Bundle { val jtag = new JTAGPins(() => PinGen(), false) val gpio = new GPIOPins(() => PinGen(), p(PeripheryGPIOKey)(0)) val qspi = new SPIPins(() => PinGen(), p(PeripherySPIFlashKey)(0)) val aon = new MockAONWrapperPins() + val phy = new PhyPins(() => PinGen()) } val jtag_reset = Bool(INPUT) val ndreset = Bool(OUTPUT) } //------------------------------------------------------------------------- -// E300ArtyDevKitPlatform +// X300ArtyDevKitPlatform //------------------------------------------------------------------------- -class E300ArtyDevKitPlatform(implicit val p: Parameters) extends Module { - val sys = Module(LazyModule(new E300ArtyDevKitSystem).module) - val io = new E300ArtyDevKitPlatformIO +class X300ArtyDevKitPlatform(implicit val p: Parameters) extends Module { + val interface = new X300ArtyDevKitSystem + val sys = Module(LazyModule(interface).module) + val io = new X300ArtyDevKitPlatformIO // This needs to be de-asserted synchronously to the coreClk. val async_corerst = sys.aon.rsts.corerst @@ -76,6 +98,30 @@ class E300ArtyDevKitPlatform(implicit val p: Parameters) extends Module { val sys_pwm = sys.pwm val sys_spi = sys.spi val sys_i2c = sys.i2c + val sys_phy = sys.phy + + sys_phy.phy_tx_clk := io.pins.phy.phy_tx_clk.inputPin().asClock + sys_phy.phy_rx_clk := io.pins.phy.phy_rx_clk.inputPin().asClock + sys_phy.phy_rx_data := io.pins.phy.phy_rx_data(3).inputPin() ## + io.pins.phy.phy_rx_data(2).inputPin() ## + io.pins.phy.phy_rx_data(1).inputPin() ## + io.pins.phy.phy_rx_data(0).inputPin() + sys_phy.phy_dv := io.pins.phy.phy_dv.inputPin() + sys_phy.phy_rx_er := io.pins.phy.phy_rx_er.inputPin() + sys_phy.phy_crs := io.pins.phy.phy_crs.inputPin() + sys_phy.phy_col := io.pins.phy.phy_col.inputPin() + io.pins.phy.phy_tx_data(3).outputPin(sys_phy.phy_tx_data(3)) + io.pins.phy.phy_tx_data(2).outputPin(sys_phy.phy_tx_data(2)) + io.pins.phy.phy_tx_data(1).outputPin(sys_phy.phy_tx_data(1)) + io.pins.phy.phy_tx_data(0).outputPin(sys_phy.phy_tx_data(0)) + io.pins.phy.phy_tx_en.outputPin(sys_phy.phy_tx_en) + io.pins.phy.phy_rst_n.outputPin(sys_phy.phy_rst_n) + io.pins.phy.phy_mdc.outputPin(sys_phy.phy_mdc) + + sys_phy.phy_mdio_i := io.pins.phy.phy_mdio.i.ival + io.pins.phy.phy_mdio.o.oval := sys_phy.phy_mdio_o + io.pins.phy.phy_mdio.o.oe := ~sys_phy.phy_mdio_t + io.pins.phy.phy_mdio.o.ie := sys_phy.phy_mdio_t val uart_pins = p(PeripheryUARTKey).map { c => Wire(new UARTPins(() => PinGen()))} val pwm_pins = p(PeripheryPWMKey).map { c => Wire(new PWMPins(() => PinGen(), c))} diff --git a/src/main/scala/x300artydevkit/System.scala b/src/main/scala/x300artydevkit/System.scala index 93d93529..fb51e18d 100644 --- a/src/main/scala/x300artydevkit/System.scala +++ b/src/main/scala/x300artydevkit/System.scala @@ -1,5 +1,6 @@ // See LICENSE for license details. -package sifive.freedom.everywhere.e300artydevkit +// Modifications copyright (C) 2018-2019 Hex-Five +package hexfive.x300artydevkit import Chisel._ @@ -8,6 +9,7 @@ import freechips.rocketchip.subsystem._ import freechips.rocketchip.devices.debug._ import freechips.rocketchip.devices.tilelink._ import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.interrupts._ import freechips.rocketchip.system._ import sifive.blocks.devices.mockaon._ @@ -17,34 +19,64 @@ import sifive.blocks.devices.spi._ import sifive.blocks.devices.uart._ import sifive.blocks.devices.i2c._ +import sifive.fpgashells.devices.xilinx.xilinxethernetlite._ + //------------------------------------------------------------------------- -// E300ArtyDevKitSystem +// X300ArtyDevKitSystem //------------------------------------------------------------------------- -class E300ArtyDevKitSystem(implicit p: Parameters) extends RocketSubsystem +class X300ArtyDevKitSystem(implicit p: Parameters) extends RocketSubsystem with HasPeripheryMaskROMSlave with HasPeripheryDebug with HasPeripheryMockAON with HasPeripheryUART with HasPeripherySPIFlash with HasPeripherySPI - with HasPeripheryGPIO with HasPeripheryPWM - with HasPeripheryI2C { - override lazy val module = new E300ArtyDevKitSystemModule(this) + with HasPeripheryI2C + with HasSystemXilinxEthernetLite { + override lazy val module = new X300ArtyDevKitSystemModule(this) + + val gpio = p(PeripheryGPIOKey).map { ps => + GPIO.attach(GPIOAttachParams(ps, pbus, ibus.fromAsync)) + } + + val gpioNodes = gpio.map { g => + g.ioNode.makeSink + } + + private val device = new Device with DeviceInterrupts { + def describe(resources: ResourceBindings): Description = { + Description("soc/local-interrupts", describeInterrupts(resources)) + } + } + + val clicInterrupts = IntSourceNode(IntSourcePortSimple(num = 3, resources = device.int)) + + val asyncXing = LazyModule(new IntXing(3)) + asyncXing.intnode := clicInterrupts + tiles(0).crossIntIn() := asyncXing.intnode } -class E300ArtyDevKitSystemModule[+L <: E300ArtyDevKitSystem](_outer: L) +class X300ArtyDevKitSystemModule[+L <: X300ArtyDevKitSystem](_outer: L) extends RocketSubsystemModuleImp(_outer) with HasPeripheryDebugModuleImp with HasPeripheryUARTModuleImp with HasPeripherySPIModuleImp - with HasPeripheryGPIOModuleImp with HasPeripherySPIFlashModuleImp with HasPeripheryMockAONModuleImp with HasPeripheryPWMModuleImp - with HasPeripheryI2CModuleImp { + with HasPeripheryI2CModuleImp + with HasSystemXilinxEthernetLiteModuleImp { // Reset vector is set to the location of the mask rom val maskROMParams = p(PeripheryMaskROMKey) global_reset_vector := maskROMParams(0).address.U + + val gpio = outer.gpioNodes.zipWithIndex.map { case(n,i) => n.makeIO()(ValName(s"gpio_$i")) } + + outer.clicInterrupts.out.map(_._1).flatten.zipWithIndex.foreach { + case(o, 0) => o := outer.gpio(0).module.lip(15) + case(o, 1) => o := outer.gpio(0).module.lip(30) + case(o, 2) => o := outer.gpio(0).module.lip(31) + } }