From fb8f11dcb936ab9fdb60e69ce6667a6a0bce7170 Mon Sep 17 00:00:00 2001 From: Raptor Engineering Development Team Date: Fri, 15 Apr 2022 01:53:24 -0500 Subject: [PATCH] WIP: non-functional For comment / early review of overall plan of attack --- src/ls2.py | 158 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 120 insertions(+), 38 deletions(-) diff --git a/src/ls2.py b/src/ls2.py index 50d69e1..d1d7072 100644 --- a/src/ls2.py +++ b/src/ls2.py @@ -34,6 +34,7 @@ from soc.bus.tercel import Tercel # SPI XIP master from soc.bus.opencores_ethmac import EthMAC # OpenCores 10/100 Ethernet MAC from soc.bus.external_core import ExternalCore # external libresoc/microwatt from soc.bus.wb_downconvert import WishboneDownConvert +from soc.bus.wb_async import WBAsyncBridge from soc.bus.syscon import MicrowattSYSCON from soc.interrupts.xics import XICS_ICP, XICS_ICS @@ -249,6 +250,7 @@ class DDR3SoC(SoC, Elaboratable): hyperram_pins=None, xics_icp_addr=None, xics_ics_addr=None, clk_freq=50e6, + dram_clk_freq=None, add_cpu=True): # wishbone routing is as follows: @@ -262,11 +264,13 @@ class DDR3SoC(SoC, Elaboratable): # | # 64to32DownCvt # | - # arbiter------------------------------------------+ - # | | - # +---decoder----+--------+---------+-------+--------+ | - # | | | | | | | | - # uart XICS CSRs DRAM XIP SPI HyperRAM EthMAC + # arbiter--------------------------------------------------------+ + # | | + # +---decoder----+--------+-----------------+-------------+--------+ | + # | | | | | | | | + # | | | WBAsyncBridge | | | | + # | | | | | | | | + # uart XICS CSRs DRAM XIP SPI HyperRAM EthMAC # set up wishbone bus arbiter and decoder. arbiter routes, # decoder maps local-relative addressed satellites to global addresses @@ -286,10 +290,17 @@ class DDR3SoC(SoC, Elaboratable): if fpga in ['versa_ecp5', 'versa_ecp5_85', 'isim', 'ulx3s']: if fpga in ['isim']: pod_bits = 6 - self.crg = ECP5CRG(clk_freq, dram_clk_freq=None, pod_bits=pod_bits) + if fpga in ['versa_ecp5_85']: + self.crg = ECP5CRG(clk_freq, dram_clk_freq=dram_clk_freq, pod_bits=pod_bits) + else: + self.crg = ECP5CRG(clk_freq, dram_clk_freq=None, pod_bits=pod_bits) if fpga in ['arty_a7']: self.crg = ArtyA7CRG(clk_freq) + self.dram_clk_freq = dram_clk_freq + if self.dram_clk_freq is None: + self.dram_clk_freq = clk_freq + # set up CPU, with 64-to-32-bit downconverters if add_cpu: self.cpu = ExternalCore(name="ext_core") @@ -344,6 +355,7 @@ class DDR3SoC(SoC, Elaboratable): spi_offset = 2<<20 if (spi_0_pins is not None) else None dram_offset = ddr_addr if (ddr_pins is not None) else None self.syscon = MicrowattSYSCON(sys_clk_freq=clk_freq, + mem_clk_freq=self.dram_clk_freq, has_uart=(uart_pins is not None), spi_offset=spi_offset, dram_addr=dram_offset) @@ -395,55 +407,103 @@ class DDR3SoC(SoC, Elaboratable): # DRAM Module if ddr_pins is not None: # or fpga == 'sim': - ddrmodule = dram_cls(clk_freq, "1:2") # match DDR3 ASIC P/N + ddrmodule = dram_cls(self.dram_clk_freq, "1:2") # match DDR3 ASIC P/N # remap both the sync domain (wherever it occurs) and - # the sync2x domain. technically this should NOT be done. - # it's a bit of a mess. ok: this should be done only - # when dramsync===sync (and dramsync2x===sync2x) - drs = DomainRenamer({"sync": "dramsync", + # the sync2x domain, if dram frequency is specified and + # not equal to the core clock + drs = None + if (dram_clk_freq is not None) and (self.dram_clk_freq != clk_freq): + drs = lambda x: x + else: + drs = DomainRenamer({"sync": "dramsync", "sync2x": "dramsync2x"}) - # HOWEVER, when the ASyncBridge is deployed, the two domains - # must NOT be renamed, instead this used: - #drs = lambda x: x - # and then the ASyncBridge takes care of the two. - # but, back in ecp5_crg.py, when ASyncBridge is added, - # dram_clk_freq must be passed to ECP5CRG, which will call - # ECP5CRG.phase2_domain on your behalf, setting up the - # necessary dramsync2x which is needed for the xdr=4 IOpads - if fpga == 'sim': self.ddrphy = FakePHY(module=ddrmodule, - settings=sim_ddr3_settings(clk_freq), + settings=sim_ddr3_settings(self.dram_clk_freq), verbosity=SDRAM_VERBOSE_DBG, - clk_freq=clk_freq) + clk_freq=self.dram_clk_freq) else: - self.ddrphy = drs(ECP5DDRPHY(ddr_pins, sys_clk_freq=clk_freq)) - self._decoder.add(self.ddrphy.bus, addr=ddrphy_addr) + self.ddrphy = drs(ECP5DDRPHY(ddr_pins, sys_clk_freq=self.dram_clk_freq)) + + # Set up Wishbone asynchronous bridge + self.ddrphy_async_bus = wishbone.Interface( + addr_width=self.ddrphy.bus.addr_width, + data_width=self.ddrphy.bus.data_width, + granularity=self.ddrphy.bus.granularity, + features={'stall'}) + self.ddrphy_async_bus.memory_map = self.ddrphy.bus.memory_map + + self.ddrphy_async_br = WBAsyncBridge( + master_bus=self.ddrphy_async_bus, + slave_bus=self.ddrphy.bus, + master_clock_domain=None, + slave_clock_domain="dramsync", + address_width=self.ddrphy.bus.addr_width, + data_width=self.ddrphy.bus.data_width, + granularity=self.ddrphy.bus.granularity, + master_features={'stall'}) + + # Add wishbone decoder + self._decoder.add(self.ddrphy_async_bus, addr=ddrphy_addr) dramcore = gramCore(phy=self.ddrphy, geom_settings=ddrmodule.geom_settings, timing_settings=ddrmodule.timing_settings, - clk_freq=clk_freq) + clk_freq=self.dram_clk_freq) if fpga == 'sim': self.dramcore = dramcore else: self.dramcore = drs(dramcore) - self._decoder.add(self.dramcore.bus, addr=dramcore_addr) - # map the DRAM onto Wishbone, XXX use stall but set classic below - # XXX WHEN ADDING ASYNCBRIDGE IT IS THE **BRIDGE** THAT MUST - # XXX HAVE THE STALL SIGNAL, AND THE **BRIDGE** THAT MUST HAVE - # XXX stall=stb&~ack APPLIED - drambone = gramWishbone(dramcore, features={'stall'}) + # Set up Wishbone asynchronous bridge + self.dramcore_async_bus = wishbone.Interface( + addr_width=self.dramcore.bus.addr_width, + data_width=self.dramcore.bus.data_width, + granularity=self.dramcore.bus.granularity, + features={'stall'}) + self.dramcore_async_bus.memory_map = self.dramcore.bus.memory_map + + self.dramcore_async_br = WBAsyncBridge( + master_bus=self.dramcore_async_bus, + slave_bus=self.dramcore.bus, + master_clock_domain=None, + slave_clock_domain="dramsync", + address_width=self.dramcore.bus.addr_width, + data_width=self.dramcore.bus.data_width, + granularity=self.dramcore.bus.granularity, + master_features={'stall'}) + + # Add wishbone decoder + self._decoder.add(self.dramcore_async_bus, addr=dramcore_addr) + + drambone = gramWishbone(dramcore) if fpga == 'sim': self.drambone = drambone else: self.drambone = drs(drambone) - # XXX ADD THE ASYNCBRIDGE NOT THE DRAMBONE.BUS, THEN - # XXX ADD DRAMBONE.BUS TO ASYNCBRIDGE - self._decoder.add(self.drambone.bus, addr=ddr_addr) + + # Set up Wishbone asynchronous bridge + self.drambone_async_bus = wishbone.Interface( + addr_width=self.drambone.bus.addr_width, + data_width=self.drambone.bus.data_width, + granularity=self.drambone.bus.granularity, + features={'stall'}) + self.drambone_async_bus.memory_map = self.drambone.bus.memory_map + + self.drambone_async_br = WBAsyncBridge( + master_bus=self.drambone_async_bus, + slave_bus=self.drambone.bus, + master_clock_domain=None, + slave_clock_domain="dramsync", + address_width=self.drambone.bus.addr_width, + data_width=self.drambone.bus.data_width, + granularity=self.drambone.bus.granularity, + master_features={'stall'}) + + # Add wishbone decoder + self._decoder.add(self.drambone_async_bus, addr=ddr_addr) # additional SRAM at address if DRAM is not also at 0x0 # (TODO, check Flash, and HyperRAM as well) @@ -566,10 +626,29 @@ class DDR3SoC(SoC, Elaboratable): m.submodules.ddrphy = self.ddrphy m.submodules.dramcore = self.dramcore m.submodules.drambone = drambone = self.drambone - # grrr, same problem with drambone: not WB4-pipe compliant - # XXX TAKE THIS OUT, REPLACE WITH ASYNCBRIDGE HAVING - # XXX asyncbridge.bus.stall.eq(asyncbridge.bus.cyc & ...) - comb += drambone.bus.stall.eq(drambone.bus.cyc & ~drambone.bus.ack) + + # add async wishbone bridges + m.submodules.ddrphy_async_br = self.ddrphy_async_br + m.submodules.dramcore_async_br = self.dramcore_async_br + m.submodules.drambone_async_br = self.drambone_async_br + + # grrr, same problem with WB async bridge: not WB4-pipe compliant + comb += self.ddrphy_async_bus.stall.eq(self.ddrphy_async_bus.cyc & ~self.ddrphy_async_bus.ack) + comb += self.dramcore_async_bus.stall.eq(self.dramcore_async_bus.cyc & ~self.dramcore_async_bus.ack) + comb += self.drambone_async_bus.stall.eq(self.drambone_async_bus.cyc & ~self.drambone_async_bus.ack) + + # add wb async bridge verilog source. assumes a directory structure where + # microwatt has been checked out in a common subdirectory with: + # git clone https://github.com/alexforencich/verilog-wishbone.git + # git checkout d1fa24a0 + verilog_wishbone = "../../verilog-wishbone/rtl" + pth = os.path.split(__file__)[0] + pth = os.path.join(pth, verilog_wishbone) + fname = os.path.abspath(pth) + print (fname) + self.ddrphy_async_br.add_verilog_source(fname, platform) + self.dramcore_async_br.add_verilog_source(fname, platform) + self.drambone_async_br.add_verilog_source(fname, platform) # add hyperram module if hasattr(self, "hyperram"): @@ -736,6 +815,7 @@ def build_platform(fpga, firmware): clk_freq = 70e6 if fpga == 'sim': clk_freq = 100e6 + dram_clk_freq = clk_freq if fpga == 'isim': clk_freq = 55e6 # below 50 mhz, stops DRAM being enabled if fpga == 'versa_ecp5': @@ -744,6 +824,7 @@ def build_platform(fpga, firmware): # 50MHz works. 100MHz works. 55MHz does NOT work. # Stick with multiples of 50MHz... clk_freq = 50e6 + dram_clk_freq = 100e6 if fpga == 'arty_a7': clk_freq = 50e6 if fpga == 'ulx3s': @@ -911,6 +992,7 @@ def build_platform(fpga, firmware): xics_icp_addr=0xc000_4000, # XICS_ICP_BASE xics_ics_addr=0xc000_5000, # XICS_ICS_BASE clk_freq=clk_freq, + dram_clk_freq=dram_clk_freq, add_cpu=True) if toolchain == 'Trellis': -- 2.30.2