mirror of
https://github.com/rdolbeau/NuBusFPGA.git
synced 2024-09-27 11:55:41 +00:00
add micro-sd HW support
This commit is contained in:
parent
77852b8d40
commit
f9886f7280
@ -2,7 +2,7 @@
|
|||||||
source /opt/Xilinx/Vivado/2020.1/settings64.sh
|
source /opt/Xilinx/Vivado/2020.1/settings64.sh
|
||||||
export LD_LIBRARY_PATH=/opt/Xilinx/Vivado/2020.1/lib/lnx64.o/SuSE
|
export LD_LIBRARY_PATH=/opt/Xilinx/Vivado/2020.1/lib/lnx64.o/SuSE
|
||||||
|
|
||||||
python3 nubus_to_fpga_soc.py --build --csr-csv csr.csv --csr-json csr.json --variant=ztex2.13a --version=V1.2 --sys-clk-freq 100e6 --goblin --goblin-res 1920x1080@60Hz --hdmi # --ethernet
|
python3 nubus_to_fpga_soc.py --build --csr-csv csr.csv --csr-json csr.json --variant=ztex2.13a --version=V1.2 --sys-clk-freq 100e6 --goblin --goblin-res 1920x1080@60Hz --hdmi --sdcard --flash # --ethernet
|
||||||
|
|
||||||
#python3 nubus_to_fpga_soc.py --csr-csv csr.csv --csr-json csr.json --variant=ztex2.13a --version=V1.2 --sys-clk-freq 100e6
|
#python3 nubus_to_fpga_soc.py --csr-csv csr.csv --csr-json csr.json --variant=ztex2.13a --version=V1.2 --sys-clk-freq 100e6
|
||||||
|
|
||||||
@ -11,3 +11,15 @@ python3 nubus_to_fpga_soc.py --build --csr-csv csr.csv --csr-json csr.json --var
|
|||||||
# --hdmi
|
# --hdmi
|
||||||
|
|
||||||
grep -A10 'Design Timing Summary' build/ztex213_nubus_V1_2/gateware/ztex213_nubus_V1_2_timing.rpt
|
grep -A10 'Design Timing Summary' build/ztex213_nubus_V1_2/gateware/ztex213_nubus_V1_2_timing.rpt
|
||||||
|
|
||||||
|
|
||||||
|
###
|
||||||
|
# For 16 MiB Flash NOR (W25Q128.V):
|
||||||
|
# truncate -s $((16*1024*1024)) vid_decl_rom.bin
|
||||||
|
# flashrom -c W25Q128.V -p linux_spi:dev=/dev/spidev0.0,spispeed=2000 -l nubus_prom.layout -i ROM -w vid_decl_rom.bin
|
||||||
|
#
|
||||||
|
# where nubus_prom.layout contains:
|
||||||
|
###
|
||||||
|
# 00000000:00007fff ROM
|
||||||
|
# 00008000:00ffffff VDISK
|
||||||
|
###
|
||||||
|
@ -37,6 +37,7 @@ from VintageBusFPGA_Common.goblin_accel import *
|
|||||||
# Wishbone stuff
|
# Wishbone stuff
|
||||||
from VintageBusFPGA_Common.cdc_wb import WishboneDomainCrossingMaster
|
from VintageBusFPGA_Common.cdc_wb import WishboneDomainCrossingMaster
|
||||||
from VintageBusFPGA_Common.fpga_blk_dma import *
|
from VintageBusFPGA_Common.fpga_blk_dma import *
|
||||||
|
from VintageBusFPGA_Common.fpga_sd_dma import *
|
||||||
|
|
||||||
from nubus_mem_wb import NuBus2Wishbone
|
from nubus_mem_wb import NuBus2Wishbone
|
||||||
from nubus_memfifo_wb import NuBus2WishboneFIFO
|
from nubus_memfifo_wb import NuBus2WishboneFIFO
|
||||||
@ -181,8 +182,26 @@ class _CRG(Module):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
class NuBusFPGA(SoCCore):
|
class NuBusFPGA(SoCCore): # Add SDCard -----------------------------------------------------------------------------------
|
||||||
def __init__(self, variant, version, sys_clk_freq, goblin, hdmi, goblin_res, ethernet, **kwargs):
|
# WiP
|
||||||
|
def add_sdcard_custom(self, name="sdcard", mode="read+write"):
|
||||||
|
# Imports.
|
||||||
|
from litesdcard.phy import SDPHY
|
||||||
|
from litesdcard.core import SDCore
|
||||||
|
|
||||||
|
# Checks.
|
||||||
|
assert mode in ["read", "write", "read+write"]
|
||||||
|
|
||||||
|
# Pads.
|
||||||
|
sdcard_pads = self.platform.request(name)
|
||||||
|
|
||||||
|
# Core.
|
||||||
|
self.check_if_exists("sdphy")
|
||||||
|
self.check_if_exists("sdcore")
|
||||||
|
self.sdphy = SDPHY(sdcard_pads, self.platform.device, self.clk_freq, cmd_timeout=10e-1, data_timeout=10e-1)
|
||||||
|
self.sdcore = SDCore(self.sdphy)
|
||||||
|
|
||||||
|
def __init__(self, variant, version, sys_clk_freq, goblin, hdmi, goblin_res, sdcard, flash, ethernet, **kwargs):
|
||||||
print(f"Building NuBusFPGA for board version {version}")
|
print(f"Building NuBusFPGA for board version {version}")
|
||||||
|
|
||||||
kwargs["cpu_type"] = "None"
|
kwargs["cpu_type"] = "None"
|
||||||
@ -193,6 +212,9 @@ class NuBusFPGA(SoCCore):
|
|||||||
self.sys_clk_freq = sys_clk_freq
|
self.sys_clk_freq = sys_clk_freq
|
||||||
|
|
||||||
self.platform = platform = ztex213_nubus.Platform(variant = variant, version = version)
|
self.platform = platform = ztex213_nubus.Platform(variant = variant, version = version)
|
||||||
|
|
||||||
|
if (flash and (version == "V1.2")):
|
||||||
|
platform.add_extension(ztex213_nubus._flashtemp_pmod_io_v1_2)
|
||||||
|
|
||||||
if (ethernet and (version == "V1.2")):
|
if (ethernet and (version == "V1.2")):
|
||||||
platform.add_extension(ztex213_nubus._rmii_eth_extpmod_io_v1_2)
|
platform.add_extension(ztex213_nubus._rmii_eth_extpmod_io_v1_2)
|
||||||
@ -253,7 +275,9 @@ class NuBusFPGA(SoCCore):
|
|||||||
"csr" : 0xF0A00000, # CSR
|
"csr" : 0xF0A00000, # CSR
|
||||||
"pingmaster": 0xF0B00000,
|
"pingmaster": 0xF0B00000,
|
||||||
"ethmac": 0xF0C00000,
|
"ethmac": 0xF0C00000,
|
||||||
|
#"spiflash": 0xF0D00000, # testing
|
||||||
"rom": 0xF0FF8000, # ROM at the end (32 KiB of it ATM)
|
"rom": 0xF0FF8000, # ROM at the end (32 KiB of it ATM)
|
||||||
|
"spiflash": 0xF0FF8000, # FIXME currently the flash is in the ROM spot, limited to 32 KiB
|
||||||
#"END OF SLOT SPACE": 0xF0FFFFFF,
|
#"END OF SLOT SPACE": 0xF0FFFFFF,
|
||||||
}
|
}
|
||||||
self.mem_map.update(wb_mem_map)
|
self.mem_map.update(wb_mem_map)
|
||||||
@ -263,6 +287,8 @@ class NuBusFPGA(SoCCore):
|
|||||||
xdc_timings_filename = None;
|
xdc_timings_filename = None;
|
||||||
#if (version == "V1.0"):
|
#if (version == "V1.0"):
|
||||||
# xdc_timings_filename = "/home/dolbeau/nubus-to-ztex-gateware/nubus_fpga_V1_0_timings.xdc"
|
# xdc_timings_filename = "/home/dolbeau/nubus-to-ztex-gateware/nubus_fpga_V1_0_timings.xdc"
|
||||||
|
if (version == "V1.2"):
|
||||||
|
xdc_timings_filename = "nubus_fpga_V1_2_timings.xdc"
|
||||||
|
|
||||||
if (xdc_timings_filename != None):
|
if (xdc_timings_filename != None):
|
||||||
xdc_timings_file = open(xdc_timings_filename)
|
xdc_timings_file = open(xdc_timings_filename)
|
||||||
@ -274,14 +300,25 @@ class NuBusFPGA(SoCCore):
|
|||||||
#print(fix_line)
|
#print(fix_line)
|
||||||
platform.add_platform_command(fix_line)
|
platform.add_platform_command(fix_line)
|
||||||
|
|
||||||
rom_file = "rom_{}.bin".format(version.replace(".", "_"))
|
if (not flash):
|
||||||
rom_data = soc_core.get_mem_data(filename_or_regions=rom_file, endianness="little") # "big"
|
rom_file = "rom_{}.bin".format(version.replace(".", "_"))
|
||||||
# rom = Array(rom_data)
|
rom_data = soc_core.get_mem_data(filename_or_regions=rom_file, endianness="little") # "big"
|
||||||
#print("\n****************************************\n")
|
# rom = Array(rom_data)
|
||||||
#for i in range(len(rom)):
|
#print("\n****************************************\n")
|
||||||
# print(hex(rom[i]))
|
#for i in range(len(rom)):
|
||||||
#print("\n****************************************\n")
|
# print(hex(rom[i]))
|
||||||
self.add_ram("rom", origin=self.mem_map["rom"], size=2**15, contents=rom_data, mode="r") ## 32 KiB, must match mmap
|
#print("\n****************************************\n")
|
||||||
|
self.add_ram("rom", origin=self.mem_map["rom"], size=2**15, contents=rom_data, mode="r") ## 32 KiB, must match mmap
|
||||||
|
|
||||||
|
if (flash):
|
||||||
|
from litespi.modules.generated_modules import W25Q128JV
|
||||||
|
from litespi.opcodes import SpiNorFlashOpCodes as Codes
|
||||||
|
self.add_spi_flash(mode="4x",
|
||||||
|
clk_freq = sys_clk_freq/4, # Fixme; PHY freq ?
|
||||||
|
module=W25Q128JV(Codes.READ_1_1_4),
|
||||||
|
region_size = 0x00008000, # 32 KiB
|
||||||
|
with_mmap=True, with_master=False)
|
||||||
|
|
||||||
|
|
||||||
#from wb_test import WA2D
|
#from wb_test import WA2D
|
||||||
#self.submodules.wa2d = WA2D(self.platform)
|
#self.submodules.wa2d = WA2D(self.platform)
|
||||||
@ -379,15 +416,18 @@ class NuBusFPGA(SoCCore):
|
|||||||
self.comb += irq_line.eq(fb_irq) # active low, enable if one is low
|
self.comb += irq_line.eq(fb_irq) # active low, enable if one is low
|
||||||
else:
|
else:
|
||||||
# details for usesampling in the NuBus python object
|
# details for usesampling in the NuBus python object
|
||||||
usesampling = True
|
usesampling = False
|
||||||
wishbone_master_sys = wishbone.Interface(data_width=self.bus.data_width)
|
wishbone_master_sys = wishbone.Interface(data_width=self.bus.data_width)
|
||||||
if (not usesampling): # we need an extra CDC
|
if (not usesampling): # we need an extra CDC
|
||||||
self.submodules.wishbone_master_nubus = WishboneDomainCrossingMaster(platform=self.platform, slave=wishbone_master_sys, cd_master="nubus", cd_slave="sys") # for non-sampling only
|
self.submodules.wishbone_master_nubus = WishboneDomainCrossingMaster(platform=self.platform, slave=wishbone_master_sys, cd_master="nubus", cd_slave="sys") # for non-sampling only
|
||||||
nubus_writemaster_sys = wishbone.Interface(data_width=self.bus.data_width)
|
nubus_writemaster_sys = wishbone.Interface(data_width=self.bus.data_width)
|
||||||
wishbone_slave_nubus = wishbone.Interface(data_width=self.bus.data_width)
|
wishbone_slave_nubus = wishbone.Interface(data_width=self.bus.data_width)
|
||||||
self.submodules.wishbone_slave_sys = WishboneDomainCrossingMaster(platform=self.platform, slave=wishbone_slave_nubus, cd_master="sys", cd_slave="nubus", force_delay=6) # force delay needed to avoid back-to-back transaction running into issue https://github.com/alexforencich/verilog-wishbone/issues/4
|
self.submodules.wishbone_slave_sys = WishboneDomainCrossingMaster(platform=self.platform, slave=wishbone_slave_nubus, cd_master="sys", cd_slave="nubus", force_delay=9) # force delay needed to avoid back-to-back transaction running into issue https://github.com/alexforencich/verilog-wishbone/issues/4
|
||||||
|
#led0 = platform.request("user_led", 0)
|
||||||
|
#led1 = platform.request("user_led", 1)
|
||||||
|
#self.comb += [ led0.eq(self.wishbone_slave_sys.stb),
|
||||||
|
# led1.eq(self.wishbone_slave_sys.cyc), ]
|
||||||
|
|
||||||
burst_size=4
|
burst_size=4
|
||||||
|
|
||||||
data_width = burst_size * 4
|
data_width = burst_size * 4
|
||||||
@ -407,9 +447,7 @@ class NuBusFPGA(SoCCore):
|
|||||||
("dmaaddress", 32),
|
("dmaaddress", 32),
|
||||||
]
|
]
|
||||||
|
|
||||||
self.submodules.tosbus_fifo = ClockDomainsRenamer({"read": "nubus", "write": "sys"})(AsyncFIFOBuffered(width=layout_len(self.tosbus_layout), depth=1024//data_width))
|
|
||||||
self.submodules.fromsbus_fifo = ClockDomainsRenamer({"write": "nubus", "read": "sys"})(AsyncFIFOBuffered(width=layout_len(self.fromsbus_layout), depth=512//data_width))
|
|
||||||
self.submodules.fromsbus_req_fifo = ClockDomainsRenamer({"read": "nubus", "write": "sys"})(AsyncFIFOBuffered(width=layout_len(self.fromsbus_req_layout), depth=512//data_width))
|
|
||||||
irq_line = self.platform.request("nmrq_3v3_n") # active low
|
irq_line = self.platform.request("nmrq_3v3_n") # active low
|
||||||
fb_irq = Signal(reset = 1) # active low
|
fb_irq = Signal(reset = 1) # active low
|
||||||
dma_irq = Signal(reset = 1) # active low
|
dma_irq = Signal(reset = 1) # active low
|
||||||
@ -422,7 +460,13 @@ class NuBusFPGA(SoCCore):
|
|||||||
#]
|
#]
|
||||||
|
|
||||||
self.comb += irq_line.eq(fb_irq & dma_irq & audio_irq) # active low, enable if one is low
|
self.comb += irq_line.eq(fb_irq & dma_irq & audio_irq) # active low, enable if one is low
|
||||||
|
|
||||||
|
|
||||||
|
self.submodules.tosbus_fifo = ClockDomainsRenamer({"read": "nubus", "write": "sys"})(AsyncFIFOBuffered(width=layout_len(self.tosbus_layout), depth=1024//data_width))
|
||||||
|
self.submodules.fromsbus_fifo = ClockDomainsRenamer({"write": "nubus", "read": "sys"})(AsyncFIFOBuffered(width=layout_len(self.fromsbus_layout), depth=512//data_width))
|
||||||
|
self.submodules.fromsbus_req_fifo = ClockDomainsRenamer({"read": "nubus", "write": "sys"})(AsyncFIFOBuffered(width=layout_len(self.fromsbus_req_layout), depth=512//data_width))
|
||||||
|
|
||||||
|
#if (not sdcard): # fixme: temporay exclusion
|
||||||
self.submodules.exchange_with_mem = ExchangeWithMem(soc=self,
|
self.submodules.exchange_with_mem = ExchangeWithMem(soc=self,
|
||||||
platform=platform,
|
platform=platform,
|
||||||
tosbus_fifo=self.tosbus_fifo,
|
tosbus_fifo=self.tosbus_fifo,
|
||||||
@ -434,8 +478,20 @@ class NuBusFPGA(SoCCore):
|
|||||||
burst_size=burst_size,
|
burst_size=burst_size,
|
||||||
do_checksum = False,
|
do_checksum = False,
|
||||||
clock_domain="nubus")
|
clock_domain="nubus")
|
||||||
|
|
||||||
self.comb += dma_irq.eq(self.exchange_with_mem.irq)
|
self.comb += dma_irq.eq(self.exchange_with_mem.irq)
|
||||||
|
#else:
|
||||||
|
# self.add_sdcard_custom()
|
||||||
|
# self.submodules.exchange_with_sd = ExchangeWithSD(soc=self,
|
||||||
|
# platform=platform,
|
||||||
|
# tosbus_fifo=self.tosbus_fifo,
|
||||||
|
# fromsbus_fifo=self.fromsbus_fifo,
|
||||||
|
# fromsbus_req_fifo=self.fromsbus_req_fifo,
|
||||||
|
# sd_source=self.sdcore.source,
|
||||||
|
# sd_sink=self.sdcore.sink,
|
||||||
|
# burst_size=burst_size,
|
||||||
|
# clock_domain="nubus")
|
||||||
|
# self.comb += dma_irq.eq(self.exchange_with_sd.irq)
|
||||||
|
|
||||||
|
|
||||||
self.submodules.nubus = nubus_full_unified.NuBus(soc=self,
|
self.submodules.nubus = nubus_full_unified.NuBus(soc=self,
|
||||||
version=version,
|
version=version,
|
||||||
@ -491,13 +547,17 @@ class NuBusFPGA(SoCCore):
|
|||||||
self.add_ram("goblin_accel_rom", origin=self.mem_map["goblin_accel_rom"], size=rounded_goblin_rom_len, contents=goblin_rom_data, mode="r")
|
self.add_ram("goblin_accel_rom", origin=self.mem_map["goblin_accel_rom"], size=rounded_goblin_rom_len, contents=goblin_rom_data, mode="r")
|
||||||
self.add_ram("goblin_accel_ram", origin=self.mem_map["goblin_accel_ram"], size=2**12, mode="rw")
|
self.add_ram("goblin_accel_ram", origin=self.mem_map["goblin_accel_ram"], size=2**12, mode="rw")
|
||||||
|
|
||||||
if (ethernet):
|
if (sdcard):
|
||||||
# we need the CRG to provide the cd_eth clock: "use refclk_cd as RMII reference clock (provided by user design) (no external clock).
|
self.add_sdcard()
|
||||||
self.ethphy = LiteEthPHYRMII(
|
# irq?
|
||||||
clock_pads = self.platform.request("eth_clocks"),
|
|
||||||
pads = self.platform.request("eth"))
|
if (ethernet):
|
||||||
self.add_ethernet(phy=self.ethphy, data_width = 32)
|
# we need the CRG to provide the cd_eth clock: "use refclk_cd as RMII reference clock (provided by user design) (no external clock).
|
||||||
print(f"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% {self.ethmac.interface.sram.ev.irq}") # FIXME HANDLEME
|
self.ethphy = LiteEthPHYRMII(
|
||||||
|
clock_pads = self.platform.request("eth_clocks"),
|
||||||
|
pads = self.platform.request("eth"))
|
||||||
|
self.add_ethernet(phy=self.ethphy, data_width = 32)
|
||||||
|
print(f"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% {self.ethmac.interface.sram.ev.irq}") # FIXME HANDLEME
|
||||||
|
|
||||||
# for testing
|
# for testing
|
||||||
if (False):
|
if (False):
|
||||||
@ -515,14 +575,28 @@ def main():
|
|||||||
parser.add_argument("--goblin", action="store_true", help="add a goblin framebuffer")
|
parser.add_argument("--goblin", action="store_true", help="add a goblin framebuffer")
|
||||||
parser.add_argument("--hdmi", action="store_true", help="The framebuffer uses HDMI (default to VGA, required for V1.2)")
|
parser.add_argument("--hdmi", action="store_true", help="The framebuffer uses HDMI (default to VGA, required for V1.2)")
|
||||||
parser.add_argument("--goblin-res", default="640x480@60Hz", help="Specify the goblin resolution")
|
parser.add_argument("--goblin-res", default="640x480@60Hz", help="Specify the goblin resolution")
|
||||||
|
parser.add_argument("--sdcard", action="store_true", help="add a sdcard controller (V1.2 only)")
|
||||||
|
parser.add_argument("--flash", action="store_true", help="add a Flash device [V1.2+FLASHTEMP PMod]")
|
||||||
parser.add_argument("--ethernet", action="store_true", help="Add Ethernet (V1.2 w/ custom PMod only)")
|
parser.add_argument("--ethernet", action="store_true", help="Add Ethernet (V1.2 w/ custom PMod only)")
|
||||||
builder_args(parser)
|
builder_args(parser)
|
||||||
vivado_build_args(parser)
|
vivado_build_args(parser)
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if (args.sdcard and (args.version == "V1.0")):
|
||||||
|
print(" ***** ERROR ***** : Ethernet not supported on V1.0\n");
|
||||||
|
assert(False)
|
||||||
|
|
||||||
|
if (args.flash and (args.version == "V1.0")):
|
||||||
|
print(" ***** ERROR ***** : Flash not supported on V1.0\n");
|
||||||
|
assert(False)
|
||||||
|
|
||||||
if (args.ethernet and (args.version == "V1.0")):
|
if (args.ethernet and (args.version == "V1.0")):
|
||||||
print(" ***** ERROR ***** : Ethernet not supported on V1.0\n");
|
print(" ***** ERROR ***** : Ethernet not supported on V1.0\n");
|
||||||
assert(False)
|
assert(False)
|
||||||
|
|
||||||
|
if (args.ethernet and args.flash):
|
||||||
|
print(" ***** ERROR ***** : Only one PMod usable on V1.2\n");
|
||||||
|
assert(False)
|
||||||
|
|
||||||
if ((not args.hdmi) and (args.version == "V1.2")):
|
if ((not args.hdmi) and (args.version == "V1.2")):
|
||||||
print(" ***** ERROR ***** : VGA not supported on V1.2\n");
|
print(" ***** ERROR ***** : VGA not supported on V1.2\n");
|
||||||
@ -535,6 +609,8 @@ def main():
|
|||||||
goblin=args.goblin,
|
goblin=args.goblin,
|
||||||
hdmi=args.hdmi,
|
hdmi=args.hdmi,
|
||||||
goblin_res=args.goblin_res,
|
goblin_res=args.goblin_res,
|
||||||
|
sdcard=args.sdcard,
|
||||||
|
flash=args.flash,
|
||||||
ethernet=args.ethernet)
|
ethernet=args.ethernet)
|
||||||
|
|
||||||
version_for_filename = args.version.replace(".", "_")
|
version_for_filename = args.version.replace(".", "_")
|
||||||
|
@ -214,17 +214,30 @@ connectors_v1_2 = [
|
|||||||
("P1", "M1 L1 N2 N1 R2 P2 T1 R1 P4 P3 P5 N5"), # check sequence! currently in pmod-* order
|
("P1", "M1 L1 N2 N1 R2 P2 T1 R1 P4 P3 P5 N5"), # check sequence! currently in pmod-* order
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# Extension
|
||||||
|
def flashtemp_pmod_io(pmod):
|
||||||
|
return [
|
||||||
|
# completely inconsistent with the SBus entry as P1 is in a different order...
|
||||||
|
("spiflash4x", 0,
|
||||||
|
Subsignal("cs_n", Pins(f"{pmod}:2")),
|
||||||
|
Subsignal("clk", Pins(f"{pmod}:5")),
|
||||||
|
Subsignal("dq", Pins(f"{pmod}:7 {pmod}:4 {pmod}:6 {pmod}:3")),
|
||||||
|
IOStandard("LVCMOS33")
|
||||||
|
),
|
||||||
|
]
|
||||||
|
_flashtemp_pmod_io_v1_2 = flashtemp_pmod_io("P1")
|
||||||
|
|
||||||
# Ethernet ----------------------------------------------------------------------------------------------
|
# Ethernet ----------------------------------------------------------------------------------------------
|
||||||
# custom not-quite-pmod
|
# custom not-quite-pmod
|
||||||
def rmii_eth_extpmod_io(extpmod):
|
def rmii_eth_extpmod_io(extpmod):
|
||||||
return [
|
return [
|
||||||
("eth_clocks", 0,
|
("eth_clocks", 0,
|
||||||
Subsignal("ref_clk", Pins(f"{extpmod}:10")),
|
Subsignal("ref_clk", Pins(f"{extpmod}:8")),
|
||||||
IOStandard("LVCMOS33"),
|
IOStandard("LVCMOS33"),
|
||||||
),
|
),
|
||||||
("eth", 0,
|
("eth", 0,
|
||||||
Subsignal("rst_n", Pins(f"{extpmod}:3")),
|
Subsignal("rst_n", Pins(f"{extpmod}:3")),
|
||||||
Subsignal("rx_data", Pins(f"{extpmod}:8 {extpmod}:11")),
|
Subsignal("rx_data", Pins(f"{extpmod}:11 {extpmod}:10")),
|
||||||
Subsignal("crs_dv", Pins(f"{extpmod}:6")),
|
Subsignal("crs_dv", Pins(f"{extpmod}:6")),
|
||||||
Subsignal("tx_en", Pins(f"{extpmod}:2")),
|
Subsignal("tx_en", Pins(f"{extpmod}:2")),
|
||||||
Subsignal("tx_data", Pins(f"{extpmod}:0 {extpmod}:1")),
|
Subsignal("tx_data", Pins(f"{extpmod}:0 {extpmod}:1")),
|
||||||
|
Loading…
Reference in New Issue
Block a user