URL
https://opencores.org/ocsvn/qaz_libs/qaz_libs/trunk
Subversion Repositories qaz_libs
Compare Revisions
- This comparison shows the changes necessary to convert path
/qaz_libs/trunk/BFM/src/axis_video_frame
- from Rev 50 to Rev 49
- ↔ Reverse comparison
Rev 50 → Rev 49
/axis_video_frame_bfm_pkg.sv
0,0 → 1,617
////////////////////////////////////////////////////////////////////// |
//// //// |
//// 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 |
|
/avf_agent_class_pkg.sv
0,0 → 1,166
////////////////////////////////////////////////////////////////////// |
//// //// |
//// 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 avf_agent_class_pkg; |
|
// -------------------------------------------------------------------- |
// |
import video_frame_pkg::*; |
import axis_video_frame_bfm_pkg::*; |
|
|
// -------------------------------------------------------------------- |
// |
class avf_agent_class #(BYTES_PER_PIXEL, OUTPUTS_PER_TILE = 1, AVF_U = 3); |
|
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 |
|
virtual axis_if #(.N(AVF_N), .U(AVF_U)) avf_axis_in_if[]; |
virtual axis_if #(.N(AVF_N), .U(AVF_U)) avf_axis_out_if[]; |
|
avf_config_class c_h; |
|
avf_tx_class #(BYTES_PER_PIXEL, OUTPUTS_PER_TILE, AVF_U) tx_h; |
avf_rx_class #(BYTES_PER_PIXEL, OUTPUTS_PER_TILE, AVF_U) rx_h; |
|
video_frame_class clone_h; |
video_frame_class sent_f_h; |
video_frame_class rx_f_h; |
|
mailbox #(video_frame_class) q[]; |
|
|
// -------------------------------------------------------------------- |
// |
virtual task |
queue_frame |
( |
string pattern = "", |
int pixel = 0 |
); |
|
if(pattern != "") |
tx_h.make_frame(pattern, pixel); |
|
foreach(tx_h.tx_bfm_h[i]) |
begin |
clone_h = tx_h.tx_bfm_h[i].f_h.clone(); |
tx_h.tx_bfm_h[i].put(clone_h); |
q[i].put(clone_h); |
end |
|
$display("^^^ %16.t | %m | using %s pattern", $time, pattern); |
|
endtask: queue_frame |
|
|
// -------------------------------------------------------------------- |
// |
virtual task automatic |
compare_frame; |
|
int mismatch_count; |
|
$display("^^^ %16.t | %m", $time); |
|
foreach(rx_h.rx_bfm_h[i]) |
begin |
q[i].get(sent_f_h); |
rx_h.rx_bfm_h[i].get(rx_f_h); |
mismatch_count = sent_f_h.compare(8, rx_f_h); |
end |
|
endtask: compare_frame |
|
|
// -------------------------------------------------------------------- |
// |
virtual task set_tready(input tready); |
$display("^^^ %16.t | %m", $time); |
foreach(rx_h.rx_bfm_h[i]) |
rx_h.rx_bfm_h[i].set_tready(tready); |
endtask: set_tready |
|
|
// -------------------------------------------------------------------- |
// |
virtual task flush_sent_frame; |
$display("^^^ %16.t | %m", $time); |
foreach(rx_h.rx_bfm_h[i]) |
q[i].get(sent_f_h); |
endtask: flush_sent_frame |
|
|
// -------------------------------------------------------------------- |
// |
virtual task rx_flush_frame; |
$display("^^^ %16.t | %m", $time); |
foreach(rx_h.rx_bfm_h[i]) |
rx_h.rx_bfm_h[i].get(rx_f_h); |
endtask: rx_flush_frame |
|
|
//-------------------------------------------------------------------- |
// |
function void init(avf_config_class c_h); |
|
rx_h = new(c_h, avf_axis_in_if); |
tx_h = new(c_h, avf_axis_out_if); |
|
this.q = new[$size(avf_axis_out_if)]; |
foreach(q[i]) |
this.q[i] = new(); |
|
endfunction: init |
|
|
//-------------------------------------------------------------------- |
// |
function new |
( |
virtual axis_if #(.N(AVF_N), .U(AVF_U)) avf_axis_in_if[], |
virtual axis_if #(.N(AVF_N), .U(AVF_U)) avf_axis_out_if[] |
); |
|
this.avf_axis_in_if = avf_axis_in_if; |
this.avf_axis_out_if = avf_axis_out_if; |
endfunction: new |
|
|
// -------------------------------------------------------------------- |
// |
|
endclass: avf_agent_class |
|
endpackage: avf_agent_class_pkg |
|
|
|
|
|
/avf_agent.sv
0,0 → 1,105
////////////////////////////////////////////////////////////////////// |
//// //// |
//// 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 //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
|
|
import axis_video_frame_bfm_pkg::*; |
|
module |
avf_agent |
#( |
BYTES_PER_PIXEL = 2, |
AVF_OUTPUTS = 4, |
AVF_TILES = 1, |
AVF_WIDTH = 32, |
AVF_HEIGHT = 16, |
AVF_BITS_PER_PIXEL = 16 |
) |
( |
axis_if axis_out[AVF_TILES], |
axis_if axis_in[AVF_TILES] |
); |
|
// -------------------------------------------------------------------- |
// |
axis_video_frame_bfm_class #(BYTES_PER_PIXEL, AVF_OUTPUTS) f_tx_h[AVF_TILES]; |
|
for(genvar j = 0; j < AVF_TILES; j++) |
initial |
begin |
f_tx_h[j] = new(axis_out[j]); |
|
f_tx_h[j].init |
( |
.avf_width(AVF_WIDTH), |
.avf_height(AVF_HEIGHT), |
.avf_bits_per_pixel(AVF_BITS_PER_PIXEL), |
.avf_name($psprintf("AVF_%0d", j)), |
.avf_type("TX") |
); |
end |
|
|
// -------------------------------------------------------------------- |
// |
axis_video_frame_bfm_class #(BYTES_PER_PIXEL, AVF_OUTPUTS) f_rx_h[AVF_TILES]; |
|
for(genvar j = 0; j < AVF_TILES; j++) |
initial |
begin |
f_rx_h[j] = new(axis_in[j]); |
|
f_rx_h[j].init |
( |
.avf_width(AVF_WIDTH), |
.avf_height(AVF_HEIGHT), |
.avf_bits_per_pixel(AVF_BITS_PER_PIXEL), |
.avf_name($psprintf("AVF_%0d", j)), |
.avf_type("RX") |
); |
end |
|
|
// -------------------------------------------------------------------- |
// |
avf_tx #(BYTES_PER_PIXEL, AVF_OUTPUTS, AVF_TILES) |
avf_tx_bfm(.*); |
|
|
// -------------------------------------------------------------------- |
// |
avf_rx #(BYTES_PER_PIXEL, AVF_OUTPUTS, AVF_TILES) |
avf_rx_bfm(.*); |
|
|
// -------------------------------------------------------------------- |
// |
|
endmodule |
|
|
|
|
/avf_rx.sv
0,0 → 1,134
////////////////////////////////////////////////////////////////////// |
//// //// |
//// 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 //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
|
import axis_video_frame_bfm_pkg::*; |
|
module |
avf_rx |
#( |
BYTES_PER_PIXEL = 2, |
AVF_OUTPUTS = 4, |
AVF_TILES = 1 |
) |
( |
ref axis_video_frame_bfm_class f_tx_h[AVF_TILES], |
ref axis_video_frame_bfm_class f_rx_h[AVF_TILES] |
); |
|
// -------------------------------------------------------------------- |
// |
localparam AVF_VERTICAL_BLANKING = 20; |
|
task automatic |
init_avf_rx; |
|
f_rx_h[0].run_rx_q(RIGHT_DOWN); |
f_rx_h[1].run_rx_q(RIGHT_UP); |
f_rx_h[2].run_rx_q(LEFT_DOWN); |
f_rx_h[3].run_rx_q(LEFT_UP); |
|
endtask: init_avf_rx |
|
|
// -------------------------------------------------------------------- |
// |
task |
wait_for_rx_frames |
( |
input int unsigned count |
); |
|
repeat(count) |
@(f_rx_h[0].rx_frame_done); |
|
endtask: wait_for_rx_frames |
|
|
// -------------------------------------------------------------------- |
// |
semaphore get_frame_semaphore = new(1); |
logic get_frame_active = 0; |
|
task automatic |
get_frame; |
|
if(get_frame_semaphore.try_get() == 0) |
begin |
$display("^^^ %16.t | %m | ERROR! Already getting a frame.", $time); |
return; |
end |
|
$display("^^^ %16.t | %m | getting a frame.", $time); |
get_frame_active = 1; |
|
fork |
begin |
|
f_rx_h[0].avf_fork_rx(RIGHT_DOWN); |
f_rx_h[1].avf_fork_rx(RIGHT_UP); |
f_rx_h[2].avf_fork_rx(LEFT_DOWN); |
f_rx_h[3].avf_fork_rx(LEFT_UP); |
|
wait fork; |
get_frame_active = 0; |
$display("^^^ %16.t | %m | Got a frame.", $time); |
get_frame_semaphore.put(); |
|
end |
join_none |
|
|
endtask: get_frame |
|
|
// -------------------------------------------------------------------- |
// |
import video_frame_pkg::*; |
|
function automatic |
int compare_frame; |
|
int mismatch_count[AVF_TILES]; |
|
$display("^^^ %16.t | %m", $time); |
|
foreach(f_rx_h[i]) |
mismatch_count[i] = f_rx_h[i].f_h.compare(8, f_tx_h[i].f_h); |
|
|
endfunction: compare_frame |
|
|
// -------------------------------------------------------------------- |
// |
|
|
endmodule |
|
|
|
|
/avf_tx.sv
0,0 → 1,171
////////////////////////////////////////////////////////////////////// |
//// //// |
//// 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 //// |
//// //// |
////////////////////////////////////////////////////////////////////// |
|
|
import axis_video_frame_bfm_pkg::*; |
|
module |
avf_tx |
#( |
BYTES_PER_PIXEL = 2, |
AVF_OUTPUTS = 4, |
AVF_TILES = 1 |
) |
( |
ref axis_video_frame_bfm_class f_tx_h[AVF_TILES], |
ref axis_video_frame_bfm_class f_rx_h[AVF_TILES] |
); |
|
// -------------------------------------------------------------------- |
// |
localparam AVF_VERTICAL_BLANKING = 20; |
|
task automatic |
init_avf_tx; |
|
foreach(f_tx_h[i]) |
f_tx_h[i].avf_vertical_blanking = AVF_VERTICAL_BLANKING; |
|
f_tx_h[0].run_tx_q(RIGHT_DOWN, 0); |
f_tx_h[1].run_tx_q(RIGHT_UP, 0); |
f_tx_h[2].run_tx_q(LEFT_DOWN, 0); |
f_tx_h[3].run_tx_q(LEFT_UP, 0); |
|
endtask: init_avf_tx |
|
|
// -------------------------------------------------------------------- |
// |
import video_frame_pkg::*; |
|
video_frame_class clone_h; |
|
|
// -------------------------------------------------------------------- |
// |
task automatic |
make_frame |
( |
string pattern, |
int pixel = 0 |
); |
|
case(pattern.tolower) |
"constant": foreach(f_tx_h[i]) f_tx_h[i].f_h.make_constant(pixel); |
"counting": foreach(f_tx_h[i]) f_tx_h[i].f_h.make_counting(); |
"horizontal": foreach(f_tx_h[i]) f_tx_h[i].f_h.make_horizontal(); |
"vertical": foreach(f_tx_h[i]) f_tx_h[i].f_h.make_vertical(); |
"random": foreach(f_tx_h[i]) f_tx_h[i].f_h.make_random(); |
default: $display("^^^ %16.t | %m | ERROR! %s pattern not supported", $time, pattern); |
endcase |
|
endtask: make_frame |
|
|
// -------------------------------------------------------------------- |
// |
|
task automatic |
queue_frame |
( |
string pattern = "" |
); |
|
if(pattern != "") |
make_frame(pattern); |
|
foreach(f_tx_h[i]) |
begin |
clone_h = f_tx_h[i].f_h.clone(); |
f_tx_h[i].avf_q.put(clone_h); |
f_rx_h[i].avf_q.put(clone_h); |
end |
|
$display("^^^ %16.t | %m | using %s pattern", $time, pattern); |
|
endtask: queue_frame |
|
|
// -------------------------------------------------------------------- |
// |
task |
wait_for_tx_frames |
( |
input int unsigned count |
); |
|
repeat(count) |
@(f_tx_h[0].tx_frame_done); |
|
endtask: wait_for_tx_frames |
|
|
// -------------------------------------------------------------------- |
// |
logic put_frame_active = 0; |
semaphore put_frame_semaphore = new(1); |
|
task automatic |
put_frame; |
|
if(put_frame_semaphore.try_get() == 0) |
begin |
$display("^^^ %16.t | %m | ERROR! Already put a frame.", $time); |
return; |
end |
|
$display("^^^ %16.t | %m | Putting a frame.", $time); |
put_frame_active = 1; |
|
fork |
begin |
|
f_tx_h[0].avf_fork_tx(RIGHT_DOWN, 0); |
f_tx_h[1].avf_fork_tx(RIGHT_UP, 0); |
f_tx_h[2].avf_fork_tx(LEFT_DOWN, 0); |
f_tx_h[3].avf_fork_tx(LEFT_UP, 0); |
|
wait fork; |
put_frame_active = 0; |
$display("^^^ %16.t | %m | Put a frame.", $time); |
put_frame_semaphore.put(); |
|
end |
join_none |
|
endtask: put_frame |
|
|
// -------------------------------------------------------------------- |
// |
|
|
endmodule |
|
|
|
|