1--! 2--! Copyright (C) 2011 - 2014 Creonic GmbH 3--! 4--! This file is part of the Creonic Viterbi Decoder, which is distributed 5--! under the terms of the GNU General Public License version 2. 6--! 7--! @file 8--! @brief Trellis parameter calculations (e.g., transitions, init values). 9--! @author Markus Fehrenz 10--! @date 2011/07/27 11--! 12--! 13 14library ieee; 15use ieee.std_logic_1164.all; 16use ieee.numeric_std.all; 17 18library dec_viterbi; 19use dec_viterbi.pkg_param.all; 20use dec_viterbi.pkg_param_derived.all; 21use dec_viterbi.pkg_types.all; 22 23 24package pkg_trellis is 25 26 type t_prev_base is array (1 downto 0) of std_logic_vector(BW_TRELLIS_STATES - 1 downto 0); 27 type t_previous_states is array (NUMBER_TRELLIS_STATES - 1 downto 0) of t_prev_base; 28 29 type t_trans_base is array (1 downto 0) of std_logic_vector(NUMBER_PARITY_BITS - 1 downto 0); 30 type t_transitions is array (NUMBER_TRELLIS_STATES - 1 downto 0) of t_trans_base; 31 32 type t_trans_base_signed is array (1 downto 0) of std_logic_vector(NUMBER_PARITY_BITS downto 0); 33 type t_transitions_signed is array (NUMBER_TRELLIS_STATES - 1 downto 0) of t_trans_base_signed; 34 35 36 -- 37 -- This function calculates the previous states of each state. 38 -- The values are used to connect the ACS units. 39 -- 40 function calc_previous_states return t_previous_states; 41 42 43 -- 44 -- This function calculates corresponding transitions to a trellis sate. 45 -- The values are used to connect branch units to ACS units. 46 -- 47 function calc_transitions return t_transitions; 48 49 50 -- 51 -- This function calculates the initialization values for trellis metrics. 52 -- The values are used as a constant and written to the ACS unit, every time a new block arrives. 53 -- 54 function calc_initialize return t_node_s; 55 56 constant PREVIOUS_STATES : t_previous_states; 57 constant TRANSITIONS : t_transitions; 58 constant INITIALIZE_TRELLIS : t_node_s; 59 60end package pkg_trellis; 61 62 63package body pkg_trellis is 64 65 66 function calc_previous_states return t_previous_states is 67 variable v_prev_states : t_previous_states := (others=>(others=>(others => '0'))); 68 variable v_state0, v_state1 : std_logic_vector(BW_TRELLIS_STATES - 1 downto 0); 69 begin 70 for i in NUMBER_TRELLIS_STATES - 1 downto 0 loop 71 v_state0 := std_logic_vector(to_unsigned(i,BW_TRELLIS_STATES)); 72 v_state1 := v_state0(BW_TRELLIS_STATES - 2 downto 0) & '0'; 73 v_prev_states(i)(0) := v_state1; 74 v_state1 := v_state0(BW_TRELLIS_STATES - 2 downto 0) & '1'; 75 v_prev_states(i)(1) := v_state1; 76 end loop; 77 return v_prev_states; 78 end function calc_previous_states; 79 80 81 function calc_transitions return t_transitions is 82 variable v_transitions : t_transitions_signed := (others => (others => (others => '0'))); 83 variable v_transitions_out : t_transitions := (others => (others => (others => '0'))); 84 variable v_one_transition : std_logic_vector(NUMBER_PARITY_BITS - 1 downto 0); 85 variable v_next_state : unsigned(ENCODER_MEMORY_DEPTH - 1 downto 0) := (others => '0'); 86 variable v_state, v_states : unsigned(ENCODER_MEMORY_DEPTH downto 0); 87 variable v_bit : std_logic := '0'; 88 begin 89 90 -- 91 -- It is possible to reduce code size at this stage, if feedback is handled differently, 92 -- but the complexity will increase. 93 -- 94 95 for i in NUMBER_TRELLIS_STATES - 1 downto 0 loop 96 97 -- 98 -- for input : 0 99 -- determine correct input with feedback 100 -- 101 v_next_state := to_unsigned(i,ENCODER_MEMORY_DEPTH) and to_unsigned(FEEDBACK_POLYNOMIAL, ENCODER_MEMORY_DEPTH); 102 for k in ENCODER_MEMORY_DEPTH - 1 downto 0 loop 103 v_bit := v_bit xor v_next_state(k); 104 end loop; 105 v_state(ENCODER_MEMORY_DEPTH) := v_bit; 106 v_state(ENCODER_MEMORY_DEPTH - 1 downto 0) := to_unsigned(i,ENCODER_MEMORY_DEPTH); 107 v_next_state := v_state(ENCODER_MEMORY_DEPTH downto 1); 108 v_bit := '0'; 109 110 -- determine paritybits 111 for j in NUMBER_PARITY_BITS - 1 downto 0 loop 112 v_states := v_state and to_unsigned(PARITY_POLYNOMIALS(j), ENCODER_MEMORY_DEPTH + 1); 113 for k in ENCODER_MEMORY_DEPTH downto 0 loop 114 v_bit := v_bit xor v_states(k); 115 end loop; 116 v_one_transition(j) := v_bit; 117 v_bit := '0'; 118 end loop; 119 120 -- decide where to save the parity result 121 if v_transitions(to_integer(v_next_state))(1)(NUMBER_PARITY_BITS) = '0' then 122 v_transitions(to_integer(v_next_state))(1)(NUMBER_PARITY_BITS) := '1'; 123 v_transitions(to_integer(v_next_state))(1)(NUMBER_PARITY_BITS - 1 downto 0) := v_one_transition; 124 else 125 v_transitions(to_integer(v_next_state))(0)(NUMBER_PARITY_BITS - 1 downto 0) := v_one_transition; 126 end if; 127 128 -- 129 -- for input: 1 130 -- determine correct input with feedback 131 -- 132 v_next_state := to_unsigned(i,ENCODER_MEMORY_DEPTH) and to_unsigned(FEEDBACK_POLYNOMIAL, ENCODER_MEMORY_DEPTH); 133 for k in ENCODER_MEMORY_DEPTH - 1 downto 0 loop 134 v_bit := v_bit xor v_next_state(k); 135 end loop; 136 v_state(ENCODER_MEMORY_DEPTH) := '1' xor v_bit; 137 v_state(ENCODER_MEMORY_DEPTH - 1 downto 0) := to_unsigned(i,ENCODER_MEMORY_DEPTH); 138 v_next_state := v_state(ENCODER_MEMORY_DEPTH downto 1); 139 v_bit := '0'; 140 141 -- determine paritybits 142 for j in NUMBER_PARITY_BITS - 1 downto 0 loop 143 v_states := v_state and to_unsigned(PARITY_POLYNOMIALS(j), ENCODER_MEMORY_DEPTH + 1); 144 for k in ENCODER_MEMORY_DEPTH downto 0 loop 145 v_bit := v_bit xor v_states(k); 146 end loop; 147 v_one_transition(j) := v_bit; 148 v_bit := '0'; 149 end loop; 150 151 -- decide where to save parity result 152 if v_transitions(to_integer(v_next_state))(1)(NUMBER_PARITY_BITS) = '0' then 153 v_transitions(to_integer(v_next_state))(1)(NUMBER_PARITY_BITS) := '1'; 154 v_transitions(to_integer(v_next_state))(1)(NUMBER_PARITY_BITS - 1 downto 0) := v_one_transition; 155 else 156 v_transitions(to_integer(v_next_state))(0)(NUMBER_PARITY_BITS - 1 downto 0) := v_one_transition; 157 end if; 158 end loop; 159 160 -- truncate, the bit, used to decide where to save parity result 161 for i in NUMBER_TRELLIS_STATES - 1 downto 0 loop 162 v_transitions_out(i)(1) := v_transitions(i)(1)(NUMBER_PARITY_BITS - 1 downto 0); 163 v_transitions_out(i)(0) := v_transitions(i)(0)(NUMBER_PARITY_BITS - 1 downto 0); 164 end loop; 165 166 return v_transitions_out; 167 end function calc_transitions; 168 169 170 function calc_initialize return t_node_s is 171 variable v_initialize : t_node_s; 172 begin 173 v_initialize(0) := to_signed(0, BW_MAX_PROBABILITY); 174 for i in NUMBER_TRELLIS_STATES - 1 downto 1 loop 175 v_initialize(i) := to_signed(- 2 ** (BW_MAX_PROBABILITY - 2), BW_MAX_PROBABILITY); 176 end loop; 177 return v_initialize; 178 end function calc_initialize; 179 180 181 constant PREVIOUS_STATES : t_previous_states := calc_previous_states; 182 constant TRANSITIONS : t_transitions := calc_transitions; 183 constant INITIALIZE_TRELLIS : t_node_s := calc_initialize; 184 185end package body pkg_trellis; 186