From ba734f0fa9f12c5a14d196c37ed23a8e42b58979 Mon Sep 17 00:00:00 2001 From: Romain Dolbeau Date: Tue, 21 Sep 2021 14:12:17 -0400 Subject: [PATCH] more ocnfigurability --- .../sbus_to_fpga_blk_dma.py | 7 +- .../sbus_to_fpga_fsm.py | 174 ++++++++++++++---- .../sbus_to_fpga_prom.py | 9 +- .../sbus_to_fpga_soc.py | 66 +++++-- 4 files changed, 196 insertions(+), 60 deletions(-) diff --git a/sbus-to-ztex-gateware-migen/sbus_to_fpga_blk_dma.py b/sbus-to-ztex-gateware-migen/sbus_to_fpga_blk_dma.py index af0fe63..5cba651 100644 --- a/sbus-to-ztex-gateware-migen/sbus_to_fpga_blk_dma.py +++ b/sbus-to-ztex-gateware-migen/sbus_to_fpga_blk_dma.py @@ -9,8 +9,9 @@ from litex.soc.interconnect import wishbone # width of fromsbus_req_fifo is 'blk_addr_width' + 'vaddr' (blk_addr + vaddr) # width of fromsbus_fifo is 'blk_addr_width' + 'burst_size * 32' (blk_addr + data) # the blk_addr does the round-trip to accompany the data +# mem_size in MiB, might be weird if some space is reserved for other use (e.g. FrameBuffer) class ExchangeWithMem(Module, AutoCSR): - def __init__(self, soc, tosbus_fifo, fromsbus_fifo, fromsbus_req_fifo, dram_dma_writer, dram_dma_reader, burst_size = 8, do_checksum = False): + def __init__(self, soc, tosbus_fifo, fromsbus_fifo, fromsbus_req_fifo, dram_dma_writer, dram_dma_reader, mem_size=256, burst_size = 8, do_checksum = False): #self.wishbone_r_slave = wishbone.Interface(data_width=soc.bus.data_width) #self.wishbone_w_slave = wishbone.Interface(data_width=soc.bus.data_width) self.tosbus_fifo = tosbus_fifo @@ -19,6 +20,8 @@ class ExchangeWithMem(Module, AutoCSR): self.dram_dma_writer = dram_dma_writer self.dram_dma_reader = dram_dma_reader + print(f"Configuring the SDRAM for {mem_size} MiB\n") + data_width = burst_size * 4 data_width_bits = burst_size * 32 blk_addr_width = 32 - log2_int(data_width) # 27 for burst_size == 8 @@ -55,7 +58,7 @@ class ExchangeWithMem(Module, AutoCSR): self.mem_size = CSRStatus(32) # report how much memory we have self.comb += self.blk_size.status.eq(data_width) self.comb += self.blk_base.status.eq(soc.wb_mem_map["main_ram"] >> log2_int(data_width)) - self.comb += self.mem_size.status.eq((256 * 1024 * 1024) >> log2_int(data_width)) # is it already available from mem_regions ? + self.comb += self.mem_size.status.eq((mem_size * 1024 * 1024) >> log2_int(data_width)) self.blk_addr = CSRStorage(32, description = "SDRAM Block address to read/write from Wishbone memory (block of size {})".format(data_width)) self.dma_addr = CSRStorage(32, description = "Host Base address where to write/read data (i.e. SPARC Virtual addr)") diff --git a/sbus-to-ztex-gateware-migen/sbus_to_fpga_fsm.py b/sbus-to-ztex-gateware-migen/sbus_to_fpga_fsm.py index 32965a1..eb42ca5 100644 --- a/sbus-to-ztex-gateware-migen/sbus_to_fpga_fsm.py +++ b/sbus-to-ztex-gateware-migen/sbus_to_fpga_fsm.py @@ -25,13 +25,14 @@ 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) -WISHBONE_CSR_ADDR_PFX = Signal(12, reset = 0x004) -USBOHCI_ADDR_PFX = Signal(12, reset = 0x008) -SRAM_ADDR_PFX = Signal(12, reset = 0x009) -ENGINE_ADDR_PFXA = Signal(12, reset = 0x00a) -ENGINE_ADDR_PFXB = Signal(12, reset = 0x00b) -#SDRAM_ADDR_PFX = Signal(12, reset = 2048) +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 +ENGINE_ADDR_PFXA = Signal(12, reset = 0x00a) +ENGINE_ADDR_PFXB = Signal(12, reset = 0x00b) +CG3_REGISTERS_ADDR_PFX = Signal(12, reset = 0x040) +CG3_PIXELS_ADDR_PFX = Signal(12, reset = 0x080) wishbone_default_timeout = 120 ## sbus_default_timeout = 50 ## must be below 255 @@ -175,7 +176,7 @@ LED_M_READ = 0x20 LED_M_CACHE = 0x40 class SBusFPGABus(Module): - def __init__(self, platform, hold_reset, wishbone_slave, wishbone_master, tosbus_fifo, fromsbus_fifo, fromsbus_req_fifo, version, burst_size = 8): + def __init__(self, platform, hold_reset, wishbone_slave, wishbone_master, tosbus_fifo, fromsbus_fifo, fromsbus_req_fifo, version, burst_size = 8, cg3_fb_size = 0 ): self.platform = platform self.hold_reset = hold_reset @@ -185,6 +186,20 @@ class SBusFPGABus(Module): self.tosbus_fifo = tosbus_fifo self.fromsbus_fifo = fromsbus_fifo self.fromsbus_req_fifo = fromsbus_req_fifo + + if (cg3_fb_size <= 1048576): #round up to 1 MiB + CG3_REMAPPED_BASE=0x8FF + CG3_UPPER_BITS=12 + CG3_KEPT_UPPER_BIT=20 + elif (cg3_fb_size == (2*1048576)): + CG3_REMAPPED_BASE=0x47F + CG3_UPPER_BITS=11 + CG3_KEPT_UPPER_BIT=21 + else: + print(f"CG3 configuration ({cg3_fb_size//1048576} MiB) not yet supported\n") + assert(False) + + print(f"CG3 remapping: {cg3_fb_size//1048576} Mib starting at prefix {CG3_REMAPPED_BASE:x}") data_width = burst_size * 4 data_width_bits = burst_size * 32 @@ -249,7 +264,7 @@ class SBusFPGABus(Module): sbus_oe_master_in = Signal(reset=0) #sbus_oe_master_br = Signal(reset=0) - sbus_last_pa = Signal(28) + sbus_last_pa = Signal(32) burst_index = Signal(4) burst_counter = Signal(4) burst_limit_m1 = Signal(4) @@ -455,12 +470,12 @@ class SBusFPGABus(Module): If((self.hold_reset == 0), NextState("Idle")) ) slave_fsm.act("Idle", + # ***** Slave (Multi-)Word Read ***** If(((SBUS_3V3_SELs_i == 0) & (SBUS_3V3_ASs_i == 0) & (siz_is_word(SBUS_3V3_SIZ_i)) & (SBUS_3V3_PPRD_i == 1)), NextValue(sbus_oe_master_in, 1), - NextValue(sbus_last_pa, SBUS_3V3_PA_i), NextValue(burst_counter, 0), Case(SBUS_3V3_SIZ_i, { SIZ_WORD: NextValue(burst_limit_m1, 0), @@ -479,7 +494,9 @@ class SBusFPGABus(Module): (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) | (SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == ENGINE_ADDR_PFXA) | - (SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == ENGINE_ADDR_PFXB)), + (SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == ENGINE_ADDR_PFXB) | + (SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG3_REGISTERS_ADDR_PFX) | + (SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG3_PIXELS_ADDR_PFX)), NextValue(SBUS_3V3_ACKs_o, ACK_IDLE), # need to wait for data, don't ACK yet NextValue(SBUS_3V3_ERRs_o, 1), NextValue(sbus_wishbone_le, (SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == SRAM_ADDR_PFX)), @@ -489,12 +506,29 @@ class SBusFPGABus(Module): NextValue(self.wishbone_master.stb, 1), NextValue(self.wishbone_master.sel, 2**len(self.wishbone_master.sel)-1), NextValue(self.wishbone_master.we, 0), - NextValue(self.wishbone_master.adr, Cat(SBUS_3V3_PA_i[2:28], Signal(4, reset = 0))), + Case(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH], { + "default": [ NextValue(self.wishbone_master.adr, Cat(SBUS_3V3_PA_i[2:28], Signal(4, reset = 0))), + NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i, Signal(4, reset = 0))), + ], + # next remap X MiB to last MiB of SDRAM for CG3_PIXELS_ADDR_PFX + 0x080: [ + NextValue(self.wishbone_master.adr, Cat(SBUS_3V3_PA_i[2:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))), + NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i[0:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))), + ], + }), NextValue(wishbone_master_timeout, wishbone_default_timeout), NextValue(sbus_slave_timeout, sbus_default_timeout), #NextValue(self.led_display.value, 0x0000000000 | Cat(Signal(8, reset = 0), SBUS_3V3_PA_i, Signal(4, reset = 0))), NextState("Slave_Ack_Read_Reg_Burst_Wait_For_Data") ).Else( + Case(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH], { + "default": [ NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i, Signal(4, reset = 0))), + ], + # next remap X MiB to last MiB of SDRAM for CG3_PIXELS_ADDR_PFX + 0x080: [ + NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i[0:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))), + ], + }), NextValue(sbus_slave_timeout, sbus_default_timeout), NextState("Slave_Ack_Read_Reg_Burst_Wait_For_Wishbone") ) @@ -506,14 +540,16 @@ class SBusFPGABus(Module): NextValue(stat_slave_early_error_counter, stat_slave_early_error_counter + 1), NextState("Slave_Error") ) + # ***** Slave Byte Read ***** ).Elif(((SBUS_3V3_SELs_i == 0) & (SBUS_3V3_ASs_i == 0) & (SIZ_BYTE == SBUS_3V3_SIZ_i) & (SBUS_3V3_PPRD_i == 1)), NextValue(sbus_oe_master_in, 1), - NextValue(sbus_last_pa, SBUS_3V3_PA_i), If(((SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == ROM_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] == SRAM_ADDR_PFX) | + (SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG3_REGISTERS_ADDR_PFX) | + (SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG3_PIXELS_ADDR_PFX)), NextValue(SBUS_3V3_ACKs_o, ACK_IDLE), # need to wait for data, don't ACK yet NextValue(SBUS_3V3_ERRs_o, 1), NextValue(sbus_wishbone_le, (SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == SRAM_ADDR_PFX)), @@ -523,12 +559,29 @@ class SBusFPGABus(Module): NextValue(self.wishbone_master.stb, 1), NextValue(self.wishbone_master.sel, 2**len(self.wishbone_master.sel)-1), NextValue(self.wishbone_master.we, 0), - NextValue(self.wishbone_master.adr, Cat(SBUS_3V3_PA_i[2:28], Signal(4, reset = 0))), + Case(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH], { + "default": [ NextValue(self.wishbone_master.adr, Cat(SBUS_3V3_PA_i[2:28], Signal(4, reset = 0))), + NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i, Signal(4, reset = 0))), + ], + # next remap X MiB to last MiB of SDRAM for CG3_PIXELS_ADDR_PFX + 0x080: [ + NextValue(self.wishbone_master.adr, Cat(SBUS_3V3_PA_i[2:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))), + NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i[0:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))), + ], + }), NextValue(wishbone_master_timeout, wishbone_default_timeout), NextValue(sbus_slave_timeout, sbus_default_timeout), #NextValue(self.led_display.value, 0x0000000000 | Cat(Signal(8, reset = 0), SBUS_3V3_PA_i, Signal(4, reset = 0))), NextState("Slave_Ack_Read_Reg_Byte_Wait_For_Data") ).Else( + Case(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH], { + "default": [ NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i, Signal(4, reset = 0))), + ], + # next remap X MiB to last MiB of SDRAM for CG3_PIXELS_ADDR_PFX + 0x080: [ + NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i[0:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))), + ], + }), NextValue(sbus_slave_timeout, sbus_default_timeout), NextState("Slave_Ack_Read_Reg_Byte_Wait_For_Wishbone") ) @@ -540,12 +593,12 @@ class SBusFPGABus(Module): NextValue(stat_slave_early_error_counter, stat_slave_early_error_counter + 1), NextState("Slave_Error") ) + # ***** Slave HalfWord Read ***** ).Elif(((SBUS_3V3_SELs_i == 0) & (SBUS_3V3_ASs_i == 0) & (SIZ_HWORD == SBUS_3V3_SIZ_i) & (SBUS_3V3_PPRD_i == 1)), NextValue(sbus_oe_master_in, 1), - NextValue(sbus_last_pa, SBUS_3V3_PA_i), If(SBUS_3V3_PA_i[0:1] != 0, NextValue(SBUS_3V3_ACKs_o, ACK_ERR), NextValue(SBUS_3V3_ERRs_o, 1), @@ -553,7 +606,9 @@ class SBusFPGABus(Module): NextValue(stat_slave_early_error_counter, stat_slave_early_error_counter + 1), NextState("Slave_Error") ).Elif(((SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == ROM_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] == SRAM_ADDR_PFX) | + (SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG3_REGISTERS_ADDR_PFX) | + (SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG3_PIXELS_ADDR_PFX)), NextValue(SBUS_3V3_ACKs_o, ACK_IDLE), # need to wait for data, don't ACK yet NextValue(SBUS_3V3_ERRs_o, 1), NextValue(sbus_wishbone_le, (SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == SRAM_ADDR_PFX)), @@ -563,12 +618,29 @@ class SBusFPGABus(Module): NextValue(self.wishbone_master.stb, 1), NextValue(self.wishbone_master.sel, 2**len(self.wishbone_master.sel)-1), NextValue(self.wishbone_master.we, 0), - NextValue(self.wishbone_master.adr, Cat(SBUS_3V3_PA_i[2:28], Signal(4, reset = 0))), + Case(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH], { + "default": [ NextValue(self.wishbone_master.adr, Cat(SBUS_3V3_PA_i[2:28], Signal(4, reset = 0))), + NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i, Signal(4, reset = 0))), + ], + # next remap X MiB to last MiB of SDRAM for CG3_PIXELS_ADDR_PFX + 0x080: [ + NextValue(self.wishbone_master.adr, Cat(SBUS_3V3_PA_i[2:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))), + NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i[0:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))), + ], + }), NextValue(wishbone_master_timeout, wishbone_default_timeout), NextValue(sbus_slave_timeout, sbus_default_timeout), #NextValue(self.led_display.value, 0x0000000000 | Cat(Signal(8, reset = 0), SBUS_3V3_PA_i, Signal(4, reset = 0))), NextState("Slave_Ack_Read_Reg_HWord_Wait_For_Data") ).Else( + Case(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH], { + "default": [ NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i, Signal(4, reset = 0))), + ], + # next remap X MiB to last MiB of SDRAM for CG3_PIXELS_ADDR_PFX + 0x080: [ + NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i[0:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))), + ], + }), NextValue(sbus_slave_timeout, sbus_default_timeout), NextState("Slave_Ack_Read_Reg_HWord_Wait_For_Wishbone") ) @@ -580,12 +652,12 @@ class SBusFPGABus(Module): NextValue(stat_slave_early_error_counter, stat_slave_early_error_counter + 1), NextState("Slave_Error") ) + # ***** Slave (Multi-)Word Write ***** ).Elif(((SBUS_3V3_SELs_i == 0) & (SBUS_3V3_ASs_i == 0) & (siz_is_word(SBUS_3V3_SIZ_i)) & (SBUS_3V3_PPRD_i == 0)), NextValue(sbus_oe_master_in, 1), - NextValue(sbus_last_pa, SBUS_3V3_PA_i), NextValue(burst_counter, 0), Case(SBUS_3V3_SIZ_i, { SIZ_WORD: NextValue(burst_limit_m1, 0), @@ -604,9 +676,19 @@ class SBusFPGABus(Module): (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) | (SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == ENGINE_ADDR_PFXA) | - (SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == ENGINE_ADDR_PFXB)), + (SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == ENGINE_ADDR_PFXB) | + (SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG3_REGISTERS_ADDR_PFX) | + (SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG3_PIXELS_ADDR_PFX)), NextValue(sbus_wishbone_le, (SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == SRAM_ADDR_PFX)), NextValue(stat_slave_start_counter, stat_slave_start_counter + 1), + Case(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH], { + "default": [ NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i, Signal(4, reset = 0))), + ], + # next remap X MiB to last MiB of SDRAM + 0x080: [ + NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i[0:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))), + ], + }), If(~self.wishbone_master.cyc, NextValue(SBUS_3V3_ACKs_o, ACK_WORD), NextValue(SBUS_3V3_ERRs_o, 1), @@ -627,15 +709,25 @@ class SBusFPGABus(Module): NextValue(stat_slave_early_error_counter, stat_slave_early_error_counter + 1), NextState("Slave_Error") ) + # ***** Slave Byte Write ***** ).Elif(((SBUS_3V3_SELs_i == 0) & (SBUS_3V3_ASs_i == 0) & (SIZ_BYTE == SBUS_3V3_SIZ_i) & (SBUS_3V3_PPRD_i == 0)), NextValue(sbus_oe_master_in, 1), - NextValue(sbus_last_pa, SBUS_3V3_PA_i), - If(((SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == SRAM_ADDR_PFX)), + If(((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_REGISTERS_ADDR_PFX) | + (SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG3_PIXELS_ADDR_PFX)), NextValue(sbus_wishbone_le, (SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == SRAM_ADDR_PFX)), NextValue(stat_slave_start_counter, stat_slave_start_counter + 1), + Case(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH], { + "default": [ NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i, Signal(4, reset = 0))), + ], + # next remap X MiB to last MiB of SDRAM + 0x080: [ + NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i[0:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))), + ], + }), If(~self.wishbone_master.cyc, NextValue(SBUS_3V3_ACKs_o, ACK_BYTE), NextValue(SBUS_3V3_ERRs_o, 1), @@ -656,21 +748,31 @@ class SBusFPGABus(Module): NextValue(stat_slave_early_error_counter, stat_slave_early_error_counter + 1), NextState("Slave_Error") ) + # ***** Slave HalfWord Write ***** ).Elif(((SBUS_3V3_SELs_i == 0) & (SBUS_3V3_ASs_i == 0) & (SIZ_HWORD == SBUS_3V3_SIZ_i) & (SBUS_3V3_PPRD_i == 0)), NextValue(sbus_oe_master_in, 1), - NextValue(sbus_last_pa, SBUS_3V3_PA_i), If(SBUS_3V3_PA_i[0:1] != 0, NextValue(SBUS_3V3_ACKs_o, ACK_ERR), NextValue(SBUS_3V3_ERRs_o, 1), #NextValue(led0123, led0123 | LED_PARITY), NextValue(stat_slave_early_error_counter, stat_slave_early_error_counter + 1), NextState("Slave_Error") - ).Elif(((SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == SRAM_ADDR_PFX)), + ).Elif(((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_REGISTERS_ADDR_PFX) | + (SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == CG3_PIXELS_ADDR_PFX)), NextValue(sbus_wishbone_le, (SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == SRAM_ADDR_PFX)), NextValue(stat_slave_start_counter, stat_slave_start_counter + 1), + Case(SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH], { + "default": [ NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i, Signal(4, reset = 0))), + ], + # next remap X MiB to last MiB of SDRAM + 0x080: [ + NextValue(sbus_last_pa, Cat(SBUS_3V3_PA_i[0:CG3_KEPT_UPPER_BIT], Signal(CG3_UPPER_BITS, reset = CG3_REMAPPED_BASE))), + ], + }), If(~self.wishbone_master.cyc, NextValue(SBUS_3V3_ACKs_o, ACK_HWORD), NextValue(SBUS_3V3_ERRs_o, 1), @@ -943,8 +1045,8 @@ class SBusFPGABus(Module): NextValue(wishbone_master_timeout, wishbone_default_timeout), NextValue(self.wishbone_master.adr, Cat(index_with_wrap(burst_counter+1, burst_limit_m1, sbus_last_pa[ADDR_PHYS_LOW+2:ADDR_PHYS_LOW+6]), # 4 bits, adr FIXME sbus_last_pa[ADDR_PHYS_LOW+6:ADDR_PFX_LOW], # 10 bits, adr - sbus_last_pa[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH], # 12 bits, adr - Signal(4, reset = 0))), + sbus_last_pa[ADDR_PFX_LOW:32] # 16 bits, adr + )), NextValue(SBUS_3V3_ACKs_o, ACK_IDLE), NextState("Slave_Ack_Read_Reg_Burst_Wait_For_Data") ) @@ -982,7 +1084,7 @@ class SBusFPGABus(Module): NextValue(self.wishbone_master.stb, 1), NextValue(self.wishbone_master.sel, 2**len(self.wishbone_master.sel)-1), NextValue(self.wishbone_master.we, 0), - NextValue(self.wishbone_master.adr, Cat(sbus_last_pa[2:28], Signal(4, reset = 0))), + NextValue(self.wishbone_master.adr, sbus_last_pa[2:32]), NextValue(wishbone_master_timeout, wishbone_default_timeout), #NextValue(self.led_display.value, 0x0000000000 | Cat(Signal(8, reset = 0), SBUS_3V3_PA_i, Signal(4, reset = 0))), NextState("Slave_Ack_Read_Reg_Burst_Wait_For_Data") @@ -1043,7 +1145,7 @@ class SBusFPGABus(Module): NextValue(self.wishbone_master.stb, 1), NextValue(self.wishbone_master.sel, 2**len(self.wishbone_master.sel)-1), NextValue(self.wishbone_master.we, 0), - NextValue(self.wishbone_master.adr, Cat(sbus_last_pa[2:28], Signal(4, reset = 0))), + NextValue(self.wishbone_master.adr, sbus_last_pa[2:32]), NextValue(wishbone_master_timeout, wishbone_default_timeout), #NextValue(self.led_display.value, 0x0000000000 | Cat(Signal(8, reset = 0), SBUS_3V3_PA_i, Signal(4, reset = 0))), NextState("Slave_Ack_Read_Reg_HWord_Wait_For_Data") @@ -1102,7 +1204,7 @@ class SBusFPGABus(Module): NextValue(self.wishbone_master.stb, 1), NextValue(self.wishbone_master.sel, 2**len(self.wishbone_master.sel)-1), NextValue(self.wishbone_master.we, 0), - NextValue(self.wishbone_master.adr, Cat(sbus_last_pa[2:28], Signal(4, reset = 0))), + NextValue(self.wishbone_master.adr, sbus_last_pa[2:32]), NextValue(wishbone_master_timeout, wishbone_default_timeout), #NextValue(self.led_display.value, 0x0000000000 | Cat(Signal(8, reset = 0), SBUS_3V3_PA_i, Signal(4, reset = 0))), NextState("Slave_Ack_Read_Reg_Byte_Wait_For_Data") @@ -1122,8 +1224,8 @@ class SBusFPGABus(Module): NextValue(self.wishbone_master.sel, 2**len(self.wishbone_master.sel)-1), NextValue(self.wishbone_master.adr, Cat(index_with_wrap(burst_counter, burst_limit_m1, sbus_last_pa[ADDR_PHYS_LOW+2:ADDR_PHYS_LOW+6]), # 4 bits, adr FIXME sbus_last_pa[ADDR_PHYS_LOW+6:ADDR_PFX_LOW], # 10 bits, adr - sbus_last_pa[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH], # 12 bits, adr - Signal(4, reset = 0))), + sbus_last_pa[ADDR_PFX_LOW:32] # 16 bits, adr + )), Case(sbus_wishbone_le, { 0: NextValue(self.wishbone_master.dat_w, Cat(SBUS_3V3_D_i)), 1: NextValue(self.wishbone_master.dat_w, Cat(SBUS_3V3_D_i[24:32], @@ -1160,7 +1262,7 @@ class SBusFPGABus(Module): NextState("Slave_Ack_Reg_Write_Burst") ).Elif(sbus_slave_timeout == 0, ### this is taking too long NextValue(SBUS_3V3_ACKs_o, ACK_RERUN), - #NextValue(self.led_display.value, Cat(Signal(8, reset = LED_RERUN | LED_RERUN_WRITE | LED_RERUN_WORD), sbus_last_pa, Signal(4, reset = 0))), + #NextValue(self.led_display.value, Cat(Signal(8, reset = LED_RERUN | LED_RERUN_WRITE | LED_RERUN_WORD), sbus_last_pa)), #NextValue(led0123, LED_RERUN | LED_RERUN_WRITE | LED_RERUN_WORD), NextValue(stat_slave_rerun_counter, stat_slave_rerun_counter + 1), NextState("Slave_Error") @@ -1182,8 +1284,8 @@ class SBusFPGABus(Module): }), NextValue(self.wishbone_master.adr, Cat(sbus_last_pa[ADDR_PHYS_LOW+2:ADDR_PHYS_LOW+6], # 4 bits, adr FIXME sbus_last_pa[ADDR_PHYS_LOW+6:ADDR_PFX_LOW], # 10 bits, adr - sbus_last_pa[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH], # 12 bits, adr - Signal(4, reset = 0))), + sbus_last_pa[ADDR_PFX_LOW:32] # 16 bits, adr + )), Case(sbus_wishbone_le, { 0: NextValue(self.wishbone_master.dat_w, Cat(SBUS_3V3_D_i[16:32], SBUS_3V3_D_i[16:32])), @@ -1229,8 +1331,8 @@ class SBusFPGABus(Module): }), NextValue(self.wishbone_master.adr, Cat(sbus_last_pa[ADDR_PHYS_LOW+2:ADDR_PHYS_LOW+6], # 4 bits, adr FIXME sbus_last_pa[ADDR_PHYS_LOW+6:ADDR_PFX_LOW], # 10 bits, adr - sbus_last_pa[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH], # 12 bits, adr - Signal(4, reset = 0))), + sbus_last_pa[ADDR_PFX_LOW:32] # 16 bits, adr + )), NextValue(self.wishbone_master.dat_w, Cat(SBUS_3V3_D_i[24:32], # LE/BE identical SBUS_3V3_D_i[24:32], SBUS_3V3_D_i[24:32], diff --git a/sbus-to-ztex-gateware-migen/sbus_to_fpga_prom.py b/sbus-to-ztex-gateware-migen/sbus_to_fpga_prom.py index d9dbd5b..2a23899 100644 --- a/sbus-to-ztex-gateware-migen/sbus_to_fpga_prom.py +++ b/sbus-to-ztex-gateware-migen/sbus_to_fpga_prom.py @@ -48,7 +48,8 @@ def get_prom(soc, sdram=True, engine=False, i2c=False, - cg3=False): + cg3=False, + cg3_res=None): r = "fcode-version2\nfload prom_csr_{}.fth\n".format(version.replace(".", "_")) @@ -114,10 +115,14 @@ def get_prom(soc, r += "finish-device\nnew-device\n" if (cg3): + hres = int(cg3_res.split("@")[0].split("x")[0]) + vres = int(cg3_res.split("@")[0].split("x")[1]) + hres_h=(f"{hres:x}").replace("0x", "") + vres_h=(f"{vres:x}").replace("0x", "") cg3_file = open("cg3.fth") cg3_lines = cg3_file.readlines() for line in cg3_lines: - r += line + r += line.replace("SBUSFPGA_CG3_WIDTH", hres_h).replace("SBUSFPGA_CG3_HEIGHT", vres_h) r += "end0\n" diff --git a/sbus-to-ztex-gateware-migen/sbus_to_fpga_soc.py b/sbus-to-ztex-gateware-migen/sbus_to_fpga_soc.py index 399bc2e..694d85c 100644 --- a/sbus-to-ztex-gateware-migen/sbus_to_fpga_soc.py +++ b/sbus-to-ztex-gateware-migen/sbus_to_fpga_soc.py @@ -193,7 +193,7 @@ class _CRG(Module): class SBusFPGA(SoCCore): - def __init__(self, version, usb, sdram, engine, i2c, cg3, **kwargs): + def __init__(self, version, usb, sdram, engine, i2c, cg3, cg3_res, **kwargs): print(f"Building SBusFPGA for board version {version}") kwargs["cpu_type"] = "None" @@ -207,6 +207,17 @@ class SBusFPGA(SoCCore): if (cg3 and (version == "V1.2")): platform.add_extension(ztex213_sbus._vga_pmod_io_v1_2) + + if (cg3): + hres = int(cg3_res.split("@")[0].split("x")[0]) + vres = int(cg3_res.split("@")[0].split("x")[1]) + cg3_fb_size = int(1048576 * ceil((hres * vres) / 1048576)) + print(f"Reserving {cg3_fb_size} bytes ({cg3_fb_size//1048576} MiB) for the CG3") + else: + hres = 0 + vres = 0 + cg3_fb_size = 0 + litex.soc.cores.video.video_timings.update(cg3_fb.cg3_timings) SoCCore.__init__(self, platform=platform, @@ -215,7 +226,7 @@ class SBusFPGA(SoCCore): csr_paging=0x1000, # default is 0x800 **kwargs) - # This mem-map is also exposed in the FSM (matched prefixes) + # *** 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: # the physical address here are used as offset in the SBus @@ -225,18 +236,18 @@ class SBusFPGA(SoCCore): # the virtual address space used by NetBSD DMA allocators # (themselves constrained by the SBus MMU capabilities) self.wb_mem_map = wb_mem_map = { - "prom": 0x00000000, + "prom": 0x00000000, # 256 Kib ought to be enough for anybody (we're using < 2.5 Kib now...) "csr" : 0x00040000, - "usb_host": 0x00080000, - "usb_shared_mem": 0x00090000, # unused - "curve25519engine": 0x000a0000, + "usb_host": 0x00080000, # OHCI registers are here, not in CSR + "usb_shared_mem": 0x00090000, # unused ATM + "curve25519engine": 0x000a0000, # includes microcode (4 KiB@0) and registers (16 KiB @ 64 KiB) "cg3_registers": 0x00400000, # required for compatibility - "cg3_pixels": 0x00800000, # required for compatibility - "main_ram": 0x80000000, - "usb_fake_dma": 0xfc000000, + "cg3_pixels": 0x00800000, # required for compatibility + "main_ram": 0x80000000, # not directly reachable from SBus mapping (only 0x0 - 0x10000000 is accessible) + "usb_fake_dma": 0xfc000000, # required to match DVMA virtual addresses } self.mem_map.update(wb_mem_map) - self.submodules.crg = _CRG(platform=platform, sys_clk_freq=sys_clk_freq, usb=usb, sdram=sdram, engine=engine, cg3=cg3, pix_clk=108e6) # FIXME: pix_clk + self.submodules.crg = _CRG(platform=platform, sys_clk_freq=sys_clk_freq, usb=usb, sdram=sdram, engine=engine, cg3=cg3, pix_clk=litex.soc.cores.video.video_timings[cg3_res]["pix_clk"]) #self.platform.add_period_constraint(self.platform.lookup_request("SBUS_3V3_CLK", loose=True), 1e9/25e6) # SBus max ## add our custom timings after the clocks have been defined @@ -302,6 +313,17 @@ class SBusFPGA(SoCCore): module = MT41J128M16(sys_clk_freq, "1:4"), l2_cache_size = 0, ) + avail_sdram = self.bus.regions["main_ram"].size + else: + avail_sdram = 0 + + if (cg3): + if (avail_sdram >= cg3_fb_size): + avail_sdram = avail_sdram - cg3_fb_size + else: + print("***** ERROR ***** Can't have a FrameBuffer without main ram\n") + assert(False) + # don't enable anything on the SBus side for 20 seconds after power up # this avoids FPGA initialization messing with the cold boot process # requires us to reset the SPARCstation afterward so the FPGA board @@ -341,6 +363,7 @@ class SBusFPGA(SoCCore): fromsbus_req_fifo=self.fromsbus_req_fifo, dram_dma_writer=self.dram_dma_writer, dram_dma_reader=self.dram_dma_reader, + mem_size=avail_sdram//1048576, burst_size=burst_size, do_checksum = True) else: @@ -356,7 +379,8 @@ class SBusFPGA(SoCCore): fromsbus_fifo=self.fromsbus_fifo, fromsbus_req_fifo=self.fromsbus_req_fifo, version=version, - burst_size=burst_size) + burst_size=burst_size, + cg3_fb_size=cg3_fb_size) #self.submodules.sbus_bus = _sbus_bus self.submodules.sbus_bus = ClockDomainsRenamer("sbus")(_sbus_bus) self.submodules.sbus_bus_stat = SBusFPGABusStat(sbus_bus = self.sbus_bus) @@ -391,9 +415,8 @@ class SBusFPGA(SoCCore): self.submodules.i2c = i2c.RTLI2C(platform, pads=platform.request("i2c")) if (cg3): - litex.soc.cores.video.video_timings.update(cg3_fb.cg3_timings) self.submodules.videophy = VideoVGAPHY(platform.request("vga"), clock_domain="vga") - self.submodules.cg3 = cg3_fb.cg3(soc=self, phy=self.videophy, timings="1152x900@76Hz", clock_domain="vga") # clock_domain for the VGA side, cg3 is running in cd_sys + self.submodules.cg3 = cg3_fb.cg3(soc=self, phy=self.videophy, timings=cg3_res, clock_domain="vga") # clock_domain for the VGA side, cg3 is running in cd_sys self.bus.add_slave("cg3_registers", self.cg3.bus, SoCRegion(origin=self.mem_map.get("cg3_registers", None), size=0x1000, cached=False)) #self.add_video_framebuffer(phy=self.videophy, timings="1152x900@76Hz", clock_domain="vga") @@ -409,8 +432,9 @@ def main(): parser.add_argument("--sdram", action="store_true", help="add a SDRAM controller (mandatory) [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 [none]") + parser.add_argument("--i2c", action="store_true", help="add an I2C bus [none, placeholder]") 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 resolution") builder_args(parser) vivado_build_args(parser) args = parser.parse_args() @@ -432,7 +456,8 @@ def main(): usb=args.usb, engine=args.engine, i2c=args.i2c, - cg3=args.cg3) + cg3=args.cg3, + cg3_res=args.cg3_res) #soc.add_uart(name="uart", baudrate=115200, fifo_depth=16) version_for_filename = args.version.replace(".", "_") @@ -471,11 +496,12 @@ def main(): write_to_file(os.path.join(f"prom_csr_{version_for_filename}.fth"), csr_forth_contents) prom_content = sbus_to_fpga_prom.get_prom(soc=soc, version=args.version, - usb=args.usb, - sdram=args.sdram, - engine=args.engine, - i2c=args.i2c, - cg3=args.cg3) + usb=args.usb, + sdram=args.sdram, + engine=args.engine, + i2c=args.i2c, + cg3=args.cg3, + cg3_res=args.cg3_res) write_to_file(os.path.join(f"prom_{version_for_filename}.fth"), prom_content)