URL
https://opencores.org/ocsvn/qaz_libs/qaz_libs/trunk
Subversion Repositories qaz_libs
[/] [qaz_libs/] [trunk/] [BFM/] [src/] [axis_video_frame/] [legacy/] [axis_video_frame_bfm_pkg.sv] - Rev 45
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 axis_video_frame_bfm_pkg;
typedef enum
{
RIGHT_DOWN,
RIGHT_UP,
LEFT_DOWN,
LEFT_UP
} avf_direction_t;
typedef struct
{
avf_direction_t direction;
int delay = 0;
} avf_tile_config_t;
// --------------------------------------------------------------------
//
import q_pkg::*;
import video_frame_pkg::*;
// --------------------------------------------------------------------
//
class avf_config_class;
int width;
int height;
int bytes_per_pixel;
int bits_per_pixel;
int pixels_per_clk;
string name;
int vertical_blanking;
avf_tile_config_t tile[];
//--------------------------------------------------------------------
function
new
(
int width,
int height,
int bytes_per_pixel,
int bits_per_pixel,
int pixels_per_clk,
string name,
int vertical_blanking,
avf_tile_config_t tile[]
);
this.width = width;
this.height = height;
this.bytes_per_pixel = bytes_per_pixel;
this.bits_per_pixel = bits_per_pixel;
this.pixels_per_clk = pixels_per_clk;
this.name = name;
this.vertical_blanking = vertical_blanking;
this.tile = tile;
$display("^^^ %16.t | %m", $time);
endfunction: new
// --------------------------------------------------------------------
//
task automatic
avf_direction
(
input avf_direction_t direction,
output frame_coordinate_t inc
);
case(direction)
RIGHT_DOWN: inc = '{ 1, 1};
RIGHT_UP: inc = '{ 1, -1};
LEFT_DOWN: inc = '{-1, 1};
LEFT_UP: inc = '{-1, -1};
default: $display("^^^ %16.t | %m | ERROR!!! Incorrect AVF direction.", $time );
endcase
endtask: avf_direction
// --------------------------------------------------------------------
//
task automatic
avf_calculate
(
input avf_direction_t direction,
output frame_coordinate_t start,
output frame_coordinate_t inc,
output int x_end,
output int y_end,
output int x_eol
);
case(direction)
RIGHT_DOWN: start = '{0 , 0 };
RIGHT_UP: start = '{0 , height - 1 };
LEFT_DOWN: start = '{width - 1 , 0 };
LEFT_UP: start = '{width - 1 , height - 1 };
default: $display("^^^ %16.t | %m | [%04d, %04d] | ERROR!!! Incorrect AVF direction.", $time, start.x, start.y );
endcase
avf_direction(direction, inc);
x_end = (start.x + (width * inc.x));
y_end = (start.y + (height * inc.y));
inc.x *= pixels_per_clk; // increment stride by number of outputs
x_eol = x_end - inc.x;
endtask: avf_calculate
endclass: avf_config_class
//--------------------------------------------------------------------
//
class avf_tx_bfm_class #(BYTES_PER_PIXEL, PIXELS_PER_CLK, AVF_U)
extends blocking_transmission_q_class #(video_frame_class);
localparam AVF_N = BYTES_PER_PIXEL * PIXELS_PER_CLK; // data bus width in bytes
localparam AVF_B = BYTES_PER_PIXEL * 8; // bits per pixel on TDATA
virtual axis_if #(.N(AVF_N), .U(AVF_U)) avf_axis_if;
string avf_name = "";
string avf_type = "";
avf_config_class c_h;
avf_tile_config_t tile;
video_frame_class f_h;
// --------------------------------------------------------------------
//
function void axis_default;
avf_axis_if.cb_m.tvalid <= 0;
avf_axis_if.cb_m.tdata <= 'hx;
avf_axis_if.cb_m.tlast <= 'hx;
avf_axis_if.cb_m.tuser <= 'hx;
endfunction: axis_default
// --------------------------------------------------------------------
//
task automatic
output_pixels(input int l, input int p);
for(int i = 0; i < PIXELS_PER_CLK; i++)
avf_axis_if.cb_m.tdata[i*AVF_B +: AVF_B] <= f_h.lines[l].pixel[p + i];
endtask: output_pixels
// --------------------------------------------------------------------
//
task automatic
avf_tx(input avf_direction_t direction, input int unsigned avf_delay);
frame_coordinate_t start;
frame_coordinate_t inc;
int x_end;
int y_end;
int x_eol;
int pixel_count = 0;
int l;
int p;
c_h.avf_calculate
(
.start(start),
.direction(direction),
.inc(inc),
.x_end(x_end),
.y_end(y_end),
.x_eol(x_eol)
);
@(avf_axis_if.cb_m);
repeat(avf_delay) @(avf_axis_if.cb_m);
avf_axis_if.cb_m.tvalid <= 1; // assert first pixel
avf_axis_if.cb_m.tuser[0] <= 1;
avf_axis_if.cb_m.tuser[1] <= 1;
avf_axis_if.cb_m.tuser[2] <= 0;
avf_axis_if.cb_m.tlast <= 0;
output_pixels(start.y, start.x);
for(l = start.y; y_end != l; l = l + inc.y)
for(p = start.x; x_end != p; p = p + inc.x)
begin
if((l == start.y) & (p == start.x)) // first pixel already asserted
continue;
@(avf_axis_if.cb_m iff avf_axis_if.cb_m.tready)
begin
avf_axis_if.cb_m.tvalid <= 1;
output_pixels(l, p);
avf_axis_if.cb_m.tuser[0] <= 0;
if(p == start.x)
avf_axis_if.cb_m.tuser[1] <= 1;
else
avf_axis_if.cb_m.tuser[1] <= 0;
if(p == x_eol)
avf_axis_if.cb_m.tlast <= 1;
else
avf_axis_if.cb_m.tlast <= 0;
if((l == y_end - 1) && (p == x_eol))
avf_axis_if.cb_m.tuser[2] <= 1;
end
end
@(avf_axis_if.cb_m);
wait(avf_axis_if.cb_m.tready);
axis_default();
endtask: avf_tx
// --------------------------------------------------------------------
//
task
avf_fork_tx;
fork
avf_tx(tile.direction, tile.delay);
join_none
#0;
endtask: avf_fork_tx
// --------------------------------------------------------------------
//
event tx_frame_done;
task automatic
transmit(ref Q_T tr_h);
f_h = tr_h;
avf_fork_tx();
wait fork;
repeat(c_h.vertical_blanking) @(avf_axis_if.cb_m);
->tx_frame_done;
endtask: transmit
//--------------------------------------------------------------------
//
function
new
(
int index,
avf_config_class c_h,
input string avf_type,
virtual axis_if #(.N(AVF_N), .U(AVF_U)) avf_axis_if
);
super.new();
this.avf_axis_if = avf_axis_if;
this.c_h = c_h;
this.tile = c_h.tile[index];
this.avf_name = $sformatf("%s%0d", c_h.name, index);
this.avf_type = avf_type.toupper();
f_h = new();
f_h.init
(
.pixels_per_line(c_h.width),
.lines_per_frame(c_h.height),
.bits_per_pixel(c_h.bits_per_pixel),
.name(avf_name)
);
axis_default();
endfunction: new
// --------------------------------------------------------------------
//
endclass: avf_tx_bfm_class
//--------------------------------------------------------------------
//
class avf_rx_bfm_class #(BYTES_PER_PIXEL, PIXELS_PER_CLK, AVF_U)
extends blocking_receiver_q_class #(video_frame_class);
localparam AVF_N = BYTES_PER_PIXEL * PIXELS_PER_CLK; // data bus width in bytes
localparam AVF_B = BYTES_PER_PIXEL * 8; // bits per pixel on TDATA
virtual axis_if #(.N(AVF_N), .U(AVF_U)) avf_axis_if;
string avf_name = "";
string avf_type = "";
avf_config_class c_h;
avf_tile_config_t tile;
video_frame_class f_h;
// --------------------------------------------------------------------
//
function void axis_default;
avf_axis_if.cb_s.tready <= 1;
endfunction: axis_default
// --------------------------------------------------------------------
//
task automatic
set_tready(input tready);
avf_axis_if.cb_s.tready <= tready;
endtask: set_tready
// --------------------------------------------------------------------
//
task automatic
avf_rx(input avf_direction_t direction);
frame_coordinate_t start;
frame_coordinate_t inc;
int x_end;
int y_end;
int x_eol;
int pixel_count = 0;
int l;
int p;
c_h.avf_calculate
(
.start(start),
.direction(direction),
.inc(inc),
.x_end(x_end),
.y_end(y_end),
.x_eol(x_eol)
);
wait(avf_axis_if.cb_s.tuser[0] & avf_axis_if.cb_s.tvalid & avf_axis_if.cb_m.tready);
for(l = start.y; y_end != l; l = l + inc.y)
for(p = start.x; x_end != p; p = p + inc.x)
begin
wait(avf_axis_if.cb_s.tvalid & avf_axis_if.cb_m.tready);
for(int i = 0; i < PIXELS_PER_CLK; i++)
f_h.lines[l].pixel[p + i] = avf_axis_if.cb_s.tdata[i*AVF_B +: AVF_B];
if(p == x_eol)
if(~avf_axis_if.cb_s.tlast)
$display("^^^ %16.t | %m | [%04d, %04d] | %s_%s | ERROR! x_eol without tlast | x_eol = %04d | 0x%06x", $time, p, l, avf_name, avf_type, x_eol, f_h.lines[l].pixel[p]);
if(avf_axis_if.cb_s.tlast)
if(p != x_eol)
$display("^^^ %16.t | %m | [%04d, %04d] | %s_%s | ERROR! tlast without x_eol | x_eol = %04d | 0x%06x", $time, p, l, avf_name, avf_type, x_eol, f_h.lines[l].pixel[p]);
@(avf_axis_if.cb_s);
end
endtask: avf_rx
// --------------------------------------------------------------------
//
task automatic
avf_fork_rx;
fork
avf_rx(tile.direction);
join_none
#0;
endtask: avf_fork_rx
// --------------------------------------------------------------------
//
event rx_frame_done;
virtual task
receive(ref Q_T tr_h);
avf_fork_rx();
wait fork;
tr_h = f_h.clone();
->rx_frame_done;
endtask: receive
//--------------------------------------------------------------------
//
function
new
(
int index,
avf_config_class c_h,
input string avf_type,
virtual axis_if #(.N(AVF_N), .U(AVF_U)) avf_axis_if
);
super.new();
this.avf_axis_if = avf_axis_if;
this.c_h = c_h;
this.tile = c_h.tile[index];
this.avf_name = $sformatf("%s%0d", c_h.name, index);
this.avf_type = avf_type.toupper();
f_h = new();
f_h.init
(
.pixels_per_line(c_h.width),
.lines_per_frame(c_h.height),
.bits_per_pixel(c_h.bits_per_pixel),
.name(avf_name)
);
axis_default();
endfunction: new
// --------------------------------------------------------------------
//
endclass: avf_rx_bfm_class
// --------------------------------------------------------------------
//
class avf_tx_class #(BYTES_PER_PIXEL, OUTPUTS_PER_TILE, AVF_U);
localparam AVF_N = BYTES_PER_PIXEL * OUTPUTS_PER_TILE; // data bus width in bytes
localparam AVF_B = BYTES_PER_PIXEL * 8; // bits per pixel on TDATA
int number_of_tx_tiles;
virtual axis_if #(.N(AVF_N), .U(AVF_U)) avf_axis_out_if[];
avf_tx_bfm_class #(BYTES_PER_PIXEL, OUTPUTS_PER_TILE, AVF_U) tx_bfm_h[];
video_frame_class clone_h;
// --------------------------------------------------------------------
//
virtual task automatic
make_frame
(
string pattern,
int pixel = 0
);
case(pattern.tolower)
"constant": foreach(tx_bfm_h[i]) tx_bfm_h[i].f_h.make_constant(pixel);
"counting": foreach(tx_bfm_h[i]) tx_bfm_h[i].f_h.make_counting();
"horizontal": foreach(tx_bfm_h[i]) tx_bfm_h[i].f_h.make_horizontal();
"vertical": foreach(tx_bfm_h[i]) tx_bfm_h[i].f_h.make_vertical();
"random": foreach(tx_bfm_h[i]) tx_bfm_h[i].f_h.make_random();
default: $display("^^^ %16.t | %m | ERROR! %s pattern not supported", $time, pattern);
endcase
endtask: make_frame
// --------------------------------------------------------------------
//
virtual task
wait_for_tx_frames
(
input int unsigned count
);
repeat(count)
@(tx_bfm_h[0].tx_frame_done);
endtask: wait_for_tx_frames
//--------------------------------------------------------------------
//
function new
(
avf_config_class c_h,
virtual axis_if #(.N(AVF_N), .U(AVF_U)) avf_axis_out_if[]
);
this.number_of_tx_tiles = $size(avf_axis_out_if);
this.avf_axis_out_if = avf_axis_out_if;
this.tx_bfm_h = new[number_of_tx_tiles];
foreach(tx_bfm_h[i])
tx_bfm_h[i] = new(i, c_h, "TX", avf_axis_out_if[i]);
endfunction: new
// --------------------------------------------------------------------
//
endclass: avf_tx_class
// --------------------------------------------------------------------
//
class avf_rx_class #(BYTES_PER_PIXEL, OUTPUTS_PER_TILE, AVF_U);
localparam AVF_N = BYTES_PER_PIXEL * OUTPUTS_PER_TILE; // data bus width in bytes
localparam AVF_B = BYTES_PER_PIXEL * 8; // bits per pixel on TDATA
int number_of_rx_tiles;
virtual axis_if #(.N(AVF_N), .U(AVF_U)) avf_axis_in_if[];
avf_rx_bfm_class #(BYTES_PER_PIXEL, OUTPUTS_PER_TILE, AVF_U) rx_bfm_h[];
video_frame_class clone_h;
// --------------------------------------------------------------------
//
virtual task
wait_for_rx_frames
(
input int unsigned count
);
repeat(count)
@(rx_bfm_h[0].rx_frame_done);
endtask: wait_for_rx_frames
//--------------------------------------------------------------------
//
function new
(
avf_config_class c_h,
virtual axis_if #(.N(AVF_N), .U(AVF_U)) avf_axis_in_if[]
);
this.number_of_rx_tiles = $size(avf_axis_in_if);
this.avf_axis_in_if = avf_axis_in_if;
this.rx_bfm_h = new[number_of_rx_tiles];
foreach(rx_bfm_h[i])
rx_bfm_h[i] = new(i, c_h, "RX", avf_axis_in_if[i]);
endfunction: new
// --------------------------------------------------------------------
//
endclass: avf_rx_class
// --------------------------------------------------------------------
//
endpackage: axis_video_frame_bfm_pkg