def axi_set_tristate_patterns(self,
                               strPattern=None):
     """
     Set sequencer patterns for the tristate ON/OFF (defined by parameters)
     <strPattern> - optional up to 4-letter pattern. Each letter is one of 3:
                    'E'- early, "N" - nominal and 'L' - late, first for DQ start,
                    second - for DQS start, then DQ end and DQS end. If no pattern
                    is provided, all will be set to Verilog parameter values (DQ*TRI_*),
                    if only 1 - it will be applied to all, if 2 - it will be
                    repeated twice, 3 will use  the same value for DQS end as for DQS start
     """
     modes={'E':0,'N':1,'L':2}
     evNames=('DQ_FIRST', 'DQS_FIRST', 'DQ_LAST','DQS_LAST')
     
     patVals={evNames[0]: (0x3,0x7,0xf), # DQ_FIRST:  early, nominal, late
              evNames[1]: (0x1,0x3,0x7), # DQS_FIRST: early, nominal, late
              evNames[2]: (0xf,0xe,0xc), # DQ_LAST:   early, nominal, late
              evNames[3]: (0xe,0xc,0x8)} # DQS_LAST:  early, nominal, late
     
     if not strPattern:
         delays=concat(((0,16), #  {16'h0, 
                        (vrlg.DQSTRI_LAST, getParWidth(vrlg.DQSTRI_LAST__TYPE)),      #  DQSTRI_LAST,
                        (vrlg.DQSTRI_FIRST,getParWidth(vrlg.DQSTRI_FIRST__TYPE)),     #  DQSTRI_FIRST,
                        (vrlg.DQTRI_LAST,  getParWidth(vrlg.DQTRI_LAST__TYPE)),       #   DQTRI_LAST,
                        (vrlg.DQTRI_FIRST, getParWidth(vrlg.DQTRI_FIRST__TYPE)))      #   DQTRI_FIRST});
                       )[0]
     else:
         strPattern=strPattern.upper()
         if len(strPattern) == 1:
             strPattern*=4
         elif len(strPattern) == 2:
             strPattern*=2
         elif len(strPattern) == 3:
             strPattern+=strPattern[1]
         strPattern=strPattern[:4]
         vals={}
         for i,n in enumerate(evNames):
             try:
                 vals[n]=patVals[n][modes[strPattern[i]]]
             except:
                 msg="axi_set_tristate_patterns(%s): Failed to determine delay mode for %s, got %s"%(strPattern,n,strPattern[i])
                 print (msg)
                 Exception(msg)              
         print ("axi_set_tristate_patterns(%s) : %s"%(strPattern,str(vals)))
         delays=concat(((0,16), #  {16'h0, 
                        (vals['DQS_LAST'],4),  # vrlg.DQSTRI_LAST, getParWidth(vrlg.DQSTRI_LAST__TYPE)),      #  DQSTRI_LAST,
                        (vals['DQS_FIRST'],4), # vrlg.DQSTRI_FIRST,getParWidth(vrlg.DQSTRI_FIRST__TYPE)),     #  DQSTRI_FIRST,
                        (vals['DQ_LAST'],4),   # vrlg.DQTRI_LAST,  getParWidth(vrlg.DQTRI_LAST__TYPE)), #   DQTRI_LAST,
                        (vals['DQ_FIRST'],4))  # vrlg.DQTRI_FIRST, getParWidth(vrlg.DQTRI_FIRST__TYPE)))       #   DQTRI_FIRST});
                       )[0]
              
     # may fail if some of the parameters used have undefined width
     print("DQTRI_FIRST=%s, DQTRI_FIRST__TYPE=%s"%(str(vrlg.DQTRI_FIRST),str(vrlg.DQTRI_FIRST__TYPE)))
     print("DQTRI_LAST=%s, DQTRI_LAST__TYPE=%s"%(str(vrlg.DQTRI_LAST),str(vrlg.DQTRI_LAST__TYPE)))
     if self.DEBUG_MODE > 1:
         print("SET TRISTATE PATTERNS, combined delays=%s"%str(delays))    
         print("SET TRISTATE PATTERNS, combined delays=0x%x"%delays)    
     self.x393_axi_tasks.write_control_register(vrlg.MCONTR_PHY_16BIT_ADDR +vrlg.MCONTR_PHY_16BIT_PATTERNS_TRI, delays) #  DQSTRI_LAST, DQSTRI_FIRST, DQTRI_LAST, DQTRI_FIRST});
Exemple #2
0
    def axi_set_tristate_patterns(self, strPattern=None):
        """
        Set sequencer patterns for the tristate ON/OFF (defined by parameters)
        <strPattern> - optional up to 4-letter pattern. Each letter is one of 3:
                       'E'- early, "N" - nominal and 'L' - late, first for DQ start,
                       second - for DQS start, then DQ end and DQS end. If no pattern
                       is provided, all will be set to Verilog parameter values (DQ*TRI_*),
                       if only 1 - it will be applied to all, if 2 - it will be
                       repeated twice, 3 will use  the same value for DQS end as for DQS start
        """
        modes = {'E': 0, 'N': 1, 'L': 2}
        evNames = ('DQ_FIRST', 'DQS_FIRST', 'DQ_LAST', 'DQS_LAST')

        patVals = {
            evNames[0]: (0x3, 0x7, 0xf),  # DQ_FIRST:  early, nominal, late
            evNames[1]: (0x1, 0x3, 0x7),  # DQS_FIRST: early, nominal, late
            evNames[2]: (0xf, 0xe, 0xc),  # DQ_LAST:   early, nominal, late
            evNames[3]: (0xe, 0xc, 0x8)
        }  # DQS_LAST:  early, nominal, late

        if not strPattern:
            delays = concat((
                (0, 16),  #  {16'h0, 
                (vrlg.DQSTRI_LAST,
                 getParWidth(vrlg.DQSTRI_LAST__TYPE)),  #  DQSTRI_LAST,
                (vrlg.DQSTRI_FIRST,
                 getParWidth(vrlg.DQSTRI_FIRST__TYPE)),  #  DQSTRI_FIRST,
                (vrlg.DQTRI_LAST,
                 getParWidth(vrlg.DQTRI_LAST__TYPE)),  #   DQTRI_LAST,
                (vrlg.DQTRI_FIRST, getParWidth(vrlg.DQTRI_FIRST__TYPE))
            )  #   DQTRI_FIRST});
                            )[0]
        else:
            strPattern = strPattern.upper()
            if len(strPattern) == 1:
                strPattern *= 4
            elif len(strPattern) == 2:
                strPattern *= 2
            elif len(strPattern) == 3:
                strPattern += strPattern[1]
            strPattern = strPattern[:4]
            vals = {}
            for i, n in enumerate(evNames):
                try:
                    vals[n] = patVals[n][modes[strPattern[i]]]
                except:
                    msg = "axi_set_tristate_patterns(%s): Failed to determine delay mode for %s, got %s" % (
                        strPattern, n, strPattern[i])
                    print(msg)
                    Exception(msg)
            print("axi_set_tristate_patterns(%s) : %s" %
                  (strPattern, str(vals)))
            delays = concat((
                (0, 16),  #  {16'h0, 
                (
                    vals['DQS_LAST'], 4
                ),  # vrlg.DQSTRI_LAST, getParWidth(vrlg.DQSTRI_LAST__TYPE)),      #  DQSTRI_LAST,
                (
                    vals['DQS_FIRST'], 4
                ),  # vrlg.DQSTRI_FIRST,getParWidth(vrlg.DQSTRI_FIRST__TYPE)),     #  DQSTRI_FIRST,
                (
                    vals['DQ_LAST'], 4
                ),  # vrlg.DQTRI_LAST,  getParWidth(vrlg.DQTRI_LAST__TYPE)), #   DQTRI_LAST,
                (vals['DQ_FIRST'], 4)
            )  # vrlg.DQTRI_FIRST, getParWidth(vrlg.DQTRI_FIRST__TYPE)))       #   DQTRI_FIRST});
                            )[0]

        # may fail if some of the parameters used have undefined width
        print("DQTRI_FIRST=%s, DQTRI_FIRST__TYPE=%s" %
              (str(vrlg.DQTRI_FIRST), str(vrlg.DQTRI_FIRST__TYPE)))
        print("DQTRI_LAST=%s, DQTRI_LAST__TYPE=%s" %
              (str(vrlg.DQTRI_LAST), str(vrlg.DQTRI_LAST__TYPE)))
        if self.DEBUG_MODE > 1:
            print("SET TRISTATE PATTERNS, combined delays=%s" % str(delays))
            print("SET TRISTATE PATTERNS, combined delays=0x%x" % delays)
        self.x393_axi_tasks.write_control_register(
            vrlg.MCONTR_PHY_16BIT_ADDR + vrlg.MCONTR_PHY_16BIT_PATTERNS_TRI,
            delays)  #  DQSTRI_LAST, DQSTRI_FIRST, DQTRI_LAST, DQTRI_FIRST});
Exemple #3
0
    def test_tiled_read(
        self,  # \
        channel,  # input            [3:0] channel;
        byte32,  # input                  byte32;
        keep_open,  # input                  keep_open;
        extra_pages,  # input            [1:0] extra_pages;
        show_data,  # input                  show_data;
        window_width,  # input [15:0]           window_width;
        window_height,  # input [15:0]           window_height;
        window_left,  # input [15:0]           window_left;
        window_top,  # input [15:0]           window_top;
        tile_width,  # input [ 7:0]           tile_width;
        tile_height,  # input [ 7:0]           tile_height;
        tile_vstep,
    ):  # input [ 7:0]           tile_vstep;
        """
        Test tiled mode write (frame size/row increment is set in parameters) 
        <channel> channel number to use. Valid values: 2, 4
        <byte32>        use 32-byte wide columns (0 - use 16-byte ones)
        <keep_open>,    do not close page between accesses (for 8 or less rows only)
        <extra_pages>    2-bit number of extra pages that need to stay (not to be overwritten) in the buffer
        <show_data>      print read data
        <window_width>   13-bit window width in 8-bursts (16 bytes)
        <window_height>  16 bit window height
        <window_left>,   13-bit window left margin in 8-bursts (16 bytes)
        <window_top>     16-bit window top margin
        <tile_width>     6-bit tile width in 8-bursts (16 bytes) (0 -> 64)
        <tile_height>    6-bit tile_height (0->64)
        <tile_vstep>     6-bit tile vertical step (0->64) to control tole vertical overlap
        Returns read data as a list
        """
        result = []  # will be a 2-d array
        #        tiles_per_row= (window_width/tile_width)+  ((window_width % tile_width==0)?0:1);
        tiles_per_row = (window_width / tile_width) + (0, 1)[(window_width % tile_width) == 0]
        tile_rows_per_window = ((window_height - 1) / tile_vstep) + 1
        tile_size = tile_width * tile_height
        channel = (0, 1)[channel]
        keep_open = (0, 1)[keep_open]
        show_data = (0, 1)[show_data]
        print(
            "====== test_tiled_read: channel=%d, byte32=%d, keep_open=%d, extra_pages=%d,  show_data=%d"
            % (channel, byte32, keep_open, extra_pages, show_data)
        )
        if channel == 2:
            start_addr = vrlg.MCNTRL_TILED_CHN2_ADDR
            status_address = vrlg.MCNTRL_TEST01_STATUS_REG_CHN2_ADDR
            status_control_address = vrlg.MCNTRL_TEST01_ADDR + vrlg.MCNTRL_TEST01_CHN2_STATUS_CNTRL
            test_mode_address = vrlg.MCNTRL_TEST01_ADDR + vrlg.MCNTRL_TEST01_CHN2_MODE
        elif channel == 4:
            start_addr = vrlg.MCNTRL_TILED_CHN4_ADDR
            status_address = vrlg.MCNTRL_TEST01_STATUS_REG_CHN4_ADDR
            status_control_address = vrlg.MCNTRL_TEST01_ADDR + vrlg.MCNTRL_TEST01_CHN4_STATUS_CNTRL
            test_mode_address = vrlg.MCNTRL_TEST01_ADDR + vrlg.MCNTRL_TEST01_CHN4_MODE
        else:
            print("**** ERROR: Invalid channel, only 2 and 4 are valid")
            start_addr = vrlg.MCNTRL_TILED_CHN2_ADDR
            status_address = vrlg.MCNTRL_TEST01_STATUS_REG_CHN2_ADDR
            status_control_address = vrlg.MCNTRL_TEST01_ADDR + vrlg.MCNTRL_TEST01_CHN2_STATUS_CNTRL
            test_mode_address = vrlg.MCNTRL_TEST01_ADDR + vrlg.MCNTRL_TEST01_CHN2_MODE

        """
        mode=   self.func_encode_mode_tiled(
                                            byte32,
                                            keep_open,
                                            extra_pages,
                                            0, # write_mem,
                                            1, # enable
                                            0)  # chn_reset
        """
        mode = x393_mcntrl.func_encode_mode_scan_tiled(
            disable_need=False,
            repetitive=True,
            single=False,
            reset_frame=False,
            byte32=byte32,
            keep_open=keep_open,
            extra_pages=extra_pages,
            write_mem=False,
            enable=True,
            chn_reset=False,
        )

        self.x393_axi_tasks.write_control_register(start_addr + vrlg.MCNTRL_TILED_MODE, 0)
        # reset channel, including page address
        self.x393_axi_tasks.write_control_register(
            start_addr + vrlg.MCNTRL_TILED_STARTADDR, vrlg.FRAME_START_ADDRESS
        )  # RA=80, CA=0, BA=0 22-bit frame start address (3 CA LSBs==0. BA==0)
        self.x393_axi_tasks.write_control_register(
            start_addr + vrlg.MCNTRL_TILED_FRAME_FULL_WIDTH, vrlg.FRAME_FULL_WIDTH
        )
        self.x393_axi_tasks.write_control_register(
            start_addr + vrlg.MCNTRL_TILED_WINDOW_WH, concat(((window_height, 16), (window_width, 16)))[0]
        )  # {window_height,window_width});
        self.x393_axi_tasks.write_control_register(
            start_addr + vrlg.MCNTRL_TILED_WINDOW_X0Y0, concat(((window_top, 16), (window_left, 16)))[0]
        )  #  {window_top,window_left});
        self.x393_axi_tasks.write_control_register(
            start_addr + vrlg.MCNTRL_TILED_WINDOW_STARTXY, concat(((vrlg.TILED_STARTY, 16), (vrlg.TILED_STARTX, 16)))[0]
        )  #  TILED_STARTX+(TILED_STARTY<<16));
        self.x393_axi_tasks.write_control_register(
            start_addr + vrlg.MCNTRL_TILED_TILE_WHS, concat(((tile_vstep, 8), (tile_height, 8), (tile_width, 8)))[0]
        )  # {8'b0,tile_vstep,tile_height,tile_width});#tile_width+(tile_height<<8)+(tile_vstep<<16));
        self.x393_axi_tasks.write_control_register(start_addr + vrlg.MCNTRL_TILED_MODE, mode)
        # set mode register: {extra_pages[1:0],enable,!reset}
        self.x393_axi_tasks.configure_channel_priority(channel, 0)  # lowest priority channel 3
        self.x393_axi_tasks.enable_memcntrl_en_dis(channel, 1)
        self.x393_axi_tasks.write_control_register(test_mode_address, vrlg.TEST01_START_FRAME)
        for ii in range(
            tiles_per_row * tile_rows_per_window
        ):  # (ii=0;ii<(tiles_per_row * tile_rows_per_window);ii = ii+1) begin
            self.x393_axi_tasks.wait_status_condition(
                status_address,  # MCNTRL_TEST01_STATUS_REG_CHN4_ADDR,
                status_control_address,  # MCNTRL_TEST01_ADDR + MCNTRL_TEST01_CHN4_STATUS_CNTRL,
                vrlg.DEFAULT_STATUS_MODE,
                ii << 16,  # -TEST_INITIAL_BURST)<<16, # 4-bit page number
                0xF << 16,  #'hf << 16,  # mask for the 4-bit page number
                1,  # not equal to
                (0, 1)[ii == 0],
            )  # synchronize sequence number - only first time, next just wait fro auto update
            if show_data:
                print("########### test_tiled_read block %d: channel=%d" % (ii, channel))

            result.append(
                self.x393_mcntrl_buffers.read_block_buf_chn(
                    channel,
                    (ii & 3),
                    tile_size << 2,
                    #                                                                       1, # chn=0, page=3, number of 32-bit words=256, show_rslt
                    show_data,
                )
            )
            self.x393_axi_tasks.write_control_register(test_mode_address, vrlg.TEST01_NEXT_PAGE)
        #     enable_memcntrl_en_dis(channel,0); # disable channel
        return result
Exemple #4
0
    def test_tiled_write(
        self,  #
        channel,  # input            [3:0] channel;
        byte32,  # input                  byte32;
        keep_open,  # input                  keep_open;
        extra_pages,  # input            [1:0] extra_pages;
        wait_done,  # input                  wait_done;
        window_width,  # input [15:0]           window_width;
        window_height,  # input [15:0]           window_height;
        window_left,  # input [15:0]           window_left;
        window_top,  # input [15:0]           window_top;
        tile_width,  # input [ 7:0]           tile_width;
        tile_height,  # input [ 7:0]           tile_height;
        tile_vstep,
    ):  # input [ 7:0]           tile_vstep;
        """
        Test tiled mode write (frame size/row increment is set in parameters) 
        <channel> channel number to use. Valid values: 2, 4
        <byte32>        use 32-byte wide columns (0 - use 16-byte ones)
        <keep_open>,    do not close page between accesses (for 8 or less rows only)
        <extra_pages>    2-bit number of extra pages that need to stay (not to be overwritten) in the buffer
        <wait_done>      wait for operation finished
        <window_width>   13-bit window width in 8-bursts (16 bytes)
        <window_height>  16 bit window height
        <window_left>,   13-bit window left margin in 8-bursts (16 bytes)
        <window_top>     16-bit window top margin
        <tile_width>     6-bit tile width in 8-bursts (16 bytes) (0 -> 64)
        <tile_height>    6-bit tile_height (0->64)
        <tile_vstep>     6-bit tile vertical step (0->64) to control tole vertical overlap
        """

        #        tiles_per_row= (window_width/tile_width)+  ((window_width % tile_width==0)?0:1);
        tiles_per_row = (window_width / tile_width) + (0, 1)[(window_width % tile_width) == 0]
        tile_rows_per_window = ((window_height - 1) / tile_vstep) + 1
        tile_size = tile_width * tile_height
        channel = (0, 1)[channel]
        keep_open = (0, 1)[keep_open]
        wait_done = (0, 1)[wait_done]

        print(
            "====== test_tiled_write: channel=%d, byte32=%d, keep_open=%d, extra_pages=%d,  wait_done=%d"
            % (channel, byte32, keep_open, extra_pages, wait_done)
        )
        if channel == 2:
            start_addr = vrlg.MCNTRL_TILED_CHN2_ADDR
            status_address = vrlg.MCNTRL_TEST01_STATUS_REG_CHN2_ADDR
            status_control_address = vrlg.MCNTRL_TEST01_ADDR + vrlg.MCNTRL_TEST01_CHN2_STATUS_CNTRL
            test_mode_address = vrlg.MCNTRL_TEST01_ADDR + vrlg.MCNTRL_TEST01_CHN2_MODE
        elif channel == 4:
            start_addr = vrlg.MCNTRL_TILED_CHN4_ADDR
            status_address = vrlg.MCNTRL_TEST01_STATUS_REG_CHN4_ADDR
            status_control_address = vrlg.MCNTRL_TEST01_ADDR + vrlg.MCNTRL_TEST01_CHN4_STATUS_CNTRL
            test_mode_address = vrlg.MCNTRL_TEST01_ADDR + vrlg.MCNTRL_TEST01_CHN4_MODE
        else:
            print("**** ERROR: Invalid channel, only 2 and 4 are valid")
            start_addr = vrlg.MCNTRL_TILED_CHN2_ADDR
            status_address = vrlg.MCNTRL_TEST01_STATUS_REG_CHN2_ADDR
            status_control_address = vrlg.MCNTRL_TEST01_ADDR + vrlg.MCNTRL_TEST01_CHN2_STATUS_CNTRL
            test_mode_address = vrlg.MCNTRL_TEST01_ADDR + vrlg.MCNTRL_TEST01_CHN2_MODE
        """    
        mode=   self.func_encode_mode_tiled(
                                            byte32,
                                            keep_open,
                                            extra_pages,
                                            1,           # write_mem,
                                            1,           # enable
                                            0)           # chn_reset
        """
        mode = x393_mcntrl.func_encode_mode_scan_tiled(
            disable_need=False,
            repetitive=True,
            single=False,
            reset_frame=False,
            byte32=byte32,
            keep_open=keep_open,
            extra_pages=extra_pages,
            write_mem=True,
            enable=True,
            chn_reset=False,
        )

        self.x393_axi_tasks.write_control_register(start_addr + vrlg.MCNTRL_TILED_MODE, 0)
        # reset channel, including page address
        self.x393_axi_tasks.write_control_register(
            start_addr + vrlg.MCNTRL_TILED_STARTADDR, vrlg.FRAME_START_ADDRESS
        )  # RA=80, CA=0, BA=0 22-bit frame start address (3 CA LSBs==0. BA==0)
        self.x393_axi_tasks.write_control_register(
            start_addr + vrlg.MCNTRL_TILED_FRAME_FULL_WIDTH, vrlg.FRAME_FULL_WIDTH
        )
        self.x393_axi_tasks.write_control_register(
            start_addr + vrlg.MCNTRL_TILED_WINDOW_WH, concat(((window_height, 16), (window_width, 16)))[0]
        )  # {window_height,window_width});
        self.x393_axi_tasks.write_control_register(
            start_addr + vrlg.MCNTRL_TILED_WINDOW_X0Y0, concat(((window_top, 16), (window_left, 16)))[0]
        )  #  {window_top,window_left});
        self.x393_axi_tasks.write_control_register(
            start_addr + vrlg.MCNTRL_TILED_WINDOW_STARTXY, concat(((vrlg.TILED_STARTY, 16), (vrlg.TILED_STARTX, 16)))[0]
        )  #  TILED_STARTX+(TILED_STARTY<<16));
        self.x393_axi_tasks.write_control_register(
            start_addr + vrlg.MCNTRL_TILED_TILE_WHS, concat(((tile_vstep, 8), (tile_height, 8), (tile_width, 8)))[0]
        )  # {8'b0,tile_vstep,tile_height,tile_width});#tile_width+(tile_height<<8)+(tile_vstep<<16));
        self.x393_axi_tasks.write_control_register(start_addr + vrlg.MCNTRL_TILED_MODE, mode)
        # set mode register: {extra_pages[1:0],enable,!reset}
        self.x393_axi_tasks.configure_channel_priority(channel, 0)  # lowest priority channel 3
        self.x393_axi_tasks.enable_memcntrl_en_dis(channel, 1)
        self.x393_axi_tasks.write_control_register(test_mode_address, vrlg.TEST01_START_FRAME)

        for ii in range(vrlg.TEST_INITIAL_BURST):  # for (ii=0;ii<TEST_INITIAL_BURST;ii=ii+1) begin
            print("########### test_tiled_write block %d: channel=%d" % (ii, channel))
            startx = window_left + ((ii % tiles_per_row) * tile_width)
            starty = window_top + (ii / tile_rows_per_window)  # SCANLINE_CUR_Y);
            self.x393_mcntrl_buffers.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);\

        for ii in range(
            tiles_per_row * tile_rows_per_window
        ):  # for (ii=0;ii<(tiles_per_row * tile_rows_per_window);ii = ii+1) begin
            if ii >= vrlg.TEST_INITIAL_BURST:  # ) begin # wait page ready and fill page after first 4 are filled
                self.x393_axi_tasks.wait_status_condition(
                    status_address,  # MCNTRL_TEST01_STATUS_REG_CHN5_ADDR,
                    status_control_address,  # MCNTRL_TEST01_ADDR + MCNTRL_TEST01_CHN5_STATUS_CNTRL,
                    vrlg.DEFAULT_STATUS_MODE,
                    (ii - vrlg.TEST_INITIAL_BURST) << 16,  # 4-bit page number
                    0xF << 16,  # 'hf << 16,  # mask for the 4-bit page number
                    1,  # not equal to
                    (0, 1)[ii == vrlg.TEST_INITIAL_BURST],
                )
                # synchronize sequence number - only first time, next just wait fro auto update
                print("########### test_tiled_write block %d: channel=%d" % (ii, channel))
                startx = window_left + ((ii % tiles_per_row) * tile_width)
                starty = window_top + (ii / tile_rows_per_window)
                self.x393_mcntrl_buffers.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);\
            self.x393_axi_tasks.write_control_register(test_mode_address, vrlg.TEST01_NEXT_PAGE)
        if wait_done:
            self.x393_axi_tasks.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,
                vrlg.DEFAULT_STATUS_MODE,
                2 << vrlg.STATUS_2LSB_SHFT,  # bit 24 - busy, bit 25 - frame done
                2 << vrlg.STATUS_2LSB_SHFT,  # mask for the 4-bit page number
                0,  # equal to
                0,
            )  # no need to synchronize sequence number