diff --git a/sbus-to-ztex-gateware-migen/sbus-to-fpga.py b/sbus-to-ztex-gateware-migen/sbus-to-fpga.py index 57b0653..770cfa6 100644 --- a/sbus-to-ztex-gateware-migen/sbus-to-fpga.py +++ b/sbus-to-ztex-gateware-migen/sbus-to-fpga.py @@ -10,8 +10,10 @@ 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")), @@ -38,39 +40,34 @@ 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_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_sys.clk = clk_sbus + self.cd_sbus.clk = clk_sbus rst_sbus = platform.request("SBUS_3V3_RSTs") - #self.submodules.pll = pll = S7MMCM(speedgrade=-1) - #pll.register_clkin(clk48, 48e6) - #pll.create_clkout(self.cd_sys, sys_clk_freq) + self.comb += self.cd_sbus.rst.eq(~rst_sbus) - #self.comb += self.cd_sbus.clk.eq(clk_sbus) - #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) - #self.comb += self.cd_sys.clk.eq(clk_sbus) - self.comb += self.cd_sys.rst.eq(~rst_sbus) - - #self.comb += self.cd_native.clk.eq(clk48) - - #platform.add_false_path_constraints(self.cd_native.clk, self.cd_sbus.clk) - platform.add_false_path_constraints(self.cd_native.clk, self.cd_sys.clk) - platform.add_false_path_constraints(self.cd_sys.clk, self.cd_native.clk) - - # Power on reset, 20 seconds - #por_count = Signal(30, reset=20*48*1000000) - #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) + # 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): @@ -80,7 +77,7 @@ class SBusFPGA(SoCCore): kwargs["with_uart"] = True kwargs["with_timer"] = False - self.sys_clk_freq = sys_clk_freq = 25e6 # SBus max + self.sys_clk_freq = sys_clk_freq = 100e6 self.platform = platform = ztex213.Platform(variant="ztex2.13a", expansion="sbus") self.platform.add_extension(_sbus_sbus) @@ -91,7 +88,7 @@ class SBusFPGA(SoCCore): } 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) + 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"), @@ -113,19 +110,27 @@ class SBusFPGA(SoCCore): # 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)) - - #self.submodules.sbus_slave = ClockDomainsRenamer("sbus")(SBusFPGASlave(platform=self.platform, soc=self, prom=prom, hold_reset=hold_reset)) - self.submodules.sbus_slave = SBusFPGASlave(platform=self.platform, - prom=prom, - hold_reset=hold_reset, - wishbone=wishbone.Interface(data_width=self.bus.data_width), - chaser=self.leds) - self.bus.add_master(name="SBusBridgeToWishbone", master=self.sbus_slave.wishbone) + + + + sbus_to_wishbone_fifo = AsyncFIFOBuffered(width=32+30, depth=8) + sbus_to_wishbone_fifo = ClockDomainsRenamer({"write": "sbus", "read": "sys"})(sbus_to_wishbone_fifo) + self.submodules += sbus_to_wishbone_fifo + self.submodules.sbus_to_wishbone = SBusToWishbone(fifo=sbus_to_wishbone_fifo, wishbone=wishbone.Interface(data_width=self.bus.data_width)) + + _sbus_slave = SBusFPGASlave(platform=self.platform, + prom=prom, + hold_reset=hold_reset, + write_fifo=sbus_to_wishbone_fifo) + 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 = {} diff --git a/sbus-to-ztex-gateware-migen/sbus_to_fpga_slave.py b/sbus-to-ztex-gateware-migen/sbus_to_fpga_slave.py index 21ecb57..d30911f 100644 --- a/sbus-to-ztex-gateware-migen/sbus_to_fpga_slave.py +++ b/sbus-to-ztex-gateware-migen/sbus_to_fpga_slave.py @@ -1,8 +1,6 @@ from migen import * -from migen.genlib.fifo import SyncFIFOBuffered from migen.fhdl.specials import Tristate -from litex.soc.interconnect import wishbone SIZ_WORD = 0x0 SIZ_BYTE = 0x1 @@ -33,7 +31,7 @@ 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 1 +# 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] @@ -146,11 +144,10 @@ class LedDisplay(Module): ) class SBusFPGASlave(Module): - def __init__(self, platform, prom, hold_reset, wishbone, chaser): + def __init__(self, platform, prom, hold_reset, write_fifo): self.platform = platform self.hold_reset = hold_reset - self.wishbone = wishbone - self.chaser = chaser + self.write_fifo = write_fifo #self.submodules.led_display = LedDisplay(pads=platform.request_all("user_led")) @@ -238,9 +235,9 @@ class SBusFPGASlave(Module): p_data = Signal(32) # prom data to read - csr_data_w_data = Signal(32) # csr data to write - csr_data_w_addr = Signal(32) # address thereof - csr_data_w_we = Signal(reset = 0) # write enable + #csr_data_w_data = Signal(32) # csr data to write + #csr_data_w_addr = Signal(32) # address thereof + #csr_data_w_we = Signal(reset = 0) # write enable slave_fsm.act("Reset", #NextValue(SBUS_DATA_OE_LED_o, 0), @@ -326,7 +323,8 @@ class SBusFPGASlave(Module): (SBUS_3V3_ASs_i == 0) & (siz_is_word(SBUS_3V3_SIZ_i)) & (SBUS_3V3_PPRD_i == 0) & - (SBUS_3V3_PA_i[0:2] == 0)), + (SBUS_3V3_PA_i[0:2] == 0) & + (self.write_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), @@ -418,13 +416,19 @@ class SBusFPGASlave(Module): #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_data, SBUS_3V3_D_i), #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_addr, 0x00040000), - NextValue(csr_data_w_we, 1), + #NextValue(csr_data_w_data, SBUS_3V3_D_i), + #NextValue(csr_data_w_addr, 0x00040000), + #NextValue(csr_data_w_we, 1), + self.write_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.write_fifo.we.eq(1), If((burst_counter == burst_limit_m1), NextValue(SBUS_3V3_ACKs_o, ACK_IDLE), NextState("Slave_Ack_Reg_Write_Final") @@ -461,35 +465,3 @@ class SBusFPGASlave(Module): NextState("Idle") ) ) - - # ##### Iface to WB ##### - self.submodules.wb_fsm = wb_fsm = FSM(reset_state="Reset") - wb_fsm.act("Reset", - self.wishbone.we.eq(0), - self.wishbone.cyc.eq(0), - self.wishbone.stb.eq(0), - NextState("Idle") - ) - wb_fsm.act("Idle", - If(csr_data_w_we == 1, - #NextValue(SBUS_DATA_OE_LED_o, 0), - NextValue(SBUS_DATA_OE_LED_2_o, 1), - NextValue(csr_data_w_we, 0), - NextState("Write") - ) - ) - wb_fsm.act("Write", - self.wishbone.adr.eq(csr_data_w_addr[2:32]), - self.wishbone.dat_w.eq(csr_data_w_data), - self.wishbone.we.eq(1), - self.wishbone.cyc.eq(1), - self.wishbone.stb.eq(1), - self.wishbone.sel.eq(2**len(self.wishbone.sel)-1), - If(self.wishbone.ack == 1, - NextValue(SBUS_DATA_OE_LED_o, 1), - self.wishbone.we.eq(0), - self.wishbone.cyc.eq(0), - self.wishbone.stb.eq(0), - NextState("Idle") - ) - ) diff --git a/sbus-to-ztex-gateware-migen/sbus_to_fpga_wishbone.py b/sbus-to-ztex-gateware-migen/sbus_to_fpga_wishbone.py new file mode 100644 index 0000000..2b20b3d --- /dev/null +++ b/sbus-to-ztex-gateware-migen/sbus_to_fpga_wishbone.py @@ -0,0 +1,42 @@ + +from migen import * +from litex.soc.interconnect import wishbone + +class SBusToWishbone(Module): + def __init__(self, fifo, wishbone): + self.fifo = fifo + self.wishbone = wishbone + + data = Signal(32) + adr = Signal(30) + + # ##### Iface to WB ##### + self.submodules.wb_fsm = wb_fsm = FSM(reset_state="Reset") + wb_fsm.act("Reset", + self.wishbone.we.eq(0), + self.wishbone.cyc.eq(0), + self.wishbone.stb.eq(0), + NextState("Idle") + ) + wb_fsm.act("Idle", + If(fifo.readable & ~self.wishbone.cyc, + fifo.re.eq(1), + NextValue(adr, fifo.dout[0:30]), + NextValue(data, fifo.dout[30:62]), + NextState("Write") + ) + ) + wb_fsm.act("Write", + self.wishbone.adr.eq(adr), + self.wishbone.dat_w.eq(data), + self.wishbone.we.eq(1), + self.wishbone.cyc.eq(1), + self.wishbone.stb.eq(1), + self.wishbone.sel.eq(2**len(self.wishbone.sel)-1), + If(self.wishbone.ack == 1, + self.wishbone.we.eq(0), + self.wishbone.cyc.eq(0), + self.wishbone.stb.eq(0), + NextState("Idle") + ) + )