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

Subversion Repositories qaz_libs

[/] [qaz_libs/] [trunk/] [BFM/] [src/] [axis_video_frame/] [axis_video_frame_bfm_pkg.sv] - Rev 34

Go to most recent revision | 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)
          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

Go to most recent revision | 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.