// (C) 2001-2025 Altera Corporation. All rights reserved.
// Your use of Altera Corporation's design tools, logic functions and other 
// software and tools, and its AMPP partner logic functions, and any output 
// files from any of the foregoing (including device programming or simulation 
// files), and any associated documentation or information are expressly subject 
// to the terms and conditions of the Altera Program License Subscription 
// Agreement, Altera IP License Agreement, or other applicable 
// license agreement, including, without limitation, that your use is for the 
// sole purpose of programming logic devices manufactured by Altera and sold by 
// Altera or its authorized distributors.  Please refer to the applicable 
// agreement for further details.


`default_nettype none
module intel_vvp_cvo_core
#(
  parameter DEVICE_FAMILY                           = "Agilex 7", // -- Cyclone 10 GX -- Arria 10 -- Stratix 10 -- Agilex
  parameter C_RAM_BLOCK_TYPE                        = "M20K",
  parameter C_VID_FIFO_DEPTH                        = 256,
  parameter C_TPG_FIFO_DEPTH                        = 256,
 
  parameter C_VID_IS_ASYNC                          = 0,
  parameter C_TPG_IS_ASYNC                          = 0,
  
  parameter C_VID_DIMENSIONS                        = 0,
  parameter C_TPG_DIMENSIONS                        = 0,
  parameter C_TIM_DIMENSIONS                        = 0,
  
  parameter C_VID_DEBUG                             = 0,
  parameter C_TPG_DEBUG                             = 0,
 
  parameter RUNTIME_CONTROL                         = 0,
  parameter C_CPU_OFFSET                            = 16,
  parameter CPU_CLK_FREQ_HZ                         = 100000000,
 
  parameter C_FALL_BACK_INPUT_EN                    = 1, // 0 = no extra input for fall back when main input stalls. 1 = enable extra input to be used when main input stalls
 
 
  parameter PIXELS_IN_PARALLEL                      = 4'd1, // at this stage, we assume the core input and output have the same number of PIP. As an extension, we could compose a core with a PIP converter.
  parameter NUMBER_OF_COLOR_PLANES                  = 3,
  parameter BPS                                     = 8,
 
  parameter C_DEFAULT_BLACK_0                       = 0,
  parameter C_DEFAULT_BLACK_1                       = 0,
  parameter C_DEFAULT_BLACK_2                       = 0,
  parameter C_DEFAULT_BLACK_3                       = 0
 
 
 
)
(
/////////////////////////////////////////////////////////////////////////
// cpu bus
//
cpu_clk,
cpu_rst,
av_address,
av_read,
av_readdata,
av_readdatavalid,
av_waitrequest,
av_write,
av_writedata,
av_byteenable,
 
//////////////////////////////////////////////////////
// main video input bus
// axi4-s vvp lite/full
vid_clk,
vid_rst,
axi4s_vid_in_tuser,
axi4s_vid_in_tdata,
axi4s_vid_in_tvalid,
axi4s_vid_in_tready,
axi4s_vid_in_tlast,
 
//////////////////////////////////////////////////////
// fall-back video input bus
// axi4-s vvp lite/full
tpg_clk,
tpg_rst,
axi4s_tpg_in_tuser,
axi4s_tpg_in_tdata,
axi4s_tpg_in_tvalid,
axi4s_tpg_in_tready,
axi4s_tpg_in_tlast,
 
//////////////////////////////////////////////////////
// fr timing-only input bus
// axi4-s vvp fr
fr_clk,
fr_rst,
axi4s_timing_in_tuser,
axi4s_timing_in_tdata,
axi4s_timing_in_tvalid,
axi4s_timing_in_tready,
axi4s_timing_in_tlast,
 
//////////////////////////////////////////////////////
// fr video+timing output bus
// axi4-s vvp fr
axi4s_fr_vid_out_tuser,
axi4s_fr_vid_out_tdata,
axi4s_fr_vid_out_tvalid,
axi4s_fr_vid_out_tready,
axi4s_fr_vid_out_tlast,
 
//////////////////////////////////////////////////////
// Status signals
//
vid_locked,
vid_is_full,
vid_stall_error,
vid_size_mismatch,
 
tpg_locked,
tpg_is_full,
tpg_stall_error,
tpg_size_mismatch
 
 
);
 
import intel_vvp_common_pkg::*;
 
// calculate localparams needed for the interface.
localparam C_AXIS_VID_IN_PIXEL_BITS   = NUMBER_OF_COLOR_PLANES*BPS;
localparam C_AXIS_VID_IN_PIXEL_BYTES  = (NUMBER_OF_COLOR_PLANES*BPS+7)/8;
localparam C_AXIS_VID_IN_WIDTH        = C_AXIS_VID_IN_PIXEL_BYTES*PIXELS_IN_PARALLEL*8;
localparam C_AXIS_VID_IN_TUSER_WIDTH  = C_AXIS_VID_IN_PIXEL_BYTES*PIXELS_IN_PARALLEL;
 
localparam C_VVP_PIXEL_BYTES          = vvp_max(VVP_USER_KEEP_BITS, C_AXIS_VID_IN_PIXEL_BYTES);
localparam C_VVP_TUSER_WIDTH          = C_VVP_PIXEL_BYTES*PIXELS_IN_PARALLEL;
localparam C_VVP_TDATA_WIDTH          = C_VVP_TUSER_WIDTH*8;
 
localparam C_AXIS_FR_PIXEL_BYTES      = ((NUMBER_OF_COLOR_PLANES+1)*BPS+7)/8;
localparam C_AXIS_FR_WIDTH            = C_AXIS_FR_PIXEL_BYTES*PIXELS_IN_PARALLEL*8;
localparam C_AXIS_FR_TUSER_WIDTH      = C_AXIS_FR_PIXEL_BYTES*PIXELS_IN_PARALLEL;
 
// internal localparams
localparam C_AXIS_FR_BITS   = (NUMBER_OF_COLOR_PLANES + 1) * BPS;
 
localparam C_BIT_FIELD      = C_AXIS_FR_BITS - 1;
localparam C_BIT_V          = C_AXIS_FR_BITS - 2;
localparam C_BIT_H          = C_AXIS_FR_BITS - 3;
localparam C_BIT_DE         = C_AXIS_FR_BITS - 4;
localparam C_BIT_SYNC_MODE  = C_AXIS_FR_BITS - 5;
 
 
//////////////////////////////////////////////////////
// cpu bus
//
input  logic                                cpu_clk;
input  logic                                cpu_rst;
input  logic [ 5:0]                         av_address;
input  logic                                av_read;
output logic [31:0]                         av_readdata;
output logic                                av_readdatavalid;
output logic                                av_waitrequest;
input  logic                                av_write;
input  logic [31:0]                         av_writedata;
input  logic [ 3:0]                         av_byteenable;
 
//////////////////////////////////////////////////////
// main video input bus
// axi4-s vvp lite/full
input  logic                                vid_clk;
input  logic                                vid_rst;
input  logic [C_VVP_TUSER_WIDTH-1:0]        axi4s_vid_in_tuser;
input  logic [C_VVP_TDATA_WIDTH-1:0]        axi4s_vid_in_tdata;
input  logic                                axi4s_vid_in_tvalid;
output logic                                axi4s_vid_in_tready;
input  logic                                axi4s_vid_in_tlast;
 
//////////////////////////////////////////////////////
// fall-back video input bus
// axi4-s vvp lite/full
input  logic                                tpg_clk;
input  logic                                tpg_rst;
input  logic [C_VVP_TUSER_WIDTH-1:0]        axi4s_tpg_in_tuser;
input  logic [C_VVP_TDATA_WIDTH-1:0]        axi4s_tpg_in_tdata;
input  logic                                axi4s_tpg_in_tvalid;
output logic                                axi4s_tpg_in_tready;
input  logic                                axi4s_tpg_in_tlast;
 
//////////////////////////////////////////////////////
// fr timing-only input bus
// axi4-s vvp fr
input  logic                                fr_clk;
input  logic                                fr_rst;
input  logic [C_AXIS_FR_TUSER_WIDTH-1:0]    axi4s_timing_in_tuser;
input  logic [C_AXIS_FR_WIDTH-1 : 0]        axi4s_timing_in_tdata;
input  logic                                axi4s_timing_in_tvalid;
output logic                                axi4s_timing_in_tready;
input  logic                                axi4s_timing_in_tlast;
 
//////////////////////////////////////////////////////
// fr video+timing output bus
// axi4-s vvp fr
output logic [C_AXIS_FR_TUSER_WIDTH-1:0]    axi4s_fr_vid_out_tuser;
output logic [C_AXIS_FR_WIDTH-1 : 0]        axi4s_fr_vid_out_tdata;
output logic                                axi4s_fr_vid_out_tvalid;
input  logic                                axi4s_fr_vid_out_tready;
output logic                                axi4s_fr_vid_out_tlast;
 
//////////////////////////////////////////////////////
// Status signals
//
output logic                                vid_locked;
output logic                                vid_is_full;
output logic                                vid_stall_error;
output logic                                vid_size_mismatch;
 
output logic                                tpg_locked;
output logic                                tpg_is_full;
output logic                                tpg_stall_error;
output logic                                tpg_size_mismatch;
 
 
 
///////////////////////////////////////////////////////
// Internal signals
//
 
 
 
 
logic [15:0] fr_totalH;
logic [15:0] fr_activeH;
logic [15:0] fr_totalV;
logic [15:0] fr_activeV;
logic [31:0] fr_vid_clk_freq;
logic [31:0] fr_vid_clks_per_frame;
 
logic [15:0] vid_totalH;
logic [15:0] vid_activeH;
logic [15:0] vid_totalV;
logic [15:0] vid_activeV;
logic [31:0] vid_vid_clk_freq;
logic [31:0] vid_vid_clks_per_frame;
 
logic [15:0] tpg_totalH;
logic [15:0] tpg_activeH;
logic [15:0] tpg_totalV;
logic [15:0] tpg_activeV;
logic [31:0] tpg_vid_clk_freq;
logic [31:0] tpg_vid_clks_per_frame;
 
logic [31:0] vid_locked_count;
logic [31:0] vid_stall_count;
logic [31:0] vid_size_err_count;
logic [31:0] tpg_locked_count;
logic [31:0] tpg_stall_count;
logic [31:0] tpg_size_err_count;
 
logic [C_AXIS_VID_IN_WIDTH-1 : 0]    axi4s_vid_tdata;
 
//////////////////////////////////////////////////////
// fall-back video input bus
// axi4-s vvp lite/full
logic [C_AXIS_VID_IN_WIDTH-1 : 0]    axi4s_tpg_tdata;
 
//////////////////////////////////////////////////////
// fr timing-only input bus
// axi4-s vvp fr
logic [C_AXIS_FR_TUSER_WIDTH-1:0]    axi4s_timing_tuser;
logic [C_AXIS_FR_WIDTH-1 : 0]        axi4s_timing_tdata;
logic                                axi4s_timing_tvalid;
logic                                axi4s_timing_tready;
logic                                axi4s_timing_tlast;

logic [C_VVP_TUSER_WIDTH-1:0]        axi4s_vid_shim_tuser;
logic [C_VVP_TDATA_WIDTH-1:0]        axi4s_vid_shim_tdata;
logic                                axi4s_vid_shim_tvalid;
logic                                axi4s_vid_shim_tready;
logic                                axi4s_vid_shim_tlast;

logic [C_VVP_TUSER_WIDTH-1:0]        vid_lite_tuser;
logic [C_VVP_TDATA_WIDTH-1:0]        vid_lite_tdata;
logic                                vid_lite_tvalid;
logic                                vid_lite_tready;
logic                                vid_lite_tlast;

logic [C_VVP_TUSER_WIDTH-1:0]        vid_shim_tuser;
logic [C_VVP_TDATA_WIDTH-1:0]        vid_shim_tdata;
logic                                vid_shim_tvalid;
logic                                vid_shim_tready;
logic                                vid_shim_tlast;

logic                                full_flag;

logic [C_VVP_TUSER_WIDTH-1:0]        axi4s_tpg_shim_tuser;
logic [C_VVP_TDATA_WIDTH-1:0]        axi4s_tpg_shim_tdata;
logic                                axi4s_tpg_shim_tvalid;
logic                                axi4s_tpg_shim_tready;
logic                                axi4s_tpg_shim_tlast;

logic [C_VVP_TUSER_WIDTH-1:0]        tpg_lite_tuser;
logic [C_VVP_TDATA_WIDTH-1:0]        tpg_lite_tdata;
logic                                tpg_lite_tvalid;
logic                                tpg_lite_tready;
logic                                tpg_lite_tlast;

logic [C_VVP_TUSER_WIDTH-1:0]        tpg_shim_tuser;
logic [C_VVP_TDATA_WIDTH-1:0]        tpg_shim_tdata;
logic                                tpg_shim_tvalid;
logic                                tpg_shim_tready;
logic                                tpg_shim_tlast;

logic                                tpg_full_flag;
 
//////////////////////////////////////////////////////
// VVP-Full to VVP-Lite conversion
// This core assumes the internal processing is done in Lite mode

//////////////////////////////////////////////////////
// decouple video input
//
intel_vvp_axi_pipeline_stage #(
  .DATA_WIDTH           ( C_VVP_TDATA_WIDTH     )
) i_VidIn_shim (
  .clk                  ( vid_clk               ),
  .rst                  ( vid_rst               ),

  .axi_st_din_tuser     ( axi4s_vid_in_tuser    ),
  .axi_st_din_tdata     ( axi4s_vid_in_tdata    ),
  .axi_st_din_tvalid    ( axi4s_vid_in_tvalid   ),
  .axi_st_din_tready    ( axi4s_vid_in_tready   ),
  .axi_st_din_tlast     ( axi4s_vid_in_tlast    ),

  .axi_st_dout_tuser    ( axi4s_vid_shim_tuser  ),
  .axi_st_dout_tdata    ( axi4s_vid_shim_tdata  ),
  .axi_st_dout_tvalid   ( axi4s_vid_shim_tvalid ),
  .axi_st_dout_tready   ( axi4s_vid_shim_tready ),
  .axi_st_dout_tlast    ( axi4s_vid_shim_tlast  )
); 

// Here we detect when the SOF-Full and SOF-Lite are generated
always_ff @(posedge vid_clk) begin
  if (vid_rst) begin
      full_flag    <= 1'b0;
  end
  else begin
      if (axi4s_vid_shim_tready) begin
          if (axi4s_vid_shim_tuser[0] && axi4s_vid_shim_tvalid) begin
              full_flag    <= 1'b0;
          end
          else if (axi4s_vid_shim_tuser[1] && axi4s_vid_shim_tvalid) begin
              full_flag    <= 1'b1;
          end
      end
  end
end

// If a SOF-Lite event is detected, we let the data passthrough
// If a SOF-Full event is detected, we consume and discard the data
always_comb begin
   if (axi4s_vid_shim_tuser[0] && axi4s_vid_shim_tvalid && axi4s_vid_shim_tready) begin
       vid_lite_tuser[0] = axi4s_vid_shim_tuser[0];
       vid_lite_tdata    = axi4s_vid_shim_tdata;
       vid_lite_tvalid   = axi4s_vid_shim_tvalid;
       vid_lite_tlast    = axi4s_vid_shim_tlast;
   end
   else if ( (full_flag) || (axi4s_vid_shim_tuser[1] && axi4s_vid_shim_tvalid && axi4s_vid_shim_tready) ) begin
       vid_lite_tuser[0] = 1'b0;
       vid_lite_tdata    = {(C_VVP_TDATA_WIDTH){1'b0}};
       vid_lite_tvalid   = 1'b0;
       vid_lite_tlast    = 1'b0;
   end
   else begin
       vid_lite_tuser[0] = axi4s_vid_shim_tuser[0];
       vid_lite_tdata    = axi4s_vid_shim_tdata;
       vid_lite_tvalid   = axi4s_vid_shim_tvalid;
       vid_lite_tlast    = axi4s_vid_shim_tlast;
   end
end

assign vid_lite_tuser[C_VVP_TUSER_WIDTH-1:1] = {(C_VVP_TUSER_WIDTH-1){1'b0}};
assign axi4s_vid_shim_tready                 = vid_lite_tready;

//////////////////////////////////////////////////////
// decouple timing input
//
intel_vvp_axi_pipeline_stage #(
  .DATA_WIDTH           ( C_VVP_TDATA_WIDTH     )
) i_VidIn_shim2 (
  .clk                  ( vid_clk               ),
  .rst                  ( vid_rst               ),

  .axi_st_din_tuser     ( vid_lite_tuser    ),
  .axi_st_din_tdata     ( vid_lite_tdata    ),
  .axi_st_din_tvalid    ( vid_lite_tvalid   ),
  .axi_st_din_tready    ( vid_lite_tready   ),
  .axi_st_din_tlast     ( vid_lite_tlast    ),

  .axi_st_dout_tuser    ( vid_shim_tuser  ),
  .axi_st_dout_tdata    ( vid_shim_tdata  ),
  .axi_st_dout_tvalid   ( vid_shim_tvalid ),
  .axi_st_dout_tready   ( vid_shim_tready ),
  .axi_st_dout_tlast    ( vid_shim_tlast  )
);
 
//////////////////////////////////////////////////////
// decouple timing input
//
intel_vvp_axi_pipeline_stage #(
  .DATA_WIDTH           ( C_AXIS_FR_WIDTH       )
) i_timingIn_shim (
  .clk                  ( fr_clk     ),
  .rst                  ( fr_rst     ),
 
  .axi_st_din_tuser     ( axi4s_timing_in_tuser    ),
  .axi_st_din_tdata     ( axi4s_timing_in_tdata    ),
  .axi_st_din_tvalid    ( axi4s_timing_in_tvalid   ),
  .axi_st_din_tready    ( axi4s_timing_in_tready   ),
  .axi_st_din_tlast     ( axi4s_timing_in_tlast    ),
 
  .axi_st_dout_tuser    ( axi4s_timing_tuser       ),
  .axi_st_dout_tdata    ( axi4s_timing_tdata       ),
  .axi_st_dout_tvalid   ( axi4s_timing_tvalid      ),
  .axi_st_dout_tready   ( axi4s_timing_tready      ),
  .axi_st_dout_tlast    ( axi4s_timing_tlast       )
);
 
 
if ((C_TIM_DIMENSIONS == 1) && (RUNTIME_CONTROL == 1))
begin:g_fr_dims
  intel_vvp_vid_dimensions
  #(
    .DEVICE_FAMILY            ( DEVICE_FAMILY          ), // = "Arria 10", // -- Cyclone 10 GX -- Arria 10 -- Stratix 10 -- Agilex
    .BUS_IS_FR                ( 1                      ), // = 1, // 0 = bus is FULL or LITE
 
    .SYS_CLK_FREQ_HZ          ( CPU_CLK_FREQ_HZ        ), // = 100000000,                 
    .PIXELS_IN_PARALLEL       ( PIXELS_IN_PARALLEL     ), // = 1, // at this stage, we assume the core input and output have the same number of PIP. As an extension, we could compose a core with a PIP converter.
    .NUMBER_OF_COLOR_PLANES   ( NUMBER_OF_COLOR_PLANES ), // = 3,
    .BPS                      ( BPS                    )  // = 8
 
  ) i_timing_vid_dimensions
  (
 
    //////////////////////////////////////////////////////
    // System inputs
    .sys_clk              ( cpu_clk       ),
    .sys_rst              ( cpu_rst       ),
    
    //////////////////////////////////////////////////////
    // video input bus
    // axi4-s vvp fr/lite/full
    .vid_clk              ( fr_clk      ),
    .vid_rst              ( fr_rst      ),
    .axi4s_vid_in_tuser   ( axi4s_timing_tuser        ),
    .axi4s_vid_in_tdata   ( axi4s_timing_tdata        ),
    .axi4s_vid_in_tvalid  ( axi4s_timing_tvalid       ),
    .axi4s_vid_in_tready  ( axi4s_timing_tready       ),
    .axi4s_vid_in_tlast   ( axi4s_timing_tlast        ),
    
    //////////////////////////////////////////////////////
    // outputs 
    // system clock
    .totalH               ( fr_totalH                 ),
    .activeH              ( fr_activeH                ),
    .totalV               ( fr_totalV                 ),
    .activeV              ( fr_activeV                ),
    .vid_clk_freq         ( fr_vid_clk_freq           ),
    .vid_clks_per_frame   ( fr_vid_clks_per_frame     )
  );
end
 
///////////////////////////////////////////////////////
// Pull the DE from the decoupled timing input
//
logic [PIXELS_IN_PARALLEL-1:0] axi4s_timing_de;
logic [PIXELS_IN_PARALLEL-1:0] r1_axi4s_timing_de;
logic [PIXELS_IN_PARALLEL-1:0] r2_axi4s_timing_de;
logic [PIXELS_IN_PARALLEL-1:0] r3_axi4s_timing_de;
logic [PIXELS_IN_PARALLEL-1:0] r4_axi4s_timing_de;
logic [PIXELS_IN_PARALLEL-1:0] r5_axi4s_timing_de;
logic [PIXELS_IN_PARALLEL-1:0] r6_axi4s_timing_de;
logic [PIXELS_IN_PARALLEL-1:0] r7_axi4s_timing_de;
always_comb
begin
  integer i;
  for (i=0;i<PIXELS_IN_PARALLEL;i=i+1)
    axi4s_timing_de[i] = axi4s_timing_tdata[C_AXIS_FR_PIXEL_BYTES*i*8+C_BIT_DE];
end
 
always_ff @(posedge fr_clk)
begin
  r1_axi4s_timing_de <= axi4s_timing_de;
  r2_axi4s_timing_de <= r1_axi4s_timing_de;
  r3_axi4s_timing_de <= r2_axi4s_timing_de;
  r4_axi4s_timing_de <= r3_axi4s_timing_de;
  r5_axi4s_timing_de <= r4_axi4s_timing_de;
  r6_axi4s_timing_de <= r5_axi4s_timing_de;
  r7_axi4s_timing_de <= r6_axi4s_timing_de;
end
 
///////////////////////////////////////////////////////
// Get the DE phase offset
//
logic [3:0] r_phase;
always_ff @(posedge fr_clk)
begin
  logic [PIXELS_IN_PARALLEL-1:0] r_axi4s_timing_de;
  localparam [PIXELS_IN_PARALLEL-1:0] C_ONES = -1;
  integer i;
  r_axi4s_timing_de <= axi4s_timing_de;
  if (fr_rst) 
  begin
    r_phase <= 4'b0;
  end
  else if ((axi4s_timing_de[PIXELS_IN_PARALLEL-1] && !r_axi4s_timing_de[PIXELS_IN_PARALLEL-1]) || (axi4s_timing_de[PIXELS_IN_PARALLEL-1] && axi4s_timing_de != C_ONES))
  begin
    for (i=PIXELS_IN_PARALLEL-1;i>=0;i=i-1)
      if (axi4s_timing_de[i])
        r_phase <= i;
      else
        break;
  end
end
 
 
///////////////////////////////////////////////////////
// Get the video input dimensions
//
if ((C_VID_DIMENSIONS == 1) && (RUNTIME_CONTROL == 1))
begin:g_make_vid_dims
  intel_vvp_vid_dimensions
  #(
    .DEVICE_FAMILY            ( DEVICE_FAMILY          ), // = "Arria 10", // -- Cyclone 10 GX -- Arria 10 -- Stratix 10 -- Agilex
    .BUS_IS_FR                ( 0                      ), // = 1, // 0 = bus is FULL or LITE
 
    .SYS_CLK_FREQ_HZ          ( CPU_CLK_FREQ_HZ        ), // = 100000000,                 
    .PIXELS_IN_PARALLEL       ( PIXELS_IN_PARALLEL     ), // = 1, // at this stage, we assume the core input and output have the same number of PIP. As an extension, we could compose a core with a PIP converter.
    .NUMBER_OF_COLOR_PLANES   ( NUMBER_OF_COLOR_PLANES ), // = 3,
    .BPS                      ( BPS                    )  // = 8
 
  ) i_timing_vid_dimensions
  (
 
    //////////////////////////////////////////////////////
    // System inputs
    .sys_clk              ( cpu_clk       ),
    .sys_rst              ( cpu_rst       ),
    
    //////////////////////////////////////////////////////
    // video input bus
    // axi4-s vvp fr/lite/full
    .vid_clk              ( vid_clk          ),
    .vid_rst              ( vid_rst          ),
    .axi4s_vid_in_tuser   ( vid_shim_tuser   ),
    .axi4s_vid_in_tdata   ( vid_shim_tdata   ),
    .axi4s_vid_in_tvalid  ( vid_shim_tvalid  ),
    .axi4s_vid_in_tready  ( vid_shim_tready  ),
    .axi4s_vid_in_tlast   ( vid_shim_tlast   ),
    
    //////////////////////////////////////////////////////
    // outputs 
    // system clock
    .totalH               ( vid_totalH                 ),
    .activeH              ( vid_activeH                ),
    .totalV               ( vid_totalV                 ),
    .activeV              ( vid_activeV                ),
    .vid_clk_freq         ( vid_vid_clk_freq           ),
    .vid_clks_per_frame   ( vid_vid_clks_per_frame     )
  );
end
 
///////////////////////////////////////////////////////
// Align the video input
//
intel_vvp_cvo_align
#(
  .DEVICE_FAMILY             ( DEVICE_FAMILY            ),
  .C_RAM_BLOCK_TYPE          ( C_RAM_BLOCK_TYPE         ),
  .C_FIFO_DEPTH              ( C_VID_FIFO_DEPTH         ),
  .C_INPUT_IS_ASYNC          ( C_VID_IS_ASYNC           ),
 
  .C_PIXELS_IN_PARALLEL      ( PIXELS_IN_PARALLEL       ),
  .C_NUMBER_OF_COLOR_PLANES  ( NUMBER_OF_COLOR_PLANES   ),
  .C_BPS                     ( BPS                      )
 
) i_vid_input_align
(
 
//////////////////////////////////////////////////////
// video input bus
// axi4-s vvp lite/full
.vid_clk                   ( vid_clk         ),
.vid_rst                   ( vid_rst         ),
.axi4s_vid_in_tuser        ( vid_shim_tuser  ),
.axi4s_vid_in_tdata        ( vid_shim_tdata  ),
.axi4s_vid_in_tvalid       ( vid_shim_tvalid ),
.axi4s_vid_in_tready       ( vid_shim_tready ),
.axi4s_vid_in_tlast        ( vid_shim_tlast  ),
 
//////////////////////////////////////////////////////
// video output bus
// axi4-s vvp lite/full
.axi4s_vid_aligned_tdata   ( axi4s_vid_tdata      ),
 
/////////////////////////////////////////////////////
// fr timing-only input bus
// axi4-s vvp fr
.fr_clk      ( fr_clk    ),
.fr_rst      ( fr_rst    ),
.axi4s_timing_in_tuser     ( axi4s_timing_tuser      ),
.axi4s_timing_in_tdata     ( axi4s_timing_tdata      ),
.axi4s_timing_in_tvalid    ( axi4s_timing_tvalid     ),
.axi4s_timing_in_tready    ( axi4s_timing_tready     ),
.axi4s_timing_in_tlast     ( axi4s_timing_tlast      ),
.timing_phase              ( r_phase                 ),
 
 
/////////////////////////////////////////////////////
// Status signals
//
.r_input_locked            ( vid_locked              ),
.input_is_full             ( vid_is_full             ),
.input_stall_error         ( vid_stall_error         ),
.input_size_mismatch       ( vid_size_mismatch       ),
 
.locked_count              ( vid_locked_count        ),
.stall_count               ( vid_stall_count         ),
.size_err_count            ( vid_size_err_count      )
 
);
 
 
 
generate
  if (C_FALL_BACK_INPUT_EN == 1)
  begin:g_make_tpg_input

//////////////////////////////////////////////////////
// VVP-Full to VVP-Lite conversion
// This core assumes the internal processing is done in Lite mode

    //////////////////////////////////////////////////////
    // decouple TPG input
    //
    intel_vvp_axi_pipeline_stage #(
      .DATA_WIDTH           ( C_VVP_TDATA_WIDTH     )
    ) i_TPGIn_shim (
      .clk                  ( tpg_clk               ),
      .rst                  ( tpg_rst               ),
    
      .axi_st_din_tuser     ( axi4s_tpg_in_tuser    ),
      .axi_st_din_tdata     ( axi4s_tpg_in_tdata    ),
      .axi_st_din_tvalid    ( axi4s_tpg_in_tvalid   ),
      .axi_st_din_tready    ( axi4s_tpg_in_tready   ),
      .axi_st_din_tlast     ( axi4s_tpg_in_tlast    ),
    
      .axi_st_dout_tuser    ( axi4s_tpg_shim_tuser  ),
      .axi_st_dout_tdata    ( axi4s_tpg_shim_tdata  ),
      .axi_st_dout_tvalid   ( axi4s_tpg_shim_tvalid ),
      .axi_st_dout_tready   ( axi4s_tpg_shim_tready ),
      .axi_st_dout_tlast    ( axi4s_tpg_shim_tlast  )
    ); 
    
    // Here we detect when the SOF-Full and SOF-Lite are generated
    always_ff @(posedge tpg_clk) begin
      if (tpg_rst) begin
          tpg_full_flag    <= 1'b0;
      end
      else begin
          if (axi4s_tpg_shim_tready) begin
              if (axi4s_tpg_shim_tuser[0] && axi4s_tpg_shim_tvalid) begin
                  tpg_full_flag    <= 1'b0;
              end
              else if (axi4s_tpg_shim_tuser[1] && axi4s_tpg_shim_tvalid) begin
                  tpg_full_flag    <= 1'b1;
              end
          end
      end
    end
    
    // If a SOF-Lite event is detected, we let the data passthrough
    // If a SOF-Full event is detected, we consume and discard the data
    always_comb begin
       if (axi4s_tpg_shim_tuser[0] && axi4s_tpg_shim_tvalid && axi4s_tpg_shim_tready) begin
           tpg_lite_tuser[0] = axi4s_tpg_shim_tuser[0];
           tpg_lite_tdata    = axi4s_tpg_shim_tdata;
           tpg_lite_tvalid   = axi4s_tpg_shim_tvalid;
           tpg_lite_tlast    = axi4s_tpg_shim_tlast;
       end
       else if ( (tpg_full_flag) || (axi4s_tpg_shim_tuser[1] && axi4s_tpg_shim_tvalid && axi4s_tpg_shim_tready) ) begin
           tpg_lite_tuser[0] = 1'b0;
           tpg_lite_tdata    = {(C_VVP_TDATA_WIDTH){1'b0}};
           tpg_lite_tvalid   = 1'b0;
           tpg_lite_tlast    = 1'b0;
       end
       else begin
           tpg_lite_tuser[0] = axi4s_tpg_shim_tuser[0];
           tpg_lite_tdata    = axi4s_tpg_shim_tdata;
           tpg_lite_tvalid   = axi4s_tpg_shim_tvalid;
           tpg_lite_tlast    = axi4s_tpg_shim_tlast;
       end
    end
    
    assign tpg_lite_tuser[C_VVP_TUSER_WIDTH-1:1] = {(C_VVP_TUSER_WIDTH-1){1'b0}};
    assign axi4s_tpg_shim_tready                 = tpg_lite_tready;  


    //////////////////////////////////////////////////////
    // decouple TPG input
    //
    intel_vvp_axi_pipeline_stage #(
      .DATA_WIDTH           ( C_VVP_TDATA_WIDTH     )
    ) i_TPGIn_shim2 (
      .clk                  ( tpg_clk               ),
      .rst                  ( tpg_rst               ),
    
      .axi_st_din_tuser     ( tpg_lite_tuser    ),
      .axi_st_din_tdata     ( tpg_lite_tdata    ),
      .axi_st_din_tvalid    ( tpg_lite_tvalid   ),
      .axi_st_din_tready    ( tpg_lite_tready   ),
      .axi_st_din_tlast     ( tpg_lite_tlast    ),
    
      .axi_st_dout_tuser    ( tpg_shim_tuser  ),
      .axi_st_dout_tdata    ( tpg_shim_tdata  ),
      .axi_st_dout_tvalid   ( tpg_shim_tvalid ),
      .axi_st_dout_tready   ( tpg_shim_tready ),
      .axi_st_dout_tlast    ( tpg_shim_tlast  )
    );
  
  
    ///////////////////////////////////////////////////////
    // Get the video input dimensions
    //
    if ((C_TPG_DIMENSIONS == 1) && (RUNTIME_CONTROL == 1))
    begin:g_make_tpg_dims
      intel_vvp_vid_dimensions
      #(
        .DEVICE_FAMILY            ( DEVICE_FAMILY          ), // = "Arria 10", // -- Cyclone 10 GX -- Arria 10 -- Stratix 10 -- Agilex
        .BUS_IS_FR                ( 0                      ), // = 1, // 0 = bus is FULL or LITE
 
        .SYS_CLK_FREQ_HZ          ( CPU_CLK_FREQ_HZ        ), // = 100000000,                 
        .PIXELS_IN_PARALLEL       ( PIXELS_IN_PARALLEL     ), // = 1, // at this stage, we assume the core input and output have the same number of PIP. As an extension, we could compose a core with a PIP converter.
        .NUMBER_OF_COLOR_PLANES   ( NUMBER_OF_COLOR_PLANES ), // = 3,
        .BPS                      ( BPS                    ) // = 8
 
      ) i_timing_vid_dimensions
      (
 
        //////////////////////////////////////////////////////
        // System inputs
        .sys_clk              ( cpu_clk       ),
        .sys_rst              ( cpu_rst       ),
        
        //////////////////////////////////////////////////////
        // video input bus
        // axi4-s vvp fr/lite/full
        .vid_clk              ( tpg_clk          ),
        .vid_rst              ( tpg_rst          ),
        .axi4s_vid_in_tuser   ( tpg_shim_tuser   ),
        .axi4s_vid_in_tdata   ( tpg_shim_tdata   ),
        .axi4s_vid_in_tvalid  ( tpg_shim_tvalid  ),
        .axi4s_vid_in_tready  ( tpg_shim_tready  ),
        .axi4s_vid_in_tlast   ( tpg_shim_tlast   ),
        
        //////////////////////////////////////////////////////
        // outputs 
        // system clock
        .totalH               ( tpg_totalH                 ),
        .activeH              ( tpg_activeH                ),
        .totalV               ( tpg_totalV                 ),
        .activeV              ( tpg_activeV                ),
        .vid_clk_freq         ( tpg_vid_clk_freq           ),
        .vid_clks_per_frame   ( tpg_vid_clks_per_frame     )
      );
    end
  
  
  ///////////////////////////////////////////////////////
  // Align the tpg input
  //
  intel_vvp_cvo_align
  #(
    .DEVICE_FAMILY             ( DEVICE_FAMILY            ),
    .C_RAM_BLOCK_TYPE          ( C_RAM_BLOCK_TYPE         ),
    .C_FIFO_DEPTH              ( C_TPG_FIFO_DEPTH         ),
    .C_INPUT_IS_ASYNC          ( C_TPG_IS_ASYNC           ),
 
    .C_PIXELS_IN_PARALLEL      ( PIXELS_IN_PARALLEL       ),
    .C_NUMBER_OF_COLOR_PLANES  ( NUMBER_OF_COLOR_PLANES   ),
    .C_BPS                     ( BPS                      )
 
  ) i_tpg_input_align
  (
 
  //////////////////////////////////////////////////////
  // video input bus
  // axi4-s vvp lite/full
  .vid_clk                   ( tpg_clk         ),
  .vid_rst                   ( tpg_rst         ),
  .axi4s_vid_in_tuser        ( tpg_shim_tuser  ),
  .axi4s_vid_in_tdata        ( tpg_shim_tdata  ),
  .axi4s_vid_in_tvalid       ( tpg_shim_tvalid ),
  .axi4s_vid_in_tready       ( tpg_shim_tready ),
  .axi4s_vid_in_tlast        ( tpg_shim_tlast  ),
                             
  //////////////////////////////////////////////////////
  // video output bus
  // axi4-s vvp lite/full
  .axi4s_vid_aligned_tdata   ( axi4s_tpg_tdata      ),
 
  /////////////////////////////////////////////////////
  // fr timing-only input bus
  // axi4-s vvp fr
  .fr_clk      ( fr_clk    ),
  .fr_rst      ( fr_rst    ),
  .axi4s_timing_in_tuser     ( axi4s_timing_tuser      ),
  .axi4s_timing_in_tdata     ( axi4s_timing_tdata      ),
  .axi4s_timing_in_tvalid    ( axi4s_timing_tvalid     ),
  .axi4s_timing_in_tready    ( axi4s_timing_tready     ),
  .axi4s_timing_in_tlast     ( axi4s_timing_tlast      ),
  .timing_phase              ( r_phase                 ),
 
 
  /////////////////////////////////////////////////////
  // Status signals
  //
  .r_input_locked            ( tpg_locked        ),
  .input_is_full             ( tpg_is_full       ),
  .input_stall_error         ( tpg_stall_error   ),
  .input_size_mismatch       ( tpg_size_mismatch ),
 
  .locked_count              ( tpg_locked_count        ),
  .stall_count               ( tpg_stall_count         ),
  .size_err_count            ( tpg_size_err_count      )
 
  
  
 
  );
end
else
begin:g_no_tpg_input
  assign axi4s_tpg_tdata      = {C_AXIS_VID_IN_WIDTH{1'b0}};
 
  assign tpg_locked           = 1'b0;
  assign tpg_stall_error      = 1'b0;
  assign tpg_size_mismatch    = 1'b0;
  assign axi4s_tpg_in_tready  = 1'b1;
end
endgenerate
 
 
/////////////////////////////////////////////////////
// Allow the video input
//
logic    vid_allowed;
logic    r_vid_do_recover;
logic    r_vid_do_recover_toggle;
logic    r2_vid_do_recover_toggle;
logic    r_vid_auto_recover;
 
logic    r_vid_force_tpg;
logic    r_vid_force_vid;
logic    r_vid_force_black;
 
 
 
always_ff @(posedge fr_clk)
begin:a_do_vid_latch
  if (fr_rst)
  begin
    vid_allowed               <= 1'b1;
    r2_vid_do_recover_toggle  <= 1'b0;
  end
  else
  begin
    r2_vid_do_recover_toggle      <= r_vid_do_recover_toggle;
    r_vid_do_recover              <= r2_vid_do_recover_toggle ^ r_vid_do_recover_toggle;
    
    if (r_vid_auto_recover || r_vid_do_recover)
      vid_allowed <= 1'b1;
    else if (!vid_locked)
      vid_allowed <= 1'b0;
  end
end
 
 
/////////////////////////////////////////////////////
// Do the merge
//
logic [4*BPS-1:0]                    r_vid_black;
logic [C_AXIS_FR_TUSER_WIDTH-1:0]    axi4s_fr_vid_tuser;
logic [C_AXIS_FR_WIDTH-1 : 0]        axi4s_fr_vid_tdata;
logic                                axi4s_fr_vid_tvalid;
logic                                axi4s_fr_vid_tready;
logic                                axi4s_fr_vid_tlast;
logic [PIXELS_IN_PARALLEL-1:0]       axi4s_fr_vid_de;
 
logic [C_AXIS_FR_TUSER_WIDTH-1:0]    r1_axi4s_fr_vid_tuser;
logic [C_AXIS_FR_WIDTH-1 : 0]        r1_axi4s_fr_vid_tdata;
logic                                r1_axi4s_fr_vid_tvalid;
logic                                r1_axi4s_fr_vid_tready;
logic                                r1_axi4s_fr_vid_tlast;
 
logic [C_AXIS_FR_TUSER_WIDTH-1:0]    r2_axi4s_fr_vid_tuser;
logic [C_AXIS_FR_WIDTH-1 : 0]        r2_axi4s_fr_vid_tdata;
logic                                r2_axi4s_fr_vid_tvalid;
logic                                r2_axi4s_fr_vid_tready;
logic                                r2_axi4s_fr_vid_tlast;
 
logic [C_AXIS_FR_TUSER_WIDTH-1:0]    r3_axi4s_fr_vid_tuser;
logic [C_AXIS_FR_WIDTH-1 : 0]        r3_axi4s_fr_vid_tdata;
logic                                r3_axi4s_fr_vid_tvalid;
logic                                r3_axi4s_fr_vid_tready;
logic                                r3_axi4s_fr_vid_tlast;
 
logic [C_AXIS_FR_TUSER_WIDTH-1:0]    r4_axi4s_fr_vid_tuser;
logic [C_AXIS_FR_WIDTH-1 : 0]        r4_axi4s_fr_vid_tdata;
logic                                r4_axi4s_fr_vid_tvalid;
logic                                r4_axi4s_fr_vid_tready;
logic                                r4_axi4s_fr_vid_tlast;
 
logic [C_AXIS_FR_TUSER_WIDTH-1:0]    r5_axi4s_fr_vid_tuser;
logic [C_AXIS_FR_WIDTH-1 : 0]        r5_axi4s_fr_vid_tdata;
logic                                r5_axi4s_fr_vid_tvalid;
logic                                r5_axi4s_fr_vid_tready;
logic                                r5_axi4s_fr_vid_tlast;
 
logic [C_AXIS_FR_TUSER_WIDTH-1:0]    r6_axi4s_fr_vid_tuser;
logic [C_AXIS_FR_WIDTH-1 : 0]        r6_axi4s_fr_vid_tdata;
logic                                r6_axi4s_fr_vid_tvalid;
logic                                r6_axi4s_fr_vid_tready;
logic                                r6_axi4s_fr_vid_tlast;
 
if (PIXELS_IN_PARALLEL > 1)
begin:select_de_delay
  assign axi4s_fr_vid_de  = r5_axi4s_timing_de;
end
else
begin
  assign axi4s_fr_vid_de  = r1_axi4s_timing_de;
end         
 
always_ff @(posedge fr_clk)
begin:a_do_merge
  integer i;
 
  r1_axi4s_fr_vid_tlast  <= axi4s_timing_tlast;
  r1_axi4s_fr_vid_tvalid <= axi4s_timing_tvalid;
  r1_axi4s_fr_vid_tuser  <= axi4s_timing_tuser;
  r1_axi4s_fr_vid_tdata  <= axi4s_timing_tdata;
  axi4s_timing_tready    <= axi4s_fr_vid_tready;
 
  r2_axi4s_fr_vid_tlast  <= r1_axi4s_fr_vid_tlast;
  r2_axi4s_fr_vid_tvalid <= r1_axi4s_fr_vid_tvalid;
  r2_axi4s_fr_vid_tuser  <= r1_axi4s_fr_vid_tuser;
  r2_axi4s_fr_vid_tdata  <= r1_axi4s_fr_vid_tdata;
 
  r3_axi4s_fr_vid_tlast  <= r2_axi4s_fr_vid_tlast;
  r3_axi4s_fr_vid_tvalid <= r2_axi4s_fr_vid_tvalid;
  r3_axi4s_fr_vid_tuser  <= r2_axi4s_fr_vid_tuser;
  r3_axi4s_fr_vid_tdata  <= r2_axi4s_fr_vid_tdata;
 
  r4_axi4s_fr_vid_tlast  <= r3_axi4s_fr_vid_tlast;
  r4_axi4s_fr_vid_tvalid <= r3_axi4s_fr_vid_tvalid;
  r4_axi4s_fr_vid_tuser  <= r3_axi4s_fr_vid_tuser;
  r4_axi4s_fr_vid_tdata  <= r3_axi4s_fr_vid_tdata;
 
  r5_axi4s_fr_vid_tlast  <= r4_axi4s_fr_vid_tlast;
  r5_axi4s_fr_vid_tvalid <= r4_axi4s_fr_vid_tvalid;
  r5_axi4s_fr_vid_tuser  <= r4_axi4s_fr_vid_tuser;
  r5_axi4s_fr_vid_tdata  <= r4_axi4s_fr_vid_tdata;
 
  r6_axi4s_fr_vid_tlast  <= r5_axi4s_fr_vid_tlast;
  r6_axi4s_fr_vid_tvalid <= r5_axi4s_fr_vid_tvalid;
  r6_axi4s_fr_vid_tuser  <= r5_axi4s_fr_vid_tuser;
  r6_axi4s_fr_vid_tdata  <= r5_axi4s_fr_vid_tdata;
 
 
 
 
  if (PIXELS_IN_PARALLEL > 1)
  begin:select_pl_delay
    axi4s_fr_vid_tlast  <= r5_axi4s_fr_vid_tlast;
    axi4s_fr_vid_tvalid <= r5_axi4s_fr_vid_tvalid;
    axi4s_fr_vid_tuser  <= r5_axi4s_fr_vid_tuser;
    axi4s_fr_vid_tdata  <= r5_axi4s_fr_vid_tdata;
  end
  else
  begin
    axi4s_fr_vid_tlast  <= r1_axi4s_fr_vid_tlast ;
    axi4s_fr_vid_tvalid <= r1_axi4s_fr_vid_tvalid;
    axi4s_fr_vid_tuser  <= r1_axi4s_fr_vid_tuser ;
    axi4s_fr_vid_tdata  <= r1_axi4s_fr_vid_tdata ;
  end         
 
 
  for (i=0;i<PIXELS_IN_PARALLEL;i=i+1)
  begin
    if (axi4s_fr_vid_de[i])
    begin
      if (((vid_locked && vid_allowed) || r_vid_force_vid) && !r_vid_force_tpg && !r_vid_force_black)
      begin
        axi4s_fr_vid_tdata[i * C_AXIS_FR_PIXEL_BYTES * 8 +: C_AXIS_VID_IN_PIXEL_BITS] <= axi4s_vid_tdata[i * C_AXIS_VID_IN_PIXEL_BYTES * 8 +: C_AXIS_VID_IN_PIXEL_BITS];
      end
      else if ((tpg_locked || r_vid_force_tpg) && !r_vid_force_vid && !r_vid_force_black)
      begin
        axi4s_fr_vid_tdata[i * C_AXIS_FR_PIXEL_BYTES * 8 +: C_AXIS_VID_IN_PIXEL_BITS] <= axi4s_tpg_tdata[i * C_AXIS_VID_IN_PIXEL_BYTES * 8 +: C_AXIS_VID_IN_PIXEL_BITS];
      end
      else 
      begin
        axi4s_fr_vid_tdata[i * C_AXIS_FR_PIXEL_BYTES * 8 +: C_AXIS_VID_IN_PIXEL_BITS] <= r_vid_black[C_AXIS_VID_IN_PIXEL_BITS-1:0];
      end
    end
  end
end
 
 
 
 
 
 
 
//////////////////////////////////////////////////////
// decouple timing output
//
intel_vvp_axi_pipeline_stage #(
  .DATA_WIDTH           ( C_AXIS_FR_WIDTH       )
) i_timingOut_shim (
  .clk                  ( fr_clk     ),
  .rst                  ( fr_rst     ),
 
  .axi_st_din_tuser     ( axi4s_fr_vid_tuser           ),
  .axi_st_din_tdata     ( axi4s_fr_vid_tdata           ),
  .axi_st_din_tvalid    ( axi4s_fr_vid_tvalid          ),
  .axi_st_din_tready    ( axi4s_fr_vid_tready          ),
  .axi_st_din_tlast     ( axi4s_fr_vid_tlast           ),
 
  .axi_st_dout_tuser    ( axi4s_fr_vid_out_tuser       ),
  .axi_st_dout_tdata    ( axi4s_fr_vid_out_tdata       ),
  .axi_st_dout_tvalid   ( axi4s_fr_vid_out_tvalid      ),
  .axi_st_dout_tready   ( 1'b1                         ),
//  .axi_st_dout_tready   ( axi4s_fr_vid_out_tready      ), // the output tReady is not supported in this release.
  .axi_st_dout_tlast    ( axi4s_fr_vid_out_tlast       )
);
 
// register cpu i/f
logic [ 5:0]                  r_av_address;
logic                         r_av_read;
logic                         r_av_write;
logic [31:0]                  r_av_writedata;
logic [ 3:0]                  r_av_byteenable;
always_ff @(posedge cpu_clk)
begin:a_reg_cpu_if
  r_av_address      <= av_address;
  r_av_read         <= av_read;
  r_av_write        <= av_write;
  r_av_writedata    <= av_writedata;
  r_av_byteenable   <= av_byteenable;
end  
////////////////////////////////////////////////////////
// a couple of cpu regs...
//
generate
  if (RUNTIME_CONTROL)
  begin:g_runtime_control
 
      
    logic r_cpu_vid_locked;
    logic r_cpu_vid_is_full;
    logic r_cpu_vid_stall_error;
    logic r_cpu_vid_size_mismatch;
 
    logic r_cpu_tpg_locked;
    logic r_cpu_tpg_is_full;
    logic r_cpu_tpg_stall_error;
    logic r_cpu_tpg_size_mismatch;
 
    logic r_cpu_vid_locked_meta;
    logic r_cpu_vid_is_full_meta;
    logic r_cpu_vid_stall_error_meta;
    logic r_cpu_vid_size_mismatch_meta;
 
    logic r_cpu_tpg_locked_meta;
    logic r_cpu_tpg_is_full_meta;
    logic r_cpu_tpg_stall_error_meta;
    logic r_cpu_tpg_size_mismatch_meta;
 
    logic [31:0] r_cpu_vid_locked_count  ;
    logic [31:0] r_cpu_vid_stall_count   ;
    logic [31:0] r_cpu_vid_size_err_count;
 
    logic [31:0] r_cpu_tpg_locked_count  ;
    logic [31:0] r_cpu_tpg_stall_count   ;
    logic [31:0] r_cpu_tpg_size_err_count;
 
    task t_cpu_write;
      input av_write;
      input [ 3:0] av_byteenable;
      input [31:0] av_writedata;
      inout [31:0] r_some_reg32;
      if (av_write)
      begin
        if (av_byteenable[0])
          r_some_reg32[ 7: 0] = av_writedata[ 7: 0];
        if (av_byteenable[1])
          r_some_reg32[15: 8] = av_writedata[15: 8];
        if (av_byteenable[2])
          r_some_reg32[23:16] = av_writedata[23:16];
        if (av_byteenable[3])
          r_some_reg32[31:24] = av_writedata[31:24];
      end
    endtask
 
    localparam C_REG_STATUS             = C_CPU_OFFSET +  0;
    localparam C_REG_BLACK_0            = C_CPU_OFFSET +  1;
    localparam C_REG_BLACK_1            = C_CPU_OFFSET +  2;
    localparam C_REG_BLACK_2            = C_CPU_OFFSET +  3;
    localparam C_REG_BLACK_3            = C_CPU_OFFSET +  4;
    localparam C_REG_FALLBACK           = C_CPU_OFFSET +  5;
    localparam C_REG_FR_H_DIMS          = C_CPU_OFFSET +  6;
    localparam C_REG_FR_V_DIMS          = C_CPU_OFFSET +  7;
    localparam C_REG_FR_FREQ_DIMS       = C_CPU_OFFSET +  8;
    localparam C_REG_FR_CLKS_DIMS       = C_CPU_OFFSET +  9;
    localparam C_REG_VID_DIMS           = C_CPU_OFFSET + 10;
    localparam C_REG_VID_FREQ_DIMS      = C_CPU_OFFSET + 11;
    localparam C_REG_VID_CLKS_DIMS      = C_CPU_OFFSET + 12;
    localparam C_REG_TPG_DIMS           = C_CPU_OFFSET + 13;
    localparam C_REG_TPG_FREQ_DIMS      = C_CPU_OFFSET + 14;
    localparam C_REG_TPG_CLKS_DIMS      = C_CPU_OFFSET + 15;
    localparam C_REG_VID_LOCKED_COUNT   = C_CPU_OFFSET + 16;
    localparam C_REG_VID_SIZE_ERR_COUNT = C_CPU_OFFSET + 17;
    localparam C_REG_VID_STALL_COUNT    = C_CPU_OFFSET + 18;
    localparam C_REG_TPG_LOCKED_COUNT   = C_CPU_OFFSET + 19;
    localparam C_REG_TPG_SIZE_ERR_COUNT = C_CPU_OFFSET + 20;
    localparam C_REG_TPG_STALL_COUNT    = C_CPU_OFFSET + 21;
 
    logic r_cpu_clear_status;
    logic r2_cpu_clear_status;
 
    logic r_cpu_do_recover;
    logic r2_cpu_do_recover;
    logic r_cpu_do_recover_toggle;
    logic r_cpu_auto_recover;
    logic r_cpu_force_black; 
    logic r_cpu_force_tpg;   
    logic r_cpu_force_vid;
  
  
    logic [15:0] r_cpu_fr_totalH;
    logic [15:0] r_cpu_fr_activeH;
    logic [15:0] r_cpu_fr_totalV;
    logic [15:0] r_cpu_fr_activeV;
    logic [31:0] r_cpu_fr_vid_clk_freq;
    logic [31:0] r_cpu_fr_vid_clks_per_frame;
 
    logic [15:0] r_cpu_vid_activeH;
    logic [15:0] r_cpu_vid_activeV;
    logic [31:0] r_cpu_vid_vid_clk_freq;
    logic [31:0] r_cpu_vid_vid_clks_per_frame;
 
    logic [15:0] r_cpu_tpg_activeH;
    logic [15:0] r_cpu_tpg_activeV;
    logic [31:0] r_cpu_tpg_vid_clk_freq;
    logic [31:0] r_cpu_tpg_vid_clks_per_frame;
  
    logic [3:0] r_cpu_phase;    
    logic [4*BPS-1:0]                    r_cpu_black;
 
    // CDC for single-bit signals 
    intel_vvp_clock_crosser #(.DATA_WIDTH ( 1), .NUM_CC_REG (3), .INPUT_REG  (1)) u_cdc_reg_1 (.in_clk (cpu_clk), .in_data (r_cpu_do_recover_toggle), .out_clk (fr_clk),  .out_data (r_vid_do_recover_toggle) );
    intel_vvp_clock_crosser #(.DATA_WIDTH ( 1), .NUM_CC_REG (3), .INPUT_REG  (1)) u_cdc_reg_2 (.in_clk (cpu_clk), .in_data (r_cpu_auto_recover     ), .out_clk (fr_clk),  .out_data (r_vid_auto_recover     ) );
 
    intel_vvp_clock_crosser #(.DATA_WIDTH ( 1), .NUM_CC_REG (3), .INPUT_REG  (1)) u_cdc_reg_3 (.in_clk (cpu_clk), .in_data (r_cpu_force_tpg        ), .out_clk (fr_clk),  .out_data (r_vid_force_tpg        ) );
    intel_vvp_clock_crosser #(.DATA_WIDTH ( 1), .NUM_CC_REG (3), .INPUT_REG  (1)) u_cdc_reg_4 (.in_clk (cpu_clk), .in_data (r_cpu_force_vid        ), .out_clk (fr_clk),  .out_data (r_vid_force_vid        ) );
    intel_vvp_clock_crosser #(.DATA_WIDTH ( 1), .NUM_CC_REG (3), .INPUT_REG  (1)) u_cdc_reg_5 (.in_clk (cpu_clk), .in_data (r_cpu_force_black      ), .out_clk (fr_clk),  .out_data (r_vid_force_black      ) );
 
    intel_vvp_clock_crosser #(.DATA_WIDTH ( 1), .NUM_CC_REG (3), .INPUT_REG  (1)) u_cdc_reg_6 (.in_clk (fr_clk), .in_data (vid_locked       ), .out_clk (cpu_clk),  .out_data (r_cpu_vid_locked_meta       ) );
    intel_vvp_clock_crosser #(.DATA_WIDTH ( 1), .NUM_CC_REG (3), .INPUT_REG  (1)) u_cdc_reg_7 (.in_clk (fr_clk), .in_data (vid_is_full      ), .out_clk (cpu_clk),  .out_data (r_cpu_vid_is_full_meta      ) );
    intel_vvp_clock_crosser #(.DATA_WIDTH ( 1), .NUM_CC_REG (3), .INPUT_REG  (1)) u_cdc_reg_8 (.in_clk (fr_clk), .in_data (vid_stall_error  ), .out_clk (cpu_clk),  .out_data (r_cpu_vid_stall_error_meta  ) );
    intel_vvp_clock_crosser #(.DATA_WIDTH ( 1), .NUM_CC_REG (3), .INPUT_REG  (1)) u_cdc_reg_9 (.in_clk (fr_clk), .in_data (vid_size_mismatch), .out_clk (cpu_clk),  .out_data (r_cpu_vid_size_mismatch_meta) );
 
    intel_vvp_clock_crosser #(.DATA_WIDTH ( 1), .NUM_CC_REG (3), .INPUT_REG  (1)) u_cdc_reg_10 (.in_clk (fr_clk), .in_data (tpg_locked       ), .out_clk (cpu_clk),  .out_data (r_cpu_tpg_locked_meta       ) );
    intel_vvp_clock_crosser #(.DATA_WIDTH ( 1), .NUM_CC_REG (3), .INPUT_REG  (1)) u_cdc_reg_11 (.in_clk (fr_clk), .in_data (tpg_is_full      ), .out_clk (cpu_clk),  .out_data (r_cpu_tpg_is_full_meta      ) );
    intel_vvp_clock_crosser #(.DATA_WIDTH ( 1), .NUM_CC_REG (3), .INPUT_REG  (1)) u_cdc_reg_12 (.in_clk (fr_clk), .in_data (tpg_stall_error  ), .out_clk (cpu_clk),  .out_data (r_cpu_tpg_stall_error_meta  ) );
    intel_vvp_clock_crosser #(.DATA_WIDTH ( 1), .NUM_CC_REG (3), .INPUT_REG  (1)) u_cdc_reg_13 (.in_clk (fr_clk), .in_data (tpg_size_mismatch), .out_clk (cpu_clk),  .out_data (r_cpu_tpg_size_mismatch_meta) );
 
 
    localparam              TGL_SAMPLE    = 6;
    logic [TGL_SAMPLE-1:0]  sample_cnt_cpu;
    logic [TGL_SAMPLE-1:0]  sample_cnt_vid;
    logic [TGL_SAMPLE-1:0]  sample_cnt_tpg;
    logic [TGL_SAMPLE-1:0]  sample_cnt_fr;
    logic                   src_tgl_enable_cpu;
    logic                   src_tgl_enable_vid;
    logic                   src_tgl_enable_tpg;
    logic                   src_tgl_enable_fr;
 
    // Let's create a few toggle signals to allow multi-bit CDC
    always_ff @(posedge cpu_clk) begin
        if (cpu_rst) begin
            sample_cnt_cpu <= ({(TGL_SAMPLE){1'b0}});
            src_tgl_enable_cpu <= 1'b0;
      end
        else begin
            if (sample_cnt_cpu >= ({(TGL_SAMPLE){1'b1}})) begin
                sample_cnt_cpu <= ({(TGL_SAMPLE){1'b0}});
                src_tgl_enable_cpu <= ~src_tgl_enable_cpu;
            end
            else begin
                sample_cnt_cpu <= sample_cnt_cpu + 1'b1;
            end
        end
    end
    
    always_ff @(posedge vid_clk) begin
        if (vid_rst) begin
            sample_cnt_vid <= ({(TGL_SAMPLE){1'b0}});
            src_tgl_enable_vid <= 1'b0;
        end
        else begin
            if (sample_cnt_vid >= ({(TGL_SAMPLE){1'b1}})) begin
                sample_cnt_vid <= ({(TGL_SAMPLE){1'b0}});
                src_tgl_enable_vid <= ~src_tgl_enable_vid;
            end
            else begin
                sample_cnt_vid <= sample_cnt_vid + 1'b1;
            end
        end
    end
 
    always_ff @(posedge tpg_clk) begin
        if (tpg_rst) begin
            sample_cnt_tpg <= ({(TGL_SAMPLE){1'b0}});
            src_tgl_enable_tpg <= 1'b0;
        end
        else begin
            if (sample_cnt_tpg >= ({(TGL_SAMPLE){1'b1}})) begin
                sample_cnt_tpg <= ({(TGL_SAMPLE){1'b0}});
                src_tgl_enable_tpg <= ~src_tgl_enable_tpg;
            end
            else begin
                sample_cnt_tpg <= sample_cnt_tpg + 1'b1;
            end
        end
    end
 
    always_ff @(posedge fr_clk) begin
        if (fr_rst) begin
            sample_cnt_fr <= ({(TGL_SAMPLE){1'b0}});
            src_tgl_enable_fr <= 1'b0;
        end
        else begin
            if (sample_cnt_fr >= ({(TGL_SAMPLE){1'b1}})) begin
                sample_cnt_fr <= ({(TGL_SAMPLE){1'b0}});
                src_tgl_enable_fr <= ~src_tgl_enable_fr;
      end
            else begin
                sample_cnt_fr <= sample_cnt_fr + 1'b1;
            end
        end
    end
 
    // multi-bit CDC
    intel_vvp_clock_crosser #(.DATA_WIDTH ( 4), .NUM_CC_REG (3), .INPUT_REG  (1)) u_mb_cdc_reg_14(.in_clk (fr_clk),  .in_data (r_phase                  ), .out_clk (cpu_clk), .out_data (r_cpu_phase                    ) );
 
    intel_vvp_clock_crosser #(.DATA_WIDTH (32), .NUM_CC_REG (3), .INPUT_REG  (1)) u_mb_cdc_reg_15(.in_clk (fr_clk),  .in_data (vid_locked_count         ), .out_clk (cpu_clk), .out_data (r_cpu_vid_locked_count         ) );
    intel_vvp_clock_crosser #(.DATA_WIDTH (32), .NUM_CC_REG (3), .INPUT_REG  (1)) u_mb_cdc_reg_16(.in_clk (fr_clk),  .in_data (vid_stall_count          ), .out_clk (cpu_clk), .out_data (r_cpu_vid_stall_count          ) );
    intel_vvp_clock_crosser #(.DATA_WIDTH (32), .NUM_CC_REG (3), .INPUT_REG  (1)) u_mb_cdc_reg_17(.in_clk (fr_clk),  .in_data (vid_size_err_count       ), .out_clk (cpu_clk), .out_data (r_cpu_vid_size_err_count       ) );
                                                                                                                                                                               
    intel_vvp_clock_crosser #(.DATA_WIDTH (32), .NUM_CC_REG (3), .INPUT_REG  (1)) u_mb_cdc_reg_18(.in_clk (fr_clk),  .in_data (tpg_locked_count         ), .out_clk (cpu_clk), .out_data (r_cpu_tpg_locked_count         ) );
    intel_vvp_clock_crosser #(.DATA_WIDTH (32), .NUM_CC_REG (3), .INPUT_REG  (1)) u_mb_cdc_reg_19(.in_clk (fr_clk),  .in_data (tpg_stall_count          ), .out_clk (cpu_clk), .out_data (r_cpu_tpg_stall_count          ) );
    intel_vvp_clock_crosser #(.DATA_WIDTH (32), .NUM_CC_REG (3), .INPUT_REG  (1)) u_mb_cdc_reg_20(.in_clk (fr_clk),  .in_data (tpg_size_err_count       ), .out_clk (cpu_clk), .out_data (r_cpu_tpg_size_err_count       ) );
                                                                                                       
    intel_vvp_clock_crosser #(.DATA_WIDTH (16), .NUM_CC_REG (3), .INPUT_REG  (1)) u_mb_cdc_reg_21(.in_clk (fr_clk),  .in_data (fr_totalH                ), .out_clk (cpu_clk), .out_data (r_cpu_fr_totalH                ) );
    intel_vvp_clock_crosser #(.DATA_WIDTH (16), .NUM_CC_REG (3), .INPUT_REG  (1)) u_mb_cdc_reg_22(.in_clk (fr_clk),  .in_data (fr_activeH               ), .out_clk (cpu_clk), .out_data (r_cpu_fr_activeH               ) );
    intel_vvp_clock_crosser #(.DATA_WIDTH (16), .NUM_CC_REG (3), .INPUT_REG  (1)) u_mb_cdc_reg_23(.in_clk (fr_clk),  .in_data (fr_totalV                ), .out_clk (cpu_clk), .out_data (r_cpu_fr_totalV                ) );
    intel_vvp_clock_crosser #(.DATA_WIDTH (16), .NUM_CC_REG (3), .INPUT_REG  (1)) u_mb_cdc_reg_24(.in_clk (fr_clk),  .in_data (fr_activeV               ), .out_clk (cpu_clk), .out_data (r_cpu_fr_activeV               ) );
        
    intel_vvp_clock_crosser #(.DATA_WIDTH (16), .NUM_CC_REG (3), .INPUT_REG  (1)) u_mb_cdc_reg_25(.in_clk (vid_clk), .in_data (vid_activeH              ), .out_clk (cpu_clk), .out_data (r_cpu_vid_activeH              ) );
    intel_vvp_clock_crosser #(.DATA_WIDTH (16), .NUM_CC_REG (3), .INPUT_REG  (1)) u_mb_cdc_reg_26(.in_clk (vid_clk), .in_data (vid_activeV              ), .out_clk (cpu_clk), .out_data (r_cpu_vid_activeV              ) );
 
    intel_vvp_clock_crosser #(.DATA_WIDTH (16), .NUM_CC_REG (3), .INPUT_REG  (1)) u_mb_cdc_reg_27(.in_clk (tpg_clk), .in_data (tpg_activeH              ), .out_clk (cpu_clk), .out_data (r_cpu_tpg_activeH              ) );
    intel_vvp_clock_crosser #(.DATA_WIDTH (16), .NUM_CC_REG (3), .INPUT_REG  (1)) u_mb_cdc_reg_28(.in_clk (tpg_clk), .in_data (tpg_activeV              ), .out_clk (cpu_clk), .out_data (r_cpu_tpg_activeV              ) );
 
    intel_vvp_clock_crosser #(.DATA_WIDTH (4*BPS), .NUM_CC_REG (3), .INPUT_REG  (1)) u_mb_cdc_reg_29(.in_clk (cpu_clk), .in_data (r_cpu_black           ), .out_clk (fr_clk),  .out_data (r_vid_black                    ) );
 
    always_ff @(posedge cpu_clk)
    begin:a_latch_status
      if (cpu_rst)
      begin
        r_cpu_vid_locked        <= 1'b0;
        r_cpu_vid_is_full       <= 1'b0;
        r_cpu_vid_stall_error   <= 1'b0;
        r_cpu_vid_size_mismatch <= 1'b0;
 
        r_cpu_tpg_locked        <= 1'b0;
        r_cpu_tpg_is_full       <= 1'b0;
        r_cpu_tpg_stall_error   <= 1'b0;
        r_cpu_tpg_size_mismatch <= 1'b0;
        r_cpu_clear_status      <= 1'b1;
        r2_cpu_clear_status     <= 1'b1;
      end
      else
      begin
        
        r2_cpu_clear_status           <= r_cpu_clear_status;
 
        if (av_address == C_REG_STATUS && av_read)
          r_cpu_clear_status          <= 1'b1;
        else 
          r_cpu_clear_status          <= 1'b0;
          
        if (r2_cpu_clear_status && !r_cpu_clear_status)
        begin
          r_cpu_vid_locked            <= r_cpu_vid_locked_meta;
          r_cpu_vid_is_full           <= r_cpu_vid_is_full_meta;
          r_cpu_vid_stall_error       <= r_cpu_vid_stall_error_meta;
          r_cpu_vid_size_mismatch     <= r_cpu_vid_size_mismatch_meta;
 
          r_cpu_tpg_locked            <= r_cpu_tpg_locked_meta;
          r_cpu_tpg_is_full           <= r_cpu_tpg_is_full_meta;
          r_cpu_tpg_stall_error       <= r_cpu_tpg_stall_error_meta;
          r_cpu_tpg_size_mismatch     <= r_cpu_tpg_size_mismatch_meta;
        end
        else
        begin
          r_cpu_vid_locked            <= r_cpu_vid_locked           || r_cpu_vid_locked_meta;
          r_cpu_vid_is_full           <= r_cpu_vid_is_full          || r_cpu_vid_is_full_meta;
          r_cpu_vid_stall_error       <= r_cpu_vid_stall_error      || r_cpu_vid_stall_error_meta;
          r_cpu_vid_size_mismatch     <= r_cpu_vid_size_mismatch    || r_cpu_vid_size_mismatch_meta;
 
          r_cpu_tpg_locked            <= r_cpu_tpg_locked           || r_cpu_tpg_locked_meta;
          r_cpu_tpg_is_full           <= r_cpu_tpg_is_full          || r_cpu_tpg_is_full_meta;
          r_cpu_tpg_stall_error       <= r_cpu_tpg_stall_error      || r_cpu_tpg_stall_error_meta;
          r_cpu_tpg_size_mismatch     <= r_cpu_tpg_size_mismatch    || r_cpu_tpg_size_mismatch_meta;
        end
      end
    end
 
    always_ff @(posedge cpu_clk)
    begin:a_make_cpu_regs
      logic [31:0] nb_local_reg32;
      if (cpu_rst)
      begin
        // cpu sigs
        av_waitrequest            <= 1'b1;
        av_readdata               <= 32'b0;
        av_readdatavalid          <= 1'b0;
        
        r_cpu_black               <= {C_DEFAULT_BLACK_3[BPS-1:0] , C_DEFAULT_BLACK_2[BPS-1:0] , C_DEFAULT_BLACK_1[BPS-1:0] , C_DEFAULT_BLACK_0[BPS-1:0]};
        r_cpu_do_recover          <= 1'b0;
        r2_cpu_do_recover         <= 1'b0;
        r_cpu_do_recover_toggle   <= 1'b0;
        
        r_cpu_auto_recover        <= 1'b1;
        r_cpu_force_black         <= 1'b0;
        r_cpu_force_tpg           <= 1'b0;
        r_cpu_force_vid           <= 1'b0;
       
      end
      else
      begin
        av_waitrequest            <= 1'b0;
        r_cpu_do_recover          <= 1'b0;
        r2_cpu_do_recover         <= r_cpu_do_recover;
        if (r2_cpu_do_recover && !r_cpu_do_recover)
          r_cpu_do_recover_toggle   <= ~r_cpu_do_recover_toggle;
          
        av_readdatavalid  <= r_av_read;
        av_readdata       <= 32'b0;
        nb_local_reg32     = 32'b0;
        case (r_av_address)
          /*  0 */
          C_REG_STATUS        : begin
                                  nb_local_reg32[0]        = r_cpu_vid_locked;
                                  nb_local_reg32[1]        = r_cpu_vid_is_full;
                                  nb_local_reg32[2]        = r_cpu_vid_stall_error;
                                  nb_local_reg32[3]        = r_cpu_vid_size_mismatch;
 
                                  nb_local_reg32[4]        = r_cpu_tpg_locked;
                                  nb_local_reg32[5]        = r_cpu_tpg_is_full;
                                  nb_local_reg32[6]        = r_cpu_tpg_stall_error;
                                  nb_local_reg32[7]        = r_cpu_tpg_size_mismatch;
                                  
                                  nb_local_reg32[11:8]     = r_cpu_phase;
 
                                  av_readdata             <= nb_local_reg32;
                                end
          /*  1 */
          C_REG_BLACK_0       : begin
                                  nb_local_reg32[BPS-1:0] = r_cpu_black[BPS*0+:BPS];
                                  av_readdata          <= nb_local_reg32;
                                  t_cpu_write(r_av_write , r_av_byteenable , r_av_writedata , nb_local_reg32);
                                  r_cpu_black[BPS*0+:BPS] <= nb_local_reg32[BPS-1:0];
                                end
          /*  2 */
          C_REG_BLACK_1       : begin
                                  if (NUMBER_OF_COLOR_PLANES > 1) begin
                                    nb_local_reg32[BPS-1:0] = r_cpu_black[BPS*1+:BPS];
                                    av_readdata          <= nb_local_reg32;
                                    t_cpu_write(r_av_write , r_av_byteenable , r_av_writedata , nb_local_reg32);
                                    r_cpu_black[BPS*1+:BPS] <= nb_local_reg32[BPS-1:0];
                                  end
                                  else begin
                                    av_readdata <= VVP_OUT_OF_RANGE_REG_READ_RET_VALUE;
                                  end
                                end
          /*  3 */
          C_REG_BLACK_2       : begin
                                  if (NUMBER_OF_COLOR_PLANES > 2) begin
                                    nb_local_reg32[BPS-1:0] = r_cpu_black[BPS*2+:BPS];
                                    av_readdata          <= nb_local_reg32;
                                    t_cpu_write(r_av_write , r_av_byteenable , r_av_writedata , nb_local_reg32);
                                    r_cpu_black[BPS*2+:BPS] <= nb_local_reg32[BPS-1:0];
                                  end
                                  else begin
                                    av_readdata <= VVP_OUT_OF_RANGE_REG_READ_RET_VALUE;
                                  end
                                end
          /*  4 */
          C_REG_BLACK_3       : begin
                                  if (NUMBER_OF_COLOR_PLANES > 3) begin
                                    nb_local_reg32[BPS-1:0] = r_cpu_black[BPS*3+:BPS];
                                    av_readdata          <= nb_local_reg32;
                                    t_cpu_write(r_av_write , r_av_byteenable , r_av_writedata , nb_local_reg32);
                                    r_cpu_black[BPS*3+:BPS] <= nb_local_reg32[BPS-1:0];
                                  end
                                  else begin
                                    av_readdata <= VVP_OUT_OF_RANGE_REG_READ_RET_VALUE;
                                  end
                                end
          /*  5 */
          C_REG_FALLBACK      : begin
                                  nb_local_reg32[0]     = r_cpu_auto_recover; // default = 1'b1
                                  nb_local_reg32[1]     = r_cpu_force_black;  // default = 1'b0
                                  nb_local_reg32[2]     = r_cpu_force_tpg;    // default = 1'b0
                                  nb_local_reg32[3]     = r_cpu_force_vid;    // default = 1'b0
 
                                  av_readdata             <= nb_local_reg32;
                                  t_cpu_write(r_av_write , r_av_byteenable , r_av_writedata , nb_local_reg32);
                                  r_cpu_auto_recover    <= nb_local_reg32[0];
                                  r_cpu_force_black     <= nb_local_reg32[1];
                                  r_cpu_force_tpg       <= nb_local_reg32[2];
                                  r_cpu_force_vid       <= nb_local_reg32[3];
                                  r_cpu_do_recover      <= nb_local_reg32[31];
                                end
          /*  6 */
          C_REG_FR_H_DIMS     : begin
                                  if (C_TIM_DIMENSIONS>0)
                                  begin
                                    nb_local_reg32[15: 0] = r_cpu_fr_totalH;
                                    nb_local_reg32[31:16] = r_cpu_fr_activeH;
                                    av_readdata             <= nb_local_reg32;
                                  end
                                  else
                                    av_readdata <= VVP_OUT_OF_RANGE_REG_READ_RET_VALUE;
                                end
          /*  7 */
          C_REG_FR_V_DIMS     : begin
                                  if (C_TIM_DIMENSIONS>0)
                                  begin
                                    nb_local_reg32[15: 0] = r_cpu_fr_totalV;
                                    nb_local_reg32[31:16] = r_cpu_fr_activeV;
                                    av_readdata             <= nb_local_reg32;
                                  end
                                  else
                                    av_readdata <= VVP_OUT_OF_RANGE_REG_READ_RET_VALUE;
                                end
          /*  8 */
          C_REG_FR_FREQ_DIMS  : begin
                                  if (C_TIM_DIMENSIONS>0)
                                  begin
                                    av_readdata             <= fr_vid_clk_freq;
                                  end
                                  else
                                    av_readdata <= VVP_OUT_OF_RANGE_REG_READ_RET_VALUE;
                                end
          /*  9 */
          C_REG_FR_CLKS_DIMS  : begin
                                  if (C_TIM_DIMENSIONS>0)
                                  begin
                                    av_readdata             <= fr_vid_clks_per_frame;
                                  end
                                  else
                                    av_readdata <= VVP_OUT_OF_RANGE_REG_READ_RET_VALUE;
                                end
          /* 10 */
          C_REG_VID_DIMS      : begin
                                  if (C_VID_DIMENSIONS>0)
                                  begin
                                    nb_local_reg32[15: 0] = r_cpu_vid_activeH;
                                    nb_local_reg32[31:16] = r_cpu_vid_activeV;
                                    av_readdata             <= nb_local_reg32;
                                  end
                                  else
                                    av_readdata <= VVP_OUT_OF_RANGE_REG_READ_RET_VALUE;
                                end
          /* 11 */
          C_REG_VID_FREQ_DIMS : begin
                                  if (C_VID_DIMENSIONS>0)
                                  begin
                                    av_readdata             <= vid_vid_clk_freq;
                                  end
                                  else
                                    av_readdata <= VVP_OUT_OF_RANGE_REG_READ_RET_VALUE;
                                end
          /* 12 */
          C_REG_VID_CLKS_DIMS : begin
                                  if (C_VID_DIMENSIONS>0)
                                  begin
                                    av_readdata             <= vid_vid_clks_per_frame;
                                  end
                                  else
                                    av_readdata <= VVP_OUT_OF_RANGE_REG_READ_RET_VALUE;
                                end
          /* 13 */
          C_REG_TPG_DIMS      : begin
                                  if (C_TPG_DIMENSIONS>0)
                                  begin
                                    nb_local_reg32[15: 0] = r_cpu_tpg_activeH;
                                    nb_local_reg32[31:16] = r_cpu_tpg_activeV;
                                    av_readdata             <= nb_local_reg32;
                                  end
                                  else
                                    av_readdata <= VVP_OUT_OF_RANGE_REG_READ_RET_VALUE;
                                end
          /* 14 */
          C_REG_TPG_FREQ_DIMS : begin
                                  if (C_TPG_DIMENSIONS>0)
                                  begin
                                    av_readdata             <= tpg_vid_clk_freq;
                                  end
                                  else
                                    av_readdata <= VVP_OUT_OF_RANGE_REG_READ_RET_VALUE;
                                end
          /* 15 */
          C_REG_TPG_CLKS_DIMS : begin
                                  if (C_TPG_DIMENSIONS>0)
                                  begin
                                    av_readdata             <= tpg_vid_clks_per_frame;
                                  end
                                  else
                                    av_readdata <= VVP_OUT_OF_RANGE_REG_READ_RET_VALUE;
                                end
          /* 16 */
          C_REG_VID_LOCKED_COUNT    : if (C_VID_DEBUG>0)  av_readdata <= r_cpu_vid_locked_count;
                                      else                av_readdata <= VVP_OUT_OF_RANGE_REG_READ_RET_VALUE;
          /* 17 */
          C_REG_VID_SIZE_ERR_COUNT  : if (C_VID_DEBUG>0)  av_readdata <= r_cpu_vid_size_err_count;
                                      else                av_readdata <= VVP_OUT_OF_RANGE_REG_READ_RET_VALUE;
          /* 18 */
          C_REG_VID_STALL_COUNT     : if (C_VID_DEBUG>0)  av_readdata <= r_cpu_vid_stall_count;
                                      else                av_readdata <= VVP_OUT_OF_RANGE_REG_READ_RET_VALUE;
 
          /* 19 */
          C_REG_TPG_LOCKED_COUNT    : if (C_TPG_DEBUG>0)  av_readdata <= r_cpu_tpg_locked_count;
                                      else                av_readdata <= VVP_OUT_OF_RANGE_REG_READ_RET_VALUE;
          /* 20 */
          C_REG_TPG_SIZE_ERR_COUNT  : if (C_TPG_DEBUG>0)  av_readdata <= r_cpu_tpg_size_err_count;
                                      else                av_readdata <= VVP_OUT_OF_RANGE_REG_READ_RET_VALUE;
          /* 21 */
          C_REG_TPG_STALL_COUNT     : if (C_TPG_DEBUG>0)  av_readdata <= r_cpu_tpg_stall_count;
                                      else                av_readdata <= VVP_OUT_OF_RANGE_REG_READ_RET_VALUE;
 
 
          default: av_readdata <= VVP_OUT_OF_RANGE_REG_READ_RET_VALUE;
        endcase
      end
    end
  end
  else begin
    always_comb
    begin
      // cpu sigs
      av_waitrequest          = 1'b1;
      av_readdata             = 32'b0;
      av_readdatavalid        = 1'b0;
 
      r_vid_black             = {C_DEFAULT_BLACK_3[BPS-1:0] , C_DEFAULT_BLACK_2[BPS-1:0] , C_DEFAULT_BLACK_1[BPS-1:0] , C_DEFAULT_BLACK_0[BPS-1:0]};
      r_vid_do_recover_toggle = 1'b0;
      r_vid_auto_recover      = 1'b1;
      
      r_vid_force_tpg         = 1'b0;
      r_vid_force_vid         = 1'b0;
      r_vid_force_black       = 1'b0;
    end
  end
endgenerate
 
endmodule
`default_nettype wire
`ifdef QUESTA_INTEL_OEM
`pragma questa_oem_00 "6vv+NLMwKGCERPrXQet892N4C1uCcErmxLgPyMYhdyaOVp6v3RudhNcA/7XKciBkOPUl2PgJ7/ZUbVxqHQKKzrSdlNXKta3IsnCAq/J9MkOatE4scrQhqz7jz78naosjfxAIOYUnLEA1oR4TKsq17eekHtg6YxLDUNA4tyS3nu/F6+GYYnJsFdi8wNo4AExJNjRD7CqV+JQu8Wz0b9258XsQQ2oy9clPj5jgEPEBfOzrsQDsJXu3EyD4YXj6yn1MNeCLQPnBEBye6mVTjsbw7A5WN0oALMJBgWxwOqdm3e3vgckCAXaP1RyLizA/MDXfC2MbMZF4s/Y7EmJZxHERrSbMPnfWUDH2X61S2y8HW2lbSkLsmgJF1RclRg0li2oVq62sO1/bRS+H3s4LLnGv5HHkdqaK9kYwNr8UUlp2o6EyjjY3dtXJX7Y1wTMghbkuKNmPt6o7hAX2azplLIf628q3pS4v85qB+ICQ4OMIKG6xHdOIUUHEI0z4ThNp8NpdBLh+U9EsYvHPoDQVrmFhq4EDGUQdddtNgGFKaXDg5a47uM2OZ6zlfGuki7PGl6LjKI9EJN/YR92+2tg72WbPp0lRkMsUP8Pkekcv5MI1/glV36+XvxlNB2jVm3/OzuCXS/oea/b2S26DKrbf0wBmAWIIml0WnLFNUVZiwFI//BxJQxC52pq6MjUsRwx883TZ9oZSSNbrB5Al6LLrt4IdktKQDnIuHQfs+ZqiL010ZqtZ87+Rp0i7ZGJzvEshLtoqjY04tXAUj32trgrUhXOeHBMzOJcIcIYT6i86IrN4AVILPsPz275Ng42gA7++92Os/VVbSCxwtzLr9DANVrXFMkfFtObVeGKHmEaHVFKHeSeERF4cXUk7hA2yVisWQ/JgPmpHEhs/exIOnOo5kdkw4hiU9lAtDqrss2nzEZm1h9Iv9X9XQ76/a9tGA3U5j3EhT3gtnJui11ho5plUPgeGXFO/oCZ2qis4rnsBUah0BLe6qk5DM2NVxrRteoNIFjKm"
`endif