/*******************************************************************************
* Module: x393_testbench02
* Date:2015-02-06
* Author: Andrey Filippov
* Description: testbench for the initial x393.v simulation
*
* Copyright (c) 2015 Elphel, Inc.
* x393_testbench02.v is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* x393_testbench02.tf 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*******************************************************************************/
`timescale 1ns/1ps
`include "system_defines.vh"
//`define use200Mhz 1
//`define DEBUG_FIFO 1
`undef WAIT_MRS
`define SET_PER_PIN_DELAYS 1 // set individual (including per-DQ pin delays)
`define READBACK_DELAYS 1
`define PS_PIO_WAIT_COMPLETE 0 // wait until PS PIO module finished transaction before starting a new one
// Disabled already passed test to speedup simulation
//`define TEST_WRITE_LEVELLING 1
//`define TEST_READ_PATTERN 1
//`define TEST_WRITE_BLOCK 1
//`define TEST_READ_BLOCK 1
//`define TEST_SCANLINE_WRITE
`define TEST_SCANLINE_WRITE_WAIT 1 // wait TEST_SCANLINE_WRITE finished (frame_done)
//`define TEST_SCANLINE_READ
`define TEST_READ_SHOW 1
//`define TEST_TILED_WRITE 1
`define TEST_TILED_WRITE_WAIT 1 // wait TEST_SCANLINE_WRITE finished (frame_done)
//`define TEST_TILED_READ 1
//`define TEST_TILED_WRITE32 1
//`define TEST_TILED_READ32 1
`define TEST_AFI_WRITE 1
`define TEST_AFI_READ 1
module x393_testbench02 #(
`include "includes/x393_parameters.vh" // SuppressThisWarning VEditor - not used
`include "includes/x393_simulation_parameters.vh"
)(
);
`ifdef IVERILOG
// $display("IVERILOG is defined");
`ifdef NON_VDT_ENVIROMENT
parameter lxtname="x393.lxt";
`else
`include "IVERILOG_INCLUDE.v"
`endif // NON_VDT_ENVIROMENT
`else // IVERILOG
// $display("IVERILOG is not defined");
`ifdef CVC
`ifdef NON_VDT_ENVIROMENT
parameter lxtname = "x393.fst";
`else // NON_VDT_ENVIROMENT
`include "IVERILOG_INCLUDE.v"
`endif // NON_VDT_ENVIROMENT
`else
parameter lxtname = "x393.lxt";
`endif // CVC
`endif // IVERILOG
`define DEBUG_WR_SINGLE 1
`define DEBUG_RD_DATA 1
//`include "includes/x393_cur_params_sim.vh" // parameters that may need adjustment, should be before x393_localparams.vh
`include "includes/x393_cur_params_target.vh" // SuppressThisWarning VEditor - not used parameters that may need adjustment, should be before x393_localparams.vh
`include "includes/x393_localparams.vh" // SuppressThisWarning VEditor - not used
// ========================== parameters from x353 ===================================
`ifdef SYNC_COMPRESS
parameter DEPEND=1'b1;
`else
parameter DEPEND=1'b0;
`endif
`ifdef TEST_ABORT
`endif
parameter SYNC_BIT_LENGTH=8-1; /// 7 pixel clock pulses
parameter FPGA_XTRA_CYCLES= 1500; // 1072+;
// moved to x393_simulation_parameters.vh
// parameter HISTOGRAM_LEFT= 0; //2; // left
// parameter HISTOGRAM_TOP = 2; // top
// parameter HISTOGRAM_WIDTH= 6; // width
// parameter HISTOGRAM_HEIGHT=6; // height
parameter CLK0_PER = 6.25; //160MHz
parameter CLK1_PER = 10.4; //96MHz
parameter CLK3_PER = 83.33; //12MHz
parameter CPU_PER=10.4;
parameter HBLANK= 12; /// 52;
parameter WOI_HEIGHT= 32;
parameter BLANK_ROWS_BEFORE= 1; //8; ///2+2 - a little faster than compressor
parameter BLANK_ROWS_AFTER= 1; //8;
parameter TRIG_LINES= 8;
parameter VBLANK= 2; /// 2 lines //SuppressThisWarning Veditor UNUSED
parameter CYCLES_PER_PIXEL= 3; /// 2 for JP4, 3 for JPEG
`ifdef PF
parameter PF_HEIGHT=8;
parameter FULL_HEIGHT=WOI_HEIGHT;
parameter PF_STRIPES=WOI_HEIGHT/PF_HEIGHT;
`else
parameter PF_HEIGHT=0;
parameter FULL_HEIGHT=WOI_HEIGHT+4;
parameter PF_STRIPES=0;
`endif
parameter VIRTUAL_WIDTH= FULL_WIDTH + HBLANK;
parameter VIRTUAL_HEIGHT= FULL_HEIGHT + BLANK_ROWS_BEFORE + BLANK_ROWS_AFTER; //SuppressThisWarning Veditor UNUSED
parameter TRIG_INTERFRAME= 100; /// extra 100 clock cycles between frames //SuppressThisWarning Veditor UNUSED
/// parameter TRIG_OUT_DATA= 'h80000; // internal cable
/// parameter TRIG_EXTERNAL_INPUT= 'h20000; // internal cable, low level on EXT[8]
parameter TRIG_DELAY= 200; /// delay in sensor clock cycles
parameter FULL_WIDTH= WOI_WIDTH+4;
// ========================== end of parameters from x353 ===================================
// Sensor signals - as on sensor pads
wire PX1_MCLK; // input sensor input clock
wire PX1_MRST; // input
wire PX1_ARO; // input
wire PX1_ARST; // input
wire PX1_OFST = 1'b1; // input // I2C address ofset by 2: for simulation 0 - still mode, 1 - video mode.
wire [11:0] PX1_D; // output[11:0]
wire PX1_DCLK; // output sensor output clock (connect to sensor BPF output )
wire PX1_HACT; // output
wire PX1_VACT; // output
// Sensor signals - as on FPGA pads
wire [ 7:0] sns1_dp; // inout[7:0] {PX_MRST, PXD8, PXD6, PXD4, PXD2, PXD0, PX_HACT, PX_DCLK}
wire [ 7:0] sns1_dn; // inout[7:0] {PX_ARST, PXD9, PXD7, PXD5, PXD3, PXD1, PX_VACT, PX_BPF}
wire sns1_clkp; // inout CNVCLK/TDO
wire sns1_clkn; // inout CNVSYNC/TDI
wire sns1_scl; // inout PX_SCL
wire sns1_sda; // inout PX_SDA
wire sns1_ctl; // inout PX_ARO/TCK
wire sns1_pg; // inout SENSPGM
//connect sensor to sensor port 1
assign sns1_dp[6:1] = {PX1_D[10], PX1_D[8], PX1_D[6], PX1_D[4], PX1_D[2], PX1_HACT};
assign PX1_MRST = sns1_dp[7]; // from FPGA to sensor
assign PX1_MCLK = sns1_dp[0]; // from FPGA to sensor
assign sns1_dn[6:0] = {PX1_D[11], PX1_D[9], PX1_D[7], PX1_D[5], PX1_D[3], PX1_VACT, PX1_DCLK};
assign PX1_ARST = sns1_dn[7];
assign sns1_clkn = PX1_D[0]; // inout CNVSYNC/TDI
assign sns1_scl = PX1_D[1]; // inout PX_SCL
assign PX1_ARO = sns1_ctl; // from FPGA to sensor
wire [ 7:0] sns2_dp; // inout[7:0] {PX_MRST, PXD8, PXD6, PXD4, PXD2, PXD0, PX_HACT, PX_DCLK}
wire [ 7:0] sns2_dn; // inout[7:0] {PX_ARST, PXD9, PXD7, PXD5, PXD3, PXD1, PX_VACT, PX_BPF}
wire sns2_clkp; // inout CNVCLK/TDO
wire sns2_clkn; // inout CNVSYNC/TDI
wire sns2_scl; // inout PX_SCL
wire sns2_sda; // inout PX_SDA
wire sns2_ctl; // inout PX_ARO/TCK
wire sns2_pg; // inout SENSPGM
wire [ 7:0] sns3_dp; // inout[7:0] {PX_MRST, PXD8, PXD6, PXD4, PXD2, PXD0, PX_HACT, PX_DCLK}
wire [ 7:0] sns3_dn; // inout[7:0] {PX_ARST, PXD9, PXD7, PXD5, PXD3, PXD1, PX_VACT, PX_BPF}
wire sns3_clkp; // inout CNVCLK/TDO
wire sns3_clkn; // inout CNVSYNC/TDI
wire sns3_scl; // inout PX_SCL
wire sns3_sda; // inout PX_SDA
wire sns3_ctl; // inout PX_ARO/TCK
wire sns3_pg; // inout SENSPGM
wire [ 7:0] sns4_dp; // inout[7:0] {PX_MRST, PXD8, PXD6, PXD4, PXD2, PXD0, PX_HACT, PX_DCLK}
wire [ 7:0] sns4_dn; // inout[7:0] {PX_ARST, PXD9, PXD7, PXD5, PXD3, PXD1, PX_VACT, PX_BPF}
wire sns4_clkp; // inout CNVCLK/TDO
wire sns4_clkn; // inout CNVSYNC/TDI
wire sns4_scl; // inout PX_SCL
wire sns4_sda; // inout PX_SDA
wire sns4_ctl; // inout PX_ARO/TCK
wire sns4_pg; // inout SENSPGM
wire [ 9:0] gpio_pins; // inout[9:0] ([6]-synco0,[7]-syncio0,[8]-synco1,[9]-syncio1)
// Connect trigger outs to triggets in (#10 needed for Icarus)
assign #10 gpio_pins[7] = gpio_pins[6];
assign #10 gpio_pins[9] = gpio_pins[8];
// DDR3 signals
wire SDRST;
wire SDCLK; // output
wire SDNCLK; // output
wire [ADDRESS_NUMBER-1:0] SDA; // output[14:0]
wire [ 2:0] SDBA; // output[2:0]
wire SDWE; // output
wire SDRAS; // output
wire SDCAS; // output
wire SDCKE; // output
wire SDODT; // output
wire [15:0] SDD; // inout[15:0]
wire SDDML; // inout
wire DQSL; // inout
wire NDQSL; // inout
wire SDDMU; // inout
wire DQSU; // inout
wire NDQSU; // inout
wire DUMMY_TO_KEEP; // output to keep PS7 signals from "optimization" // SuppressThisWarning all - not used
wire memclk;
wire ffclk0p; // input
wire ffclk0n; // input
wire ffclk1p; // input
wire ffclk1n; // input
// axi_hp simulation signals
wire HCLK;
wire [31:0] afi_sim_rd_address; // output[31:0]
wire [ 5:0] afi_sim_rid; // output[5:0] SuppressThisWarning VEditor - not used - just view
// reg afi_sim_rd_valid; // input
wire afi_sim_rd_valid; // input
wire afi_sim_rd_ready; // output
// reg [63:0] afi_sim_rd_data; // input[63:0]
wire [63:0] afi_sim_rd_data; // input[63:0]
wire [ 2:0] afi_sim_rd_cap; // output[2:0] SuppressThisWarning VEditor - not used - just view
wire [ 3:0] afi_sim_rd_qos; // output[3:0] SuppressThisWarning VEditor - not used - just view
wire [ 1:0] afi_sim_rd_resp; // input[1:0]
// reg [ 1:0] afi_sim_rd_resp; // input[1:0]
wire [31:0] afi_sim_wr_address; // output[31:0] SuppressThisWarning VEditor - not used - just view
wire [ 5:0] afi_sim_wid; // output[5:0] SuppressThisWarning VEditor - not used - just view
wire afi_sim_wr_valid; // output
wire afi_sim_wr_ready; // input
// reg afi_sim_wr_ready; // input
wire [63:0] afi_sim_wr_data; // output[63:0] SuppressThisWarning VEditor - not used - just view
wire [ 7:0] afi_sim_wr_stb; // output[7:0] SuppressThisWarning VEditor - not used - just view
wire [ 3:0] afi_sim_bresp_latency; // input[3:0]
// reg [ 3:0] afi_sim_bresp_latency; // input[3:0]
wire [ 2:0] afi_sim_wr_cap; // output[2:0] SuppressThisWarning VEditor - not used - just view
wire [ 3:0] afi_sim_wr_qos; // output[3:0] SuppressThisWarning VEditor - not used - just view
assign HCLK = x393_i.ps7_i.SAXIHP0ACLK; // shortcut name
// afi loopback
assign #1 afi_sim_rd_data= afi_sim_rd_ready?{2'h0,afi_sim_rd_address[31:3],1'h1, 2'h0,afi_sim_rd_address[31:3],1'h0}:64'bx;
assign #1 afi_sim_rd_valid = afi_sim_rd_ready;
assign #1 afi_sim_rd_resp = afi_sim_rd_ready?2'b0:2'bx;
assign #1 afi_sim_wr_ready = afi_sim_wr_valid;
assign #1 afi_sim_bresp_latency=4'h5;
// SAXI_GP0 - histograms to system memory
wire SAXI_GP0_CLK;
wire [31:0] saxi_gp0_sim_wr_address; // output[31:0] SuppressThisWarning VEditor - not used - just view
wire [ 5:0] saxi_gp0_sim_wid; // output[5:0] SuppressThisWarning VEditor - not used - just view
wire saxi_gp0_sim_wr_valid; // output
wire saxi_gp0_sim_wr_ready; // input
wire [31:0] saxi_gp0_sim_wr_data; // output[31:0] SuppressThisWarning VEditor - not used - just view
wire [ 3:0] saxi_gp0_sim_wr_stb; // output[3:0] SuppressThisWarning VEditor - not used - just view
wire [ 1:0] saxi_gp0_sim_wr_size; // output[1:0] SuppressThisWarning VEditor - not used - just view
wire [ 3:0] saxi_gp0_sim_bresp_latency; // input[3:0]
wire [ 3:0] saxi_gp0_sim_wr_qos; // output[3:0] SuppressThisWarning VEditor - not used - just view
assign SAXI_GP0_CLK = x393_i.ps7_i.SAXIGP0ACLK;
assign #1 saxi_gp0_sim_wr_ready = saxi_gp0_sim_wr_valid;
assign #1 saxi_gp0_sim_bresp_latency=4'h5;
// axi_hp register access
// PS memory mapped registers to read/write over a separate simulation bus running at HCLK, no waits
reg [31:0] PS_REG_ADDR;
reg PS_REG_WR;
reg PS_REG_RD;
reg [31:0] PS_REG_DIN;
wire [31:0] PS_REG_DOUT;
reg [31:0] PS_RDATA; // SuppressThisWarning VEditor - not used - just view
/*
reg [31:0] afi_reg_addr;
reg afi_reg_wr;
reg afi_reg_rd;
reg [31:0] afi_reg_din;
wire [31:0] afi_reg_dout;
reg [31:0] AFI_REG_RD; // SuppressThisWarning VEditor - not used - just view
*/
initial begin
PS_REG_ADDR <= 'bx;
PS_REG_WR <= 0;
PS_REG_RD <= 0;
PS_REG_DIN <= 'bx;
PS_RDATA <= 'bx;
end
always @ (posedge HCLK) if (PS_REG_RD) PS_RDATA <= PS_REG_DOUT;
reg [639:0] TEST_TITLE;
// Simulation signals
reg [11:0] ARID_IN_r;
reg [31:0] ARADDR_IN_r;
reg [3:0] ARLEN_IN_r;
reg [2:0] ARSIZE_IN_r;
reg [1:0] ARBURST_IN_r;
reg [11:0] AWID_IN_r;
reg [31:0] AWADDR_IN_r;
reg [3:0] AWLEN_IN_r;
reg [2:0] AWSIZE_IN_r;
reg [1:0] AWBURST_IN_r;
reg [11:0] WID_IN_r;
reg [31:0] WDATA_IN_r;
reg [ 3:0] WSTRB_IN_r;
reg WLAST_IN_r;
reg [11:0] LAST_ARID; // last issued ARID
// SuppressWarnings VEditor : assigned in $readmem() system task
wire [SIMUL_AXI_READ_WIDTH-1:0] SIMUL_AXI_ADDR_W;
// SuppressWarnings VEditor
wire SIMUL_AXI_MISMATCH;
// SuppressWarnings VEditor
reg [31:0] SIMUL_AXI_READ;
// SuppressWarnings VEditor
reg [SIMUL_AXI_READ_WIDTH-1:0] SIMUL_AXI_ADDR;
// SuppressWarnings VEditor
reg SIMUL_AXI_FULL; // some data available
wire SIMUL_AXI_EMPTY= ~rvalid && rready && (rid==LAST_ARID); //SuppressThisWarning VEditor : may be unused, just for simulation // use it to wait for?
reg [31:0] registered_rdata; // here read data from tasks goes
// SuppressWarnings VEditor
reg WAITING_STATUS; // tasks are waiting for status
wire CLK;
reg RST;
reg AR_SET_CMD_r;
wire AR_READY;
reg AW_SET_CMD_r;
wire AW_READY;
reg W_SET_CMD_r;
wire W_READY;
wire [11:0] #(AXI_TASK_HOLD) ARID_IN = ARID_IN_r;
wire [31:0] #(AXI_TASK_HOLD) ARADDR_IN = ARADDR_IN_r;
wire [3:0] #(AXI_TASK_HOLD) ARLEN_IN = ARLEN_IN_r;
wire [2:0] #(AXI_TASK_HOLD) ARSIZE_IN = ARSIZE_IN_r;
wire [1:0] #(AXI_TASK_HOLD) ARBURST_IN = ARBURST_IN_r;
wire [11:0] #(AXI_TASK_HOLD) AWID_IN = AWID_IN_r;
wire [31:0] #(AXI_TASK_HOLD) AWADDR_IN = AWADDR_IN_r;
wire [3:0] #(AXI_TASK_HOLD) AWLEN_IN = AWLEN_IN_r;
wire [2:0] #(AXI_TASK_HOLD) AWSIZE_IN = AWSIZE_IN_r;
wire [1:0] #(AXI_TASK_HOLD) AWBURST_IN = AWBURST_IN_r;
wire [11:0] #(AXI_TASK_HOLD) WID_IN = WID_IN_r;
wire [31:0] #(AXI_TASK_HOLD) WDATA_IN = WDATA_IN_r;
wire [ 3:0] #(AXI_TASK_HOLD) WSTRB_IN = WSTRB_IN_r;
wire #(AXI_TASK_HOLD) WLAST_IN = WLAST_IN_r;
wire #(AXI_TASK_HOLD) AR_SET_CMD = AR_SET_CMD_r;
wire #(AXI_TASK_HOLD) AW_SET_CMD = AW_SET_CMD_r;
wire #(AXI_TASK_HOLD) W_SET_CMD = W_SET_CMD_r;
reg [3:0] RD_LAG; // ready signal lag in axi read channel (0 - RDY=1, 1..15 - RDY is asserted N cycles after valid)
reg [3:0] B_LAG; // ready signal lag in axi arete response channel (0 - RDY=1, 1..15 - RDY is asserted N cycles after valid)
// Simulation modules interconnection
wire [11:0] arid;
wire [31:0] araddr;
wire [3:0] arlen;
wire [2:0] arsize;
wire [1:0] arburst;
// SuppressWarnings VEditor : assigned in $readmem(14) system task
wire [3:0] arcache;
// SuppressWarnings VEditor : assigned in $readmem() system task
wire [2:0] arprot;
wire arvalid;
wire arready;
wire [11:0] awid;
wire [31:0] awaddr;
wire [3:0] awlen;
wire [2:0] awsize;
wire [1:0] awburst;
// SuppressWarnings VEditor : assigned in $readmem() system task
wire [3:0] awcache;
// SuppressWarnings VEditor : assigned in $readmem() system task
wire [2:0] awprot;
wire awvalid;
wire awready;
wire [11:0] wid;
wire [31:0] wdata;
wire [3:0] wstrb;
wire wlast;
wire wvalid;
wire wready;
wire [31:0] rdata;
// SuppressWarnings VEditor : assigned in $readmem() system task
wire [11:0] rid;
wire rlast;
// SuppressWarnings VEditor : assigned in $readmem() system task
wire [1:0] rresp;
wire rvalid;
wire rready;
wire rstb=rvalid && rready;
// SuppressWarnings VEditor : assigned in $readmem() system task
wire [1:0] bresp;
// SuppressWarnings VEditor : assigned in $readmem() system task
wire [11:0] bid;
wire bvalid;
wire bready;
integer NUM_WORDS_READ;
integer NUM_WORDS_EXPECTED;
reg [15:0] ENABLED_CHANNELS = 0; // currently enabled memory channels
// integer SCANLINE_CUR_X;
// integer SCANLINE_CUR_Y;
wire AXI_RD_EMPTY=NUM_WORDS_READ==NUM_WORDS_EXPECTED; //SuppressThisWarning VEditor : may be unused, just for simulation
//NUM_XFER_BITS=6
// localparam SCANLINE_PAGES_PER_ROW= (WINDOW_WIDTH>>NUM_XFER_BITS)+((WINDOW_WIDTH[NUM_XFER_BITS-1:0]==0)?0:1);
// localparam TILES_PER_ROW= (WINDOW_WIDTH/TILE_WIDTH)+ ((WINDOW_WIDTH % TILE_WIDTH==0)?0:1);
// localparam TILE_ROWS_PER_WINDOW= ((WINDOW_HEIGHT-1)/TILE_VSTEP) + 1;
// localparam TILE_SIZE= TILE_WIDTH*TILE_HEIGHT;
// localparam integer SCANLINE_FULL_XFER= 1<0 - generate HACT from start to specified width
setup_sensor_memory (
0, // input [1:0] num_sensor;
FRAME_START_ADDRESS, // input [31:0] frame_sa; // 22-bit frame start address ((3 CA LSBs==0. BA==0)
FRAME_START_ADDRESS_INC, // input [31:0] frame_sa_inc; // 22-bit frame start address increment ((3 CA LSBs==0. BA==0)
last_buf_frame, // input [31:0] last_frame_num; // 16-bit number of the last frame in a buffer
frame_full_width, // input [31:0] frame_full_width; // 13-bit Padded line length (8-row increment), in 8-bursts (16 bytes)
window_width, // input [31:0] window_width; // 13 bit - in 8*16=128 bit bursts
window_height, // input [31:0] window_height; // 16 bit
window_left, // input [31:0] window_left;
window_top); // input [31:0] window_top;
// Run after histogram channel is set up?
set_sensor_mode (
0, // input [1:0] num_sensor;
4'h1, // input [3:0] hist_en; // [0..3] 1 - enable histogram modules, disable after processing the started frame
4'h1, // input [3:0] hist_nrst; // [4..7] 0 - immediately reset histogram module
1'b1, // input chn_en; // [8] 1 - enable sensor channel (0 - reset)
1'b0); // input bits16; // [9] 0 - 8 bpp mode, 1 - 16 bpp (bypass gamma). Gamma-processed data is still used for histograms
// test i2c - manual and sequencer (same data as in 353 test fixture
set_sensor_gamma_ctl (// doing last to enable sesnor data when everything else is set up
0, // input [1:0] num_sensor; // sensor channel number (0..3)
2'h3, // input [1:0] bayer; // bayer shift (0..3)
0, // input table_page; // table page (only used if SENS_GAMMA_BUFFER)
1'b1, // input en_input; // enable channel input
1'b1, // input repet_mode; // Normal mode, single trigger - just for debugging
1'b0); // input trig; // pass next frame
end
endtask
task setup_sensor_memory;
input [1:0] num_sensor;
input [31:0]frame_sa; // 22-bit frame start address ((3 CA LSBs==0. BA==0)
input [31:0] frame_sa_inc; // 22-bit frame start address increment ((3 CA LSBs==0. BA==0)
input [31:0] last_frame_num; // 16-bit number of the last frame in a buffer
input [31:0] frame_full_width; // 13-bit Padded line length (8-row increment), in 8-bursts (16 bytes)
input [31:0] window_width; // 13 bit - in 8*16=128 bit bursts
input [31:0] window_height; // 16 bit
input [31:0] window_left;
input [31:0] window_top;
/*
input [NUM_RC_BURST_BITS-1:0] frame_sa; // 22-bit frame start address ((3 CA LSBs==0. BA==0)
input [NUM_RC_BURST_BITS-1:0] frame_sa_inc; // 22-bit frame start address increment ((3 CA LSBs==0. BA==0)
input [LAST_FRAME_BITS-1:0] last_frame_num; // 16-bit number of the last frame in a buffer
input [FRAME_WIDTH_BITS-1:0] frame_full_width; // 13-bit Padded line length (8-row increment), in 8-bursts (16 bytes)
input [FRAME_WIDTH_BITS-1:0] window_width; // 13 bit - in 8*16=128 bit bursts
input [FRAME_HEIGHT_BITS-1:0] window_height; // 16 bit
input [FRAME_WIDTH_BITS-1:0] window_left;
input [FRAME_HEIGHT_BITS-1:0] window_top;
*/
reg [29:0] base_addr;
integer mode;
begin
base_addr = MCONTR_SENS_BASE + MCONTR_SENS_INC * num_sensor;
mode= func_encode_mode_scanline(
1, // repetitive,
0, // single,
0, // reset_frame,
0, // extra_pages,
1, // write_mem,
1, // enable
0); // chn_reset
write_contol_register(base_addr + MCNTRL_SCANLINE_STARTADDR, frame_sa); // RA=80, CA=0, BA=0 22-bit frame start address (3 CA LSBs==0. BA==0)
write_contol_register(base_addr + MCNTRL_SCANLINE_FRAME_SIZE, frame_sa_inc);
write_contol_register(base_addr + MCNTRL_SCANLINE_FRAME_LAST, last_frame_num);
write_contol_register(base_addr + MCNTRL_SCANLINE_FRAME_FULL_WIDTH, frame_full_width);
write_contol_register(base_addr + MCNTRL_SCANLINE_WINDOW_WH, {window_height[15:0],window_width[15:0]}); //WINDOW_WIDTH + (WINDOW_HEIGHT<<16));
write_contol_register(base_addr + MCNTRL_SCANLINE_WINDOW_X0Y0, {window_top[15:0],window_left[15:0]}); //WINDOW_X0+ (WINDOW_Y0<<16));
write_contol_register(base_addr + MCNTRL_SCANLINE_WINDOW_STARTXY, 32'b0);
write_contol_register(base_addr + MCNTRL_SCANLINE_MODE, mode);
end
endtask
task test_i2c_353;
begin
set_sensor_i2c_command(
2'b0, // input [1:0] num_sensor;
1'b1, // input rst_cmd; // [14] reset all FIFO (takes 16 clock pulses), also - stops i2c until run command
2'b0, // input [SENSI2C_CMD_RUN_PBITS : 0] run_cmd; // [13:12]3 - run i2c, 2 - stop i2c (needed before software i2c), 1,0 - no change to run state
1'b1, // input set_bytes; // [11] if 1, use bytes (below), 0 - nop
2'h3, // input [SENSI2C_CMD_BYTES_PBITS -1 : 0] bytes; // [10:9] set command bytes to send after slave address (0..3)
1'b1, // input set_dly; // [8] if 1, use dly (0 - ignore)
8'h0a, // input [SENSI2C_CMD_DLY_PBITS - 1 : 0] dly; // [7:0] - duration of quater i2c cycle (if 0, [3:0] control SCL+SDA)
2'b0, // input [SENSI2C_CMD_SCL_WIDTH -1 : 0] scl_ctl; // [1:0] : 0: NOP, 1: 1'b0->SCL, 2: 1'b1->SCL, 3: 1'bz -> SCL
2'b0); // input [SENSI2C_CMD_SDA_WIDTH -1 : 0] sda_ctl; // [3:2] : 0: NOP, 1: 1'b0->SDA, 2: 1'b1->SDA, 3: 1'bz -> SDA
repeat (10) @ (posedge CLK); // wait for initialization to be done TODO: use status
set_sensor_i2c_command (0, 0, 3, 0, 0, 0, 0, 0, 0); // run i2c - reset software bits
set_sensor_i2c_command (0, 0, 2, 0, 0, 0, 0, 0, 0); // stop i2c, enable software control
set_sensor_i2c_command (0, 0, 0, 0, 0, 0, 0, 0, 2); // SDA = 1
set_sensor_i2c_command (0, 0, 0, 0, 0, 0, 0, 0, 1); // SDA = 0
set_sensor_i2c_command (0, 0, 0, 0, 0, 0, 0, 2, 0); // SCL = 1
set_sensor_i2c_command (0, 0, 0, 0, 0, 0, 0, 1, 0); // SCL = 0
set_sensor_i2c_command (0, 0, 0, 0, 0, 0, 0, 0, 2); // SDA = 1
set_sensor_i2c_command (0, 0, 0, 0, 0, 0, 0, 2, 0); // SCL = 1
set_sensor_i2c_command (0, 0, 0, 0, 0, 0, 0, 0, 3); // SDA = 'bz
set_sensor_i2c_command (0, 0, 0, 0, 0, 0, 0, 3, 0); // SCL = 'bz
set_sensor_i2c_command (0, 0, 3, 0, 0, 0, 0, 0, 0); // run i2c
write_sensor_i2c (
0, // input [1:0] num_sensor;
0, // input rel_addr; // 0 - absolute, 1 - relative
1, // input integer addr;
'h90040793); // input [31:0] data;
write_sensor_i2c (0, 0, 1,'h90050a23);
write_sensor_i2c (0, 0, 2,'h90080001);
write_sensor_i2c (0, 0, 3,'h90090123);
write_sensor_i2c (0, 1, 2,'h90091234);
write_sensor_i2c (0, 0, 4,'h9004001f);
write_sensor_i2c (0, 0, 4,'h9005002f);
write_sensor_i2c (0, 1, 3,'h90020013);
write_sensor_i2c (0, 1, 3,'h90030017);
end
endtask
task program_status_sensor_i2c;
input [1:0] num_sensor;
input [1:0] mode;
input [5:0] seq_num;
begin
program_status (SENSOR_GROUP_ADDR + num_sensor * SENSOR_BASE_INC + SENSI2C_CTRL_RADDR,
SENSI2C_STATUS,
mode,
seq_num);
end
endtask
task program_status_sensor_io;
input [1:0] num_sensor;
input [1:0] mode;
input [5:0] seq_num;
begin
program_status (SENSOR_GROUP_ADDR + num_sensor * SENSOR_BASE_INC + SENSIO_RADDR,
SENSI2C_STATUS,
mode,
seq_num);
end
endtask
task set_sensor_mode;
input [1:0] num_sensor;
input [3:0] hist_en; // [0..3] 1 - enable histogram modules, disable after processing the started frame
input [3:0] hist_nrst; // [4..7] 0 - immediately reset histogram module
input chn_en; // [8] 1 - enable sensor channel (0 - reset)
input bits16; // [9] 0 - 8 bpp mode, 1 - 16 bpp (bypass gamma). Gamma-processed data is still used for histograms
reg [31:0] tmp;
begin
tmp= {{(32-SENSOR_MODE_WIDTH){1'b0}},func_sensor_mode(hist_en, hist_nrst, chn_en,bits16)};
write_contol_register( SENSOR_GROUP_ADDR + num_sensor * SENSOR_BASE_INC +SENSOR_CTRL_RADDR, tmp);
end
endtask
task set_sensor_i2c_command;
input [1:0] num_sensor;
input rst_cmd; // [14] reset all FIFO (takes 16 clock pulses), also - stops i2c until run command
input [SENSI2C_CMD_RUN_PBITS : 0] run_cmd; // [13:12]3 - run i2c, 2 - stop i2c (needed before software i2c), 1,0 - no change to run state
input set_bytes; // [11] if 1, use bytes (below), 0 - nop
input [SENSI2C_CMD_BYTES_PBITS -1 : 0] bytes; // [10:9] set command bytes to send after slave address (0..3)
input set_dly; // [8] if 1, use dly (0 - ignore)
input [SENSI2C_CMD_DLY_PBITS - 1 : 0] dly; // [7:0] - duration of quater i2c cycle (if 0, [3:0] control SCL+SDA)
input [SENSI2C_CMD_SCL_WIDTH -1 : 0] scl_ctl; // [1:0] : 0: NOP, 1: 1'b0->SCL, 2: 1'b1->SCL, 3: 1'bz -> SCL
input [SENSI2C_CMD_SDA_WIDTH -1 : 0] sda_ctl; // [3:2] : 0: NOP, 1: 1'b0->SDA, 2: 1'b1->SDA, 3: 1'bz -> SDA
reg [31:0] tmp;
begin
tmp= {func_sensor_i2c_command(rst_cmd, run_cmd, set_bytes, bytes, set_dly, dly, scl_ctl, sda_ctl)};
write_contol_register( SENSOR_GROUP_ADDR + num_sensor * SENSOR_BASE_INC +SENSI2C_CTRL_RADDR, tmp);
end
endtask
task write_sensor_i2c;
input [1:0] num_sensor;
input rel_addr; // 0 - absolute, 1 - relative
input integer addr;
input [31:0] data;
reg [29:0] reg_addr;
begin
reg_addr = (SENSOR_GROUP_ADDR + num_sensor * SENSOR_BASE_INC) +
(rel_addr ? SENSI2C_REL_RADDR : SENSI2C_ABS_RADDR) +
(addr & ~SENSI2C_ADDR_MASK);
write_contol_register(reg_addr, data);
end
endtask
task set_sensor_io_ctl;
input [1:0] num_sensor;
input [1:0] mrst; // <2: keep MRST, 2 - MRST low (active), 3 - high (inactive)
input [1:0] arst; // <2: keep ARST, 2 - ARST low (active), 3 - high (inactive)
input [1:0] aro; // <2: keep ARO, 2 - set ARO (software controlled) low, 3 - set ARO (software controlled) high
input [1:0] mmcm_rst; // <2: keep MMCM reset, 2 - MMCM reset off, 3 - MMCM reset on
input [1:0] clk_sel; // <2: keep MMCM clock source, 2 - use internal pixel clock, 3 - use pixel clock from the sensor
input set_delays; // (self-clearing) load all pre-programmed delays
input set_quadrants; // 0 - keep quadrants settings, 1 - update quadrants
input [SENS_CTRL_QUADRANTS_WIDTH-1:0] quadrants; // 90-degree shifts for data [1:0], hact [3:2] and vact [5:4]
reg [31:0] data;
reg [29:0] reg_addr;
begin
data = func_sensor_io_ctl (
mrst,
arst,
aro,
mmcm_rst,
clk_sel,
set_delays,
set_quadrants,
quadrants);
reg_addr = (SENSOR_GROUP_ADDR + num_sensor * SENSOR_BASE_INC) + SENSIO_RADDR + SENSIO_CTRL;
write_contol_register(reg_addr, data);
end
endtask
task set_sensor_io_dly;
input [1:0] num_sensor;
input [127:0] dly; // {mmsm_phase, bpf, vact, hact, pxd11,...,pxd0]
reg [29:0] reg_addr;
begin
reg_addr = (SENSOR_GROUP_ADDR + num_sensor * SENSOR_BASE_INC) + SENSIO_RADDR + SENSIO_DELAYS;
write_contol_register(reg_addr + 0, dly[ 31: 0]); // {pxd3, pxd2, pxd1, pxd0}
write_contol_register(reg_addr + 1, dly[ 63:32]); // {pxd7, pxd6, pxd5, pxd4}
write_contol_register(reg_addr + 2, dly[ 95:64]); // {pxd11, pxd10, pxd9, pxd8}
write_contol_register(reg_addr + 3, dly[127:96]); // {mmcm_phase, bpf, vact, hact}
set_sensor_io_ctl(
num_sensor,
0, // input [1:0] mrst; // <2: keep MRST, 2 - MRST low (active), 3 - high (inactive)
0, // input [1:0] arst; // <2: keep ARST, 2 - ARST low (active), 3 - high (inactive)
0, // input [1:0] aro; // <2: keep ARO, 2 - set ARO (software controlled) low, 3 - set ARO (software controlled) high
0, // input [1:0] mmcm_rst; // <2: keep MMCM reset, 2 - MMCM reset off, 3 - MMCM reset on
0, // input [1:0] clk_sel; // <2: keep MMCM clock source, 2 - use internal pixel clock, 3 - use pixel clock from the sensor
1'b1, //input set_delays; // (self-clearing) load all pre-programmed delays
0, // input set_quadrants; // 0 - keep quadrants settings, 1 - update quadrants
0); // input [SENS_CTRL_QUADRANTS_WIDTH-1:0] quadrants; // 90-degree shifts for data [1:0], hact [3:2] and vact [5:4]
end
endtask
task set_sensor_io_jtag; // SuppressThisWarning VEditor - may be unused
input [1:0] num_sensor;
input [1:0] pgmen; // <2: keep PGMEN, 2 - PGMEN low (inactive), 3 - high (active) enable JTAG control
input [1:0] prog; // <2: keep prog, 2 - prog low (active), 3 - high (inactive) ("program" pin control)
input [1:0] tck; // <2: keep TCK, 2 - set TCK low, 3 - set TCK high
input [1:0] tms; // <2: keep TMS, 2 - set TMS low, 3 - set TMS high
input [1:0] tdi; // <2: keep TDI, 2 - set TDI low, 3 - set TDI high
reg [29:0] reg_addr;
reg [31:0] data;
begin
reg_addr = (SENSOR_GROUP_ADDR + num_sensor * SENSOR_BASE_INC) + SENSIO_RADDR + SENSIO_JTAG;
data = func_sensor_jtag_ctl (
pgmen, // <2: keep PGMEN, 2 - PGMEN low (inactive), 3 - high (active) enable JTAG control
prog, // <2: keep prog, 2 - prog low (active), 3 - high (inactive) ("program" pin control)
tck, // <2: keep TCK, 2 - set TCK low, 3 - set TCK high
tms, // <2: keep TMS, 2 - set TMS low, 3 - set TMS high
tdi); // <2: keep TDI, 2 - set TDI low, 3 - set TDI high
write_contol_register(reg_addr, data);
end
endtask
task set_sensor_io_width;
input [1:0] num_sensor;
input [15:0] width; // 0 - use HACT, >0 - generate HACT from start to specified width
reg [29:0] reg_addr;
begin
reg_addr = (SENSOR_GROUP_ADDR + num_sensor * SENSOR_BASE_INC) + SENSIO_RADDR + SENSIO_WIDTH;
write_contol_register(reg_addr, {16'b0, width});
end
endtask
task program_curves;
input [1:0] num_sensor;
input [1:0] sub_channel;
reg [9:0] curves_data[0:1027]; // SuppressThisWarning VEditor : assigned in $readmem() system task
integer n,i,base,diff,diff1;
// reg [10:0] curv_diff;
reg [17:0] data18;
begin
$readmemh("linear1028rgb.dat",curves_data);
set_sensor_gamma_table_addr (
num_sensor,
sub_channel,
2'b0, //input [1:0] color;
1'b0); //input page; // only used if SENS_GAMMA_BUFFER != 0
for (n=0;n<4;n=n+1) begin
for (i=0;i<256;i=i+1) begin
base =curves_data[257*n+i];
diff =curves_data[257*n+i+1]-curves_data[257*n+i];
diff1=curves_data[257*n+i+1]-curves_data[257*n+i]+8;
// $display ("%x %x %x %x %x %x",n,i,curves_data[257*n+i], base, diff, diff1);
#1;
if ((diff>63) || (diff < -64)) data18 = {1'b1,diff1[10:4],base[9:0]};
else data18 = {1'b0,diff [ 6:0],base[9:0]};
set_sensor_gamma_table_data ( // need 256 for a single color data
num_sensor,
data18); // 18-bit table data
end
end
end
endtask
task set_sensor_gamma_table_addr;
input [1:0] num_sensor;
input [1:0] sub_channel;
input [1:0] color;
input page; // only used if SENS_GAMMA_BUFFER != 0
reg [31:0] data;
reg [29:0] reg_addr;
begin
data = 0;
data [20] = 1'b1;
data [7:0] = 8'b0;
data [9:8] = color;
if (SENS_GAMMA_BUFFER) data[12:10] = {sub_channel[1:0], page};
else data[11:10] = sub_channel[1:0];
reg_addr = (SENSOR_GROUP_ADDR + num_sensor * SENSOR_BASE_INC) + SENS_GAMMA_RADDR + SENS_GAMMA_ADDR_DATA;
write_contol_register(reg_addr, data);
end
endtask
task set_sensor_gamma_table_data; // need 256 for a single color data
input [1:0] num_sensor;
input [17:0] data18; // 18-bit table data
reg [29:0] reg_addr;
begin
reg_addr = (SENSOR_GROUP_ADDR + num_sensor * SENSOR_BASE_INC) + SENS_GAMMA_RADDR + SENS_GAMMA_ADDR_DATA;
write_contol_register(reg_addr, {14'b0, data18});
end
endtask
task set_sensor_gamma_heights;
input [1:0] num_sensor;
input [15:0] height0_m1; // height of the first sub-frame minus 1
input [15:0] height1_m1; // height of the second sub-frame minus 1
input [15:0] height2_m1; // height of the third sub-frame minus 1 (no need for 4-th)
reg [29:0] reg_addr;
begin
reg_addr = (SENSOR_GROUP_ADDR + num_sensor * SENSOR_BASE_INC) + SENS_GAMMA_RADDR + SENS_GAMMA_HEIGHT01;
write_contol_register(reg_addr, {height1_m1, height0_m1});
reg_addr = (SENSOR_GROUP_ADDR + num_sensor * SENSOR_BASE_INC) + SENS_GAMMA_RADDR + SENS_GAMMA_HEIGHT2;
write_contol_register(reg_addr, {16'b0, height2_m1});
end
endtask
task set_sensor_gamma_ctl;
input [1:0] num_sensor; // sensor channel number (0..3)
input [1:0] bayer; // bayer shift (0..3)
input table_page; // table page (only used if SENS_GAMMA_BUFFER)
input en_input; // enable channel input
input repet_mode; // Normal mode, single trigger - just for debugging
input trig; // pass next frame
reg [31:0] data;
reg [29:0] reg_addr;
begin
data = func_sensor_gamma_ctl (
bayer,
table_page,
en_input,
repet_mode,
trig);
reg_addr = (SENSOR_GROUP_ADDR + num_sensor * SENSOR_BASE_INC) + SENS_GAMMA_RADDR + SENS_GAMMA_CTRL;
write_contol_register(reg_addr, data);
end
endtask
task set_sensor_histogram_window;
input [1:0] num_sensor; // sensor channel number (0..3)
input [1:0] subchannel; // subchannel number (for multiplexed images)
input [15:0] left;
input [15:0] top;
input [15:0] width_m1; // one less than window width. If 0 - use frame right margin (end of HACT)
input [15:0] height_m1; // one less than window height. If 0 - use frame bottom margin (end of VACT)
// reg [31:0] data;
reg [29:0] reg_addr;
begin
reg_addr = (SENSOR_GROUP_ADDR + num_sensor * SENSOR_BASE_INC); // + HISTOGRAM_LEFT_TOP;
case (subchannel[1:0])
2'h0: reg_addr = reg_addr + HISTOGRAM_RADDR0;
2'h1: reg_addr = reg_addr + HISTOGRAM_RADDR1;
2'h2: reg_addr = reg_addr + HISTOGRAM_RADDR2;
2'h3: reg_addr = reg_addr + HISTOGRAM_RADDR3;
endcase
write_contol_register(reg_addr + HISTOGRAM_LEFT_TOP, {top, left});
write_contol_register(reg_addr + HISTOGRAM_WIDTH_HEIGHT, {height_m1, width_m1});
end
endtask
task set_sensor_histogram_saxi;
input en;
input nrst;
input confirm_write; // wait for the write confirmed befoer swicthing channels
input [3:0] cache_mode; // default should be 4'h3
reg [31:0] data;
begin
data = 0;
data [HIST_SAXI_EN] = en;
data [HIST_SAXI_NRESET] = nrst;
data [HIST_CONFIRM_WRITE] = confirm_write;
data [HIST_SAXI_AWCACHE +: 4] = cache_mode;
write_contol_register(SENSOR_GROUP_ADDR + HIST_SAXI_MODE_ADDR_REL, data);
end
endtask
task set_sensor_histogram_saxi_addr;
input [1:0] num_sensor; // sensor channel number (0..3)
input [1:0] subchannel; // subchannel number (for multiplexed images)
input [19:0] page; //start address in 4KB pages (1 page - one subchannel histogram)
begin
write_contol_register(SENSOR_GROUP_ADDR + HIST_SAXI_ADDR_REL + (num_sensor << 2) + subchannel,{12'b0,page});
end
endtask
function [STATUS_DEPTH-1:0] func_status_addr_sensor_i2c;
input [1:0] num_sensor;
begin
func_status_addr_sensor_i2c = (SENSI2C_STATUS_REG_BASE + num_sensor * SENSI2C_STATUS_REG_INC + SENSI2C_STATUS_REG_REL);
end
endfunction
function [STATUS_DEPTH-1:0] func_status_addr_sensor_io;
input [1:0] num_sensor;
begin
func_status_addr_sensor_io = (SENSI2C_STATUS_REG_BASE + num_sensor * SENSI2C_STATUS_REG_INC + SENSIO_STATUS_REG_REL);
end
endfunction
// RTC tasks
task program_status_rtc; // set status mode, and take a time snapshot (wait response and read time)
input [1:0] mode;
input [5:0] seq_num;
begin
program_status (RTC_ADDR,
RTC_SET_STATUS,
mode,
seq_num);
end
endtask
task set_rtc;
input [31:0] sec;
input [19:0] usec;
input [15:0] corr;
begin
write_contol_register(RTC_ADDR + RTC_SET_CORR,{16'b0,corr});
write_contol_register(RTC_ADDR + RTC_SET_USEC,{12'b0,usec});
write_contol_register(RTC_ADDR + RTC_SET_SEC, sec);
end
endtask
function [STATUS_DEPTH-1:0] func_status_addr_rtc_status;
begin
func_status_addr_rtc_status = RTC_STATUS_REG_ADDR;
end
endfunction
function [STATUS_DEPTH-1:0] func_status_addr_rtc_usec; // sec is in the next address
begin
func_status_addr_rtc_usec = RTC_SEC_USEC_ADDR;
end
endfunction
// camsync tasks
task set_camsync_mode;
input [1:0] en_snd; // <2 - NOP, 2 - disable, 3 - enable sending timestamp with sync pulse
input [1:0] en_ts_external; // <2 - NOP, 2 - local timestamp in the frame header, 3 - use external timestamp
input [1:0] triggered_mode; // <2 - NOP, 2 - async sesnor mode, 3 - triggered sensor mode
input [2:0] master_chn; // <4 - NOP, 4..7 - set master channel
input [4:0] chn_en; // <16 - NOP, [3:0] - bit mask of enabled sensor channels
reg [31:0] data;
begin
data = 0;
data [CAMSYNC_SNDEN_BIT -: 2] = en_snd;
data [CAMSYNC_EXTERNAL_BIT -: 2] = en_ts_external;
data [CAMSYNC_TRIGGERED_BIT -: 2] = triggered_mode;
data [CAMSYNC_MASTER_BIT -: 3] = master_chn;
data [CAMSYNC_CHN_EN_BIT -: 5] = chn_en;
write_contol_register(CAMSYNC_ADDR + CAMSYNC_MODE, data);
end
endtask
task set_camsync_inout; // set specified input bit, keep other ones
input is_out; // 0 - input selection, 1 - output selection
input integer bit_number; // 0..9 - bit to use
input active_positive; // 0 - active negative pulse, 1 - active positive pulse,
reg [31:0] data;
begin
data = {32'h00055555};
data[2 * bit_number +: 2 ] = {1'b1, active_positive};
if (is_out) write_contol_register(CAMSYNC_ADDR + CAMSYNC_TRIG_DST, data);
else write_contol_register(CAMSYNC_ADDR + CAMSYNC_TRIG_SRC, data);
end
endtask
task reset_camsync_inout; // disable all inputs
input is_out; // 0 - input selection, 1 - output selection
begin
if (is_out) write_contol_register(CAMSYNC_ADDR + CAMSYNC_TRIG_DST, 0);
else write_contol_register(CAMSYNC_ADDR + CAMSYNC_TRIG_SRC, 0);
end
endtask
task set_camsync_period;
input [31:0] period; // 0 - input selection, 1 - output selection
begin
write_contol_register(CAMSYNC_ADDR + CAMSYNC_TRIG_PERIOD, period);
end
endtask
task set_camsync_delay;
input [1:0] sub_chn;
input [31:0] dly; // 0 - input selection, 1 - output selection
begin
write_contol_register(CAMSYNC_ADDR + CAMSYNC_TRIG_DELAY0 + sub_chn, dly);
end
endtask
// command sequencer control
// Functions used by sensor-related tasks
task ctrl_cmd_frame_sequencer;
input [1:0] num_sensor; // sensor channel number
input reset; // reset sequencer (also stops)
input start; // start sequencer
input stop; // stop sequencer
reg [31:0] data;
reg [29:0] reg_addr;
begin
reg_addr= CMDFRAMESEQ_ADDR_BASE + num_sensor * CMDFRAMESEQ_ADDR_INC + CMDFRAMESEQ_CTRL;
data = 0;
data [CMDFRAMESEQ_RST_BIT] = reset;
data [CMDFRAMESEQ_RUN_BIT -:2] = {start | stop, start};
write_contol_register(reg_addr, data);
end
endtask
task write_cmd_frame_sequencer;
input [1:0] num_sensor; // sensor channel number
input relative; // 0 - absolute (address = 0..f), 1 - relative (address= 0..e)
input [3:0] frame_addr; // frame address (relative ort absolute)
input [AXI_WR_ADDR_BITS-1:0] addr; // command address (register to which command should be applied)
input [31:0] data; // command data
reg [29:0] reg_addr;
begin
if (relative && (&frame_addr)) $display("task write_cmd_frame_sequencer(): relative adderss 'hf is invalid, it is reserved for module control");
else begin
reg_addr = CMDFRAMESEQ_ADDR_BASE + num_sensor * CMDFRAMESEQ_ADDR_INC + (relative ? CMDFRAMESEQ_REL : CMDFRAMESEQ_ABS) + frame_addr;
write_contol_register(reg_addr, {{32-AXI_WR_ADDR_BITS{1'b0}}, addr});
write_contol_register(reg_addr, data);
end
end
endtask
function [SENSOR_MODE_WIDTH-1:0] func_sensor_mode;
input [3:0] hist_en; // [0..3] 1 - enable histogram modules, disable after processing the started frame
input [3:0] hist_nrst; // [4..7] 0 - immediately reset histogram module
input chn_en; // [8] 1 - enable sensor channel (0 - reset)
input bits16; // [9] 0 - 8 bpp mode, 1 - 16 bpp (bypass gamma). Gamma-processed data is still used for histograms
reg [SENSOR_MODE_WIDTH-1:0] tmp;
begin
tmp = 0;
tmp [SENSOR_HIST_EN_BITS +: 4] = hist_en;
tmp [SENSOR_HIST_NRST_BITS +: 4] = hist_nrst;
tmp [SENSOR_CHN_EN_BIT] = chn_en;
tmp [SENSOR_16BIT_BIT] = bits16;
func_sensor_mode = tmp;
end
endfunction
function [31 : 0] func_sensor_i2c_command;
input rst_cmd; // [14] reset all FIFO (takes 16 clock pulses), also - stops i2c until run command
input [SENSI2C_CMD_RUN_PBITS : 0] run_cmd; // [13:12]3 - run i2c, 2 - stop i2c (needed before software i2c), 1,0 - no change to run state
input set_bytes; // [11] if 1, use bytes (below), 0 - nop
input [SENSI2C_CMD_BYTES_PBITS -1 : 0] bytes; // [10:9] set command bytes to send after slave address (0..3)
input set_dly; // [8] if 1, use dly (0 - ignore)
input [SENSI2C_CMD_DLY_PBITS - 1 : 0] dly; // [7:0] - duration of quater i2c cycle (if 0, [3:0] control SCL+SDA)
input [SENSI2C_CMD_SCL_WIDTH -1 : 0] scl_ctl; // [17:16] : 0: NOP, 1: 1'b0->SCL, 2: 1'b1->SCL, 3: 1'bz -> SCL
input [SENSI2C_CMD_SDA_WIDTH -1 : 0] sda_ctl; // [19:18] : 0: NOP, 1: 1'b0->SDA, 2: 1'b1->SDA, 3: 1'bz -> SDA
reg [31 : 0] tmp;
begin
tmp = 0;
tmp [SENSI2C_CMD_RESET] = rst_cmd;
tmp [SENSI2C_CMD_RUN -: SENSI2C_CMD_RUN_PBITS+1] = run_cmd;
tmp [SENSI2C_CMD_BYTES] = set_bytes;
tmp [SENSI2C_CMD_BYTES -1 -: SENSI2C_CMD_BYTES_PBITS ] = bytes;
tmp [SENSI2C_CMD_DLY] = set_dly;
tmp [SENSI2C_CMD_DLY -1 -: SENSI2C_CMD_DLY_PBITS ] = dly;
tmp [SENSI2C_CMD_SCL +: SENSI2C_CMD_SCL_WIDTH] = scl_ctl;
tmp [SENSI2C_CMD_SDA +: SENSI2C_CMD_SDA_WIDTH] = sda_ctl;
func_sensor_i2c_command = tmp;
end
endfunction
function [31 : 0] func_sensor_io_ctl;
input [1:0] mrst; // <2: keep MRST, 2 - MRST low (active), 3 - high (inactive)
input [1:0] arst; // <2: keep ARST, 2 - ARST low (active), 3 - high (inactive)
input [1:0] aro; // <2: keep ARO, 2 - set ARO (software controlled) low, 3 - set ARO (software controlled) high
input [1:0] mmcm_rst; // <2: keep MMCM reset, 2 - MMCM reset off, 3 - MMCM reset on
input [1:0] clk_sel; // <2: keep MMCM clock source, 2 - use internal pixel clock, 3 - use pixel clock from the sensor
input set_delays; // (self-clearing) load all pre-programmed delays
input set_guadrants; // 0 - keep quadrants settings, 1 - update quadrants
input [SENS_CTRL_QUADRANTS_WIDTH-1:0] quadrants; // 90-degree shifts for data [1:0], hact [3:2] and vact [5:4]
reg [31 : 0] tmp;
begin
tmp = 0;
tmp [SENS_CTRL_MRST +: 2] = mrst;
tmp [SENS_CTRL_ARST +: 2] = arst;
tmp [SENS_CTRL_ARO +: 2] = aro;
tmp [SENS_CTRL_RST_MMCM +: 2] = mmcm_rst;
tmp [SENS_CTRL_EXT_CLK +: 2] = clk_sel;
tmp [SENS_CTRL_LD_DLY] = set_delays;
tmp [SENS_CTRL_QUADRANTS_EN] = set_guadrants;
tmp [SENS_CTRL_EXT_CLK +: SENS_CTRL_QUADRANTS_WIDTH] = quadrants;
func_sensor_io_ctl = tmp;
end
endfunction
function [31 : 0] func_sensor_jtag_ctl;
input [1:0] pgmen; // <2: keep PGMEN, 2 - PGMEN low (inactive), 3 - high (active) enable JTAG control
input [1:0] prog; // <2: keep prog, 2 - prog low (active), 3 - high (inactive) ("program" pin control)
input [1:0] tck; // <2: keep TCK, 2 - set TCK low, 3 - set TCK high
input [1:0] tms; // <2: keep TMS, 2 - set TMS low, 3 - set TMS high
input [1:0] tdi; // <2: keep TDI, 2 - set TDI low, 3 - set TDI high
reg [31 : 0] tmp;
begin
tmp = 0;
tmp [SENS_JTAG_TDI +: 2] = pgmen;
tmp [SENS_JTAG_TMS +: 2] = prog;
tmp [SENS_JTAG_TCK +: 2] = tck;
tmp [SENS_JTAG_TMS +: 2] = tms;
tmp [SENS_JTAG_TDI +: 2] = tdi;
func_sensor_jtag_ctl = tmp;
end
endfunction
function [31 : 0] func_sensor_gamma_ctl;
input [1:0] bayer;
input table_page;
input en_input;
input repet_mode; // Normal mode, single trigger - just for debugging TODO: re-assign?
input trig;
reg [31 : 0] tmp;
begin
tmp = 0;
tmp[SENS_GAMMA_MODE_BAYER +: 2] = bayer;
tmp [SENS_GAMMA_MODE_PAGE] = table_page;
tmp [SENS_GAMMA_MODE_EN] = en_input;
tmp [SENS_GAMMA_MODE_REPET] = repet_mode;
tmp [SENS_GAMMA_MODE_TRIG] = trig;
func_sensor_gamma_ctl = tmp;
end
endfunction
`include "includes/tasks_tests_memory.vh" // SuppressThisWarning VEditor - may be unused
`include "includes/x393_tasks_afi.vh" // SuppressThisWarning VEditor - may be unused
`include "includes/x393_tasks_mcntrl_en_dis_priority.vh"
`include "includes/x393_tasks_mcntrl_buffers.vh"
`include "includes/x393_tasks_pio_sequences.vh"
`include "includes/x393_tasks_mcntrl_timing.vh" // SuppressThisWarning VEditor - not used
`include "includes/x393_tasks_ps_pio.vh"
`include "includes/x393_tasks_status.vh"
`include "includes/x393_tasks01.vh"
`include "includes/x393_mcontr_encode_cmd.vh"
endmodule