diff --git a/.travis.yml b/.travis.yml index 26c889fd..4359e711 100644 --- a/.travis.yml +++ b/.travis.yml @@ -114,6 +114,9 @@ jobs: - stage: Targets env: C=lm32.lite P=tinyfpga_bx F=stub T="base" + - stage: Targets + env: C=lm32 P=mimas_a7 T="base net" + # or1k base targets - stage: Targets env: C=or1k P=arty T="base net" @@ -130,6 +133,9 @@ jobs: - stage: Targets env: C=or1k P=pipistrello T="base" + - stage: Targets + env: C=or1k P=mimas_a7 T="base net" + # vexriscv Base targets - stage: Targets env: C=vexriscv P=arty T="base net" @@ -140,6 +146,9 @@ jobs: - stage: Targets env: C=vexriscv P=opsis T="base net" + - stage: Targets + env: C=vexriscv P=mimas_a7 T="base net" + # picorv32 Base targets - stage: Targets env: C=picorv32 P=arty T="base net" @@ -153,6 +162,9 @@ jobs: - stage: Targets env: C=picorv32 P=tinyfpga_bx F=stub T="base" + - stage: Targets + env: C=picorv32 P=mimas_a7 T="base net" + # Linux Targets #-------------------------------------------- - stage: Targets diff --git a/platforms/mimas_a7.py b/platforms/mimas_a7.py new file mode 100644 index 00000000..1eb3500f --- /dev/null +++ b/platforms/mimas_a7.py @@ -0,0 +1,199 @@ +from litex.build.generic_platform import * +from litex.build.xilinx import XilinxPlatform, XC3SProg, VivadoProgrammer + +_io = [ + ("user_led", 0, Pins("K17"), IOStandard("LVCMOS33")), + ("user_led", 1, Pins("J17"), IOStandard("LVCMOS33")), + ("user_led", 2, Pins("L14"), IOStandard("LVCMOS33")), + ("user_led", 3, Pins("L15"), IOStandard("LVCMOS33")), + ("user_led", 4, Pins("L16"), IOStandard("LVCMOS33")), + ("user_led", 5, Pins("K16"), IOStandard("LVCMOS33")), + ("user_led", 6, Pins("M15"), IOStandard("LVCMOS33")), + ("user_led", 7, Pins("M16"), IOStandard("LVCMOS33")), + + ("user_sw", 0, Pins("B21"), IOStandard("LVCMOS33")), + ("user_sw", 1, Pins("A21"), IOStandard("LVCMOS33")), + ("user_sw", 2, Pins("E22"), IOStandard("LVCMOS33")), + ("user_sw", 3, Pins("D22"), IOStandard("LVCMOS33")), + ("user_sw", 4, Pins("E21"), IOStandard("LVCMOS33")), + ("user_sw", 5, Pins("D21"), IOStandard("LVCMOS33")), + ("user_sw", 6, Pins("G21"), IOStandard("LVCMOS33")), + ("user_sw", 7, Pins("G22"), IOStandard("LVCMOS33")), + + + ("user_btn", 0, Pins("P20"), IOStandard("LVCMOS33")), + ("user_btn", 1, Pins("P19"), IOStandard("LVCMOS33")), + ("user_btn", 2, Pins("P17"), IOStandard("LVCMOS33")), + ("user_btn", 3, Pins("N17"), IOStandard("LVCMOS33")), + + + ("clk100", 0, Pins("H4"), IOStandard("LVCMOS33")), + + ("cpu_reset", 0, Pins("M2"), IOStandard("LVCMOS33")), + + + # P22 - QSPI_DQ0 - MOSI + # R22 - QSPI_DQ1 - MISO + # P21 - QSPI_DQ2 - ~WP + # R21 - QSPI_DQ3 - ~HOLD + # T19 - QSPI_CS - ~CS + # L12 - CCLK + ("spiflash_4x", 0, # clock needs to be accessed through STARTUPE2 + Subsignal("cs_n", Pins("T19")), + Subsignal("dq", Pins("P22", "R22", "P21", "R21")), + IOStandard("LVCMOS33") + ), + ("spiflash_1x", 0, # clock needs to be accessed through STARTUPE2 + Subsignal("cs_n", Pins("T19")), + Subsignal("mosi", Pins("P22")), + Subsignal("miso", Pins("R22")), + Subsignal("wp", Pins("P21")), + Subsignal("hold", Pins("R21")), + IOStandard("LVCMOS33") + ), + + ("serial", 0, + Subsignal("tx", Pins("Y21")), + Subsignal("rx", Pins("Y22")), + IOStandard("LVCMOS33"), + ), + + ("ddram", 0, + Subsignal("a", Pins( + "U6 T5 Y6 T6 V2 T4 Y2 R2", + "Y1 R4 W5 W1 AA6 U2"), + IOStandard("SSTL15")), + Subsignal("ba", Pins("W6 U5 R6"), IOStandard("SSTL15")), + Subsignal("ras_n", Pins("V5"), IOStandard("SSTL15")), + Subsignal("cas_n", Pins("T1"), IOStandard("SSTL15")), + Subsignal("we_n", Pins("R3"), IOStandard("SSTL15")), + Subsignal("dm", Pins("Y7 AA1"), IOStandard("SSTL15")), + Subsignal("dq", Pins( + "Y8 AB6 W9 AA8 AB7 V7 AB8 W7", + "V4 AB2 AA5 AB3 AB5 W4 AB1 AA4"), + IOStandard("SSTL15"), + Misc("IN_TERM=UNTUNED_SPLIT_40")), + Subsignal("dqs_p", Pins("V9 Y3"), IOStandard("DIFF_SSTL15")), + Subsignal("dqs_n", Pins("V8 AA3"), IOStandard("DIFF_SSTL15")), + Subsignal("clk_p", Pins("U3"), IOStandard("DIFF_SSTL15")), + Subsignal("clk_n", Pins("V3"), IOStandard("DIFF_SSTL15")), + Subsignal("cke", Pins("U1"), IOStandard("SSTL15")), + Subsignal("odt", Pins("W2"), IOStandard("SSTL15")), + Subsignal("cs_n", Pins("T3"), IOStandard("SSTL15")), + Subsignal("reset_n", Pins("U7"), IOStandard("SSTL15")), + Misc("SLEW=FAST"), + ), + + ("eth_clocks", 0, + Subsignal("tx", Pins("U20")), + Subsignal("rx", Pins("W19")), + IOStandard("LVCMOS33") + ), + ("eth", 0, + Subsignal("rst_n", Pins("R14"), IOStandard("LVCMOS33")), + Subsignal("int_n", Pins("V19")), + Subsignal("mdio", Pins("P16")), + Subsignal("mdc", Pins("R19")), + Subsignal("rx_ctl", Pins("Y19")), + Subsignal("rx_data", Pins("AB18 W20 W17 V20")), + Subsignal("tx_ctl", Pins("T20")), + Subsignal("tx_data", Pins("V18 U18 V17 U17")), + IOStandard("LVCMOS33") + ), + + ("hdmi_in", 0, + Subsignal("clk_p", Pins("K4"), IOStandard("TMDS_33")), + Subsignal("clk_n", Pins("J4"), IOStandard("TMDS_33")), + Subsignal("data0_p", Pins("K1"), IOStandard("TMDS_33")), + Subsignal("data0_n", Pins("J1"), IOStandard("TMDS_33")), + Subsignal("data1_p", Pins("M1"), IOStandard("TMDS_33")), + Subsignal("data1_n", Pins("L1"), IOStandard("TMDS_33")), + Subsignal("data2_p", Pins("P2"), IOStandard("TMDS_33")), + Subsignal("data2_n", Pins("N2"), IOStandard("TMDS_33")), + Subsignal("scl", Pins("J2"), IOStandard("LVCMOS33")), + Subsignal("sda", Pins("H2"), IOStandard("LVCMOS33")), + Subsignal("hpd_en", Pins("G2"), IOStandard("LVCMOS33")), + Subsignal("cec", Pins("K2"), IOStandard("LVCMOS33")), # FIXME + # Subsignal("txen", Pins("R3"), IOStandard("LVCMOS33")), # FIXME + ), + + ("hdmi_out", 0, + Subsignal("clk_p", Pins("L3"), IOStandard("TMDS_33")), + Subsignal("clk_n", Pins("K3"), IOStandard("TMDS_33")), + Subsignal("data0_p", Pins("B1"), IOStandard("TMDS_33")), + Subsignal("data0_n", Pins("A1"), IOStandard("TMDS_33")), + Subsignal("data1_p", Pins("E1"), IOStandard("TMDS_33")), + Subsignal("data1_n", Pins("D1"), IOStandard("TMDS_33")), + Subsignal("data2_p", Pins("G1"), IOStandard("TMDS_33")), + Subsignal("data2_n", Pins("F1"), IOStandard("TMDS_33")), + Subsignal("scl", Pins("D2"), IOStandard("LVCMOS33")), + Subsignal("sda", Pins("C2"), IOStandard("LVCMOS33")), + Subsignal("cec", Pins("E2"), IOStandard("LVCMOS33")), # FIXME + Subsignal("hdp", Pins("B2"), IOStandard("LVCMOS33")), # FIXME + ), +] + +_connectors = [] + +_hdmi_infos = { + "HDMI_OUT0_MNEMONIC": "OUT1", + "HDMI_OUT0_DESCRIPTION" : ( + " Add description\\r\\n" + ), + + "HDMI_IN0_MNEMONIC": "IN1", + "HDMI_IN0_DESCRIPTION" : ( + " Add description\\r\\n" + ), +} + +class Platform(XilinxPlatform): + name = "mimas_a7" + default_clk_name = "clk100" + default_clk_period = 10.0 + hdmi_infos = _hdmi_infos + + # From https://www.xilinx.com/support/documentation/user_guides/ug470_7Series_Config.pdf + # 77,845,216 bits == 9730652 == 0x947a5c -- Therefore 0x1000000 + gateware_size = 0x1000000 + + # Spansion S25FL256S (ID 0x00190201) + # FIXME: Create a "spi flash module" object in the same way we have SDRAM + # module objects. + spiflash_read_dummy_bits = 10 + spiflash_clock_div = 4 + spiflash_total_size = int((128/8)*1024*1024) # 256Mbit + spiflash_page_size = 256 + spiflash_sector_size = 0x10000 + spiflash_model = "n25q128" + + def __init__(self, toolchain="vivado", programmer="openocd"): + XilinxPlatform.__init__(self, "xc7a50t-fgg484-1", _io, _connectors, + toolchain=toolchain) + self.toolchain.bitstream_commands = \ + ["set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]"] + self.toolchain.additional_commands = \ + ["write_cfgmem -force -format bin -interface spix4 -size 16 " + "-loadbit \"up 0x0 {build_name}.bit\" -file {build_name}.bin"] + self.programmer = programmer + self.add_platform_command("set_property INTERNAL_VREF 0.750 [get_iobanks 34]") + + + def create_programmer(self): + if self.programmer == "openocd": + proxy="bscan_spi_{}.bit".format(self.device.split('-')[0]) + return OpenOCD(config="board/numato_mimas_a7.cfg", flash_proxy_basename=proxy) + elif self.programmer == "xc3sprog": + return XC3SProg("nexys4") + elif self.programmer == "vivado": + return VivadoProgrammer(flash_part="n25q128-3.3v-spi-x1_x2_x4") # FIXME: Spansion S25FL256S + else: + raise ValueError("{} programmer is not supported" + .format(self.programmer)) + + def do_finalize(self, fragment): + XilinxPlatform.do_finalize(self, fragment) + try: + self.add_period_constraint(self.lookup_request("eth_clocks").rx, 8.0) + except ConstraintError: + pass diff --git a/targets/mimas_a7/Makefile.mk b/targets/mimas_a7/Makefile.mk new file mode 100644 index 00000000..361ac922 --- /dev/null +++ b/targets/mimas_a7/Makefile.mk @@ -0,0 +1,51 @@ +# mimas_a7 targets + +ifneq ($(PLATFORM),mimas_a7) + $(error "Platform should be mimas_a7 when using this file!?") +endif + +# Settings +DEFAULT_TARGET = base +TARGET ?= $(DEFAULT_TARGET) + +PROG_PORT ?= /dev/ttyUSB1 +COMM_PORT ?= /dev/ttyUSB0 +BAUD ?= 115200 + +# Image +image-flash-$(PLATFORM): image-flash-py + @true + +# Gateware +gateware-load-$(PLATFORM): + openocd -f board/numato_$(PLATFORM).cfg -c "init; pld load 0 $(TARGET_BUILD_DIR)/gateware/top.bit; exit" + +gateware-flash-$(PLATFORM): gateware-flash-py + @true + +# Firmware +firmware-load-$(PLATFORM): + flterm --port=$(COMM_PORT) --kernel=$(FIRMWARE_FILEBASE).bin --speed=$(BAUD) + +firmware-flash-$(PLATFORM): firmwage-flash-py + @true + +firmware-connect-$(PLATFORM): + flterm --port=$(COMM_PORT) --speed=$(BAUD) + +firmware-clear-$(PLATFORM): + @echo "FIXME: Unsupported?." + @false + +# Bios +bios-flash-$(PLATFORM): + @echo "Unsupported." + @false + +# Extra commands +help-$(PLATFORM): + @true + +reset-$(PLATFORM): + @echo "Unsupported." + @false diff --git a/targets/mimas_a7/base.py b/targets/mimas_a7/base.py new file mode 100755 index 00000000..eb689b6f --- /dev/null +++ b/targets/mimas_a7/base.py @@ -0,0 +1,142 @@ +# Support for Numato Mimas A7 board +from migen import * +from migen.genlib.resetsync import AsyncResetSynchronizer + +from litex.soc.integration.soc_core import mem_decoder +from litex.soc.integration.soc_sdram import * +from litex.soc.integration.builder import * +from litex.soc.cores.uart import * + +from litedram.modules import MT41K128M16 +from litedram.phy import a7ddrphy +from litedram.core import ControllerSettings + +from gateware import info +from gateware import spi_flash + +from targets.utils import csr_map_update, period_ns + + +class _CRG(Module): + def __init__(self, platform): + self.clock_domains.cd_sys = ClockDomain() + self.clock_domains.cd_sys4x = ClockDomain(reset_less=True) + self.clock_domains.cd_sys4x_dqs = ClockDomain(reset_less=True) + self.clock_domains.cd_clk200 = ClockDomain() + self.clock_domains.cd_clk100 = ClockDomain() + + clk100 = platform.request("clk100") + rst = platform.request("cpu_reset") + + pll_locked = Signal() + pll_fb = Signal() + self.pll_sys = Signal() + pll_sys4x = Signal() + pll_sys4x_dqs = Signal() + pll_clk200 = Signal() + self.specials += [ + Instance("PLLE2_BASE", + p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked, + + # VCO @ 1600 MHz + p_REF_JITTER1=0.01, p_CLKIN1_PERIOD=10.0, + p_CLKFBOUT_MULT=16, p_DIVCLK_DIVIDE=1, + i_CLKIN1=clk100, i_CLKFBIN=pll_fb, o_CLKFBOUT=pll_fb, + + # 100 MHz + p_CLKOUT0_DIVIDE=16, p_CLKOUT0_PHASE=0.0, + o_CLKOUT0=self.pll_sys, + + # 400 MHz + p_CLKOUT1_DIVIDE=4, p_CLKOUT1_PHASE=0.0, + o_CLKOUT1=pll_sys4x, + + # 400 MHz dqs + p_CLKOUT2_DIVIDE=4, p_CLKOUT2_PHASE=90.0, + o_CLKOUT2=pll_sys4x_dqs, + + # 200 MHz + p_CLKOUT3_DIVIDE=8, p_CLKOUT3_PHASE=0.0, + o_CLKOUT3=pll_clk200 + ), + Instance("BUFG", i_I=self.pll_sys, o_O=self.cd_sys.clk), + Instance("BUFG", i_I=pll_sys4x, o_O=self.cd_sys4x.clk), + Instance("BUFG", i_I=pll_sys4x_dqs, o_O=self.cd_sys4x_dqs.clk), + Instance("BUFG", i_I=pll_clk200, o_O=self.cd_clk200.clk), + Instance("BUFG", i_I=clk100, o_O=self.cd_clk100.clk), + AsyncResetSynchronizer(self.cd_sys, ~pll_locked | rst), + AsyncResetSynchronizer(self.cd_clk200, ~pll_locked | rst), + AsyncResetSynchronizer(self.cd_clk100, ~pll_locked | rst), + ] + + reset_counter = Signal(4, reset=15) + ic_reset = Signal(reset=1) + self.sync.clk200 += \ + If(reset_counter != 0, + reset_counter.eq(reset_counter - 1) + ).Else( + ic_reset.eq(0) + ) + self.specials += Instance("IDELAYCTRL", i_REFCLK=ClockSignal("clk200"), i_RST=ic_reset) + + +class BaseSoC(SoCSDRAM): + csr_peripherals = ( + "spiflash", + "ddrphy", + "info", + ) + csr_map_update(SoCSDRAM.csr_map, csr_peripherals) + + mem_map = { + "spiflash": 0x20000000, # (default shadow @0xa0000000) + } + mem_map.update(SoCSDRAM.mem_map) + + def __init__(self, platform, spiflash="spiflash_1x", **kwargs): + clk_freq = int(100e6) + SoCSDRAM.__init__(self, platform, clk_freq, + integrated_rom_size=0x10000, + integrated_sram_size=0x10000, + **kwargs) + + self.submodules.crg = _CRG(platform) + self.crg.cd_sys.clk.attr.add("keep") + self.platform.add_period_constraint(self.crg.cd_sys.clk, period_ns(clk_freq)) + + # Basic peripherals + self.submodules.info = info.Info(platform, self.__class__.__name__) + + # sdram + self.submodules.ddrphy = a7ddrphy.A7DDRPHY(platform.request("ddram")) + sdram_module = MT41K128M16(self.clk_freq, "1:4") + self.register_sdram(self.ddrphy, + sdram_module.geom_settings, + sdram_module.timing_settings, + controller_settings=ControllerSettings( + with_bandwidth=True, + cmd_buffer_depth=8, + with_refresh=True)) + + # spi flash + spiflash_pads = platform.request(spiflash) + spiflash_pads.clk = Signal() + self.specials += Instance("STARTUPE2", + i_CLK=0, i_GSR=0, i_GTS=0, i_KEYCLEARB=0, i_PACK=0, + i_USRCCLKO=spiflash_pads.clk, i_USRCCLKTS=0, i_USRDONEO=1, i_USRDONETS=1) + spiflash_dummy = { + "spiflash_1x": 9, + "spiflash_4x": 11, + } + self.submodules.spiflash = spi_flash.SpiFlash( + spiflash_pads, + dummy=spiflash_dummy[spiflash], + div=2) + self.add_constant("SPIFLASH_PAGE_SIZE", 256) + self.add_constant("SPIFLASH_SECTOR_SIZE", 0x10000) + self.add_wb_slave(mem_decoder(self.mem_map["spiflash"]), self.spiflash.bus) + self.add_memory_region( + "spiflash", self.mem_map["spiflash"] | self.shadow_base, 16*1024*1024) + + +SoC = BaseSoC diff --git a/targets/mimas_a7/bridge_net.py b/targets/mimas_a7/bridge_net.py new file mode 100755 index 00000000..05df401c --- /dev/null +++ b/targets/mimas_a7/bridge_net.py @@ -0,0 +1,110 @@ +from migen import * +from migen.genlib.resetsync import AsyncResetSynchronizer +from litex.soc.integration.soc_core import * +from litex.soc.cores.uart import * + +from targets.utils import csr_map_update, period_ns + +from liteeth.common import convert_ip +from liteeth.phy.s7rgmii import LiteEthPHYRGMII +from liteeth.core import LiteEthUDPIPCore +from liteeth.frontend.etherbone import LiteEthEtherbone + + +class CRG(Module): + def __init__(self, platform): + self.clock_domains.cd_sys = ClockDomain() + self.clock_domains.cd_clk200 = ClockDomain() + self.clock_domains.cd_clk100 = ClockDomain() + + clk100 = platform.request("clk100") + rst = platform.request("cpu_reset") + + pll_locked = Signal() + pll_fb = Signal() + self.pll_sys = Signal() + pll_clk200 = Signal() + self.specials += [ + Instance("PLLE2_BASE", + p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked, + + # VCO @ 1400 MHz + p_REF_JITTER1=0.01, p_CLKIN1_PERIOD=10.0, + p_CLKFBOUT_MULT=14, p_DIVCLK_DIVIDE=1, + i_CLKIN1=clk100, i_CLKFBIN=pll_fb, o_CLKFBOUT=pll_fb, + + # 140 MHz + p_CLKOUT0_DIVIDE=10, p_CLKOUT0_PHASE=0.0, + o_CLKOUT0=self.pll_sys, + + # 200 MHz + p_CLKOUT1_DIVIDE=7, p_CLKOUT1_PHASE=0.0, + o_CLKOUT1=pll_clk200, + ), + Instance("BUFG", i_I=self.pll_sys, o_O=self.cd_sys.clk), + Instance("BUFG", i_I=pll_clk200, o_O=self.cd_clk200.clk), + Instance("BUFG", i_I=clk100, o_O=self.cd_clk100.clk), + AsyncResetSynchronizer(self.cd_sys, ~pll_locked | rst), + AsyncResetSynchronizer(self.cd_clk200, ~pll_locked | rst), + AsyncResetSynchronizer(self.cd_clk100, ~pll_locked | rst), + ] + + reset_counter = Signal(4, reset=15) + ic_reset = Signal(reset=1) + self.sync.clk200 += \ + If(reset_counter != 0, + reset_counter.eq(reset_counter - 1) + ).Else( + ic_reset.eq(0) + ) + self.specials += Instance("IDELAYCTRL", i_REFCLK=ClockSignal("clk200"), i_RST=ic_reset) + + +class EtherboneSoC(SoCCore): + csr_peripherals = ( + "ethphy", + "ethcore", + ) + csr_map_update(SoCCore.csr_map, csr_peripherals) + + def __init__(self, platform, cpu_type=None, mac_address=0x10e2d5000000, ip_address="192.168.100.50", **kwargs): + clk_freq = int(142e6) + SoCCore.__init__(self, platform, clk_freq, + cpu_type=None, + integrated_main_ram_size=0x8000, + integrated_rom_size=0x8000, + integrated_sram_size=0x8000, + csr_data_width=32, + with_uart=False, + **kwargs) + + self.submodules.crg = CRG(platform) + + self.crg.cd_sys.clk.attr.add("keep") + self.platform.add_period_constraint(self.crg.cd_sys.clk, period_ns(clk_freq)) + + # ethernet mac/udp/ip stack + self.submodules.ethphy = LiteEthPHYRGMII(self.platform.request("eth_clocks"), + self.platform.request("eth")) + self.submodules.ethcore = LiteEthUDPIPCore(self.ethphy, + mac_address, + convert_ip(ip_address), + self.clk_freq, + with_icmp=True) + + # etherbone bridge + self.add_cpu_or_bridge(LiteEthEtherbone(self.ethcore.udp, 1234)) + self.add_wb_master(self.cpu_or_bridge.wishbone.bus) + + self.ethphy.crg.cd_eth_rx.clk.attr.add("keep") + self.ethphy.crg.cd_eth_tx.clk.attr.add("keep") + self.platform.add_period_constraint(self.ethphy.crg.cd_eth_rx.clk, period_ns(125e6)) + self.platform.add_period_constraint(self.ethphy.crg.cd_eth_tx.clk, period_ns(125e6)) + + self.platform.add_false_path_constraints( + self.crg.cd_sys.clk, + self.ethphy.crg.cd_eth_rx.clk, + self.ethphy.crg.cd_eth_tx.clk) + + +SoC = EtherboneSoC diff --git a/targets/mimas_a7/net.py b/targets/mimas_a7/net.py new file mode 100755 index 00000000..4699d4ab --- /dev/null +++ b/targets/mimas_a7/net.py @@ -0,0 +1,66 @@ +from litex.soc.integration.soc_core import mem_decoder +from litex.soc.integration.soc_sdram import * + +from liteeth.core.mac import LiteEthMAC +from liteeth.phy.s7rgmii import LiteEthPHYRGMII + +from targets.utils import csr_map_update +from targets.mimas_a7.base import SoC as BaseSoC + + +class NetSoC(BaseSoC): + csr_peripherals = ( + "ethphy", + "ethmac", + ) + csr_map_update(BaseSoC.csr_map, csr_peripherals) + + interrupt_map = { + "ethmac": 3, + } + interrupt_map.update(BaseSoC.interrupt_map) + + mem_map = { + "ethmac": 0x30000000, # (shadow @0xb0000000) + } + mem_map.update(BaseSoC.mem_map) + + def __init__(self, platform, *args, **kwargs): + BaseSoC.__init__(self, platform, *args, **kwargs) + + self.submodules.ethphy = LiteEthPHYRGMII( + platform.request("eth_clocks"), + platform.request("eth")) + self.submodules.ethmac = LiteEthMAC( + phy=self.ethphy, dw=32, interface="wishbone") + self.add_wb_slave(mem_decoder(self.mem_map["ethmac"]), self.ethmac.bus) + self.add_memory_region("ethmac", + self.mem_map["ethmac"] | self.shadow_base, 0x2000) + + self.ethphy.crg.cd_eth_rx.clk.attr.add("keep") + self.ethphy.crg.cd_eth_tx.clk.attr.add("keep") + #self.platform.add_period_constraint(self.crg.cd_sys.clk, 10.0) + self.platform.add_period_constraint(self.ethphy.crg.cd_eth_rx.clk, 8.0) + self.platform.add_period_constraint(self.ethphy.crg.cd_eth_tx.clk, 8.0) + self.platform.add_false_path_constraints( + self.crg.cd_sys.clk, + self.ethphy.crg.cd_eth_rx.clk, + self.ethphy.crg.cd_eth_tx.clk) + + def configure_iprange(self, iprange): + iprange = [int(x) for x in iprange.split(".")] + while len(iprange) < 4: + iprange.append(0) + # Our IP address + self._configure_ip("LOCALIP", iprange[:-1]+[50]) + # IP address of tftp host + self._configure_ip("REMOTEIP", iprange[:-1]+[100]) + + def _configure_ip(self, ip_type, ip): + for i, e in enumerate(ip): + s = ip_type + str(i + 1) + s = s.upper() + self.add_constant(s, e) + + +SoC = NetSoC diff --git a/targets/mimas_a7/video.py b/targets/mimas_a7/video.py new file mode 100755 index 00000000..3dcbc6f0 --- /dev/null +++ b/targets/mimas_a7/video.py @@ -0,0 +1,145 @@ +from litevideo.input import HDMIIn +from litevideo.output import VideoOut + +from litex.soc.cores.frequency_meter import FrequencyMeter + +from litescope import LiteScopeAnalyzer + +from targets.utils import csr_map_update, period_ns +from targets.mimas_a7.net import NetSoC as BaseSoC + + +class VideoSoC(BaseSoC): + csr_peripherals = ( + "hdmi_out0", + "hdmi_in0", + "hdmi_in0_freq", + "hdmi_in0_edid_mem", + ) + csr_map_update(BaseSoC.csr_map, csr_peripherals) + + interrupt_map = { + "hdmi_in0": 4, + } + interrupt_map.update(BaseSoC.interrupt_map) + + def __init__(self, platform, *args, **kwargs): + BaseSoC.__init__(self, platform, *args, **kwargs) + + mode = "ycbcr422" + if mode == "ycbcr422": + dw = 16 + elif mode == "rgb": + dw = 32 + else: + raise SystemError("Unknown pixel mode.") + + pix_freq = 148.50e6 + + # hdmi in 0 + hdmi_in0_pads = platform.request("hdmi_in") + + self.submodules.hdmi_in0 = HDMIIn( + hdmi_in0_pads, + self.sdram.crossbar.get_port(mode="write"), + fifo_depth=512, + device="xc7") + + self.submodules.hdmi_in0_freq = FrequencyMeter(period=self.clk_freq) + + self.comb += [ + self.hdmi_in0_freq.clk.eq(self.hdmi_in0.clocking.cd_pix.clk), + ] + self.platform.add_period_constraint(self.hdmi_in0.clocking.cd_pix.clk, period_ns(1*pix_freq)) + self.platform.add_period_constraint(self.hdmi_in0.clocking.cd_pix1p25x.clk, period_ns(1.25*pix_freq)) + self.platform.add_period_constraint(self.hdmi_in0.clocking.cd_pix5x.clk, period_ns(5*pix_freq)) + + self.platform.add_false_path_constraints( + self.crg.cd_sys.clk, + self.hdmi_in0.clocking.cd_pix.clk, + self.hdmi_in0.clocking.cd_pix1p25x.clk, + self.hdmi_in0.clocking.cd_pix5x.clk) + + # hdmi out 0 + hdmi_out0_pads = platform.request("hdmi_out") + + hdmi_out0_dram_port = self.sdram.crossbar.get_port( + mode="read", + dw=dw, + cd="hdmi_out0_pix", + reverse=True) + + self.submodules.hdmi_out0 = VideoOut( + platform.device, + hdmi_out0_pads, + hdmi_out0_dram_port, + mode=mode, + fifo_depth=4096) + + self.platform.add_false_path_constraints( + self.crg.cd_sys.clk, + self.hdmi_out0.driver.clocking.cd_pix.clk) + + self.platform.add_period_constraint(self.hdmi_out0.driver.clocking.cd_pix.clk, period_ns(1*pix_freq)) + self.platform.add_period_constraint(self.hdmi_out0.driver.clocking.cd_pix5x.clk, period_ns(5*pix_freq)) + + self.platform.add_false_path_constraints( + self.crg.cd_sys.clk, + self.hdmi_out0.driver.clocking.cd_pix.clk, + self.hdmi_out0.driver.clocking.cd_pix5x.clk) + + for name, value in sorted(self.platform.hdmi_infos.items()): + self.add_constant(name, value) + + +class VideoSoCDebug(VideoSoC): + csr_peripherals = ( + "analyzer", + ) + csr_map_update(VideoSoC.csr_map, csr_peripherals) + + def __init__(self, platform, *args, **kwargs): + VideoSoC.__init__(self, platform, *args, **kwargs) + + # # # + + # analyzer + analyzer_signals = [ + self.hdmi_in0.data0_charsync.raw_data, + self.hdmi_in0.data1_charsync.raw_data, + self.hdmi_in0.data2_charsync.raw_data, + + self.hdmi_in0.data0_charsync.synced, + self.hdmi_in0.data1_charsync.synced, + self.hdmi_in0.data2_charsync.synced, + + self.hdmi_in0.data0_charsync.data, + self.hdmi_in0.data1_charsync.data, + self.hdmi_in0.data2_charsync.data, + + self.hdmi_in0.syncpol.valid_o, + self.hdmi_in0.syncpol.de, + self.hdmi_in0.syncpol.hsync, + self.hdmi_in0.syncpol.vsync, + ] + self.submodules.analyzer = LiteScopeAnalyzer(analyzer_signals, 1024, cd="hdmi_in0_pix", cd_ratio=2) + + # leds + pix_counter = Signal(32) + self.sync.hdmi_in0_pix += pix_counter.eq(pix_counter + 1) + self.comb += platform.request("user_led", 0).eq(pix_counter[26]) + + pix1p25x_counter = Signal(32) + self.sync.pix1p25x += pix1p25x_counter.eq(pix1p25x_counter + 1) + self.comb += platform.request("user_led", 1).eq(pix1p25x_counter[26]) + + pix5x_counter = Signal(32) + self.sync.hdmi_in0_pix5x += pix5x_counter.eq(pix5x_counter + 1) + self.comb += platform.request("user_led", 2).eq(pix5x_counter[26]) + + + def do_exit(self, vns): + self.analyzer.export_csv(vns, "test/analyzer.csv") + + +SoC = VideoSoC