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_shuffle.v] - Rev 2

Compare with Previous | Blame | View Log

`timescale 1ns/10ps
 
module tb_shuffle();
 
localparam CLK_PERIOD = 10ns;
localparam HOLD  = 1ns;
 
localparam FOLDFACTOR     = 4;
localparam NUMINSTANCES   = 360 / FOLDFACTOR;
localparam LOG2INSTANCES = (FOLDFACTOR==1) ? 9 :
                           (FOLDFACTOR==2) ? 8 :
                           (FOLDFACTOR==3) ? 7 :
                           /* 4 */           7;
localparam LLRWIDTH       = 4;
 
localparam LASTSHIFTDIST = (FOLDFACTOR==1) ? 11 :
                           (FOLDFACTOR==2) ? 5  :
                           (FOLDFACTOR==3) ? 3  :
                           /* 4 */           2;
localparam LASTSHIFTWIDTH  = (FOLDFACTOR==1) ? 4 :
                             (FOLDFACTOR==2) ? 3 :
                             (FOLDFACTOR==3) ? 2 :
                             /* 4 */           2;
reg clk;
reg rst;
 
initial
begin
  clk <= 0;
  rst <= 1;
  #0;
 
  #(CLK_PERIOD/2) clk <= ~clk;
  #(CLK_PERIOD/2)clk <= ~clk;
  #(CLK_PERIOD/2)clk <= ~clk;
 
  rst <= 0;
 
  forever
    #(CLK_PERIOD/2) clk <= ~clk;
end
 
////////////////////
reg                       vnmsg0_cnmsg1;
reg                       first_half;
integer                   shiftval;
integer                   shiftval_del1;
integer                   shiftval_del2;
wire[1:0]                 shift0;
wire[2:0]                 shift1;
wire[LASTSHIFTWIDTH-1:0]  shift2;
 
 
reg[LLRWIDTH-1:0] vn_2d[NUMINSTANCES-1:0];
reg[LLRWIDTH-1:0] cn_2d[NUMINSTANCES-1:0];
reg[LLRWIDTH-1:0] vn_pipe[0:2][NUMINSTANCES-1:0];
reg[LLRWIDTH-1:0] cn_pipe[0:2][NUMINSTANCES-1:0];
 
reg[NUMINSTANCES*LLRWIDTH-1:0]  vn_concat;
reg[NUMINSTANCES*LLRWIDTH-1:0]  cn_concat;
wire[NUMINSTANCES*LLRWIDTH-1:0] sh_concat;
////////////////////
 
localparam SHIFTFACTOR0 = FOLDFACTOR==1 ? 90 :
                          FOLDFACTOR==2 ? 45 :
                          FOLDFACTOR==3 ? 30 :
                                          23;
localparam SHIFTFACTOR1 = (FOLDFACTOR==1) ? 12 :
                          (FOLDFACTOR==2) ? 6  :
                          (FOLDFACTOR==3) ? 4  :
                          /* 4 */           3;     
 
assign shift0 = shiftval / SHIFTFACTOR0;
assign shift1 = (shiftval_del1 % SHIFTFACTOR0) / SHIFTFACTOR1;
assign shift2 = (shiftval_del2 % SHIFTFACTOR0) % SHIFTFACTOR1;
 
always @( posedge clk, posedge rst )
  if( rst )
  begin
    shiftval_del1 <= 0;
    shiftval_del2 <= 0;
  end
  else
  begin
    shiftval_del1 <= #HOLD shiftval;
    shiftval_del2 <= #HOLD shiftval_del1;
  end
 
// shift random distances (1 million iterations)
initial
begin
  first_half <= 1;
  shiftval   <= 0;
 
  for( int j=0; j<NUMINSTANCES; j++ )
  begin
    vn_2d[j] <= #HOLD 0;
    cn_2d[j] <= #HOLD 0;
  end
 
  @( negedge rst );
  @( posedge clk );
 
  // a few corner cases
  for( int j=0; j<NUMINSTANCES; j++ )
  begin
    vn_2d[j] <= #HOLD j % (2**LLRWIDTH);
    cn_2d[j] <= #HOLD j % (2**LLRWIDTH);
  end
 
  shiftval <= #HOLD NUMINSTANCES - 1;
  @( posedge clk );
  shiftval <= #HOLD 0;
  @( posedge clk );
  shiftval <= #HOLD 1;
  @( posedge clk );
  shiftval <= #HOLD NUMINSTANCES/8 - 1;
  @( posedge clk );
  shiftval <= #HOLD NUMINSTANCES/8;
  @( posedge clk );
  shiftval <= #HOLD NUMINSTANCES/8 + 1;
  @( posedge clk );
  shiftval <= #HOLD NUMINSTANCES/4 - 1;
  @( posedge clk );
  shiftval <= #HOLD NUMINSTANCES/4;
  @( posedge clk );
  shiftval <= #HOLD NUMINSTANCES/4 + 1;
  @( posedge clk );
  shiftval <= #HOLD NUMINSTANCES/2 - 1;
  @( posedge clk );
  shiftval <= #HOLD NUMINSTANCES/2;
  @( posedge clk );
  shiftval <= #HOLD NUMINSTANCES/2 + 1;
  @( posedge clk );
 
  for( int i=0; i<1000000; i++ )
  begin
    // random shift
    shiftval = #HOLD {$random()} % NUMINSTANCES;
 
    // random data
    for( int j=0; j<NUMINSTANCES; j++ )
    begin
      vn_2d[j] <= #HOLD $random();
      cn_2d[j] <= #HOLD $random();
    end
 
    @( posedge clk );
  end
 
  $stop();
end
 
generate
  genvar inst;
 
  for( inst=0; inst<NUMINSTANCES; inst=inst+1 )
  begin: twodto1d
    assign vn_concat[inst*LLRWIDTH+LLRWIDTH-1:inst*LLRWIDTH] = vn_2d[inst];
    assign cn_concat[inst*LLRWIDTH+LLRWIDTH-1:inst*LLRWIDTH] = cn_2d[inst];
  end
endgenerate
 
task rotate_ldpc( output reg[LLRWIDTH-1:0] out_array[NUMINSTANCES-1:0],
                  input  reg[LLRWIDTH-1:0] inp_array[NUMINSTANCES-1:0],
                  input  int               shift_distance );
begin
  for( int inst=0; inst<NUMINSTANCES; inst++ )
    out_array[(NUMINSTANCES+inst+shift_distance) % NUMINSTANCES] = inp_array[inst];
end
endtask
 
// simulate shuffle behavior
int shift_pipe[0:2];
reg[LLRWIDTH-1:0] shuffle_result[NUMINSTANCES-1:0];
 
initial
begin
  for( int i=0; i<4; i++ )
  begin
    shift_pipe[i] <= 0;
    for( int j=0; j<NUMINSTANCES; j++ )
    begin
      vn_pipe[i][j] <= 0;
      cn_pipe[i][j] <= 0;
    end
  end
 
  @(negedge rst);
  @(posedge clk);
 
  forever
  begin
    shift_pipe[0] <= shiftval;
    shift_pipe[1] <= shift_pipe[0];
    shift_pipe[2] <= shift_pipe[1];
 
    vn_pipe[0] <= vn_2d;
    vn_pipe[1] <= vn_pipe[0];
    rotate_ldpc( shuffle_result, vn_pipe[1], shift_pipe[1] );
    vn_pipe[2] <= shuffle_result;
 
    cn_pipe[0] <= cn_2d;
    cn_pipe[1] <= cn_pipe[0];
    rotate_ldpc( shuffle_result, cn_pipe[1], NUMINSTANCES - shift_pipe[1] );
    cn_pipe[2] <= shuffle_result;
    @(posedge clk);
  end
end
 
// assert that shuffler always returns correct result
logic[LLRWIDTH-1:0] local_result;
 
initial
begin
  @(negedge rst);
  repeat( 3 ) @(posedge clk);
 
  forever
  begin
    for( int i=NUMINSTANCES-1; i>=0; i-- )
    begin
      local_result = sh_concat[(i+1)*LLRWIDTH-1 -: LLRWIDTH];
 
      if( first_half )
      begin
        if( local_result!=vn_pipe[2][i] )
          $display( "%0t: Shuffle mismatch: position %0d: expected %0h: result %0h", $time, i, local_result, vn_pipe[2][i] );
      end
      else
        if( local_result!=cn_pipe[2][i] )
          $display( "%0t: Shuffle mismatch: position %0d: expected %0h: result %0h", $time, i, local_result, cn_pipe[2][i] );
    end
    @( posedge clk );
  end
end
 
ldpc_shuffle #( .FOLDFACTOR(FOLDFACTOR),
                .NUMINSTANCES(NUMINSTANCES),
                .LOG2INSTANCES(LOG2INSTANCES),
                .LLRWIDTH(LLRWIDTH),
                .LASTSHIFTWIDTH(LASTSHIFTWIDTH),
                .LASTSHIFTDIST(LASTSHIFTDIST)
 ) ldpc_shufflei(
  .clk          (clk),
  .rst          (rst),
  .first_half   (first_half),
  .shift0       (shift0),
  .shift1       (shift1),
  .shift2       (shift2),
  .incpoint     (incpoint),
  .vn_concat    (vn_concat),
  .cn_concat    (cn_concat),
  .sh_concat    (sh_concat),
  .increment    (increment)
);
 
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.