def __init__(self, cfg):
        self.pads = pads = _sdpads()
        self.sink = sink = stream.Endpoint([("data", 8)])
        self.source = source = stream.Endpoint([("data", 8), ("status", 3)])

        # # #

        cmdrfb_reset = Signal()

        self.submodules.cmdrfb = SDPHYRFB(pads.cmd.i, False)
        self.submodules.fifo = ClockDomainsRenamer({"write": "sd_fb", "read": "sd"})(
            stream.AsyncFIFO(self.cmdrfb.source.description, 4)
        )
        self.comb += self.cmdrfb.source.connect(self.fifo.sink)

        ctimeout = Signal(32)

        cread = Signal(10)
        ctoread = Signal(10)
        cnt = Signal(8)

        self.submodules.fsm = fsm = ClockDomainsRenamer("sd")(FSM(reset_state="IDLE"))

        fsm.act("IDLE",
            If(sink.valid,
                NextValue(ctimeout, 0),
                NextValue(cread, 0),
                NextValue(ctoread, sink.data),
                NextState("CMD_READSTART")
            ).Else(
                cmdrfb_reset.eq(1),
                self.fifo.source.ready.eq(1),
            )
        )
        self.specials += MultiReg(cmdrfb_reset, self.cmdrfb.reset, "sd_fb")

        fsm.act("CMD_READSTART",
            pads.cmd.oe.eq(0),
            pads.clk.eq(1),
            NextValue(ctimeout, ctimeout + 1),
            If(self.fifo.source.valid,
                NextState("CMD_READ")
            ).Elif(ctimeout > cfg.cmdtimeout,
                NextState("TIMEOUT")
            )
        )

        fsm.act("CMD_READ",
            pads.cmd.oe.eq(0),
            pads.clk.eq(1),
            source.valid.eq(self.fifo.source.valid),
            source.data.eq(self.fifo.source.data),
            source.status.eq(SDCARD_STREAM_STATUS_OK),
            source.last.eq(cread == ctoread),
            self.fifo.source.ready.eq(source.ready),
            If(source.valid & source.ready,
                NextValue(cread, cread + 1),
                If(cread == ctoread,
                    If(sink.last,
                        NextState("CMD_CLK8")
                    ).Else(
                        sink.ready.eq(1),
                        NextState("IDLE")
                    )
                )
            )
        )

        fsm.act("CMD_CLK8",
            If(cnt < 7,
                NextValue(cnt, cnt + 1),
                pads.clk.eq(1)
            ).Else(
                NextValue(cnt, 0),
                sink.ready.eq(1),
                NextState("IDLE")
            )
        )

        fsm.act("TIMEOUT",
            source.valid.eq(1),
            source.data.eq(0),
            source.status.eq(SDCARD_STREAM_STATUS_TIMEOUT),
            source.last.eq(1),
            If(source.valid & source.ready,
                sink.ready.eq(1),
                NextState("IDLE")
            )
        )
Exemple #2
0
    def __init__(self, hres=800, vres=600, with_csi_interpreter=True):
        self.enable    = Signal(reset=1)
        self.vtg_sink  = vtg_sink   = stream.Endpoint(video_timing_layout)
        self.uart_sink = uart_sink  = stream.Endpoint([("data", 8)])
        self.source    = source     = stream.Endpoint(video_data_layout)

        # # #

        csi_width = 8 if with_csi_interpreter else 0

        # Font Mem.
        # ---------
        os.system("wget https://github.com/enjoy-digital/litex/files/6076336/ter-u16b.txt") # FIXME: Store Font in LiteX?
        os.system("mv ter-u16b.txt ter-u16b.bdf")
        font        = import_bdf_font("ter-u16b.bdf")
        font_width  = 8
        font_heigth = 16
        font_mem    = Memory(width=8, depth=4096, init=font)
        font_rdport = font_mem.get_port(has_re=True)
        self.specials += font_mem, font_rdport

        # Terminal Mem.
        # -------------
        term_colums = 128 # 80 rounded to next power of two.
        term_lines  = math.floor(vres/font_heigth)
        term_depth  = term_colums * term_lines
        term_init   = [ord(c) for c in [" "]*term_colums*term_lines]
        term_mem    = Memory(width=font_width + csi_width, depth=term_depth, init=term_init)
        term_wrport = term_mem.get_port(write_capable=True)
        term_rdport = term_mem.get_port(has_re=True)
        self.specials += term_mem, term_wrport, term_rdport

        # UART Terminal Fill.
        # -------------------

        # Optional CSI Interpreter.
        if with_csi_interpreter:
            self.submodules.csi_interpreter = CSIInterpreter()
            self.comb += uart_sink.connect(self.csi_interpreter.sink)
            uart_sink = self.csi_interpreter.source
            self.comb += term_wrport.dat_w[font_width:].eq(self.csi_interpreter.color)

        self.submodules.uart_fifo = stream.SyncFIFO([("data", 8)], 8)
        self.comb += uart_sink.connect(self.uart_fifo.sink)
        uart_sink = self.uart_fifo.source

        # UART Reception and Terminal Fill.
        x_term = term_wrport.adr[:7]
        y_term = term_wrport.adr[7:]
        y_term_rollover = Signal()
        self.submodules.uart_fsm = uart_fsm = FSM(reset_state="RESET")
        uart_fsm.act("RESET",
            NextValue(x_term, 0),
            NextValue(y_term, 0),
            NextState("CLEAR-XY")
        )
        uart_fsm.act("CLEAR-XY",
            term_wrport.we.eq(1),
            term_wrport.dat_w[:font_width].eq(ord(" ")),
            NextValue(x_term, x_term + 1),
            If(x_term == (term_colums - 1),
                NextValue(x_term, 0),
                NextValue(y_term, y_term + 1),
                If(y_term == (term_lines - 1),
                    NextValue(y_term, 0),
                    NextState("IDLE")
                )
            )
        )
        uart_fsm.act("IDLE",
            If(uart_sink.valid,
                If(uart_sink.data == ord("\n"),
                    uart_sink.ready.eq(1), # Ack sink.
                    NextState("INCR-Y")
                ).Elif(uart_sink.data == ord("\r"),
                    uart_sink.ready.eq(1), # Ack sink.
                    NextState("RST-X")
                ).Else(
                    NextState("WRITE")
                )
            )
        )
        uart_fsm.act("WRITE",
            uart_sink.ready.eq(1),
            term_wrport.we.eq(1),
            term_wrport.dat_w[:font_width].eq(uart_sink.data),
            NextState("INCR-X")
        )
        uart_fsm.act("RST-X",
            NextValue(x_term, 0),
            NextState("CLEAR-X")
        )
        uart_fsm.act("INCR-X",
            NextValue(x_term, x_term + 1),
            NextState("IDLE"),
            If(x_term == (80 - 1),
                NextValue(x_term, 0),
                NextState("INCR-Y")
            )
        )
        uart_fsm.act("RST-Y",
            NextValue(y_term, 0),
            NextState("CLEAR-X")
        )
        uart_fsm.act("INCR-Y",
            NextValue(y_term, y_term + 1),
            NextState("CLEAR-X"),
            If(y_term == (term_lines - 1),
                NextValue(y_term_rollover, 1),
                NextState("RST-Y")
            )
        )
        uart_fsm.act("CLEAR-X",
            NextValue(x_term, x_term + 1),
            term_wrport.we.eq(1),
            term_wrport.dat_w[:font_width].eq(ord(" ")),
            If(x_term == (term_colums - 1),
                NextValue(x_term, 0),
                NextState("IDLE")
            )
        )

        # Video Generation.
        # -----------------
        ce = (vtg_sink.valid & vtg_sink.ready)

        # Timing delay line.
        latency     = 2
        timing_bufs = [stream.Buffer(video_timing_layout) for i in range(latency)]
        self.comb += vtg_sink.connect(timing_bufs[0].sink)
        for i in range(len(timing_bufs) - 1):
            self.comb += timing_bufs[i].source.connect(timing_bufs[i+1].sink)
        self.comb += timing_bufs[-1].source.connect(source, keep={"valid", "ready", "last", "de", "hsync", "vsync"})
        self.submodules += timing_bufs

        # Compute X/Y position.
        x = vtg_sink.hcount[int(math.log2(font_width)):]
        y = vtg_sink.vcount[int(math.log2(font_heigth)):]
        y_rollover = Signal(8)
        self.comb += [
            If(~y_term_rollover,
                y_rollover.eq(y)
            ).Else(
                # FIXME: Use Modulo.
                If((y + y_term + 1) >= term_lines,
                    y_rollover.eq(y + y_term + 1 - term_lines)
                ).Else(
                    y_rollover.eq(y + y_term + 1)
                ),
            )
        ]

        # Get character from Terminal Mem.
        term_dat_r = Signal(font_width)
        self.comb += term_rdport.re.eq(ce)
        self.comb += term_rdport.adr.eq(x + y_rollover*term_colums)
        self.comb += [
            term_dat_r.eq(term_rdport.dat_r[:font_width]),
            If((x >= 80) | (y >= term_lines),
                term_dat_r.eq(ord(" ")), # Out of range, generate space.
            )
        ]

        # Translate character to video data through Font Mem.
        self.comb += font_rdport.re.eq(ce)
        self.comb += font_rdport.adr.eq(term_dat_r*font_heigth + timing_bufs[0].source.vcount[:4])
        bit = Signal()
        cases = {}
        for i in range(font_width):
            cases[i] = [bit.eq(font_rdport.dat_r[font_width-1-i])]
        self.comb += Case(timing_bufs[1].source.hcount[:int(math.log2(font_width))], cases)
        # FIXME: Add Palette.
        self.comb += [
            If(bit,
                Case(term_rdport.dat_r[font_width:], {
                    0: [Cat(source.r, source.g, source.b).eq(0xffffff)],
                    1: [Cat(source.r, source.g, source.b).eq(0x34e289)],
                })
            ).Else(
                Cat(source.r, source.g, source.b).eq(0x000000),
            )
        ]
Exemple #3
0
    def __init__(self, sink_description, source_description, header):
        self.sink = sink = stream.Endpoint(sink_description)
        self.source = source = stream.Endpoint(source_description)
        self.header = Signal(header.length * 8)

        # # #

        dw = len(sink.data)

        header_reg = Signal(header.length * 8, reset_less=True)
        header_words = (header.length * 8) // dw

        shift = Signal()
        counter = Signal(max=max(header_words, 2))
        counter_reset = Signal()
        counter_ce = Signal()
        self.sync += \
            If(counter_reset,
                counter.eq(0)
            ).Elif(counter_ce,
                counter.eq(counter + 1)
            )

        if header_words == 1:
            self.sync += \
                If(shift,
                    header_reg.eq(sink.data)
                )
        else:
            self.sync += \
                If(shift,
                    header_reg.eq(Cat(header_reg[dw:], sink.data))
                )
        self.comb += self.header.eq(header_reg)

        fsm = FSM(reset_state="IDLE")
        self.submodules += fsm

        if header_words == 1:
            idle_next_state = "COPY"
        else:
            idle_next_state = "RECEIVE_HEADER"

        fsm.act("IDLE", sink.ready.eq(1), counter_reset.eq(1),
                If(sink.valid, shift.eq(1), NextState(idle_next_state)))
        if header_words != 1:
            fsm.act(
                "RECEIVE_HEADER", sink.ready.eq(1),
                If(sink.valid, counter_ce.eq(1), shift.eq(1),
                   If(counter == header_words - 2, NextState("COPY"))))
        no_payload = Signal()
        self.sync += \
            If(fsm.before_entering("COPY"),
                no_payload.eq(sink.last)
            )

        if hasattr(sink, "error"):
            self.comb += source.error.eq(sink.error)
        self.comb += [
            source.last.eq(sink.last | no_payload),
            source.data.eq(sink.data),
            header.decode(self.header, source)
        ]
        fsm.act(
            "COPY", sink.ready.eq(source.ready),
            source.valid.eq(sink.valid | no_payload),
            If(source.valid & source.ready & source.last, NextState("IDLE")))
Exemple #4
0
    def __init__(self, dram_port, mode="rgb", fifo_depth=512):
        try:
            dw = modes_dw[mode]
        except:
            raise ValueError("Unsupported {} video mode".format(mode))
        assert dram_port.dw >= dw
        assert dram_port.dw == 2**log2_int(dw, need_pow2=False)
        self.source = source = stream.Endpoint(video_out_layout(dw))

        self.underflow_enable = CSRStorage()
        self.underflow_update = CSR()
        self.underflow_counter = CSRStatus(32)

        # # #

        cd = dram_port.cd

        self.submodules.initiator = initiator = Initiator(cd)
        self.submodules.timing = timing = ClockDomainsRenamer(cd)(
            TimingGenerator())
        self.submodules.dma = dma = ClockDomainsRenamer(cd)(DMAReader(
            dram_port, fifo_depth))

        # ctrl path
        self.comb += [
            # dispatch initiator parameters to timing & dma
            timing.sink.valid.eq(initiator.source.valid),
            dma.sink.valid.eq(initiator.source.valid),
            initiator.source.ready.eq(timing.sink.ready),

            # combine timing and dma
            source.valid.eq(timing.source.valid
                            & (~timing.source.de | dma.source.valid)),
            # flush dma/timing when disabled
            If(~initiator.source.valid, timing.source.ready.eq(1),
               dma.source.ready.eq(1)).Elif(
                   source.valid & source.ready, timing.source.ready.eq(1),
                   dma.source.ready.eq(timing.source.de | (mode == "raw")))
        ]

        # data path
        self.comb += [
            # dispatch initiator parameters to timing & dma
            initiator.source.connect(
                timing.sink, keep=list_signals(frame_parameter_layout)),
            initiator.source.connect(dma.sink,
                                     keep=list_signals(frame_dma_layout)),

            # combine timing and dma
            source.de.eq(timing.source.de),
            source.hsync.eq(timing.source.hsync),
            source.vsync.eq(timing.source.vsync),
            source.data.eq(dma.source.data)
        ]

        # underflow detection
        underflow_enable = Signal()
        underflow_update = Signal()
        underflow_counter = Signal(32)
        self.specials += MultiReg(self.underflow_enable.storage,
                                  underflow_enable)
        underflow_update_synchronizer = PulseSynchronizer("sys", cd)
        self.submodules += underflow_update_synchronizer
        self.comb += [
            underflow_update_synchronizer.i.eq(self.underflow_update.re),
            underflow_update.eq(underflow_update_synchronizer.o)
        ]
        sync = getattr(self.sync, cd)
        sync += [
            If(underflow_enable,
               If(~source.valid,
                  underflow_counter.eq(underflow_counter + 1))).Else(
                      underflow_counter.eq(0)),
            If(underflow_update,
               self.underflow_counter.status.eq(underflow_counter))
        ]
Exemple #5
0
    def __init__(self,
                 flash,
                 clock_domain="sys",
                 endianness="big",
                 with_csr=True):
        self.source = source = stream.Endpoint(spi_core2phy_layout)
        self.sink = sink = stream.Endpoint(spi_phy2core_layout)
        self.bus = bus = wishbone.Interface()
        self.cs = cs = Signal()

        # Burst Control.
        burst_cs = Signal()
        burst_adr = Signal(len(bus.adr), reset_less=True)
        burst_timeout = WaitTimer(MMAP_DEFAULT_TIMEOUT)
        self.submodules += burst_timeout

        cmd_bits = 8
        data_bits = 32

        if flash.cmd_width == 1:
            self._default_dummy_bits = flash.dummy_bits if flash.fast_mode else 0
        elif flash.cmd_width == 4:
            self._default_dummy_bits = flash.dummy_bits * 3 if flash.fast_mode else 0
        else:
            raise NotImplementedError(
                f'Command width of {flash.cmd_width} bits is currently not supported!'
            )

        self._spi_dummy_bits = spi_dummy_bits = Signal(8)

        if with_csr:
            self.dummy_bits = dummy_bits = CSRStorage(
                8, reset=self._default_dummy_bits)
            if clock_domain != "sys":
                self.specials += MultiReg(dummy_bits.storage, spi_dummy_bits,
                                          clock_domain)
            else:
                self.comb += spi_dummy_bits.eq(dummy_bits.storage)
        else:
            self.comb += spi_dummy_bits.eq(self._default_dummy_bits)

        dummy = Signal(data_bits, reset=0xdead)

        # FSM.
        self.submodules.fsm = fsm = FSM(reset_state="IDLE")
        fsm.act(
            "IDLE",
            # Keep CS active after Burst for Timeout.
            burst_timeout.wait.eq(1),
            NextValue(burst_cs, burst_cs & ~burst_timeout.done),
            cs.eq(burst_cs),
            # On Bus Read access...
            If(
                bus.cyc & bus.stb & ~bus.we,
                # If CS is still active and Bus address matches previous Burst address:
                # Just continue the current Burst.
                If(burst_cs & (bus.adr == burst_adr),
                   NextState("BURST-REQ")
                   # Otherwise initialize a new Burst.
                   ).Else(cs.eq(0), NextState("BURST-CMD"))))

        fsm.act(
            "BURST-CMD",
            cs.eq(1),
            source.valid.eq(1),
            source.data.eq(flash.read_opcode.code),  # send command.
            source.len.eq(cmd_bits),
            source.width.eq(flash.cmd_width),
            source.mask.eq(cmd_oe_mask[flash.cmd_width]),
            NextValue(burst_adr, bus.adr),
            If(
                source.ready,
                NextState("CMD-RET"),
            ))

        fsm.act("CMD-RET", cs.eq(1), sink.ready.eq(1),
                If(
                    sink.valid,
                    NextState("BURST-ADDR"),
                ))

        fsm.act(
            "BURST-ADDR",
            cs.eq(1),
            source.valid.eq(1),
            source.width.eq(flash.addr_width),
            source.mask.eq(addr_oe_mask[flash.addr_width]),
            source.data.eq(Cat(Signal(2), bus.adr)),  # send address.
            source.len.eq(flash.addr_bits),
            NextValue(burst_cs, 1),
            NextValue(burst_adr, bus.adr),
            If(
                source.ready,
                NextState("ADDR-RET"),
            ))

        fsm.act(
            "ADDR-RET", cs.eq(1), sink.ready.eq(1),
            If(
                sink.valid,
                If(
                    spi_dummy_bits == 0,
                    NextState("BURST-REQ"),
                ).Else(NextState("DUMMY"), )))

        fsm.act("DUMMY", cs.eq(1), source.valid.eq(1),
                source.width.eq(flash.addr_width),
                source.mask.eq(addr_oe_mask[flash.addr_width]),
                source.data.eq(dummy), source.len.eq(spi_dummy_bits),
                If(
                    source.ready,
                    NextState("DUMMY-RET"),
                ))

        fsm.act("DUMMY-RET", cs.eq(1), sink.ready.eq(1),
                If(
                    sink.valid,
                    NextState("BURST-REQ"),
                ))

        fsm.act("BURST-REQ", cs.eq(1), source.valid.eq(1), source.last.eq(1),
                source.width.eq(flash.bus_width), source.len.eq(data_bits),
                source.mask.eq(0), If(
                    source.ready,
                    NextState("BURST-DAT"),
                ))

        fsm.act(
            "BURST-DAT", cs.eq(1), sink.ready.eq(1),
            bus.dat_r.eq({
                "big": sink.data,
                "little": reverse_bytes(sink.data)
            }[endianness]),
            If(
                sink.valid,
                bus.ack.eq(1),
                NextValue(burst_adr, burst_adr + 1),
                NextState("IDLE"),
            ))
Exemple #6
0
    def __init__(self):
        self.sink   = sink   = stream.Endpoint([("data", 8)])
        self.source = source = stream.Endpoint([("data", 8)])

        self.color = Record([("r", 8), ("g", 8), ("b", 8)])
        self.color.r.reset = 0xff
        self.color.g.reset = 0xff
        self.color.b.reset = 0xff

        # # #

        csi_count = Signal(3)
        csi_bytes = Array([Signal(8) for _ in range(8)])
        csi_final = Signal(8)

        self.submodules.fsm = fsm = FSM(reset_state="RECOPY")
        fsm.act("RECOPY",
            sink.connect(source),
            If(sink.valid & (sink.data == self.esc_start),
                source.valid.eq(0),
                sink.ready.eq(1),
                NextState("GET-CSI-START")
            )
        )
        fsm.act("GET-CSI-START",
            sink.ready.eq(1),
            If(sink.valid,
                If(sink.data == self.csi_start,
                    NextValue(csi_count, 0),
                    NextState("GET-CSI-PARAMETERS")
                ).Else(
                    NextState("RECOPY")
                )
            )
        )
        fsm.act("GET-CSI-PARAMETERS",
            If(sink.valid,
                If((sink.data >= self.csi_param_min) & (sink.data <= self.csi_param_max),
                    sink.ready.eq(1),
                    NextValue(csi_count, csi_count + 1),
                    NextValue(csi_bytes[csi_count], sink.data),
                ).Else(
                    NextState("GET-CSI-FINAL")
                )
            )
        )
        fsm.act("GET-CSI-FINAL",
            sink.ready.eq(1),
            NextValue(csi_final, sink.data),
            NextState("DECODE-CSI")
        )
        fsm.act("DECODE-CSI",
            If(csi_final == ord("m"),
                # FIXME: Write color in Terminal Mem.
                If((csi_bytes[0] == ord("9")) and (csi_bytes[1] == ord("2")),
                    NextValue(self.color.r, 0x89),
                    NextValue(self.color.g, 0xe2),
                    NextValue(self.color.b, 0x34),
                ).Else(
                    NextValue(self.color.r, self.color.r.reset),
                    NextValue(self.color.g, self.color.g.reset),
                    NextValue(self.color.b, self.color.b.reset),
                ),
            ),
            NextState("RECOPY")
        )
Exemple #7
0
    def __init__(self, data_width, depth):
        self.sink = sink = stream.Endpoint(core_layout(data_width))

        self.enable = CSRStorage()
        self.done = CSRStatus()

        self.length = CSRStorage(bits_for(depth))
        self.offset = CSRStorage(bits_for(depth))

        self.mem_valid = CSRStatus()
        self.mem_data = CSRStatus(data_width)

        # # #

        # Control re-synchronization
        enable = Signal()
        enable_d = Signal()
        self.specials += MultiReg(self.enable.storage, enable, "scope")
        self.sync.scope += enable_d.eq(enable)

        length = Signal().like(self.length.storage)
        offset = Signal().like(self.offset.storage)
        self.specials += MultiReg(self.length.storage, length, "scope")
        self.specials += MultiReg(self.offset.storage, offset, "scope")

        # Status re-synchronization
        done = Signal()
        self.specials += MultiReg(done, self.done.status)

        # Memory
        mem = stream.SyncFIFO([("data", data_width)], depth, buffered=True)
        mem = ClockDomainsRenamer("scope")(mem)
        cdc = stream.AsyncFIFO([("data", data_width)], 4)
        cdc = ClockDomainsRenamer({"write": "scope", "read": "sys"})(cdc)
        self.submodules += mem, cdc

        # Flush
        mem_flush = WaitTimer(depth)
        mem_flush = ClockDomainsRenamer("scope")(mem_flush)
        self.submodules += mem_flush

        # FSM
        fsm = FSM(reset_state="IDLE")
        fsm = ClockDomainsRenamer("scope")(fsm)
        self.submodules += fsm
        fsm.act("IDLE", done.eq(1), If(enable & ~enable_d, NextState("FLUSH")),
                sink.ready.eq(1), mem.source.connect(cdc.sink))
        fsm.act("FLUSH", sink.ready.eq(1), mem_flush.wait.eq(1),
                mem.source.ready.eq(1), If(mem_flush.done, NextState("WAIT")))
        fsm.act("WAIT", sink.connect(mem.sink, omit={"hit"}),
                If(sink.valid & sink.hit, NextState("RUN")),
                mem.source.ready.eq(mem.level >= offset))
        fsm.act("RUN", sink.connect(mem.sink, omit={"hit"}),
                If(
                    mem.level >= length,
                    NextState("IDLE"),
                ))

        # Memory read
        self.comb += [
            self.mem_valid.status.eq(cdc.source.valid),
            cdc.source.ready.eq(self.mem_data.we | ~self.enable.storage),
            self.mem_data.status.eq(cdc.source.data)
        ]
    def __init__(self, channel):
        self.decval = stream.Endpoint(terc4_layout)  # decoded values output
        self.data_in = Record(channel_layout)  # data input from chansync
        self.valid_in = Signal()  # valid input from chansync &|

        # decode the data path
        ### NOTE NOTE NOTE THIS IS UNTESTED
        for i, t in enumerate(terc4_tokens):
            self.sync.pix += If(self.data_in.raw == t, self.decval.d.eq(i))

        # decode the control signals
        if channel != 1:
            self.sync.pix += [
                If(
                    self.valid_in,
                    If(self.data_in.raw == control_tokens[0],
                       self.decval.c.eq(0), self.decval.de.eq(0),
                       self.decval.dgb.eq(0), self.decval.vgb.eq(0),
                       self.decval.c_valid.eq(1)).Elif(
                           self.data_in.raw == control_tokens[1],
                           self.decval.c.eq(1), self.decval.de.eq(0),
                           self.decval.dgb.eq(0), self.decval.vgb.eq(0),
                           self.decval.c_valid.eq(1)).Elif(
                               self.data_in.raw == control_tokens[2],
                               self.decval.c.eq(2), self.decval.de.eq(0),
                               self.decval.dgb.eq(0), self.decval.vgb.eq(0),
                               self.decval.c_valid.eq(1)).
                    Elif(self.data_in.raw == control_tokens[3],
                         self.decval.c.eq(3), self.decval.de.eq(0),
                         self.decval.dgb.eq(0), self.decval.vgb.eq(0),
                         self.decval.c_valid.eq(1)).Elif(
                             self.data_in.raw == data_gb_tokens[0],
                             self.decval.c.eq(0), self.decval.de.eq(0),
                             self.decval.dgb.eq(1), self.decval.vgb.eq(0),
                             self.decval.c_valid.eq(0)).Elif(
                                 self.data_in.raw == video_gb_tokens[channel],
                                 self.decval.c.eq(0), self.decval.de.eq(0),
                                 self.decval.dgb.eq(0), self.decval.vgb.eq(1),
                                 self.decval.c_valid.eq(0)).Else(
                                     self.decval.de.eq(1),
                                     self.decval.dgb.eq(0),
                                     self.decval.vgb.eq(0),
                                     self.decval.c_valid.eq(0))).Else(
                                         self.decval.c.eq(0),
                                         self.decval.de.eq(0),
                                         self.decval.dgb.eq(0),
                                         self.decval.vgb.eq(0),
                                         self.decval.c_valid.eq(0))
            ]
        else:  # green channel is special
            self.sync.pix += [
                If(
                    self.valid_in,
                    If(self.data_in.raw == control_tokens[0],
                       self.decval.c.eq(0), self.decval.de.eq(0),
                       self.decval.dgb.eq(0), self.decval.vgb.eq(0),
                       self.decval.c_valid.eq(1)).Elif(
                           self.data_in.raw == control_tokens[1],
                           self.decval.c.eq(1), self.decval.de.eq(0),
                           self.decval.dgb.eq(0), self.decval.vgb.eq(0),
                           self.decval.c_valid.eq(1)).Elif(
                               self.data_in.raw == control_tokens[2],
                               self.decval.c.eq(2), self.decval.de.eq(0),
                               self.decval.dgb.eq(0), self.decval.vgb.eq(0),
                               self.decval.c_valid.eq(1)).
                    Elif(
                        self.data_in.raw == control_tokens[3],
                        self.decval.c.eq(3), self.decval.de.eq(0),
                        self.decval.dgb.eq(0), self.decval.vgb.eq(0),
                        self.decval.c_valid.eq(1)).Elif(
                            self.data_in.raw == data_gb_tokens[0],
                            self.decval.c.eq(0),
                            self.decval.de.eq(0),
                            self.decval.dgb.eq(
                                1),  # green channel gb tokens are ambiguous
                            self.decval.vgb.eq(1),
                            self.decval.c_valid.eq(0)).Elif(
                                self.data_in.raw == video_gb_tokens[channel],
                                self.decval.c.eq(0),
                                self.decval.de.eq(0),
                                self.decval.dgb.eq(
                                    1),  #green channel gb tokens are ambiguous
                                self.decval.vgb.eq(1),
                                self.decval.c_valid.eq(0)).Else(
                                    self.decval.de.eq(1),
                                    self.decval.dgb.eq(0),
                                    self.decval.vgb.eq(0),
                                    self.decval.c_valid.eq(0))).Else(
                                        self.decval.c.eq(0),
                                        self.decval.de.eq(0),
                                        self.decval.dgb.eq(0),
                                        self.decval.vgb.eq(0),
                                        self.decval.c_valid.eq(0))
            ]
Exemple #9
0
    def __init__(self):
        self.enable   = Signal(reset=1)
        self.vtg_sink = vtg_sink   = stream.Endpoint(video_timing_layout)
        self.source   = source = stream.Endpoint(video_data_layout)

        # # #

        enable = Signal()
        self.specials += MultiReg(self.enable, enable)

        # Control Path.
        pix = Signal(hbits)
        bar = Signal(3)

        fsm = FSM(reset_state="IDLE")
        fsm = ResetInserter()(fsm)
        self.submodules.fsm = fsm
        self.comb += fsm.reset.eq(~self.enable)
        fsm.act("IDLE",
            NextValue(pix, 0),
            NextValue(bar, 0),
            vtg_sink.ready.eq(1),
            If(vtg_sink.valid & vtg_sink.first & (vtg_sink.hcount == 0) & (vtg_sink.vcount == 0),
                vtg_sink.ready.eq(0),
                NextState("RUN")
            )
        )
        fsm.act("RUN",
            vtg_sink.connect(source, keep={"valid", "ready", "last", "de", "hsync", "vsync"}),
            If(source.valid & source.ready & source.de,
                NextValue(pix, pix + 1),
                If(pix == (vtg_sink.hres[3:] -1), # 8 Color Bars.
                    NextValue(pix, 0),
                    NextValue(bar, bar + 1)
                )
            ).Else(
                NextValue(pix, 0),
                NextValue(bar, 0)
            )
        )

        # Data Path.
        color_bar = [
            # R     G     B
            [0xff, 0xff, 0xff], # White
            [0xff, 0xff, 0x00], # Yellow
            [0x00, 0xff, 0xff], # Cyan
            [0x00, 0xff, 0x00], # Green
            [0xff, 0x00, 0xff], # Purple
            [0xff, 0x00, 0x00], # Red
            [0x00, 0x00, 0xff], # Blue
            [0x00, 0x00, 0x00], # Black
        ]
        cases = {}
        for i in range(8):
            cases[i] = [
                source.r.eq(color_bar[i][0]),
                source.g.eq(color_bar[i][1]),
                source.b.eq(color_bar[i][2])
            ]
        self.comb += Case(bar, cases)
Exemple #10
0
    def __init__(self, ordered_set, n_ordered_sets=1):
        self.sink = stream.Endpoint([("data", 32), ("ctrl", 4)])
        self.detected = Signal()  # o
        self.error = Signal()  # o

        self.reset = Signal()  # o
        self.loopback = Signal()  # o
        self.scrambling = Signal(reset=1)  # o

        # # #

        self.comb += self.sink.ready.eq(1)

        # Memory -----------------------------------------------------------------------------------
        mem_depth = len(ordered_set.to_bytes()) // 4
        mem_init = [
            int.from_bytes(ordered_set.to_bytes()[4 * i:4 * (i + 1)], "little")
            for i in range(mem_depth)
        ]
        mem = Memory(32, mem_depth, mem_init)
        port = mem.get_port(async_read=True)
        self.specials += mem, port

        # Data check -------------------------------------------------------------------------------
        error = Signal()
        error_mask = Signal(32, reset=2**32 - 1)
        first_ctrl = 0b1111
        self.comb += If(port.adr == 1, error_mask.eq(0xffff00ff))
        self.comb += [
            If(
                self.sink.valid,
                # Check Comma
                If((port.adr == 0) & (self.sink.ctrl != first_ctrl),
                   error.eq(1)),
                If((port.adr != 0) & (self.sink.ctrl != 0), error.eq(1)),
                # Check Word
                If((self.sink.data & error_mask) != (port.dat_r & error_mask),
                   error.eq(1))),
            self.error.eq(error)
        ]

        # Link Config ------------------------------------------------------------------------------
        self.sync += [
            If(self.sink.valid & (port.adr == 1),
               self.reset.eq(self.sink.data[8]),
               self.loopback.eq(self.sink.data[10]),
               self.scrambling.eq(~self.sink.data[11]))
        ]

        # Memory address generation ----------------------------------------------------------------
        self.sync += [
            If(
                self.sink.valid,
                If(
                    ~error,
                    If(port.adr == (mem_depth - 1), port.adr.eq(0)).Else(
                        port.adr.eq(port.adr + 1))).Else(port.adr.eq(0)))
        ]

        # Count ------------------------------------------------------------------------------------
        count = Signal(max=mem_depth * n_ordered_sets)
        count_done = (count == (mem_depth * n_ordered_sets - 1))
        self.sync += [
            If(self.sink.valid,
               If(~error & ~count_done, count.eq(count + 1)).Else(count.eq(0)))
        ]

        # Result -----------------------------------------------------------------------------------
        self.comb += self.detected.eq(self.sink.valid & count_done)
Exemple #11
0
    def __init__(self, dram_port, nslots):
        bus_aw = dram_port.aw
        bus_dw = dram_port.dw
        alignment_bits = bits_for(bus_dw // 8) - 1

        fifo_word_width = bus_dw
        self.frame = stream.Endpoint([("sof", 1), ("pixels", fifo_word_width)])
        self._frame_size = CSRStorage(bus_aw + alignment_bits,
                                      alignment_bits=alignment_bits)
        self.submodules._slot_array = _SlotArray(nslots, bus_aw,
                                                 alignment_bits)
        self.ev = self._slot_array.ev

        # # #

        # address generator + maximum memory word count to prevent DMA buffer
        # overrun
        reset_words = Signal()
        count_word = Signal()
        last_word = Signal()
        self.current_address = current_address = Signal(bus_aw)
        mwords_remaining = Signal(bus_aw)
        self.comb += [
            self._slot_array.address_reached.eq(current_address),
            last_word.eq(mwords_remaining == 1)
        ]
        self.sync += [
            If(reset_words, current_address.eq(self._slot_array.address),
               mwords_remaining.eq(self._frame_size.storage)).Elif(
                   count_word, current_address.eq(current_address + 1),
                   mwords_remaining.eq(mwords_remaining - 1))
        ]

        memory_word = Signal(bus_dw)
        pixbits = []
        for i in range(bus_dw // 16):
            pixbits.append(self.frame.pixels)
        self.comb += memory_word.eq(Cat(*pixbits))

        # bus accessor
        self.submodules._bus_accessor = LiteDRAMDMAWriter(dram_port)
        self.comb += [
            self._bus_accessor.sink.address.eq(current_address),
            self._bus_accessor.sink.data.eq(memory_word)
        ]

        # control FSM
        fsm = FSM()
        self.submodules += fsm

        fsm.act(
            "WAIT_SOF", reset_words.eq(1),
            self.frame.ready.eq(~self._slot_array.address_valid
                                | ~self.frame.sof),
            If(
                self._slot_array.address_valid & self.frame.sof
                & self.frame.valid, NextState("TRANSFER_PIXELS")))
        fsm.act(
            "TRANSFER_PIXELS",
            self.frame.ready.eq(self._bus_accessor.sink.ready),
            If(
                self.frame.valid, self._bus_accessor.sink.valid.eq(1),
                If(self._bus_accessor.sink.ready, count_word.eq(1),
                   If(last_word, NextState("EOF")))))
        fsm.act(
            "EOF",
            If(~dram_port.wdata.valid, self._slot_array.address_done.eq(1),
               NextState("WAIT_SOF")))
Exemple #12
0
    def __init__(self, ordered_set, n_ordered_sets=1):
        self.start = Signal()  # i
        self.done = Signal()  # o
        self.source = stream.Endpoint([("data", 32), ("ctrl", 4)])

        if ordered_set.name in ["TS1", "TS2"]:
            self.reset = Signal()  # i
            self.loopback = Signal()  # i
            self.scrambling = Signal(reset=1)  # i

        # # #

        run = Signal()

        # Memory --------------------------------------------------------------------------------
        mem_depth = len(ordered_set.to_bytes()) // 4
        mem_init = [
            int.from_bytes(ordered_set.to_bytes()[4 * i:4 * (i + 1)], "little")
            for i in range(mem_depth)
        ]
        mem = Memory(32, mem_depth, mem_init)
        port = mem.get_port(async_read=True)
        self.specials += mem, port

        # Memory address generation ----------------------------------------------------------------
        self.sync += [
            If(
                self.source.valid,
                If(
                    self.source.ready,
                    If(port.adr == (mem_depth - 1), port.adr.eq(0)).Else(
                        port.adr.eq(port.adr + 1)))).Else(port.adr.eq(0))
        ]

        # Link Config ------------------------------------------------------------------------------
        link_config = Signal(8)
        if ordered_set.name in ["TS1", "TS2"]:
            self.comb += [
                link_config[0].eq(self.reset),
                link_config[2].eq(self.loopback),
                link_config[3].eq(~self.scrambling)
            ]

        # Data generation --------------------------------------------------------------------------
        if ordered_set.name in ["TS1", "TS2"]:
            first_ctrl = 0b1111
        else:
            first_ctrl = 0b0001
        self.comb += [
            self.source.valid.eq(self.start | run),
            If(
                port.adr == 0,
                self.source.ctrl.eq(first_ctrl),
            ).Else(self.source.ctrl.eq(0)),
            self.source.data.eq(port.dat_r)
        ]
        if ordered_set.name in ["TS1", "TS2"]:
            self.comb += If(port.adr == 1,
                            self.source.data[8:16].eq(link_config))

        # Count ------------------------------------------------------------------------------------
        count = Signal(max=mem_depth * n_ordered_sets)
        count_done = (count == (mem_depth * n_ordered_sets - 1))
        self.sync += [
            If(
                run,
                If(self.source.ready, count.eq(count + 1),
                   If(count_done, run.eq(0), count.eq(0)))).Elif(
                       self.start, If(self.source.ready, run.eq(1),
                                      count.eq(1)))
        ]
        # Delimiters -------------------------------------------------------------------------------
        self.comb += [
            self.source.first.eq(count == 0),
            self.source.last.eq(count_done),
        ]

        # Result -----------------------------------------------------------------------------------
        self.comb += self.done.eq(self.source.ready & run & count_done)
Exemple #13
0
    def __init__(self, sink_description, source_description, header):
        self.sink = sink = stream.Endpoint(sink_description)
        self.source = source = stream.Endpoint(source_description)
        self.header = Signal(header.length * 8)

        # # #

        # Parameters.
        data_width = len(sink.data)
        bytes_per_clk = data_width // 8
        header_words = (header.length * 8) // data_width
        header_leftover = header.length % bytes_per_clk
        aligned = header_leftover == 0

        # Signals.
        sr = Signal(header.length * 8, reset_less=True)
        sr_shift = Signal()
        sr_shift_leftover = Signal()
        count = Signal(max=max(header_words, 2))
        sink_d = stream.Endpoint(sink_description)

        # Header Shift/Decode.
        if (header_words) == 1 and (header_leftover == 0):
            self.sync += If(sr_shift, sr.eq(sink.data))
        else:
            self.sync += [
                If(sr_shift, sr.eq(Cat(sr[bytes_per_clk * 8:], sink.data))),
                If(sr_shift_leftover,
                   sr.eq(Cat(sr[header_leftover * 8:], sink.data)))
            ]
        self.comb += self.header.eq(sr)
        self.comb += header.decode(self.header, source)

        # FSM.
        self.submodules.fsm = fsm = FSM(reset_state="IDLE")
        fsm_from_idle = Signal()
        fsm.act(
            "IDLE", sink.ready.eq(1), NextValue(count, 1),
            If(
                sink.valid, sr_shift.eq(1), NextValue(fsm_from_idle, 1),
                If(
                    header_words == 1,
                    NextState("ALIGNED-DATA-COPY"
                              if aligned else "UNALIGNED-DATA-COPY"),
                ).Else(NextState("HEADER-RECEIVE"))))
        fsm.act(
            "HEADER-RECEIVE", sink.ready.eq(1),
            If(
                sink.valid, NextValue(count, count + 1), sr_shift.eq(1),
                If(
                    count == (header_words - 1),
                    NextState("ALIGNED-DATA-COPY"
                              if aligned else "UNALIGNED-DATA-COPY"),
                    NextValue(count, count + 1),
                )))
        fsm.act(
            "ALIGNED-DATA-COPY", source.valid.eq(sink.valid | sink_d.last),
            source.last.eq(sink.last | sink_d.last),
            sink.ready.eq(source.ready), source.data.eq(sink.data),
            If(source.valid & source.ready, If(source.last,
                                               NextState("IDLE"))))

        if not aligned:
            self.sync += If(sink.valid & sink.ready, sink_d.eq(sink))
            fsm.act(
                "UNALIGNED-DATA-COPY",
                source.valid.eq(sink.valid | sink_d.last),
                source.last.eq(sink.last | sink_d.last),
                sink.ready.eq(source.ready),
                source.data.eq(sink_d.data[header_leftover * 8:]),
                source.data[min((bytes_per_clk - header_leftover) *
                                8, data_width - 1):].eq(sink.data),
                If(
                    fsm_from_idle, source.valid.eq(sink_d.last),
                    sink.ready.eq(1),
                    If(
                        sink.valid,
                        NextValue(fsm_from_idle, 0),
                        sr_shift_leftover.eq(1),
                    )),
                If(source.valid & source.ready,
                   If(source.last, NextState("IDLE"))))

        # Error.
        if hasattr(sink, "error") and hasattr(source, "error"):
            self.comb += source.error.eq(sink.error)

        # Last BE.
        if hasattr(sink, "last_be") and hasattr(source, "last_be"):
            x = [
                sink.last_be[(i - (bytes_per_clk - header_leftover)) %
                             bytes_per_clk] for i in range(bytes_per_clk)
            ]
            self.comb += source.last_be.eq(Cat(*x))
Exemple #14
0
    def __init__(self, sink_description, source_description, header):
        self.sink = sink = stream.Endpoint(sink_description)
        self.source = source = stream.Endpoint(source_description)
        self.header = Signal(header.length * 8)

        # # #

        # Parameters.
        data_width = len(self.sink.data)
        bytes_per_clk = data_width // 8
        header_words = (header.length * 8) // data_width
        header_leftover = header.length % bytes_per_clk
        aligned = header_leftover == 0

        # Signals.
        sr = Signal(header.length * 8, reset_less=True)
        sr_load = Signal()
        sr_shift = Signal()
        count = Signal(max=max(header_words, 2))
        sink_d = stream.Endpoint(sink_description)

        # Header Encode/Load/Shift.
        self.comb += header.encode(sink, self.header)
        self.sync += If(sr_load, sr.eq(self.header))
        if header_words != 1:
            self.sync += If(sr_shift, sr.eq(sr[data_width:]))

        # Last BE.
        last_be = Signal(data_width // 8)
        last_be_d = Signal(data_width // 8)
        if hasattr(sink, "last_be") and hasattr(source, "last_be"):
            rotate_by = header.length % bytes_per_clk
            x = [
                sink.last_be[(i + rotate_by) % bytes_per_clk]
                for i in range(bytes_per_clk)
            ]
            self.comb += last_be.eq(Cat(*x))
            self.sync += last_be_d.eq(last_be)

        # FSM.
        self.submodules.fsm = fsm = FSM(reset_state="IDLE")
        fsm_from_idle = Signal()
        fsm.act(
            "IDLE", sink.ready.eq(1), NextValue(count, 1),
            If(
                sink.valid, sink.ready.eq(0), source.valid.eq(1),
                source.last.eq(0), source.data.eq(self.header[:data_width]),
                If(
                    source.valid & source.ready, sr_load.eq(1),
                    NextValue(fsm_from_idle, 1),
                    If(
                        header_words == 1,
                        NextState("ALIGNED-DATA-COPY"
                                  if aligned else "UNALIGNED-DATA-COPY")).Else(
                                      NextState("HEADER-SEND")))))
        fsm.act(
            "HEADER-SEND", source.valid.eq(1), source.last.eq(0),
            source.data.eq(sr[min(data_width,
                                  len(sr) - 1):]),
            If(
                source.valid & source.ready, sr_shift.eq(1),
                If(
                    count == (header_words - 1), sr_shift.eq(0),
                    NextState("ALIGNED-DATA-COPY"
                              if aligned else "UNALIGNED-DATA-COPY"),
                    NextValue(count,
                              count + 1)).Else(NextValue(count, count + 1), )))
        source_last_be = getattr(source, "last_be", Signal())
        fsm.act(
            "ALIGNED-DATA-COPY", source.valid.eq(sink.valid),
            source.last.eq(sink.last), source_last_be.eq(last_be),
            source.data.eq(sink.data),
            If(source.valid & source.ready, sink.ready.eq(1),
               If(source.last, NextState("IDLE"))))
        if not aligned:
            header_offset_multiplier = 1 if header_words == 1 else 2
            self.sync += If(source.ready, sink_d.eq(sink))
            fsm.act(
                "UNALIGNED-DATA-COPY",
                source.valid.eq(sink.valid | sink_d.last),
                source.last.eq(sink_d.last), source_last_be.eq(last_be_d),
                If(
                    fsm_from_idle,
                    source.data[:max(header_leftover * 8, 1)].eq(
                        sr[min(header_offset_multiplier * data_width,
                               len(sr) - 1):]
                    )).Else(source.data[:max(header_leftover * 8, 1)].eq(
                        sink_d.data[min((bytes_per_clk - header_leftover) *
                                        8, data_width - 1):])),
                source.data[header_leftover * 8:].eq(sink.data),
                If(source.valid & source.ready, sink.ready.eq(~source.last),
                   NextValue(fsm_from_idle, 0),
                   If(source.last, NextState("IDLE"))))

        # Error.
        if hasattr(sink, "error") and hasattr(source, "error"):
            self.comb += source.error.eq(sink.error)
Exemple #15
0
    def __init__(self, n, aw, address_align, settings):
        self.req = req = Record(cmd_layout(aw))
        self.refresh_req = Signal()
        self.refresh_gnt = Signal()
        a = settings.geom.addressbits
        ba = settings.geom.bankbits
        self.cmd = cmd = stream.Endpoint(cmd_request_rw_layout(a, ba))

        # # #

        # Command buffer
        cmd_buffer_layout = [("we", 1), ("adr", len(req.adr))]
        cmd_buffer = stream.SyncFIFO(cmd_buffer_layout, settings.cmd_buffer_depth)
        self.submodules += cmd_buffer
        self.comb += [
            req.connect(cmd_buffer.sink, omit=["wdata_valid", "wdata_ready",
                                               "rdata_valid", "rdata_ready",
                                               "lock"]),
            cmd_buffer.source.ready.eq(req.wdata_ready | req.rdata_valid),
            req.lock.eq(cmd_buffer.source.valid),
        ]

        slicer = _AddressSlicer(settings.geom.colbits, address_align)

        # Row tracking
        has_openrow = Signal()
        openrow = Signal(settings.geom.rowbits, reset_less=True)
        hit = Signal()
        self.comb += hit.eq(openrow == slicer.row(cmd_buffer.source.adr))
        track_open = Signal()
        track_close = Signal()
        self.sync += \
            If(track_close,
                has_openrow.eq(0)
            ).Elif(track_open,
                has_openrow.eq(1),
                openrow.eq(slicer.row(cmd_buffer.source.adr))
            )


        # Four Activate Window
        activate = Signal()
        activate_allowed = Signal(reset=1)
        tfaw = settings.timing.tFAW
        if tfaw is not None:
            activate_count = Signal(max=tfaw)
            activate_window = Signal(tfaw)
            self.sync += activate_window.eq(Cat(activate, activate_window))
            for i in range(tfaw):
                next_activate_count = Signal(max=tfaw)
                self.comb += next_activate_count.eq(activate_count + activate_window[i])
                activate_count = next_activate_count
            self.comb += If(activate_count >=4, activate_allowed.eq(0))

        # CAS to CAS
        cas = Signal()
        cas_allowed = Signal(reset=1)
        tccd =  settings.timing.tCCD
        if tccd is not None:
            cas_count = Signal(max=tccd+1)
            self.sync += \
                If(cas,
                    cas_count.eq(tccd-1)
                ).Elif(~cas_allowed,
                    cas_count.eq(cas_count-1)
                )
            self.comb += cas_allowed.eq(cas_count == 0)

        # Address generation
        sel_row_adr = Signal()
        self.comb += [
            cmd.ba.eq(n),
            If(sel_row_adr,
                cmd.a.eq(slicer.row(cmd_buffer.source.adr))
            ).Else(
                cmd.a.eq(slicer.col(cmd_buffer.source.adr))
            )
        ]

        # Respect write-to-precharge specification
        precharge_time = 2 + settings.timing.tWR - 1 + 1
        self.submodules.precharge_timer = WaitTimer(precharge_time)
        self.comb += self.precharge_timer.wait.eq(~(cmd.valid &
                                                    cmd.ready &
                                                    cmd.is_write))

        # Control and command generation FSM
        self.submodules.fsm = fsm = FSM()
        fsm.act("REGULAR",
            If(self.refresh_req,
                NextState("REFRESH")
            ).Elif(cmd_buffer.source.valid,
                If(has_openrow,
                    If(hit,
                        If(cas_allowed,
                            cas.eq(1),
                            # Note: write-to-read specification is enforced by
                            # multiplexer
                            cmd.valid.eq(1),
                            If(cmd_buffer.source.we,
                                req.wdata_ready.eq(cmd.ready),
                                cmd.is_write.eq(1),
                                cmd.we.eq(1),
                            ).Else(
                                req.rdata_valid.eq(cmd.ready),
                                cmd.is_read.eq(1)
                            ),
                            cmd.cas.eq(1)
                        )
                    ).Else(
                        NextState("PRECHARGE")
                    )
                ).Else(
                    If(activate_allowed,
                        NextState("ACTIVATE")
                    )
                )
            )
        )
        fsm.act("PRECHARGE",
            # Note: we are presenting the column address, A10 is always low
            If(self.precharge_timer.done,
                cmd.valid.eq(1),
                If(cmd.ready,
                    NextState("TRP")
                ),
                cmd.ras.eq(1),
                cmd.we.eq(1),
                cmd.is_cmd.eq(1)
            ),
            track_close.eq(1)
        )
        fsm.act("ACTIVATE",
            activate.eq(1),
            sel_row_adr.eq(1),
            track_open.eq(1),
            cmd.valid.eq(1),
            cmd.is_cmd.eq(1),
            If(cmd.ready,
                NextState("TRCD")
            ),
            cmd.ras.eq(1)
        )
        fsm.act("REFRESH",
            If(self.precharge_timer.done,
                self.refresh_gnt.eq(1),
            ),
            track_close.eq(1),
            cmd.is_cmd.eq(1),
            If(~self.refresh_req,
                NextState("REGULAR")
            )
        )
        fsm.delayed_enter("TRP", "ACTIVATE", settings.timing.tRP-1)
        fsm.delayed_enter("TRCD", "REGULAR", settings.timing.tRCD-1)
Exemple #16
0
    def __init__(self, enable=True):
        self.sink   = sink   = stream.Endpoint([("data", 8)])
        self.source = source = stream.Endpoint([("data", 8)])

        self.color    = Signal(4)
        self.clear_xy = Signal()

        # # #

        if not enable:
            self.comb += self.sink.connect(self.source)
            return

        csi_count = Signal(3)
        csi_bytes = Array([Signal(8) for _ in range(8)])
        csi_final = Signal(8)

        self.submodules.fsm = fsm = FSM(reset_state="RECOPY")
        fsm.act("RECOPY",
            sink.connect(source),
            If(sink.valid & (sink.data == self.esc_start),
                source.valid.eq(0),
                sink.ready.eq(1),
                NextState("GET-CSI-START")
            )
        )
        fsm.act("GET-CSI-START",
            sink.ready.eq(1),
            If(sink.valid,
                If(sink.data == self.csi_start,
                    NextValue(csi_count, 0),
                    NextState("GET-CSI-PARAMETERS")
                ).Else(
                    NextState("RECOPY")
                )
            )
        )
        fsm.act("GET-CSI-PARAMETERS",
            If(sink.valid,
                If((sink.data >= self.csi_param_min) & (sink.data <= self.csi_param_max),
                    sink.ready.eq(1),
                    NextValue(csi_count, csi_count + 1),
                    NextValue(csi_bytes[csi_count], sink.data),
                ).Else(
                    NextState("GET-CSI-FINAL")
                )
            )
        )
        fsm.act("GET-CSI-FINAL",
            sink.ready.eq(1),
            NextValue(csi_final, sink.data),
            NextState("DECODE-CSI")
        )
        fsm.act("DECODE-CSI",
            If(csi_final == ord("m"),
                If((csi_bytes[0] == ord("9")) and (csi_bytes[1] == ord("2")),
                    NextValue(self.color, 1), # FIXME: Add Palette.
                ).Else(
                    NextValue(self.color, 0), # FIXME: Add Palette.
                ),
            ),
            If(csi_final == ord("A"), # FIXME: Move Up.
                self.clear_xy.eq(1)
            ),
            NextState("RECOPY")
        )
Exemple #17
0
    def __init__(self, default_video_timings="800x600@60Hz"):
        vt = video_timings[default_video_timings]
        # MMAP Control/Status Registers.
        self._enable      = CSRStorage(reset=1)

        self._hres        = CSRStorage(hbits, vt["h_active"])
        self._hsync_start = CSRStorage(hbits, vt["h_active"] + vt["h_sync_offset"])
        self._hsync_end   = CSRStorage(hbits, vt["h_active"] + vt["h_sync_offset"] + vt["h_sync_width"])
        self._hscan       = CSRStorage(hbits, vt["h_active"] + vt["h_blanking"])

        self._vres        = CSRStorage(vbits, vt["v_active"])
        self._vsync_start = CSRStorage(vbits, vt["v_active"] + vt["v_sync_offset"])
        self._vsync_end   = CSRStorage(vbits, vt["v_active"] + vt["v_sync_offset"] + vt["v_sync_width"])
        self._vscan       = CSRStorage(vbits, vt["v_active"] + vt["v_blanking"])

        # Video Timing Source
        self.source = source = stream.Endpoint(video_timing_layout)

        # # #

        # Resynchronize Enable to Video clock domain.
        self.enable = enable = Signal()
        self.specials += MultiReg(self._enable.storage, enable)

        # Resynchronize Horizontal Timings to Video clock domain.
        self.hres        = hres        = Signal(hbits)
        self.hsync_start = hsync_start = Signal(hbits)
        self.hsync_end   = hsync_end   = Signal(hbits)
        self.hscan       = hscan       = Signal(hbits)
        self.specials += MultiReg(self._hres.storage,        hres)
        self.specials += MultiReg(self._hsync_start.storage, hsync_start)
        self.specials += MultiReg(self._hsync_end.storage,   hsync_end)
        self.specials += MultiReg(self._hscan.storage,       hscan)

        # Resynchronize Vertical Timings to Video clock domain.
        self.vres        = vres        = Signal(vbits)
        self.vsync_start = vsync_start = Signal(vbits)
        self.vsync_end   = vsync_end   = Signal(vbits)
        self.vscan       = vscan       = Signal(vbits)
        self.specials += MultiReg(self._vres.storage,        vres)
        self.specials += MultiReg(self._vsync_start.storage, vsync_start)
        self.specials += MultiReg(self._vsync_end.storage,   vsync_end)
        self.specials += MultiReg(self._vscan.storage,       vscan)

        # Generate timings.
        hactive = Signal()
        vactive = Signal()
        self.submodules.fsm = fsm = FSM(reset_state="IDLE")
        fsm.act("IDLE",
            NextValue(hactive, 0),
            NextValue(vactive, 0),
            NextValue(source.hres, hres),
            NextValue(source.vres, vres),
            NextValue(source.hcount,  0),
            NextValue(source.vcount,  0),
            If(enable,
                NextState("RUN")
            )
        )
        self.comb += source.de.eq(hactive & vactive) # DE when both HActive and VActive.
        self.sync += source.first.eq((source.hcount ==     0) & (source.vcount ==     0)),
        self.sync += source.last.eq( (source.hcount == hscan) & (source.vcount == vscan)),
        fsm.act("RUN",
            source.valid.eq(1),
            If(source.ready,
                # Increment HCount.
                NextValue(source.hcount, source.hcount + 1),
                # Generate HActive / HSync.
                If(source.hcount == 0,           NextValue(hactive,      1)), # Start of HActive.
                If(source.hcount == hres,        NextValue(hactive,      0)), # End of HActive.
                If(source.hcount == hsync_start, NextValue(source.hsync, 1)), # Start of HSync.
                If(source.hcount == hsync_end,   NextValue(source.hsync, 0)), # End of HSync.
                # End of HScan.
                If(source.hcount == hscan,
                    # Reset HCount.
                    NextValue(source.hcount, 0),
                    # Increment VCount.
                    NextValue(source.vcount, source.vcount + 1),
                    # Generate VActive / VSync.
                    If(source.vcount == 0,           NextValue(vactive,      1)), # Start of VActive.
                    If(source.vcount == vres,        NextValue(vactive,      0)), # End of HActive.
                    If(source.vcount == vsync_start, NextValue(source.vsync, 1)), # Start of VSync.
                    If(source.vcount == vsync_end,   NextValue(source.vsync, 0)), # End of VSync.
                    # End of VScan.
                    If(source.vcount == vscan,
                        # Reset VCount.
                        NextValue(source.vcount, 0),
                    )
                )
            )
        )
Exemple #18
0
    def __init__(self, dram_port, hres=800, vres=600, base=0x00000000, fifo_depth=65536, clock_domain="sys", clock_faster_than_sys=False, format="rgb888"):
        self.vtg_sink  = vtg_sink = stream.Endpoint(video_timing_layout)
        self.source    = source   = stream.Endpoint(video_data_layout)
        self.underflow = Signal()

        self.depth = depth = {
            "rgb888" : 32,
            "rgb565" : 16
        }[format]

        # # #

        # Video DMA.
        from litedram.frontend.dma import LiteDRAMDMAReader
        self.submodules.dma = LiteDRAMDMAReader(dram_port, fifo_depth=fifo_depth//(dram_port.data_width//8), fifo_buffered=True)
        self.dma.add_csr(
            default_base   = base,
            default_length = hres*vres*depth//8, # 32-bit RGB-888 or 16-bit RGB-565
            default_enable = 0,
            default_loop   = 1
        )

        # If DRAM Data Width > depth and Video clock is faster than sys_clk:
        if (dram_port.data_width > depth) and clock_faster_than_sys:
            # Do Clock Domain Crossing first...
            self.submodules.cdc = stream.ClockDomainCrossing([("data", dram_port.data_width)], cd_from="sys", cd_to=clock_domain)
            self.comb += self.dma.source.connect(self.cdc.sink)
            # ... and then Data-Width Conversion.
            self.submodules.conv = ClockDomainsRenamer(clock_domain)(stream.Converter(dram_port.data_width, depth))
            self.comb += self.cdc.source.connect(self.conv.sink)
            video_pipe_source = self.conv.source
        # Elsif DRAM Data Width <= depth or Video clock is slower than sys_clk:
        else:
            # Do Data-Width Conversion first...
            self.submodules.conv = stream.Converter(dram_port.data_width, depth)
            self.comb += self.dma.source.connect(self.conv.sink)
            # ... and then Clock Domain Crossing.
            self.submodules.cdc = stream.ClockDomainCrossing([("data", depth)], cd_from="sys", cd_to=clock_domain)
            self.comb += self.conv.source.connect(self.cdc.sink)
            if (dram_port.data_width < depth) and (depth == 32): # FIXME.
                self.comb += [
                    self.cdc.sink.data[ 0: 8].eq(self.conv.source.data[16:24]),
                    self.cdc.sink.data[16:24].eq(self.conv.source.data[ 0: 8]),
                ]
            video_pipe_source = self.cdc.source

        # Video Generation.
        self.comb += [
            vtg_sink.ready.eq(1),
            If(vtg_sink.valid & vtg_sink.de,
                video_pipe_source.connect(source, keep={"valid", "ready"}),
                vtg_sink.ready.eq(source.valid & source.ready),

            ),
            vtg_sink.connect(source, keep={"de", "hsync", "vsync"}),
        ]
        if (depth == 32):
            self.comb += [
               source.r.eq(video_pipe_source.data[16:24]),
               source.g.eq(video_pipe_source.data[ 8:16]),
               source.b.eq(video_pipe_source.data[ 0: 8]),
            ]
        else: # depth == 16
            self.comb += [
                source.r.eq(Cat(Signal(3, reset = 0), video_pipe_source.data[ 0: 5])),
                source.g.eq(Cat(Signal(2, reset = 0), video_pipe_source.data[ 5:11])),
                source.b.eq(Cat(Signal(3, reset = 0), video_pipe_source.data[11:16])),
            ]

        # Underflow.
        self.comb += self.underflow.eq(~source.valid)
Exemple #19
0
    def __init__(self, axi, axi_lite):
        assert axi.data_width == axi_lite.data_width
        assert axi.address_width == axi_lite.address_width

        ax_buffer = stream.Buffer(
            ax_description(axi.address_width, axi.id_width))
        ax_burst = stream.Endpoint(
            ax_description(axi.address_width, axi.id_width))
        ax_beat = stream.Endpoint(
            ax_description(axi.address_width, axi.id_width))
        self.comb += ax_burst.connect(ax_buffer.sink)
        ax_burst2beat = AXIBurst2Beat(ax_buffer.source, ax_beat)
        self.submodules += ax_buffer, ax_burst2beat

        _data = Signal(axi.data_width)
        _cmd_done = Signal()
        _last_ar_aw_n = Signal()

        self.submodules.fsm = fsm = FSM(reset_state="IDLE")
        fsm.act(
            "IDLE",
            NextValue(_cmd_done, 0),
            If(
                axi.ar.valid & axi.aw.valid,
                # If last access was a read, do a write
                If(_last_ar_aw_n, axi.aw.connect(ax_burst),
                   NextValue(_last_ar_aw_n, 0),
                   NextState("WRITE")
                   # If last access was a write, do a read
                   ).Else(
                       axi.ar.connect(ax_burst),
                       NextValue(_last_ar_aw_n, 1),
                       NextState("READ"),
                   )).Elif(
                       axi.ar.valid,
                       axi.ar.connect(ax_burst),
                       NextValue(_last_ar_aw_n, 1),
                       NextState("READ"),
                   ).Elif(axi.aw.valid, axi.aw.connect(ax_burst),
                          NextValue(_last_ar_aw_n, 0), NextState("WRITE")))
        fsm.act(
            "READ",
            # ar (read command)
            axi_lite.ar.valid.eq(ax_beat.valid & ~_cmd_done),
            axi_lite.ar.addr.eq(ax_beat.addr),
            ax_beat.ready.eq(axi_lite.ar.ready & ~_cmd_done),
            If(
                ax_beat.valid & ax_beat.last,
                If(axi_lite.ar.ready, ax_beat.ready.eq(0),
                   NextValue(_cmd_done, 1))),
            # r (read data & response)
            axi.r.valid.eq(axi_lite.r.valid),
            axi.r.last.eq(_cmd_done),
            axi.r.resp.eq(RESP_OKAY),
            axi.r.id.eq(ax_beat.id),
            axi.r.data.eq(axi_lite.r.data),
            axi_lite.r.ready.eq(axi.r.ready),
            # Exit
            If(axi.r.valid & axi.r.last & axi.r.ready, ax_beat.ready.eq(1),
               NextState("IDLE")))
        # Always accept write responses.
        self.comb += axi_lite.b.ready.eq(1)
        fsm.act(
            "WRITE",
            # aw (write command)
            axi_lite.aw.valid.eq(ax_beat.valid & ~_cmd_done),
            axi_lite.aw.addr.eq(ax_beat.addr),
            ax_beat.ready.eq(axi_lite.aw.ready & ~_cmd_done),
            If(
                ax_beat.valid & ax_beat.last,
                If(axi_lite.aw.ready, ax_beat.ready.eq(0),
                   NextValue(_cmd_done, 1))),
            # w (write data)
            axi_lite.w.valid.eq(axi.w.valid),
            axi_lite.w.data.eq(axi.w.data),
            axi_lite.w.strb.eq(axi.w.strb),
            axi.w.ready.eq(axi_lite.w.ready),
            # Exit
            If(axi.w.valid & axi.w.last & axi.w.ready,
               NextState("WRITE-RESP")))
        fsm.act("WRITE-RESP", axi.b.valid.eq(1), axi.b.resp.eq(RESP_OKAY),
                axi.b.id.eq(ax_beat.id),
                If(axi.b.ready, ax_beat.ready.eq(1), NextState("IDLE")))
    def __init__(self):
        self.pads = pads = _sdpads()
        self.sink = sink = stream.Endpoint([("data", 8)])

        # # #

        isinit = Signal()
        cntinit = Signal(8)
        cnt = Signal(8)
        wrsel = Signal(3)
        wrtmpdata = Signal(8)

        wrcases = {} # For command write
        for i in range(8):
            wrcases[i] =  pads.cmd.o.eq(wrtmpdata[7-i])

        self.submodules.fsm = fsm = ClockDomainsRenamer("sd")(FSM(reset_state="IDLE"))

        fsm.act("IDLE",
            If(sink.valid,
                If(~isinit,
                    NextState("INIT")
                ).Else(
                    pads.clk.eq(1),
                    pads.cmd.o.eq(sink.data[7]),
                    NextValue(wrtmpdata, sink.data),
                    NextValue(wrsel, 1),
                    NextState("CMD_WRITE")
                )
            )
        )

        fsm.act("INIT",
            # Initialize sdcard with 80 clock cycles
            pads.clk.eq(1),
            If(cntinit < 80,
                NextValue(cntinit, cntinit + 1),
                NextValue(pads.data.oe, 1),
                NextValue(pads.data.o, 0xf)
            ).Else(
                NextValue(cntinit, 0),
                NextValue(isinit, 1),
                NextValue(pads.data.oe, 0),
                NextState("IDLE")
            )
        )

        fsm.act("CMD_WRITE",
            Case(wrsel, wrcases),
            NextValue(wrsel, wrsel + 1),
            If(wrsel == 0,
                If(sink.last,
                    pads.clk.eq(1),
                    NextState("CMD_CLK8")
                ).Else(
                    sink.ready.eq(1),
                    NextState("IDLE")
                )
            ).Else(
                pads.clk.eq(1)
            )
        )

        fsm.act("CMD_CLK8",
            If(cnt < 7,
                NextValue(cnt, cnt + 1),
                pads.clk.eq(1)
            ).Else(
                NextValue(cnt, 0),
                sink.ready.eq(1),
                NextState("IDLE")
            )
        )
Exemple #21
0
 def __init__(self):
     self.sink = stream.Endpoint([("data", 8)])
     self.source = stream.Endpoint([("data", 8)])
    def __init__(self, cfg):
        self.pads = pads = _sdpads()
        self.sink = sink = stream.Endpoint([("data", 8)])
        self.source = source = stream.Endpoint([("data", 8), ("status", 3)])

        # # #

        datarfb_reset = Signal()

        self.submodules.datarfb = SDPHYRFB(pads.data.i, True)
        self.submodules.cdc = ClockDomainsRenamer({"write": "sd_fb", "read": "sd"})(
            stream.AsyncFIFO(self.datarfb.source.description, 4)
        )
        self.submodules.buffer = ClockDomainsRenamer("sd")(stream.Buffer(self.datarfb.source.description))
        self.comb += self.datarfb.source.connect(self.buffer.sink)

        dtimeout = Signal(32)

        read = Signal(10)
        toread = Signal(10)
        cnt = Signal(8)

        self.submodules.fsm = fsm = ClockDomainsRenamer("sd")(FSM(reset_state="IDLE"))

        fsm.act("IDLE",
            pads.data.oe.eq(0),
            pads.clk.eq(1),
            datarfb_reset.eq(1),
            self.buffer.source.ready.eq(1),
            If(sink.valid,
                NextValue(dtimeout, 0),
                NextValue(read, 0),
                # Read 1 block + 8*8 == 64 bits CRC
                NextValue(toread, cfg.blocksize + 8),
                NextState("DATA_READSTART")
            )
        )

        self.specials += MultiReg(datarfb_reset, self.datarfb.reset, "sd_fb")

        fsm.act("DATA_READSTART",
            pads.data.oe.eq(0),
            pads.clk.eq(1),
            NextValue(dtimeout, dtimeout + 1),
            If(self.buffer.source.valid,
                NextState("DATA_READ")
            ).Elif(dtimeout > cfg.datatimeout,
                NextState("TIMEOUT")
            )
        )

        fsm.act("DATA_READ",
            pads.data.oe.eq(0),
            pads.clk.eq(1),
            source.valid.eq(self.buffer.source.valid),
            source.data.eq(self.buffer.source.data),
            source.status.eq(SDCARD_STREAM_STATUS_OK),
            source.last.eq(read == (toread - 1)),
            self.buffer.source.ready.eq(source.ready),
            If(source.valid & source.ready,
                NextValue(read, read + 1),
                If(read == (toread - 1),
                    If(sink.last,
                        NextState("DATA_CLK40")
                    ).Else(
                        sink.ready.eq(1),
                        NextState("DATA_FLUSH")
                    )
                )
            )
        )

        fsm.act("DATA_FLUSH",
            pads.data.oe.eq(0),
            datarfb_reset.eq(1),
            self.buffer.source.ready.eq(1),
            If(cnt < 5,
                NextValue(cnt, cnt + 1),
            ).Else(
                NextValue(cnt, 0),
                NextState("IDLE")
            )
        )

        fsm.act("DATA_CLK40",
            pads.data.oe.eq(1),
            pads.data.o.eq(0xf),
            If(cnt < 40,
                NextValue(cnt, cnt + 1),
                pads.clk.eq(1)
            ).Else(
                NextValue(cnt, 0),
                sink.ready.eq(1),
                NextState("IDLE")
            )
        )

        fsm.act("TIMEOUT",
            source.valid.eq(1),
            source.data.eq(0),
            source.status.eq(SDCARD_STREAM_STATUS_TIMEOUT),
            source.last.eq(1),
            If(source.valid & source.ready,
                sink.ready.eq(1),
                NextState("IDLE")
            )
        )
Exemple #23
0
    def __init__(self, axi, port, buffer_depth):
        self.cmd_request = Signal()
        self.cmd_grant = Signal()

        # # #

        can_read = Signal()

        ashift = log2_int(port.data_width // 8)

        # Burst to Beat
        ar_buffer = stream.Buffer(
            ax_description(axi.address_width, axi.id_width))
        self.submodules += ar_buffer
        self.comb += axi.ar.connect(ar_buffer.sink)
        ar = stream.Endpoint(ax_description(axi.address_width, axi.id_width))
        ar_burst2beat = AXIBurst2Beat(ar_buffer.source, ar)
        self.submodules.ar_burst2beat = ar_burst2beat

        # Read buffer
        r_buffer = stream.SyncFIFO(r_description(axi.data_width, axi.id_width),
                                   buffer_depth,
                                   buffered=True)
        self.submodules.r_buffer = r_buffer

        # Read Buffer reservation
        # - Incremented when data is planned to be queued
        # - Decremented when data is dequeued
        r_buffer_queue = Signal()
        r_buffer_dequeue = Signal()
        r_buffer_level = Signal(max=buffer_depth + 1)
        self.comb += [
            r_buffer_queue.eq(port.cmd.valid & port.cmd.ready & ~port.cmd.we),
            r_buffer_dequeue.eq(r_buffer.source.valid & r_buffer.source.ready)
        ]
        self.sync += [
            If(r_buffer_queue,
               If(~r_buffer_dequeue,
                  r_buffer_level.eq(r_buffer_level + 1))).Elif(
                      r_buffer_dequeue, r_buffer_level.eq(r_buffer_level - 1))
        ]
        self.comb += can_read.eq(r_buffer_level != buffer_depth)

        # Read ID Buffer
        id_buffer = stream.SyncFIFO([("id", axi.id_width)], buffer_depth)
        self.submodules += id_buffer
        self.comb += [
            id_buffer.sink.valid.eq(ar.valid & ar.ready),
            id_buffer.sink.last.eq(ar.last),
            id_buffer.sink.id.eq(ar.id),
            axi.r.last.eq(id_buffer.source.last),
            axi.r.id.eq(id_buffer.source.id),
            id_buffer.source.ready.eq(axi.r.valid & axi.r.ready)
        ]

        # Command
        self.comb += [
            self.cmd_request.eq(ar.valid & can_read),
            If(self.cmd_grant, port.cmd.valid.eq(ar.valid & can_read),
               ar.ready.eq(port.cmd.ready & can_read), port.cmd.we.eq(0),
               port.cmd.addr.eq(ar.addr >> ashift))
        ]

        # Read data
        self.comb += [
            port.rdata.connect(r_buffer.sink, omit={"bank"}),
            r_buffer.source.connect(axi.r, omit={"id", "last"}),
            axi.r.resp.eq(RESP_OKAY)
        ]
    def __init__(self):
        self.pads = pads = _sdpads()
        self.sink = sink = stream.Endpoint([("data", 8)])

        self.crc_clear = Signal()
        self.crc_valids = Signal(32)
        self.crc_errors = Signal(32)

        # # #


        wrstarted = Signal()
        cnt = Signal(8)

        self.submodules.crcfb = SDPHYCRCRFB(pads.data.i[0])
        self.sync.sd += [
            If(self.crc_clear,
                self.crc_valids.eq(0),
                self.crc_errors.eq(0)
            ),
            If(self.crcfb.valid,
                self.crc_valids.eq(self.crc_valids + 1)
            ),
            If(self.crcfb.error,
                self.crc_errors.eq(self.crc_errors + 1)
            )
        ]

        self.submodules.fsm = fsm = ClockDomainsRenamer("sd")(FSM(reset_state="IDLE"))

        fsm.act("IDLE",
            If(sink.valid,
                pads.clk.eq(1),
                pads.data.oe.eq(1),
                If(wrstarted,
                    pads.data.o.eq(sink.data[4:8]),
                    NextState("DATA_WRITE")
                ).Else(
                    pads.data.o.eq(0),
                    NextState("DATA_WRITESTART")
                )
            )
        )

        fsm.act("DATA_WRITESTART",
            pads.clk.eq(1),
            pads.data.oe.eq(1),
            pads.data.o.eq(sink.data[4:8]),
            NextValue(wrstarted, 1),
            NextState("DATA_WRITE")
        )

        fsm.act("DATA_WRITE",
            pads.clk.eq(1),
            pads.data.oe.eq(1),
            pads.data.o.eq(sink.data[0:4]),
            If(sink.last,
                NextState("DATA_WRITESTOP")
            ).Else(
                sink.ready.eq(1),
                NextState("IDLE")
            )
        )

        fsm.act("DATA_WRITESTOP",
            pads.clk.eq(1),
            pads.data.oe.eq(1),
            pads.data.o.eq(0xf),
            NextValue(wrstarted, 0),
            self.crcfb.start.eq(1),
            NextState("DATA_RESPONSE")
        )

        fsm.act("DATA_RESPONSE",
            pads.clk.eq(1),
            pads.data.oe.eq(0),
            If(cnt < 16,
                NextValue(cnt, cnt + 1),
            ).Else(
                # wait while busy
                If(pads.data.i[0],
                    NextValue(cnt, 0),
                    sink.ready.eq(1),
                    NextState("IDLE")
                )
            )
        )
Exemple #25
0
    def __init__(self, default_video_timings="800x600@60Hz"):
        # Check / Get Video Timings (can be str or dict)
        if isinstance(default_video_timings, str):
            try:
                self.video_timings = vt = video_timings[default_video_timings]
            except KeyError:
                msg = [f"Video Timings {default_video_timings} not supported, availables:"]
                for video_timing in video_timings.keys():
                    msg.append(f" - {video_timing} / {video_timings[video_timing]['pix_clk']/1e6:3.2f}MHz.")
                raise ValueError("\n".join(msg))
        else:
            self.video_timings = vt = default_video_timings

        # MMAP Control/Status Registers.
        self._enable      = CSRStorage(reset=1)

        self._hres        = CSRStorage(hbits, vt["h_active"])
        self._hsync_start = CSRStorage(hbits, vt["h_active"] + vt["h_sync_offset"])
        self._hsync_end   = CSRStorage(hbits, vt["h_active"] + vt["h_sync_offset"] + vt["h_sync_width"])
        self._hscan       = CSRStorage(hbits, vt["h_active"] + vt["h_blanking"])

        self._vres        = CSRStorage(vbits, vt["v_active"])
        self._vsync_start = CSRStorage(vbits, vt["v_active"] + vt["v_sync_offset"])
        self._vsync_end   = CSRStorage(vbits, vt["v_active"] + vt["v_sync_offset"] + vt["v_sync_width"])
        self._vscan       = CSRStorage(vbits, vt["v_active"] + vt["v_blanking"])

        # Video Timing Source
        self.source = source = stream.Endpoint(video_timing_layout)

        # # #

        # Resynchronize Enable to Video clock domain.
        self.enable = enable = Signal()
        self.specials += MultiReg(self._enable.storage, enable)

        # Resynchronize Horizontal Timings to Video clock domain.
        self.hres        = hres        = Signal(hbits)
        self.hsync_start = hsync_start = Signal(hbits)
        self.hsync_end   = hsync_end   = Signal(hbits)
        self.hscan       = hscan       = Signal(hbits)
        self.specials += MultiReg(self._hres.storage,        hres)
        self.specials += MultiReg(self._hsync_start.storage, hsync_start)
        self.specials += MultiReg(self._hsync_end.storage,   hsync_end)
        self.specials += MultiReg(self._hscan.storage,       hscan)

        # Resynchronize Vertical Timings to Video clock domain.
        self.vres        = vres        = Signal(vbits)
        self.vsync_start = vsync_start = Signal(vbits)
        self.vsync_end   = vsync_end   = Signal(vbits)
        self.vscan       = vscan       = Signal(vbits)
        self.specials += MultiReg(self._vres.storage,        vres)
        self.specials += MultiReg(self._vsync_start.storage, vsync_start)
        self.specials += MultiReg(self._vsync_end.storage,   vsync_end)
        self.specials += MultiReg(self._vscan.storage,       vscan)

        # Generate timings.
        hactive = Signal()
        vactive = Signal()
        fsm = FSM(reset_state="IDLE")
        fsm = ResetInserter()(fsm)
        self.submodules.fsm = fsm
        self.comb += fsm.reset.eq(~enable)
        fsm.act("IDLE",
            NextValue(hactive, 0),
            NextValue(vactive, 0),
            NextValue(source.hres, hres),
            NextValue(source.vres, vres),
            NextValue(source.hcount,  0),
            NextValue(source.vcount,  0),
            NextState("RUN")
        )
        self.comb += source.de.eq(hactive & vactive) # DE when both HActive and VActive.
        self.sync += source.first.eq((source.hcount ==     0) & (source.vcount ==     0)),
        self.sync += source.last.eq( (source.hcount == hscan) & (source.vcount == vscan)),
        fsm.act("RUN",
            source.valid.eq(1),
            If(source.ready,
                # Increment HCount.
                NextValue(source.hcount, source.hcount + 1),
                # Generate HActive / HSync.
                If(source.hcount == 0,           NextValue(hactive,      1)), # Start of HActive.
                If(source.hcount == hres,        NextValue(hactive,      0)), # End of HActive.
                If(source.hcount == hsync_start, NextValue(source.hsync, 1)), # Start of HSync.
                If(source.hcount == hsync_end,   NextValue(source.hsync, 0)), # End of HSync.
                # End of HScan.
                If(source.hcount == hscan,
                    # Reset HCount.
                    NextValue(source.hcount, 0),
                    # Increment VCount.
                    NextValue(source.vcount, source.vcount + 1),
                    # Generate VActive / VSync.
                    If(source.vcount == 0,           NextValue(vactive,      1)), # Start of VActive.
                    If(source.vcount == vres,        NextValue(vactive,      0)), # End of HActive.
                    If(source.vcount == vsync_start, NextValue(source.vsync, 1)), # Start of VSync.
                    If(source.vcount == vsync_end,   NextValue(source.vsync, 0)), # End of VSync.
                    # End of VScan.
                    If(source.vcount == vscan,
                        # Reset VCount.
                        NextValue(source.vcount, 0),
                    )
                )
            )
        )
    def __init__(self, pads, device, **kwargs):
        self.sink = sink = stream.Endpoint([("data", 8), ("cmd_data_n", 1), ("rd_wr_n", 1)])
        self.source = source = stream.Endpoint([("data", 8), ("status", 3)])
        if hasattr(pads, "sel"):
            self.voltage_sel = CSRStorage()
            self.comb += pads.sel.eq(self.voltage_sel.storage)

        # # #

        self.sdpads = sdpads = _sdpads()

        # IOs (device specific)
        if not hasattr(pads, "clkfb"):
            self.comb += [
                ClockSignal("sd_fb").eq(ClockSignal("sd")),
                ResetSignal("sd_fb").eq(ResetSignal("sd"))
            ]
        if hasattr(pads, "cmd_t") and hasattr(pads, "dat_t"):
            # emulator phy
            self.comb += [
                If(sdpads.clk, pads.clk.eq(~ClockSignal("sd"))),

                pads.cmd_i.eq(1),
                If(sdpads.cmd.oe, pads.cmd_i.eq(sdpads.cmd.o)),
                sdpads.cmd.i.eq(1),
                If(~pads.cmd_t, sdpads.cmd.i.eq(pads.cmd_o)),

                pads.dat_i.eq(0b1111),
                If(sdpads.data.oe, pads.dat_i.eq(sdpads.data.o)),
                sdpads.data.i.eq(0b1111),
                If(~pads.dat_t[0], sdpads.data.i[0].eq(pads.dat_o[0])),
                If(~pads.dat_t[1], sdpads.data.i[1].eq(pads.dat_o[1])),
                If(~pads.dat_t[2], sdpads.data.i[2].eq(pads.dat_o[2])),
                If(~pads.dat_t[3], sdpads.data.i[3].eq(pads.dat_o[3]))
            ]
        else:
            # real phy
            if device[:3] == "xc6":
                self.submodules.io = io = SDPHYIOS6(sdpads, pads, **kwargs)
            elif device[:3] == "xc7":
                self.submodules.io = io = SDPHYIOS7(sdpads, pads, **kwargs)
            else:
                raise NotImplementedError
            self.sync.sd += [
                io.cmd_t.oe.eq(sdpads.cmd.oe),
                io.cmd_t.o.eq(sdpads.cmd.o),

                io.data_t.oe.eq(sdpads.data.oe),
                io.data_t.o.eq(sdpads.data.o)
            ]

        # PHY submodules
        self.submodules.cfg = cfg = SDPHYCFG()
        self.submodules.cmdw = cmdw = SDPHYCMDW()
        self.submodules.cmdr = cmdr = SDPHYCMDR(cfg)
        self.submodules.dataw = dataw = SDPHYDATAW()
        self.submodules.datar = datar = SDPHYDATAR(cfg)

        self.comb += \
            If(sink.valid,
                # Command mode
                If(sink.cmd_data_n,
                    # Write command
                    If(~sink.rd_wr_n,
                        sink.connect(cmdw.sink, omit=set(["cmd_data_n", "rd_wr_n"])),
                        cmdw.pads.connect(sdpads)
                    # Read command
                    ).Else(
                        sink.connect(cmdr.sink, omit=set(["cmd_data_n", "rd_wr_n"])),
                        cmdr.pads.connect(sdpads),
                        cmdr.source.connect(source)
                    )
                # Data mode
                ).Else(
                    # Write data
                    If(~sink.rd_wr_n,
                        sink.connect(dataw.sink, omit=set(["cmd_data_n", "rd_wr_n"])),
                        dataw.pads.connect(sdpads)
                    # Read data
                    ).Else(
                        sink.connect(datar.sink, omit=set(["cmd_data_n", "rd_wr_n"])),
                        datar.pads.connect(sdpads),
                        datar.source.connect(source)
                    )
                )
            )
Exemple #27
0
    def __init__(self, pads, sys_clk_freq, clock_domain="sys", clk_freq=148.5e6, refclk=None):
        assert sys_clk_freq >= clk_freq
        self.sink = sink = stream.Endpoint(video_data_layout)

        # # #

        from liteiclink.serdes.gtp_7series import GTPQuadPLL, GTP

        # Always ack Sink, no backpressure.
        self.comb += sink.ready.eq(1)

        # Clocking + Differential Signaling.
        pads_clk = Signal()
        self.specials += DDROutput(i1=1, i2=0, o=pads_clk, clk=ClockSignal(clock_domain))
        self.specials += Instance("OBUFDS", i_I=pads_clk, o_O=pads.clk_p, o_OB=pads.clk_n)

        # GTP Quad PLL.
        if refclk is None:
            # No RefClk provided, use the Video Clk as GTP RefClk.
            refclk = ClockSignal(clock_domain)
        elif isinstance(refclk, Record):
            # Differential RefCLk provided, add an IBUFDS_GTE2.
            refclk_se = Signal()
            self.specials += Instance("IBUFDS_GTE2",
                i_CEB = 0,
                i_I   = refclk.p,
                i_IB  = refclk.n,
                o_O   = refclk_se
            )
            refclk = refclk_se
        self.submodules.pll = pll = GTPQuadPLL(refclk, clk_freq, 1.485e9)

        # Encode/Serialize Datas.
        for color in ["r", "g", "b"]:
            # TMDS Encoding.
            encoder = ClockDomainsRenamer(clock_domain)(TMDSEncoder())
            self.submodules += encoder
            self.comb += encoder.d.eq(getattr(sink, color))
            self.comb += encoder.c.eq(Cat(sink.hsync, sink.vsync) if color == "r" else 0)
            self.comb += encoder.de.eq(sink.de)

            # 10:20 (SerDes has a minimal 20:1 Serialization ratio).
            converter = ClockDomainsRenamer(clock_domain)(stream.Converter(10, 20))
            self.submodules += converter
            self.comb += converter.sink.valid.eq(1)
            self.comb += converter.sink.data.eq(encoder.out)

            # Clock Domain Crossing (video_clk --> gtp_tx)
            cdc = stream.ClockDomainCrossing([("data", 20)], cd_from=clock_domain, cd_to=f"gtp{color}_tx")
            self.submodules += cdc
            self.comb += converter.source.connect(cdc.sink)
            self.comb += cdc.source.ready.eq(1) # No backpressure.

            # 20:1 Serialization + Differential Signaling.
            c2d  = {"r": 2, "g": 1, "b": 0}
            class GTPPads:
                def __init__(self, p, n):
                    self.p = p
                    self.n = n
            tx_pads = GTPPads(p=getattr(pads, f"data{c2d[color]}_p"), n=getattr(pads, f"data{c2d[color]}_n"))
            # FIXME: Find a way to avoid RX pads.
            rx_pads = GTPPads(p=getattr(pads, f"rx{c2d[color]}_p"),   n=getattr(pads, f"rx{c2d[color]}_n"))
            gtp = GTP(pll, tx_pads, rx_pads=rx_pads, sys_clk_freq=sys_clk_freq,
                tx_polarity      = 1, # FIXME: Specific to Decklink Mini 4K, make it configurable.
                tx_buffer_enable = True,
                rx_buffer_enable = True,
                clock_aligner    = False
            )
            setattr(self.submodules, f"gtp{color}", gtp)
            self.comb += gtp.tx_produce_pattern.eq(1)
            self.comb += gtp.tx_pattern.eq(cdc.source.data)
Exemple #28
0
    def __init__(self, buffer_depth=4):
        self.sink = sink = stream.Endpoint(etherbone_record_description(32))
        self.source = source = stream.Endpoint(etherbone_mmap_description(32))

        # # #

        fifo = stream.SyncFIFO(etherbone_record_description(32),
                               buffer_depth,
                               buffered=True)
        self.submodules += fifo
        self.comb += sink.connect(fifo.sink)

        base_addr = Signal(32)
        base_addr_update = Signal()
        self.sync += If(base_addr_update, base_addr.eq(fifo.source.data))

        counter = Signal(max=512)
        counter_reset = Signal()
        counter_ce = Signal()
        self.sync += \
            If(counter_reset,
                counter.eq(0)
            ).Elif(counter_ce,
                counter.eq(counter + 1)
            )

        self.submodules.fsm = fsm = FSM(reset_state="IDLE")
        fsm.act(
            "IDLE", fifo.source.ready.eq(1), counter_reset.eq(1),
            If(
                fifo.source.valid, base_addr_update.eq(1),
                If(fifo.source.wcount, NextState("RECEIVE_WRITES")).Elif(
                    fifo.source.rcount, NextState("RECEIVE_READS"))))
        fsm.act(
            "RECEIVE_WRITES", source.valid.eq(fifo.source.valid),
            source.last.eq(counter == fifo.source.wcount - 1),
            source.count.eq(fifo.source.wcount),
            source.be.eq(fifo.source.byte_enable),
            source.addr.eq(base_addr[2:] + counter), source.we.eq(1),
            source.data.eq(fifo.source.data),
            fifo.source.ready.eq(source.ready),
            If(
                source.valid & source.ready, counter_ce.eq(1),
                If(
                    source.last,
                    If(fifo.source.rcount,
                       NextState("RECEIVE_BASE_RET_ADDR")).Else(
                           NextState("IDLE")))))
        fsm.act(
            "RECEIVE_BASE_RET_ADDR", counter_reset.eq(1),
            If(fifo.source.valid, base_addr_update.eq(1),
               NextState("RECEIVE_READS")))
        fsm.act(
            "RECEIVE_READS", source.valid.eq(fifo.source.valid),
            source.last.eq(counter == fifo.source.rcount - 1),
            source.count.eq(fifo.source.rcount),
            source.base_addr.eq(base_addr),
            source.addr.eq(fifo.source.data[2:]),
            fifo.source.ready.eq(source.ready),
            If(source.valid & source.ready, counter_ce.eq(1),
               If(source.last, NextState("IDLE"))))