1 |
2 |
mfehrenz |
--!
|
2 |
|
|
--! Copyright (C) 2011 - 2012 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 |
|
|
|
14 |
|
|
library ieee;
|
15 |
|
|
use ieee.std_logic_1164.all;
|
16 |
|
|
use ieee.numeric_std.all;
|
17 |
|
|
|
18 |
|
|
library dec_viterbi;
|
19 |
|
|
use dec_viterbi.pkg_param.all;
|
20 |
|
|
use dec_viterbi.pkg_param_derived.all;
|
21 |
|
|
use dec_viterbi.pkg_types.all;
|
22 |
|
|
|
23 |
|
|
|
24 |
|
|
package 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 := calc_previous_states;
|
57 |
|
|
constant TRANSITIONS : t_transitions := calc_transitions;
|
58 |
|
|
constant INITIALIZE_TRELLIS : t_node_s := calc_initialize;
|
59 |
|
|
|
60 |
|
|
end package pkg_trellis;
|
61 |
|
|
|
62 |
|
|
|
63 |
|
|
package 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 |
|
|
end package body pkg_trellis;
|