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/] [tb_ldpc.v] - Rev 2

Compare with Previous | Blame | View Log

`include "Codeword.sv"
`timescale 1ns/10ps
 
module tb_ldpc();
 
localparam CLK_PERIOD = 5ns;
localparam HOLD       = 1ns;
 
localparam SYMS_PER_EBN0 = 10;
localparam EBN0_MIN      = 3.8;
localparam EBN0_MAX      = 4.0;
localparam EBN0_STEP     = 0.2;
localparam CODE_TYPE     = "1_2";
 
localparam LLRWIDTH = 6;
 
//////////
// Clocks
//////////
logic clk;
logic rst;
 
initial
begin
  clk <= 1'b0;
  forever
    #(CLK_PERIOD /2) clk <= ~clk;
end
 
initial
begin
  rst <= 1'b1;
 
  repeat(3) @(posedge clk);
  rst <= #HOLD 1'b0;
end
 
/////////////
// Generator
/////////////
int    packet_number;
int    debug_level;
int    log_level;
string logfilename;
string name;
 
/* VCS doesn't support parameterized mailboxes, just use one Codeword
   throughout the testbench and one big initial block instead.
Codeword datapath_orig;
Codeword checkpath_orig;
 
mailbox #(Codeword) data_source;
mailbox #(Codeword) check_source;
semaphore check;
*/
Codeword  check_word;
 
//////////////
// Transactors
//////////////
// Load data into LLR
// LLR I/O
logic      llr_access;
logic[7:0] llr_addr;
logic      llr_din_we;
logic[360*LLRWIDTH-1:0]      llr_din;
bit signed[360*LLRWIDTH-1:0] llr_dout;
 
// start command; completion indicator
logic      start;
logic[4:0] mode;
logic[5:0] iter_limit;
bit        done;
 
localparam READ_LATENCY = 5;
 
initial
begin
  packet_number = 0;
  debug_level   = 0;
  log_level     = 1;
  logfilename   = "test_testbench.txt";
  name          = "CodewordSpecial";
 
  check_word = new( CODE_TYPE, debug_level, log_level, logfilename, packet_number, name );
 
  llr_access  <= 0;
  llr_addr    <= 0;
  llr_din_we  <= 0;
  llr_din     <= 0;
  start       <= 0;
  mode        <= 0;
  iter_limit  <= 20;
 
  @( posedge rst );
  repeat( 5 ) @( posedge clk );
 
  for( real ebn0dB=EBN0_MIN; ebn0dB<EBN0_MAX; ebn0dB+=EBN0_STEP )
    for( int symnum=0; symnum<SYMS_PER_EBN0; symnum++ )
    begin
      // create word
      check_word.create_random_msg();
      check_word.encode();
 
      check_word.AddNoise( ebn0dB );
      check_word.QuantizeLlr( LLRWIDTH );
 
      // begin testing DUT
      @(posedge clk);
 
      // write normal data bits
      for( int i=0; i<check_word.GetK()/360; i++ )
      begin
        int wr_val;
        int abs_wr_val;
 
        llr_addr   <= i;
        llr_access <= 1;
 
        for( int j=0; j<360; j++ )
        begin
          wr_val = check_word.GetVal(360*i +j);
          //wr_val = 360*i +j;
          abs_wr_val = wr_val < 0 ? -1*wr_val : wr_val;
 
          llr_din[(j+1)*LLRWIDTH-1 -: LLRWIDTH]
            <= (wr_val<0) ? { 1'b1, abs_wr_val[LLRWIDTH-2:0] }
                          : { 1'b0, abs_wr_val[LLRWIDTH-2:0] };
        end
 
        llr_din_we <= 1;
        @( posedge clk );
      end
 
      // write parity bits
      for( int i=0; i<(check_word.GetN()-check_word.GetK())/360; i++ )
      begin
        int rotate_pos;
        int wr_val;
        int abs_wr_val;
 
        llr_addr <= check_word.GetK()/360 + i;
 
        for( int j=0; j<360; j++ )
        begin
          rotate_pos = check_word.GetK() + i + j*check_word.GetQ();
          wr_val     = check_word.GetVal(rotate_pos);
          //wr_val     = rotate_pos;
          abs_wr_val = wr_val < 0 ? -1*wr_val : wr_val;
 
          llr_din[j*LLRWIDTH+LLRWIDTH-1 -: LLRWIDTH]
            <= (wr_val<0) ? { 1'b1, abs_wr_val[LLRWIDTH-2:0] }
                          : { 1'b0, abs_wr_val[LLRWIDTH-2:0] };
        end
 
        llr_din_we <= 1;
        @( posedge clk );
      end
 
      llr_din_we <= 0;
      llr_access <= 0;
      @( posedge clk );
 
      //controls
      start <= 1;
 
      case( CODE_TYPE )
        "1_4":    mode <= 0;
        "1_3":    mode <= 1;
        "2_5":    mode <= 2;
        "1_2":    mode <= 3;
        "3_5":    mode <= 4;
        "2_3":    mode <= 5;
        "3_4":    mode <= 6;
        "4_5":    mode <= 7;
        "5_6":    mode <= 8;
        "8_9":    mode <= 9;
        "9_10":   mode <= 10;
        "1_5s":   mode <= 11;
        "1_3s":   mode <= 12;
        "2_5s":   mode <= 13;
        "4_9s":   mode <= 14;
        "3_5s":   mode <= 15;
        "2_3s":   mode <= 16;
        "11_15s": mode <= 17;
        "7_9s":   mode <= 18;
        "37_45s": mode <= 19;
        "8_9s":   mode <= 20;
        default: $stop( "Illegal code type!" );
      endcase
      @( posedge clk );
      start <= 0;
      @( posedge clk );
 
      // read data out
      @(posedge done);
      @(posedge clk);
 
      llr_access <= 1;
      llr_addr   <= 0;
      @(posedge clk);
 
      // read normal data bits
      for( int i=0; i<(check_word.GetK()/360)+READ_LATENCY; i++ )
      begin
        int result;
 
        llr_addr <= i;
        llr_din  <= { LLRWIDTH{1'bX} };
        @( posedge clk );
 
        if( i>=READ_LATENCY )
          for( int j=0; j<360; j++ )
          begin
            result = llr_dout[j*LLRWIDTH+LLRWIDTH-1]
              ? -1 * { 1'b0, llr_dout[j*LLRWIDTH+LLRWIDTH-2 -: LLRWIDTH-1] }
              : { 1'b0, llr_dout[j*LLRWIDTH+LLRWIDTH-2 -: LLRWIDTH-1] };
 
            check_word.SetDecoded( 360*(i-READ_LATENCY) +j, result );
          end
      end
 
      // read parity bits
      for( int i=0; i<((check_word.GetN()-check_word.GetK())/360)+READ_LATENCY; i++ )
      begin
        int result;
        int rotate_pos;
 
        llr_addr <= check_word.GetK()/360 + i;
        @(posedge clk);
 
        if( i>=READ_LATENCY )
          for( int j=0; j<360; j++ )
          begin
            rotate_pos = check_word.GetK() + i-READ_LATENCY + j*check_word.GetQ();
 
            result = llr_dout[j*LLRWIDTH+LLRWIDTH-1]
              ? -1 * { 1'b0, llr_dout[j*LLRWIDTH+LLRWIDTH-2 -: LLRWIDTH-1] }
              : { 1'b0, llr_dout[j*LLRWIDTH+LLRWIDTH-2 -: LLRWIDTH-1] };
 
            check_word.SetDecoded( rotate_pos, result );
          end
      end
 
      llr_access <= 0;
      @( posedge clk );
 
      $display( "EbN0 = %0fdB", ebn0dB );
      $display( "Orig had    %0d errors", check_word.CountOrigErrs() );
      $display( "Decoded had %0d errors", check_word.CountDecodedErrs() );
 
      check_word.inc(); // increment packet number
    end
 
  check_word.delete();
  $stop();
end
 
///////////
// Checker
///////////
 
////////////
// Instance
////////////
ldp_top #(
  .FOLDFACTOR  (1),
  .NUMINSTANCES(360),
  .LLRWIDTH    (LLRWIDTH)
) ldp_top_i(
  .clk(clk),
  .rst(rst),
 
  .llr_access (llr_access),
  .llr_addr   (llr_addr),
  .llr_din_we (llr_din_we),
  .llr_din    (llr_din),
  .llr_dout   (llr_dout),
 
  .start     (start),
  .mode      (mode),
  .iter_limit(iter_limit),
  .done      (done)
);
 
endmodule
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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