OpenCores
URL https://opencores.org/ocsvn/qaz_libs/qaz_libs/trunk

Subversion Repositories qaz_libs

[/] [qaz_libs/] [trunk/] [basal/] [sim/] [src/] [fifo_bfm_pkg.sv] - Rev 34

Compare with Previous | Blame | View Log

//////////////////////////////////////////////////////////////////////
////                                                              ////
//// Copyright (C) 2015 Authors and OPENCORES.ORG                 ////
////                                                              ////
//// This source file may be used and distributed without         ////
//// restriction provided that this copyright statement is not    ////
//// removed from the file and that any derivative work contains  ////
//// the original copyright notice and the associated disclaimer. ////
////                                                              ////
//// This source file is free software; you can redistribute it   ////
//// and/or modify it under the terms of the GNU Lesser General   ////
//// Public License as published by the Free Software Foundation; ////
//// either version 2.1 of the License, or (at your option) any   ////
//// later version.                                               ////
////                                                              ////
//// This source is distributed in the hope that it will be       ////
//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
//// PURPOSE.  See the GNU Lesser General Public License for more ////
//// details.                                                     ////
////                                                              ////
//// You should have received a copy of the GNU Lesser General    ////
//// Public License along with this source; if not, download it   ////
//// from http://www.opencores.org/lgpl.shtml                     ////
////                                                              ////
//////////////////////////////////////////////////////////////////////


package fifo_bfm_pkg;

  typedef enum
  {
    SOURCE,
    SINK,
    BOTH
  } fifo_type_t;

  // --------------------------------------------------------------------
  //
  class fifo_transaction_class;

    rand int data;
    rand int write_delay = 0;
    rand int read_delay = 0;

    constraint default_write_delay
    {
      write_delay >= 0 && write_delay <= 4;
      write_delay dist {0 := 60, [1:4] :=40 };
    }

    constraint default_read_delay
    {
      read_delay >= 0 && read_delay <= 4;
      read_delay dist {0 := 60, [1:4] :=40 };
    }


    // --------------------------------------------------------------------
    //
    function void copy
    (
      ref fifo_transaction_class from
    );

      // $display("^^^ %16.t | %m", $time);

      this.data         = from.data;
      this.write_delay  = from.write_delay;
      this.read_delay   = from.read_delay;

    endfunction: copy


    // --------------------------------------------------------------------
    //
    extern virtual function fifo_transaction_class clone();
    // virtual function fifo_transaction_class clone();

      // $display("^^^ %16.t | %m", $time);

      // clone = new();
      // clone.copy(this);
      // return(clone);

    // endfunction: clone


    // --------------------------------------------------------------------
    //

  endclass: fifo_transaction_class


  // --------------------------------------------------------------------
  //
  function fifo_transaction_class fifo_transaction_class::clone();

    // $display("^^^ %16.t | %m", $time);

    clone = new();
    clone.copy(this);

  endfunction: clone


  // --------------------------------------------------------------------
  //
  class fifo_bfm_class #(W = 8);

    string      fifo_name;
    fifo_type_t fifo_type;

    virtual fifo_write_if   #(.W(W)) source = null;
    virtual fifo_read_if    #(.W(W)) sink = null;
    fifo_transaction_class  fifo_tr = new();


    //--------------------------------------------------------------------
    function new
      (
        virtual fifo_write_if #(.W(W)) source = null,
        virtual fifo_read_if  #(.W(W)) sink = null
      );

      if(source != null)
        this.source = source;

      if(sink != null)
        this.sink   = sink;

    endfunction: new


    // --------------------------------------------------------------------
    //
    function void
      init
      (
        input string      fifo_name,
        input fifo_type_t fifo_type
      );

      this.fifo_name  = fifo_name;
      this.fifo_type  = fifo_type;

      if(fifo_type == SOURCE)
        source.cb_s.wr_en <= 0;
      else if(fifo_type == SINK)
        sink.cb_s.rd_en   <= 0;
      else if(fifo_type == BOTH)
        if((this.source == null) | (this.sink == null))
        begin
          $display("^^^ %16.t | %m | ERROR! %s fifo_type == BOTH with null class", $time, fifo_type.name);
          $stop;
        end
        else
        begin
          source.cb_s.wr_en <= 0;
          sink.cb_s.rd_en   <= 0;
        end
      else
      begin
        $display("^^^ %16.t | %m | ERROR! fifo_type %s is invalid", $time, fifo_type.name);
        $stop;
      end

      $display("^^^ %16.t | %m | initialization of %s for %s", $time, fifo_name, fifo_type.name);

    endfunction: init


    // --------------------------------------------------------------------
    //
    task
      write
      (
        input [W-1:0] wr_data,
        input int write_delay = 0
      );

        source.cb_s.wr_data <= wr_data;
        source.cb_s.wr_en <= 0;

        source.zero_cycle_delay();

        if(write_delay != 0)
          repeat(write_delay) @(source.cb_s);

        @(source.cb_s iff (source.cb_s.full == 0));
        // @(source.cb_s iff (~source.cb_s.full));
        source.cb_s.wr_en <= 1;

        @(posedge source.clk);
        source.cb_s.wr_en <= 0;

    endtask: write


    // --------------------------------------------------------------------
    //
    task
      fork_write
      (
        input [W-1:0] wr_data,
        input int write_delay = 0
      );

      fork
        write(wr_data, write_delay);
      join_none

      #0;

    endtask: fork_write


    // --------------------------------------------------------------------
    //
    mailbox #(int) rd_data_q  = new();

    task
      read
      (
        input int read_delay = 0
      );

        sink.cb_s.rd_en <= 0;

        sink.zero_cycle_delay();

        if(read_delay != 0)
          repeat(read_delay) @(sink.cb_s);

        @(sink.cb_s iff (sink.cb_s.empty == 0));
        // @(sink.cb_s iff (~sink.cb_s.empty));
        sink.cb_s.rd_en <= 1;

        @(posedge sink.clk);

        sink.cb_s.rd_en <= 0;

        rd_data_q.put(sink.cb_s.rd_data);

    endtask: read


    // --------------------------------------------------------------------
    //
    task automatic
      fork_read
      (
        input int read_delay = 0
      );

      fork
        read(read_delay);
      join_none

      #0;

    endtask: fork_read


    // --------------------------------------------------------------------
    //
    mailbox #(fifo_transaction_class) fifo_tr_q;
    semaphore                         fifo_tr_q_semaphore = new(1);


    // --------------------------------------------------------------------
    //
    event fifo_write_done;

    task automatic
      fifo_write_q;

        if((fifo_type != SOURCE) & (fifo_type == BOTH))
        begin
          $display("^^^ %16.t | %m | ERROR! wrong fifo_type |", $time);
          return;
        end

        if(fifo_tr_q_semaphore.try_get() == 0)
        begin
          $display("^^^ %16.t | %m | ERROR! fifo_tr_q_semaphore.try_get() == 0 |", $time);
          return;
        end

        $display("^^^ %16.t | %m is active |", $time);

        this.fifo_tr_q = new();

        fifo_write_fork : fork
          forever
          begin

            fifo_tr_q.get(fifo_tr);
            fork_write(fifo_tr.data, fifo_tr.write_delay);

            wait fork;

            ->fifo_write_done;
          end
        join_none

        #0;

    endtask: fifo_write_q


    // --------------------------------------------------------------------
    //
    fifo_transaction_class  fifo_tr_clone;
    event                   fifo_read_done;
    logic [W - 1:0]         rd_data;
    logic [W - 1:0]         rd_result;
    int                     compare_result;
    int                     compare_errors = 0;

    task automatic
      fifo_read_q;

        if((fifo_type != SINK) & (fifo_type == BOTH))
        begin
          $display("^^^ %16.t | %m | ERROR! wrong fifo_type |", $time);
          return;
        end


        if(fifo_tr_q_semaphore.try_get() == 0)
        begin
          $display("^^^ %16.t | %m | ERROR! fifo_tr_q_semaphore.try_get() == 0 |", $time);
          return;
        end

        $display("^^^ %16.t | %m is active |", $time);

        this.fifo_tr_q  = new();
        fifo_tr_clone   = fifo_tr.clone();

        fifo_read_q_fork : fork
          forever
          begin

            fifo_tr_q.get(fifo_tr);
            fork_read(fifo_tr.read_delay);

            wait fork;

            ->fifo_read_done;

            rd_data_q.get(rd_result);
            rd_data = fifo_tr.data;

            if(rd_result != rd_data)
            begin
              $display("^^^ %16.t | %m | ERROR! rd_result != fifo_tr.data |", $time);
              $display("^^^ %16.t | %m | rd_result = %h |", $time, rd_result);
              $display("^^^ %16.t | %m | fifo_tr.data = %h |", $time, fifo_tr.data);
            end

            // compare_result = avf_in_frame.compare(8, f_h);
            // compare_errors += compare_result;

          end
        join_none

        #0;

    endtask: fifo_read_q


    // --------------------------------------------------------------------
    //

  endclass: fifo_bfm_class

endpackage: fifo_bfm_pkg

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

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