|  | 
|  | 1 | +//------------------------------------------------------------------------------ | 
|  | 2 | +// slicer_functions_tb.sv | 
|  | 3 | +// published as part of https://github.com/pConst/basic_verilog | 
|  | 4 | +// Konstantin Pavlov, [email protected] | 
|  | 5 | +//------------------------------------------------------------------------------ | 
|  | 6 | + | 
|  | 7 | +// INFO ------------------------------------------------------------------------ | 
|  | 8 | +// Testbench for slicer_functions.vh | 
|  | 9 | + | 
|  | 10 | +// use this define to make some things differently in simulation | 
|  | 11 | +`define SIMULATION yes | 
|  | 12 | + | 
|  | 13 | +`timescale 1ns / 1ps | 
|  | 14 | + | 
|  | 15 | +module slicer_functions_tb(); | 
|  | 16 | + | 
|  | 17 | +initial begin | 
|  | 18 | +  // Print out time markers in nanoseconds | 
|  | 19 | +  // Example:  $display("[T=%0t] start=%d", $realtime, start); | 
|  | 20 | +  $timeformat(-9, 3, " ns"); | 
|  | 21 | + | 
|  | 22 | +  // seed value setting is intentionally manual to achieve repeatability between sim runs | 
|  | 23 | +  $urandom( 1 );  // SEED value | 
|  | 24 | +end | 
|  | 25 | + | 
|  | 26 | +logic clk200; | 
|  | 27 | +sim_clk_gen #( | 
|  | 28 | +  .FREQ( 200_000_000 ), // in Hz | 
|  | 29 | +  .PHASE( 0 ),          // in degrees | 
|  | 30 | +  .DUTY( 50 ),          // in percentage | 
|  | 31 | +  .DISTORT( 10 )        // in picoseconds | 
|  | 32 | +) clk200_gen ( | 
|  | 33 | +  .ena( 1'b1 ), | 
|  | 34 | +  .clk( clk200 ), | 
|  | 35 | +  .clkd(  ) | 
|  | 36 | +); | 
|  | 37 | + | 
|  | 38 | +logic nrst_once; | 
|  | 39 | + | 
|  | 40 | +logic [31:0] clk200_div; | 
|  | 41 | +clk_divider #( | 
|  | 42 | +  .WIDTH( 32 ) | 
|  | 43 | +) cd1 ( | 
|  | 44 | +  .clk( clk200 ), | 
|  | 45 | +  .nrst( nrst_once ), | 
|  | 46 | +  .ena( 1'b1 ), | 
|  | 47 | +  .out( clk200_div[31:0] ) | 
|  | 48 | +); | 
|  | 49 | + | 
|  | 50 | +logic [31:0] clk200_div_rise; | 
|  | 51 | +edge_detect ed1[31:0] ( | 
|  | 52 | +  .clk( {32{clk200}} ), | 
|  | 53 | +  .anrst( {32{nrst_once}} ), | 
|  | 54 | +  .in( clk200_div[31:0] ), | 
|  | 55 | +  .rising( clk200_div_rise[31:0] ), | 
|  | 56 | +  .falling(  ), | 
|  | 57 | +  .both(  ) | 
|  | 58 | +); | 
|  | 59 | + | 
|  | 60 | +// external device "asynchronous" clock | 
|  | 61 | +logic clk33; | 
|  | 62 | +logic clk33d; | 
|  | 63 | +sim_clk_gen #( | 
|  | 64 | +  .FREQ( 200_000_000 ), // in Hz | 
|  | 65 | +  .PHASE( 0 ),          // in degrees | 
|  | 66 | +  .DUTY( 50 ),          // in percentage | 
|  | 67 | +  .DISTORT( 1000 )      // in picoseconds | 
|  | 68 | +) clk33_gen ( | 
|  | 69 | +  .ena( 1'b1 ), | 
|  | 70 | +  .clk( clk33 ), | 
|  | 71 | +  .clkd( clk33d ) | 
|  | 72 | +); | 
|  | 73 | + | 
|  | 74 | + | 
|  | 75 | +logic rst; | 
|  | 76 | +initial begin | 
|  | 77 | +  rst = 1'b0; // initialization | 
|  | 78 | +  repeat( 1 ) @(posedge clk200); | 
|  | 79 | + | 
|  | 80 | +  forever begin | 
|  | 81 | +    repeat( 1 ) @(posedge clk200); // synchronous rise | 
|  | 82 | +    rst = 1'b1; | 
|  | 83 | +    //$urandom( 1 ); // uncomment to get the same random pattern EVERY nrst | 
|  | 84 | + | 
|  | 85 | +    repeat( 2 ) @(posedge clk200); // synchronous fall, controls rst pulse width | 
|  | 86 | +    rst = 1'b0; | 
|  | 87 | + | 
|  | 88 | +    repeat( 100 ) @(posedge clk200); // controls test body width | 
|  | 89 | +  end | 
|  | 90 | +end | 
|  | 91 | +logic nrst; | 
|  | 92 | +assign nrst = ~rst; | 
|  | 93 | + | 
|  | 94 | + | 
|  | 95 | +logic rst_once; | 
|  | 96 | +initial begin | 
|  | 97 | +  rst_once = 1'b0; // initialization | 
|  | 98 | +  repeat( 1 ) @(posedge clk200); | 
|  | 99 | + | 
|  | 100 | +  repeat( 1 ) @(posedge clk200); // synchronous rise | 
|  | 101 | +  rst_once = 1'b1; | 
|  | 102 | + | 
|  | 103 | +  repeat( 2 ) @(posedge clk200); // synchronous fall, controls rst_once pulse width | 
|  | 104 | +  rst_once = 1'b0; | 
|  | 105 | +end | 
|  | 106 | +//logic nrst_once; // declared before | 
|  | 107 | +assign nrst_once = ~rst_once; | 
|  | 108 | + | 
|  | 109 | + | 
|  | 110 | +// random pattern generation | 
|  | 111 | +logic [31:0] rnd_data; | 
|  | 112 | +always_ff @(posedge clk200) begin | 
|  | 113 | +  rnd_data[31:0] <= $urandom; | 
|  | 114 | +  end | 
|  | 115 | + | 
|  | 116 | +initial forever begin | 
|  | 117 | +  @(posedge nrst); | 
|  | 118 | +  $display("[T=%0t] rnd_data[]=%h", $realtime, rnd_data[31:0]); | 
|  | 119 | +end | 
|  | 120 | + | 
|  | 121 | + | 
|  | 122 | +// helper start strobe appears unpredictable up to 20 clocks after nrst | 
|  | 123 | +logic start; | 
|  | 124 | +initial forever begin | 
|  | 125 | +  start = 1'b0; // initialization | 
|  | 126 | + | 
|  | 127 | +  @(posedge nrst); // synchronous rise after EVERY nrst | 
|  | 128 | +  repeat( $urandom_range(0, 20) ) @(posedge clk200); | 
|  | 129 | +  start = 1'b1; | 
|  | 130 | + | 
|  | 131 | +  @(posedge clk200); // synchronous fall exactly 1 clock after rise | 
|  | 132 | +  start = 1'b0; | 
|  | 133 | +end | 
|  | 134 | + | 
|  | 135 | + | 
|  | 136 | +initial begin | 
|  | 137 | +//  #10000 $stop; | 
|  | 138 | +//  #10000 $finish; | 
|  | 139 | +end | 
|  | 140 | + | 
|  | 141 | +// Module under test =========================================================== | 
|  | 142 | + | 
|  | 143 | +logic [15:0] seq_cntr = '0; | 
|  | 144 | + | 
|  | 145 | +logic [31:0] id = '0; | 
|  | 146 | +always_ff @(posedge clk200) begin | 
|  | 147 | +  if( ~nrst_once ) begin | 
|  | 148 | +    seq_cntr[15:0] <= '0; | 
|  | 149 | +    id[31:0] <= '0; | 
|  | 150 | +  end else begin | 
|  | 151 | +    // incrementing sequence counter | 
|  | 152 | +    if( seq_cntr[15:0]!= '1 ) begin | 
|  | 153 | +      seq_cntr[15:0] <= seq_cntr[15:0] + 1'b1; | 
|  | 154 | +    end | 
|  | 155 | + | 
|  | 156 | +    if( seq_cntr[15:0]<300 ) begin | 
|  | 157 | +      id[31:0] <= '1; | 
|  | 158 | +      //id[31:0] <= {4{rnd_data[15:0]}}; | 
|  | 159 | +    end else begin | 
|  | 160 | +      id[31:0] <= '0; | 
|  | 161 | +    end | 
|  | 162 | +  end | 
|  | 163 | +end | 
|  | 164 | + | 
|  | 165 | +`include "gray_functions.vh" | 
|  | 166 | + | 
|  | 167 | +logic [15:0] gray; | 
|  | 168 | +logic [15:0] bin; | 
|  | 169 | +always_comb begin | 
|  | 170 | +  gray[15:0] = gray_functions#(16)::bin2gray( seq_cntr[15:0] ); | 
|  | 171 | +  bin[15:0] = gray_functions#(16)::gray2bin( gray[15:0] ); | 
|  | 172 | +end | 
|  | 173 | + | 
|  | 174 | + | 
|  | 175 | +`include "slicer_functions.vh" | 
|  | 176 | + | 
|  | 177 | +logic [3:0][3:0][7:0] d1 = {32'hdead_beef,32'h1234_5678,32'hface_face,32'habcd_efef}; | 
|  | 178 | +logic [2:1][2:1][3:0] s1; | 
|  | 179 | +always_comb begin | 
|  | 180 | +  s1 = slicer_functions#( | 
|  | 181 | +      .I3_HI( 3 ), .I3_LO( 0 ), .I2_HI( 3 ), .I2_LO( 0 ), | 
|  | 182 | +      .I1_HI( 7 ), .I1_LO( 0 ), .O3_HI( 2 ), .O3_LO( 1 ), | 
|  | 183 | +      .O2_HI( 2 ), .O2_LO( 1 ), .O1_HI( 3 ), .O1_LO( 0 )  )::slice3d( d1 ); | 
|  | 184 | +end | 
|  | 185 | + | 
|  | 186 | + | 
|  | 187 | +typedef struct packed { | 
|  | 188 | +  logic a; | 
|  | 189 | +  //logic b; | 
|  | 190 | +} my_struct_t; | 
|  | 191 | + | 
|  | 192 | +my_struct_t [3:0][3:0][7:0] d2 = {32'hdead_beef,32'h1234_5678,32'hface_face,32'habcd_efef}; | 
|  | 193 | +my_struct_t [2:1][2:1][3:0] s2; | 
|  | 194 | +always_comb begin | 
|  | 195 | +  s2 = slicer_functions#( .T(my_struct_t), | 
|  | 196 | +      .I3_HI( 3 ), .I3_LO( 0 ), .I2_HI( 3 ), .I2_LO( 0 ), | 
|  | 197 | +      .I1_HI( 7 ), .I1_LO( 0 ), .O3_HI( 2 ), .O3_LO( 1 ), | 
|  | 198 | +      .O2_HI( 2 ), .O2_LO( 1 ), .O1_HI( 3 ), .O1_LO( 0 )  )::slice3d_t( d2 ); | 
|  | 199 | +end | 
|  | 200 | + | 
|  | 201 | + | 
|  | 202 | +endmodule | 
|  | 203 | + | 
0 commit comments