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

Subversion Repositories qaz_libs

[/] [qaz_libs/] [trunk/] [axi4_lib/] [sim/] [src/] [axi4_models/] [axi4_memory_pkg.sv] - Rev 31

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 axi4_memory_pkg;

  // --------------------------------------------------------------------
  //
  import axi4_models_pkg::*;
  import bfm_pkg::*;
  import logger_pkg::*;


  // --------------------------------------------------------------------
  //
  class memory_tr_class #(A, N, I, type WORD_T = byte)
    extends transaction_class #(memory_tr_class #(A, N, I));

    rand int addr;
    rand int size;
    rand byte data[];

    constraint default_addr
    {
      addr[$clog2(N*8)-1:0] == 0;
    }

    constraint default_size
    {
      size dist {N := 40, [N*2:N*15] := 40, [N*16:N*255] := 20};
    }


    //--------------------------------------------------------------------
    //
    function void init(int addr, int size);
      this.data = new[size];
      this.addr = addr;
      this.size = size;
    endfunction: init


    //--------------------------------------------------------------------
    //
    function void random(int addr, int size);
      this.data = new[size];
      assert(this.randomize() with
      {
        this.addr == addr;  // why not working?
        this.size == size;
      });
      this.addr = addr;
      this.size = size;
    endfunction: random


    // --------------------------------------------------------------------
    //
    task constant(int addr, int size, byte value[]);
      init(addr, size);
      this.data = new[size];
      for(int i = 0; i < size; i += value.size)
        foreach(value[k])
          data[i + k] = value[k];
    endtask: constant


    // --------------------------------------------------------------------
    //
    task automatic counting(int addr, int count);
      byte word[];
      int word_size = $bits(WORD_T) / 8; // word size in bytes
      init(addr, count * word_size);
      for(WORD_T i = 0; i < count; i++)
      begin
        word = {<< byte{i}};
        foreach(word[k])
          data[addr + (i * word_size) + k] = word[k];
      end
    endtask: counting


    // --------------------------------------------------------------------
    //
    function void copy(TR_T from);
      init(from.addr, from.size);
      this.data = new[from.size];
      foreach(from.data[i])
        this.data[i] = from.data[i];
    endfunction: copy


    //--------------------------------------------------------------------
    function new;
      a_word_t_mod_n: assert($bits(WORD_T) % 8 == 0) else $fatal;
    endfunction: new


  // --------------------------------------------------------------------
  //
  endclass: memory_tr_class


  // --------------------------------------------------------------------
  //
  class axi4_memory_class #(A, N, I, type WORD_T = byte)
    extends axi4_slave_model_class #(.A(A), .N(N), .I(I));

    logger_class log;
    byte memory [*];


    // --------------------------------------------------------------------
    //
    function void clear_all;
      memory.delete;
    endfunction: clear_all


    // --------------------------------------------------------------------
    //
    function void compare(memory_tr_class #(A, N, I, WORD_T) tr_h);
      foreach(tr_h.data[i])
        if(memory.exists(tr_h.addr + i))
        begin
          if(memory[tr_h.addr + i] != tr_h.data[i])
            log.error($sformatf("%m | 1 memory[0x%8.h] = 0x%2.h | 0x%2.h", tr_h.addr + i, memory[tr_h.addr + i], tr_h.data[i]));
        end
        else
          log.error($sformatf("%m | 2 memory[0x%8.h] = 0x%2.h | 0x%2.h", tr_h.addr + i, 'bx, tr_h.data[i]));
    endfunction: compare


    // --------------------------------------------------------------------
    //
    task display_memory(int offset, int count);
      for(int i = 0; i < count; i++)
        if(memory.exists(offset + i))
          $display("^^^ %16.t | %m | memory[0x%8.x] = 0x%2.x", $time, offset + i, memory[offset + i]);
        else
          $display("^^^ %16.t | %m | memory[0x%8.x] = 0x%2.x", $time, offset + i, 8'hxx);
    endtask: display_memory


    // --------------------------------------------------------------------
    //
    task constant_fill(int offset, int count, int value);
      for(int i = 0; i < count; i++)
        memory[offset + i] = value;
    endtask: constant_fill


    // --------------------------------------------------------------------
    //
    task counting_fill(int offset, int count);
      for(int i = 0; i < count; i++)
        memory[offset + i] = i;
    endtask: counting_fill


    // --------------------------------------------------------------------
    //
    task dump_words(int offset, ref byte data[]);
      foreach(data[i])
        if(memory.exists(offset + i))
          data[i] = memory[offset + i];
        else
          data[i] = 'bx;
    endtask: dump_words


    // --------------------------------------------------------------------
    //
    function reg [7:0] dump(int offset);
      if(memory.exists(offset))
        return(memory[offset]);
      else
        return('bx);
    endfunction: dump


    // --------------------------------------------------------------------
    //
    task load_words(int offset, byte data[]);
      foreach(data[i])
        memory[offset + i] = data[i];
    endtask: load_words


    // --------------------------------------------------------------------
    //
    task load(int offset, reg [7:0] data);
      memory[offset] = data;
    endtask: load


    // --------------------------------------------------------------------
    //
    task run_read_interface;
      int result;
      logic [9:0] delay = 0;
      int memory_addr;

      forever
        @(axi4_s.cb_s)
        begin
          result = ar_q_h.q.try_peek(ar_if_h);
          if(result != 0)
          begin
            log.debug($sformatf("araddr = 0x%h", ar_if_h.araddr));
            log.debug($sformatf("arlen  = 0x%h", ar_if_h.arlen));
            delay = $urandom_range(9, 0);
            if(delay > 6)
              repeat($urandom_range(50, 1))
                @(axi4_s.cb_s);

            for(int i = 0; i < ar_if_h.arlen + 1; i++)
            begin
              memory_addr = ar_if_h.araddr + (i * (2 ** ar_if_h.arsize));
              for(int i = 0; i < ar_if_h.N; i++)
              begin
                if(memory.exists(memory_addr))
                  r_if_h.rdata[i*8 +: 8] = memory[memory_addr];
                else
                  r_if_h.rdata[i*8 +: 8] = 8'hxx;

                memory_addr++;
              end
              log.debug($sformatf("rdata  = 0x%h", r_if_h.rdata));

              if(i == ar_if_h.arlen)
              begin
                ar_q_h.q.get(ar_if_h);
                r_if_h.rlast = 1;
              end
              else
                r_if_h.rlast = 0;

              r_if_h.rid = 0;
              r_if_h.rresp = 0;

              r_q_h.q.put(r_if_h);
              r_if_h = new(axi4_s);

              @(axi4_s.cb_s);
            end
            r_if_h.rlast = 0;
          end
        end
    endtask: run_read_interface


    // --------------------------------------------------------------------
    //
    task run_write_interface;

      int result;
      logic [9:0] delay = 0;
      int memory_addr;

      forever
        @(axi4_s.cb_s)
        begin
          result = aw_q_h.q.try_peek(aw_if_h);
          if(result != 0)
          begin
            memory_addr = aw_if_h.awaddr;
            log.debug($sformatf("awaddr = 0x%h", aw_if_h.awaddr));

            delay = $urandom_range(9, 0);
            if(delay > 6)
              repeat($urandom_range(8, 1))
                @(axi4_s.cb_s);

            for(int i = 0; i < aw_if_h.awlen + 1; i++)
            begin
              w_q_h.q.get(w_if_h);
              log.debug($sformatf("wdata = 0x%h", w_if_h.wdata));
              for(int k = 0; k < aw_if_h.N; k++)
              begin
                memory[memory_addr] = w_if_h.wdata[k*8 +: 8];
                memory_addr++;
              end

              if(i == aw_if_h.awlen)
              begin
                b_if_h.bresp = 0;
                b_if_h.bid = aw_if_h.awid;
                b_q_h.q.put(b_if_h);
                b_if_h = new(axi4_s);
                aw_q_h.q.get(aw_if_h);
              end

              @(axi4_s.cb_s);
            end
          end
        end

    endtask: run_write_interface


    // --------------------------------------------------------------------
    //
    task run_model;
      wait(axi4_s.cb_s.aresetn);
      axi4_s.zero_cycle_delay();

      aw_q_h.run_q();
      w_q_h.run_q();
      b_q_h.run_q();
      ar_q_h.run_q();
      r_q_h.run_q();

      fork
        run_write_interface();
      join_none

      fork
        run_read_interface();
      join_none
    endtask: run_model


    //--------------------------------------------------------------------
    function new(virtual axi4_if  #(.A(A), .N(N), .I(I)) axi4_s);
      super.new(axi4_s);
      a_word_t_mod_n: assert($bits(WORD_T) % 8 == 0) else $fatal;
      this.aw_q_h = new(axi4_s, 2);
      this.w_q_h = new(axi4_s, 16);
      this.b_q_h = new(axi4_s, 2);
      this.ar_q_h = new(axi4_s, 2);
      this.r_q_h = new(axi4_s, 16);
      this.log = new();
    endfunction: new


  // --------------------------------------------------------------------
  //
  endclass: axi4_memory_class


// --------------------------------------------------------------------
//
endpackage: axi4_memory_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.