Guest User

Untitled

a guest
Jan 17th, 2017
54
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.44 KB | None | 0 0
  1. from litex.gen import *
  2. from litex.gen.genlib.misc import timeline
  3.  
  4. from litex.soc.interconnect import wishbone
  5. from litex.soc.interconnect.csr import AutoCSR, CSRStorage, CSRStatus
  6.  
  7.  
  8. _FAST_READ = 0x0b
  9. _DIOFR = 0xbb
  10. _QIOFR = 0xeb
  11.  
  12.  
  13. def _format_cmd(cmd, spi_width):
  14.     """
  15.    `cmd` is the read instruction. Since everything is transmitted on all
  16.    dq lines (cmd, adr and data), extend/interleave cmd to full pads.dq
  17.    width even if dq1-dq3 are don't care during the command phase:
  18.    For example, for N25Q128, 0xeb is the quad i/o fast read, and
  19.    extended to 4 bits (dq1,dq2,dq3 high) is: 0xfffefeff
  20.    """
  21.     c = 2**(8*spi_width)-1
  22.     for b in range(8):
  23.         if not (cmd>>b)%2:
  24.             c &= ~(1<<(b*spi_width))
  25.     return c
  26.  
  27.  
  28. class SpiFlashDualQuad(Module, AutoCSR):
  29.     def __init__(self, pads, dummy=15, div=2, with_bitbang=True):
  30.         """
  31.        Simple SPI flash, e.g. N25Q128 on the LX9 Microboard.
  32.  
  33.        Supports multi-bit pseudo-parallel reads (aka Dual or Quad I/O Fast
  34.        Read). Only supports mode0 (cpol=0, cpha=0).
  35.        Optionally supports software bitbanging (for write, erase, or other commands).
  36.        """
  37.         self.bus = bus = wishbone.Interface()
  38.         spi_width = len(pads.dq)
  39.         assert spi_width >= 2
  40.         if with_bitbang:
  41.             self.bitbang = CSRStorage(4)
  42.             self.miso = CSRStatus()
  43.             self.bitbang_en = CSRStorage()
  44.  
  45.         # # #
  46.  
  47.         cs_n = Signal(reset=1)
  48.         clk = Signal()
  49.         dq_oe = Signal()
  50.         wbone_width = len(bus.dat_r)
  51.  
  52.  
  53.         read_cmd_params = {
  54.             4: (_format_cmd(_QIOFR, 4), 4*8),
  55.             2: (_format_cmd(_DIOFR, 2), 2*8),
  56.             1: (_format_cmd(_FAST_READ, 1), 1*8)
  57.         }
  58.         read_cmd, cmd_width = read_cmd_params[spi_width]
  59.         addr_width = 24
  60.  
  61.         pads.cs_n.reset = 1
  62.  
  63.         dq = TSTriple(spi_width)
  64.         self.specials.dq = dq.get_tristate(pads.dq)
  65.  
  66.         sr = Signal(max(cmd_width, addr_width, wbone_width))
  67.         self.comb += bus.dat_r.eq(sr)
  68.  
  69.         hw_read_logic = [
  70.             pads.clk.eq(clk),
  71.             pads.cs_n.eq(cs_n),
  72.             dq.o.eq(sr[-spi_width:]),
  73.             dq.oe.eq(dq_oe)
  74.         ]
  75.  
  76.         if with_bitbang:
  77.             bitbang_logic = [
  78.                 pads.clk.eq(self.bitbang.storage[1]),
  79.                 pads.cs_n.eq(self.bitbang.storage[2]),
  80.                 If(self.bitbang.storage[3],
  81.                     dq.oe.eq(0)
  82.                 ).Else(
  83.                     dq.oe.eq(1)
  84.                 ),
  85.                 If(self.bitbang.storage[1],
  86.                     self.miso.status.eq(dq.i[1])
  87.                 )
  88.             ]
  89.             if spi_width > 1:
  90.                 bitbang_logic += [
  91.                     dq.o.eq(Cat(self.bitbang.storage[0], Replicate(1, spi_width-1)))
  92.                 ]
  93.             else:
  94.                 bitbang_logic += [
  95.                     dq.o.eq(self.bitbang.storage[0])
  96.                 ]
  97.  
  98.             self.comb += \
  99.                 If(self.bitbang_en.storage,
  100.                     bitbang_logic
  101.                 ).Else(
  102.                     hw_read_logic
  103.                 )
  104.         else:
  105.             self.comb += hw_read_logic
  106.  
  107.         if div < 2:
  108.             raise ValueError("Unsupported value \'{}\' for div parameter for SpiFlash core".format(div))
  109.         else:
  110.             i = Signal(max=div)
  111.             dqi = Signal(spi_width)
  112.             self.sync += [
  113.                 If(i == div//2 - 1,
  114.                     clk.eq(1),
  115.                     dqi.eq(dq.i),
  116.                 ),
  117.                 If(i == div - 1,
  118.                     i.eq(0),
  119.                     clk.eq(0),
  120.                     sr.eq(Cat(dqi, sr[:-spi_width]))
  121.                 ).Else(
  122.                     i.eq(i + 1),
  123.                 ),
  124.             ]
  125.  
  126.         # spi is byte-addressed, prefix by zeros
  127.         z = Replicate(0, log2_int(wbone_width//8))
  128.  
  129.         seq = [
  130.             (cmd_width//spi_width*div,
  131.                 [dq_oe.eq(1), cs_n.eq(0), sr[-cmd_width:].eq(read_cmd)]),
  132.             (addr_width//spi_width*div,
  133.                 [sr[-addr_width:].eq(Cat(z, bus.adr))]),
  134.             ((dummy + wbone_width//spi_width)*div,
  135.                 [dq_oe.eq(0)]),
  136.             (1,
  137.                 [bus.ack.eq(1), cs_n.eq(1)]),
  138.             (div, # tSHSL!
  139.                 [bus.ack.eq(0)]),
  140.             (0,
  141.                 []),
  142.         ]
  143.  
  144.         # accumulate timeline deltas
  145.         t, tseq = 0, []
  146.         for dt, a in seq:
  147.             tseq.append((t, a))
  148.             t += dt
  149.  
  150.         self.sync += timeline(bus.cyc & bus.stb & (i == div - 1), tseq)
  151.  
  152.  
  153. class SpiFlashSingle(Module, AutoCSR):
  154.     def __init__(self, pads, dummy=8, div=2, with_bitbang=True):
  155.         """
  156.        Simple SPI flash, e.g. N25Q128 on the LX9 Microboard.
  157.  
  158.        Supports 1-bit reads. Only supports mode0 (cpol=0, cpha=0).
  159.        Optionally supports software bitbanging (for write, erase, or other commands).
  160.        """
  161.         self.bus = bus = wishbone.Interface()
  162.         if with_bitbang:
  163.             self.bitbang = CSRStorage(4)
  164.             self.miso = CSRStatus()
  165.             self.bitbang_en = CSRStorage()
  166.  
  167.         # # #
  168.  
  169.         cs_n = Signal(reset=1)
  170.         clk = Signal()
  171.         dq_oe = Signal()
  172.         wbone_width = len(bus.dat_r)
  173.  
  174.         read_cmd = _FAST_READ
  175.         cmd_width = 8
  176.         addr_width = 24
  177.  
  178.         pads.cs_n.reset = 1
  179.  
  180.         sr = Signal(max(8, addr_width, wbone_width))
  181.         self.comb += bus.dat_r.eq(sr)
  182.  
  183.         hw_read_logic = [
  184.             pads.clk.eq(clk),
  185.             pads.cs_n.eq(cs_n),
  186.             pads.mosi.eq(sr[-1:])
  187.         ]
  188.  
  189.         if with_bitbang:
  190.             bitbang_logic = [
  191.                 pads.clk.eq(self.bitbang.storage[1]),
  192.                 pads.cs_n.eq(self.bitbang.storage[2]),
  193.                 self.miso.status.eq(pads.miso),
  194.                 pads.mosi.eq(self.bitbang.storage[0]),
  195.             ]
  196.             self.comb += \
  197.                 If(self.bitbang_en.storage,
  198.                     bitbang_logic
  199.                 ).Else(
  200.                     hw_read_logic
  201.                 )
  202.         else:
  203.             self.comb += hw_read_logic
  204.  
  205.         if div < 2:
  206.             raise ValueError("Unsupported value \'{}\' for div parameter for SpiFlash core".format(div))
  207.         else:
  208.             i = Signal(max=div)
  209.             dqi = Signal(1)
  210.             self.sync += [
  211.                 If(i == div//2 - 1,
  212.                     clk.eq(1),
  213.                     dqi.eq(pads.miso),
  214.                 ),
  215.                 If(i == div - 1,
  216.                     i.eq(0),
  217.                     clk.eq(0),
  218.                     sr.eq(Cat(dqi, sr[:-1]))
  219.                 ).Else(
  220.                     i.eq(i + 1),
  221.                 ),
  222.             ]
  223.  
  224.         # spi is byte-addressed, prefix by zeros
  225.         z = Replicate(0, log2_int(wbone_width//8))
  226.  
  227.         seq = [
  228.             (cmd_width//div,
  229.                 [cs_n.eq(0), sr[-cmd_width:].eq(read_cmd)]),
  230.             (addr_width//div,
  231.                 [sr[-addr_width:].eq(Cat(z, bus.adr))]),
  232.             ((dummy + wbone_width)*div,
  233.                 []),
  234.             (1,
  235.                 [bus.ack.eq(1), cs_n.eq(1)]),
  236.             (div, # tSHSL!
  237.                 [bus.ack.eq(0)]),
  238.             (0,
  239.                 []),
  240.         ]
  241.  
  242.         # accumulate timeline deltas
  243.         t, tseq = 0, []
  244.         for dt, a in seq:
  245.             tseq.append((t, a))
  246.             t += dt
  247.  
  248.         self.sync += timeline(bus.cyc & bus.stb & (i == div - 1), tseq)
Add Comment
Please, Sign In to add comment