1 |
7 |
dbrochart |
######################################################################
|
2 |
|
|
#### ####
|
3 |
|
|
#### trellis.py ####
|
4 |
|
|
#### ####
|
5 |
|
|
#### This file is part of the turbo decoder IP core project ####
|
6 |
|
|
#### http://www.opencores.org/projects/turbocodes/ ####
|
7 |
|
|
#### ####
|
8 |
|
|
#### Author(s): ####
|
9 |
|
|
#### - David Brochart(dbrochart@opencores.org) ####
|
10 |
|
|
#### ####
|
11 |
|
|
#### All additional information is available in the README.txt ####
|
12 |
|
|
#### file. ####
|
13 |
|
|
#### ####
|
14 |
|
|
######################################################################
|
15 |
|
|
#### ####
|
16 |
|
|
#### Copyright (C) 2005 Authors ####
|
17 |
|
|
#### ####
|
18 |
|
|
#### This source file may be used and distributed without ####
|
19 |
|
|
#### restriction provided that this copyright statement is not ####
|
20 |
|
|
#### removed from the file and that any derivative work contains ####
|
21 |
|
|
#### the original copyright notice and the associated disclaimer. ####
|
22 |
|
|
#### ####
|
23 |
|
|
#### This source file is free software; you can redistribute it ####
|
24 |
|
|
#### and/or modify it under the terms of the GNU Lesser General ####
|
25 |
|
|
#### Public License as published by the Free Software Foundation; ####
|
26 |
|
|
#### either version 2.1 of the License, or (at your option) any ####
|
27 |
|
|
#### later version. ####
|
28 |
|
|
#### ####
|
29 |
|
|
#### This source is distributed in the hope that it will be ####
|
30 |
|
|
#### useful, but WITHOUT ANY WARRANTY; without even the implied ####
|
31 |
|
|
#### warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ####
|
32 |
|
|
#### PURPOSE. See the GNU Lesser General Public License for more ####
|
33 |
|
|
#### details. ####
|
34 |
|
|
#### ####
|
35 |
|
|
#### You should have received a copy of the GNU Lesser General ####
|
36 |
|
|
#### Public License along with this source; if not, download it ####
|
37 |
|
|
#### from http://www.opencores.org/lgpl.shtml ####
|
38 |
|
|
#### ####
|
39 |
|
|
######################################################################
|
40 |
|
|
|
41 |
|
|
|
42 |
|
|
|
43 |
|
|
from myhdl import Signal, posedge, negedge, intbv, always
|
44 |
|
|
|
45 |
|
|
trans2state = [[0, 6, 1, 7], [2, 4, 3, 5], [5, 3, 4, 2], [7, 1, 6, 0], [1, 7, 0, 6], [3, 5, 2, 4], [4, 2, 5, 3], [6, 0, 7, 1]]
|
46 |
|
|
state2trans = [[0, 2, 1, 3], [1, 3, 0, 2], [2, 0, 3, 1], [3, 1, 2, 0], [2, 0, 3, 1], [3, 1, 2, 0], [0, 2, 1, 3], [1, 3, 0, 2]]
|
47 |
|
|
|
48 |
|
|
def trellis1(clk, rst, selState, selTrans, selStateL2, selStateL1, stateL1, selTransL2, l = 20):
|
49 |
|
|
""" First trellis.
|
50 |
|
|
|
51 |
|
|
l -- first trellis length
|
52 |
|
|
clk, rst -- in : clock and negative reset
|
53 |
|
|
selState -- in : selected state at time 0
|
54 |
|
|
selTrans -- in : 8 selected transitions (1 per state) at time 0
|
55 |
|
|
selStateL2 -- out : selected state at time (l - 2)
|
56 |
|
|
selStateL1 -- out : selected state at time (l - 1)
|
57 |
|
|
stateL1 -- out : 4 possible states at time (l - 1)
|
58 |
|
|
selTransL2 -- out : selected transition at time (l - 2)
|
59 |
|
|
|
60 |
|
|
"""
|
61 |
|
|
reg = [[Signal(intbv(0, 0, 4)) for i in range(8)] for j in range(l)]
|
62 |
|
|
free = intbv(255, 0, 256)
|
63 |
|
|
freeBeg = [bool(1) for i in range(8)]
|
64 |
|
|
pastState = [intbv(0, 0, 8) for i in range(8)]
|
65 |
|
|
pathIdReg = [Signal(intbv(i, 0, 8)) for i in range(8)]
|
66 |
|
|
pathId = [intbv(0, 0, 8) for i in range(8)]
|
67 |
|
|
freePathId = intbv(0, 0, 8)
|
68 |
|
|
current_state = intbv(0, 0, 8)
|
69 |
|
|
outState_l2 = intbv(0, 0, 8)
|
70 |
|
|
outState_l1 = intbv(0, 0, 8)
|
71 |
|
|
state_l3 = intbv(0, 0, 4)
|
72 |
|
|
state_l2 = intbv(0, 0, 4)
|
73 |
|
|
state_l1 = intbv(0, 0, 4)
|
74 |
|
|
@always(clk.posedge, rst.negedge)
|
75 |
|
|
def trellis1Logic():
|
76 |
|
|
if rst.val == 0:
|
77 |
|
|
for i in range(4):
|
78 |
|
|
stateL1[i].next = 0
|
79 |
|
|
selStateL1.next = 0
|
80 |
|
|
selStateL2.next = 0
|
81 |
|
|
selTransL2.next = 0
|
82 |
|
|
for i in range(8):
|
83 |
|
|
pathIdReg[i].next = i
|
84 |
|
|
for j in range(l):
|
85 |
|
|
reg[j][i].next = 0
|
86 |
|
|
else:
|
87 |
|
|
free = intbv(255)
|
88 |
|
|
for i in range(8):
|
89 |
|
|
pastState[i] = trans2state[i][int(selTrans[i].val)]
|
90 |
|
|
pathId[i] = pathIdReg[pastState[i]].val
|
91 |
|
|
free[int(pathId[i])] = 0
|
92 |
|
|
freeBeg = [bool(1) for i in range(8)]
|
93 |
|
|
for i in range(8):
|
94 |
|
|
current_state = intbv(i)
|
95 |
|
|
if freeBeg[int(pathId[int(current_state)])] == 1:
|
96 |
|
|
reg[0][int(pathId[int(current_state)])].next = current_state[2:0]
|
97 |
|
|
freeBeg[int(pathId[i])] = 0
|
98 |
|
|
pathIdReg[int(current_state)].next = pathId[int(current_state)]
|
99 |
|
|
for j in range(l - 1):
|
100 |
|
|
reg[j + 1][int(pathId[int(current_state)])].next = reg[j][int(pathId[int(current_state)])].val
|
101 |
|
|
else:
|
102 |
|
|
if free[0] == 1:
|
103 |
|
|
freePathId = 0
|
104 |
|
|
if free[2:0] == 2:
|
105 |
|
|
freePathId = 1
|
106 |
|
|
if free[3:0] == 4:
|
107 |
|
|
freePathId = 2
|
108 |
|
|
if free[4:0] == 8:
|
109 |
|
|
freePathId = 3
|
110 |
|
|
if free[5:0] == 16:
|
111 |
|
|
freePathId = 4
|
112 |
|
|
if free[6:0] == 32:
|
113 |
|
|
freePathId = 5
|
114 |
|
|
if free[7:0] == 64:
|
115 |
|
|
freePathId = 6
|
116 |
|
|
if free[8:0] == 128:
|
117 |
|
|
freePathId = 7
|
118 |
|
|
reg[0][freePathId].next = current_state[2:0]
|
119 |
|
|
free[freePathId] = 0
|
120 |
|
|
pathIdReg[int(current_state)].next = freePathId
|
121 |
|
|
for j in range(l - 1):
|
122 |
|
|
reg[j + 1][freePathId].next = reg[j][int(pathId[int(current_state)])].val
|
123 |
|
|
state_l3 = reg[l - 3][int(pathId[int(selState.val)])].val
|
124 |
|
|
state_l2 = reg[l - 2][int(pathId[int(selState.val)])].val
|
125 |
|
|
state_l1 = reg[l - 1][int(pathId[int(selState.val)])].val
|
126 |
|
|
outState_l2[2] = state_l3[1] ^ (state_l3[0] ^ state_l2[1])
|
127 |
|
|
outState_l2[2:0] = state_l2
|
128 |
|
|
outState_l1[2] = state_l2[1] ^ (state_l2[0] ^ state_l1[1])
|
129 |
|
|
outState_l1[2:0] = state_l1
|
130 |
|
|
selStateL1.next = outState_l1
|
131 |
|
|
selStateL2.next = outState_l2
|
132 |
|
|
selTransL2.next = state2trans[int(outState_l2)][int(state_l1)]
|
133 |
|
|
for i in range(4):
|
134 |
|
|
stateL1[i].next = trans2state[int(outState_l2)][i]
|
135 |
|
|
if __debug__:
|
136 |
|
|
# Monitor: checks that in the first trellis, from each of the 8 states (trellis' beginning) we arrive at the same state (trellis' end).
|
137 |
|
|
# (Ignore this message until every iteration is fully started)
|
138 |
|
|
diff = 0
|
139 |
|
|
ref = intbv(0)
|
140 |
|
|
tmp = intbv(0)
|
141 |
|
|
state_l2_deb = reg[l - 2][int(pathId[7])].val
|
142 |
|
|
state_l1_deb = reg[l - 1][int(pathId[7])].val
|
143 |
|
|
ref[2] = state_l2_deb[1] ^ (state_l2_deb[0] ^ state_l1_deb[1])
|
144 |
|
|
ref[2:0] = state_l1_deb
|
145 |
|
|
for i in range(7):
|
146 |
|
|
state_l2_deb = reg[l - 2][int(pathId[i])].val
|
147 |
|
|
state_l1_deb = reg[l - 1][int(pathId[i])].val
|
148 |
|
|
tmp[2] = state_l2_deb[1] ^ (state_l2_deb[0] ^ state_l1_deb[1])
|
149 |
|
|
tmp[2:0] = state_l1_deb
|
150 |
|
|
if ref != tmp:
|
151 |
|
|
diff = 1
|
152 |
|
|
if diff == 1:
|
153 |
|
|
print "WARNING: all paths don't arrive at same state at end of first trellis (you should think about increasing its length)"
|
154 |
|
|
return trellis1Logic
|
155 |
|
|
|
156 |
|
|
def trellis2(clk, rst, selState, state, selTrans, weight, llr0, llr1, llr2, llr3, a, b, m = 10, q = 8):
|
157 |
|
|
""" Second trellis and revision logic.
|
158 |
|
|
|
159 |
|
|
m -- second trellis length
|
160 |
|
|
q -- accumulated distance width
|
161 |
|
|
clk, rst -- in : clock and negative reset
|
162 |
|
|
selState -- in : selected state at time (l - 1)
|
163 |
|
|
state -- in : 4 possible states at time (l - 1)
|
164 |
|
|
selTrans -- in : 8 selected transitions (1 per state) at time (l - 1)
|
165 |
|
|
weight -- in : four weights sorted by transition code at time (l - 1)
|
166 |
|
|
llr0 -- out : LLR for (a, b) = (0, 0) at time (l + m - 1)
|
167 |
|
|
llr1 -- out : LLR for (a, b) = (0, 1) at time (l + m - 1)
|
168 |
|
|
llr2 -- out : LLR for (a, b) = (1, 0) at time (l + m - 1)
|
169 |
|
|
llr3 -- out : LLR for (a, b) = (1, 1) at time (l + m - 1)
|
170 |
|
|
a, b -- out : decoded values of (a, b) at time (l + m - 1)
|
171 |
|
|
|
172 |
|
|
"""
|
173 |
|
|
reg = [[Signal(intbv(0, 0, 4)) for i in range(8)] for j in range(m)]
|
174 |
|
|
free = intbv(255, 0, 256)
|
175 |
|
|
freeBeg = [bool(1) for i in range(8)]
|
176 |
|
|
pastState = [intbv(0, 0, 8) for i in range(8)]
|
177 |
|
|
pathIdReg = [Signal(intbv(i, 0, 8)) for i in range(8)]
|
178 |
|
|
pathId = [intbv(0, 0, 8) for i in range(8)]
|
179 |
|
|
freePathId = intbv(0, 0, 8)
|
180 |
|
|
revWeight = [[Signal(intbv(0, 0, 2**q)) for i in range(m)] for j in range(4)]
|
181 |
|
|
revWeightTmp = [[intbv(0, 0, 2**q) for i in range(m)] for j in range(4)]
|
182 |
|
|
revWeightFilt = [intbv(0, 0, 2**q) for j in range(3)]
|
183 |
|
|
op = [intbv(0, 0, 2**q) for i in range(4)]
|
184 |
|
|
tmp = [intbv(0, 0, 2**q) for i in range(4)]
|
185 |
|
|
tmp4 = intbv(0, 0, 2**(q+1))
|
186 |
|
|
notZero = [[intbv(0, 0, 4) for i in range(3)] for j in range(2)]
|
187 |
|
|
ind = [[intbv(0, 0, 4) for i in range(3)] for j in range(2)]
|
188 |
|
|
minTmp = [bool(0) for i in range(3)]
|
189 |
|
|
@always(clk.posedge, rst.negedge)
|
190 |
|
|
def trellis2Logic():
|
191 |
|
|
if rst.val == 0:
|
192 |
|
|
for i in range(4):
|
193 |
|
|
for j in range(m):
|
194 |
|
|
revWeight[i][j].next = 0
|
195 |
|
|
a.next = 0
|
196 |
|
|
b.next = 0
|
197 |
|
|
llr0.next = 0
|
198 |
|
|
llr1.next = 0
|
199 |
|
|
llr2.next = 0
|
200 |
|
|
llr3.next = 0
|
201 |
|
|
for i in range(8):
|
202 |
|
|
pathIdReg[i].next = i
|
203 |
|
|
for j in range(m):
|
204 |
|
|
reg[j][i].next = 0
|
205 |
|
|
else:
|
206 |
|
|
free = intbv(255)
|
207 |
|
|
for i in range(8):
|
208 |
|
|
pastState[i] = trans2state[i][int(selTrans[i].val)]
|
209 |
|
|
pathId[i] = pathIdReg[pastState[i]].val
|
210 |
|
|
free[int(pathId[i])] = 0
|
211 |
|
|
freeBeg = [bool(1) for i in range(8)]
|
212 |
|
|
for i in range(8):
|
213 |
|
|
if freeBeg[int(pathId[i])] == 1:
|
214 |
|
|
reg[0][int(pathId[i])].next = selTrans[i].val
|
215 |
|
|
freeBeg[int(pathId[i])] = 0
|
216 |
|
|
pathIdReg[i].next = pathId[i]
|
217 |
|
|
for j in range(m - 1):
|
218 |
|
|
reg[j + 1][int(pathId[i])].next = reg[j][int(pathId[i])].val
|
219 |
|
|
else:
|
220 |
|
|
if free[1:0] == 1:
|
221 |
|
|
freePathId = 0
|
222 |
|
|
if free[2:0] == 2:
|
223 |
|
|
freePathId = 1
|
224 |
|
|
if free[3:0] == 4:
|
225 |
|
|
freePathId = 2
|
226 |
|
|
if free[4:0] == 8:
|
227 |
|
|
freePathId = 3
|
228 |
|
|
if free[5:0] == 16:
|
229 |
|
|
freePathId = 4
|
230 |
|
|
if free[6:0] == 32:
|
231 |
|
|
freePathId = 5
|
232 |
|
|
if free[7:0] == 64:
|
233 |
|
|
freePathId = 6
|
234 |
|
|
if free[8:0] == 128:
|
235 |
|
|
freePathId = 7
|
236 |
|
|
reg[0][freePathId].next = selTrans[i].val
|
237 |
|
|
free[freePathId] = 0
|
238 |
|
|
pathIdReg[i].next = freePathId
|
239 |
|
|
for j in range(m - 1):
|
240 |
|
|
reg[j + 1][freePathId].next = reg[j][int(pathId[i])].val
|
241 |
|
|
a.next = reg[m - 1][int(pathId[int(selState.val)])].val[1]
|
242 |
|
|
b.next = reg[m - 1][int(pathId[int(selState.val)])].val[0]
|
243 |
|
|
for i in range(4):
|
244 |
|
|
for j in range(m - 1):
|
245 |
|
|
for k in range(4):
|
246 |
|
|
if reg[j][int(pathId[int(state[k].val)])].val == i and state[k].val != selState.val:
|
247 |
|
|
op[k] = weight[k].val
|
248 |
|
|
else:
|
249 |
|
|
op[k] = (2 ** q) - 1
|
250 |
|
|
if op[0] < op[1]:
|
251 |
|
|
tmp[0] = op[0]
|
252 |
|
|
else:
|
253 |
|
|
tmp[0] = op[1]
|
254 |
|
|
if op[2] < op[3]:
|
255 |
|
|
tmp[1] = op[2]
|
256 |
|
|
else:
|
257 |
|
|
tmp[1] = op[3]
|
258 |
|
|
if tmp[0] < tmp[1]:
|
259 |
|
|
tmp[2] = tmp[0]
|
260 |
|
|
else:
|
261 |
|
|
tmp[2] = tmp[1]
|
262 |
|
|
if tmp[2] < revWeight[i][j].val:
|
263 |
|
|
revWeightTmp[i][j + 1] = tmp[2]
|
264 |
|
|
else:
|
265 |
|
|
revWeightTmp[i][j + 1] = revWeight[i][j].val
|
266 |
|
|
revWeightTmp[i][0] = weight[i].val
|
267 |
|
|
for j in range(2):
|
268 |
|
|
if revWeightTmp[0][j] == 0:
|
269 |
|
|
notZero[j] = [1, 2, 3]
|
270 |
|
|
elif revWeightTmp[1][j] == 0:
|
271 |
|
|
notZero[j] = [0, 2, 3]
|
272 |
|
|
elif revWeightTmp[2][j] == 0:
|
273 |
|
|
notZero[j] = [0, 1, 3]
|
274 |
|
|
elif revWeightTmp[3][j] == 0:
|
275 |
|
|
notZero[j] = [0, 1, 2]
|
276 |
|
|
if revWeightTmp[int(notZero[j][0])][j] <= revWeightTmp[int(notZero[j][1])][j]:
|
277 |
|
|
minTmp[0] = 0
|
278 |
|
|
else:
|
279 |
|
|
minTmp[0] = 1
|
280 |
|
|
if revWeightTmp[int(notZero[j][0])][j] <= revWeightTmp[int(notZero[j][2])][j]:
|
281 |
|
|
minTmp[1] = 0
|
282 |
|
|
else:
|
283 |
|
|
minTmp[1] = 1
|
284 |
|
|
if revWeightTmp[int(notZero[j][1])][j] <= revWeightTmp[int(notZero[j][2])][j]:
|
285 |
|
|
minTmp[2] = 0
|
286 |
|
|
else:
|
287 |
|
|
minTmp[2] = 1
|
288 |
|
|
if minTmp == [0, 0, 0]:
|
289 |
|
|
ind[j] = [0, 1, 2]
|
290 |
|
|
elif minTmp == [0, 0, 1]:
|
291 |
|
|
ind[j] = [0, 2, 1]
|
292 |
|
|
elif minTmp == [1, 0, 0]:
|
293 |
|
|
ind[j] = [1, 0, 2]
|
294 |
|
|
elif minTmp == [0, 1, 1]:
|
295 |
|
|
ind[j] = [1, 2, 0]
|
296 |
|
|
elif minTmp == [1, 1, 0]:
|
297 |
|
|
ind[j] = [2, 0, 1]
|
298 |
|
|
elif minTmp == [1, 1, 1]:
|
299 |
|
|
ind[j] = [2, 1, 0]
|
300 |
|
|
else:
|
301 |
|
|
print "ERROR: Configuration does not exist", minTmp
|
302 |
|
|
for i in range(3):
|
303 |
|
|
tmp[3] = revWeightTmp[int(notZero[0][int(ind[0][i])])][0]
|
304 |
|
|
tmp4 = revWeightTmp[int(notZero[1][int(ind[1][i])])][1] + (2 ** (q - 4))
|
305 |
|
|
if tmp[3] < tmp4:
|
306 |
|
|
revWeightFilt[int(ind[0][i])] = tmp[3]
|
307 |
|
|
else:
|
308 |
|
|
revWeightFilt[int(ind[0][i])] = intbv(tmp4)[q:0]
|
309 |
|
|
for i in range(3):
|
310 |
|
|
revWeightTmp[int(notZero[0][i])][0] = revWeightFilt[i]
|
311 |
|
|
for i in range(4):
|
312 |
|
|
for j in range(m):
|
313 |
|
|
revWeight[i][j].next = revWeightTmp[i][j]
|
314 |
|
|
llr0.next = revWeight[0][m - 1]
|
315 |
|
|
llr1.next = revWeight[1][m - 1]
|
316 |
|
|
llr2.next = revWeight[2][m - 1]
|
317 |
|
|
llr3.next = revWeight[3][m - 1]
|
318 |
|
|
return trellis2Logic
|