Exemple #1
0
 def __init__(self, polynom=0x07):
     self.submodules.crc = LiteEthMACCRCEngine(data_width=8,
                                               width=8,
                                               polynom=polynom)
     self.din = Signal(8)
     self.comb += self.crc.data.eq(self.din[::-1])
     self.sync += self.crc.last.eq(self.crc.next)
Exemple #2
0
    def __init__(self, n_data, t_clk, n_frame):
        n_word = n_data*t_clk
        n_marker = n_frame//2 + 1
        n_crc = n_data

        self.data = Signal(n_data)
        self.data_stb = Signal()
        self.end_of_frame = Signal()
        self.frame = Signal(n_word*n_frame - n_marker - n_crc)
        self.frame_stb = Signal()
        self.crc_err = Signal(8)
        # response bitstream
        self.miso = Signal(reset_less=True)
        # response data, latched on end_of_frame
        self.response = Signal(n_frame*t_clk, reset_less=True)

        poly = {
            # 6: 0x27,  # CRC-6-CDMA2000-A
            6: 0x2f,  # CRC-6-GSM
        }[n_data]
        self.submodules.crc = LiteEthMACCRCEngine(
            data_width=n_data, width=n_data, polynom=poly)
        self.crc.last.reset_less = True
        crc_good = Signal()
        crc = Signal.like(self.crc.last, reset_less=True)
        self.comb += [
            crc_good.eq(self.crc.next == 0),
            # crc_good.eq(1),  # TODO
            # LiteEthMACCRCEngine takes LSB first
            self.crc.data.eq(self.data[::-1]),
        ]
        self.sync += [
            self.crc.last.eq(self.crc.next),
            If(self.end_of_frame | ~self.data_stb,
                self.crc.last.eq(0),
                If(~crc_good,
                    self.crc_err.eq(self.crc_err + 1),
                ),
            ),
        ]

        frame_buf = Signal(n_word*n_frame, reset_less=True)
        self.sync += [
            frame_buf.eq(Cat(self.data, frame_buf)),
            self.frame_stb.eq(self.end_of_frame & crc_good & self.data_stb),
        ]

        frame_parts = []
        for i in range(n_frame):
            if i == 0:
                offset = n_crc
            elif i < n_marker + 1:
                offset = 1
            else:
                offset = 0
            frame_parts.append(frame_buf[i*n_word + offset: (i + 1)*n_word])
        assert len(Cat(frame_parts)) == len(self.frame)
        self.comb += self.frame.eq(Cat(frame_parts))

        response_sr = Signal.like(self.response)
        self.comb += self.miso.eq(response_sr[-1])
        self.sync += [
            response_sr[1:].eq(response_sr),
            If(self.frame_stb,
                response_sr.eq(self.response),
            )
        ]
Exemple #3
0
    def __init__(self, mems):
        self.sink = Endpoint(bus_layout)
        self.source = Endpoint(bus_layout)
        self.board = Signal(4)

        # mapped registers
        self.config = Record([
            ("reset", 1),
            ("clk2x", 1),
            ("enable", 1),
            ("trigger", 1),
            ("aux_miso", 1),
            ("aux_dac", 3),
        ])
        self.checksum = Signal(8)
        self.frame = Signal(max=32)

        ###

        # CRC8-CCIT
        crc = LiteEthMACCRCEngine(data_width=8, width=8, polynom=0x07)
        self.submodules += crc

        self.comb += [
            crc.data.eq(self.sink.data[::-1]),
            crc.last.eq(self.checksum),
        ]
        self.sync += [
            If(
                self.sink.stb & ~self.sink.eop & ~self.source.stb,
                self.checksum.eq(crc.next),
            ),
        ]

        cmd_layout = [
            ("adr", 2),  # reg or mem
            ("is_mem", 1),  # is_mem/is_reg_n
            ("board", 4),  # 0xf: broadcast
            ("we", 1),  # write/read_n
        ]
        cmd_cur = Record(cmd_layout)
        self.comb += cmd_cur.raw_bits().eq(self.sink.data)
        cmd = Record(cmd_layout)

        reg_map = Array([self.config.raw_bits(), self.checksum, self.frame])
        reg_we = Signal()
        self.sync += [If(
            reg_we,
            reg_map[cmd.adr].eq(self.sink.data),
        )]

        mems = [
            mem.get_port(write_capable=True, we_granularity=8) for mem in mems
        ]
        self.specials += mems
        mem_adr = Signal(16)
        mem_we = Signal()
        mem_dat_r = Signal(16)
        self.comb += [
            self.sink.ack.eq(1),
            [[
                mem.adr.eq(mem_adr[1:]),
                mem.dat_w.eq(Replicate(self.sink.data, 2)),
            ] for mem in mems],
            If(
                mem_we,
                Array([mem.we for mem in mems
                       ])[cmd.adr].eq(Mux(mem_adr[0], 0b10, 0b01)),
            ),
            mem_dat_r.eq(Array([mem.dat_r for mem in mems])[cmd.adr]),
        ]

        fsm = ResetInserter()(CEInserter()(FSM(reset_state="CMD")))
        self.submodules += fsm
        self.comb += [
            fsm.reset.eq(self.sink.eop),
            fsm.ce.eq(self.sink.stb),
        ]

        fsm.act(
            "CMD",
            If(
                (cmd_cur.board == self.board) | (cmd_cur.board == 0xf),
                If(
                    cmd_cur.is_mem,
                    NextState("MEM_ADRL"),
                ).Else(NextState("REG_DO"), ),
            ).Else(NextState("IGNORE"), ),
        )
        fsm.act("IGNORE", NextState("IGNORE"))
        fsm.act(
            "REG_DO",
            self.source.stb.eq(self.sink.stb & ~cmd.we),
            reg_we.eq(self.sink.stb & cmd.we),
            self.source.data.eq(reg_map[cmd.adr]),
            NextState("IGNORE"),
        )
        fsm.act(
            "MEM_ADRL",
            NextState("MEM_ADRH"),
        )
        fsm.act(
            "MEM_ADRH",
            NextState("MEM_DO"),
        )
        fsm.act(
            "MEM_DO",
            mem_we.eq(self.sink.stb & cmd.we),
            self.source.stb.eq(self.sink.stb & ~cmd.we),
            self.source.data.eq(Mux(mem_adr[0], mem_dat_r[8:], mem_dat_r[:8])),
        )
        self.sync += [
            If(
                fsm.before_leaving("CMD"),
                cmd.raw_bits().eq(self.sink.data),
            ),
            If(
                fsm.before_leaving("MEM_ADRL"),
                mem_adr[:8].eq(self.sink.data),
            ),
            If(
                fsm.before_leaving("MEM_ADRH"),
                mem_adr[8:].eq(self.sink.data),
            ),
            If(
                fsm.ongoing("MEM_DO") & self.sink.stb,
                mem_adr.eq(mem_adr + 1),
            ),
        ]
Exemple #4
0
    def __init__(self, n_data=8, t_clk=7, d_clk=0b1100011,
                 n_frame=14, n_crc=12, poly=0x80f):
        """DDR fast link.

        * One word clock lane with `t_clk` period.
        * Multiple data lanes at DDR speed.
        * One return data lane at slower speed.
        * n_frame//2 - 1 marker bits are used to provide framing.

        * `n_data` lanes
        * `t_clk` bits per clk cycle with pattern `d_clk`
        * `n_frame` words per frame
        * `n_crc` CRC bits per frame for divisor poly `poly`
        """
        # pins
        self.data = [Signal(2, reset_less=True) for _ in range(n_data)]
        n_mosi = n_data - 2  # mosi lanes
        n_word = n_mosi*t_clk  # bits per word
        t_frame = t_clk*n_frame  # frame duration
        n_marker = n_frame//2 + 1
        n_body = n_word*n_frame - n_marker - n_crc
        t_miso = 0  # miso sampling latency  TODO
        assert n_crc % n_mosi == 0

        # frame data
        self.payload = Signal(n_body)
        # readback data
        self.readback = Signal(n_frame, reset_less=True)
        # data load synchronization event
        self.stb = Signal()

        # # #

        self.submodules.crca = LiteEthMACCRCEngine(
            data_width=n_mosi, width=n_crc, polynom=poly)
        self.submodules.crcb = LiteEthMACCRCEngine(
            data_width=n_mosi, width=n_crc, polynom=poly)

        words_ = []
        j = 0
        # build from LSB to MSB because MSB first
        for i in range(n_frame):  # iterate over words
            if i == 0:  # data and checksum
                words_.append(C(0, n_crc))
                k = n_word - n_crc
            elif i == 1:  # marker
                words_.append(C(1))
                k = n_word - 1
            elif i < n_frame//2 + 2:  # marker
                words_.append(C(0))
                k = n_word - 1
            else:  # full word
                k = n_word
            # append corresponding frame body bits
            words_.append(self.payload[j:j + k])
            j += k
        words_ = Cat(words_)
        assert len(words_) == n_frame*n_word
        words = Signal(len(words_))
        self.comb += words.eq(words_)

        clk = Signal(t_clk, reset=d_clk)
        i = Signal(max=t_frame//2)
        # big shift register for mosi and
        sr = [Signal(t_frame, reset_less=True) for i in range(n_mosi)]
        assert len(Cat(sr)) == len(words)
        crc_insert = Cat(([d[0] for d in self.data[1:-1]] +
                          [d[1] for d in self.data[1:-1]])[:n_crc])
        miso_sr = Signal(t_frame, reset_less=True)
        miso_sr_next = Signal.like(miso_sr)
        self.comb += [
            self.stb.eq(i == t_frame//2 - 1),
            # LiteETHMACCRCEngine takes data LSB first
            self.crca.data.eq(Cat([sri[-1] for sri in sr[::-1]])),
            self.crcb.data.eq(Cat([sri[-2] for sri in sr[::-1]])),
            self.crcb.last.eq(self.crca.next),
            miso_sr_next.eq(Cat(self.data[-1], miso_sr)),
            # unload miso
            # TODO: align to marker
            self.readback.eq(Cat([miso_sr_next[t_miso + i*t_clk]
                                  for i in range(n_frame)])),
        ]
        self.sync.rio_phy += [
            # shift everything by two bits
            [di.eq(sri[-2:]) for di, sri in zip(self.data, [clk] + sr)],
            clk.eq(Cat(clk[-2:], clk)),
            [sri.eq(Cat(C(0, 2), sri)) for sri in sr],
            miso_sr.eq(miso_sr_next),
            self.crca.last.eq(self.crcb.next),
            i.eq(i + 1),
            If(self.stb,
                i.eq(0),
                clk.eq(clk.reset),
                self.crca.last.eq(0),
                # transpose, load
                [sri.eq(Cat(words[i::n_mosi])) for i, sri in enumerate(sr)],
                # inject crc for the last cycle
                crc_insert.eq(self.crca.next if n_crc // n_mosi <= 1
                              else self.crca.last),
            ),
        ]
Exemple #5
0
    def __init__(self, n_frame=14):
        n = 7 * 6
        # input word from link
        self.word = Signal(n)
        checksum = Signal(12, reset_less=True)
        self.submodules.crc = LiteEthMACCRCEngine(
            data_width=n, width=len(checksum), polynom=0x80f)  # crc-12 telco
        # frame body
        self.body = Signal(n_frame * n - n_frame // 2 - 1 - len(checksum))
        self.stb = Signal()
        self.crc_err = Signal(8)

        # frame: n_frame = 14
        # 0: body(n_word)
        # ...
        # n_frame//2 - 4: body(n_word)
        # ...
        # n_frame//2 - 3: marker(1), body(n_word - 1)
        # ...
        # n_frame - 2: marker(1), body(n_word - 1)
        # n_frame - 1: crc(n_crc = 12), body(n_word - 12)
        # n_body = n_frame*n_word - n_frame//2 - 1 - n_crc

        eof = Signal()
        frame = Signal(n * n_frame, reset_less=True)
        crc_good = Signal()

        body_ = Cat(
            # checksum in the most recent word
            frame[len(checksum):n],
            # skip eof marker bits in the next n_frame//2 + 1 words
            [frame[1 + i * n:(i + 1) * n] for i in range(1, 2 + n_frame // 2)],
            # complete words
            frame[(2 + n_frame // 2) * n:],
        )
        assert len(body_) == len(self.body)

        self.comb += [
            self.crc.last.eq(checksum),
            # LiteEthMACCRCEngine takes LSB first
            self.crc.data[::-1].eq(self.word),
            self.body.eq(body_),
            # CRC([x, CRC(x)]) == 0
            crc_good.eq(self.crc.next == 0),
        ]
        self.sync += [
            eof.eq(
                Cat(self.word[0], [frame[i * n]
                                   for i in range(n_frame // 2)]) == 1),
            self.stb.eq(eof & crc_good),
            frame.eq(Cat(self.word, frame)),
            checksum.eq(self.crc.next),
            If(
                eof,
                checksum.eq(0),
                If(
                    ~crc_good,
                    self.crc_err.eq(self.crc_err + 1),
                ),
            ),
        ]
Exemple #6
0
    def __init__(self, pins, pins_n):
        n_bits = 16  # bits per dac data word
        n_channels = 32  # channels per fastino
        n_div = 7  # bits per lane and word
        assert n_div == 7
        n_frame = 14  # word per frame
        n_lanes = len(pins.mosi)  # number of data lanes
        n_checksum = 12  # checksum bits
        n_addr = 4  # readback address bits
        n_word = n_lanes*n_div
        n_body = n_word*n_frame - (n_frame//2 + 1) - n_checksum

        # dac data words
        self.dacs = [Signal(n_bits) for i in range(n_channels)]
        # dac update enable
        self.enable = Signal(n_channels)
        # configuration word
        self.cfg = Signal(20)
        # readback data
        self.dat_r = Signal(n_frame//2*(1 << n_addr))
        # data load synchronization event
        self.stb = Signal()

        # # #

        # crc-12 telco
        self.submodules.crc = LiteEthMACCRCEngine(
            data_width=2*n_lanes, width=n_checksum, polynom=0x80f)

        addr = Signal(4)
        body_ = Cat(self.cfg, addr, self.enable, self.dacs)
        assert len(body_) == n_body
        body = Signal(n_body)
        self.comb += body.eq(body_)

        words_ = []
        j = 0
        for i in range(n_frame):  # iterate over words
            if i == 0:  # data and checksum
                k = n_word - n_checksum
            elif i == 1:  # marker
                words_.append(C(1))
                k = n_word - 1
            elif i < n_frame//2 + 2:  # marker
                words_.append(C(0))
                k = n_word - 1
            else:  # full word
                k = n_word
            # append corresponding frame body bits
            words_.append(body[j:j + k])
            j += k
        words_ = Cat(words_)
        assert len(words_) == n_frame*n_word - n_checksum
        words = Signal(len(words_))
        self.comb += words.eq(words_)

        clk = Signal(n_div, reset=0b1100011)
        clk_stb = Signal()
        i_frame = Signal(max=n_div*n_frame//2)  # DDR
        frame_stb = Signal()
        sr = [Signal(n_frame*n_div - n_checksum//n_lanes, reset_less=True)
                for i in range(n_lanes)]
        assert len(Cat(sr)) == len(words)
        # DDR bits for each register
        ddr_data = Cat([sri[-2] for sri in sr], [sri[-1] for sri in sr])
        self.comb += [
            # assert one cycle ahead
            clk_stb.eq(~clk[0] & clk[-1]),
            # double period because of DDR
            frame_stb.eq(i_frame == n_div*n_frame//2 - 1),

            # LiteETHMACCRCEngine takes data LSB first
            self.crc.data[::-1].eq(ddr_data),
            self.stb.eq(frame_stb & clk_stb),
        ]
        miso = Signal()
        miso_sr = Signal(n_frame, reset_less=True)
        self.sync.rio_phy += [
            # shift 7 bit clock pattern by two bits each DDR cycle
            clk.eq(Cat(clk[-2:], clk)),
            [sri[2:].eq(sri) for sri in sr],
            self.crc.last.eq(self.crc.next),
            If(clk[:2] == 0,  # TODO: tweak MISO sampling
                miso_sr.eq(Cat(miso, miso_sr)),
            ),
            If(~frame_stb,
                i_frame.eq(i_frame + 1),
            ),
            If(frame_stb & clk_stb,
                i_frame.eq(0),
                self.crc.last.eq(0),
                # transpose, load
                Cat(sr).eq(Cat(words[mm::n_lanes] for mm in range(n_lanes))),
                Array([self.dat_r[i*n_frame//2:(i + 1)*n_frame//2]
                    for i in range(1 << len(addr))])[addr].eq(miso_sr),
                addr.eq(addr + 1),
            ),
            If(i_frame == n_div*n_frame//2 - 2,
                # inject crc
                ddr_data.eq(self.crc.next),
            ),
        ]

        clk_ddr = Signal()
        miso0 = Signal()
        self.specials += [
            DDROutput(clk[-1], clk[-2], clk_ddr, ClockSignal("rio_phy")),
            DifferentialOutput(clk_ddr, pins.clk, pins_n.clk),
            DifferentialInput(pins.miso, pins_n.miso, miso0),
            MultiReg(miso0, miso, "rio_phy"),
        ]
        for sri, ddr, mp, mn in zip(
                sr, Signal(n_lanes), pins.mosi, pins_n.mosi):
            self.specials += [
                DDROutput(sri[-1], sri[-2], ddr, ClockSignal("rio_phy")),
                DifferentialOutput(ddr, mp, mn),
            ]