def __init__(self, settings): # 1st command 1 cycle after assertion of ready self.cmd = cmd = stream.Endpoint(cmd_request_rw_layout(settings.geom.addressbits, settings.geom.bankbits)) # # # # Refresh sequence generator: # PRECHARGE ALL --(tRP)--> AUTO REFRESH --(tRFC)--> done seq_start = Signal() seq_done = Signal() self.sync += [ cmd.a.eq(2**10), cmd.ba.eq(0), cmd.cas.eq(0), cmd.ras.eq(0), cmd.we.eq(0), seq_done.eq(0) ] self.sync += timeline(seq_start, [ (1, [ cmd.ras.eq(1), cmd.we.eq(1) ]), (1+settings.timing.tRP, [ cmd.cas.eq(1), cmd.ras.eq(1) ]), (1+settings.timing.tRP+settings.timing.tRFC, [ seq_done.eq(1) ]) ]) # Periodic refresh counter self.submodules.timer = WaitTimer(settings.timing.tREFI) self.comb += self.timer.wait.eq(settings.with_refresh & ~self.timer.done) # Control FSM self.submodules.fsm = fsm = FSM() fsm.act("IDLE", If(self.timer.done, NextState("WAIT_GRANT") ) ) fsm.act("WAIT_GRANT", cmd.valid.eq(1), If(cmd.ready, seq_start.eq(1), NextState("WAIT_SEQ") ) ) fsm.act("WAIT_SEQ", If(seq_done, cmd.last.eq(1), NextState("IDLE") ).Else( cmd.valid.eq(1) ) )
def __init__(self, platform): self.clock_domains.cd_sys = ClockDomain("sys") # soft reset generaton self._soft_rst = CSR() soft_rst = Signal() # trigger soft reset 1us after CSR access to terminate # Wishbone access when reseting from PCIe self.sync += [ timeline(self._soft_rst.re & self._soft_rst.r, [(125, [soft_rst.eq(1)])]), ] # sys_clk / sys_rst (from PCIe) self.comb += self.cd_sys.clk.eq(ClockSignal("pcie")) self.specials += AsyncResetSynchronizer(self.cd_sys, ResetSignal("pcie") | soft_rst)
def __init__(self, platform): self.clock_domains.cd_sys = ClockDomain("sys") self.clock_domains.cd_clk125 = ClockDomain("clk125") # soft reset generaton self._soft_rst = CSR() soft_rst = Signal() # trigger soft reset 1us after CSR access to terminate # Wishbone access when reseting from PCIe self.sync += [ timeline(self._soft_rst.re & self._soft_rst.r, [(125, [soft_rst.eq(1)])]), ] # sys_clk / sys_rst (from PCIe) self.comb += self.cd_sys.clk.eq(self.cd_clk125.clk) self.specials += AsyncResetSynchronizer(self.cd_sys, self.cd_clk125.rst | soft_rst)
def __init__(self, a, ba, tRP, tREFI, tRFC): self.req = Signal() self.ack = Signal() # 1st command 1 cycle after assertion of ack self.cmd = CommandRequest(a, ba) ### # Refresh sequence generator: # PRECHARGE ALL --(tRP)--> AUTO REFRESH --(tRFC)--> done seq_start = Signal() seq_done = Signal() self.sync += [ self.cmd.a.eq(2**10), self.cmd.ba.eq(0), self.cmd.cas_n.eq(1), self.cmd.ras_n.eq(1), self.cmd.we_n.eq(1), seq_done.eq(0) ] self.sync += timeline( seq_start, [(1, [self.cmd.ras_n.eq(0), self.cmd.we_n.eq(0)]), (1 + tRP, [self.cmd.cas_n.eq(0), self.cmd.ras_n.eq(0)]), (1 + tRP + tRFC, [seq_done.eq(1)])]) # Periodic refresh counter counter = Signal(max=tREFI) start = Signal() self.sync += [ start.eq(0), If(counter == 0, start.eq(1), counter.eq(tREFI - 1)).Else(counter.eq(counter - 1)) ] # Control FSM fsm = FSM() self.submodules += fsm fsm.act("IDLE", If(start, NextState("WAIT_GRANT"))) fsm.act("WAIT_GRANT", self.req.eq(1), If(self.ack, seq_start.eq(1), NextState("WAIT_SEQ"))) fsm.act("WAIT_SEQ", self.req.eq(1), If(seq_done, NextState("IDLE")))
def __init__(self, bus_wishbone=None, bus_csr=None): if bus_wishbone is None: bus_wishbone = wishbone.Interface() self.wishbone = bus_wishbone if bus_csr is None: bus_csr = csr_bus.Interface() self.csr = bus_csr ### self.sync += [ self.csr.we.eq(0), self.csr.dat_w.eq(self.wishbone.dat_w), self.csr.adr.eq(self.wishbone.adr), self.wishbone.dat_r.eq(self.csr.dat_r) ] self.sync += timeline(self.wishbone.cyc & self.wishbone.stb, [(1, [self.csr.we.eq(self.wishbone.we)]), (2, [self.wishbone.ack.eq(1)]), (3, [self.wishbone.ack.eq(0)])])
def __init__(self, settings): # 1st command 1 cycle after assertion of ready self.cmd = cmd = stream.Endpoint( cmd_request_rw_layout(settings.geom.addressbits, settings.geom.bankbits)) # # # # Refresh sequence generator: # PRECHARGE ALL --(tRP)--> AUTO REFRESH --(tRFC)--> done seq_start = Signal() seq_done = Signal() self.sync += [ cmd.a.eq(2**10), cmd.ba.eq(0), cmd.cas.eq(0), cmd.ras.eq(0), cmd.we.eq(0), seq_done.eq(0) ] self.sync += timeline(seq_start, [ (1, [cmd.ras.eq(1), cmd.we.eq(1)]), (1 + settings.timing.tRP, [cmd.cas.eq(1), cmd.ras.eq(1)]), (1 + settings.timing.tRP + settings.timing.tRFC, [seq_done.eq(1)]) ]) # Periodic refresh counter self.submodules.timer = WaitTimer(settings.timing.tREFI) self.comb += self.timer.wait.eq(settings.with_refresh & ~self.timer.done) # Control FSM self.submodules.fsm = fsm = FSM() fsm.act("IDLE", If(self.timer.done, NextState("WAIT_GRANT"))) fsm.act("WAIT_GRANT", cmd.valid.eq(1), If(cmd.ready, seq_start.eq(1), NextState("WAIT_SEQ"))) fsm.act( "WAIT_SEQ", If(seq_done, cmd.last.eq(1), NextState("IDLE")).Else(cmd.valid.eq(1)))
def __init__(self, bus_wishbone=None, bus_csr=None): if bus_wishbone is None: bus_wishbone = wishbone.Interface() self.wishbone = bus_wishbone if bus_csr is None: bus_csr = csr_bus.Interface() self.csr = bus_csr ### self.sync += [ self.csr.we.eq(0), self.csr.dat_w.eq(self.wishbone.dat_w), self.csr.adr.eq(self.wishbone.adr), self.wishbone.dat_r.eq(self.csr.dat_r) ] self.sync += timeline(self.wishbone.cyc & self.wishbone.stb, [ (1, [self.csr.we.eq(self.wishbone.we)]), (2, [self.wishbone.ack.eq(1)]), (3, [self.wishbone.ack.eq(0)]) ])
def __init__(self, pads, dummy=15, div=2, with_bitbang=True): """ Simple SPI flash, e.g. N25Q128 on the LX9 Microboard. Supports multi-bit pseudo-parallel reads (aka Dual or Quad I/O Fast Read). Only supports mode0 (cpol=0, cpha=0). Optionally supports software bitbanging (for write, erase, or other commands). """ self.bus = bus = wishbone.Interface() spi_width = len(pads.dq) if with_bitbang: self.bitbang = CSRStorage(4) self.miso = CSRStatus() self.bitbang_en = CSRStorage() ### cs_n = Signal(reset=1) clk = Signal() dq_oe = Signal() wbone_width = len(bus.dat_r) read_cmd_params = { 4: (_format_cmd(_QIOFR, 4), 4 * 8), 2: (_format_cmd(_DIOFR, 2), 2 * 8), 1: (_format_cmd(_FAST_READ, 1), 1 * 8), } read_cmd, cmd_width = read_cmd_params[spi_width] addr_width = 24 pads.cs_n.reset = 1 dq = TSTriple(spi_width) self.specials.dq = dq.get_tristate(pads.dq) sr = Signal(max(cmd_width, addr_width, wbone_width)) dqs = Replicate(1, spi_width - 1) self.comb += bus.dat_r.eq(sr) hw_read_logic = [pads.clk.eq(clk), pads.cs_n.eq(cs_n), dq.o.eq(sr[-spi_width:]), dq.oe.eq(dq_oe)] if with_bitbang: bitbang_logic = [ pads.clk.eq(self.bitbang.storage[1]), pads.cs_n.eq(self.bitbang.storage[2]), dq.o.eq(Cat(self.bitbang.storage[0], dqs)), If(self.bitbang.storage[3], dq.oe.eq(0)).Else(dq.oe.eq(1)), If(self.bitbang.storage[1], self.miso.status.eq(dq.i[1])), ] self.comb += If(self.bitbang_en.storage, bitbang_logic).Else(hw_read_logic) else: self.comb += hw_read_logic if div < 2: raise ValueError("Unsupported value '{}' for div parameter for SpiFlash core".format(div)) else: i = Signal(max=div) dqi = Signal(spi_width) self.sync += [ If(i == div // 2 - 1, clk.eq(1), dqi.eq(dq.i)), If(i == div - 1, i.eq(0), clk.eq(0), sr.eq(Cat(dqi, sr[:-spi_width]))).Else(i.eq(i + 1)), ] # spi is byte-addressed, prefix by zeros z = Replicate(0, log2_int(wbone_width // 8)) seq = [ (cmd_width // spi_width * div, [dq_oe.eq(1), cs_n.eq(0), sr[-cmd_width:].eq(read_cmd)]), (addr_width // spi_width * div, [sr[-addr_width:].eq(Cat(z, bus.adr))]), ((dummy + wbone_width // spi_width) * div, [dq_oe.eq(0)]), (1, [bus.ack.eq(1), cs_n.eq(1)]), (div, [bus.ack.eq(0)]), # tSHSL! (0, []), ] # accumulate timeline deltas t, tseq = 0, [] for dt, a in seq: tseq.append((t, a)) t += dt self.sync += timeline(bus.cyc & bus.stb & (i == div - 1), tseq)
def __init__(self, pads, dummy=15, div=2, with_bitbang=True): """ Simple SPI flash. Supports multi-bit pseudo-parallel reads (aka Dual or Quad I/O Fast Read). Only supports mode0 (cpol=0, cpha=0). """ self.bus = bus = wishbone.Interface() spi_width = len(pads.dq) assert spi_width >= 2 if with_bitbang: self.bitbang = CSRStorage(4) self.miso = CSRStatus() self.bitbang_en = CSRStorage() # # # cs_n = Signal(reset=1) clk = Signal() dq_oe = Signal() wbone_width = len(bus.dat_r) read_cmd_params = { 4: (_format_cmd(_QIOFR, 4), 4 * 8), 2: (_format_cmd(_DIOFR, 2), 2 * 8), } read_cmd, cmd_width = read_cmd_params[spi_width] addr_width = 24 dq = TSTriple(spi_width) self.specials.dq = dq.get_tristate(pads.dq) sr = Signal(max(cmd_width, addr_width, wbone_width)) self.comb += bus.dat_r.eq(sr) hw_read_logic = [ pads.clk.eq(clk), pads.cs_n.eq(cs_n), dq.o.eq(sr[-spi_width:]), dq.oe.eq(dq_oe) ] if with_bitbang: bitbang_logic = [ pads.clk.eq(self.bitbang.storage[1]), pads.cs_n.eq(self.bitbang.storage[2]), # In Dual/Quad mode, no single data pin is consistently # an input or output thanks to dual/quad reads, so we need a bit # to swap direction of the pins. Aside from this additional bit, # bitbang mode is identical for Single/Dual/Quad; dq[0] is mosi # and dq[1] is miso, meaning remaining data pin values don't # appear in CSR registers. If(self.bitbang.storage[3], dq.oe.eq(0)).Else(dq.oe.eq(1)), If( self.bitbang. storage[1], # CPOL=0/CPHA=0 or CPOL=1/CPHA=1 only. self.miso.status.eq(dq.i[1])), dq.o.eq( Cat(self.bitbang.storage[0], Replicate(1, spi_width - 1))) ] self.comb += [ If(self.bitbang_en.storage, bitbang_logic).Else(hw_read_logic) ] else: self.comb += hw_read_logic if div < 2: raise ValueError( "Unsupported value \'{}\' for div parameter for SpiFlash core". format(div)) else: i = Signal(max=div) dqi = Signal(spi_width) self.sync += [ If( i == div // 2 - 1, clk.eq(1), dqi.eq(dq.i), ), If(i == div - 1, i.eq(0), clk.eq(0), sr.eq(Cat(dqi, sr[:-spi_width]))).Else(i.eq(i + 1), ), ] # spi is byte-addressed, prefix by zeros z = Replicate(0, log2_int(wbone_width // 8)) seq = [ (cmd_width // spi_width * div, [dq_oe.eq(1), cs_n.eq(0), sr[-cmd_width:].eq(read_cmd)]), (addr_width // spi_width * div, [sr[-addr_width:].eq(Cat(z, bus.adr))]), ((dummy + wbone_width // spi_width) * div, [dq_oe.eq(0)]), (1, [bus.ack.eq(1), cs_n.eq(1)]), ( div, # tSHSL! [bus.ack.eq(0)]), (0, []), ] # accumulate timeline deltas t, tseq = 0, [] for dt, a in seq: tseq.append((t, a)) t += dt self.sync += timeline(bus.cyc & bus.stb & (i == div - 1), tseq)
def __init__(self, pads, dummy=15, div=2, with_bitbang=True): """ Simple SPI flash. Supports 1-bit reads. Only supports mode0 (cpol=0, cpha=0). """ self.bus = bus = wishbone.Interface() if with_bitbang: self.bitbang = CSRStorage(4) self.miso = CSRStatus() self.bitbang_en = CSRStorage() # # # if hasattr(pads, "wp"): self.comb += pads.wp.eq(1) if hasattr(pads, "hold"): self.comb += pads.hold.eq(1) cs_n = Signal(reset=1) clk = Signal() wbone_width = len(bus.dat_r) read_cmd = _FAST_READ cmd_width = 8 addr_width = 24 sr = Signal(max(cmd_width, addr_width, wbone_width)) self.comb += bus.dat_r.eq(sr) hw_read_logic = [ pads.clk.eq(clk), pads.cs_n.eq(cs_n), pads.mosi.eq(sr[-1:]) ] if with_bitbang: bitbang_logic = [ pads.clk.eq(self.bitbang.storage[1]), pads.cs_n.eq(self.bitbang.storage[2]), If( self.bitbang. storage[1], # CPOL=0/CPHA=0 or CPOL=1/CPHA=1 only. self.miso.status.eq(pads.miso)), pads.mosi.eq(self.bitbang.storage[0]) ] self.comb += [ If(self.bitbang_en.storage, bitbang_logic).Else(hw_read_logic) ] else: self.comb += hw_read_logic if div < 2: raise ValueError( "Unsupported value \'{}\' for div parameter for SpiFlash core". format(div)) else: i = Signal(max=div) miso = Signal() self.sync += [ If( i == div // 2 - 1, clk.eq(1), miso.eq(pads.miso), ), If(i == div - 1, i.eq(0), clk.eq(0), sr.eq(Cat(miso, sr[:-1]))).Else(i.eq(i + 1), ), ] # spi is byte-addressed, prefix by zeros z = Replicate(0, log2_int(wbone_width // 8)) seq = [ (cmd_width * div, [cs_n.eq(0), sr[-cmd_width:].eq(read_cmd)]), (addr_width * div, [sr[-addr_width:].eq(Cat(z, bus.adr))]), ((dummy + wbone_width) * div, []), (1, [bus.ack.eq(1), cs_n.eq(1)]), ( div, # tSHSL! [bus.ack.eq(0)]), (0, []), ] # accumulate timeline deltas t, tseq = 0, [] for dt, a in seq: tseq.append((t, a)) t += dt self.sync += timeline(bus.cyc & bus.stb & (i == div - 1), tseq)
def __init__(self, pads, dummy=15, div=2): """ Simple SPI flash. Supports multi-bit pseudo-parallel reads (aka Dual or Quad I/O Fast Read). Only supports mode0 (cpol=0, cpha=0). """ self.bus = bus = wishbone.Interface() spi_width = len(pads.dq) assert spi_width >= 2 # # # cs_n = Signal(reset=1) clk = Signal() dq_oe = Signal() wbone_width = len(bus.dat_r) read_cmd_params = { 4: (_format_cmd(_QIOFR, 4), 4 * 8), 2: (_format_cmd(_DIOFR, 2), 2 * 8), 1: (_format_cmd(_FAST_READ, 1), 1 * 8) } read_cmd, cmd_width = read_cmd_params[spi_width] addr_width = 24 dq = TSTriple(spi_width) self.specials.dq = dq.get_tristate(pads.dq) sr = Signal(max(cmd_width, addr_width, wbone_width)) self.comb += bus.dat_r.eq(sr) self.comb += [ pads.clk.eq(clk), pads.cs_n.eq(cs_n), dq.o.eq(sr[-spi_width:]), dq.oe.eq(dq_oe) ] if div < 2: raise ValueError( "Unsupported value \'{}\' for div parameter for SpiFlash core". format(div)) else: i = Signal(max=div) dqi = Signal(spi_width) self.sync += [ If( i == div // 2 - 1, clk.eq(1), dqi.eq(dq.i), ), If(i == div - 1, i.eq(0), clk.eq(0), sr.eq(Cat(dqi, sr[:-spi_width]))).Else(i.eq(i + 1), ), ] # spi is byte-addressed, prefix by zeros z = Replicate(0, log2_int(wbone_width // 8)) seq = [ (cmd_width // spi_width * div, [dq_oe.eq(1), cs_n.eq(0), sr[-cmd_width:].eq(read_cmd)]), (addr_width // spi_width * div, [sr[-addr_width:].eq(Cat(z, bus.adr))]), ((dummy + wbone_width // spi_width) * div, [dq_oe.eq(0)]), (1, [bus.ack.eq(1), cs_n.eq(1)]), ( div, # tSHSL! [bus.ack.eq(0)]), (0, []), ] # accumulate timeline deltas t, tseq = 0, [] for dt, a in seq: tseq.append((t, a)) t += dt self.sync += timeline(bus.cyc & bus.stb & (i == div - 1), tseq)
def __init__(self, pads, dummy=15, div=2, with_bitbang=True): """ Simple SPI flash, e.g. N25Q128 on the LX9 Microboard. Supports multi-bit pseudo-parallel reads (aka Dual or Quad I/O Fast Read). Only supports mode0 (cpol=0, cpha=0). Optionally supports software bitbanging (for write, erase, or other commands). """ self.bus = bus = wishbone.Interface() spi_width = len(pads.dq) if with_bitbang: self.bitbang = CSRStorage(4) self.miso = CSRStatus() self.bitbang_en = CSRStorage() ### cs_n = Signal(reset=1) clk = Signal() dq_oe = Signal() wbone_width = len(bus.dat_r) read_cmd_params = { 4: (_format_cmd(_QIOFR, 4), 4 * 8), 2: (_format_cmd(_DIOFR, 2), 2 * 8), 1: (_format_cmd(_FAST_READ, 1), 1 * 8) } read_cmd, cmd_width = read_cmd_params[spi_width] addr_width = 24 pads.cs_n.reset = 1 dq = TSTriple(spi_width) self.specials.dq = dq.get_tristate(pads.dq) sr = Signal(max(cmd_width, addr_width, wbone_width)) dqs = Replicate(1, spi_width - 1) self.comb += bus.dat_r.eq(sr) hw_read_logic = [ pads.clk.eq(clk), pads.cs_n.eq(cs_n), dq.o.eq(sr[-spi_width:]), dq.oe.eq(dq_oe) ] if with_bitbang: bitbang_logic = [ pads.clk.eq(self.bitbang.storage[1]), pads.cs_n.eq(self.bitbang.storage[2]), dq.o.eq(Cat(self.bitbang.storage[0], dqs)), If(self.bitbang.storage[3], dq.oe.eq(0)).Else(dq.oe.eq(1)), If(self.bitbang.storage[1], self.miso.status.eq(dq.i[1])) ] self.comb += \ If(self.bitbang_en.storage, bitbang_logic ).Else( hw_read_logic ) else: self.comb += hw_read_logic if div < 2: raise ValueError( "Unsupported value \'{}\' for div parameter for SpiFlash core". format(div)) else: i = Signal(max=div) dqi = Signal(spi_width) self.sync += [ If( i == div // 2 - 1, clk.eq(1), dqi.eq(dq.i), ), If(i == div - 1, i.eq(0), clk.eq(0), sr.eq(Cat(dqi, sr[:-spi_width]))).Else(i.eq(i + 1), ), ] # spi is byte-addressed, prefix by zeros z = Replicate(0, log2_int(wbone_width // 8)) seq = [ (cmd_width // spi_width * div, [dq_oe.eq(1), cs_n.eq(0), sr[-cmd_width:].eq(read_cmd)]), (addr_width // spi_width * div, [sr[-addr_width:].eq(Cat(z, bus.adr))]), ((dummy + wbone_width // spi_width) * div, [dq_oe.eq(0)]), (1, [bus.ack.eq(1), cs_n.eq(1)]), ( div, # tSHSL! [bus.ack.eq(0)]), (0, []), ] # accumulate timeline deltas t, tseq = 0, [] for dt, a in seq: tseq.append((t, a)) t += dt self.sync += timeline(bus.cyc & bus.stb & (i == div - 1), tseq)