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/] [tb/] [Codeword.sv] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 jcorley
class Codeword;
2
  // Basic descriptors
3
  string  name;
4
  string  label;
5
  int number;
6
  int debug_level; // -1=no output, 0=report error, 1=display lots of status info
7
 
8
  // Data
9
  int n;
10
  int k;
11
  int q;
12
  int word_width;
13
 
14
  // Parity function
15
  int h_defs_file;
16
  int h_defs_height;
17
  int h_defs_width;
18
  int h_defs[];
19
 
20
  // binary data
21
  int orig_data[];
22
  int coded_data[];
23
  int decoded_data[];
24
 
25
  // data after AWGN
26
  real ebn0, N0;
27
  real r[];
28
  int  r_quantized[];
29
 
30
  // Log file
31
  int    log_level; // -1=no log file, 0=add to log when function is called, 1=log each iteration
32
  int    logfile;
33
  string logfilename;
34
 
35
  // Status
36
  logic valid_codeword;
37
  real  certainty_history[];
38
 
39
 
40
 
41
  /////////////
42
  // Constructor
43
  /////////////
44
  function new( string label,
45
                int    debug_level  = 0,
46
                int    log_level    = -1,
47
                string logfilename  = "",
48
                int    number       = 0,
49
                string name         = "Codeword" );
50
 
51
    int found_target;
52
    string    oneline;
53
    string    locallabel;
54
    int       temp_i;
55
 
56
    this.label       = label;
57
    this.number      = number;
58
    this.debug_level = debug_level;
59
    this.debug_level = log_level;
60
    this.logfilename = logfilename;
61
    this.name        = name;
62
 
63
    // check for bad settings
64
    assert( debug_level>-2 ) else disp_error( "Debug level may be -1, 0 or 1" );
65
    assert( debug_level<2 )  else disp_error( "Debug level may be -1, 0 or 1" );
66
    assert( log_level>-2 )   else disp_error( "Log level may be -1, 0 or 1" );
67
    assert( log_level<2 )    else disp_error( "Log level may be -1, 0 or 1" );
68
 
69
    // log filename must be specified unless no log is requested
70
    assert( (logfilename!="") || (log_level==-1) ) else disp_error( "Specify file name" );
71
 
72
    if( debug_level>0 )
73
      note( "Creating object" );
74
 
75
    // H is a sparse matrix. The location of each one is stored as an integer.
76
    // -1 is used to represent unused memory locations.
77
    h_defs_file = $fopen( "dvbs2_hdef.txt", "r" );
78
 
79
    if( !h_defs_file )
80
      disp_error( "File dvbs2_hdef.txt not found" );
81
    h_defs_width  = 30;
82
 
83
    found_target = 0;
84
 
85
    while( !found_target )
86
    begin
87
      temp_i = $fgets( oneline, h_defs_file );
88
      temp_i = $sscanf( oneline, "label %s lines %d n %d q %d", locallabel, h_defs_height, n, q );
89
 
90
      if( label==locallabel )
91
        found_target = 1;
92
      else // discard this group
93
        for( int linenum=0; linenum
94
          temp_i = $fgets( oneline, h_defs_file );
95
 
96
      if( $feof(h_defs_file) )
97
      begin
98
        $fclose(h_defs_file);
99
        disp_error( "Didn't find requested code type!" );
100
      end
101
    end
102
 
103
    // at this point, the label has been found and the file pointer is at the correct position
104
    h_defs = new[h_defs_height*h_defs_width];
105
 
106
    // fill array with -1
107
    for( int hdef_pos=0; hdef_pos
108
      h_defs[hdef_pos] = -1;
109
 
110
    // put correct values in array
111
    for( int linenum=0; linenum
112
    begin
113
      int eol;
114
      byte c;
115
      string oneword;
116
      int word_offset;
117
 
118
      eol         = 0;
119
      oneword     = "";
120
      word_offset = 0;
121
 
122
      while( !$feof(h_defs_file) && !eol )
123
      begin
124
        c       = $fgetc( h_defs_file );
125
        eol     = (c=="\n");
126
        oneword = { oneword, c };
127
 
128
        if( eol || (c==" ") )
129
        begin
130
          temp_i = $sscanf( oneword, "%d", h_defs[linenum*h_defs_width + word_offset] );
131
 
132
          word_offset = word_offset + 1;
133
          oneword     = "";
134
        end
135
      end
136
    end
137
 
138
    $fclose(h_defs_file);
139
 
140
    k = n - 360*q;
141
 
142
    // allocate array memory
143
    orig_data    = new[k];
144
    coded_data   = new[n];
145
    decoded_data = new[n];
146
    r            = new[n];
147
    r_quantized  = new[n];
148
 
149
    // Create logfile, if necessary
150
    if( (log_level>-1) && (logfilename!="") )
151
    begin
152
      // check whether file exists
153
      logfile = $fopen( logfilename, "a" );
154
 
155
      // if file does not exist, create file
156
      if( logfile==0 )
157
        logfile = $fopen( logfilename, "w" );
158
 
159
      if( logfile==0 ) // error in file creation
160
      begin
161
        if( debug_level!=-1 )
162
          disp_error( "Could not create or append to file" );
163
        log_level = -1;  // turn off file output
164
      end
165
      else
166
      begin
167
        file_write( "New Codeword" );
168
        $fwrite( logfile, "\n" );
169
        $fclose( logfile );
170
      end
171
    end
172
  endfunction
173
 
174
 
175
 
176
  ////////////////////////////////////////////////
177
  // Screen, file output
178
  // Use these functions for a consistent output format
179
  ////////////////////////////////////////////////
180
  function void note( string note_msg );
181
    $display( "%0t\t%s\t%d\tnote\t%s", $time, name, number, note_msg );
182
  endfunction
183
 
184
  function void disp_error( string err_msg );
185
    if( log_level!=-1 )
186
      $display( "%0t\t%s\t%d\tERROR\t%s", $time, name, number, err_msg );
187
  endfunction
188
 
189
  function void file_write( string file_msg );
190
    $fwrite( logfile, "%0t\t%s\t%d\tERROR\t", $time, name, number );
191
  endfunction
192
 
193
 
194
 
195
  ////////////////////////////////////////////////////////
196
  // read_msg reads a message from a file and stores it in memory
197
  ////////////////////////////////////////////////////////
198
  function void read_msg( string inpfilename, int line_number );
199
    int inp_file;
200
    int     i; // loop variable
201
    byte    c;
202
    int     fgets_result;
203
    string  unused_line;
204
 
205
    inp_file = $fopen( inpfilename, "r" );
206
 
207
    // set to all 0's by default
208
    for( i=0; i
209
      orig_data[i] = 1;
210
 
211
 
212
    if( inp_file==0 ) // error in file creation
213
    begin
214
      if( debug_level!=-1 )
215
        disp_error( "Could not create/append to file" );
216
    end
217
    else
218
    begin
219
      // read to correct line number
220
      i = (line_number<1) ? 1 : line_number;
221
      while( !$feof( inp_file ) && (i!=1) )
222
      begin
223
        fgets_result = $fgets( unused_line, inp_file );
224
        i--;
225
      end
226
 
227
      i=0;
228
      while( !$feof( inp_file ) && (i
229
      begin
230
        c = $fgetc( inp_file );
231
        if( c!="0" )
232
          orig_data[i] = 1;
233
        i++;
234
      end
235
 
236
      $fclose( inp_file );
237
    end
238
  endfunction
239
 
240
 
241
 
242
  ///////////////////////////////////////////////
243
  // randomize message creates a random input message
244
  ///////////////////////////////////////////////
245
  function void create_random_msg( );
246
    orig_data[0] = $random(0); // does this set the seed?  I hope so.
247
 
248
    for( int i=0; i
249
      orig_data[i] = {$random()} % 2;
250
  endfunction
251
 
252
 
253
 
254
  ////////////////////
255
  // Fetch some values
256
  ////////////////////
257
  function int GetN( );
258
    GetN = n;
259
  endfunction
260
 
261
  function int GetK( );
262
    GetK = k;
263
  endfunction
264
 
265
  function int GetQ( );
266
    GetQ = q;
267
  endfunction
268
 
269
  function int GetVal( int pos );
270
    GetVal = r_quantized[pos];
271
  endfunction
272
 
273
  function void SetDecoded( int pos, int newval );
274
    //if( ((newval<0)  && (coded_data[pos]>=0)) ||
275
    //    ((newval>=0) && (coded_data[pos]<0)) )
276
    //  $display( "Setting pos %0d = %0d, orig = %0d", pos, newval, coded_data[pos] );
277
    decoded_data[pos] = newval;
278
  endfunction
279
 
280
 
281
 
282
  ////////////////////////////////////////////////////////////
283
  // encode creates the parity bits, according to the
284
  // procedure described in the standard
285
  ////////////////////////////////////////////////////////////
286
  function void encode();
287
    int h_pointer;
288
    int parity_bits[];
289
 
290
    parity_bits = new[n-k];
291
 
292
    for( int rownum=0; rownum
293
      for( int colnum=0; colnum
294
      begin
295
        int base_position;
296
 
297
        base_position = h_defs[rownum*h_defs_width + colnum];
298
 
299
        if( base_position!=-1 )
300
          for( int local_offset=0; local_offset<360; local_offset++ )
301
          begin
302
            int parity_address;
303
            parity_address = (base_position + local_offset*q) % (n-k);
304
 
305
            parity_bits[parity_address] ^= orig_data[rownum*360 + local_offset];
306
          end
307
      end
308
 
309
    for( int parityloc=1; parityloc
310
      parity_bits[parityloc] ^= parity_bits[parityloc-1];
311
 
312
    // Copy input to output
313
    for( int j=0; j
314
    begin
315
      if( j
316
        coded_data[j] = -2*orig_data[j] +1;
317
      else
318
        coded_data[j] = -2*parity_bits[j-k] +1;
319
    end
320
 
321
    parity_bits.delete();
322
  endfunction
323
 
324
 
325
 
326
  ///////////////////////
327
  // Add AWGN
328
  ///////////////////////
329
  function void genNoiseVec( output real result[64800], input real ebn0db );
330
    string filename;
331
    real rand_noise_vec[10000];
332
    int noise_file;
333
    int check_eof;
334
 
335
    int db_int;
336
    int db_tenths;
337
    int db_int_char;
338
    int db_tenths_char;
339
    if( ebn0db>=2.0 )
340
      db_int = 2;
341
    else if( ebn0db>=1.0 )
342
      db_int = 1;
343
    else
344
      db_int = 0;
345
    db_tenths = int'(10*ebn0db) %10;
346
    db_int_char    = ( int'("0") + db_int );
347
    db_tenths_char = ( int'("0") + db_tenths );
348
 
349
  $display("");
350
    filename  = { "noise_", label, "_", db_int_char, "pt", db_tenths_char };
351
  $display( "opening file %s", filename );
352
 
353
    noise_file = $fopen( filename, "r" );
354
 
355
    for( int i=0; i<10000; i++ )
356
      check_eof = $fscanf( noise_file, "%f", rand_noise_vec[i] );
357
 
358
    for( int i=0; i
359
      result[i] = rand_noise_vec[ { $random() } % 10000  ];
360
 
361
    $fclose( noise_file );
362
  endfunction
363
 
364
  function void AddNoise( real ebn0db );
365
    real noisevec[64800];
366
    real rate;
367
 
368
    rate = (1.0*k)/ (1.0*n);
369
 
370
    N0 = 10.0**(-ebn0db/10.0) / rate / 2.0;
371
    $display( "RATE, N0 = %0f, %0f", rate, N0 );
372
 
373
    genNoiseVec( noisevec, ebn0db );
374
 
375
    // print noise vector
376
    for( int j=0; j
377
      if( debug_level>1 ) $display( "noise %d = %f", j, noisevec[j] );
378
 
379
    // add noise vector
380
    for( int j=0; j
381
      r[j] = 1.0*coded_data[j] + noisevec[j];
382
 
383
    // Convert to LLR
384
    // Based on IT++: LLR=received * 4 / N0   (I don't know why)
385
    for( int i=0; i
386
      r[i] *= 4.0 / N0;
387
  endfunction
388
 
389
 
390
  ///////////////////////
391
  // Quantize LLR to a few bits
392
  ///////////////////////
393
  function void QuantizeLlr( int llr_bits );
394
    real MAXVAL;
395
    int table_range;
396
    real quant_table[2048]; // only 2*table_range is used!
397
 
398
    MAXVAL      = 12.0 / N0;
399
    table_range = 1<<(llr_bits-1);
400
 
401
    // build table
402
    for( int i=0; i<2*table_range; i++ )
403
    begin
404
      quant_table[i] = 0.5*i * MAXVAL / (1.0*table_range-1.0);
405
      //if( this.debug_level>0 ) $display( "quant table[%0d] = %0f", i, quant_table[i] );
406
    end
407
 
408
    // find correct place in table for all values
409
    for( int i=0; i
410
    begin
411
      int orig_sign;
412
      int j;
413
 
414
      orig_sign = r[i] < 0.0 ? -1 : 1;
415
      j=2*table_range-1;
416
 
417
      while( (r[i]*orig_sign) < quant_table[j] )
418
        j--;
419
 
420
      j = j>>1;
421
 
422
      r_quantized[i] = orig_sign * j;
423
    end
424
 
425
    if( debug_level>1 )
426
      for( int i=0; i<10; i++ )
427
        $display( "%0d --> %0d --> %0f --> %0d", orig_data[i], coded_data[i], r[i], r_quantized[i] );
428
 endfunction
429
 
430
 
431
 
432
  ///////////////////////
433
  // Count Errors
434
  ///////////////////////
435
  function int CountOrigErrs();
436
    CountOrigErrs = 0;
437
 
438
    for( int i=0; i
439
      if( ((r_quantized[i]<0)  && (coded_data[i]>=0)) ||
440
          ((r_quantized[i]>=0) && (coded_data[i]<0)) )
441
        CountOrigErrs++;
442
  endfunction
443
 
444
  function int CountDecodedErrs();
445
    CountDecodedErrs = 0;
446
 
447
    for( int i=0; i
448
      if( ((decoded_data[i]<0)  && (coded_data[i]>=0)) ||
449
          ((decoded_data[i]>=0) && (coded_data[i]<0)) )
450
      begin
451
        if( CountDecodedErrs<500 )
452
        $display( "mismatch %0d %0d-->%0d", i, r_quantized[i], decoded_data[i] );
453
        CountDecodedErrs++;
454
      end
455
  endfunction
456
 
457
  ///////////////////////
458
  // Display unencoded data
459
  ///////////////////////
460
  function void print_orig();
461
    string string_msg;
462
 
463
    //note( "Original data" );
464
 
465
    string_msg = "";
466
 
467
    for( int i=0; i
468
    begin
469
      if( orig_data[i] )
470
        string_msg = {string_msg, "1"};
471
      else
472
        string_msg = {string_msg, "0"};
473
    end
474
      //note( string_msg );
475
  endfunction
476
 
477
 
478
 
479
  //////////////////////
480
  // Display encoded data
481
  //////////////////////
482
  function void print_encoded();
483
    string string_msg;
484
 
485
    //note( "Encoded data" );
486
 
487
    string_msg = "";
488
 
489
    for( int i=0; i
490
    begin
491
      if( coded_data[i] )
492
        string_msg = {string_msg, "1"};
493
      else
494
        string_msg = {string_msg, "0"};
495
    end
496
 
497
    note( string_msg );
498
  endfunction
499
 
500
 
501
 
502
  //////////////////////////
503
  // Increment packet number
504
  //////////////////////////
505
  function void inc( );
506
    number++;
507
  endfunction
508
 
509
 
510
 
511
  // De-allocate memory
512
  function void delete();
513
    orig_data.delete();
514
    coded_data.delete();
515
    r.delete();
516
    r_quantized.delete();
517
    h_defs.delete();
518
  endfunction
519
endclass
520
 

powered by: WebSVN 2.1.0

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