1
0
mirror of synced 2026-01-11 23:42:59 +00:00

add preliminary support for PROM-in-flash-NOR using a custom PMod

This commit is contained in:
Romain Dolbeau 2023-02-26 13:19:09 +01:00
parent a60b731d72
commit c4717d4bd6
6 changed files with 102 additions and 45 deletions

@ -1 +1 @@
Subproject commit c708a834691efb34bbcc7d4c0022dd2f59aa7e4d
Subproject commit 1697001fb4f7d929005db86bd44a5339f750cf15

View File

@ -24,6 +24,8 @@ for V in "V1_2"; do
#echo "rom = ["
#cat /tmp/${PFX}.txt_hexa
#echo "]"
hexdump -v -e '1/4 "%08x"' -e '"\n"' ${PFX}.fc | xxd -r -p > ${PFX}_flash_little.fc
fi
done

View File

@ -25,21 +25,27 @@ ADDR_PHYS_LOW = 0
ADDR_PFX_HIGH = ADDR_PHYS_HIGH
ADDR_PFX_LOW = 16 ## 64 KiB per prefix
ADDR_PFX_LENGTH = 12 #(1 + ADDR_PFX_HIGH - ADDR_PFX_LOW)
ROM_ADDR_PFX = Signal(12, reset = 0x000) # read only
WISHBONE_CSR_ADDR_PFX = Signal(12, reset = 0x004)
USBOHCI_ADDR_PFX = Signal(12, reset = 0x008)
SRAM_ADDR_PFX = Signal(12, reset = 0x009) # unmapped ; LE
ENGINE_ADDR_PFXA = Signal(12, reset = 0x00a)
ENGINE_ADDR_PFXB = Signal(12, reset = 0x00b)
JARETH_ADDR_PFXA = Signal(12, reset = 0x00c)
JARETH_ADDR_PFXB = Signal(12, reset = 0x00d)
CG6_BT_ADDR_PFX = Signal(12, reset = 0x020)
CG6_ALT_ADDR_PFX = Signal(12, reset = 0x028)
CG6_FHC_ADDR_PFX = Signal(12, reset = 0x030)
CG3_BT_ADDR_PFX = Signal(12, reset = 0x040)
FBC_ROM_ADDR_PFX = Signal(12, reset = 0x041)
#FBC_RAM_ADDR_PFX = Signal(12, reset = 0x042)
CG6_FBC_ADDR_PFX = Signal(12, reset = 0x070)
ROM_ADDR_PFX = Signal(ADDR_PFX_LENGTH, reset = 0x000) # read only
WISHBONE_CSR_ADDR_PFX = Signal(ADDR_PFX_LENGTH, reset = 0x004) # 0x00040000
USBOHCI_ADDR_PFX = Signal(ADDR_PFX_LENGTH, reset = 0x008)
SRAM_ADDR_PFX = Signal(ADDR_PFX_LENGTH, reset = 0x009) # unmapped ; LE
ENGINE_ADDR_PFXA = Signal(ADDR_PFX_LENGTH, reset = 0x00a)
ENGINE_ADDR_PFXB = Signal(ADDR_PFX_LENGTH, reset = 0x00b)
JARETH_ADDR_PFXA = Signal(ADDR_PFX_LENGTH, reset = 0x00c)
JARETH_ADDR_PFXB = Signal(ADDR_PFX_LENGTH, reset = 0x00d)
CG6_BT_ADDR_PFX = Signal(ADDR_PFX_LENGTH, reset = 0x020)
CG6_ALT_ADDR_PFX = Signal(ADDR_PFX_LENGTH, reset = 0x028)
CG6_FHC_ADDR_PFX = Signal(ADDR_PFX_LENGTH, reset = 0x030)
CG3_BT_ADDR_PFX = Signal(ADDR_PFX_LENGTH, reset = 0x040)
FBC_ROM_ADDR_PFX = Signal(ADDR_PFX_LENGTH, reset = 0x041) # read only
#FBC_RAM_ADDR_PFX = Signal(ADDR_PFX_LENGTH, reset = 0x042) #
CG6_FBC_ADDR_PFX = Signal(ADDR_PFX_LENGTH, reset = 0x070)
ADDR_LONG_PFX_HIGH = ADDR_PHYS_HIGH
ADDR_LONG_PFX_LOW = 26 ## 64 MiB per prefix
ADDR_LONG_PFX_LENGTH = 2 #(1 + ADDR_LONG_PFX_HIGH - ADDR_LONG_PFX_LOW)
SPIFLASH_ADDR_LONG_PFX = Signal(ADDR_LONG_PFX_LENGTH, reset = 0x1) # 0x04000000
wishbone_default_timeout = 120 ##
sbus_default_timeout = 50 ## must be below 255/2 (two waits)
@ -541,6 +547,7 @@ class SBusFPGABus(Module):
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG6_ALT_ADDR_PFX) |
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG6_FHC_ADDR_PFX) |
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG3_BT_ADDR_PFX) |
(SBUS_3V3_PA_i[ADDR_LONG_PFX_LOW:ADDR_LONG_PFX_LOW+ADDR_LONG_PFX_LENGTH] == SPIFLASH_ADDR_LONG_PFX) |
(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH] == CG3_PIXELS_ADDR_BIGPFX)),
NextValue(SBUS_3V3_ACKs_o, ACK_IDLE), # need to wait for data, don't ACK yet
NextValue(SBUS_3V3_ERRs_o, 1),
@ -598,6 +605,7 @@ class SBusFPGABus(Module):
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == WISHBONE_CSR_ADDR_PFX) |
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == SRAM_ADDR_PFX) |
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG3_BT_ADDR_PFX) |
(SBUS_3V3_PA_i[ADDR_LONG_PFX_LOW:ADDR_LONG_PFX_LOW+ADDR_LONG_PFX_LENGTH] == SPIFLASH_ADDR_LONG_PFX) |
(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH] == CG3_PIXELS_ADDR_BIGPFX)),
NextValue(SBUS_3V3_ACKs_o, ACK_IDLE), # need to wait for data, don't ACK yet
NextValue(SBUS_3V3_ERRs_o, 1),
@ -663,6 +671,7 @@ class SBusFPGABus(Module):
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == SRAM_ADDR_PFX) |
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG6_FHC_ADDR_PFX) |
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG3_BT_ADDR_PFX) |
(SBUS_3V3_PA_i[ADDR_LONG_PFX_LOW:ADDR_LONG_PFX_LOW+ADDR_LONG_PFX_LENGTH] == SPIFLASH_ADDR_LONG_PFX) |
(SBUS_3V3_PA_i[ADDR_BIGPFX_LOW:ADDR_BIGPFX_LOW+ADDR_BIGPFX_LENGTH] == CG3_PIXELS_ADDR_BIGPFX)),
NextValue(SBUS_3V3_ACKs_o, ACK_IDLE), # need to wait for data, don't ACK yet
NextValue(SBUS_3V3_ERRs_o, 1),
@ -732,7 +741,6 @@ class SBusFPGABus(Module):
#NextValue(sbus_master_error_virtual, Cat(SBUS_3V3_PA_i, SBUS_3V3_SIZ_i, Signal(1, reset=0))),
NextState("Slave_Error")
).Elif(((SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == WISHBONE_CSR_ADDR_PFX) |
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == FBC_ROM_ADDR_PFX) |
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG6_FBC_ADDR_PFX) |
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == USBOHCI_ADDR_PFX) |
(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == SRAM_ADDR_PFX) |

View File

@ -212,7 +212,7 @@ class SBusFPGA(SoCCore):
#if self.irq.enabled:
#self.irq.add(name, use_loc_if_exists=True)
def __init__(self, variant, version, sys_clk_freq, trng, stat, usb, sdram, engine, i2c, bw2, cg3, cg6, goblin, cg3_res, sdcard, jareth, **kwargs):
def __init__(self, variant, version, sys_clk_freq, trng, stat, usb, sdram, engine, i2c, bw2, cg3, cg6, goblin, cg3_res, sdcard, jareth, flash, **kwargs):
framebuffer = (bw2 or cg3 or cg6 or goblin)
print(f"Building SBusFPGA for board version {version}")
@ -229,6 +229,14 @@ class SBusFPGA(SoCCore):
if (framebuffer and (version == "V1.2")):
platform.add_extension(ztex213_sbus._vga_pmod_io_v1_2)
if (i2c and (version == "V1.0")):
platform.add_extension(ztex213_sbus._tempi2c_pmod_io_v1_0)
if (i2c and (version == "V1.2")):
platform.add_extension(ztex213_sbus._tempi2c_pmod_io_v1_2)
if (flash and (version == "V1.2")):
platform.add_extension(ztex213_sbus._flashtemp_pmod_io_v1_2)
if (framebuffer):
hres = int(cg3_res.split("@")[0].split("x")[0])
@ -265,6 +273,8 @@ class SBusFPGA(SoCCore):
bus_interconnect = "crossbar",
**kwargs)
###### self.cpu.endianness = "big" # some devices use that, such as Flash & SD # should try to figure out eveything that breaks when I do that...
# *** This mem-map is also exposed in the FSM (matched prefixes) ***
# and in the PROM (to tell NetBSD where everything is)
# Currently it is a straight mapping between the two:
@ -278,6 +288,7 @@ class SBusFPGA(SoCCore):
# differently.
self.wb_mem_map = wb_mem_map = {
"prom": 0x00000000, # 256 Kib ought to be enough for anybody (we're using < 8 Kib now...)
"spiflash": 0x00000000, # FIXME currently the flash is in 0 as well, limited to 256 KiB
"csr" : 0x00040000,
"usb_host": 0x00080000, # OHCI registers are here, not in CSR
#"usb_shared_mem": 0x00090000, # unused ATM
@ -295,6 +306,7 @@ class SBusFPGA(SoCCore):
#"cg6_tec": 0x00701000, # required for compatibility
"cg3_pixels": 0x00800000, # required for compatibility, 1/2/4/8 MiB for now (up to 0x00FFFFFF inclusive) (bw2, cg3 and cg6 idem)
"goblin_pixels": 0x01000000, # base address for 16 MiB Goblin Framebuffer
# "spiflash": 0x04000000, # base address for up to 64 MiB Flash
"main_ram": 0x80000000, # not directly reachable from SBus mapping (only 0x0 - 0x10000000 is accessible),
"video_framebuffer":0x80000000 + 0x10000000 - cg3_fb_size, # Updated later
"dvma_bridge": 0xf0000000, # required to match DVMA virtual addresses
@ -348,24 +360,36 @@ class SBusFPGA(SoCCore):
#self.comb += pad_SBUS_DATA_OE_LED_2.eq(SBUS_DATA_OE_LED_2_o)
#self.comb += SBUS_DATA_OE_LED_o.eq(~SBUS_3V3_INT1s_o)
prom_file = "prom_{}.fc".format(version.replace(".", "_"))
#prom_file = "SUNW,501-2325.bin" # real TGX
#prom_file = "SUNW,501-1415.bin" # real cg3
#prom_file = "SUNW,501-2253.bin" # real TGX+
prom_data = soc_core.get_mem_data(filename_or_regions=prom_file, endianness="big")
# prom = Array(prom_data)
#print("\n****************************************\n")
#for i in range(len(prom)):
# print(hex(prom[i]))
#print("\n****************************************\n")
prom_len = 4*len(prom_data);
rounded_prom_len = 2**log2_int(prom_len, False)
print(f"ROM is {prom_len} bytes, using {rounded_prom_len}")
assert(rounded_prom_len <= 2**16)
self.add_ram("prom", origin=self.mem_map["prom"], size=rounded_prom_len, contents=prom_data, mode="r")
#getattr(self,"prom").mem.init = prom_data
#getattr(self,"prom").mem.depth = 2**15
# PROM
# in the bitstream if no Flash available
if (not flash):
prom_file = "prom_{}.fc".format(version.replace(".", "_"))
#prom_file = "SUNW,501-2325.bin" # real TGX
#prom_file = "SUNW,501-1415.bin" # real cg3
#prom_file = "SUNW,501-2253.bin" # real TGX+
prom_data = soc_core.get_mem_data(filename_or_regions=prom_file, endianness="big")
# prom = Array(prom_data)
#print("\n****************************************\n")
#for i in range(len(prom)):
# print(hex(prom[i]))
#print("\n****************************************\n")
prom_len = 4*len(prom_data);
rounded_prom_len = 2**log2_int(prom_len, False)
print(f"ROM is {prom_len} bytes, using {rounded_prom_len}")
assert(rounded_prom_len <= 2**16)
self.add_ram("prom", origin=self.mem_map["prom"], size=rounded_prom_len, contents=prom_data, mode="r")
# SPI Flash
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 = 0x00040000,
with_mmap=True, with_master=False)
# DDR3
self.submodules.ddrphy = s7ddrphy.A7DDRPHY(platform.request("ddram"),
memtype = "DDR3",
nphases = 4,
@ -596,7 +620,7 @@ def main():
parser.add_argument("--sdram", action="store_true", help="expose the sdram to the host [all]")
parser.add_argument("--usb", action="store_true", help="add a USB OHCI controller [V1.2]")
parser.add_argument("--engine", action="store_true", help="add a Engine crypto core [all]")
parser.add_argument("--i2c", action="store_true", help="add an I2C bus [V1.2+custom temp. pmod]")
parser.add_argument("--i2c", action="store_true", help="add an I2C bus [V1.2+TEMPI2C or FLASHTEMP pmod]")
parser.add_argument("--bw2", action="store_true", help="add a BW2 framebuffer [V1.2+VGA_RGB222 pmod]")
parser.add_argument("--cg3", action="store_true", help="add a CG3 framebuffer [V1.2+VGA_RGB222 pmod]")
parser.add_argument("--cg3-res", default="1152x900@76Hz", help="Specify the CG3/CG6 resolution")
@ -604,6 +628,7 @@ def main():
parser.add_argument("--goblin", action="store_true", help="add a Goblin framebuffer [V1.2+VGA_RGB222 pmod]")
parser.add_argument("--sdcard", action="store_true", help="add a sdcard controller [all]")
parser.add_argument("--jareth", action="store_true", help="add a Jareth vector core [all]")
parser.add_argument("--flash", action="store_true", help="add a Flash device [V1.2+FLASHTEMP pmod]")
builder_args(parser)
vivado_build_args(parser)
args = parser.parse_args()
@ -612,11 +637,15 @@ def main():
print(" ***** WARNING ***** : not enabling the SDRAM still adds a controller, but doesn't add the DMA engines\n")
if (args.usb and (args.version == "V1.0")):
print(" ***** WARNING ***** : USB on V1.0 is an ugly hack \n");
if (args.i2c):
print(" ***** WARNING ***** : I2C on V1.x is for testing the core \n");
if (args.i2c and (args.version == "V1.0")):
print(" ***** WARNING ***** : I2C on V1.0 is for testing the core \n");
if ((args.bw2 or args.cg3 or args.cg6 or args.goblin) and (args.version == "V1.0")):
print(" ***** ERROR ***** : VGA 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)
fbcount = 0
if (args.bw2):
fbcount = fbcount + 1
@ -648,7 +677,8 @@ def main():
goblin=args.goblin,
cg3_res=args.cg3_res,
sdcard=args.sdcard,
jareth=args.jareth)
jareth=args.jareth,
flash=args.flash)
#soc.add_uart(name="uart", baudrate=115200, fifo_depth=16)
version_for_filename = args.version.replace(".", "_")

View File

@ -115,16 +115,16 @@
: dphy_rst_wr ( value -- )
ddrphy-virt h# 0000 + l!
;
: dphy_half_sys8x_taps_wr ( value -- )
: dphy_dly_sel_wr ( value -- )
ddrphy-virt h# 0004 + l!
;
: dphy_wlevel_en_wr ( value -- )
: dphy_half_sys8x_taps_wr ( value -- )
ddrphy-virt h# 0008 + l!
;
: dphy_wlevel_strobe_wr ( value -- )
: dphy_wlevel_en_wr ( value -- )
ddrphy-virt h# 000c + l!
;
: dphy_dly_sel_wr ( value -- )
: dphy_wlevel_strobe_wr ( value -- )
ddrphy-virt h# 0010 + l!
;
: dphy_rdly_dq_rst_wr ( value -- )
@ -151,6 +151,8 @@
: dphy_wrphase_wr ( value -- )
ddrphy-virt h# 0030 + l!
;
: sdr_dfii_control_wr ( value -- )
sdram-virt h# 0000 + l!
;

View File

@ -183,7 +183,8 @@ _usb_io_v1_0 = [
_connectors_v1_0 = [
]
_connectors_v1_2 = [
("P1", "T8 P3 T1 R1 U6 P4 U4 T3"), # swapped line?
("P1", "T8 P3 T1 R1 U6 P4 U4 T3"), # swapped line? & columns?
# PMOD- 11 9 7 5 12 10 8 6
]
# I2C ----------------------------------------------------------------------------------------------
@ -213,6 +214,17 @@ def tempi2c_pmod_io(pmod):
]
_tempi2c_pmod_io_v1_2 = tempi2c_pmod_io("P1")
def flashtemp_pmod_io(pmod):
return [
("spiflash4x", 0,
Subsignal("cs_n", Pins(f"{pmod}:2")),
Subsignal("clk", Pins(f"{pmod}:5")),
Subsignal("dq", Pins(f"{pmod}:4 {pmod}:1 {pmod}:0 {pmod}:6")),
IOStandard("LVCMOS33")
),
]
_flashtemp_pmod_io_v1_2 = flashtemp_pmod_io("P1")
# VGA ----------------------------------------------------------------------------------------------
def vga_rgb222_pmod_io(pmod):
@ -284,6 +296,10 @@ class Platform(XilinxPlatform):
"V1.0" : _i2c_v1_0,
"V1.2" : _tempi2c_pmod_io_v1_2,
}[version]
flashrom = {
"V1.0": None,
"V1.2": _flashtemp_pmod_io_v1_2,
}
self.avail_irqs = {
"V1.0" : { 1 }, # don't add 7 here, too risky
"V1.2" : { 1, 2, 3, 4, 5, 6 },
@ -297,7 +313,6 @@ class Platform(XilinxPlatform):
XilinxPlatform.__init__(self, device, _io, connectors, toolchain="vivado")
self.add_extension(sbus_io)
self.add_extension(sbus_sbus)
self.add_extension(i2c)
self.toolchain.opt_directive = "Explore"
#self.toolchain.vivado_place_directive = "Explore"