/******************************************************************************* * Module: x393_testbench01 * Date:2015-02-06 * Author: Andrey Filippov * Description: testbench for the initial x393.v simulation * * Copyright (c) 2015 Elphel, Inc. * x393_testbench01.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_testbench01.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_testbench01 #( `include "includes/x393_parameters.vh" // SuppressThisWarning VEditor - not used `include "includes/x393_simulation_parameters.vh"// SuppressThisWarning VEditor - not used )( ); `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 // 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; // 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<>NUM_XFER_BITS)+((window_width[NUM_XFER_BITS-1:0]==0)?0:1); $display("====== test_scanline_write: channel=%d, extra_pages=%d, wait_done=%d @%t", channel, extra_pages, wait_done, $time); case (channel) // 1: begin // start_addr= MCNTRL_SCANLINE_CHN1_ADDR; // status_address= MCNTRL_TEST01_STATUS_REG_CHN1_ADDR; // status_control_address= MCNTRL_TEST01_ADDR + MCNTRL_TEST01_CHN1_STATUS_CNTRL; // test_mode_address= MCNTRL_TEST01_ADDR + MCNTRL_TEST01_CHN1_MODE; // end 3: begin start_addr= MCNTRL_SCANLINE_CHN3_ADDR; status_address= MCNTRL_TEST01_STATUS_REG_CHN3_ADDR; status_control_address= MCNTRL_TEST01_ADDR + MCNTRL_TEST01_CHN3_STATUS_CNTRL; test_mode_address= MCNTRL_TEST01_ADDR + MCNTRL_TEST01_CHN3_MODE; end default: begin $display("**** ERROR: Invalid channel, only 3 is valid"); start_addr= MCNTRL_SCANLINE_CHN3_ADDR; status_address= MCNTRL_TEST01_STATUS_REG_CHN1_ADDR; status_control_address= MCNTRL_TEST01_ADDR + MCNTRL_TEST01_CHN1_STATUS_CNTRL; test_mode_address= MCNTRL_TEST01_ADDR + MCNTRL_TEST01_CHN1_MODE; end endcase mode= func_encode_mode_scanline( repetitive, single, reset_frame, extra_pages, 1, // write_mem, 1, // enable 0); // chn_reset write_contol_register(start_addr + MCNTRL_SCANLINE_STARTADDR, FRAME_START_ADDRESS); // RA=80, CA=0, BA=0 22-bit frame start address (3 CA LSBs==0. BA==0) write_contol_register(start_addr + MCNTRL_SCANLINE_FRAME_FULL_WIDTH, FRAME_FULL_WIDTH); write_contol_register(start_addr + MCNTRL_SCANLINE_WINDOW_WH, {window_height,window_width}); //WINDOW_WIDTH + (WINDOW_HEIGHT<<16)); write_contol_register(start_addr + MCNTRL_SCANLINE_WINDOW_X0Y0, {window_top,window_left}); //WINDOW_X0+ (WINDOW_Y0<<16)); write_contol_register(start_addr + MCNTRL_SCANLINE_WINDOW_STARTXY, SCANLINE_STARTX+(SCANLINE_STARTY<<16)); write_contol_register(start_addr + MCNTRL_SCANLINE_MODE, mode); configure_channel_priority(channel,0); // lowest priority channel 3 // enable_memcntrl_channels(16'h000b); // channels 0,1,3 are enabled enable_memcntrl_en_dis(channel,1); write_contol_register(test_mode_address, TEST01_START_FRAME); for (ii=0;ii1)? ( ( ((ii % pages_per_row) < (pages_per_row-1))? (1<= TEST_INITIAL_BURST) begin // wait page ready and fill page after first 4 are filled wait_status_condition ( status_address, //MCNTRL_TEST01_STATUS_REG_CHN3_ADDR, status_control_address, // MCNTRL_TEST01_ADDR + MCNTRL_TEST01_CHN3_STATUS_CNTRL, DEFAULT_STATUS_MODE, (ii-TEST_INITIAL_BURST)<<16, // 4-bit page number 'hf << 16, // mask for the 4-bit page number 1, // not equal to (ii == TEST_INITIAL_BURST)); // synchronize sequence number - only first time, next just wait fro auto update xfer_size= ((pages_per_row>1)? ( ( ((ii % pages_per_row) < (pages_per_row-1))? (1<>NUM_XFER_BITS)+((window_width[NUM_XFER_BITS-1:0]==0)?0:1); $display("====== test_scanline_read: channel=%d, extra_pages=%d, show_data=%d @%t", channel, extra_pages, show_data, $time); case (channel) // 1: begin // start_addr= MCNTRL_SCANLINE_CHN1_ADDR; // status_address= MCNTRL_TEST01_STATUS_REG_CHN1_ADDR; // status_control_address= MCNTRL_TEST01_ADDR + MCNTRL_TEST01_CHN1_STATUS_CNTRL; // test_mode_address= MCNTRL_TEST01_ADDR + MCNTRL_TEST01_CHN1_MODE; // end 3: begin start_addr= MCNTRL_SCANLINE_CHN3_ADDR; status_address= MCNTRL_TEST01_STATUS_REG_CHN3_ADDR; status_control_address= MCNTRL_TEST01_ADDR + MCNTRL_TEST01_CHN3_STATUS_CNTRL; test_mode_address= MCNTRL_TEST01_ADDR + MCNTRL_TEST01_CHN3_MODE; end default: begin $display("**** ERROR: Invalid channel, only 3 is valid"); start_addr= MCNTRL_SCANLINE_CHN3_ADDR; status_address= MCNTRL_TEST01_STATUS_REG_CHN1_ADDR; status_control_address= MCNTRL_TEST01_ADDR + MCNTRL_TEST01_CHN1_STATUS_CNTRL; test_mode_address= MCNTRL_TEST01_ADDR + MCNTRL_TEST01_CHN1_MODE; end endcase mode= func_encode_mode_scanline( repetitive, single, reset_frame, extra_pages, 0, // write_mem, 1, // enable 0); // chn_reset // program to the write_contol_register(start_addr + MCNTRL_SCANLINE_STARTADDR, FRAME_START_ADDRESS); // RA=80, CA=0, BA=0 22-bit frame start address (3 CA LSBs==0. BA==0) write_contol_register(start_addr + MCNTRL_SCANLINE_FRAME_FULL_WIDTH, FRAME_FULL_WIDTH); write_contol_register(start_addr + MCNTRL_SCANLINE_WINDOW_WH, {window_height,window_width}); //WINDOW_WIDTH + (WINDOW_HEIGHT<<16)); write_contol_register(start_addr + MCNTRL_SCANLINE_WINDOW_X0Y0, {window_top,window_left}); //WINDOW_X0+ (WINDOW_Y0<<16)); write_contol_register(start_addr + MCNTRL_SCANLINE_WINDOW_STARTXY, SCANLINE_STARTX+(SCANLINE_STARTY<<16)); write_contol_register(start_addr + MCNTRL_SCANLINE_MODE, mode);// set mode register: {extra_pages[1:0],enable,!reset} configure_channel_priority(channel,0); // lowest priority channel 3 enable_memcntrl_en_dis(channel,1); write_contol_register(test_mode_address, TEST01_START_FRAME); for (ii=0;ii<(window_height * pages_per_row);ii = ii+1) begin xfer_size= ((pages_per_row>1)? ( ( ((ii % pages_per_row) < (pages_per_row-1))? (1<= TEST_INITIAL_BURST) begin // wait page ready and fill page after first 4 are filled wait_status_condition ( status_address, // MCNTRL_TEST01_STATUS_REG_CHN5_ADDR, status_control_address, // MCNTRL_TEST01_ADDR + MCNTRL_TEST01_CHN5_STATUS_CNTRL, DEFAULT_STATUS_MODE, (ii-TEST_INITIAL_BURST)<<16, // 4-bit page number 'hf << 16, // mask for the 4-bit page number 1, // not equal to (ii == TEST_INITIAL_BURST)); // synchronize sequence number - only first time, next just wait fro auto update $display("########### test_tiled_write block %d: channel=%d, @%t", ii, channel, $time); startx = window_left + ((ii % tiles_per_row) * tile_width); starty = window_top + (ii / tile_rows_per_window); write_block_scanline_chn( // TODO: Make a different tile buffer data, matching the order channel, // channel (ii & 3), tile_size, startx, // window_left + ((ii % tiles_per_row) * tile_width), starty); // window_top + (ii / tile_rows_per_window)); // SCANLINE_CUR_Y);\ end write_contol_register(test_mode_address, TEST01_NEXT_PAGE); end if (wait_done) begin wait_status_condition ( // may also be read directly from the same bit of mctrl_linear_rw (address=5) status status_address, // MCNTRL_TEST01_STATUS_REG_CHN3_ADDR, status_control_address, // MCNTRL_TEST01_ADDR + MCNTRL_TEST01_CHN3_STATUS_CNTRL, DEFAULT_STATUS_MODE, 2 << STATUS_2LSB_SHFT, // bit 24 - busy, bit 25 - frame done 2 << STATUS_2LSB_SHFT, // mask for the 4-bit page number 0, // equal to 0); // no need to synchronize sequence number // enable_memcntrl_en_dis(channel,0); // disable channel end end endtask task test_tiled_read; // SuppressThisWarning VEditor - may be unused input [3:0] channel; input byte32; input keep_open; input [1:0] extra_pages; input show_data; input [15:0] window_width; input [15:0] window_height; input [15:0] window_left; input [15:0] window_top; input [ 7:0] tile_width; input [ 7:0] tile_height; input [ 7:0] tile_vstep; reg [29:0] start_addr; integer mode; reg [STATUS_DEPTH-1:0] status_address; reg [29:0] status_control_address; reg [29:0] test_mode_address; integer ii; integer tiles_per_row; integer tile_rows_per_window; integer tile_size; reg repetitive; reg single; reg reset_frame; begin repetitive = 1'b1; single = 1'b0; reset_frame = 1'b0; tiles_per_row= (window_width/tile_width)+ ((window_width % tile_width==0)?0:1); tile_rows_per_window= ((window_height-1)/tile_vstep) + 1; tile_size= tile_width*tile_height; $display("====== test_tiled_read: channel=%d, byte32=%d, keep_open=%d, extra_pages=%d, show_data=%d @%t", channel, byte32, keep_open, extra_pages, show_data, $time); case (channel) 2: begin start_addr= MCNTRL_TILED_CHN2_ADDR; status_address= MCNTRL_TEST01_STATUS_REG_CHN2_ADDR; status_control_address= MCNTRL_TEST01_ADDR + MCNTRL_TEST01_CHN2_STATUS_CNTRL; test_mode_address= MCNTRL_TEST01_ADDR + MCNTRL_TEST01_CHN2_MODE; end 4: begin start_addr= MCNTRL_TILED_CHN4_ADDR; status_address= MCNTRL_TEST01_STATUS_REG_CHN4_ADDR; status_control_address= MCNTRL_TEST01_ADDR + MCNTRL_TEST01_CHN4_STATUS_CNTRL; test_mode_address= MCNTRL_TEST01_ADDR + MCNTRL_TEST01_CHN4_MODE; end default: begin $display("**** ERROR: Invalid channel, only 2 and 4 are valid"); start_addr= MCNTRL_TILED_CHN2_ADDR; status_address= MCNTRL_TEST01_STATUS_REG_CHN2_ADDR; status_control_address= MCNTRL_TEST01_ADDR + MCNTRL_TEST01_CHN2_STATUS_CNTRL; test_mode_address= MCNTRL_TEST01_ADDR + MCNTRL_TEST01_CHN2_MODE; end endcase mode= func_encode_mode_tiled( repetitive, single, reset_frame, byte32, keep_open, extra_pages, 0, // write_mem, 1, // enable 0); // chn_reset write_contol_register(start_addr + MCNTRL_TILED_STARTADDR, FRAME_START_ADDRESS); // RA=80, CA=0, BA=0 22-bit frame start address (3 CA LSBs==0. BA==0) write_contol_register(start_addr + MCNTRL_TILED_FRAME_FULL_WIDTH, FRAME_FULL_WIDTH); write_contol_register(start_addr + MCNTRL_TILED_WINDOW_WH, {window_height,window_width}); //WINDOW_WIDTH + (WINDOW_HEIGHT<<16)); write_contol_register(start_addr + MCNTRL_TILED_WINDOW_X0Y0, {window_top,window_left}); //WINDOW_X0+ (WINDOW_Y0<<16)); write_contol_register(start_addr + MCNTRL_TILED_WINDOW_STARTXY, TILED_STARTX+(TILED_STARTY<<16)); write_contol_register(start_addr + MCNTRL_TILED_TILE_WHS, {8'b0,tile_vstep,tile_height,tile_width});//(tile_height<<8)+(tile_vstep<<16)); write_contol_register(start_addr + MCNTRL_TILED_MODE, mode);// set mode register: {extra_pages[1:0],enable,!reset} configure_channel_priority(channel,0); // lowest priority channel 3 enable_memcntrl_en_dis(channel,1); write_contol_register(test_mode_address, TEST01_START_FRAME); for (ii=0;ii<(tiles_per_row * tile_rows_per_window);ii = ii+1) begin wait_status_condition ( status_address, // MCNTRL_TEST01_STATUS_REG_CHN4_ADDR, status_control_address, // MCNTRL_TEST01_ADDR + MCNTRL_TEST01_CHN4_STATUS_CNTRL, DEFAULT_STATUS_MODE, ii << 16, // -TEST_INITIAL_BURST)<<16, // 4-bit page number 'hf << 16, // mask for the 4-bit page number 1, // not equal to (ii == 0)); // synchronize sequence number - only first time, next just wait fro auto update if (show_data) begin $display("########### test_tiled_read block %d: channel=%d, @%t", ii, channel, $time); read_block_buf_chn ( channel, (ii & 3), tile_size <<2, 1 ); // chn=0, page=3, number of 32-bit words=256, wait_done end write_contol_register(test_mode_address, TEST01_NEXT_PAGE); end // enable_memcntrl_en_dis(channel,0); // disable channel end endtask task set_all_sequences; input rsel; input wsel; begin $display("SET MRS @ %t",$time); set_mrs(1); $display("SET REFRESH @ %t",$time); set_refresh( T_RFC, // input [ 9:0] t_rfc; // =50 for tCK=2.5ns T_REFI); //input [ 7:0] t_refi; // 48/97 for normal, 8 - for simulation $display("SET WRITE LEVELING @ %t",$time); set_write_lev(16); // write leveling, 16 times (full buffer - 128) $display("SET READ PATTERN @ %t",$time); set_read_pattern(8); // 8x2*64 bits, 32x32 bits to read $display("SET WRITE BLOCK @ %t",$time); set_write_block( 3'h5, // bank 15'h1234, // row address 10'h100, // column address wsel ); $display("SET READ BLOCK @ %t",$time); set_read_block( 3'h5, // bank 15'h1234, // row address 10'h100, // column address rsel // sel ); end endtask task write_block_scanline_chn; // S uppressThisWarning VEditor : may be unused // input integer chn; // buffer channel input [3:0] chn; // buffer channel input [1:0] page; // input integer num_words; // number of words to write (will be rounded up to multiple of 16) input [NUM_XFER_BITS:0] num_bursts; // number of 8-bursts to write (will be rounded up to multiple of 16) input integer startX; input integer startY; reg [29:0] start_addr; integer num_words; begin // $display("====== write_block_scanline_chn:%d page: %x X=0x%x Y=0x%x num=%d @%t", chn, page, startX, startY,num_words, $time); $display("====== write_block_scanline_chn:%d page: %x X=0x%x Y=0x%x num=%d @%t", chn, page, startX, startY,num_bursts, $time); case (chn) 0: start_addr=MCONTR_BUF0_WR_ADDR + (page << 8); // 1: start_addr=MCONTR_BUF1_WR_ADDR + (page << 8); 2: start_addr=MCONTR_BUF2_WR_ADDR + (page << 8); 3: start_addr=MCONTR_BUF3_WR_ADDR + (page << 8); 4: start_addr=MCONTR_BUF4_WR_ADDR + (page << 8); default: begin $display("**** ERROR: Invalid channel (not 0,2,3,4) for write_block_scanline_chn = %d @%t", chn, $time); start_addr = MCONTR_BUF0_WR_ADDR+ (page << 8); end endcase num_words=num_bursts << 2; write_block_incremtal (start_addr, num_words, (startX<<2) + (startY<<16)); // 1 of startX is 8x16 bit, 16 bytes or 4 32-bit words // write_block_incremtal (start_addr, num_bursts << 2, (startX<<2) + (startY<<16)); // 1 of startX is 8x16 bit, 16 bytes or 4 32-bit words end endtask function [10:0] func_encode_mode_tiled; input repetitive; input single; input reset_frame; input byte32; // 32-byte columns (0 - 16-byte columns) input keep_open; // for 8 or less rows - do not close page between accesses input [1:0] extra_pages; // number of extra pages that need to stay (not to be overwritten) in the buffer // can be used for overlapping tile read access input write_mem; // write to memory mode (0 - read from memory) input enable; // enable requests from this channel ( 0 will let current to finish, but not raise want/need) input chn_reset; // immediately reset al;l the internal circuitry reg [10:0] rslt; begin rslt = 0; rslt[MCONTR_LINTILE_EN] = ~chn_reset; rslt[MCONTR_LINTILE_NRESET] = enable; rslt[MCONTR_LINTILE_WRITE] = write_mem; rslt[MCONTR_LINTILE_EXTRAPG +: MCONTR_LINTILE_EXTRAPG_BITS] = extra_pages; rslt[MCONTR_LINTILE_KEEP_OPEN] = keep_open; rslt[MCONTR_LINTILE_BYTE32] = byte32; rslt[MCONTR_LINTILE_RST_FRAME] = reset_frame; rslt[MCONTR_LINTILE_SINGLE] = single; rslt[MCONTR_LINTILE_REPEAT] = repetitive; // func_encode_mode_tiled={byte32,keep_open,extra_pages,write_mem,enable,~chn_reset}; func_encode_mode_tiled = rslt; end endfunction function [10:0] func_encode_mode_scanline; input repetitive; input single; input reset_frame; input [1:0] extra_pages; // number of extra pages that need to stay (not to be overwritten) in the buffer // can be used for overlapping tile read access input write_mem; // write to memory mode (0 - read from memory) input enable; // enable requests from this channel ( 0 will let current to finish, but not raise want/need) input chn_reset; // immediately reset al;l the internal circuitry reg [10:0] rslt; begin rslt = 0; rslt[MCONTR_LINTILE_EN] = ~chn_reset; rslt[MCONTR_LINTILE_NRESET] = enable; rslt[MCONTR_LINTILE_WRITE] = write_mem; rslt[MCONTR_LINTILE_EXTRAPG +: MCONTR_LINTILE_EXTRAPG_BITS] = extra_pages; rslt[MCONTR_LINTILE_RST_FRAME] = reset_frame; rslt[MCONTR_LINTILE_SINGLE] = single; rslt[MCONTR_LINTILE_REPEAT] = repetitive; // func_encode_mode_scanline={extra_pages,write_mem,enable,~chn_reset}; func_encode_mode_scanline = rslt; end endfunction `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