fix formatting on spiopi

Pycharm really butchered the code when I did a copy-and-paste...
it has questionable default formatting preferences.
This commit is contained in:
bunnie 2020-02-06 17:54:26 +08:00
parent cc6ed667df
commit 33d9e45a8b
1 changed files with 323 additions and 340 deletions

View File

@ -1,6 +1,3 @@
# This file is Copyright (c) 2020 bunnie <bunnie@kosagi.com>
# License: BSD
from litex.soc.interconnect.csr_eventmanager import *
from litex.soc.interconnect import wishbone
from litex.soc.integration.doc import AutoDoc, ModuleDoc
@ -79,7 +76,7 @@ class SpiOpi(Module, AutoCSR, AutoDoc):
CSRField("dummy", size=5, description="Number of dummy cycles", reset=10),
])
delay_type = "VAR_LOAD"
delay_type="VAR_LOAD"
# DQS input conditioning -----------------------------------------------------------------
dqs_iobuf = Signal()
@ -89,6 +86,7 @@ class SpiOpi(Module, AutoCSR, AutoDoc):
Instance("BUFR", i_I=pads.dqs, o_O=dqs_iobuf),
]
# DQ connections -------------------------------------------------------------------------
# PHY API
self.do = Signal(16) # OPI data to SPI
@ -127,40 +125,33 @@ class SpiOpi(Module, AutoCSR, AutoDoc):
self.specials += Instance("ODDR",
p_DDR_CLK_EDGE="SAME_EDGE",
i_C=ClockSignal(), i_R=ResetSignal(), i_S=0, i_CE=1,
i_D1=do_rise[i], i_D2=do_fall[i], o_Q=dq.o[i - 1],
i_D1=do_rise[i], i_D2=do_fall[i], o_Q=dq.o[i-1],
)
if sim == False:
if i == 1: # only wire up o_CNTVALUEOUT for one instance
self.specials += Instance("IDELAYE2",
p_DELAY_SRC="IDATAIN", p_SIGNAL_PATTERN="DATA",
p_CINVCTRL_SEL="FALSE", p_HIGH_PERFORMANCE_MODE="FALSE",
p_REFCLK_FREQUENCY=200.0,
p_PIPE_SEL="FALSE", p_IDELAY_VALUE=dq_delay_taps,
p_IDELAY_TYPE=delay_type,
p_CINVCTRL_SEL="FALSE", p_HIGH_PERFORMANCE_MODE="FALSE", p_REFCLK_FREQUENCY=200.0,
p_PIPE_SEL="FALSE", p_IDELAY_VALUE=dq_delay_taps, p_IDELAY_TYPE=delay_type,
i_C=ClockSignal(), i_CINVCTRL=0, i_REGRST=0, i_LDPIPEEN=0, i_INC=0,
i_CE=0,
i_C=ClockSignal(), i_CINVCTRL=0, i_REGRST=0, i_LDPIPEEN=0, i_INC=0, i_CE=0,
i_LD=self.delay_update,
i_CNTVALUEIN=self.delay_config.fields.d,
o_CNTVALUEOUT=self.delay_status.fields.q,
i_IDATAIN=dq.i[i - 1], o_DATAOUT=dq_delayed[i],
i_CNTVALUEIN=self.delay_config.fields.d, o_CNTVALUEOUT=self.delay_status.fields.q,
i_IDATAIN=dq.i[i-1], o_DATAOUT=dq_delayed[i],
),
else: # don't wire up o_CNTVALUEOUT for others
self.specials += Instance("IDELAYE2",
p_DELAY_SRC="IDATAIN", p_SIGNAL_PATTERN="DATA",
p_CINVCTRL_SEL="FALSE", p_HIGH_PERFORMANCE_MODE="FALSE",
p_REFCLK_FREQUENCY=200.0,
p_PIPE_SEL="FALSE", p_IDELAY_VALUE=dq_delay_taps,
p_IDELAY_TYPE=delay_type,
p_CINVCTRL_SEL="FALSE", p_HIGH_PERFORMANCE_MODE="FALSE", p_REFCLK_FREQUENCY=200.0,
p_PIPE_SEL="FALSE", p_IDELAY_VALUE=dq_delay_taps, p_IDELAY_TYPE=delay_type,
i_C=ClockSignal(), i_CINVCTRL=0, i_REGRST=0, i_LDPIPEEN=0, i_INC=0,
i_CE=0,
i_C=ClockSignal(), i_CINVCTRL=0, i_REGRST=0, i_LDPIPEEN=0, i_INC=0, i_CE=0,
i_LD=self.delay_update,
i_CNTVALUEIN=self.delay_config.fields.d,
i_IDATAIN=dq.i[i - 1], o_DATAOUT=dq_delayed[i],
i_IDATAIN=dq.i[i-1], o_DATAOUT=dq_delayed[i],
),
else:
self.comb += dq_delayed[i].eq(dq.i[i - 1])
self.comb += dq_delayed[i].eq(dq.i[i-1])
self.specials += Instance("IDDR", name="{}{}".format(iddr_name, str(i)),
p_DDR_CLK_EDGE="SAME_EDGE_PIPELINED",
i_C=dqs_iobuf, i_R=ResetSignal(), i_S=0, i_CE=1,
@ -224,7 +215,7 @@ class SpiOpi(Module, AutoCSR, AutoDoc):
# wire up CS_N
spi_cs_n = Signal()
opi_cs_n = Signal()
self.comb += cs_n.eq((self.spi_mode & spi_cs_n) | (~self.spi_mode & opi_cs_n))
self.comb += cs_n.eq( (self.spi_mode & spi_cs_n) | (~self.spi_mode & opi_cs_n) )
self.specials += [
Instance("ODDR",
p_DDR_CLK_EDGE="SAME_EDGE",
@ -342,8 +333,7 @@ class SpiOpi(Module, AutoCSR, AutoDoc):
""")
self.bus = wishbone.Interface()
self.command = CSRStorage(
description="Write individual bits to issue special commands to SPI; setting multiple bits at once leads to undefined behavior.",
self.command = CSRStorage(description="Write individual bits to issue special commands to SPI; setting multiple bits at once leads to undefined behavior.",
fields=[
CSRField("wakeup", size=1, description="Sequence through init & wakeup routine"),
CSRField("sector_erase", size=1, description="Erase a sector"),
@ -373,8 +363,7 @@ class SpiOpi(Module, AutoCSR, AutoDoc):
self.comb += do_mux_fall.eq(~self.spi_mode & do_fall[0] | self.spi_mode & self.mosi)
has_dummy = Signal() # indicates if the current "req" requires dummy cycles to be appended (used for both OPI/SPI)
rom_addr = Signal(32,
reset=0xFFFFFFFC) # location of the internal ROM address pointer; reset to invalid address to force an address request on first read
rom_addr = Signal(32, reset=0xFFFFFFFC) # location of the internal ROM address pointer; reset to invalid address to force an address request on first read
# MAC/PHY abstraction for OPI
txphy_do = Signal(16) # two sources of data out for OPI, one from the PHY, one from MAC
@ -416,7 +405,7 @@ class SpiOpi(Module, AutoCSR, AutoDoc):
# Direct FIFO primitive is more resource-efficient and faster than migen primitive.
Instance("FIFO_DUALCLOCK_MACRO",
p_DEVICE="7SERIES", p_FIFO_SIZE="18Kb", p_DATA_WIDTH=32, p_FIRST_WORD_FALL_THROUGH="TRUE",
p_ALMOST_EMPTY_OFFSET=6, p_ALMOST_FULL_OFFSET=(512 - (8 * prefetch_lines)),
p_ALMOST_EMPTY_OFFSET=6, p_ALMOST_FULL_OFFSET=(512- (8*prefetch_lines)),
o_ALMOSTEMPTY=rx_almostempty, o_ALMOSTFULL=rx_almostfull,
o_DO=opi_fifo_rd, o_EMPTY=rx_empty, o_FULL=rx_full,
@ -428,7 +417,7 @@ class SpiOpi(Module, AutoCSR, AutoDoc):
self.sync.dqs += opi_di.eq(self.di)
self.comb += opi_fifo_wd.eq(Cat(opi_di, self.di))
# --------- OPI Rx Phy machine ------------------------------
#--------- OPI Rx Phy machine ------------------------------
self.submodules.rxphy = rxphy = FSM(reset_state="IDLE")
cti_pipe = Signal(3)
rxphy_cnt = Signal(3)
@ -444,10 +433,8 @@ class SpiOpi(Module, AutoCSR, AutoDoc):
NextValue(rx_fifo_rst, 1),
).Elif(opi_rx_run,
NextValue(rx_wren, 1),
If((self.bus.cyc & self.bus.stb & ~self.bus.we) & ((self.bus.cti == 2) |
((
self.bus.cti == 7) & ~self.bus.ack)),
# handle case of non-pipelined read, ack is late
If( (self.bus.cyc & self.bus.stb & ~self.bus.we) & ((self.bus.cti == 2) |
((self.bus.cti == 7) & ~self.bus.ack) ), # handle case of non-pipelined read, ack is late
If(~rx_empty,
NextValue(self.bus.dat_r, opi_fifo_rd),
rx_rden.eq(1),
@ -468,6 +455,7 @@ class SpiOpi(Module, AutoCSR, AutoDoc):
)
)
# TxPHY machine: OPI -------------------------------------------------------------------------
txphy_cnt = Signal(4)
tx_run = Signal()
@ -477,10 +465,10 @@ class SpiOpi(Module, AutoCSR, AutoDoc):
txcmd_clken = Signal()
txphy_oe = Signal()
txcmd_oe = Signal()
self.sync += opi_cs_n.eq((tx_run & txphy_cs_n) | (~tx_run & txcmd_cs_n))
self.comb += If(tx_run, self.do.eq(txphy_do)).Else(self.do.eq(txcmd_do))
self.comb += opi_clk_en.eq((tx_run & txphy_clken) | (~tx_run & txcmd_clken))
self.comb += self.tx.eq((tx_run & txphy_oe) | (~tx_run & txcmd_oe))
self.sync += opi_cs_n.eq( (tx_run & txphy_cs_n) | (~tx_run & txcmd_cs_n) )
self.comb += If( tx_run, self.do.eq(txphy_do) ).Else( self.do.eq(txcmd_do) )
self.comb += opi_clk_en.eq( (tx_run & txphy_clken) | (~tx_run & txcmd_clken) )
self.comb += self.tx.eq( (tx_run & txphy_oe) | (~tx_run & txcmd_oe) )
tx_almostfull = Signal()
self.sync += tx_almostfull.eq(rx_almostfull) # sync the rx_almostfull signal into the local clock domain
txphy_bus = Signal()
@ -500,7 +488,7 @@ class SpiOpi(Module, AutoCSR, AutoDoc):
txphy.act("TX_SETUP",
NextValue(opi_rx_run, 0),
NextValue(txphy_cnt, txphy_cnt - 1),
If(txphy_cnt > 0,
If( txphy_cnt > 0,
NextValue(txphy_cs_n, 1)
).Else(
NextValue(txphy_cs_n, 0),
@ -542,7 +530,7 @@ class SpiOpi(Module, AutoCSR, AutoDoc):
)
txphy.act("TX_FILL",
If(tx_run,
If(((~txphy_bus & (self.bus.cyc & self.bus.stb & ~self.bus.we & (self.bus.cti == 2))) &
If( ((~txphy_bus & (self.bus.cyc & self.bus.stb & ~self.bus.we & (self.bus.cti == 2))) &
(opi_addr[2:] != self.bus.adr)) | tx_resetcycle,
# it's a new bus cycle, and the requested address is not equal to the current read buffer address
NextValue(txphy_clken, 1),
@ -578,7 +566,7 @@ class SpiOpi(Module, AutoCSR, AutoDoc):
)
)
# --------- OPI CMD machine ------------------------------
#--------- OPI CMD machine ------------------------------
self.submodules.opicmd = opicmd = FSM(reset_state="RESET")
opicmd.act("RESET",
NextValue(txcmd_do, 0),
@ -608,7 +596,7 @@ class SpiOpi(Module, AutoCSR, AutoDoc):
# - then run the command
# - Else wait until a bus cycle, and once it happens, put the system into run mode
If(self.bus.cyc & self.bus.stb,
If(~self.bus.we & (self.bus.cti == 2),
If(~self.bus.we & (self.bus.cti ==2),
NextState("TX_RUN")
).Else(
# handle other cases here, e.g. what do we do if we get a write? probably
@ -626,7 +614,7 @@ class SpiOpi(Module, AutoCSR, AutoDoc):
)
)
opicmd.act("WAIT_DISPATCH", # wait until the current cycle is done, then stop TX and dispatch command
If(~(self.bus.cyc & self.bus.stb),
If( ~(self.bus.cyc & self.bus.stb),
NextValue(tx_run, 0),
NextState("DISPATCH_CMD")
)
@ -665,8 +653,7 @@ class SpiOpi(Module, AutoCSR, AutoDoc):
spi_di_load = Signal() # spi_do load is pipelined back one cycle using this mechanism
spi_di_load2 = Signal()
spi_ack_pipe = Signal()
self.sync += [
# pipelining is required the MISO path is very slow (IOB->fabric FD), and a falling-edge retiming reg is used to meet timing
self.sync += [ # pipelining is required the MISO path is very slow (IOB->fabric FD), and a falling-edge retiming reg is used to meet timing
spi_di_load2.eq(spi_di_load),
If(spi_di_load2, spi_di.eq(Cat(self.miso, spi_si[:-1]))).Else(spi_di.eq(spi_di)),
spi_ack.eq(spi_ack_pipe),
@ -690,11 +677,11 @@ class SpiOpi(Module, AutoCSR, AutoDoc):
)
spiphy.act("REQ",
If(spicount > 0,
NextValue(spicount, spicount - 1),
NextValue(spicount, spicount-1),
NextValue(spi_clk_en, 1),
NextValue(spi_so, Cat(0, spi_so[:-1])),
NextValue(spi_ack_pipe, 0),
).Elif((spicount == 0) & spi_req & ~spi_dummy, # back-to-back transaction
).Elif( (spicount == 0) & spi_req & ~spi_dummy, # back-to-back transaction
NextValue(spi_clk_en, 1),
NextValue(spicount, 7),
NextValue(spi_clk_en, 1),
@ -702,12 +689,12 @@ class SpiOpi(Module, AutoCSR, AutoDoc):
spi_di_load.eq(1), # "naked" .eq() create single-cycle pulses that default back to 0
NextValue(spi_ack_pipe, 1),
NextValue(spi_dummy, has_dummy),
).Elif((spicount == 0) & ~spi_req & ~spi_dummy, # go back to idle
).Elif( (spicount == 0) & ~spi_req & ~spi_dummy, # go back to idle
spi_di_load.eq(1),
NextValue(spi_ack_pipe, 1),
NextValue(spi_clk_en, 0),
NextState("RESET"),
).Elif((spicount == 0) & spi_dummy,
).Elif( (spicount == 0) & spi_dummy,
spi_di_load.eq(1),
NextValue(spicount, self.config.fields.dummy),
NextValue(spi_clk_en, 1),
@ -733,6 +720,7 @@ class SpiOpi(Module, AutoCSR, AutoDoc):
)
)
# SPI MAC machine -------------------------------------------------------------------------------
# default active on boot
addr_updated = Signal()
@ -757,14 +745,13 @@ class SpiOpi(Module, AutoCSR, AutoDoc):
mac.act("IDLE",
If(self.spi_mode, # this machine stays in idle once spi_mode is dropped
NextValue(self.bus.ack, 0),
If((self.bus.cyc == 1) & (self.bus.stb == 1) & (self.bus.we == 0) & (self.bus.cti != 7),
# read cycle requested, not end-of-burst
If((rom_addr[2:] != self.bus.adr) & new_cycle,
If((self.bus.cyc == 1) & (self.bus.stb == 1) & (self.bus.we == 0) & (self.bus.cti != 7), # read cycle requested, not end-of-burst
If( (rom_addr[2:] != self.bus.adr) & new_cycle,
NextValue(rom_addr, Cat(Signal(2, reset=0), self.bus.adr)),
NextValue(addr_updated, 1),
NextValue(spi_cs_n, 1), # raise CS in anticipation of a new address cycle
NextState("SPI_READ_32_CS"),
).Elif((rom_addr[2:] == self.bus.adr) | (~new_cycle & self.bus.cti == 2),
).Elif( (rom_addr[2:] == self.bus.adr) | (~new_cycle & self.bus.cti == 2),
NextValue(mac_count, 3), # get another beat of 4 bytes at the next address
NextState("SPI_READ_32")
).Else(
@ -791,21 +778,21 @@ class SpiOpi(Module, AutoCSR, AutoDoc):
)
)
# --------- wakup chip ------------------------------
#--------- wakup chip ------------------------------
mac.act("WAKEUP_PRE",
NextValue(spi_cs_n, 1), # why isn't this sticking? i shouldn't have to put this here
NextValue(mac_count, 4),
NextState("WAKEUP_PRE_CS_WAIT")
)
mac.act("WAKEUP_PRE_CS_WAIT",
NextValue(mac_count, mac_count - 1),
NextValue(mac_count, mac_count-1),
If(mac_count == 0,
NextState("WAKEUP_WUP"),
NextValue(spi_cs_n, 0),
)
)
mac.act("WAKEUP_WUP",
NextValue(mac_count, mac_count - 1),
NextValue(mac_count, mac_count-1),
If(mac_count == 0,
NextValue(spi_cs_n, 0),
NextValue(spi_do, 0xab), # wakeup from deep sleep
@ -822,9 +809,9 @@ class SpiOpi(Module, AutoCSR, AutoDoc):
)
)
# --------- WREN+CR2 - dummy cycles ------------------------------
#--------- WREN+CR2 - dummy cycles ------------------------------
mac.act("WAKEUP_CR2_WREN_1",
NextValue(mac_count, mac_count - 1),
NextValue(mac_count, mac_count-1),
If(mac_count == 0,
NextValue(spi_cs_n, 0),
NextValue(spi_do, 0x06), # WREN to unlock CR2 writing
@ -841,7 +828,7 @@ class SpiOpi(Module, AutoCSR, AutoDoc):
)
)
mac.act("WAKEUP_CR2_DUMMY_CMD",
NextValue(mac_count, mac_count - 1),
NextValue(mac_count, mac_count-1),
If(mac_count == 0,
NextValue(spi_cs_n, 0),
NextValue(spi_do, 0x72), # CR2 command
@ -853,7 +840,7 @@ class SpiOpi(Module, AutoCSR, AutoDoc):
mac.act("WAKEUP_CR2_DUMMY_ADRHI",
NextValue(spi_do, 0x00), # we want to send 00_00_03_00
If(spi_ack,
NextValue(mac_count, mac_count - 1),
NextValue(mac_count, mac_count -1),
),
If(mac_count == 0,
NextState("WAKEUP_CR2_DUMMY_ADRMID")
@ -880,9 +867,9 @@ class SpiOpi(Module, AutoCSR, AutoDoc):
)
)
# --------- WREN+CR2 to DOPI mode ------------------------------
#--------- WREN+CR2 to DOPI mode ------------------------------
mac.act("WAKEUP_CR2_WREN_2",
NextValue(mac_count, mac_count - 1),
NextValue(mac_count, mac_count-1),
If(mac_count == 0,
NextValue(spi_cs_n, 0),
NextValue(spi_do, 0x06), # WREN to unlock CR2 writing
@ -899,7 +886,7 @@ class SpiOpi(Module, AutoCSR, AutoDoc):
)
)
mac.act("WAKEUP_CR2_DOPI_CMD",
NextValue(mac_count, mac_count - 1),
NextValue(mac_count, mac_count-1),
If(mac_count == 0,
NextValue(spi_cs_n, 0),
NextValue(spi_do, 0x72), # CR2 command
@ -931,14 +918,14 @@ class SpiOpi(Module, AutoCSR, AutoDoc):
)
mac.act("WAKEUP_CS_EXIT",
NextValue(self.spi_mode, 0), # now enter DOPI mode
NextValue(mac_count, mac_count - 1),
NextValue(mac_count, mac_count-1),
If(mac_count == 0,
NextState("IDLE"),
)
)
if spiread:
# --------- SPI read machine ------------------------------
#--------- SPI read machine ------------------------------
mac.act("SPI_READ_32",
If(addr_updated,
NextState("SPI_READ_32_CS"),
@ -954,9 +941,8 @@ class SpiOpi(Module, AutoCSR, AutoDoc):
).Else(
NextValue(spi_req, 0),
If(spi_ack,
If(self.spi_mode,
# protect these in a spi_mode mux to prevent excess inference of logic to handle otherwise implicit dual-master situation
NextValue(self.bus.dat_r, Cat(d_to_wb[8:], spi_di)),
If(self.spi_mode, # protect these in a spi_mode mux to prevent excess inference of logic to handle otherwise implicit dual-master situation
NextValue(self.bus.dat_r, Cat(d_to_wb[8:],spi_di)),
NextValue(self.bus.ack, 1),
),
NextValue(rom_addr, rom_addr + 1),
@ -968,14 +954,14 @@ class SpiOpi(Module, AutoCSR, AutoDoc):
mac.act("SPI_READ_32_D",
If(spi_ack,
# shift in one byte at a time to d_to_wb(32)
NextValue(d_to_wb, Cat(d_to_wb[8:], spi_di, )),
NextValue(d_to_wb, Cat(d_to_wb[8:],spi_di,)),
NextValue(mac_count, mac_count - 1),
NextState("SPI_READ_32"),
NextValue(rom_addr, rom_addr + 1),
)
)
mac.act("SPI_READ_32_CS",
NextValue(mac_count, mac_count - 1),
NextValue(mac_count, mac_count-1),
If(mac_count == 0,
NextValue(spi_cs_n, 0),
NextState("SPI_READ_32_A0"),
@ -987,8 +973,7 @@ class SpiOpi(Module, AutoCSR, AutoDoc):
NextState("SPI_READ_32_A1"),
)
mac.act("SPI_READ_32_A1",
NextValue(spi_do, rom_addr[24:] & 0x7),
# queue up MSB to send, leave req high; mask off unused high bits
NextValue(spi_do, rom_addr[24:] & 0x7), # queue up MSB to send, leave req high; mask off unused high bits
If(spi_ack,
NextState("SPI_READ_32_A2"),
)
@ -1045,10 +1030,8 @@ class SpiOpi(Module, AutoCSR, AutoDoc):
CSRField("ecc_address", size=32, description="Address of the most recent ECC event")
])
self.ecc_status = CSRStatus(fields=[
CSRField("ecc_error", size=1,
description="Live status of the ECS_N bit (ECC error on current packet when low)"),
CSRField("ecc_overflow", size=1,
description="More than one ECS_N event has happened since th last time ecc_address was checked")
CSRField("ecc_error", size=1, description="Live status of the ECS_N bit (ECC error on current packet when low)"),
CSRField("ecc_overflow", size=1, description="More than one ECS_N event has happened since th last time ecc_address was checked")
])
self.comb += self.ecc_status.fields.ecc_error.eq(ecs_n)