Source code for hdmi.cores.receiver.phase_aligner

from myhdl import block, always, Signal, modbv, concat, intbv, always_comb, instances

from hdmi.cores import control_token_0, control_token_1, control_token_2, control_token_3

INIT = 1
SEARCH = 2
BIT_SLIP = 4
RCVD_CTRL_TKN = 8  # Received control token
BLANK_PERIOD = 16
PHASE_ALIGNED = 32  # Phase Alignment Achieved
nSTATES = 6


@block
[docs]def phase_aligner(reset, clock, s_data, bit_slip, flip_gear, phase_aligned): """ This impliments the phase alignment logic modelled after the phase aligner module from xapp495 application notes. Args: reset: reset signal clock: pixel clock s_data: the 10-bit TMDS data bit_slip: An input signal flip_gear: An input signal phase_aligned: denotes whether the phase is aligned Returns: myhdl.instances() : A list of myhdl instances. """ open_eye_counter_width = 3 ctrl_tkn_counter_width = 7 search_timer_width = 12 blank_period_counter_width = 1 received_ctrl_token, _received_ctrl_token, blank_begin = [Signal(False) for _ in range(3)] @always(clock.posedge) def assign_control(): received_ctrl_token.next = (s_data == control_token_0) or (s_data == control_token_1) \ or (s_data == control_token_2) or (s_data == control_token_3) _received_ctrl_token.next = received_ctrl_token blank_begin.next = not _received_ctrl_token and received_ctrl_token ctrl_tkn_search_timer = Signal(modbv(0)[search_timer_width:]) ctrl_tkn_search_reset = Signal(False) @always(clock.posedge) def search_timer(): if ctrl_tkn_search_reset: ctrl_tkn_search_timer.next = 0 else: ctrl_tkn_search_timer.next = ctrl_tkn_search_timer + 1 ctrl_tkn_search_tout = Signal(False) @always(clock.posedge) def search_time_out(): if ctrl_tkn_search_timer == (1 << search_timer_width + 1) - 1: ctrl_tkn_search_tout.next = True else: ctrl_tkn_search_tout.next = False ctrl_tkn_event_timer = Signal(modbv(0)[ctrl_tkn_counter_width:]) ctrl_tkn_event_reset = Signal(False) @always(clock.posedge) def event_timer(): if ctrl_tkn_event_reset: ctrl_tkn_event_timer.next = 0 else: ctrl_tkn_event_timer.next = ctrl_tkn_event_timer + 1 ctrl_tkn_event_tout = Signal(False) @always(clock.posedge) def event_time_out(): if ctrl_tkn_event_timer == (1 << ctrl_tkn_counter_width + 1) - 1: ctrl_tkn_event_tout.next = True else: ctrl_tkn_event_tout.next = False # Below starts the phase alignment state machine curr_state = Signal(intbv(1)[nSTATES:]) next_state = Signal(intbv(0)[nSTATES:]) @always(clock.posedge, reset.posedge) def assign_state(): if reset: curr_state.next = INIT else: curr_state.next = next_state blank_period_counter = Signal(modbv(0)[blank_period_counter_width:]) @always_comb def switch_state(): if curr_state == INIT: next_state.next = SEARCH if ctrl_tkn_search_tout else INIT elif curr_state == SEARCH: if blank_begin: next_state.next = RCVD_CTRL_TKN else: next_state.next = BIT_SLIP if ctrl_tkn_search_tout else SEARCH elif curr_state == BIT_SLIP: next_state.next = SEARCH elif curr_state == RCVD_CTRL_TKN: if received_ctrl_token: next_state.next = BLANK_PERIOD if ctrl_tkn_event_tout else RCVD_CTRL_TKN else: next_state.next = SEARCH elif curr_state == BLANK_PERIOD: if blank_period_counter == (1 << blank_period_counter_width + 1) - 1: next_state.next = PHASE_ALIGNED else: next_state.next = SEARCH elif curr_state == PHASE_ALIGNED: next_state.next = PHASE_ALIGNED bit_slip_counter = Signal(modbv(0)[3:0]) @always(clock.posedge, reset.posedge) def assign(): if reset: phase_aligned.next = 0 bit_slip.next = 0 ctrl_tkn_search_reset.next = 1 ctrl_tkn_event_reset.next = 1 bit_slip_counter.next = 0 flip_gear.next = 0 blank_period_counter.next = 0 else: if curr_state == INIT: ctrl_tkn_search_reset.next = 0 ctrl_tkn_event_reset.next = 1 bit_slip.next = 0 bit_slip_counter.next = 0 if __debug__: phase_aligned.next = 1 flip_gear.next = 0 blank_period_counter.next = 0 elif curr_state == SEARCH: ctrl_tkn_search_reset.next = 0 ctrl_tkn_event_reset.next = 1 bit_slip.next = 0 phase_aligned.next = 0 if __debug__: phase_aligned.next = 1 elif curr_state == BIT_SLIP: ctrl_tkn_search_reset.next = 1 bit_slip.next = 1 bit_slip_counter.next = bit_slip_counter + 1 flip_gear.next = bit_slip_counter[2] elif curr_state == RCVD_CTRL_TKN: ctrl_tkn_search_reset.next = 0 ctrl_tkn_event_reset.next = 0 elif curr_state == BLANK_PERIOD: blank_period_counter.next = blank_period_counter + 1 elif curr_state == PHASE_ALIGNED: phase_aligned.next = 1 return instances()