URL
https://opencores.org/ocsvn/qaz_libs/qaz_libs/trunk
Subversion Repositories qaz_libs
[/] [qaz_libs/] [trunk/] [basal/] [sim/] [src/] [legacy/] [fifo_bfm_pkg.sv] - Rev 50
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