コード例 #1
0
 def blanking(p,
              length,
              omit_footer=False,
              type=DsiLongPacketDataType.BLANKING_PACKET_NO_DATA):
     length_without_overhead = length - 6
     m.d.sync += blanking_counter.eq(0)
     if not isinstance(length_without_overhead, Value):
         length_without_overhead = Const(length_without_overhead, 16)
     send_short_packet(p, type, length_without_overhead[0:16])
     with process_write_to_stream(m, self.output, payload=0x0):
         m.d.sync += blanking_counter.eq(blanking_counter + 1)
         m.d.comb += is_ready.eq(1)
     p += m.If(
         blanking_counter + is_ready >= length_without_overhead //
         2)  # the packet overhead is 6 bytes (4 header and 2 footer)
     if not omit_footer:
         p += process_write_to_stream(m, self.output,
                                      payload=0x0)  # checksum
コード例 #2
0
        def v_porch(name, to, length, skip_first_hsync=False):
            if not skip_first_hsync:
                first_name = name
                second_process_name = f"{name}_OVERHEAD"
            else:
                first_name = f"{name}_HSYNC"
                second_process_name = name

            with Process(m, first_name, to=second_process_name) as p:
                send_short_packet(p, DsiShortPacketDataType.H_SYNC_START)

            with Process(m, second_process_name, to=None) as p:
                blanking(p,
                         self.hfp + self.image_width + self.hbp,
                         type=DsiLongPacketDataType.NULL_PACKET_NO_DATA,
                         omit_footer=True)
                with process_write_to_stream(m, self.output, payload=0x0):
                    with m.If(v_porch_counter < length):
                        m.d.sync += v_porch_counter.eq(v_porch_counter + 1)
                        m.next = first_name
                    with m.Else():
                        m.d.sync += v_porch_counter.eq(0)
                        m.next = to
コード例 #3
0
 def send_hs(data):
     return process_write_to_stream(m, serializer.input, payload=data)
コード例 #4
0
 def send_short_packet(p, type, payload=Const(0, 16), lp_after=False):
     for value, last in short_packet_words(type, payload):
         p += process_write_to_stream(m,
                                      self.output,
                                      payload=value,
                                      last=last & lp_after)
コード例 #5
0
    def elaborate(self, platform):
        m = Module()

        gearbox = m.submodules.gearbox = StreamGearbox(
            self.input, target_width=len(self.output.payload))

        def repack_to_lanes(packet):
            values = [
                packet[i * 8:(i + 1) * 8] for i in range(len(packet) // 8)
            ]
            if self.num_lanes == 1:
                pass
            elif self.num_lanes == 2:
                values = [
                    Cat(values[0:2]),
                    Cat(values[2:4]),
                ]
            elif self.num_lanes == 4:
                values = Cat(values)
            else:
                raise AssertionError("Invalid number of lanes!")
            return [(v, i == len(values) - 1) for i, v in enumerate(values)]

        def short_packet_words(type, payload=Const(0, 16)):
            data_id = DataIdentifier(data_type=type,
                                     virtual_channel_identifier=0)
            packet_prelim = PacketHeader(data_id=data_id,
                                         word_count=payload,
                                         ecc=0)
            packet = PacketHeader(data_id=data_id,
                                  word_count=payload,
                                  ecc=packet_prelim.calculate_ecc())
            return repack_to_lanes(packet.as_value())

        def send_short_packet(p, type, payload=Const(0, 16), lp_after=False):
            for value, last in short_packet_words(type, payload):
                p += process_write_to_stream(m,
                                             self.output,
                                             payload=value,
                                             last=last & lp_after)

        def end_of_transmission(p):
            send_short_packet(
                p,
                DsiShortPacketDataType.END_OF_TRANSMISSION_PACKET,
                lp_after=True)

        blanking_counter = Signal(16)
        is_ready = Signal()

        def blanking(p,
                     length,
                     omit_footer=False,
                     type=DsiLongPacketDataType.BLANKING_PACKET_NO_DATA):
            length_without_overhead = length - 6
            m.d.sync += blanking_counter.eq(0)
            if not isinstance(length_without_overhead, Value):
                length_without_overhead = Const(length_without_overhead, 16)
            send_short_packet(p, type, length_without_overhead[0:16])
            with process_write_to_stream(m, self.output, payload=0x0):
                m.d.sync += blanking_counter.eq(blanking_counter + 1)
                m.d.comb += is_ready.eq(1)
            p += m.If(
                blanking_counter + is_ready >= length_without_overhead //
                2)  # the packet overhead is 6 bytes (4 header and 2 footer)
            if not omit_footer:
                p += process_write_to_stream(m, self.output,
                                             payload=0x0)  # checksum

        frame_last = Signal()
        v_porch_counter = Signal(16)

        def v_porch(name, to, length, skip_first_hsync=False):
            if not skip_first_hsync:
                first_name = name
                second_process_name = f"{name}_OVERHEAD"
            else:
                first_name = f"{name}_HSYNC"
                second_process_name = name

            with Process(m, first_name, to=second_process_name) as p:
                send_short_packet(p, DsiShortPacketDataType.H_SYNC_START)

            with Process(m, second_process_name, to=None) as p:
                blanking(p,
                         self.hfp + self.image_width + self.hbp,
                         type=DsiLongPacketDataType.NULL_PACKET_NO_DATA,
                         omit_footer=True)
                with process_write_to_stream(m, self.output, payload=0x0):
                    with m.If(v_porch_counter < length):
                        m.d.sync += v_porch_counter.eq(v_porch_counter + 1)
                        m.next = first_name
                    with m.Else():
                        m.d.sync += v_porch_counter.eq(0)
                        m.next = to

        trig = Signal()
        if self.debug and False:
            probe(m, self.output.valid)
            probe(m, self.output.ready)
            probe(m, self.output.last)
            probe(m, self.output.payload)
            probe(m, gearbox.output.ready)
            probe(m, gearbox.output.valid)
            probe(m, gearbox.output.frame_last)
            probe(m, gearbox.output.line_last)
            probe(m, gearbox.output.payload)

            # trigger(m, trig)

        with m.FSM() as fsm:
            fsm_status_reg(platform, m, fsm)
            if self.debug:
                ...
                #fsm_probe(m, fsm)

            with Process(m, "VSYNC_START", to="VBP") as p:
                send_short_packet(p, DsiShortPacketDataType.V_SYNC_START)

            v_porch("VBP", "LINE_START", self.vbp, skip_first_hsync=True)

            with Process(m, "LINE_START", to="LINE_DATA") as p:
                end_of_transmission(p)
                p += m.If(gearbox.output.valid)
                m.d.comb += trig.eq(1)
                send_short_packet(p, DsiShortPacketDataType.H_SYNC_START)
                blanking(p, self.hbp)
                send_short_packet(
                    p,
                    DsiLongPacketDataType.PACKED_PIXEL_STREAM_24_BIT_RGB_8_8_8,
                    self.image_width)
            with m.State("LINE_DATA"):
                with m.If(gearbox.output.line_last & gearbox.output.valid
                          & gearbox.output.ready):
                    m.next = "LINE_END"
                    m.d.sync += frame_last.eq(gearbox.output.frame_last)
                with m.If(~gearbox.output.valid):
                    m.d.sync += self.gearbox_not_ready.eq(
                        self.gearbox_not_ready + 1)
                m.d.comb += self.output.connect_upstream(gearbox.output,
                                                         allow_partial=True)
            with Process(m, "LINE_END", to=None) as p:
                p += process_write_to_stream(
                    m, self.output,
                    payload=0x0)  # TODO: handle the non 2 lane case
                blanking(
                    p, self.hfp, omit_footer=True
                )  # we omit the footer to be able to do dispatch the next state with zero cycle delay
                with process_write_to_stream(m, self.output, payload=0x0):
                    with m.If(frame_last):
                        m.next = "VFP"
                    with m.Else():
                        m.next = "LINE_START"

            v_porch("VFP", "FRAME_END", self.vfp)

            with Process(m, "FRAME_END", to="VSYNC_START") as p:
                end_of_transmission(p)

        return m