<reponame>srivatsan-ramesh/HDMI-Source-Sink-Modules
from myhdl import block, Signal, always, always_comb, intbv, concat, instances

from hdmi.cores import control_token_0, control_token_1, control_token_2, control_token_3
from hdmi.cores.receiver import phase_aligner, channel_bonding, serdes_1_to_5


@block
def decode(reset, p_clock, p_clockx2, p_clockx10, serdes_strobe, data_in_p, data_in_n,
           other_ch0_valid, other_ch1_valid, other_ch0_ready, other_ch1_ready,
           video_preamble, data_island_preamble, i_am_ready, i_am_valid, phase_align_err,
           c0, c1, vde, ade, s_data_out, video_out, audio_out, channel='BLUE'):

    """

    This module performs the decoding logic of a hdmi decoder for a particular channel.
    It is modelled after the xilinx application notes xapp460 and xapp495.

    Args:
        reset: An asynchronous reset signal that resets the output.
        p_clock: The pixel clock
        p_clockx2: Clock with twice the frequency of pixel clock
        p_clockx10: Clock with ten times the frequency of pixel clock
        serdes_strobe: The signal used in serdes block
        data_in_p: Differential signal input
        data_in_n: Differential signal input
        other_ch0_valid: Denotes the validity of other channel data
        other_ch1_valid: Denotes the validity of other channel data
        other_ch0_ready: Denotes the readiness of other channel data
        other_ch1_ready: Denotes the readiness of other channel data
        video_preamble: Denotes the video preamble region of the input data
        data_island_preamble: Denotes the data island preamble region of the input data
        i_am_ready: Denotes the readiness of this channel data
        i_am_valid: Denotes the validity of this channel data
        phase_align_err: Becomes True when there is an error in aligning the phase
        c0: Control signal (hsync in BLUE channel)
        c1: Control signal (vsync in BLUE channel)
        vde: Video data enable
        ade: Auxiliary data enable
        s_data_out: The raw 10 bit data obtained from TMDS channels
        video_out: The decoded video data
        audio_out: The decoded audio data
        channel: The color of the channel (Default: BLUE)

    Returns:
        myhdl.instances() : A list of myhdl instances.

    """

    flip_gear, flip_gearx2, toggle, rx_toggle = [Signal(bool(0)) for _ in range(4)]

    @always(p_clockx2.posedge)
    def assign_flip_gear():
        flip_gearx2.next = flip_gear

    @always(p_clockx2.posedge, reset.posedge)
    def toggle_toggle():
        if reset:
            toggle.next = 0
        else:
            toggle.next = not toggle

    @always_comb
    def assign_toggle():
        rx_toggle.next = toggle ^ flip_gearx2

    raw_5_bit, _raw_5_bit = [Signal(intbv(0)[5:0]) for _ in range(2)]
    raw_word, raw_data = [Signal(intbv(0)[10:0]) for _ in range(2)]

    @always(p_clockx2.posedge)
    def make_10bit():
        _raw_5_bit.next = raw_5_bit
        if rx_toggle:
            raw_word.next = concat(raw_5_bit, _raw_5_bit)
        raw_data.next = raw_word

    bit_slip, _bit_slip, bit_slipx2 = [Signal(bool(0)) for _ in range(3)]

    @always(p_clockx2.posedge)
    def bitslip():
        _bit_slip.next = bit_slip
        bit_slipx2.next = bit_slip and not _bit_slip

    des_0 = serdes_1_to_5.serdes_1_to_5(Signal(True), data_in_p, data_in_n, p_clockx10,
                                        serdes_strobe, reset, p_clockx2, bit_slipx2, raw_5_bit)

    phase_aligner_0 = phase_aligner.phase_aligner(reset, p_clock, raw_data, bit_slip, flip_gear, i_am_valid)

    phase_align_err.next = 0

    data_in = Signal(intbv(0)[10:0])
    channel_bond = channel_bonding.channel_bonding(p_clock, raw_data, i_am_valid, other_ch0_valid, other_ch1_valid,
                                                   other_ch0_ready, other_ch1_ready, i_am_ready, data_in)

    # Control signals
    control, _control, control_end = [Signal(bool(0)) for _ in range(3)]

    # Signals to detect video period and data island period
    video_period = Signal(bool(0))
    data_island_period = Signal(bool(0))

    data = Signal(intbv(0)[8:0])

    is_blue = True if channel == 'BLUE' else False

    @always_comb
    def continuous_assignment():
        data.next = ~data_in[8:0] if data_in[9] else data_in[8:0]
        control_end.next = (not control) & _control

    @always(p_clock.posedge)
    def sequential_logic():
        _control.next = control

        if control:
            video_period.next = 0
        elif control_end and video_preamble:
            video_period.next = 1

        if control:
            data_island_period.next = 0
        elif control_end and data_island_preamble:
            data_island_period.next = 1

        if i_am_ready and other_ch0_ready and other_ch1_ready:
            if data_in == control_token_0:
                c0.next = 0
                c1.next = 0
                vde.next = 0
                ade.next = 0
                control.next = 1

            elif data_in == control_token_1:
                c0.next = 1
                c1.next = 0
                vde.next = 0
                ade.next = 0
                control.next = 1

            elif data_in == control_token_2:
                c0.next = 0
                c1.next = 1
                vde.next = 0
                ade.next = 0
                control.next = 1

            elif data_in == control_token_3:
                c0.next = 1
                c1.next = 1
                vde.next = 0
                ade.next = 0
                control.next = 1

            else:
                control.next = 0
                if video_period:
                    video_out.next[0] = data[0]
                    if data_in[8]:
                        video_out.next[8:1] = data[8:1] ^ data[7:0]
                    else:
                        video_out.next[8:1] = data[8:1] ^ (~ data[7:0])
                    ade.next = 0
                    vde.next = 1

                elif is_blue or data_island_period:
                    if data_in == 668:
                        audio_out.next = 0
                        ade.next = 1
                        vde.next = 0

                    elif data_in == 611:
                        audio_out.next = 1
                        ade.next = 1
                        vde.next = 0

                    elif data_in == 740:
                        audio_out.next = 2
                        ade.next = 1
                        vde.next = 0

                    elif data_in == 738:
                        audio_out.next = 3
                        ade.next = 1
                        vde.next = 0

                    elif data_in == 369:
                        audio_out.next = 4
                        ade.next = 1
                        vde.next = 0

                    elif data_in == 286:
                        audio_out.next = 5
                        ade.next = 1
                        vde.next = 0

                    elif data_in == 398:
                        audio_out.next = 6
                        ade.next = 1
                        vde.next = 0

                    elif data_in == 316:
                        audio_out.next = 7
                        ade.next = 1
                        vde.next = 0

                    elif data_in == 716:
                        if is_blue and _control:
                            ade.next = 0
                        else:
                            audio_out.next = 8
                            ade.next = 1
                        vde.next = 0

                    elif data_in == 313:
                        audio_out.next = 9
                        ade.next = 1
                        vde.next = 0

                    elif data_in == 412:
                        audio_out.next = 10
                        ade.next = 1
                        vde.next = 0

                    elif data_in == 710:
                        audio_out.next = 11
                        ade.next = 1
                        vde.next = 0

                    elif data_in == 654:
                        audio_out.next = 12
                        ade.next = 1
                        vde.next = 0

                    elif data_in == 625:
                        audio_out.next = 13
                        ade.next = 1
                        vde.next = 0

                    elif data_in == 355:
                        audio_out.next = 14
                        ade.next = 1
                        vde.next = 0

                    elif data_in == 707:
                        audio_out.next = 15
                        ade.next = 1
                        vde.next = 0

                    else:
                        audio_out.next = audio_out
                        ade.next = 0
                        vde.next = 0

            s_data_out.next = data_in

    return instances()
from myhdl import block, Signal, always, always_comb, intbv, concat, instances

from hdmi.cores import control_token_0, control_token_1, control_token_2, control_token_3
from hdmi.cores.receiver import phase_aligner, channel_bonding, serdes_1_to_5


@block
def decode(reset, p_clock, p_clockx2, p_clockx10, serdes_strobe, data_in_p, data_in_n,
           other_ch0_valid, other_ch1_valid, other_ch0_ready, other_ch1_ready,
           video_preamble, data_island_preamble, i_am_ready, i_am_valid, phase_align_err,
           c0, c1, vde, ade, s_data_out, video_out, audio_out, channel='BLUE'):

    """

    This module performs the decoding logic of a hdmi decoder for a particular channel.
    It is modelled after the xilinx application notes xapp460 and xapp495.

    Args:
        reset: An asynchronous reset signal that resets the output.
        p_clock: The pixel clock
        p_clockx2: Clock with twice the frequency of pixel clock
        p_clockx10: Clock with ten times the frequency of pixel clock
        serdes_strobe: The signal used in serdes block
        data_in_p: Differential signal input
        data_in_n: Differential signal input
        other_ch0_valid: Denotes the validity of other channel data
        other_ch1_valid: Denotes the validity of other channel data
        other_ch0_ready: Denotes the readiness of other channel data
        other_ch1_ready: Denotes the readiness of other channel data
        video_preamble: Denotes the video preamble region of the input data
        data_island_preamble: Denotes the data island preamble region of the input data
        i_am_ready: Denotes the readiness of this channel data
        i_am_valid: Denotes the validity of this channel data
        phase_align_err: Becomes True when there is an error in aligning the phase
        c0: Control signal (hsync in BLUE channel)
        c1: Control signal (vsync in BLUE channel)
        vde: Video data enable
        ade: Auxiliary data enable
        s_data_out: The raw 10 bit data obtained from TMDS channels
        video_out: The decoded video data
        audio_out: The decoded audio data
        channel: The color of the channel (Default: BLUE)

    Returns:
        myhdl.instances() : A list of myhdl instances.

    """

    flip_gear, flip_gearx2, toggle, rx_toggle = [Signal(bool(0)) for _ in range(4)]

    @always(p_clockx2.posedge)
    def assign_flip_gear():
        flip_gearx2.next = flip_gear

    @always(p_clockx2.posedge, reset.posedge)
    def toggle_toggle():
        if reset:
            toggle.next = 0
        else:
            toggle.next = not toggle

    @always_comb
    def assign_toggle():
        rx_toggle.next = toggle ^ flip_gearx2

    raw_5_bit, _raw_5_bit = [Signal(intbv(0)[5:0]) for _ in range(2)]
    raw_word, raw_data = [Signal(intbv(0)[10:0]) for _ in range(2)]

    @always(p_clockx2.posedge)
    def make_10bit():
        _raw_5_bit.next = raw_5_bit
        if rx_toggle:
            raw_word.next = concat(raw_5_bit, _raw_5_bit)
        raw_data.next = raw_word

    bit_slip, _bit_slip, bit_slipx2 = [Signal(bool(0)) for _ in range(3)]

    @always(p_clockx2.posedge)
    def bitslip():
        _bit_slip.next = bit_slip
        bit_slipx2.next = bit_slip and not _bit_slip

    des_0 = serdes_1_to_5.serdes_1_to_5(Signal(True), data_in_p, data_in_n, p_clockx10,
                                        serdes_strobe, reset, p_clockx2, bit_slipx2, raw_5_bit)

    phase_aligner_0 = phase_aligner.phase_aligner(reset, p_clock, raw_data, bit_slip, flip_gear, i_am_valid)

    phase_align_err.next = 0

    data_in = Signal(intbv(0)[10:0])
    channel_bond = channel_bonding.channel_bonding(p_clock, raw_data, i_am_valid, other_ch0_valid, other_ch1_valid,
                                                   other_ch0_ready, other_ch1_ready, i_am_ready, data_in)

    # Control signals
    control, _control, control_end = [Signal(bool(0)) for _ in range(3)]

    # Signals to detect video period and data island period
    video_period = Signal(bool(0))
    data_island_period = Signal(bool(0))

    data = Signal(intbv(0)[8:0])

    is_blue = True if channel == 'BLUE' else False

    @always_comb
    def continuous_assignment():
        data.next = ~data_in[8:0] if data_in[9] else data_in[8:0]
        control_end.next = (not control) & _control

    @always(p_clock.posedge)
    def sequential_logic():
        _control.next = control

        if control:
            video_period.next = 0
        elif control_end and video_preamble:
            video_period.next = 1

        if control:
            data_island_period.next = 0
        elif control_end and data_island_preamble:
            data_island_period.next = 1

        if i_am_ready and other_ch0_ready and other_ch1_ready:
            if data_in == control_token_0:
                c0.next = 0
                c1.next = 0
                vde.next = 0
                ade.next = 0
                control.next = 1

            elif data_in == control_token_1:
                c0.next = 1
                c1.next = 0
                vde.next = 0
                ade.next = 0
                control.next = 1

            elif data_in == control_token_2:
                c0.next = 0
                c1.next = 1
                vde.next = 0
                ade.next = 0
                control.next = 1

            elif data_in == control_token_3:
                c0.next = 1
                c1.next = 1
                vde.next = 0
                ade.next = 0
                control.next = 1

            else:
                control.next = 0
                if video_period:
                    video_out.next[0] = data[0]
                    if data_in[8]:
                        video_out.next[8:1] = data[8:1] ^ data[7:0]
                    else:
                        video_out.next[8:1] = data[8:1] ^ (~ data[7:0])
                    ade.next = 0
                    vde.next = 1

                elif is_blue or data_island_period:
                    if data_in == 668:
                        audio_out.next = 0
                        ade.next = 1
                        vde.next = 0

                    elif data_in == 611:
                        audio_out.next = 1
                        ade.next = 1
                        vde.next = 0

                    elif data_in == 740:
                        audio_out.next = 2
                        ade.next = 1
                        vde.next = 0

                    elif data_in == 738:
                        audio_out.next = 3
                        ade.next = 1
                        vde.next = 0

                    elif data_in == 369:
                        audio_out.next = 4
                        ade.next = 1
                        vde.next = 0

                    elif data_in == 286:
                        audio_out.next = 5
                        ade.next = 1
                        vde.next = 0

                    elif data_in == 398:
                        audio_out.next = 6
                        ade.next = 1
                        vde.next = 0

                    elif data_in == 316:
                        audio_out.next = 7
                        ade.next = 1
                        vde.next = 0

                    elif data_in == 716:
                        if is_blue and _control:
                            ade.next = 0
                        else:
                            audio_out.next = 8
                            ade.next = 1
                        vde.next = 0

                    elif data_in == 313:
                        audio_out.next = 9
                        ade.next = 1
                        vde.next = 0

                    elif data_in == 412:
                        audio_out.next = 10
                        ade.next = 1
                        vde.next = 0

                    elif data_in == 710:
                        audio_out.next = 11
                        ade.next = 1
                        vde.next = 0

                    elif data_in == 654:
                        audio_out.next = 12
                        ade.next = 1
                        vde.next = 0

                    elif data_in == 625:
                        audio_out.next = 13
                        ade.next = 1
                        vde.next = 0

                    elif data_in == 355:
                        audio_out.next = 14
                        ade.next = 1
                        vde.next = 0

                    elif data_in == 707:
                        audio_out.next = 15
                        ade.next = 1
                        vde.next = 0

                    else:
                        audio_out.next = audio_out
                        ade.next = 0
                        vde.next = 0

            s_data_out.next = data_in

    return instances()
This module performs the decoding logic of a hdmi decoder for a particular channel.     It is modelled after the xilinx application notes xapp460 and xapp495.      Args:         reset: An asynchronous reset signal that resets the output.         p_clock: The pixel clock         p_clockx2: Clock with twice the frequency of pixel clock         p_clockx10: Clock with ten times the frequency of pixel clock         serdes_strobe: The signal used in serdes block         data_in_p: Differential signal input         data_in_n: Differential signal input         other_ch0_valid: Denotes the validity of other channel data         other_ch1_valid: Denotes the validity of other channel data         other_ch0_ready: Denotes the readiness of other channel data         other_ch1_ready: Denotes the readiness of other channel data         video_preamble: Denotes the video preamble region of the input data         data_island_preamble: Denotes the data island preamble region of the input data         i_am_ready: Denotes the readiness of this channel data         i_am_valid: Denotes the validity of this channel data         phase_align_err: Becomes True when there is an error in aligning the phase         c0: Control signal (hsync in BLUE channel)         c1: Control signal (vsync in BLUE channel)         vde: Video data enable         ade: Auxiliary data enable         s_data_out: The raw 10 bit data obtained from TMDS channels         video_out: The decoded video data         audio_out: The decoded audio data         channel: The color of the channel (Default: BLUE)      Returns:         myhdl.instances() : A list of myhdl instances. # Control signals # Signals to detect video period and data island period