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 cac43c0..79b9471 100644 --- a/sbus-to-ztex-gateware-migen/sbus_to_fpga_fsm.py +++ b/sbus-to-ztex-gateware-migen/sbus_to_fpga_fsm.py @@ -64,20 +64,21 @@ def siz_to_burst_size_m1(siz): return 1 class LedDisplay(Module): - def __init__(self, pads): - n = len(pads) + def __init__(self): #, pads + #n = len(pads) + n = 8 self.value = Signal(32, reset = 0x18244281) old_value = Signal(32) - display = Signal(8) + self.display = Signal(8) + #self.comb += pads.eq(self.display) 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(self.display, 0x00), NextValue(old_value, self.value), NextState("Quick")) fsm.act("Quick", @@ -86,10 +87,10 @@ class LedDisplay(Module): ).Elif(time_counter == 0, If (blink_counter == 0, NextValue(time_counter, 25000000//2), - NextValue(display, self.value[0:8]), + NextValue(self.display, self.value[0:8]), NextState("Byte0") ).Else( - NextValue(display, ~display), + NextValue(self.display, ~self.display), NextValue(time_counter, 25000000//10), NextValue(blink_counter, blink_counter - 1) ) @@ -102,7 +103,7 @@ class LedDisplay(Module): NextState("Reset") ).Elif(time_counter == 0, NextValue(time_counter, 25000000//2), - NextValue(display, self.value[8:16]), + NextValue(self.display, self.value[8:16]), NextState("Byte1") ).Else( NextValue(time_counter, time_counter - 1) @@ -113,7 +114,7 @@ class LedDisplay(Module): NextState("Reset") ).Elif(time_counter == 0, NextValue(time_counter, 25000000//2), - NextValue(display, self.value[16:24]), + NextValue(self.display, self.value[16:24]), NextState("Byte2") ).Else( NextValue(time_counter, time_counter - 1) @@ -124,7 +125,7 @@ class LedDisplay(Module): NextState("Reset") ).Elif(time_counter == 0, NextValue(time_counter, 25000000//2), - NextValue(display, self.value[24:32]), + NextValue(self.display, self.value[24:32]), NextState("Byte3") ).Else( NextValue(time_counter, time_counter - 1) @@ -136,7 +137,7 @@ class LedDisplay(Module): ).Elif(time_counter == 0, NextValue(time_counter, 25000000//10), NextValue(blink_counter, 10), - NextValue(display, 0x00), + NextValue(self.display, 0x00), NextState("Quick") ).Else( NextValue(time_counter, time_counter - 1) @@ -144,26 +145,36 @@ class LedDisplay(Module): ) class SBusFPGABus(Module): - def __init__(self, platform, prom, hold_reset, wr_fifo, rd_fifo_addr, rd_fifo_data): + def __init__(self, platform, prom, hold_reset, wr_fifo, rd_fifo_addr, rd_fifo_data, master_wr_fifo, master_rd_fifo_addr, master_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")) + self.master_wr_fifo = master_wr_fifo + self.master_rd_fifo_addr = master_rd_fifo_addr + self.master_rd_fifo_data = master_rd_fifo_data + + ##pad_SBUS_DATA_OE_LED = platform.request("SBUS_DATA_OE_LED") + ##SBUS_DATA_OE_LED_o = Signal() + ##self.comb += pad_SBUS_DATA_OE_LED.eq(SBUS_DATA_OE_LED_o) + ##pad_SBUS_DATA_OE_LED_2 = platform.request("SBUS_DATA_OE_LED_2") + ##SBUS_DATA_OE_LED_2_o = Signal() + ##self.comb += pad_SBUS_DATA_OE_LED_2.eq(SBUS_DATA_OE_LED_2_o) + + #self.comb += SBUS_DATA_OE_LED_o.eq(~rd_fifo_addr.writable) + #self.comb += SBUS_DATA_OE_LED_2_o.eq(rd_fifo_data.readable) #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_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") @@ -176,9 +187,9 @@ class SBusFPGABus(Module): 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_int1 = Signal(reset=0) sbus_oe_int7 = Signal(reset=0) - sbus_oe_master_br = Signal(reset=0) + #sbus_oe_master_br = Signal(reset=0) sbus_last_pa = Signal(28) burst_index = Signal(4) @@ -191,21 +202,18 @@ class SBusFPGABus(Module): 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) + #self.specials += Tristate(pad_SBUS_3V3_BRs, SBUS_3V3_BRs_o, sbus_oe_master_br, None) + self.comb += pad_SBUS_3V3_BRs.eq(SBUS_3V3_BRs_o) 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_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) @@ -230,35 +238,51 @@ class SBusFPGABus(Module): data_read_timeout = Signal(7) data_read_stale = Signal(5, reset = 0) + master_data = Signal(32) # could be merged with p_data + master_addr = Signal(30) # could be meged with data_read_addr + + master_we = Signal(); + +# self.submodules.led_display = LedDisplay() +# #self.comb += self.led_display.value.eq(Cat(Signal(2, reset=0), master_addr)) +# self.comb += self.led_display.value.eq(p_data) +# old_display = Signal(8) +# self.sync += old_display.eq(self.led_display.display) +# self.submodules.display_fsm = display_fsm = FSM(reset_state="Reset") +# display_fsm.act("Reset", +# NextState("Idle")) +# display_fsm.act("Idle", +# If(old_display != self.led_display.display, +# NextState("Update"))) +# display_fsm.act("Update", +# If(self.wr_fifo.writable & SBUS_3V3_ASs_i, ## available space and not in a slave cycle +# self.wr_fifo.we.eq(1), +# self.wr_fifo.din.eq(Cat(Signal(30, reset=0x00040000), self.led_display.display, Signal(24, reset=0))), +# NextState("Idle"))) + # clean the read FIFO from stale data self.submodules.cleaning_fsm = cleaning_fsm = FSM(reset_state="Reset") cleaning_fsm.act("Reset", NextState("Idle")) cleaning_fsm.act("Idle", - If(rd_fifo_data.readable & (data_read_stale != 0), - rd_fifo_data.re.eq(1), + If(self.rd_fifo_data.readable & (data_read_stale != 0), + self.rd_fifo_data.re.eq(1), NextValue(data_read_stale, data_read_stale - 1))) - self.comb += SBUS_DATA_OE_LED_o.eq(data_read_stale != 0) + #self.comb += SBUS_DATA_OE_LED_o.eq(data_read_stale != 0) self.submodules.slave_fsm = slave_fsm = FSM(reset_state="Reset") slave_fsm.act("Reset", - 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), NextState("Start") ) slave_fsm.act("Start", - 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), If((self.hold_reset == 0), NextState("Idle")) ) @@ -296,7 +320,7 @@ class SBusFPGABus(Module): 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(data_read_timeout, 0xFF), + NextValue(data_read_timeout, 0x7F), NextState("Slave_Ack_Read_Reg_Burst_Wait_For_Data") ).Else( NextValue(SBUS_3V3_ACKs_o, ACK_ERR), @@ -315,7 +339,6 @@ class SBusFPGABus(Module): 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") @@ -345,9 +368,39 @@ class SBusFPGABus(Module): NextValue(SBUS_3V3_ERRs_o, 1), NextState("Slave_Error") ) + ).Elif(SBUS_3V3_BGs_i & + (self.master_wr_fifo.readable | self.master_rd_fifo_addr.readable), + NextValue(SBUS_3V3_BRs_o, 0) + ).Elif(~SBUS_3V3_BGs_i & + (self.master_wr_fifo.readable | self.master_rd_fifo_addr.readable), + NextValue(SBUS_3V3_BRs_o, 1), # relinquish the request + NextValue(sbus_oe_data, 1), ## output data (at least for @ during translation) + NextValue(sbus_oe_slave_in, 1), ## PPRD, SIZ becomes output + NextValue(sbus_oe_master_in, 0), ## ERRs, ACKs are input + NextValue(burst_counter, 0), + NextValue(burst_limit_m1, 0), ## only single word for now + If(self.master_wr_fifo.readable, + NextValue(master_addr, self.master_wr_fifo.dout[0:30]), + NextValue(master_data, self.master_wr_fifo.dout[30:32]), + self.master_wr_fifo.re.eq(1), + NextValue(SBUS_3V3_D_o, Cat(Signal(2, reset = 0), self.master_wr_fifo.dout[0:30])), + NextValue(SBUS_3V3_PPRD_o, 0), + NextValue(master_we, 1), + NextState("Master_Translation") + ).Elif(self.master_rd_fifo_addr.readable, + NextValue(master_addr, self.master_rd_fifo_addr.dout), + self.master_rd_fifo_addr.re.eq(1), + NextValue(SBUS_3V3_D_o, Cat(Signal(2, reset = 0), self.master_rd_fifo_addr.dout[0:30])), + NextValue(SBUS_3V3_PPRD_o, 1), + NextValue(master_we, 0), + NextState("Master_Translation") + ).Else( + # FIXME: handle error + ) + ) ) - # ##### READ ##### + # ##### SLAVE READ ##### slave_fsm.act("Slave_Ack_Read_Prom_Burst", NextValue(sbus_oe_data, 1), NextValue(SBUS_3V3_D_o, p_data), @@ -374,12 +427,9 @@ class SBusFPGABus(Module): NextState("Slave_Do_Read") ) slave_fsm.act("Slave_Do_Read", - 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") ) @@ -392,13 +442,14 @@ class SBusFPGABus(Module): NextState("Slave_Do_Read") ).Else( NextValue(burst_counter, burst_counter + 1), - If(rd_fifo_data.readable, - If(rd_fifo_data.dout[32] == 0, - NextValue(p_data, rd_fifo_data.dout), - rd_fifo_data.re.eq(1), + If(self.rd_fifo_data.readable, + If(self.rd_fifo_data.dout[32] == 0, + NextValue(p_data, self.rd_fifo_data.dout), + self.rd_fifo_data.re.eq(1), NextValue(SBUS_3V3_ACKs_o, ACK_WORD) ).Else( - rd_fifo_data.re.eq(1), + self.rd_fifo_data.re.eq(1), + NextValue(p_data, self.rd_fifo_data.dout), NextValue(SBUS_3V3_ACKs_o, ACK_RERUN), NextValue(data_read_stale, burst_limit_m1 - burst_counter), NextState("Slave_Do_Read"), @@ -411,18 +462,27 @@ class SBusFPGABus(Module): ) slave_fsm.act("Slave_Ack_Read_Reg_Burst_Wait_For_Data", NextValue(data_read_timeout, data_read_timeout - 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), - NextState("Slave_Ack_Read_Reg_Burst") + If(self.rd_fifo_data.readable, + If(self.rd_fifo_data.dout[32] == 0, + NextValue(p_data, self.rd_fifo_data.dout), + self.rd_fifo_data.re.eq(1), + NextValue(SBUS_3V3_ACKs_o, ACK_WORD), + NextState("Slave_Ack_Read_Reg_Burst") + ).Else( + self.rd_fifo_data.re.eq(1), + NextValue(p_data, self.rd_fifo_data.dout), + NextValue(SBUS_3V3_ACKs_o, ACK_RERUN), + NextValue(data_read_stale, burst_limit_m1 - burst_counter), + NextState("Slave_Do_Read"), + ) ).Elif(data_read_timeout == 0, - NextValue(SBUS_3V3_ACKs_o, ACK_RERUN), - NextValue(data_read_stale, 1 + burst_limit_m1 - burst_counter), - NextState("Slave_Do_Read") + NextValue(p_data, 0x00C0FFEE), + NextValue(SBUS_3V3_ACKs_o, ACK_RERUN), + NextValue(data_read_stale, 1 + burst_limit_m1 - burst_counter), + NextState("Slave_Do_Read") ) ) - # ##### WRITE ##### + # ##### SLAVE WRITE ##### slave_fsm.act("Slave_Ack_Reg_Write_Burst", 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 @@ -439,30 +499,148 @@ class SBusFPGABus(Module): ) ) slave_fsm.act("Slave_Ack_Reg_Write_Final", - 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 ERROR ##### slave_fsm.act("Slave_Error", - 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") ) ) + # ##### MASTER ##### + slave_fsm.act("Master_Translation", + If(master_we, + NextValue(sbus_oe_data, 1), + NextValue(SBUS_3V3_D_o, master_data) + ).Else( + NextValue(sbus_oe_data, 0) + ), + Case(SBUS_3V3_ACKs_i, { + ACK_ERR: ## ouch + [NextValue(sbus_oe_data, 0), + NextValue(sbus_oe_slave_in, 0), + NextValue(sbus_oe_master_in, 0), + NextState("Idle")], + ACK_RERUN: ### dunno how to handle that yet, maybe delay the fifo re(1)? + [NextValue(sbus_oe_data, 0), + NextValue(sbus_oe_slave_in, 0), + NextValue(sbus_oe_master_in, 0), + NextState("Idle")], + ACK_IDLE: + [If(master_we, + NextState("Master_Write"), + ## FIXME: in burst mode, should update master_data with the next value + ## FIXME: we don't do burst mode yet + ).Else( + NextState("Master_Read"), + )], + "default": + [If(SBUS_3V3_BGs_i, ## oups, we lost our bus access without error ?!? + NextValue(sbus_oe_data, 0), + NextValue(sbus_oe_slave_in, 0), + NextValue(sbus_oe_master_in, 0), + NextState("Idle") + )], + }) + ) + slave_fsm.act("Master_Read", + Case(SBUS_3V3_ACKs_i, { + ACK_WORD: + [NextState("Master_Read_Ack") + ], + ACK_IDLE: + [NextState("Master_Read") ## redundant + ], + ACK_RERUN: ### dunno how to handle that yet, maybe delay the fifo re(1)? + [NextValue(sbus_oe_data, 0), + NextValue(sbus_oe_slave_in, 0), + NextValue(sbus_oe_master_in, 0), + NextState("Idle") + ], + "default": ## ACK_ERRS or other + [NextValue(sbus_oe_data, 0), + NextValue(sbus_oe_slave_in, 0), + NextValue(sbus_oe_master_in, 0), + NextState("Idle") + ], + }) + ) + slave_fsm.act("Master_Read_Ack", + self.master_rd_fifo_data.we.eq(1), + NextValue(self.master_rd_fifo_data.din, SBUS_3V3_D_i), + NextValue(burst_counter, burst_counter + 1), + If(burst_counter == burst_limit_m1, + NextState("Master_Read_Finish") + ).Else( + Case(SBUS_3V3_ACKs_i, { + ACK_WORD: NextState("Master_Read_Ack"), ## redundant + ACK_IDLE: NextState("Master_Read"), + ACK_RERUN: ### dunno how to handle that yet, maybe delay the fifo re(1)? + [NextValue(sbus_oe_data, 0), + NextValue(sbus_oe_slave_in, 0), + NextValue(sbus_oe_master_in, 0), + NextState("Idle") + ], + "default": + [NextValue(sbus_oe_data, 0), + NextValue(sbus_oe_slave_in, 0), + NextValue(sbus_oe_master_in, 0), + NextState("Idle") + ], + }), + ) + ) + slave_fsm.act("Master_Read_Finish", ## missing the handling of late error + NextValue(sbus_oe_data, 0), + NextValue(sbus_oe_slave_in, 0), + NextValue(sbus_oe_master_in, 0), + NextState("Idle") + ) + slave_fsm.act("Master_Write", + Case(SBUS_3V3_ACKs_i, { + ACK_WORD: + [If(burst_counter == burst_limit_m1, + NextState("Master_Write_Final"), + ).Else( + NextValue(SBUS_3V3_D_o, master_data), ## FIXME: we're not updating master_data for burst mode yet + NextValue(burst_counter, burst_counter + 1), + )], + ACK_IDLE: + [NextState("Master_Write") ## redundant + ], + ACK_RERUN: ### dunno how to handle that yet, maybe delay the fifo re(1)? + [NextValue(sbus_oe_data, 0), + NextValue(sbus_oe_slave_in, 0), + NextValue(sbus_oe_master_in, 0), + NextState("Idle") + ], + "default": ## ACK_ERRS or other + [NextValue(sbus_oe_data, 0), + NextValue(sbus_oe_slave_in, 0), + NextValue(sbus_oe_master_in, 0), + NextState("Idle") + ], + }) + ) + slave_fsm.act("Master_Write_Final", + NextValue(sbus_oe_data, 0), + NextValue(sbus_oe_slave_in, 0), + NextValue(sbus_oe_master_in, 0), + NextState("Idle") + ) + # ##### FINISHED ##### self.submodules.request_fsm = request_fsm = FSM(reset_state="Reset") + req_counter = Signal(4) + req_limit_m1 = Signal(4) request_fsm.act("Reset", NextState("Idle") ) @@ -472,16 +650,17 @@ class SBusFPGABus(Module): 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), + NextValue(req_counter, burst_counter + 1), + NextValue(req_limit_m1, burst_limit_m1), 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), + self.rd_fifo_addr.din.eq(Cat(index_with_wrap(req_counter, req_limit_m1, data_read_addr[0:4]), data_read_addr[4:])), + If(req_limit_m1 != req_counter, + NextValue(req_counter, req_counter + 1), ).Else( NextState("Idle") ) 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 89323e8..85d5ea2 100644 --- a/sbus-to-ztex-gateware-migen/sbus_to_fpga_soc.py +++ b/sbus-to-ztex-gateware-migen/sbus_to_fpga_soc.py @@ -37,8 +37,8 @@ _sbus_sbus = [ _usb_io = [ ("usb", 0, - Subsignal("dp", Pins("E3")), # Serial TX - Subsignal("dm", Pins("F3")), # Serial RX + Subsignal("dp", Pins("V9")), # Serial TX + Subsignal("dm", Pins("U9")), # Serial RX IOStandard("LVCMOS33")) ] # CRG ---------------------------------------------------------------------------------------------- @@ -99,9 +99,10 @@ class SBusFPGA(SoCCore): self.platform.add_extension(_usb_io) SoCCore.__init__(self, platform=platform, sys_clk_freq=sys_clk_freq, clk_freq=sys_clk_freq, **kwargs) wb_mem_map = { - "prom": 0x00000000, - "csr" : 0x00040000, - "usb_host": 0x00080000, + "prom": 0x00000000, + "csr" : 0x00040000, + "usb_host": 0x00080000, + "usb_fake_dma": 0x000c0000, } self.mem_map.update(wb_mem_map) self.submodules.crg = _CRG(platform=platform, sys_clk_freq=sys_clk_freq) @@ -114,6 +115,24 @@ class SBusFPGA(SoCCore): self.add_usb_host(pads=platform.request("usb"), usb_clk_freq=48e6) #self.comb += self.cpu.interrupt[16].eq(self.usb_host.interrupt) #fixme: need to deal with interrupts + + pad_SBUS_3V3_INT1s = platform.request("SBUS_3V3_INT1s") + SBUS_3V3_INT1s_o = Signal(reset=1) + # the 74LVC2G07 takes care of the Z state: 1 -> Z on the bus, 0 -> 0 on the bus (asserted interrupt) + self.comb += pad_SBUS_3V3_INT1s.eq(SBUS_3V3_INT1s_o) + self.comb += SBUS_3V3_INT1s_o.eq(~self.usb_host.interrupt) + + + pad_SBUS_DATA_OE_LED = platform.request("SBUS_DATA_OE_LED") + SBUS_DATA_OE_LED_o = Signal() + self.comb += pad_SBUS_DATA_OE_LED.eq(SBUS_DATA_OE_LED_o) + #pad_SBUS_DATA_OE_LED_2 = platform.request("SBUS_DATA_OE_LED_2") + #SBUS_DATA_OE_LED_2_o = Signal() + #self.comb += pad_SBUS_DATA_OE_LED_2.eq(SBUS_DATA_OE_LED_2_o) + interrupt_memory = Signal() + self.sync += interrupt_memory.eq(interrupt_memory | ~SBUS_3V3_INT1s_o) + self.comb += SBUS_DATA_OE_LED_o.eq(interrupt_memory) + #self.comb += SBUS_DATA_OE_LED_2_o.eq(~SBUS_3V3_INT1s_o) prom_file = "prom_migen.fc" prom_data = soc_core.get_mem_data(prom_file, "big") @@ -150,24 +169,50 @@ class SBusFPGA(SoCCore): 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 - # SBus to Wishbone FSM, 'Slave' on the SBus side, 'Master' on the Wishbone side + # SBus to Wishbone, 'Slave' on the SBus side, 'Master' on the Wishbone side self.submodules.sbus_to_wishbone = SBusToWishbone(platform=self.platform, 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)) + + # FIFO to send data & address from Wishbone to the SBus + wishbone_to_sbus_wr_fifo = AsyncFIFOBuffered(width=32+30, depth=16) + wishbone_to_sbus_wr_fifo = ClockDomainsRenamer({"write": "sys", "read": "sbus"})(wishbone_to_sbus_wr_fifo) + self.submodules += wishbone_to_sbus_wr_fifo + + # FIFOs to send address / receive data from Wishbone to the SBus + wishbone_to_sbus_rd_fifo_addr = AsyncFIFOBuffered(width=30, depth=4) + wishbone_to_sbus_rd_fifo_addr = ClockDomainsRenamer({"write": "sys", "read": "sbus"})(wishbone_to_sbus_rd_fifo_addr) + self.submodules += wishbone_to_sbus_rd_fifo_addr + wishbone_to_sbus_rd_fifo_data = AsyncFIFOBuffered(width=32, depth=4) + wishbone_to_sbus_rd_fifo_data = ClockDomainsRenamer({"write": "sbus", "read": "sys"})(wishbone_to_sbus_rd_fifo_data) + self.submodules += wishbone_to_sbus_rd_fifo_data + + # Wishbone to SBus, 'Master' on the SBus side, 'Slave' on the Wishbone side + self.submodules.wishbone_to_sbus = WishboneToSBus(platform=self.platform, + soc=self, + wr_fifo=wishbone_to_sbus_wr_fifo, + rd_fifo_addr=wishbone_to_sbus_rd_fifo_addr, + rd_fifo_data=wishbone_to_sbus_rd_fifo_data, + wishbone=wishbone.Interface(data_width=self.bus.data_width)) + _sbus_bus = SBusFPGABus(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,) + 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, + master_wr_fifo=wishbone_to_sbus_wr_fifo, + master_rd_fifo_addr=wishbone_to_sbus_rd_fifo_addr, + master_rd_fifo_data=wishbone_to_sbus_rd_fifo_data) self.submodules.sbus_bus = ClockDomainsRenamer("sbus")(_sbus_bus) self.bus.add_master(name="SBusBridgeToWishbone", master=self.sbus_to_wishbone.wishbone) - - # self.soc = Module() + self.bus.add_slave(name="usb_fake_dma", slave=self.wishbone_to_sbus.wishbone, region=SoCRegion(origin=self.mem_map.get("usb_fake_dma", None), size=0x10000, cached=False)) + +# self.soc = Module() # self.soc.mem_regions = self.mem_regions = {} # region = litex.soc.integration.soc.SoCRegion(origin=0x0, size=0x0) # region.length = 0 diff --git a/sbus-to-ztex-gateware-migen/sbus_to_fpga_wishbone.py b/sbus-to-ztex-gateware-migen/sbus_to_fpga_wishbone.py index 73132bf..063a0c5 100644 --- a/sbus-to-ztex-gateware-migen/sbus_to_fpga_wishbone.py +++ b/sbus-to-ztex-gateware-migen/sbus_to_fpga_wishbone.py @@ -2,6 +2,7 @@ from migen import * from litex.soc.interconnect import wishbone +# ******************************************************************************************************** class SBusToWishbone(Module): def __init__(self, platform, wr_fifo, rd_fifo_addr, rd_fifo_data, wishbone): self.platform = platform @@ -10,6 +11,9 @@ class SBusToWishbone(Module): self.rd_fifo_data = rd_fifo_data self.wishbone = wishbone + #pad_SBUS_DATA_OE_LED = platform.request("SBUS_DATA_OE_LED") + #SBUS_DATA_OE_LED_o = Signal() + #self.comb += pad_SBUS_DATA_OE_LED.eq(SBUS_DATA_OE_LED_o) pad_SBUS_DATA_OE_LED_2 = platform.request("SBUS_DATA_OE_LED_2") SBUS_DATA_OE_LED_2_o = Signal() self.comb += pad_SBUS_DATA_OE_LED_2.eq(SBUS_DATA_OE_LED_2_o) @@ -17,8 +21,10 @@ class SBusToWishbone(Module): data = Signal(32) adr = Signal(30) timeout = Signal(7) + + self.real_hcca = Signal(32) - # ##### FSM: write to WB ##### + # ##### FSM: read/write from/to WB ##### self.submodules.fsm = fsm = FSM(reset_state="Reset") fsm.act("Reset", self.wishbone.we.eq(0), @@ -27,21 +33,30 @@ class SBusToWishbone(Module): NextState("Idle") ) fsm.act("Idle", - If (rd_fifo_addr.readable & ~self.wishbone.cyc & self.rd_fifo_data.writable, - rd_fifo_addr.re.eq(1), - NextValue(adr, self.rd_fifo_addr.dout[0:30]), - NextValue(timeout, 127), - NextState("Read") - ).Elif(self.wr_fifo.readable & ~self.wishbone.cyc, - self.wr_fifo.re.eq(1), - NextValue(adr, self.wr_fifo.dout[0:30]), - NextValue(data, self.wr_fifo.dout[30:62]), - NextValue(timeout, 127), - NextState("Write") + # write first, we don't want a read to pass before a previous write + If(self.wr_fifo.readable & ~self.wishbone.cyc, + self.wr_fifo.re.eq(1), + NextValue(adr, self.wr_fifo.dout[0:30]), + ## need to cheat with the USB HCCA registers + If((self.wr_fifo.dout[0:30] == 0x00020006), ## 80018 >> 2 == HCCA register for USB + NextValue(SBUS_DATA_OE_LED_2_o, 1), + NextValue(self.real_hcca, self.wr_fifo.dout[30:62]), + NextValue(data, Cat(self.wr_fifo.dout[30:46], Signal(16, reset=0x000c))) ## 0x000c: are reserved for DMA bridging + ).Elif((self.wr_fifo.dout[0:30] >= 0x00020007) & (self.wr_fifo.dout[0:30] <= 0x0002000c) & (self.wr_fifo.dout[30:62] != 0), + NextValue(data, Cat(self.wr_fifo.dout[30:46], Signal(16, reset=0x000c))) + ).Else( + NextValue(data, self.wr_fifo.dout[30:62]) + ), + NextValue(timeout, 127), + NextState("Write") + ).Elif (rd_fifo_addr.readable & ~self.wishbone.cyc & self.rd_fifo_data.writable, + rd_fifo_addr.re.eq(1), + NextValue(adr, self.rd_fifo_addr.dout[0:30]), + NextValue(timeout, 127), + NextState("Read") ) ) fsm.act("Write", - SBUS_DATA_OE_LED_2_o.eq(1), self.wishbone.adr.eq(adr), self.wishbone.dat_w.eq(data), self.wishbone.we.eq(1), @@ -62,7 +77,6 @@ class SBusToWishbone(Module): ) ) fsm.act("Read", - SBUS_DATA_OE_LED_2_o.eq(1), self.wishbone.adr.eq(adr), self.wishbone.we.eq(0), self.wishbone.cyc.eq(1), @@ -71,7 +85,11 @@ class SBusToWishbone(Module): NextValue(timeout, timeout - 1), If(self.wishbone.ack, self.rd_fifo_data.we.eq(1), - self.rd_fifo_data.din.eq(Cat(self.wishbone.dat_r, Signal(reset = 0))), + If((adr >= 0x00020006) & (adr <= 0x0002000c) & (self.wishbone.dat_r != 0), ## 80018 >> 2 == HCCA register for USB + self.rd_fifo_data.din.eq(Cat(self.wishbone.dat_r[0:16], self.real_hcca[16:32], Signal(reset = 0))) + ).Else( + self.rd_fifo_data.din.eq(Cat(self.wishbone.dat_r, Signal(reset = 0))) + ), self.wishbone.we.eq(0), self.wishbone.cyc.eq(0), self.wishbone.stb.eq(0), @@ -85,3 +103,80 @@ class SBusToWishbone(Module): NextState("Idle") ) ) + +# ******************************************************************************************************** +class WishboneToSBus(Module): + def __init__(self, platform, soc, wr_fifo, rd_fifo_addr, rd_fifo_data, wishbone): + self.platform = platform + self.wr_fifo = wr_fifo + self.rd_fifo_addr = rd_fifo_addr + self.rd_fifo_data = rd_fifo_data + self.wishbone = wishbone + self.soc = soc + + #pad_SBUS_DATA_OE_LED_2 = platform.request("SBUS_DATA_OE_LED_2") + #SBUS_DATA_OE_LED_2_o = Signal() + #self.comb += pad_SBUS_DATA_OE_LED_2.eq(SBUS_DATA_OE_LED_2_o) + + data = Signal(32) + adr = Signal(30) + + self.real_hcca = self.soc.sbus_to_wishbone.real_hcca + + # ##### FSM: read/write from/to SBus ##### + self.submodules.fsm = fsm = FSM(reset_state="Reset") + fsm.act("Reset", + NextState("Idle") + ) + fsm.act("Idle", + If(self.wishbone.stb & self.wishbone.cyc & self.wishbone.we & self.wr_fifo.writable, + If((self.wishbone.adr[14:30] == 0x000c) & (self.real_hcca != 0), ## in our DMA range + self.wr_fifo.we.eq(1), + self.wr_fifo.din.eq(Cat(self.wishbone.adr[0:14], self.real_hcca[16:32], self.wishbone.dat_w[30:62])) + ), + NextState("WriteWait") + ).Elif(self.wishbone.stb & self.wishbone.cyc & ~self.wishbone.we & self.rd_fifo_addr.writable, + If((self.wishbone.adr[14:30] == 0x000c) & (self.real_hcca != 0), ## in our DMA range + NextValue(adr, self.wishbone.adr), + self.rd_fifo_addr.we.eq(1), + self.rd_fifo_addr.din.eq(Cat(self.wishbone.adr[0:14], self.real_hcca[16:32])) + ), + NextState("ReadWait"), + ) + ) + fsm.act("WriteWait", + #SBUS_DATA_OE_LED_2_o.eq(1), + If((self.wishbone.adr[14:30] == 0x000c) & (self.real_hcca != 0), ## in our DMA range + self.wishbone.ack.eq(1), + ).Else( + self.wishbone.err.eq(1) + ), + If(~self.wishbone.stb, + NextState("Idle") + ) + ) + fsm.act("ReadWait", + #SBUS_DATA_OE_LED_2_o.eq(1), + If((adr[14:30] == 0x000c) & (self.real_hcca != 0), ## in our DMA range + If(self.rd_fifo_data.readable, + self.wishbone.ack.eq(1), + self.rd_fifo_data.re.eq(1), + NextValue(data, self.rd_fifo_data.dout), + self.wishbone.dat_r.eq(self.rd_fifo_data.dout), + NextState("ReadWait2") + ) + ).Else( + self.wishbone.err.eq(1), + If(~self.wishbone.stb, + NextState("Idle") + ) + ) + ) + fsm.act("ReadWait2", + #SBUS_DATA_OE_LED_2_o.eq(1), + self.wishbone.ack.eq(1), + self.wishbone.dat_r.eq(data), + If(~self.wishbone.stb, + NextState("Idle") + ) + )