1
0
mirror of synced 2026-01-25 11:26:37 +00:00

more ocnfigurability

This commit is contained in:
Romain Dolbeau 2021-09-21 14:12:17 -04:00
parent 4609e15dc6
commit ba734f0fa9
4 changed files with 196 additions and 60 deletions

View File

@ -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)")

View File

@ -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],

View File

@ -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"

View File

@ -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)