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