Template

Design

//------------------------------------------------------------------------------
  //
  //  Filename       : calc_add_knl.v
  //  Author         : Huang Leilei
  //  Status         : draft
  //  Created        : 2022-04-18
  //  Description    : [kernal logic] of [adder]
  //
//------------------------------------------------------------------------------

`include "define_calc.vh"

module calc_add_knl(
  // global
  clk                   ,
  rstn                  ,
  // cfg_i
  cfg_flg_saturate_i    ,
  // dat_i
  val_i                 ,
  dat_a_i               ,
  dat_b_i               ,
  // dat_o
  val_o                 ,
  dat_o
);


//*** PARAMETER ****************************************************************

  // global
  // !!! a special case here
  localparam   DATA_WD           = 'd32             ;

  // derived
  localparam   DATA_MAX          = { {DATA_WD{1'b1}}
                                 }                  ;


//*** INPUT/OUTPUT *************************************************************

  // global
  input                          clk                ;
  input                          rstn               ;

  // cfg_i
  input                          cfg_flg_saturate_i ;

  // val_i
  input                          val_i              ;
  input      [DATA_WD  -1 :0]    dat_a_i            ;
  input      [DATA_WD  -1 :0]    dat_b_i            ;

  // val_o
  output reg                     val_o              ;
  output reg [DATA_WD  -1 :0]    dat_o              ;


//*** WIRE/REG *****************************************************************

  // output
  wire       [DATA_WD+1-1 :0]    dat_w              ;


//*** MAIN BODY ****************************************************************
//--- OUTPUT ---------------------------
  // val_o, dat_o
  always @(posedge clk or negedge rstn ) begin
    if( !rstn ) begin
      val_o <= 'd0 ;
      dat_o <= 'd0 ;
    end
    else begin
        val_o <= val_i ;
      if( val_i ) begin
        dat_o <= (cfg_flg_saturate_i&&(dat_w>DATA_MAX)) ? DATA_MAX : dat_w ;
      end
    end
  end

  // dat_w
  assign dat_w = dat_a_i + dat_b_i ;


//*** DEBUG ********************************************************************

  `ifdef KNOB_DBG_CALC

  `endif

endmodule

`include "undef_calc.vh"

Testbench

//------------------------------------------------------------------------------
  //
  //  Filename       : sim_calc_add_knl.v
  //  Author         : Huang Leilei
  //  Status         : draft
  //  Created        : 2022-04-18
  //  Description    : [testbench] for [calc_add_knl]
  //
//------------------------------------------------------------------------------

//--- GLOBAL ---------------------------
  // SIM
  //`define SIM_EVAL_TOP               -1
  //`define SIM_CSTR_TOP               -1
  //`define SIM_KNOB_DBG               -1
  //`define SIM_CSTR_LEVEL_STOP        -1
  //`define SIM_DATA_SEED              -1
  //`define SIM_KNOB_WAVEFORM_SHM      -1
  //`define SIM_KNOB_WAVEFORM_FSDB     -1
  //`define SIM_DATA_WAVEFORM_TIME     -1
  //`define SIM_CSTR_WAVEFORM_LEVEL    -1

  // DUT
  //`define DUT_EVAL_TOP    -1
  //`define DUT_CSTR_TOP    -1
  `include "check_data/dut_setting.vh"


//--- LOCAL (VARIABLE) -----------------
  // SIM
  `define SIM_KNOB_CHKO                         'b1
  `define SIM_KNOB_CHKO_CALC_ADD_KNL_DAT    'b1
  `ifdef  SIM_KNOB_DBG
  `define SIM_KNOB_CHKO_XXX                     `SIM_KNOB_DBG
  `endif
  //`define SIM_KNOB_WAVEFORM_VCD
  //`define SIM_KNOB_WAVEFORM_EVCD

  // DUT
  `ifdef  SIM_KNOB_DBG
  `define SIM_KNOB_DBG_CALC
  `endif
  `include "define_calc.vh"


//--- LOCAL (CONSTANT) -----------------
  // SIM
  `define SIM_DATA_PRD_CLK                             10.000
  `define SIM_CSTR_FILE_INIT_XXX                       "XXX"
  `define SIM_CSTR_FILE_CHKI_CALC_ADD_KNL_DAT_A    "check_data/dat_a.dat"
  `define SIM_CSTR_FILE_CHKI_CALC_ADD_KNL_DAT_B    "check_data/dat_b.dat"
  `define SIM_CSTR_FILE_CHKI_XXX                       "XXX"
  `define SIM_CSTR_FILE_CHKO_CALC_ADD_KNL_DAT      "check_data/dat.dat"
  `define SIM_CSTR_FILE_CHKO_XXX                       "XXX"
  `define SIM_CSTR_FILE_WAVE_SHM                       "simul_data/waveform.shm"
  `define SIM_CSTR_FILE_WAVE_FSDB                      "simul_data/waveform.fsdb"
  `define SIM_CSTR_FILE_WAVE_VCD                       "simul_data/waveform.vcd"
  `define SIM_CSTR_FILE_WAVE_EVCD                      "simul_data/waveform.evcd"

  // DUT (setting)
  //`define DUT_XXX    XXX


module `SIM_EVAL_TOP ;


//*** PARAMETER ****************************************************************

  // global
  `include "localparam_calc.vh"

  // local
  localparam    DATA_WD  = 'd32             ;


//*** INPUT/OUTPUT *************************************************************

  // global
  reg                    clk                ;
  reg                    rstn               ;

  // cfg_i
  reg                    cfg_flg_saturate_i ;

  // val_i
  reg                    val_i              ;
  reg  [DATA_WD-1 :0]    dat_a_i            ;
  reg  [DATA_WD-1 :0]    dat_b_i            ;

  // val_o
  wire                   val_o              ;
  wire [DATA_WD-1 :0]    dat_o              ;


//*** WIRE/REG *****************************************************************

  // seed
  integer                dat_seed_r    ;


//*** SUB BENCH ****************************************************************

  `include "sub_bench/sub_bench.vh"


//*** MAIN BODY ****************************************************************
//--- PROC -----------------------------
  // clk
  initial begin
    clk = 'd0 ;
    forever begin
      #( `SIM_DATA_PRD_CLK / 'd2 );
      clk = ! clk ;
    end
  end

  // rstn
  initial begin
    rstn = 'd0 ;
    #( 5 * `SIM_DATA_PRD_CLK );
    @(negedge clk );
    rstn = 'd1 ;
  end

  // dat_seed_r
  initial begin
    dat_seed_r = `SIM_DATA_SEED ;
  end

  // main
  initial begin
    // init
    cfg_flg_saturate_i = 'd0 ;
    val_i              = 'd0 ;
    dat_a_i            = 'd0 ;
    dat_b_i            = 'd0 ;

    // delay
    #( 5 * `SIM_DATA_PRD_CLK );

    // log
    $display( "\n\n*** CHECK %s BEGIN ! ***\n" ,`DUT_CSTR_TOP );

    // delay
    #( 5 * `SIM_DATA_PRD_CLK );
    $display( "" );

    // core
    -> event_init_calc_add_knl_cfg     ;
    -> event_chki_calc_add_knl_dat_bgn ;
    @  event_chki_calc_add_knl_dat_end ;

    // delay
    #( 5 * `SIM_DATA_PRD_CLK );

    // post
    rstn               = 'd0 ;
    cfg_flg_saturate_i = 'd0 ;
    val_i              = 'd0 ;
    dat_a_i            = 'd0 ;
    dat_b_i            = 'd0 ;

    // log
    #( 1000 * `SIM_DATA_PRD_CLK );
    $display( "\n\n*** CHECK %s END ! ***\n" ,`DUT_CSTR_TOP );
    $finish;
  end


//--- INST -----------------------------
  // begin of DUT
    `DUT_EVAL_TOP dut(
      // global
      .clk                   ( clk                   ),
      .rstn                  ( rstn                  ),
      // cfg_i
      .cfg_flg_saturate_i    ( cfg_flg_saturate_i    ),
      // dat_i
      .val_i                 ( val_i                 ),
      .dat_a_i               ( dat_a_i               ),
      .dat_b_i               ( dat_b_i               ),
      // dat_o
      .val_o                 ( val_o                 ),
      .dat_o                 ( dat_o                 )
    );
  // end   of DUT


//--- DUMP -----------------------------
  // shm
  `ifdef SIM_KNOB_WAVEFORM_SHM
    initial begin
      if( `SIM_KNOB_WAVEFORM_SHM ) begin
        #`SIM_DATA_WAVEFORM_TIME ;
        $shm_open( `SIM_CSTR_FILE_WAVE_SHM );
        $shm_probe( `SIM_EVAL_TOP ,`SIM_CSTR_WAVEFORM_LEVEL );
        #( 10 * `SIM_DATA_PRD_CLK );
        $display( "\t\t dump (shm,%s) to this test is on!" ,`SIM_CSTR_WAVEFORM_LEVEL );
      end
    end
  `endif

  // fsdb
  `ifdef SIM_KNOB_WAVEFORM_FSDB
    initial begin
      if( `SIM_KNOB_WAVEFORM_FSDB ) begin
        #`SIM_DATA_WAVEFORM_TIME ;
        $fsdbDumpfile( `SIM_CSTR_FILE_WAVE_FSDB );
        $fsdbDumpvars( `SIM_EVAL_TOP );
        #( 10 * `SIM_DATA_PRD_CLK );
        $display( "\t\t dump (fsdb) to this test is on!" );
      end
    end
  `endif

  // vcd
  `ifdef SIM_KNOB_WAVEFORM_VCD
    initial begin
      #`VCD_TIME_BGN ;
      $dumpfile( `SIM_CSTR_FILE_WAVE_VCD );
      $dumpvars( 'd0, `SIM_EVAL_TOP );
      #( 10 * `SIM_DATA_PRD_CLK );
      $display( "\t\t dump (vcd) to this test is on!" );
    end
  `endif

  // evcd
  `ifdef SIM_KNOB_WAVEFORM_EVCD
    initial begin
      #`EVCD_TIME_BGN ;
      $dumpports( dut ,`SIM_CSTR_FILE_WAVE_EVCD );
      #( 10 * `SIM_DATA_PRD_CLK );
      $display( "\t\t dump (evcd) to this test is on!" );
    end
  `endif


//*** DEBUG ********************************************************************

  `ifdef KNOB_DBG_CALC

  `endif

endmodule

`include "undef_calc.vh"

Sub-Testbench (Driver)

//------------------------------------------------------------------------------
  //
  //  Filename       : sub_bench.vh
  //  Author         : Huang Leilei
  //  Status         : draft
  //  Created        : 2022-04-18
  //  Description    : [sub testbench] for [calc_add_knl]
  //
//------------------------------------------------------------------------------

//*** SIM_TASK_INIT ************************************************************
//--- SIM_TASK_INIT_CALC_ADD_KNL_CFG
  event    event_init_calc_add_knl_cfg ;

  initial begin
    SIM_TASK_INIT_CALC_ADD_KNL_CFG ;
  end

  task SIM_TASK_INIT_CALC_ADD_KNL_CFG ;
    // main body
    begin
      // wait
      @( event_init_calc_add_knl_cfg );

      // set
      cfg_flg_saturate_i = `CALC_FLAG_SATURATE ;
    end
  endtask


//*** SIM_TASK_CHKI ************************************************************
//--- SIM_TASK_CHKI_CALC_ADD_KNL_DAT
  event    event_chki_calc_add_knl_dat_bgn ;
  event    event_chki_calc_add_knl_dat_end ;

  initial begin
    SIM_TASK_CHKI_CALC_ADD_KNL_DAT ;
  end

  task SIM_TASK_CHKI_CALC_ADD_KNL_DAT ;
    // variables
    integer    sim_fpt_a ;
    integer    sim_fpt_b ;
    integer    sim_tmp   ;

    // main body
    begin
      // core loop
      forever begin
        // wait
        @( event_chki_calc_add_knl_dat_bgn );

        // open files
        sim_fpt_a = $fopen( `SIM_CSTR_FILE_CHKI_CALC_ADD_KNL_DAT_A ,"r" );
        sim_fpt_b = $fopen( `SIM_CSTR_FILE_CHKI_CALC_ADD_KNL_DAT_B ,"r" );

        // set
        sim_tmp = 'd1 ;
        while( sim_tmp != -'sd1 ) begin
          @(negedge clk );
          val_i   = 'd1 ;
          sim_tmp = $fscanf( sim_fpt_a ,"%x", dat_a_i );
          sim_tmp = $fscanf( sim_fpt_b ,"%x", dat_b_i );
        end

        // reset
        val_i   = 'd0 ;
        dat_a_i = $random( dat_seed_r );
        dat_b_i = $random( dat_seed_r );

        // close files
        $fclose( sim_fpt_a );
        $fclose( sim_fpt_b );

        // return
        -> event_chki_calc_add_knl_dat_end ;
      end
    end
  endtask


//*** SIM_TASK_CHKO ************************************************************
//--- CHKO_DAT -------------------------
  `define EVAL_PATH_CALC_ADD_KNL    dut
  `include "sub_bench/sub_bench_dat.vh"

Sub-Testbench (Monitor)

//------------------------------------------------------------------------------
  //
  //  Filename       : sub_bench_dat.vh
  //  Author         : Huang Leilei
  //  Status         : draft
  //  Created        : 2022-04-18
  //  Description    : [sub-testbench dat] for [example]
  //
//------------------------------------------------------------------------------

//--- SIM_TASK_CHKO_CALC_ADD_KNL_DAT
`ifdef SIM_KNOB_CHKO_CALC_ADD_KNL_DAT
  initial begin
    SIM_TASK_CHKO_CALC_ADD_KNL_DAT ;
  end

  task SIM_TASK_CHKO_CALC_ADD_KNL_DAT ;
    // variables
    integer                   sim_fpt ;
    integer                   sim_tmp ;
    reg     [DATA_WD-1 :0]    sim_dat ;

    reg                       dut_val ;
    reg     [DATA_WD-1 :0]    dut_dat ;

    // main body
    begin
      if( `SIM_KNOB_CHKO && `SIM_KNOB_CHKO_CALC_ADD_KNL_DAT ) begin
        // log info
        #( 10 * `SIM_DATA_PRD_CLK );
        $display( "\t\t function check to %s's dat is on!" ,`DUT_CSTR_TOP );

        // open files
        sim_fpt = $fopen( `SIM_CSTR_FILE_CHKO_CALC_ADD_KNL_DAT ,"r" );

        // core loop
        forever begin
          // wait
          @(negedge clk );

          // dut_val
          dut_val = `EVAL_PATH_CALC_ADD_KNL.val_o ;

          // if valid
          if( dut_val ) begin
            // dut_*
            dut_dat = `EVAL_PATH_CALC_ADD_KNL.dat_o ;

            // sim_*
            sim_tmp = $fscanf( sim_fpt ,"%x" ,sim_dat );

            // check
            if( dut_dat !== sim_dat ) begin
              $display("\n\t CALC_ADD_KNL ERROR: at %08d ns, dat_o should be %x, however is %x!\n"
                ,$time
                ,sim_dat
                ,dut_dat
              );
              if( `SIM_CSTR_LEVEL_STOP != "none" ) begin
                #( 1000 * `SIM_DATA_PRD_CLK );
                $finish ;
              end
            end
          end
        end
      end
    end
  endtask
`endif