Advertisement
Guest User

Untitled

a guest
Jul 20th, 2016
118
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 13.46 KB | None | 0 0
  1. from itertools import product
  2.  
  3. from migen import *
  4. from misoc.interconnect.csr import *
  5.  
  6.  
  7. class SPIClockGen(Module):
  8.     def __init__(self, width):
  9.         self.load = Signal(width)
  10.         self.bias = Signal()  # bias this clock phase to longer times
  11.         self.edge = Signal()
  12.         self.clk = Signal(reset=1)
  13.  
  14.         cnt = Signal.like(self.load)
  15.         bias = Signal()
  16.         zero = Signal()
  17.         self.comb += [
  18.             zero.eq(cnt == 0),
  19.             self.edge.eq(zero & ~bias),
  20.         ]
  21.         self.sync += [
  22.             If(zero,
  23.                 bias.eq(0),
  24.             ).Else(
  25.                 cnt.eq(cnt - 1),
  26.             ),
  27.             If(self.edge,
  28.                 cnt.eq(self.load[1:]),
  29.                 bias.eq(self.load[0] & (self.clk ^ self.bias)),
  30.                 self.clk.eq(~self.clk),
  31.             )
  32.         ]
  33.  
  34.  
  35. class SPIRegister(Module):
  36.     def __init__(self, width):
  37.         self.data = Signal(width)
  38.         self.o = Signal()
  39.         self.i = Signal()
  40.         self.lsb = Signal()
  41.         self.shift = Signal()
  42.         self.sample = Signal()
  43.  
  44.         self.comb += [
  45.             self.o.eq(Mux(self.lsb, self.data[0], self.data[-1])),
  46.         ]
  47.         self.sync += [
  48.             If(self.shift,
  49.                 If(self.lsb,
  50.                     self.data[:-1].eq(self.data[1:]),
  51.                 ).Else(
  52.                     self.data[1:].eq(self.data[:-1]),
  53.                 )
  54.             ),
  55.             If(self.sample,
  56.                 If(self.lsb,
  57.                     self.data[-1].eq(self.i),
  58.                 ).Else(
  59.                     self.data[0].eq(self.i),
  60.                 )
  61.             )
  62.         ]
  63.  
  64.  
  65. class SPIBitCounter(Module):
  66.     def __init__(self, width):
  67.         self.n_read = Signal(width)
  68.         self.n_write = Signal(width)
  69.         self.read = Signal()
  70.         self.write = Signal()
  71.         self.done = Signal()
  72.  
  73.         self.comb += [
  74.             self.write.eq(self.n_write != 0),
  75.             self.read.eq(self.n_read != 0),
  76.             self.done.eq(~(self.write | self.read)),
  77.         ]
  78.         self.sync += [
  79.             If(self.write,
  80.                 self.n_write.eq(self.n_write - 1),
  81.             ).Elif(self.read,
  82.                 self.n_read.eq(self.n_read - 1),
  83.             )
  84.         ]
  85.  
  86.  
  87. class SPIMachine(Module):
  88.     def __init__(self, data_width, clock_width, bits_width):
  89.         ce = CEInserter()
  90.         self.submodules.cg = ce(SPIClockGen(clock_width))
  91.         self.submodules.reg = ce(SPIRegister(data_width))
  92.         self.submodules.bits = ce(SPIBitCounter(bits_width))
  93.         self.div_write = Signal.like(self.cg.load)
  94.         self.div_read = Signal.like(self.cg.load)
  95.         self.clk_phase = Signal()
  96.         self.start = Signal()
  97.         self.cs = Signal()
  98.         self.oe = Signal()
  99.         self.done = Signal()
  100.  
  101.         # # #
  102.  
  103.         fsm = CEInserter()(FSM("IDLE"))
  104.         self.submodules += fsm
  105.  
  106.         fsm.act("IDLE",
  107.             If(self.start,
  108.                 If(self.clk_phase,
  109.                     NextState("WAIT"),
  110.                 ).Else(
  111.                     NextState("SETUP"),
  112.                 )
  113.             )
  114.         )
  115.         fsm.act("SETUP",
  116.             self.reg.sample.eq(1),
  117.             NextState("HOLD"),
  118.         )
  119.         fsm.act("HOLD",
  120.             If(self.bits.done & ~self.start,
  121.                 If(self.clk_phase,
  122.                     NextState("IDLE"),
  123.                 ).Else(
  124.                     NextState("WAIT"),
  125.                 )
  126.             ).Else(
  127.                 self.reg.shift.eq(~self.start),
  128.                 NextState("SETUP"),
  129.             )
  130.         )
  131.         fsm.act("WAIT",
  132.             If(self.bits.done,
  133.                 NextState("IDLE"),
  134.             ).Else(
  135.                 NextState("SETUP"),
  136.             )
  137.         )
  138.  
  139.         write0 = Signal()
  140.         self.sync += [
  141.             If(self.cg.edge & self.reg.shift,
  142.                 write0.eq(self.bits.write),
  143.             )
  144.         ]
  145.         self.comb += [
  146.             self.cg.ce.eq(self.start | self.cs | ~self.cg.edge),
  147.             If(self.bits.write | ~self.bits.read,
  148.                 self.cg.load.eq(self.div_write),
  149.             ).Else(
  150.                 self.cg.load.eq(self.div_read),
  151.             ),
  152.             self.cg.bias.eq(self.clk_phase),
  153.             fsm.ce.eq(self.cg.edge),
  154.             self.cs.eq(~fsm.ongoing("IDLE")),
  155.             self.reg.ce.eq(self.cg.edge),
  156.             self.bits.ce.eq(self.cg.edge & self.reg.sample),
  157.             self.done.eq(self.cg.edge & self.bits.done & fsm.ongoing("HOLD")),
  158.             self.oe.eq(write0 | self.bits.write),
  159.         ]
  160.  
  161.  
  162. class SPIMasterCore(Module):
  163.     """SPI Master Core.
  164.  
  165.    Notes:
  166.        * M = 32 is the data width (maximum write bits, maximum read bits)
  167.        * Every transfer consists of a write_length 0-M bit write followed
  168.          by a read_length 0-M bit read.
  169.        * cs_n is asserted at the beginning and deasserted at the end of the
  170.          transfer if there is no other transfer pending.
  171.        * cs_n handling is agnostic to whether it is one-hot or decoded
  172.          somewhere downstream. If it is decoded, "cs_n all deasserted"
  173.          should be handled accordingly (no slave selected).
  174.          If it is one-hot, asserting multiple slaves should only be attempted
  175.          if miso is either not connected between slaves, or open collector,
  176.          or correctly multiplexed externally.
  177.        * If config.cs_polarity == 0 (cs active low, the default),
  178.          "cs_n all deasserted" means "all cs_n bits high".
  179.        * cs is not mandatory in pads. Framing and chip selection can also
  180.          be handled independently through other means.
  181.        * If there is a miso wire in pads, the input and output can be done
  182.          with two signals (a.k.a. 4-wire SPI), else mosi must be used for
  183.          both output and input (a.k.a. 3-wire SPI) and config.half_duplex
  184.          must to be set when reading data is desired.
  185.        * For 4-wire SPI only the sum of read_length and write_length matters.
  186.          The behavior is the same no matter how the total transfer length is
  187.          divided between the two. For 3-wire SPI, the direction of mosi/miso
  188.          is switched from output to input after write_len cycles, at the
  189.          "shift_out" clk edge corresponding to bit write_length + 1 of the
  190.          transfer.
  191.        * The first bit output on mosi is always the MSB/LSB (depending on
  192.          config.lsb_first) of the miso_data signal, independent of
  193.          xfer.write_len. The last bit input from miso always ends up in
  194.          the LSB/MSB (respectively) of the misoc_data signal, independent of
  195.          read_len.
  196.        * Data output on mosi in 4-wire SPI during the read cycles is what
  197.          is found in the data register at the time.
  198.          Data in the data register outside the least/most (depending
  199.          on config.lsb_first) significant read_length bits is what is
  200.          seen on miso during the write cycles.
  201.        * The SPI data register is double-buffered: Once a transfer has
  202.          started, new write data can be written, queuing a new transfer.
  203.          Transfers submitted this way are chained and executed without
  204.          deasserting cs. Once a transfer completes, the previous transfer's
  205.          read data is available in the data register.
  206.        * Changes to config signal take effect immediately. Changes
  207.          to xfer_* signals are synchronized to the start of a transfer.
  208.  
  209.    Transaction Sequence:
  210.        * If desired, set the config signal to set up the core.
  211.        * If designed, set the xfer signal to set up lengths and cs_n.
  212.        * Set the miso_data signal (not required for zero-length writes),
  213.        * Set start signal to 1
  214.        * Wait for active and pending signals to be 0.
  215.        * If desired, use the misoc_data signal corresponding to the last
  216.          completed transfer.
  217.  
  218.    Core IOs:
  219.  
  220.    config signal:
  221.        1 offline: all pins high-z (reset=1)
  222.        1 active: cs/transfer active (read-only)
  223.        1 pending: transfer pending in intermediate buffer (read-only)
  224.        1 cs_polarity: active level of chip select (reset=0)
  225.        1 clk_polarity: idle level of clk (reset=0)
  226.        1 clk_phase: first edge after cs assertion to sample data on (reset=0)
  227.            (clk_polarity, clk_phase) == (CPOL, CPHA) in Freescale language.
  228.            (0, 0): idle low, output on falling, input on rising
  229.            (0, 1): idle low, output on rising, input on falling
  230.            (1, 0): idle high, output on rising, input on falling
  231.            (1, 1): idle high, output on falling, input on rising
  232.            There is never a clk edge during a cs edge.
  233.        1 lsb_first: LSB is the first bit on the wire (reset=0)
  234.        1 half_duplex: 3-wire SPI, in/out on mosi (reset=0)
  235.        8 undefined
  236.        8 div_write: counter load value to divide this module's clock
  237.            to generate the SPI write clk (reset=0)
  238.            f_clk/f_spi_write == div_write + 2
  239.        8 div_read: ditto for the read clock
  240.  
  241.    xfer_config signal:
  242.        16 cs: active high bit mask of chip selects to assert (reset=0)
  243.        6 write_len: 0-M bits (reset=0)
  244.        2 undefined
  245.        6 read_len: 0-M bits (reset=0)
  246.        2 undefined
  247.  
  248.    xfer_mosi/miso_data signal:
  249.        M write/read data (reset=0)
  250.    """
  251.     def __init__(self, pads):
  252.         self.config = Record([
  253.             ("offline", 1),
  254.             ("padding0", 2),
  255.             ("cs_polarity", 1),
  256.             ("clk_polarity", 1),
  257.             ("clk_phase", 1),
  258.             ("lsb_first", 1),
  259.             ("half_duplex", 1),
  260.             ("padding1", 8),
  261.             ("div_write", 8),
  262.             ("div_read", 8),
  263.         ])
  264.         self.config.offline.reset = 1
  265.  
  266.         self.xfer = Record([
  267.             ("cs", 16),
  268.             ("write_length", 6),
  269.             ("padding0", 2),
  270.             ("read_length", 6),
  271.             ("padding1", 2),
  272.         ])
  273.  
  274.         self.start = Signal()
  275.         self.active = Signal()
  276.         self.pending = Signal()
  277.         self.mosi_data = Signal(32)
  278.         self.miso_data = Signal(32)
  279.  
  280.         # # #
  281.  
  282.         self.submodules.machine = machine = SPIMachine(
  283.             data_width=32,
  284.             clock_width=len(self.config.div_read),
  285.             bits_width=len(self.xfer.read_length))
  286.  
  287.         pending = Signal()
  288.         cs = Signal.like(self.xfer.cs)
  289.         data_read = Signal.like(machine.reg.data)
  290.         data_write = Signal.like(machine.reg.data)
  291.  
  292.         self.comb += [
  293.             self.miso_data.eq(data_read),
  294.             machine.start.eq(pending & (~machine.cs | machine.done)),
  295.             machine.clk_phase.eq(self.config.clk_phase),
  296.             machine.reg.lsb.eq(self.config.lsb_first),
  297.             machine.div_write.eq(self.config.div_write),
  298.             machine.div_read.eq(self.config.div_read),
  299.         ]
  300.         self.sync += [
  301.             If(machine.done,
  302.                 data_read.eq(machine.reg.data),
  303.             ),
  304.             If(machine.start,
  305.                 cs.eq(self.xfer.cs),
  306.                 machine.bits.n_write.eq(self.xfer.write_length),
  307.                 machine.bits.n_read.eq(self.xfer.read_length),
  308.                 machine.reg.data.eq(data_write),
  309.                 pending.eq(0),
  310.             ),
  311.             If(self.start,
  312.                 data_write.eq(self.mosi_data),
  313.                 pending.eq(1)
  314.             ),
  315.             self.active.eq(machine.cs),
  316.             self.pending.eq(pending),
  317.         ]
  318.  
  319.         # I/O
  320.         if hasattr(pads, "cs_n"):
  321.             cs_n_t = TSTriple(len(pads.cs_n))
  322.             self.specials += cs_n_t.get_tristate(pads.cs_n)
  323.             self.comb += [
  324.                 cs_n_t.oe.eq(~self.config.offline),
  325.                 cs_n_t.o.eq((cs & Replicate(machine.cs, len(cs))) ^
  326.                             Replicate(~self.config.cs_polarity, len(cs))),
  327.             ]
  328.  
  329.         clk_t = TSTriple()
  330.         self.specials += clk_t.get_tristate(pads.clk)
  331.         self.comb += [
  332.             clk_t.oe.eq(~self.config.offline),
  333.             clk_t.o.eq((machine.cg.clk & machine.cs) ^ self.config.clk_polarity),
  334.         ]
  335.  
  336.         mosi_t = TSTriple()
  337.         self.specials += mosi_t.get_tristate(pads.mosi)
  338.         self.comb += [
  339.             mosi_t.oe.eq(~self.config.offline & machine.cs &
  340.                          (machine.oe | ~self.config.half_duplex)),
  341.             mosi_t.o.eq(machine.reg.o),
  342.             machine.reg.i.eq(Mux(self.config.half_duplex, mosi_t.i,
  343.                              getattr(pads, "miso", mosi_t.i))),
  344.         ]
  345.  
  346.  
  347. class SPIMaster(Module, AutoCSR):
  348.     """SPI Master."""
  349.     def __init__(self, pads, interface="csr"):
  350.         self.submodules.core = core = SPIMasterCore(pads)
  351.  
  352.         # # #
  353.  
  354.         if interface == "csr":
  355.             self.config = CSRStorage(32)
  356.             self.xfer = CSRStorage(32)
  357.             self.start = CSR()
  358.             self.active = CSRStatus()
  359.             self.pending = CSRStatus()
  360.             self.mosi_data = CSRStorage(32)
  361.             self.miso_data = CSRStatus(32)
  362.  
  363.             self.comb += [
  364.                 core.config.raw_bits().eq(self.config.storage),
  365.                 core.xfer.raw_bits().eq(self.xfer.storage),
  366.                 core.start.eq(self.start.re & self.start.r),
  367.                 self.active.status.eq(core.active),
  368.                 self.pending.status.eq(core.pending),
  369.                 core.mosi_data.eq(self.mosi_data.storage),
  370.                 self.miso_data.status.eq(core.miso_data)
  371.             ]
  372.         else:
  373.             raise NotImplementedError
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement