Links:

Home

Contact us

Samples

CORES

A test bench that can be used to check the functionality of the wide parallel PRBS generator/checker.

 

So that's a lot to take for granted. Lets run a simulation. This test bench combines the 16 SFI5 tx channels into one 40 Gbs stream. Checks that stream for correctness for a PRBS. Then adds a variable delay before demuxing the stream back into 16 rx channels. By adding a variable delay we can control how the data is striped across the incoming channels, and more importantly test that the rx side is correct independant of the alignement of the data between the tx and rx side. To test the locking of the checkers, the 'fiber delay' which changes the striping offset gets changed periodically, and the RX side relocks. Then the pattern is also changed through all 4 patterns as well. Each time, the rx side will relock. The reset on the rx side is optional for actual implementation as the relock will take care of putting all of the logic in the correct state. Unfortunately simulation needs some state to start with. Optionally, there is a commnted out direct connect between the tx and rx sides. Useful for simulation debug.

module test_tx_rx (
                );
   reg [31:0] prbs_40;
   reg               error_40;
   reg               clk;
   reg [6:0]  channel_counter, rx_channel_counter;
   reg               reset;
   reg [7:0] byte_shifter_f,
             byte_shifter_e,
             byte_shifter_d,
             byte_shifter_c,
             byte_shifter_b,
             byte_shifter_a,
             byte_shifter_9,
             byte_shifter_8,
             byte_shifter_7,
             byte_shifter_6,
             byte_shifter_5,
             byte_shifter_4,
             byte_shifter_3,
             byte_shifter_2,
             byte_shifter_1,
             byte_shifter_0,
             rx_byte_shifter_f,
             rx_byte_shifter_e,
             rx_byte_shifter_d,
             rx_byte_shifter_c,
             rx_byte_shifter_b,
             rx_byte_shifter_a,
             rx_byte_shifter_9,
             rx_byte_shifter_8,
             rx_byte_shifter_7,
             rx_byte_shifter_6,
             rx_byte_shifter_5,
             rx_byte_shifter_4,
             rx_byte_shifter_3,
             rx_byte_shifter_2,
             rx_byte_shifter_1,
             rx_byte_shifter_0;
   reg [15:0] bit_shifter, rx_bit_shifter;
   reg               data_out, data_in;
   reg               tx_clk, rx_clk;
   wire [7:0] tx_prbs_f,
              tx_prbs_e,
              tx_prbs_d,
              tx_prbs_c,
              tx_prbs_b,
              tx_prbs_a,
              tx_prbs_9,
              tx_prbs_8,
              tx_prbs_7,
              tx_prbs_6,
              tx_prbs_5,
              tx_prbs_4,
              tx_prbs_3,
              tx_prbs_2,
              tx_prbs_1,
              tx_prbs_0,
              tx_deskew;
   reg [7:0]  rx_prbs_f,
              rx_prbs_e,
              rx_prbs_d,
              rx_prbs_c,
              rx_prbs_b,
              rx_prbs_a,
              rx_prbs_9,
              rx_prbs_8,
              rx_prbs_7,
              rx_prbs_6,
              rx_prbs_5,
              rx_prbs_4,
              rx_prbs_3,
              rx_prbs_2,
              rx_prbs_1,
              rx_prbs_0;
   reg [31:0] fiber,fiber_p1;
   wire [6:0] error;
   wire       bad;
   reg [1:0]             prbs_select;
   reg [15:0]             fiber_delay;
   
   initial begin
      clk = 0;
      channel_counter = 0;
      rx_channel_counter = 5;
      reset = 0;
      prbs_select = 0;
      fiber_delay = 15;
      #1000 reset = 1;
      #2000 reset = 0;
      #10_000 fiber_delay = fiber_delay + 1;
      #10_000 fiber_delay = fiber_delay + 1;
      #10_000 fiber_delay = fiber_delay + 1;
      #10_000 fiber_delay = fiber_delay + 1;
      #10_000 prbs_select = 1;
      #10_000 fiber_delay = fiber_delay + 1;
      #10_000 fiber_delay = fiber_delay + 1;
      #10_000 fiber_delay = fiber_delay + 1;
      #10_000 fiber_delay = fiber_delay + 1;
      #10_000 prbs_select = 2;
      #10_000 fiber_delay = fiber_delay + 1;
      #10_000 fiber_delay = fiber_delay + 1;
      #10_000 fiber_delay = fiber_delay + 1;
      #10_000 fiber_delay = fiber_delay + 1;
      #10_000 prbs_select = 3;
      #10_000 fiber_delay = fiber_delay + 1;
      #10_000 fiber_delay = fiber_delay + 1;
      #10_000 fiber_delay = fiber_delay + 1;
      #10_000 fiber_delay = fiber_delay + 1;
      #10_000 $stop;
   end
 
   always clk = #0.0125 ~ clk; //the "40G" clk


/*******************************
 * tx mux side
 * output is data out which connects to "fiber" variable delay
 * ******************************/
   
   always @ (posedge clk)
     begin
        data_out <= bit_shifter[15];
        channel_counter <= channel_counter + 1;
        if (channel_counter[3:0]=='hf)
          begin
             bit_shifter <= {byte_shifter_f[7],
                          byte_shifter_e[7],
                          byte_shifter_d[7],
                          byte_shifter_c[7],
                          byte_shifter_b[7],
                          byte_shifter_a[7],
                          byte_shifter_9[7],
                          byte_shifter_8[7],
                          byte_shifter_7[7],
                          byte_shifter_6[7],
                          byte_shifter_5[7],
                          byte_shifter_4[7],
                          byte_shifter_3[7],
                          byte_shifter_2[7],
                          byte_shifter_1[7],
                          byte_shifter_0[7]};
             if (channel_counter[6:4] =='h7)
               begin
                  byte_shifter_f <= tx_prbs_f;
                  byte_shifter_e <= tx_prbs_e;
                  byte_shifter_d <= tx_prbs_d;
                  byte_shifter_c <= tx_prbs_c;
                  byte_shifter_b <= tx_prbs_b;
                  byte_shifter_a <= tx_prbs_a;
                  byte_shifter_9 <= tx_prbs_9;
                  byte_shifter_8 <= tx_prbs_8;
                  byte_shifter_7 <= tx_prbs_7;
                  byte_shifter_6 <= tx_prbs_6;
                  byte_shifter_5 <= tx_prbs_5;
                  byte_shifter_4 <= tx_prbs_4;
                  byte_shifter_3 <= tx_prbs_3;
                  byte_shifter_2 <= tx_prbs_2;
                  byte_shifter_1 <= tx_prbs_1;
                  byte_shifter_0 <= tx_prbs_0;
                  tx_clk <= 1;
               end         
             else
               begin
                  byte_shifter_f <= {byte_shifter_f,1'b0};
                  byte_shifter_e <= {byte_shifter_e,1'b0};
                  byte_shifter_d <= {byte_shifter_d,1'b0};
                  byte_shifter_c <= {byte_shifter_c,1'b0};
                  byte_shifter_b <= {byte_shifter_b,1'b0};
                  byte_shifter_a <= {byte_shifter_a,1'b0};
                  byte_shifter_9 <= {byte_shifter_9,1'b0};
                  byte_shifter_8 <= {byte_shifter_8,1'b0};
                  byte_shifter_7 <= {byte_shifter_7,1'b0};
                  byte_shifter_6 <= {byte_shifter_6,1'b0};
                  byte_shifter_5 <= {byte_shifter_5,1'b0};
                  byte_shifter_4 <= {byte_shifter_4,1'b0};
                  byte_shifter_3 <= {byte_shifter_3,1'b0};
                  byte_shifter_2 <= {byte_shifter_2,1'b0};
                  byte_shifter_1 <= {byte_shifter_1,1'b0};
                  byte_shifter_0 <= {byte_shifter_0,1'b0};
                  tx_clk <= 1'b0; 
               end
          end // if (channel_counter[3:0]=='hf)
        else
          begin
             bit_shifter <= {bit_shifter,1'b0};
             tx_clk <= 0;
          end // else: !if(channel_counter[3:0]=='hf)
     end // always @ (posedge clk)
   //instantiate the tx 
   tx_prbs sfi5_tx_test (
                         .i_clk(tx_clk),
                         .i_reset(reset),
                         .prbs_select(prbs_select),
                         .o_prbs_data_0(tx_prbs_0),
                         .o_prbs_data_1(tx_prbs_1),
                         .o_prbs_data_2(tx_prbs_2),
                         .o_prbs_data_3(tx_prbs_3),
                         .o_prbs_data_4(tx_prbs_4),
                         .o_prbs_data_5(tx_prbs_5),
                         .o_prbs_data_6(tx_prbs_6),
                         .o_prbs_data_7(tx_prbs_7),
                         .o_prbs_data_8(tx_prbs_8),
                         .o_prbs_data_9(tx_prbs_9),
                         .o_prbs_data_a(tx_prbs_a),
                         .o_prbs_data_b(tx_prbs_b),
                         .o_prbs_data_c(tx_prbs_c),
                         .o_prbs_data_d(tx_prbs_d),
                         .o_prbs_data_e(tx_prbs_e),
                         .o_prbs_data_f(tx_prbs_f)
                         );

/**********************************
 * here we add the variable delay between the mux and demux
 * *******************************/
   always @ (posedge clk)
     begin
        fiber <= {fiber,data_out};
        fiber_p1 <= fiber;
        data_in <= fiber[fiber_delay];  //this is the delay #
        //for checking the stream as one 40g prbs
        if (error_40)
          prbs_40 <= {fiber,data_out};
        else
          case (prbs_select)
            0:           prbs_40 <= {prbs_40,prbs_40[6]^prbs_40[5]};
            1:           prbs_40 <= {prbs_40,prbs_40[14]^prbs_40[13]};
            2:           prbs_40 <= {prbs_40,prbs_40[22]^prbs_40[17]};
            3:           prbs_40 <= {prbs_40,prbs_40[30]^prbs_40[27]};
          endcase // case(prbs_select)
        if (prbs_40[31:0] == fiber[31:0])
          error_40 <= 0;
        else
          error_40 <= 1;
     end
   
/******************************************************
 * and the demux on the recieve side
 * **************************************/
   
always @ (posedge clk)
  begin
     rx_channel_counter <= rx_channel_counter + 1;
     rx_bit_shifter <= {rx_bit_shifter,data_in};
     if (rx_channel_counter[3:0] == 4'hf)
       begin
          rx_byte_shifter_f <= {rx_byte_shifter_f,rx_bit_shifter['hf]};
          rx_byte_shifter_e <= {rx_byte_shifter_e,rx_bit_shifter['he]};
          rx_byte_shifter_d <= {rx_byte_shifter_d,rx_bit_shifter['hd]};
          rx_byte_shifter_c <= {rx_byte_shifter_c,rx_bit_shifter['hc]};
          rx_byte_shifter_b <= {rx_byte_shifter_b,rx_bit_shifter['hb]};
          rx_byte_shifter_a <= {rx_byte_shifter_a,rx_bit_shifter['ha]};
          rx_byte_shifter_9 <= {rx_byte_shifter_9,rx_bit_shifter['h9]};
          rx_byte_shifter_8 <= {rx_byte_shifter_8,rx_bit_shifter['h8]};
          rx_byte_shifter_7 <= {rx_byte_shifter_7,rx_bit_shifter['h7]};
          rx_byte_shifter_6 <= {rx_byte_shifter_6,rx_bit_shifter['h6]};
          rx_byte_shifter_5 <= {rx_byte_shifter_5,rx_bit_shifter['h5]};
          rx_byte_shifter_4 <= {rx_byte_shifter_4,rx_bit_shifter['h4]};
          rx_byte_shifter_3 <= {rx_byte_shifter_3,rx_bit_shifter['h3]};
          rx_byte_shifter_2 <= {rx_byte_shifter_2,rx_bit_shifter['h2]};
          rx_byte_shifter_1 <= {rx_byte_shifter_1,rx_bit_shifter['h1]};
          rx_byte_shifter_0 <= {rx_byte_shifter_0,rx_bit_shifter['h0]};
          if (rx_channel_counter[6:4] == 3'h7)
            begin
               rx_prbs_f <= rx_byte_shifter_f;
               rx_prbs_e <= rx_byte_shifter_e;
               rx_prbs_d <= rx_byte_shifter_d;
               rx_prbs_c <= rx_byte_shifter_c;
               rx_prbs_b <= rx_byte_shifter_b;
               rx_prbs_a <= rx_byte_shifter_a;
               rx_prbs_9 <= rx_byte_shifter_9;
               rx_prbs_8 <= rx_byte_shifter_8;
               rx_prbs_7 <= rx_byte_shifter_7;
               rx_prbs_6 <= rx_byte_shifter_6;
               rx_prbs_5 <= rx_byte_shifter_5;
               rx_prbs_4 <= rx_byte_shifter_4;
               rx_prbs_3 <= rx_byte_shifter_3;
               rx_prbs_2 <= rx_byte_shifter_2;
               rx_prbs_1 <= rx_byte_shifter_1;
               rx_prbs_0 <= rx_byte_shifter_0;
               rx_clk <= 1;
            end
          else
            rx_clk <= 0;
       end // if (rx_channel_counter[3:0] == 4'hf)
     else
       rx_clk <= 0;
    end // always @ (posedge clk)
   
/*************************************
 * and of course instantiate the rx sfi5
 * ********************************/
sfi5_rx sfi5_rx_test (
                      .i_clk_in(rx_clk),
                      .i_reset(reset),
                      .prbs_select(prbs_select),
                      .i_ch_0(rx_prbs_0),
                      .i_ch_1(rx_prbs_1),
                      .i_ch_2(rx_prbs_2),
                      .i_ch_3(rx_prbs_3),
                      .i_ch_4(rx_prbs_4),
                      .i_ch_5(rx_prbs_5),
                      .i_ch_6(rx_prbs_6),
                      .i_ch_7(rx_prbs_7),
                      .i_ch_8(rx_prbs_8),
                      .i_ch_9(rx_prbs_9),
                      .i_ch_a(rx_prbs_a),
                      .i_ch_b(rx_prbs_b),
                      .i_ch_c(rx_prbs_c),
                      .i_ch_d(rx_prbs_d),
                      .i_ch_e(rx_prbs_e),
                      .i_ch_f(rx_prbs_f),
/* skip the mux/demux                      
                      .i_ch_0(tx_prbs_0),
                      .i_ch_1(tx_prbs_1),
                      .i_ch_2(tx_prbs_2),
                      .i_ch_3(tx_prbs_3),
                      .i_ch_4(tx_prbs_4),
                      .i_ch_5(tx_prbs_5),
                      .i_ch_6(tx_prbs_6),
                      .i_ch_7(tx_prbs_7),
                      .i_ch_8(tx_prbs_8),
                      .i_ch_9(tx_prbs_9),
                      .i_ch_a(tx_prbs_a),
                      .i_ch_b(tx_prbs_b),
                      .i_ch_c(tx_prbs_c),
                      .i_ch_d(tx_prbs_d),
                      .i_ch_e(tx_prbs_e),
                      .i_ch_f(tx_prbs_f),

*/
                      
                      .i_ch_deskew(8'h0),
                      .o_error(error),
                      .o_bad(bad)
                      );

 always @ (error)
   $display("error is %d",error);
endmodule // test_tx


Still have questions?