📄 a10281_ph.vhd
字号:
read_counter <= ac_t_minus_1; ELSIF read_counter = ac_1 THEN read_counter <= ac_t; ELSIF read_counter = ac_t THEN read_counter <= ac_2t_minus_1; ELSIF read_counter = ac_t_plus_1 THEN read_mem_2t <= TRUE; ctr_state <= offset_ascending; read_counter <= ac_1; END IF; -- mem_2T between these two states (1 count) WHEN offset_ascending => -- Count up 1..T-1, 0, T+1..2T-1, T (2T counts) modulo_inc(read_counter); IF read_counter = ac_t_minus_1 THEN read_counter <= ac_0; ELSIF read_counter = ac_0 THEN read_counter <= ac_t_plus_1; ELSIF read_counter = ac_2t_minus_1 THEN read_counter <= ac_t; ELSIF read_counter = ac_t THEN ctr_state <= short_descending; read_counter <= ac_t_minus_1; END IF; WHEN short_descending => -- Count down T-1..1, 2T, 2T-1..T+1 (2T-1 counts) modulo_dec(read_counter); IF read_counter = ac_1 THEN read_mem_2t <= TRUE; read_counter <= ac_2t_minus_1; ELSIF read_counter = ac_t_plus_1 THEN read_counter <= ac_0; ctr_state <= normal_ascending; END IF; WHEN OTHERS => ctr_state <= normal_ascending; END CASE; END IF; -- NOT read_mem_2t END IF; -- enable END IF; -- clock END PROCESS addrgen; tre_d1 : PROCESS (reset_n, clk_out) BEGIN IF reset_n = '0' THEN tre_rd_index <= ( OTHERS => '0' ); tre_rd_d1 <= ( OTHERS => '0' ); rd_sel <= '0'; rd_sel_2t <= FALSE; trellis_en_d1 <= '0'; shift_d <= ( OTHERS => '0' ); shift_y <= ( OTHERS => '0' ); mask_counter_d1 <= ( OTHERS => '0' ); reverser_shift_d1 <= FALSE; mask_counter_d3 <= ( OTHERS => '0' ); ELSIF clk_out'EVENT AND clk_out = '1' THEN IF viterbi_init = '1' THEN tre_rd_index <= ( OTHERS => '0' ); tre_rd_d1 <= ( OTHERS => '0' ); rd_sel <= '0'; rd_sel_2t <= FALSE; trellis_en_d1 <= '0'; shift_d <= ( OTHERS => '0' ); shift_y <= ( OTHERS => '0' ); mask_counter_d1 <= ( OTHERS => '0' ); reverser_shift_d1 <= FALSE; mask_counter_d3 <= ( OTHERS => '0' ); ELSIF clk_out_enable = '1' THEN tre_rd_index <= tre_rd_d1; tre_rd_d1 <= trellis_sel; rd_sel <= read_counter(0); rd_sel_2t <= read_mem_2t; trellis_en_d1 <= trellis_en; shift_d(conv_integer(unsigned(tre_rd_index))) <= selected_memory_bit; shift_y(conv_integer(unsigned(tre_rd_index))) <= selected_y; mask_counter_d1 <= mask_counter; reverser_shift_d1 <= reverser_shift_left; mask_counter_d3 <= mask_counter_tre; END IF; END IF; END PROCESS tre_d1; -- this is the 2T'th memory location. memory_element_2t : PROCESS BEGIN WAIT UNTIL clk_out'EVENT AND clk_out = '1'; IF clk_out_enable = '1' AND write_mem_2t THEN mem_2t(conv_integer(unsigned(tre_rd_d1))) <= out_y & decision; END IF; END PROCESS memory_element_2t; -- The traceback unit. The "addrgen" process provides a correctly sequenced -- data stream. This process must synchronised to the block boundaries, and -- perform the traceback on the data, which it must push into the bit reverser. traceback_cont : PROCESS (reset_n, clk_out) BEGIN IF reset_n = '0' THEN linear_counter <= (OTHERS => '0'); mask_counter <= (OTHERS => '0'); mask_counter_tre<= (OTHERS => '0'); mask_counter_d2 <= (OTHERS => '0'); capture_regs <= TRUE; ELSIF clk_out'EVENT AND clk_out = '1' THEN IF viterbi_init = '1' THEN linear_counter <= (OTHERS => '0'); mask_counter <= (OTHERS => '0'); mask_counter_tre<= (OTHERS => '0'); mask_counter_d2 <= (OTHERS => '0'); capture_regs <= TRUE; ELSIF clk_out_enable = '1' AND trellis_en = '1' THEN mask_counter_d2 <= mask_counter; mask_counter_tre<= mask_counter_d2; -- Linear counter is for timing purposes within the T-clock macro cycle -- The "write_mem_2t" term synchronises it to the address generator. IF read_mem_2t OR linear_counter = linear_counter_max THEN linear_counter <= (OTHERS => '0'); capture_regs <= TRUE; IF mask_counter /= 3 THEN mask_counter <= mask_counter + 1; END IF; ELSE linear_counter <= linear_counter + 1; --IF linear_counter = conv_unsigned(memory_order-1, traceback_address_type'LENGTH) THEN capture_regs <= FALSE; --END IF; END IF; END IF; END IF; END PROCESS traceback_cont; shift_cont : PROCESS (reset_n, clk_out) BEGIN IF reset_n = '0' THEN reverser_shift_left <= FALSE; ELSIF clk_out'EVENT AND clk_out = '1' THEN IF viterbi_init = '1' THEN reverser_shift_left <= FALSE; ELSIF clk_out_enable = '1' AND trellis_en = '1' THEN --IF linear_counter = linear_counter_max THEN IF linear_counter = linear_counter_zero THEN -- initialise traceback reverser_shift_left <= NOT reverser_shift_left; END IF; END IF; END IF; END PROCESS shift_cont; traceback : PROCESS (reset_n, clk_out) variable tmp : unsigned(memory_order-1 DOWNTO 0); variable gs_tmp : unsigned(memory_order-1 DOWNTO 0); BEGIN IF reset_n = '0' THEN shifter <= (OTHERS => (OTHERS => '-')); reverser <= (OTHERS => (OTHERS => '-')); reverser_y <= (OTHERS => (OTHERS => '0')); ELSIF clk_out'EVENT AND clk_out = '1' THEN IF clk_out_enable = '1' THEN IF linear_counter = linear_counter_zero AND trellis_en_d1 = '1' THEN -- initialise traceback FOR index IN 11 DOWNTO 0 LOOP shifter(index) <= unsigned(regex(index)(0)); END LOOP; ELSE -- do a cycle of traceback tmp := shifter(conv_integer(unsigned(tre_rd_index))); tmp := tmp( memory_order-2 DOWNTO 0 ) & tmp( memory_order-1 ); gs_tmp := ( OTHERS => '0' ); gs_tmp( memory_order-1 ) := selected_memory_bit; tmp := unsigned( std_logic_vector( tmp ) xor std_logic_vector( gs_tmp )); shifter(conv_integer(unsigned(tre_rd_index))) <= tmp; END IF; IF reverser_shift_d1 THEN reverser(conv_integer(unsigned(tre_rd_index))) <= reverser(conv_integer(unsigned(tre_rd_index)))(traceback_length-2 DOWNTO 0) & shift_d(conv_integer(unsigned(tre_rd_index))); reverser_y(conv_integer(unsigned(tre_rd_index))) <= reverser_y(conv_integer(unsigned(tre_rd_index)))(traceback_length-2 DOWNTO 0) & shift_y(conv_integer(unsigned(tre_rd_index))); ELSE reverser(conv_integer(unsigned(tre_rd_index))) <= shift_d(conv_integer(unsigned(tre_rd_index))) & reverser(conv_integer(unsigned(tre_rd_index)))(traceback_length-1 DOWNTO 1); reverser_y(conv_integer(unsigned(tre_rd_index))) <= shift_y(conv_integer(unsigned(tre_rd_index))) & reverser_y(conv_integer(unsigned(tre_rd_index)))(traceback_length-1 DOWNTO 1); END IF; --IF reverser_shift_d1 THEN -- reverser(conv_integer(unsigned(tre_rd_index))) <= reverser(conv_integer(unsigned(tre_rd_index)))(traceback_length-2 DOWNTO 0) & selected_memory_bit; -- reverser_y(conv_integer(unsigned(tre_rd_index))) <= reverser_y(conv_integer(unsigned(tre_rd_index)))(traceback_length-2 DOWNTO 0) & selected_y; --ELSE -- reverser(conv_integer(unsigned(tre_rd_index))) <= selected_memory_bit & reverser(conv_integer(unsigned(tre_rd_index)))(traceback_length-1 DOWNTO 1); -- reverser_y(conv_integer(unsigned(tre_rd_index))) <= selected_y & reverser_y(conv_integer(unsigned(tre_rd_index)))(traceback_length-1 DOWNTO 1); --END IF; END IF; END IF; END PROCESS traceback; -- The register exchange unit. This must synchronise to the block boundaries -- as determined by the linear counter regex_unit : PROCESS (reset_n, clk_out) VARIABLE vec_state : std_logic_vector(memory_order-1 DOWNTO 0); VARIABLE prev_state_a : std_logic_vector(memory_order-1 DOWNTO 0); VARIABLE prev_state_b : std_logic_vector(memory_order-1 DOWNTO 0); VARIABLE prev_reg_a : std_logic_vector(memory_order-1 DOWNTO 0); VARIABLE prev_reg_b : std_logic_vector(memory_order-1 DOWNTO 0); BEGIN IF reset_n = '0' THEN regex <= (OTHERS => (OTHERS => regex_zero)); ELSIF clk_out'EVENT AND clk_out = '1' THEN IF viterbi_init = '1' THEN regex <= (OTHERS => (OTHERS => regex_zero)); ELSIF clk_out_enable = '1' THEN -- The Register Exchange unit, of length memory_order FOR state IN 0 TO trellis_width-1 LOOP -- get the bitwise representation of this state vec_state := std_logic_vector(conv_unsigned(state, vec_state'LENGTH)); -- the two previous states for getting to this state prev_state_a := vec_state(vec_state'HIGH-1 DOWNTO 0) & vec_state(vec_state'HIGH); prev_state_b := (vec_state(vec_state'HIGH-1 DOWNTO 0) & vec_state(vec_state'HIGH)) xor gs; -- and their respective registers prev_reg_a := regex(conv_integer(unsigned(tre_rd_d1)))(conv_integer(unsigned(prev_state_a))); prev_reg_b := regex(conv_integer(unsigned(tre_rd_d1)))(conv_integer(unsigned(prev_state_b))); -- the above should just synthesise to wires. Now for some logic... IF capture_regs THEN IF decision(state) = '0' THEN regex(conv_integer(unsigned(tre_rd_d1)))(state) <= prev_state_a; ELSE regex(conv_integer(unsigned(tre_rd_d1)))(state) <= prev_state_b; END IF; ELSE IF decision(state) = '0' THEN regex(conv_integer(unsigned(tre_rd_d1)))(state) <= prev_reg_a; ELSE regex(conv_integer(unsigned(tre_rd_d1)))(state) <= prev_reg_b; END IF; END IF; END LOOP; END IF; -- clk_out_enable END IF; -- clock END PROCESS regex_unit; END rtl ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -