Пример #1
0
 def __init__(self):
     self._storage = csr.CSRStorage(fields=[
         csr.CSRField(
             "foo", size=4, offset=0, reset=0xa, description="foo"),
         csr.CSRField("bar",
                      size=8,
                      offset=16,
                      reset=0x5a,
                      description="bar")
     ])
     self._status = csr.CSRStatus(fields=[
         csr.CSRField("foo", size=4, offset=4, description="foo"),
         csr.CSRField("bar", size=8, offset=8, description="bar")
     ])
     self.comb += [
         self._status.fields.foo.eq(self._storage.fields.foo),
         self._status.fields.bar.eq(self._storage.fields.bar),
     ]
Пример #2
0
    def __init__(self):
        self._csr = csr.CSR()
        self._storage = csr.CSRStorage(32,
                                       reset=0x12345678,
                                       write_from_dev=True)
        self._status = csr.CSRStatus(32, reset=0x12345678)

        # # #

        # When csr is written:
        # - set storage to 0xdeadbeef
        # - set status to storage value
        self.comb += [
            If(self._csr.re, self._storage.we.eq(1),
               self._storage.dat_w.eq(0xdeadbeef))
        ]
        self.sync += [
            If(self._csr.re, self._status.status.eq(self._storage.storage))
        ]
Пример #3
0
    def __init__(self, pads, num):

        self._status = csr.CSRStatus(32, name='status', reset=0xadc)
        self._control = csr.CSRStorage(32, name='control')

        # just make sure these pads exist:

        pads.d_p
        pads.d_n
        pads.fclk_p
        pads.fclk_n
        pads.lclk_p
        pads.lclk_n

        # input delay control; doesn't seem required so not hooked up.

        self.rx_delay_rst = Signal()
        self.rx_delay_inc = Signal()

        self.bitslip_do = Signal()

        N_CHANNELS = len(pads.d_p)

        self.d_preslip = Signal(N_CHANNELS * 8)
        self.d = Signal(N_CHANNELS * 8)
        self.fclk = Signal(8)
        self.d_clk = Signal()
        self.d_rst = Signal()
        self.d_valid = Signal() # output
        self.d_last = Signal()
        self.d_ready = Signal() # input

        self.fclk_preslip = Signal(8)

        # rx clock:
        # pads.lclk_p/n -> IBUFDS  -> lclk_i

        lclk_i = Signal()
        lclk_i_bufio = Signal()

        self.clock_domains.cd_lclkdiv = ClockDomain()

        self.specials += MultiReg(self._control.storage[0], self.cd_lclkdiv.rst, "lclkdiv")

        self.specials += [
            Instance("IBUFDS",
                i_I=pads.lclk_p,
                i_IB=pads.lclk_n,
                o_O=lclk_i
            ),
            Instance("BUFIO", i_I=lclk_i, o_O=lclk_i_bufio),
            Instance("BUFR", i_I=lclk_i, o_O=self.cd_lclkdiv.clk, p_BUFR_DIVIDE="4"),
        ]

        # frame clock

        for i in range(N_CHANNELS + 1):

            if i == N_CHANNELS: # fclk
                d_p = pads.fclk_p
                d_n = pads.fclk_n
            else:
                d_p = pads.d_p[i]
                d_n = pads.d_n[i]

            # pad -> IBUFDS_DIFF_OUT
            serdes_i_nodelay = Signal()
            self.specials += [
                Instance("IBUFDS_DIFF_OUT",
                    i_I=d_p,
                    i_IB=d_n,
                    o_O=serdes_i_nodelay
                )
            ]

            serdes_i_delayed = Signal()
            serdes_q = Signal(8)
            self.specials += [
                Instance("IDELAYE2",
                    p_DELAY_SRC="IDATAIN", p_SIGNAL_PATTERN="DATA",
                    p_CINVCTRL_SEL="FALSE", p_HIGH_PERFORMANCE_MODE="TRUE",
                    p_REFCLK_FREQUENCY=200.0, p_PIPE_SEL="FALSE",
                    p_IDELAY_TYPE="VARIABLE", p_IDELAY_VALUE=0,

                    i_C=self.cd_lclkdiv.clk,
                    i_LD=self.rx_delay_rst,
                    i_CE=self.rx_delay_inc,
                    i_LDPIPEEN=0, i_INC=1,

                    i_IDATAIN=serdes_i_nodelay, o_DATAOUT=serdes_i_delayed
                ),
                Instance("ISERDESE2",
                    p_DATA_WIDTH=8, p_DATA_RATE="DDR",
                    p_SERDES_MODE="MASTER", p_INTERFACE_TYPE="NETWORKING",
                    p_NUM_CE=1, p_IOBDELAY="IFD",
                    i_DDLY=serdes_i_delayed,
                    i_CE1=1,
                    i_RST=self.cd_lclkdiv.rst,
                    i_CLK=lclk_i_bufio,
                    i_CLKB=~lclk_i_bufio,
                    i_CLKDIV=self.cd_lclkdiv.clk,
                    i_BITSLIP=self.bitslip_do,
                    o_Q8=serdes_q[0], o_Q7=serdes_q[1],
                    o_Q6=serdes_q[2], o_Q5=serdes_q[3],
                    o_Q4=serdes_q[4], o_Q3=serdes_q[5],
                    o_Q2=serdes_q[6], o_Q1=serdes_q[7]
                )
            ]

            if i == N_CHANNELS:
                self.comb += self.fclk_preslip.eq(serdes_q)
            else:
                self.comb += self.d_preslip[i*8:i*8+8].eq(serdes_q)


        # async fifo
        # fclk_preslip || d_preslip (in lclkdiv clock domain) -> data clock domain

        self.clock_domains.cd_data = ClockDomain()
        self.comb += self.cd_data.clk.eq(self.d_clk)
        self.comb += self.cd_data.rst.eq(self.d_rst)

        data_fifo = AsyncFIFOBuffered((N_CHANNELS + 1) * 8, 64)
        self.submodules.fifo = ClockDomainsRenamer({"write": "lclkdiv", "read": "data"})(data_fifo)

        # data -> FIFO

        bitslip_delay = Signal(16)

        for i in range(N_CHANNELS + 1):

            # FIFO data layout:
            # low 8*N_CHANNELS bits is data,
            # upper 8 bits is FCLK
            if i == N_CHANNELS:
                src = self.fclk_preslip
            else:
                src = self.d_preslip[i*8:i*8+8]

            self.sync.lclkdiv += [
                data_fifo.din[i*8:i*8+8].eq(src),
            ]

            # bitslip handling:
            # every once in a while (64k ticks), if the FCLK pattern doesn't match, increment bitslip.
            # (why only ever 64k? just to make debugging easier. could be reduced or even removed.)
            if i == N_CHANNELS:
                self.sync.lclkdiv += [
                    bitslip_delay.eq(bitslip_delay + 1),
                    self.bitslip_do.eq(((src != 0x0F) & (src != 0x33) & (src != 0x55)) & (bitslip_delay == 0)),
                ]

        self.last_counter = Signal(max=16383)

        self.sync += [
            If(self.d_valid & self.d_ready,
                If(self.last_counter == 16383,
                    self.last_counter.eq(0)
                ).Else(
                    self.last_counter.eq(self.last_counter + 1)
                )
            )
        ]

        self.comb += [
            data_fifo.we.eq(1),
            data_fifo.re.eq(self.d_ready),
            self.d.eq(data_fifo.dout[:N_CHANNELS*8]),
            self.fclk.eq(data_fifo.dout[N_CHANNELS*8:N_CHANNELS*8+8]),
            self.d_valid.eq(data_fifo.readable),
            self.d_last.eq(self.last_counter == 16383)
        ]

        if num == 0:
            self.specials += [
                Instance("IDELAYCTRL",
                    i_REFCLK=ClockSignal(),
                    i_RST=ResetSignal(),
                )
            ]
Пример #4
0
    def __init__(self):
        self._status = csr.CSRStatus(32, name='status', reset=0x0ffdac)
        self.spi = Record(SPI)
        self.mux = Record(MUX)

        self._control = csr.CSRStorage(32, name='control') # DAC PD control
        self._clkdiv = csr.CSRStorage(32, name='clkdiv', reset=326) # roughly matches original timing
        self._enable = csr.CSRStorage(32, name='enable', reset=1)

        self._v0 = csr.CSRStorage(32, name='v0', reset = 0x8000) # unused
        self._v1 = csr.CSRStorage(32, name='v1', reset = 0x8000) # unused
        self._v2 = csr.CSRStorage(32, name='v2', reset = 0x8000) # unused
        self._v3 = csr.CSRStorage(32, name='v3', reset = 0x8000) # unused
        self._v4 = csr.CSRStorage(32, name='v4', reset = 0x8000) # CH1 offset
        self._v5 = csr.CSRStorage(32, name='v5', reset = 0x8000) # CH2 offset
        self._v6 = csr.CSRStorage(32, name='v6', reset = 0x8000) # CH3 offset
        self._v7 = csr.CSRStorage(32, name='v7', reset = 0x8000) # CH4 offset

        # data is transferred on falling edge of SCLK while nSYNC=0
        # data is MSB-first
        # on 24th bit, data is updated.
        # | 6 bits | 2 bits  | 16 bits |
        # | XXXXXX | PD1,PD0 | data    |
        # PD: 0 - normal
        #     1 - 1k to GND
        #     2 - 100k to GND
        #     3 - Hi-Z

        # MUX sequence:
        # A single DAC is used and connected to a 74HC4051 (8-channel
        # analog multiplexer/demultiplexer)
        # The DAC output is connected to the MUX "Z" pin
        # Z is connnected to the output selected by S if
        # /E is low, otherwise left unconnected.

        # TIMING:
        # /E high pulse is ~8.1us
        # SPI clock rate: 250kHz
        # repetition rate: 9.8kHz => 1/25.5 of SPI clock rate
        #
        # So DAC SPI clock is constantly running, /E is deactivated
        # during the DAC transition for 2 cycles

        # wavedrom file:
        """{signal: [
    ["DAC",
     {name: 'SCLK',  wave: 'n............................'},
     {name: 'DIN',   wave: '2.0xxxxxx2.3...............0x', data: ["Value-1", "PD", "Value"]},
     {name: 'nSYNC', wave: '0.10.......................10'},
     {name: 'OUT',   wave: 'z.1........................z.'},
    ],

    ["MUX",
     {name: 'nE',    wave: '01.0......................1.0'},
     {name: 'S',     wave: '2.2........................3.', data: ["S-2", "S-1", "S"]},
    ],
]}
        """


        # CLK divider

        clkdiv = Signal(16)
        self.sync += [
            If(clkdiv == self._clkdiv.storage[:16],
                clkdiv.eq(0)
            ).Else(
                clkdiv.eq(clkdiv + 1),
            )
        ]

        clk = Signal()

        clk_falling = Signal()

        self.sync += [
            clk_falling.eq(0),
            If(clkdiv == 0,
                clk.eq(~clk),
                clk_falling.eq(~clk)
            ),
        ]

        # FSM

        self.submodules.fsm = FSM(reset_state='start')

        dac_data = Array([self._v0.storage, self._v1.storage, self._v2.storage, self._v3.storage,
                          self._v4.storage, self._v5.storage, self._v6.storage, self._v7.storage])

        current_bit = Signal(max=24)
        current_channel = Signal(max=8)

        pd = Signal(2)
        pd.eq(self._control.storage[:2])

        current_dac_word = Signal(24)
        self.comb += [
            current_dac_word[0:16].eq(dac_data[current_channel][:16]),
            current_dac_word[16:18].eq(pd),
            current_dac_word[18:24].eq(0)
        ]

        self.fsm.act('start',
            If(clk_falling,
                NextValue(current_bit, 0),
                NextValue(self.mux.nE, 1),
                NextValue(self.spi.nSYNC, 1),
                NextValue(self.spi.DIN, 0),
                If(self._enable.storage[0],
                    NextState('transfer'),
                ).Else(
                    NextValue(current_channel, 0),
                ),
            )
        )

        self.fsm.act('transfer',
            If(clk_falling,
                NextValue(self.spi.nSYNC, 0),
                NextValue(self.mux.nE, 0),
                NextValue(self.spi.DIN, Array(current_dac_word)[23 - current_bit]),
                If(current_bit == 23,
                    NextValue(self.mux.nE, 1),
                    NextState('start'),
                    NextValue(self.mux.S, current_channel),
                    NextValue(current_channel, current_channel + 1)
                ).Else(NextValue(current_bit, current_bit + 1))
            )
        )

        # output SPI CLK (if enabled)
        self.sync += self.spi.SCLK.eq(clk & self._enable.storage[0])