OpenCores
URL https://opencores.org/ocsvn/dvb_s2_ldpc_decoder/dvb_s2_ldpc_decoder/trunk

Subversion Repositories dvb_s2_ldpc_decoder

[/] [dvb_s2_ldpc_decoder/] [trunk/] [rtl/] [ldpc_vn.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 jcorley
//-------------------------------------------------------------------------
2
//
3
// File name    :  ldpc_vn.v
4
// Title        :
5
//              :
6
// Purpose      : Variable node holder/message calculator.  Loads llr
7
//              : data serially, and controls RAM's.  This module is
8
//              : written to be as compact as possible, since it is
9
//              : instantiated a large number of times.  Some outputs,
10
//              : especially RAM controls, are not registered.
11
//
12
// ----------------------------------------------------------------------
13
// Revision History :
14
// ----------------------------------------------------------------------
15
//   Ver  :| Author   :| Mod. Date   :| Changes Made:
16
//   v1.0  | JTC      :| 2008/07/02  :|
17
// ----------------------------------------------------------------------
18
`timescale 1ns/10ps
19
 
20
module ldpc_vn #(
21
  parameter FOLDFACTOR     = 1,
22
  parameter LLRWIDTH       = 6
23
)(
24
  input clk,
25
  input rst,
26
 
27
  // LLR I/O
28
  input                   llr_access,
29
  input[7+FOLDFACTOR-1:0] llr_addr,
30
  input                   llr_din_we,
31
  input[LLRWIDTH-1:0]     llr_din,
32
  output[LLRWIDTH-1:0]    llr_dout,
33
 
34
  // message control
35
  input                   iteration,
36
  input                   first_half,
37
  input                   first_iteration,  // ignore upmsgs
38
  input                   we_vnmsg,
39
  input                   disable_vn,
40
  input[7+FOLDFACTOR-1:0] addr_vn,
41
 
42
  // message I/O
43
  input[LLRWIDTH-1:0]  sh_msg,
44
  output[LLRWIDTH-1:0] vn_msg,
45
 
46
  // Attached RAM, holds iteration number, original LLR and message sum
47
  output[7+FOLDFACTOR-1:0] vnram_wraddr,
48
  output[7+FOLDFACTOR-1:0] vnram_rdaddr,
49
  output                   upmsg_we,
50
  output[2*LLRWIDTH+4:0]   upmsg_din,
51
  input[2*LLRWIDTH+4:0]    upmsg_dout
52
);
53
 
54
// Split RAM outputs
55
wire[LLRWIDTH-1:0] llr_orig;
56
wire[LLRWIDTH+3:0] stored_msg_sum;
57
wire               stored_iteration;
58
 
59
assign llr_orig         = upmsg_dout[LLRWIDTH-1:0];
60
assign stored_msg_sum   = upmsg_dout[2*LLRWIDTH+3:LLRWIDTH];
61
assign stored_iteration = upmsg_dout[2*LLRWIDTH+4];
62
 
63
/************************************************************
64
 * Add 1's complement numbers, assume overflow not possible *
65
 ************************************************************/
66
function[LLRWIDTH+3:0] AddNewMsg( input[LLRWIDTH+3:0] a,
67
                                  input[LLRWIDTH-1:0] b );
68
  reg               signa;
69
  reg               signb;
70
  reg[LLRWIDTH+2:0] maga;
71
  reg[LLRWIDTH+2:0] magb;
72
 
73
  reg[LLRWIDTH+2:0] sum;
74
  reg[LLRWIDTH+2:0] diffa;
75
  reg[LLRWIDTH+2:0] diffb;
76
 
77
  reg               add;
78
  reg               b_big;
79
  reg               sign;
80
  reg[LLRWIDTH+3:0] result;
81
 
82
begin
83
  // strip out magnitude and sign bits
84
  signa = a[LLRWIDTH+3];
85
  signb = b[LLRWIDTH-1];
86
  maga  = a[LLRWIDTH+2:0];
87
  magb  = { 4'b0000, b[LLRWIDTH-2:0] };
88
 
89
  // basic calculations
90
  sum   = maga + magb;
91
  diffa = maga - magb;
92
  diffb = magb - maga;
93
 
94
  // control bits
95
  add   = signa==signb;
96
  b_big = maga<magb;
97
  sign  = b_big ? signb : signa;
98
 
99
  if( add )
100
    result = { sign, sum };
101
  else if( b_big )
102
    result = { sign, diffb };
103
  else
104
    result = { sign, diffa };
105
 
106
  AddNewMsg = result;
107
end
108
endfunction
109
 
110
/*************************************************
111
 * Saturate message to fewer bits before passing *
112
 *************************************************/
113
function[LLRWIDTH-1:0] SaturateMsg( input[LLRWIDTH+3:0] a );
114
begin
115
  if( a[LLRWIDTH+2:LLRWIDTH-1] != 4'b0000 )
116
    SaturateMsg[LLRWIDTH-2:0] = { (LLRWIDTH-1){1'b1} };
117
  else
118
    SaturateMsg[LLRWIDTH-2:0] = a[LLRWIDTH-2:0];
119
 
120
  SaturateMsg[LLRWIDTH-1] = a[LLRWIDTH+3];
121
end
122
endfunction
123
 
124
/********************************************
125
 * Delays to align controls with RAM output *
126
 ********************************************/
127
localparam RAM_LATENCY = 2;
128
 
129
integer loopvar1;
130
 
131
reg[7+FOLDFACTOR-1:0] vnram_rdaddr_int;
132
 
133
reg[LLRWIDTH-1:0]     sh_msg_del[0:RAM_LATENCY-1];
134
reg                   we_vnmsg_del[0:RAM_LATENCY-1];
135
reg[7+FOLDFACTOR-1:0] vnram_rdaddr_del[0:RAM_LATENCY-1];
136
reg                   disable_del[0:RAM_LATENCY-1];
137
 
138
wire[LLRWIDTH-1:0]     sh_msg_aligned_ram;
139
wire                   we_vnmsg_aligned_ram;
140
wire[7+FOLDFACTOR-1:0] vnram_rdaddr_aligned_ram;
141
wire                   disable_aligned_ram;
142
 
143
reg recycle_result;
144
 
145
// mux in alternative address for final read-out
146
assign vnram_rdaddr = vnram_rdaddr_int;
147
always @( * ) vnram_rdaddr_int <= #1 llr_access ? llr_addr : addr_vn;
148
 
149
assign sh_msg_aligned_ram       = sh_msg_del[RAM_LATENCY-1];
150
assign we_vnmsg_aligned_ram     = we_vnmsg_del[RAM_LATENCY-1];
151
assign vnram_rdaddr_aligned_ram = vnram_rdaddr_del[RAM_LATENCY-1];
152
assign disable_aligned_ram      = disable_del[RAM_LATENCY-1];
153
 
154
always @( posedge rst, posedge clk )
155
  if( rst )
156
  begin
157
    for( loopvar1=0; loopvar1<RAM_LATENCY; loopvar1=loopvar1+1 )
158
    begin
159
      sh_msg_del[loopvar1]       <= 0;
160
      we_vnmsg_del[loopvar1]     <= 0;
161
      vnram_rdaddr_del[loopvar1] <= 0;
162
      disable_del[loopvar1]      <= 0;
163
    end
164
    recycle_result <= 0;
165
  end
166
  else
167
  begin
168
    sh_msg_del[0]        <= sh_msg;
169
    we_vnmsg_del[0]      <= we_vnmsg;
170
    vnram_rdaddr_del[0]  <= vnram_rdaddr_int;
171
    disable_del[0]       <= disable_vn;
172
 
173
    for( loopvar1=1; loopvar1<RAM_LATENCY; loopvar1=loopvar1+1 )
174
    begin
175
      sh_msg_del[loopvar1]       <= sh_msg_del[loopvar1 -1];
176
      we_vnmsg_del[loopvar1]     <= we_vnmsg_del[loopvar1 -1];
177
      vnram_rdaddr_del[loopvar1] <= vnram_rdaddr_del[loopvar1 -1];
178
      disable_del[loopvar1]      <= disable_del[loopvar1 -1];
179
    end
180
 
181
    // Use previous result rather than the RAM contents for two adjacent
182
    // writes to the same address
183
    recycle_result <= (vnram_rdaddr_aligned_ram==vnram_rdaddr_del[RAM_LATENCY-2]) &
184
                      we_vnmsg_aligned_ram & we_vnmsg_del[RAM_LATENCY-2];
185
  end
186
 
187
/************************
188
 * Message calculations *
189
 ************************/
190
// Add initial LLR to message offset (except for first iteration)
191
reg[LLRWIDTH+3:0]  msg0_norst;
192
wire[LLRWIDTH+3:0] msg0;
193
reg[LLRWIDTH-1:0]  msg1;
194
 
195
wire start_new_upmsg;
196
reg  rst_msg0;
197
 
198
wire[LLRWIDTH+3:0] msg_sum;
199
 
200
reg[LLRWIDTH+3:0] msg_sum_reg;
201
 
202
// Add upmsg to the result, except:
203
// - during first iteration, since no upmsg exists
204
// - first message of each new iteration, where upmsg needs to be reset
205
assign start_new_upmsg = (stored_iteration!=iteration) & we_vnmsg_aligned_ram;
206
 
207
assign msg0 = rst_msg0 ? 0 : msg0_norst;
208
 
209
always @( posedge clk, posedge rst )
210
  if( rst )
211
  begin
212
    msg0_norst  <= 0;
213
    rst_msg0    <= 0;
214
    msg1        <= 0;
215
    msg_sum_reg <= 0;
216
  end
217
  else
218
  begin
219
    // msg0 = sum of received upstream messages
220
    // clear msg0 when beginning a new set of upstream messages
221
    msg0_norst <= recycle_result ? msg_sum : stored_msg_sum;
222
    rst_msg0   <= start_new_upmsg & ~recycle_result;
223
 
224
    msg1 <= (llr_access || first_half) ? llr_orig : sh_msg_aligned_ram;
225
 
226
    msg_sum_reg <= msg_sum;
227
  end
228
 
229
// When creating downstream messages, or preparing final result:
230
//      msg_sum = llr + sum of messages
231
// When receiving upstream messages:
232
//      msg_sum = new message + sum of messages
233
assign msg_sum = AddNewMsg( msg0, msg1 );
234
 
235
/****************************************
236
 * Delay controls to align with msg_sum *
237
 ****************************************/
238
localparam CALC_LATENCY = 2;
239
 
240
integer loopvar2;
241
 
242
reg                   we_vnmsg_del2[0:RAM_LATENCY-1];
243
reg[7+FOLDFACTOR-1:0] vnram_rdaddr_del2[0:RAM_LATENCY-1];
244
reg[LLRWIDTH-1:0]     llrram_dout_del2[0:RAM_LATENCY-1];
245
reg                   disable_del2[0:RAM_LATENCY-1];
246
 
247
wire                   we_vnmsg_aligned_msg;
248
wire[7+FOLDFACTOR-1:0] vnram_rdaddr_aligned_msg;
249
wire[LLRWIDTH-1:0]     llrram_dout_aligned_msg;
250
wire                   disable_aligned_msg;
251
 
252
assign we_vnmsg_aligned_msg     = we_vnmsg_del2[RAM_LATENCY-1];
253
assign vnram_rdaddr_aligned_msg = vnram_rdaddr_del2[RAM_LATENCY-1];
254
assign llrram_dout_aligned_msg  = llrram_dout_del2[RAM_LATENCY-1];
255
assign disable_aligned_msg      = disable_del2[RAM_LATENCY-1];
256
 
257
always @( posedge rst, posedge clk )
258
  if( rst )
259
  begin
260
    for( loopvar2=0; loopvar2<RAM_LATENCY; loopvar2=loopvar2+1 )
261
    begin
262
      we_vnmsg_del2[loopvar2]     <= 0;
263
      vnram_rdaddr_del2[loopvar2] <= 0;
264
      llrram_dout_del2[loopvar2]  <= 0;
265
      disable_del2[loopvar2]      <= 0;
266
    end
267
  end
268
  else
269
  begin
270
    we_vnmsg_del2[0]      <= we_vnmsg_aligned_ram;
271
    vnram_rdaddr_del2[0]  <= vnram_rdaddr_aligned_ram;
272
    llrram_dout_del2[0]   <= llr_orig;
273
    disable_del2[0]       <= disable_aligned_ram;
274
 
275
    for( loopvar2=1; loopvar2<RAM_LATENCY; loopvar2=loopvar2+1 )
276
    begin
277
      we_vnmsg_del2[loopvar2]     <= we_vnmsg_del2[loopvar2 -1];
278
      vnram_rdaddr_del2[loopvar2] <= vnram_rdaddr_del2[loopvar2 -1];
279
      llrram_dout_del2[loopvar2]  <= llrram_dout_del2[loopvar2 -1];
280
      disable_del2[loopvar2]      <= disable_del2[loopvar2 -1];
281
    end
282
  end
283
 
284
/*******************************
285
 * Write message totals to RAM *
286
 *******************************/
287
reg[7+FOLDFACTOR-1:0] vnram_wraddr_int;
288
reg[LLRWIDTH-1:0]     new_llr;
289
reg                   new_iteration;
290
reg[LLRWIDTH+3:0]     new_msg_sum;
291
reg                   upmsg_we_int;
292
 
293
assign vnram_wraddr = vnram_wraddr_int;
294
assign upmsg_din    = { new_iteration, new_msg_sum, new_llr };
295
assign upmsg_we     = upmsg_we_int;
296
 
297
always @( posedge rst, posedge clk )
298
  if( rst )
299
  begin
300
    vnram_wraddr_int <= 0;
301
    new_llr          <= 0;
302
    new_msg_sum      <= 0;
303
    new_iteration    <= 0;
304
    upmsg_we_int     <= 1;
305
  end
306
  else
307
  begin
308
    // mux and register outputs
309
    vnram_wraddr_int <= #1 llr_access ? llr_addr : vnram_rdaddr_aligned_msg;
310
    new_llr          <= #1 llr_access ? llr_din  : llrram_dout_aligned_msg;
311
    new_msg_sum      <= #1 llr_access ? 0        : msg_sum_reg;
312
 
313
    new_iteration    <= #1 llr_access | iteration;
314
 
315
    upmsg_we_int     <= #1 ~(llr_din_we | (we_vnmsg_aligned_msg & ~disable_aligned_msg));
316
  end
317
 
318
/*****************************************************************
319
 * Saturate message to fewer bits for message passing and output *
320
 *****************************************************************/
321
reg[LLRWIDTH-1:0] vn_msg_int;
322
 
323
assign llr_dout = vn_msg_int;
324
assign vn_msg   = vn_msg_int;
325
 
326
always @( posedge rst, posedge clk )
327
  if( rst )
328
    vn_msg_int <= 0;
329
  else
330
    vn_msg_int <= SaturateMsg(msg_sum_reg);
331
 
332
endmodule
333
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.