1
0
mirror of synced 2026-03-06 02:38:58 +00:00
This commit is contained in:
Romain Dolbeau
2021-06-22 14:56:51 -04:00
parent b6bbbd05e8
commit da0c49062d
2 changed files with 0 additions and 675 deletions

View File

@@ -1,174 +0,0 @@
import os
import argparse
from migen import *
import litex
from litex.build.generic_platform import *
from litex.build.xilinx.vivado import vivado_build_args, vivado_build_argdict
from litex.soc.integration.soc import *
from litex.soc.integration.soc_core import *
from litex.soc.integration.builder import *
from litex.soc.cores.clock import *
from litex.soc.cores.led import LedChaser
from litex_boards.platforms import ztex213
from migen.genlib.fifo import *
from sbus_to_fpga_slave import *;
from sbus_to_fpga_wishbone import *;
_sbus_sbus = [
("SBUS_3V3_CLK", 0, Pins("D15"), IOStandard("lvttl")),
("SBUS_3V3_ASs", 0, Pins("T4"), IOStandard("lvttl")),
("SBUS_3V3_BGs", 0, Pins("T6"), IOStandard("lvttl")),
("SBUS_3V3_BRs", 0, Pins("R6"), IOStandard("lvttl")),
("SBUS_3V3_ERRs", 0, Pins("V2"), IOStandard("lvttl")),
("SBUS_DATA_OE_LED", 0, Pins("U1"), IOStandard("lvttl")),
("SBUS_DATA_OE_LED_2", 0, Pins("T3"), IOStandard("lvttl")),
("SBUS_3V3_RSTs", 0, Pins("U2"), IOStandard("lvttl")),
("SBUS_3V3_SELs", 0, Pins("K6"), IOStandard("lvttl")),
("SBUS_3V3_INT1s", 0, Pins("R3"), IOStandard("lvttl")),
("SBUS_3V3_INT7s", 0, Pins("N5"), IOStandard("lvttl")),
("SBUS_3V3_PPRD", 0, Pins("N6"), IOStandard("lvttl")),
("SBUS_OE", 0, Pins("P5"), IOStandard("lvttl")),
("SBUS_3V3_ACKs", 0, Pins("M6 L6 N4"), IOStandard("lvttl")),
("SBUS_3V3_SIZ", 0, Pins("R7 U3 V1"), IOStandard("lvttl")),
("SBUS_3V3_D", 0, Pins("J18 K16 J17 K15 K13 J15 J13 J14 H14 H17 G14 G17 G16 G18 H16 F18 F16 E18 F15 D18 E17 G13 D17 F13 F14 E16 E15 C17 C16 A18 B18 C15"), IOStandard("lvttl")),
("SBUS_3V3_PA", 0, Pins("B16 B17 D14 C14 D12 A16 A15 B14 B13 B12 C12 A14 A13 B11 A11 M4 R2 M3 P2 M2 N2 K5 N1 L4 M1 L3 L1 K3"), IOStandard("lvttl")),
]
# CRG ----------------------------------------------------------------------------------------------
class _CRG(Module):
def __init__(self, platform, sys_clk_freq):
self.clock_domains.cd_sys = ClockDomain()
self.clock_domains.cd_native = ClockDomain(reset_less=True)
self.clock_domains.cd_sbus = ClockDomain()
self.clock_domains.cd_por = ClockDomain()
# # #
clk48 = platform.request("clk48")
self.cd_native.clk = clk48
clk_sbus = platform.request("SBUS_3V3_CLK")
self.cd_sbus.clk = clk_sbus
rst_sbus = platform.request("SBUS_3V3_RSTs")
self.comb += self.cd_sbus.rst.eq(~rst_sbus)
self.submodules.pll = pll = S7MMCM(speedgrade=-1)
pll.register_clkin(clk48, 48e6)
pll.create_clkout(self.cd_sys, sys_clk_freq)
platform.add_false_path_constraints(self.cd_native.clk, self.cd_sbus.clk)
platform.add_false_path_constraints(self.cd_sys.clk, self.cd_sbus.clk)
platform.add_false_path_constraints(self.cd_sbus.clk, self.cd_native.clk)
platform.add_false_path_constraints(self.cd_sbus.clk, self.cd_sys.clk)
# Power on reset, reset propagate from SBus to SYS
por_count = Signal(16, reset=2**16-1)
por_done = Signal()
self.comb += self.cd_por.clk.eq(clk48)
self.comb += por_done.eq(por_count == 0)
self.sync.por += If(~por_done, por_count.eq(por_count - 1))
self.comb += pll.reset.eq(~por_done | ~rst_sbus)
class SBusFPGA(SoCCore):
def __init__(self, **kwargs):
kwargs["cpu_type"] = "None"
kwargs["integrated_sram_size"] = 0
kwargs["with_uart"] = True
kwargs["with_timer"] = False
self.sys_clk_freq = sys_clk_freq = 100e6
self.platform = platform = ztex213.Platform(variant="ztex2.13a", expansion="sbus")
self.platform.add_extension(_sbus_sbus)
SoCCore.__init__(self, platform=platform, sys_clk_freq=sys_clk_freq, clk_freq=sys_clk_freq, **kwargs)
wb_mem_map = {
"prom": 0x00000000,
"csr" : 0x00040000,
}
self.mem_map.update(wb_mem_map)
self.submodules.crg = _CRG(platform=platform, sys_clk_freq=sys_clk_freq)
self.platform.add_period_constraint(self.platform.lookup_request("SBUS_3V3_CLK", loose=True), 1e9/25e6) # SBus max
self.submodules.leds = LedChaser(
pads = platform.request_all("user_led"),
sys_clk_freq = sys_clk_freq)
self.add_csr("leds")
prom_file = "prom_mini.fc"
prom_data = soc_core.get_mem_data(prom_file, "big")
prom = Array(prom_data)
#print("\n****************************************\n")
#for i in range(len(prom)):
# print(hex(prom[i]))
#print("\n****************************************\n")
self.add_ram("prom", origin=self.mem_map["prom"], size=2**16, contents=prom_data, mode="r") # for show
#getattr(self,"prom").mem.init = prom_data
#getattr(self,"prom").mem.depth = 2**14
# 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
# is properly identified
# This is in the 'native' ClockDomain that is never reset
hold_reset_ctr = Signal(30, reset=960000000)
self.sync.native += If(hold_reset_ctr>0, hold_reset_ctr.eq(hold_reset_ctr - 1))
hold_reset = Signal(reset=1)
self.comb += hold_reset.eq(~(hold_reset_ctr == 0))
sbus_to_wishbone_wr_fifo = AsyncFIFOBuffered(width=32+30, depth=16)
sbus_to_wishbone_wr_fifo = ClockDomainsRenamer({"write": "sbus", "read": "sys"})(sbus_to_wishbone_wr_fifo)
self.submodules += sbus_to_wishbone_wr_fifo
sbus_to_wishbone_rd_fifo_addr = AsyncFIFOBuffered(width=30, depth=16)
sbus_to_wishbone_rd_fifo_addr = ClockDomainsRenamer({"write": "sbus", "read": "sys"})(sbus_to_wishbone_rd_fifo_addr)
self.submodules += sbus_to_wishbone_rd_fifo_addr
sbus_to_wishbone_rd_fifo_data = AsyncFIFOBuffered(width=32, depth=16)
sbus_to_wishbone_rd_fifo_data = ClockDomainsRenamer({"write": "sys", "read": "sbus"})(sbus_to_wishbone_rd_fifo_data)
self.submodules += sbus_to_wishbone_rd_fifo_data
self.submodules.sbus_to_wishbone = SBusToWishbone(wr_fifo=sbus_to_wishbone_wr_fifo,
rd_fifo_addr=sbus_to_wishbone_rd_fifo_addr,
rd_fifo_data=sbus_to_wishbone_rd_fifo_data,
wishbone=wishbone.Interface(data_width=self.bus.data_width))
_sbus_slave = SBusFPGASlave(platform=self.platform,
prom=prom,
hold_reset=hold_reset,
wr_fifo=sbus_to_wishbone_wr_fifo,
rd_fifo_addr=sbus_to_wishbone_rd_fifo_addr,
rd_fifo_data=sbus_to_wishbone_rd_fifo_data,)
self.submodules.sbus_slave = ClockDomainsRenamer("sbus")(_sbus_slave)
self.bus.add_master(name="SBusBridgeToWishbone", master=self.sbus_to_wishbone.wishbone)
# self.soc = Module()
# self.soc.mem_regions = self.mem_regions = {}
# region = litex.soc.integration.soc.SoCRegion(origin=0x0, size=0x0)
# region.length = 0
# self.mem_regions['csr'] = region
# self.soc.constants = self.constants = {}
# self.soc.csr_regions = self.csr_regions = {}
# self.soc.cpu_type = self.cpu_type = None
# def do_finalize(self):
# self.platform.add_period_constraint(self.platform.lookup_request("SBUS_3V3_CLK", loose=True), 1e9/25e6)
def main():
parser = argparse.ArgumentParser(description="SbusFPGA")
parser.add_argument("--build", action="store_true", help="Build bitstream")
builder_args(parser)
vivado_build_args(parser)
args = parser.parse_args()
soc = SBusFPGA(**soc_core_argdict(args))
#soc.add_uart(name="uart", baudrate=115200, fifo_depth=16)
builder = Builder(soc, **builder_argdict(args))
builder.build(**vivado_build_argdict(args), run=args.build)
if __name__ == "__main__":
main()

View File

@@ -1,501 +0,0 @@
from migen import *
from migen.fhdl.specials import Tristate
SIZ_WORD = 0x0
SIZ_BYTE = 0x1
SIZ_HWORD = 0x2
SIZ_EXT = 0x3
SIZ_BURST4 = 0x4
SIZ_BURST8 = 0x5
SIZ_BURST16 = 0x6
SIZ_BURST2 = 0x7
ACK_IDLE = 0x7
ACK_ERR = 0x6
ACK_BYTE = 0x5
ACK_RERUN = 0x4
ACK_WORD = 0x3
ACK_DWORD = 0x2
ACK_HWORD = 0x1
ACK_RECV = 0x0
ADDR_PHYS_HIGH = 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 = 0)
WISHBONE_CSR_ADDR_PFX = Signal(12, reset = 4)
def siz_is_word(siz):
return (SIZ_WORD == siz) | (SIZ_BURST2 == siz) | (SIZ_BURST4 == siz) | (SIZ_BURST8 == siz) | (SIZ_BURST16 == siz)
# FIXME: this doesn't work. Verilog aways use value[0:4]
#def _index_with_wrap(counter, limit_m1, value):
# if (limit_m1 == 0):
# return value[0:4]
# elif (limit_m1 == 1):
# return Cat((value + counter)[0:1], value[1:4])
# elif (limit_m1 == 3):
# return Cat((value + counter)[0:2], value[2:4])
# elif (limit_m1 == 7):
# return Cat((value + counter)[0:3], value[3:4])
# elif (limit_m1 == 15):
# return (value + counter)[0:4]
# return value[0:4]
def index_with_wrap(counter, limit_m1, value):
return ((value+counter) & limit_m1)[0:4] | (value&(~limit_m1))[0:4]
# FIXME: this doesn't work. Verilog aways use 1
def siz_to_burst_size_m1(siz):
if (SIZ_WORD == siz):
return 0
elif (SIZ_BURST2 == siz):
return 1
elif (SIZ_BURST4 == siz):
return 3
elif (SIZ_BURST8 == siz):
return 7
elif (SIZ_BURST16 == siz):
return 15
return 1
class LedDisplay(Module):
def __init__(self, pads):
n = len(pads)
self.value = Signal(32, reset = 0x18244281)
old_value = Signal(32)
display = Signal(8)
self.submodules.fsm = fsm = FSM(reset_state="Reset")
time_counter = Signal(32, reset = 0)
blink_counter = Signal(4, reset = 0)
self.comb += pads.eq(display)
fsm.act("Reset",
NextValue(time_counter, 25000000//10),
NextValue(blink_counter, 10),
NextValue(display, 0x00),
NextValue(old_value, self.value),
NextState("Quick"))
fsm.act("Quick",
If (old_value != self.value,
NextState("Reset")
).Elif(time_counter == 0,
If (blink_counter == 0,
NextValue(time_counter, 25000000//2),
NextValue(display, self.value[0:8]),
NextState("Byte0")
).Else(
NextValue(display, ~display),
NextValue(time_counter, 25000000//10),
NextValue(blink_counter, blink_counter - 1)
)
).Else(
NextValue(time_counter, time_counter - 1)
)
)
fsm.act("Byte0",
If (old_value != self.value,
NextState("Reset")
).Elif(time_counter == 0,
NextValue(time_counter, 25000000//2),
NextValue(display, self.value[8:16]),
NextState("Byte1")
).Else(
NextValue(time_counter, time_counter - 1)
)
)
fsm.act("Byte1",
If (old_value != self.value,
NextState("Reset")
).Elif(time_counter == 0,
NextValue(time_counter, 25000000//2),
NextValue(display, self.value[16:24]),
NextState("Byte2")
).Else(
NextValue(time_counter, time_counter - 1)
)
)
fsm.act("Byte2",
If (old_value != self.value,
NextState("Reset")
).Elif(time_counter == 0,
NextValue(time_counter, 25000000//2),
NextValue(display, self.value[24:32]),
NextState("Byte3")
).Else(
NextValue(time_counter, time_counter - 1)
)
)
fsm.act("Byte3",
If (old_value != self.value,
NextState("Reset")
).Elif(time_counter == 0,
NextValue(time_counter, 25000000//10),
NextValue(blink_counter, 10),
NextValue(display, 0x00),
NextState("Quick")
).Else(
NextValue(time_counter, time_counter - 1)
)
)
class SBusFPGASlave(Module):
def __init__(self, platform, prom, hold_reset, wr_fifo, rd_fifo_addr, rd_fifo_data):
self.platform = platform
self.hold_reset = hold_reset
self.wr_fifo = wr_fifo
self.rd_fifo_addr = rd_fifo_addr
self.rd_fifo_data = rd_fifo_data
#self.submodules.led_display = LedDisplay(pads=platform.request_all("user_led"))
#pad_SBUS_3V3_CLK = platform.request("SBUS_3V3_CLK")
pad_SBUS_3V3_ASs = platform.request("SBUS_3V3_ASs")
pad_SBUS_3V3_BGs = platform.request("SBUS_3V3_BGs")
pad_SBUS_3V3_BRs = platform.request("SBUS_3V3_BRs")
pad_SBUS_3V3_ERRs = platform.request("SBUS_3V3_ERRs")
pad_SBUS_DATA_OE_LED = platform.request("SBUS_DATA_OE_LED")
pad_SBUS_DATA_OE_LED_2 = platform.request("SBUS_DATA_OE_LED_2")
#pad_SBUS_3V3_RSTs = platform.request("SBUS_3V3_RSTs")
pad_SBUS_3V3_SELs = platform.request("SBUS_3V3_SELs")
pad_SBUS_3V3_INT1s = platform.request("SBUS_3V3_INT1s")
pad_SBUS_3V3_INT7s = platform.request("SBUS_3V3_INT7s")
pad_SBUS_3V3_PPRD = platform.request("SBUS_3V3_PPRD")
pad_SBUS_OE = platform.request("SBUS_OE")
pad_SBUS_3V3_ACKs = platform.request("SBUS_3V3_ACKs")
pad_SBUS_3V3_SIZ = platform.request("SBUS_3V3_SIZ")
pad_SBUS_3V3_D = platform.request("SBUS_3V3_D")
pad_SBUS_3V3_PA = platform.request("SBUS_3V3_PA")
assert len(pad_SBUS_3V3_D) == 32, "len(pad_SBUS_3V3_D) should be 32"
assert len(pad_SBUS_3V3_PA) == 28, "len(pad_SBUS_3V3_PA) should be 28"
#leds = Signal(8, reset=0xF0)
#self.comb += platform.request("user_led", 0).eq(leds[0])
#self.comb += platform.request("user_led", 1).eq(leds[1])
#self.comb += platform.request("user_led", 2).eq(leds[2])
#self.comb += platform.request("user_led", 3).eq(leds[3])
#self.comb += platform.request("user_led", 4).eq(leds[4])
#self.comb += platform.request("user_led", 5).eq(leds[5])
#self.comb += platform.request("user_led", 6).eq(leds[6])
#self.comb += platform.request("user_led", 7).eq(leds[7])
sbus_oe_data = Signal(reset=0)
sbus_oe_slave_in = Signal(reset=0)
sbus_oe_master_in = Signal(reset=0)
sbus_oe_int1 = Signal(reset=0)
sbus_oe_int7 = Signal(reset=0)
sbus_oe_master_br = Signal(reset=0)
sbus_last_pa = Signal(28)
burst_index = Signal(4)
burst_counter = Signal(4)
burst_limit_m1 = Signal(4)
#SBUS_3V3_CLK = Signal()
SBUS_3V3_ASs_i = Signal()
self.comb += SBUS_3V3_ASs_i.eq(pad_SBUS_3V3_ASs)
SBUS_3V3_BGs_i = Signal()
self.comb += SBUS_3V3_BGs_i.eq(pad_SBUS_3V3_BGs)
SBUS_3V3_BRs_o = Signal(reset=1)
self.specials += Tristate(pad_SBUS_3V3_BRs, SBUS_3V3_BRs_o, sbus_oe_master_br, None)
SBUS_3V3_ERRs_i = Signal()
SBUS_3V3_ERRs_o = Signal()
self.specials += Tristate(pad_SBUS_3V3_ERRs, SBUS_3V3_ERRs_o, sbus_oe_master_in, SBUS_3V3_ERRs_i)
SBUS_DATA_OE_LED_o = Signal()
self.comb += pad_SBUS_DATA_OE_LED.eq(SBUS_DATA_OE_LED_o)
SBUS_DATA_OE_LED_2_o = Signal()
self.comb += pad_SBUS_DATA_OE_LED_2.eq(SBUS_DATA_OE_LED_2_o)
#SBUS_3V3_RSTs = Signal()
SBUS_3V3_SELs_i = Signal()
self.comb += SBUS_3V3_SELs_i.eq(pad_SBUS_3V3_SELs)
SBUS_3V3_INT1s_o = Signal(reset=1)
self.specials += Tristate(pad_SBUS_3V3_INT1s, SBUS_3V3_INT1s_o, sbus_oe_int1, None)
SBUS_3V3_INT7s_o = Signal(reset=1)
self.specials += Tristate(pad_SBUS_3V3_INT7s, SBUS_3V3_INT7s_o, sbus_oe_int7, None)
SBUS_3V3_PPRD_i = Signal()
SBUS_3V3_PPRD_o = Signal()
self.specials += Tristate(pad_SBUS_3V3_PPRD, SBUS_3V3_PPRD_o, sbus_oe_slave_in, SBUS_3V3_PPRD_i)
#SBUS_OE_o = Signal()
self.comb += pad_SBUS_OE.eq(self.hold_reset)
SBUS_3V3_ACKs_i = Signal(3)
SBUS_3V3_ACKs_o = Signal(3)
self.specials += Tristate(pad_SBUS_3V3_ACKs, SBUS_3V3_ACKs_o, sbus_oe_master_in, SBUS_3V3_ACKs_i)
SBUS_3V3_SIZ_i = Signal(3)
SBUS_3V3_SIZ_o = Signal(3)
self.specials += Tristate(pad_SBUS_3V3_SIZ, SBUS_3V3_SIZ_o, sbus_oe_slave_in, SBUS_3V3_SIZ_i)
SBUS_3V3_D_i = Signal(32)
SBUS_3V3_D_o = Signal(32)
self.specials += Tristate(pad_SBUS_3V3_D, SBUS_3V3_D_o, sbus_oe_data, SBUS_3V3_D_i)
SBUS_3V3_PA_i = Signal(28)
self.comb += SBUS_3V3_PA_i.eq(pad_SBUS_3V3_PA)
p_data = Signal(32) # data to read/write
data_read_addr = Signal(30) # first addr of req. when reading from WB
data_read_enable = Signal() # start enqueuing req. to read from WB
self.submodules.slave_fsm = slave_fsm = FSM(reset_state="Reset")
slave_fsm.act("Reset",
#NextValue(SBUS_DATA_OE_LED_o, 0),
#NextValue(SBUS_DATA_OE_LED_2_o, 0),
NextValue(sbus_oe_int1, 0),
NextValue(sbus_oe_int7, 0),
NextValue(sbus_oe_data, 0),
NextValue(sbus_oe_slave_in, 0),
NextValue(sbus_oe_master_in, 0),
NextValue(sbus_oe_master_br, 0),
NextValue(p_data, 0),
#NextValue(leds, 0x0F),
NextState("Start")
)
slave_fsm.act("Start",
#NextValue(SBUS_DATA_OE_LED_o, 0),
#NextValue(SBUS_DATA_OE_LED_2_o, 0),
NextValue(sbus_oe_int1, 0),
NextValue(sbus_oe_int7, 0),
NextValue(sbus_oe_data, 0),
NextValue(sbus_oe_slave_in, 0),
NextValue(sbus_oe_master_in, 0),
NextValue(sbus_oe_master_br, 0),
NextValue(p_data, 0),
#NextValue(leds, 0x01),
If((self.hold_reset == 0), NextState("Idle"))
)
slave_fsm.act("Idle",
#NextValue(leds, 0x11),
If(((SBUS_3V3_SELs_i == 0) &
(SBUS_3V3_ASs_i == 0) &
(siz_is_word(SBUS_3V3_SIZ_i)) &
(SBUS_3V3_PPRD_i == 1) &
(SBUS_3V3_PA_i[0:2] == 0)),
#NextValue(SBUS_DATA_OE_LED_o, 1),
#NextValue(SBUS_DATA_OE_LED_2_o, 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),
SIZ_BURST2: NextValue(burst_limit_m1, 1),
SIZ_BURST4: NextValue(burst_limit_m1, 3),
SIZ_BURST8: NextValue(burst_limit_m1, 7),
SIZ_BURST16: NextValue(burst_limit_m1, 15)}),
If((SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == ROM_ADDR_PFX),
NextValue(SBUS_3V3_ACKs_o, ACK_WORD),
NextValue(SBUS_3V3_ERRs_o, 1),
NextValue(p_data, prom[SBUS_3V3_PA_i[ADDR_PHYS_LOW+2:ADDR_PFX_LOW]]),
NextValue(SBUS_DATA_OE_LED_o, 1),
NextState("Slave_Ack_Read_Prom_Burst")
).Elif((SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == WISHBONE_CSR_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(p_data, 0xDEADBEEF),
NextValue(data_read_addr, (Cat(SBUS_3V3_PA_i[2:], Signal(4, reset=0)))), # enqueue all the request to the wishbone
NextValue(data_read_enable, 1), # enqueue all the request to the wishbone
NextValue(SBUS_DATA_OE_LED_2_o, 1),
NextState("Slave_Ack_Read_Reg_Burst_Wait_For_Data")
).Else(
#NextValue(self.led_display.value, Cat(SBUS_3V3_PA_i, Signal(2, reset = 1), SBUS_3V3_PA_i[1:2], SBUS_3V3_PPRD_i)),
NextValue(SBUS_3V3_ACKs_o, ACK_ERR),
NextValue(SBUS_3V3_ERRs_o, 1),
NextState("Slave_Error")
)
).Elif(((SBUS_3V3_SELs_i == 0) &
(SBUS_3V3_ASs_i == 0) &
(SIZ_BYTE == SBUS_3V3_SIZ_i) &
(SBUS_3V3_PPRD_i == 1)),
#NextValue(SBUS_DATA_OE_LED_o, 0),
#NextValue(SBUS_DATA_OE_LED_2_o, 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),
NextValue(SBUS_3V3_ACKs_o, ACK_BYTE),
NextValue(SBUS_3V3_ERRs_o, 1),
NextValue(p_data, prom[SBUS_3V3_PA_i[ADDR_PHYS_LOW+2:ADDR_PFX_LOW]]),
NextState("Slave_Ack_Read_Prom_Byte")
).Else(
#NextValue(self.led_display.value, Cat(SBUS_3V3_PA_i, Signal(2, reset = 2), SBUS_3V3_PA_i[1:2], SBUS_3V3_PPRD_i)),
NextValue(SBUS_3V3_ACKs_o, ACK_ERR),
NextValue(SBUS_3V3_ERRs_o, 1),
NextState("Slave_Error")
)
).Elif(((SBUS_3V3_SELs_i == 0) &
(SBUS_3V3_ASs_i == 0) &
(siz_is_word(SBUS_3V3_SIZ_i)) &
(SBUS_3V3_PPRD_i == 0) &
(SBUS_3V3_PA_i[0:2] == 0) &
(self.wr_fifo.writable)), # maybe we should check for enough space? not that we'll encounter write burst...
#NextValue(SBUS_DATA_OE_LED_o, 1),
#NextValue(SBUS_DATA_OE_LED_2_o, 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),
SIZ_BURST2: NextValue(burst_limit_m1, 1),
SIZ_BURST4: NextValue(burst_limit_m1, 3),
SIZ_BURST8: NextValue(burst_limit_m1, 7),
SIZ_BURST16: NextValue(burst_limit_m1, 15)}),
If((SBUS_3V3_PA_i[ADDR_PFX_LOW:ADDR_PFX_LOW+ADDR_PFX_LENGTH] == WISHBONE_CSR_ADDR_PFX),
NextValue(SBUS_3V3_ACKs_o, ACK_WORD),
NextValue(SBUS_3V3_ERRs_o, 1),
NextState("Slave_Ack_Reg_Write_Burst")
).Else(
#NextValue(self.led_display.value, Cat(SBUS_3V3_PA_i, Signal(2, reset = 3), SBUS_3V3_PA_i[1:2], SBUS_3V3_PPRD_i)),
NextValue(SBUS_3V3_ACKs_o, ACK_ERR),
NextValue(SBUS_3V3_ERRs_o, 1),
NextState("Slave_Error")
)
)
)
# ##### READ #####
slave_fsm.act("Slave_Ack_Read_Prom_Burst",
#NextValue(leds, 0x03),
NextValue(sbus_oe_data, 1),
NextValue(SBUS_3V3_D_o, p_data),
#NextValue(burst_index, index_with_wrap((burst_counter+1), burst_limit_m1, sbus_last_pa[ADDR_PHYS_LOW+2:ADDR_PHYS_LOW+6])),
NextValue(p_data, prom[Cat(index_with_wrap((burst_counter+1), burst_limit_m1, sbus_last_pa[ADDR_PHYS_LOW+2:ADDR_PHYS_LOW+6]), sbus_last_pa[ADDR_PHYS_LOW+6:ADDR_PFX_LOW])]),
If((burst_counter == burst_limit_m1),
NextValue(SBUS_3V3_ACKs_o, ACK_IDLE),
NextState("Slave_Do_Read")
).Else(
NextValue(SBUS_3V3_ACKs_o, ACK_WORD),
NextValue(burst_counter, burst_counter + 1)
)
)
slave_fsm.act("Slave_Ack_Read_Prom_Byte",
#NextValue(leds, 0x0c),
NextValue(sbus_oe_data, 1),
#NextValue(self.led_display.value, sbus_last_pa[0:2]),
If((sbus_last_pa[0:2] == 0x0),
NextValue(SBUS_3V3_D_o, Cat(Signal(24), p_data[24:32]))
).Elif((sbus_last_pa[0:2] == 0x1),
NextValue(SBUS_3V3_D_o, Cat(Signal(24), p_data[16:24]))
).Elif((sbus_last_pa[0:2] == 0x2),
NextValue(SBUS_3V3_D_o, Cat(Signal(24), p_data[ 8:16]))
).Elif((sbus_last_pa[0:2] == 0x3),
NextValue(SBUS_3V3_D_o, Cat(Signal(24), p_data[ 0: 8]))
),
NextState("Slave_Do_Read")
)
slave_fsm.act("Slave_Do_Read",
#NextValue(leds, 0x30),
NextValue(sbus_oe_int1, 0),
NextValue(sbus_oe_int7, 0),
NextValue(sbus_oe_data, 0),
NextValue(sbus_oe_slave_in, 0),
NextValue(sbus_oe_master_in, 0),
NextValue(sbus_oe_master_br, 0),
If((SBUS_3V3_ASs_i == 1),
NextState("Idle")
)
)
slave_fsm.act("Slave_Ack_Read_Reg_Burst",
NextValue(sbus_oe_data, 1),
NextValue(SBUS_3V3_D_o, p_data),
If((burst_counter == burst_limit_m1),
NextValue(SBUS_3V3_ACKs_o, ACK_IDLE),
NextState("Slave_Do_Read")
).Else(
NextValue(burst_counter, burst_counter + 1),
If(rd_fifo_data.readable,
NextValue(p_data, rd_fifo_data.dout),
rd_fifo_data.re.eq(1),
NextValue(SBUS_3V3_ACKs_o, ACK_WORD)
).Else(
NextValue(SBUS_3V3_ACKs_o, ACK_IDLE),
NextState("Slave_Ack_Read_Reg_Burst_Wait_For_Data")
)
)
)
slave_fsm.act("Slave_Ack_Read_Reg_Burst_Wait_For_Data",
If(rd_fifo_data.readable,
NextValue(p_data, rd_fifo_data.dout),
rd_fifo_data.re.eq(1),
NextValue(SBUS_3V3_ACKs_o, ACK_WORD),
NextState("Slave_Ack_Read_Reg_Burst")
)
)
# ##### WRITE #####
slave_fsm.act("Slave_Ack_Reg_Write_Burst",
#NextValue(SBUS_DATA_OE_LED_o, 1),
#NextValue(SBUS_DATA_OE_LED_2_o, 1),
#NextValue(leds, 0x03),
#NextValue(burst_index, index_with_wrap((burst_counter+1), burst_limit_m1, sbus_last_pa[ADDR_PHYS_LOW+2:ADDR_PHYS_LOW+6])),
#NextValue(csr_data_w_addr, Cat(Signal(2, reset = 0),
# index_with_wrap(burst_counter, burst_limit_m1, sbus_last_pa[ADDR_PHYS_LOW+2:ADDR_PHYS_LOW+6]),
# sbus_last_pa[ADDR_PHYS_LOW+6:ADDR_PFX_LOW],
# WISHBONE_CSR_ADDR_PFX)),
#NextValue(csr_data_w_data, SBUS_3V3_D_i),
#NextValue(csr_data_w_addr, 0x00040000),
#NextValue(csr_data_w_we, 1),
self.wr_fifo.din.eq(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
WISHBONE_CSR_ADDR_PFX, # 12 bits, adr
Signal(4, reset = 0), # 4 bits, adr (could be removed)
SBUS_3V3_D_i)), # 32 bits, data
self.wr_fifo.we.eq(1),
If((burst_counter == burst_limit_m1),
NextValue(SBUS_3V3_ACKs_o, ACK_IDLE),
NextState("Slave_Ack_Reg_Write_Final")
).Else(
NextValue(SBUS_3V3_ACKs_o, ACK_WORD),
NextValue(burst_counter, burst_counter + 1)
)
)
slave_fsm.act("Slave_Ack_Reg_Write_Final",
#NextValue(SBUS_DATA_OE_LED_o, 1),
#NextValue(SBUS_DATA_OE_LED_2_o, 0),
NextValue(sbus_oe_int1, 0),
NextValue(sbus_oe_int7, 0),
NextValue(sbus_oe_data, 0),
NextValue(sbus_oe_slave_in, 0),
NextValue(sbus_oe_master_in, 0),
NextValue(sbus_oe_master_br, 0),
If((SBUS_3V3_ASs_i == 1),
NextState("Idle")
)
)
# ##### ERROR #####
slave_fsm.act("Slave_Error",
#NextValue(leds, 0xc0),
#NextValue(SBUS_DATA_OE_LED_o, 1),
#NextValue(SBUS_DATA_OE_LED_2_o, 1),
NextValue(sbus_oe_int1, 0),
NextValue(sbus_oe_int7, 0),
NextValue(sbus_oe_data, 0),
NextValue(sbus_oe_slave_in, 0),
NextValue(sbus_oe_master_in, 0),
NextValue(sbus_oe_master_br, 0),
If((SBUS_3V3_ASs_i == 1),
NextState("Idle")
)
)
self.submodules.request_fsm = request_fsm = FSM(reset_state="Reset")
request_fsm.act("Reset",
NextState("Idle")
)
request_fsm.act("Idle",
If(data_read_enable,
NextValue(data_read_enable, 0),
self.rd_fifo_addr.we.eq(1),
self.rd_fifo_addr.din.eq(data_read_addr),
If (burst_limit_m1 != burst_counter, # 0 the first time
NextValue(burst_counter, burst_counter + 1),
NextState("Queue")
)
)
)
request_fsm.act("Queue",
self.rd_fifo_addr.we.eq(1),
self.rd_fifo_addr.din.eq(Cat(index_with_wrap(burst_counter, burst_limit_m1, data_read_addr[0:4]), data_read_addr[4:])),
If (burst_limit_m1 != burst_counter,
NextValue(burst_counter, burst_counter + 1),
).Else(
NextState("Idle")
)
)