diff --git a/make.py b/make.py index fc8548ff4..e051beae9 100755 --- a/make.py +++ b/make.py @@ -4,14 +4,14 @@ import argparse, os, importlib, subprocess from mibuild.tools import write_to_file -from misoclib import cpuif +from misoclib.gensoc import cpuif from misoclib.s6ddrphy import initsequence import top, jtag def build(platform_name, build_bitstream, build_header, csr_csv_filename, *soc_args, **soc_kwargs): platform_module = importlib.import_module("mibuild.platforms."+platform_name) platform = platform_module.Platform() - soc = top.SoC(platform, platform_name, *soc_args, **soc_kwargs) + soc = top.SoC(platform, *soc_args, **soc_kwargs) platform.add_platform_command(""" INST "mxcrg/wr_bufpll" LOC = "BUFPLL_X0Y2"; diff --git a/misoclib/gensoc/__init__.py b/misoclib/gensoc/__init__.py new file mode 100644 index 000000000..ee2efafa1 --- /dev/null +++ b/misoclib/gensoc/__init__.py @@ -0,0 +1,128 @@ +from operator import itemgetter +from collections import defaultdict +from math import ceil + +from migen.fhdl.std import * +from migen.bank import csrgen +from migen.bus import wishbone, csr, lasmibus, dfi +from migen.bus import wishbone2lasmi, wishbone2csr + +from misoclib import lm32, uart, dfii, lasmicon, identifier, timer, memtest + +class GenSoC(Module): + csr_base = 0xe0000000 + csr_map = { + "crg": 0, # user + "uart": 1, # provided + "identifier": 2, # provided + "timer0": 3, # provided + "buttons": 4, # user + "leds": 5, # user + } + interrupt_map = { + "uart": 0, + "timer0": 1, + } + known_platform_id = defaultdict(lambda: 0x554E, { + "mixxeo": 0x4D58, + "m1": 0x4D31 + }) + + def __init__(self, platform, clk_freq, sram_size, l2_size=0): + self.clk_freq = clk_freq + self.sram_size = sram_size + self.l2_size = l2_size + + # Wishbone + self.submodules.cpu = lm32.LM32() + self.submodules.sram = wishbone.SRAM(sram_size) + self.submodules.wishbone2csr = wishbone2csr.WB2CSR() + + # rom 0x00000000 (shadow @0x80000000) user + # SRAM/debug 0x10000000 (shadow @0x90000000) provided + # CSR bridge 0x60000000 (shadow @0xe0000000) provided + self._wb_masters = [self.cpu.ibus, self.cpu.dbus] + self._wb_slaves = [ + (lambda a: a[26:29] == 1, self.sram.bus), + (lambda a: a[27:29] == 3, self.wishbone2csr.wishbone) + ] + + # CSR + self.submodules.uart = uart.UART(platform.request("serial"), clk_freq, baud=115200) + self.submodules.identifier = identifier.Identifier(self.known_platform_id[platform.name], int(clk_freq), + log2_int(l2_size) if l2_size else 0) + self.submodules.timer0 = timer.Timer() + + def add_wb_master(self, wbm): + if self.finalized: + raise FinalizeError + self._wb_masters.append(wbm) + + def add_wb_slave(self, address_decoder, interface): + if self.finalized: + raise FinalizeError + self._wb_slaves.append((address_decoder, interface)) + + def do_finalize(self): + # Wishbone + self.submodules.wishbonecon = wishbone.InterconnectShared(self._wb_masters, + self._wb_slaves, register=True) + + # CSR + self.submodules.csrbankarray = csrgen.BankArray(self, + lambda name, memory: self.csr_map[name if memory is None else name + "_" + memory.name_override]) + self.submodules.csrcon = csr.Interconnect(self.wishbone2csr.csr, self.csrbankarray.get_buses()) + + # Interrupts + for k, v in sorted(self.interrupt_map.items(), key=itemgetter(1)): + if hasattr(self, k): + self.comb += self.cpu.interrupt[v].eq(getattr(self, k).ev.irq) + + def ns(self, t, margin=True): + clk_period_ns = 1000000000/self.clk_freq + if margin: + t += clk_period_ns/2 + return ceil(t/clk_period_ns) + +class SDRAMSoC(GenSoC): + csr_map = { + "dfii": 6, + "lasmicon": 7, + "memtest_w": 8, + "memtest_r": 9 + } + csr_map.update(GenSoC.csr_map) + + def __init__(self, platform, clk_freq, sram_size, l2_size, with_memtest): + GenSoC.__init__(self, platform, clk_freq, sram_size, l2_size) + self.with_memtest = with_memtest + self._sdram_modules_created = False + + def create_sdram_modules(self, phy_dfi, phy_settings, sdram_geom, sdram_timing): + if self._sdram_modules_created: + raise FinalizeError + self._sdram_modules_created = True + + # DFI + self.submodules.dfii = dfii.DFIInjector(sdram_geom.mux_a, sdram_geom.bank_a, + phy_settings.dfi_d, phy_settings.nphases) + self.submodules.dficon0 = dfi.Interconnect(self.dfii.master, phy_dfi) + + # LASMI + self.submodules.lasmicon = lasmicon.LASMIcon(phy_settings, sdram_geom, sdram_timing) + self.submodules.dficon1 = dfi.Interconnect(self.lasmicon.dfi, self.dfii.slave) + + self.submodules.lasmixbar = lasmibus.Crossbar([self.lasmicon.lasmic], self.lasmicon.nrowbits) + + if self.with_memtest: + self.submodules.memtest_w = memtest.MemtestWriter(self.lasmixbar.get_master()) + self.submodules.memtest_r = memtest.MemtestReader(self.lasmixbar.get_master()) + + # Wishbone bridge: map SDRAM at 0x40000000 (shadow @0xc0000000) + self.submodules.wishbone2lasmi = wishbone2lasmi.WB2LASMI(self.l2_size//4, self.lasmixbar.get_master()) + self.add_wb_slave(lambda a: a[27:29] == 2, self.wishbone2lasmi.wishbone) + + def do_finalize(self): + if not self._sdram_modules_created: + raise FinalizeError("Need to call SDRAMSoC.create_sdram_modules()") + GenSoC.do_finalize(self) diff --git a/misoclib/cpuif.py b/misoclib/gensoc/cpuif.py similarity index 100% rename from misoclib/cpuif.py rename to misoclib/gensoc/cpuif.py diff --git a/top.py b/top.py index 50a6502be..ecf3074f6 100644 --- a/top.py +++ b/top.py @@ -1,46 +1,12 @@ from fractions import Fraction -from math import ceil -from operator import itemgetter -from collections import defaultdict from migen.fhdl.std import * -from migen.bus import wishbone, csr, lasmibus, dfi -from migen.bus import wishbone2lasmi, wishbone2csr -from migen.bank import csrgen from mibuild.generic_platform import ConstraintError -from misoclib import mxcrg, lm32, norflash, uart, s6ddrphy, dfii, lasmicon, \ - identifier, timer, minimac3, framebuffer, dvisampler, gpio, memtest +from misoclib import lasmicon, mxcrg, norflash, s6ddrphy, minimac3, framebuffer, dvisampler, gpio +from misoclib.gensoc import SDRAMSoC -clk_freq = (83 + Fraction(1, 3))*1000000 -sram_size = 4096 # in bytes -l2_size = 8192 # in bytes - -clk_period_ns = 1000000000/clk_freq -def ns(t, margin=True): - if margin: - t += clk_period_ns/2 - return ceil(t/clk_period_ns) - -sdram_geom = lasmicon.GeomSettings( - bank_a=2, - row_a=13, - col_a=10 -) -sdram_timing = lasmicon.TimingSettings( - tRP=ns(15), - tRCD=ns(15), - tWR=ns(15), - tWTR=2, - tREFI=ns(7800, False), - tRFC=ns(70), - - req_queue_size=8, - read_time=32, - write_time=16 -) - -class MXClockPads: +class _MXClockPads: def __init__(self, platform): self.clk50 = platform.request("clk50") self.trigger_reset = 0 @@ -57,129 +23,96 @@ class MXClockPads: self.eth_rx_clk = eth_clocks.rx self.eth_tx_clk = eth_clocks.tx -class SoC(Module): - csr_base = 0xe0000000 +class MiniSoC(SDRAMSoC): csr_map = { - "crg": 0, - "uart": 1, - "dfii": 2, - "identifier": 3, - "timer0": 4, - "minimac": 5, - "fb": 6, - "lasmicon": 7, - "dvisampler0": 8, - "dvisampler0_edid_mem": 9, - "dvisampler1": 10, - "dvisampler1_edid_mem": 11, - "pots": 12, - "buttons": 13, - "leds": 14, - "memtest_w": 15, - "memtest_r": 16 + "minimac": 10, + "fb": 11, + "dvisampler0": 12, + "dvisampler0_edid_mem": 13, + "dvisampler1": 14, + "dvisampler1_edid_mem": 15, } + csr_map.update(SDRAMSoC.csr_map) + interrupt_map = { - "uart": 0, - "timer0": 1, "minimac": 2, "dvisampler0": 3, "dvisampler1": 4, } - known_platform_id = defaultdict(lambda: 0x554E, { - "mixxeo": 0x4D58, - "m1": 0x4D31 - }) + interrupt_map.update(SDRAMSoC.interrupt_map) - def __init__(self, platform, platform_name, with_memtest): - # - # DFI - # - self.submodules.ddrphy = s6ddrphy.S6DDRPHY(platform.request("ddram"), memtype="DDR", nphases=2, cl=3, rd_bitslip=0, wr_bitslip=3, dqs_ddr_alignment="C1") - self.submodules.dfii = dfii.DFIInjector(sdram_geom.mux_a, sdram_geom.bank_a, - self.ddrphy.phy_settings.dfi_d, self.ddrphy.phy_settings.nphases) - self.submodules.dficon0 = dfi.Interconnect(self.dfii.master, self.ddrphy.dfi) + def __init__(self, platform, with_memtest): + SDRAMSoC.__init__(self, platform, + clk_freq=(83 + Fraction(1, 3))*1000000, + sram_size=4096, + l2_size=8192, + with_memtest=with_memtest) - # - # LASMI - # - self.submodules.lasmicon = lasmicon.LASMIcon(self.ddrphy.phy_settings, sdram_geom, sdram_timing) - self.submodules.dficon1 = dfi.Interconnect(self.lasmicon.dfi, self.dfii.slave) + sdram_geom = lasmicon.GeomSettings( + bank_a=2, + row_a=13, + col_a=10 + ) + sdram_timing = lasmicon.TimingSettings( + tRP=self.ns(15), + tRCD=self.ns(15), + tWR=self.ns(15), + tWTR=2, + tREFI=self.ns(7800, False), + tRFC=self.ns(70), - self.submodules.lasmixbar = lasmibus.Crossbar([self.lasmicon.lasmic], self.lasmicon.nrowbits) - lasmim_wb = self.lasmixbar.get_master() - if platform_name == "mixxeo": - lasmim_fb0, lasmim_fb1, lasmim_dvi0, lasmim_dvi1 = (self.lasmixbar.get_master() for i in range(4)) - if platform_name == "m1": - lasmim_fb = self.lasmixbar.get_master() - if with_memtest: - lasmim_mtw, lasmim_mtr = self.lasmixbar.get_master(), self.lasmixbar.get_master() + req_queue_size=8, + read_time=32, + write_time=16 + ) + self.submodules.ddrphy = s6ddrphy.S6DDRPHY(platform.request("ddram"), memtype="DDR", + nphases=2, cl=3, rd_bitslip=0, wr_bitslip=3, dqs_ddr_alignment="C1") + self.create_sdram_modules(self.ddrphy.dfi, self.ddrphy.phy_settings, sdram_geom, sdram_timing) - # - # WISHBONE - # - self.submodules.cpu = lm32.LM32() + # Wishbone self.submodules.norflash = norflash.NorFlash(platform.request("norflash"), 12) - self.submodules.sram = wishbone.SRAM(sram_size) self.submodules.minimac = minimac3.MiniMAC(platform.request("eth")) - self.submodules.wishbone2lasmi = wishbone2lasmi.WB2LASMI(l2_size//4, lasmim_wb) - self.submodules.wishbone2csr = wishbone2csr.WB2CSR() + self.add_wb_slave(lambda a: a[26:29] == 0, self.norflash.bus) + self.add_wb_slave(lambda a: a[26:29] == 3, self.minimac.membus) - # norflash 0x00000000 (shadow @0x80000000) - # SRAM/debug 0x10000000 (shadow @0x90000000) - # USB 0x20000000 (shadow @0xa0000000) - # Ethernet 0x30000000 (shadow @0xb0000000) - # SDRAM 0x40000000 (shadow @0xc0000000) - # CSR bridge 0x60000000 (shadow @0xe0000000) - self.submodules.wishbonecon = wishbone.InterconnectShared( - [ - self.cpu.ibus, - self.cpu.dbus - ], [ - (lambda a: a[26:29] == 0, self.norflash.bus), - (lambda a: a[26:29] == 1, self.sram.bus), - (lambda a: a[26:29] == 3, self.minimac.membus), - (lambda a: a[27:29] == 2, self.wishbone2lasmi.wishbone), - (lambda a: a[27:29] == 3, self.wishbone2csr.wishbone) - ], - register=True) - - # # CSR - # - self.submodules.crg = mxcrg.MXCRG(MXClockPads(platform), clk_freq) - self.submodules.uart = uart.UART(platform.request("serial"), clk_freq, baud=115200) - self.submodules.identifier = identifier.Identifier(self.known_platform_id[platform_name], int(clk_freq), - log2_int(l2_size)) - self.submodules.timer0 = timer.Timer() - if platform_name == "mixxeo": + self.submodules.crg = mxcrg.MXCRG(_MXClockPads(platform), self.clk_freq) + if platform.name == "mixxeo": self.submodules.leds = gpio.GPIOOut(platform.request("user_led")) - self.submodules.fb = framebuffer.MixFramebuffer(platform.request("vga_out"), platform.request("dvi_out"), - lasmim_fb0, lasmim_fb1) - self.submodules.dvisampler0 = dvisampler.DVISampler(platform.request("dvi_in", 0), lasmim_dvi0) - self.submodules.dvisampler1 = dvisampler.DVISampler(platform.request("dvi_in", 1), lasmim_dvi1) - if platform_name == "m1": + if platform.name == "m1": self.submodules.buttons = gpio.GPIOIn(Cat(platform.request("user_btn", 0), platform.request("user_btn", 2))) self.submodules.leds = gpio.GPIOOut(Cat(*[platform.request("user_led", i) for i in range(2)])) - self.submodules.fb = framebuffer.Framebuffer(platform.request("vga"), None, lasmim_fb) - if with_memtest: - self.submodules.memtest_w = memtest.MemtestWriter(lasmim_mtw) - self.submodules.memtest_r = memtest.MemtestReader(lasmim_mtr) - self.submodules.csrbankarray = csrgen.BankArray(self, - lambda name, memory: self.csr_map[name if memory is None else name + "_" + memory.name_override]) - self.submodules.csrcon = csr.Interconnect(self.wishbone2csr.csr, self.csrbankarray.get_buses()) - - # - # Interrupts - # - for k, v in sorted(self.interrupt_map.items(), key=itemgetter(1)): - if hasattr(self, k): - self.comb += self.cpu.interrupt[v].eq(getattr(self, k).ev.irq) - - # - # Clocking - # + # Clock glue self.comb += [ self.ddrphy.clk4x_wr_strb.eq(self.crg.clk4x_wr_strb), self.ddrphy.clk4x_rd_strb.eq(self.crg.clk4x_rd_strb) ] + +def _get_vga_dvi(platform): + try: + pads_vga = platform.request("vga_out") + except ConstraintError: + pads_vga = None + try: + pads_dvi = platform.request("dvi_out") + except ConstraintError: + pads_dvi = None + return pads_vga, pads_dvi + +class FramebufferSoC(MiniSoC): + def __init__(self, platform, with_memtest): + MiniSoC.__init__(self, platform, with_memtest) + pads_vga, pads_dvi = _get_vga_dvi(platform) + self.submodules.fb = framebuffer.Framebuffer(pads_vga, pads_dvi, self.lasmixbar.get_master()) + +class VideomixerSoC(MiniSoC): + def __init__(self, platform, with_memtest): + MiniSoC.__init__(self, platform, with_memtest) + pads_vga, pads_dvi = _get_vga_dvi(platform) + self.submodules.fb = framebuffer.MixFramebuffer(pads_vga, pads_dvi, + self.lasmixbar.get_master(), self.lasmixbar.get_master()) + self.submodules.dvisampler0 = dvisampler.DVISampler(platform.request("dvi_in", 0), self.lasmixbar.get_master()) + self.submodules.dvisampler1 = dvisampler.DVISampler(platform.request("dvi_in", 1), self.lasmixbar.get_master()) + +SoC = VideomixerSoC