Source code for hdmi.cores.receiver.decode

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
[docs]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()