Commit a22c0250 authored by Andrey Filippov's avatar Andrey Filippov

Working on compression bypassing in raw data mode

parent 1725c547
......@@ -292,6 +292,7 @@
parameter MCONTR_LINTILE_EXTRAPG_BITS = 2, // number of bits to use for extra pages
parameter MCONTR_LINTILE_KEEP_OPEN = 5, // keep banks open (will be used only if number of rows <= 8)
parameter MCONTR_LINTILE_BYTE32 = 6, // use 32-byte wide columns in each tile (false - 16-byte)
parameter MCONTR_LINTILE_LINEAR = 7, // Use linear mode instead of tiled
parameter MCONTR_LINTILE_RST_FRAME = 8, // reset frame number
parameter MCONTR_LINTILE_SINGLE = 9, // read/write a single page
parameter MCONTR_LINTILE_REPEAT = 10, // read/write pages until disabled
......
......@@ -255,7 +255,8 @@ module mcntrl393 #(
parameter MCONTR_LINTILE_EXTRAPG = 3, // extra pages (over 1) needed by the client simultaneously
parameter MCONTR_LINTILE_EXTRAPG_BITS = 2, // number of bits to use for extra pages
parameter MCONTR_LINTILE_KEEP_OPEN = 5, // keep banks open (will be used only if number of rows <= 8)
parameter MCONTR_LINTILE_BYTE32 = 6, // use 32-byte wide columns in each tile (false - 16-byte)
parameter MCONTR_LINTILE_BYTE32 = 6, // use 32-byte wide columns in each tile (false - 16-byte)
parameter MCONTR_LINTILE_LINEAR = 7, // Use linear mode instead of tiled
parameter MCONTR_LINTILE_RST_FRAME = 8, // reset frame number
parameter MCONTR_LINTILE_SINGLE = 9, // read/write a single page
parameter MCONTR_LINTILE_REPEAT = 10, // read/write pages until disabled
......@@ -1190,6 +1191,7 @@ module mcntrl393 #(
.MCONTR_LINTILE_EXTRAPG_BITS (MCONTR_LINTILE_EXTRAPG_BITS),
.MCONTR_LINTILE_KEEP_OPEN (MCONTR_LINTILE_KEEP_OPEN),
.MCONTR_LINTILE_BYTE32 (MCONTR_LINTILE_BYTE32),
.MCONTR_LINTILE_LINEAR (MCONTR_LINTILE_LINEAR), // Use linear mode instead of tiled
.MCONTR_LINTILE_RST_FRAME (MCONTR_LINTILE_RST_FRAME),
.MCONTR_LINTILE_SINGLE (MCONTR_LINTILE_SINGLE),
.MCONTR_LINTILE_REPEAT (MCONTR_LINTILE_REPEAT),
......@@ -1216,17 +1218,17 @@ module mcntrl393 #(
.frames_in_sync (cmprs_frames_in_sync[i]), // output
.master_frame (cmprs_frame_number_src[i * LAST_FRAME_BITS +: LAST_FRAME_BITS]), // input[15:0]
.master_set (sens_frame_set[i]), // input
// .master_follow (master_follow[i]), // input
.xfer_want (cmprs_want[i]), // output
.xfer_need (cmprs_need[i]), // output
.xfer_grant (cmprs_channel_pgm_en[i]), // input
.xfer_start_rd (cmprs_start_rd16[i]), // output
.xfer_start_rd (cmprs_start_rd16[i]), // output // TODO: start rd (wr too?) linear
.xfer_start_wr (), // output
.xfer_start32_rd (cmprs_start_rd32[i]), // output
.xfer_start32_wr (), // output
.xfer_bank (cmprs_bank[i * 3 +: 3]), // output[2:0]
.xfer_row (cmprs_row[ADDRESS_NUMBER * i +: ADDRESS_NUMBER]), // output[14:0]
.xfer_col (cmprs_col[COL_WDTH * i +: COL_WDTH]), // output[6:0]
.xfer_col (cmprs_col[COL_WDTH * i +: COL_WDTH]), // output[6:0]
// 5:0: add xfer_num128[5:0]
.rowcol_inc (cmprs_rowcol_inc[i * FRAME_WBP1 +: FRAME_WBP1]), // output[13:0]
.num_rows_m1 (cmprs_num_rows_m1[i * MAX_TILE_WIDTH +: MAX_TILE_WIDTH]), // output[5:0]
.num_cols_m1 (cmprs_num_cols_m1[i * MAX_TILE_HEIGHT +: MAX_TILE_HEIGHT]), // output[5:0]
......@@ -1237,8 +1239,27 @@ module mcntrl393 #(
.xfer_page_rst_rd (cmprs_xfer_reset_page_rd[i]) // output @negedge
);
/*
.xfer_num128 (sens_num128[i * 6 +: 6]), // output[5:0]
.xfer_partial (sens_partial[i]), // output
.xfer_done (sens_seq_done[i]), // input : page sequence over
.xfer_page_rst_wr (sens_rpage_set[i]), // output @ posedge mclk
.xfer_page_rst_rd (), // output @ negedge mclk
.xfer_skipped (sens_xfer_skipped[i]), // output reg
.cmd_wrmem () // output
.xfer_num128 (lin_rw_chn3_num128), // output[5:0]
.xfer_partial (lin_rw_chn3_partial), // output
.xfer_done (seq_done3), // input : sequence over
.xfer_page_rst_wr (xfer_reset_page3_wr), // output
.xfer_page_rst_rd (xfer_reset_page3_rd), // output
.xfer_skipped (), // output reg
.cmd_wrmem () // output
// assign cmd_wrmem = mode_reg[MCONTR_LINTILE_WRITE];// 0: read from memory, 1:write to memory
*/
end
......@@ -1423,6 +1444,7 @@ module mcntrl393 #(
.MCONTR_LINTILE_EXTRAPG_BITS (MCONTR_LINTILE_EXTRAPG_BITS),
.MCONTR_LINTILE_KEEP_OPEN (MCONTR_LINTILE_KEEP_OPEN),
.MCONTR_LINTILE_BYTE32 (MCONTR_LINTILE_BYTE32),
.MCONTR_LINTILE_LINEAR (MCONTR_LINTILE_LINEAR), // Use linear mode instead of tiled
.MCONTR_LINTILE_RST_FRAME (MCONTR_LINTILE_RST_FRAME),
.MCONTR_LINTILE_SINGLE (MCONTR_LINTILE_SINGLE),
.MCONTR_LINTILE_REPEAT (MCONTR_LINTILE_REPEAT),
......@@ -1441,12 +1463,12 @@ module mcntrl393 #(
.next_page (next_page_chn2), // input
.frame_done (frame_done_chn2), // output
.frame_finished (), // output
.line_unfinished (line_unfinished_chn2), // output[15:0]
.line_unfinished (line_unfinished_chn2), // output[15:0]
.suspend (suspend_chn2), // input
.frame_number (frame_number_chn2),
.frame_number (frame_number_chn2), // output[15:0]
.frames_in_sync(), // output
.master_frame (16'b0), // input[15:0]
.master_set (1'b0), // input
.master_frame (16'b0), // input[15:0] // Set master frame number value
.master_set (1'b0), // input // set master frame strobe
// .master_follow (1'b0), // input
.xfer_want (want_rq2), // output
.xfer_need (need_rq2), // output
......@@ -1497,6 +1519,7 @@ module mcntrl393 #(
.MCONTR_LINTILE_EXTRAPG_BITS (MCONTR_LINTILE_EXTRAPG_BITS),
.MCONTR_LINTILE_KEEP_OPEN (MCONTR_LINTILE_KEEP_OPEN),
.MCONTR_LINTILE_BYTE32 (MCONTR_LINTILE_BYTE32),
.MCONTR_LINTILE_LINEAR (MCONTR_LINTILE_LINEAR), // Use linear mode instead of tiled
.MCONTR_LINTILE_RST_FRAME (MCONTR_LINTILE_RST_FRAME),
.MCONTR_LINTILE_SINGLE (MCONTR_LINTILE_SINGLE),
.MCONTR_LINTILE_REPEAT (MCONTR_LINTILE_REPEAT),
......
......@@ -101,7 +101,6 @@ module mcntrl_linear_rw #(
input frame_start, // resets page, x,y, and initiates transfer requests (in write mode will wait for next_page)
output frame_run, // @mclk - enable pixels from sensor to memory buffer
input next_page, // page was read/written from/to 4*1kB on-chip buffer
// output page_ready, // == xfer_done, connect externally | Single-cycle pulse indicating that a page was read/written from/to DDR3 memory
output frame_done, // single-cycle pulse when the full frame (window) was transferred to/from DDR3 memory
output frame_finished,// turns on and stays on after frame_done
// optional I/O for channel synchronization
......@@ -154,27 +153,27 @@ module mcntrl_linear_rw #(
reg [FRAME_WIDTH_BITS:0] frame_full_width_r; // (14 bit) register to be absorbed by MPY
reg [MPY_WIDTH-1:0] mul_rslt;
reg [NUM_RC_BURST_BITS-1:0] start_addr_r; // 22 bit - to be absorbed by DSP
// reg [2:0] bank_reg [2:0];
reg [3 * 3 - 1:0] bank_reg;
wire [FRAME_WIDTH_BITS+FRAME_HEIGHT_BITS-3:0] mul_rslt_w;
reg [FRAME_WIDTH_BITS:0] row_left; // number of 8-bursts left in the current row
reg last_in_row;
reg [COLADDR_NUMBER-3:0] mem_page_left; // number of 8-bursts left in the pointed memory page
reg [COLADDR_NUMBER-4:0] line_start_page_left; // number of 8-burst left in the memory page from the start of the frame line
reg [NUM_XFER_BITS:0] lim_by_xfer; // number of bursts left limited by the longest transfer (currently 64)
// reg [MAX_TILE_WIDTH:0] lim_by_tile_width; // number of bursts left limited by the longest transfer (currently 64)
wire [COLADDR_NUMBER-3:0] remainder_in_xfer ;//remainder_tile_width; // number of bursts postponed to the next partial tile (because of the page crossing) MSB-sign
reg continued_xfer; //continued_tile; // this is a continued tile (caused by page crossing) - only once
reg [NUM_XFER_BITS-1:0] leftover; //[MAX_TILE_WIDTH-1:0] leftover_cols; // valid with continued_tile, number of columns left
reg [NUM_XFER_BITS:0] xfer_num128_r; // number of 128-bit words to transfer (8*16 bits) - full bursts of 8
// reg [NUM_XFER_BITS-1:0] xfer_num128_m1_r; // number of 128-bit words to transfer minus 1 (8*16 bits) - full bursts of 8
wire pgm_param_w; // program one of the parameters, invalidate calculated results for PAR_MOD_LATENCY
reg [2:0] xfer_start_r; // 1 hot started by xfer start only (not by parameter change)
reg xfer_start_rd_r;
reg xfer_start_wr_r;
reg [PAR_MOD_LATENCY-1:0] par_mod_r;
reg [PAR_MOD_LATENCY-1:0] recalc_r; // 1-hot CE for re-calculating registers
// SuppressWarnings VEditor unused
......@@ -210,7 +209,6 @@ module mcntrl_linear_rw #(
reg frame_finished_r;
wire last_in_row_w;
wire last_row_w;
// wire last_block_w;
reg last_block;
reg [MCNTRL_SCANLINE_PENDING_CNTR_BITS-1:0] pending_xfers; // number of requested,. but not finished block transfers
reg [NUM_RC_BURST_BITS-1:0] row_col_r;
......@@ -258,7 +256,6 @@ module mcntrl_linear_rw #(
reg [LAST_FRAME_BITS-1:0] frame_number_current;
reg is_last_frame;
// reg [2:0] frame_start_r;
reg [4:0] frame_start_r; // increased length to have time from line_unfinished to suspend (external)
reg [FRAME_WIDTH_BITS:0] frame_full_width; // (programmed) increment combined row/col when moving to the next line
......@@ -270,6 +267,7 @@ module mcntrl_linear_rw #(
reg [FRAME_HEIGHT_BITS-1:0] window_y0; // (programmed) window top
reg [FRAME_WIDTH_BITS-1:0] start_x; // (programmed) normally 0, copied to curr_x on frame_start_late
reg [FRAME_HEIGHT_BITS-1:0] start_y; // (programmed) normally 0, copied to curr_y on frame_start_late
reg xfer_done_d; // xfer_done delayed by 1 cycle (also includes xfer_skipped)
reg [MCNTRL_SCANLINE_DLY_WIDTH-1:0] start_delay; // how much to delay frame start
reg [MCNTRL_SCANLINE_DLY_WIDTH:0] start_delay_cntr = {MCNTRL_SCANLINE_DLY_WIDTH+1{1'b1}}; // start delay counter
......@@ -311,12 +309,7 @@ module mcntrl_linear_rw #(
if (mrst) rst_frame_num_r <= 0;
else rst_frame_num_r <= {rst_frame_num_r[0], rst_frame_num_w }; // now only at specific command
/*
|
set_start_addr_w |
set_last_frame_w |
set_frame_size_w};
*/
if (mrst) start_range_addr <= 0;
else if (set_start_addr_w) start_range_addr <= cmd_data[NUM_RC_BURST_BITS-1:0];
......@@ -331,7 +324,6 @@ module mcntrl_linear_rw #(
else if (set_frame_width_w) frame_full_width <= {lsw13_zero,cmd_data[FRAME_WIDTH_BITS-1:0]};
if (mrst) is_last_frame <= 0;
// else is_last_frame <= frame_number_cntr == last_frame_number;
else is_last_frame <= frame_number_cntr >= last_frame_number; // trying to make it safe
`ifdef REPORT_FRAME_NUMBER
......@@ -342,7 +334,6 @@ module mcntrl_linear_rw #(
// if (mrst) frame_start_r <= 0;
// else frame_start_r <= {frame_start_r[3:0], frame_start_late & frame_en};
// if (mrst) frame_en <= 0;
if (!chn_en) frame_en <= 0;
else if (single_frame_r || repeat_frames) frame_en <= 1;
else if (frame_start_late) frame_en <= 0;
......@@ -407,9 +398,9 @@ module mcntrl_linear_rw #(
assign xfer_start_rd= xfer_start_rd_r;
assign xfer_start_wr= xfer_start_wr_r;
assign calc_valid= par_mod_r[PAR_MOD_LATENCY-1]; // MSB, longest 0
assign xfer_page_rst_wr= xfer_page_rst_r;
assign xfer_page_rst_rd= xfer_page_rst_neg;
assign xfer_partial= xfer_limited_by_mem_page_r;
assign frame_done= frame_done_r;
......@@ -430,7 +421,7 @@ module mcntrl_linear_rw #(
assign xfer_row= row_col_r[NUM_RC_BURST_BITS-1:COLADDR_NUMBER-3] ; // memory row
assign xfer_col= row_col_r[COLADDR_NUMBER-4:0]; // start memory column in 8-bursts
assign line_unfinished = line_unfinished_r; // [FRAME_HEIGHT_BITS +: FRAME_HEIGHT_BITS];
assign chn_en = mode_reg[MCONTR_LINTILE_NRESET] & mode_reg[MCONTR_LINTILE_EN]; // enable requests by channel (continue ones in progress)
assign chn_en = mode_reg[MCONTR_LINTILE_NRESET] & mode_reg[MCONTR_LINTILE_EN]; // enable requests by channel (continue ones in progress)
assign chn_rst = ~mode_reg[MCONTR_LINTILE_NRESET]; // resets command, including fifo;
assign cmd_wrmem = mode_reg[MCONTR_LINTILE_WRITE];// 0: read from memory, 1:write to memory
assign cmd_extra_pages = mode_reg[MCONTR_LINTILE_EXTRAPG+:MCONTR_LINTILE_EXTRAPG_BITS]; // external module needs more than 1 page
......@@ -448,7 +439,8 @@ module mcntrl_linear_rw #(
assign status_data= {frame_finished_r, busy_r}; // TODO: Add second bit?
`endif
`endif
assign pgm_param_w= cmd_we;
assign pgm_param_w= cmd_we;
localparam [COLADDR_NUMBER-3-NUM_XFER_BITS-1:0] EXTRA_BITS=0;
assign remainder_in_xfer = {EXTRA_BITS, lim_by_xfer}-mem_page_left;
......@@ -575,10 +567,6 @@ wire start_not_partial= xfer_start_r[0] && !xfer_limited_by_mem_page_r;
// calculate number to read (min of row_left, maximal xfer and what is left in the DDR3 page
always @(posedge mclk) begin
// acceletaring pre_want
// pre_want_r1 <= chn_en && !frame_done_r && busy_r && par_mod_r[PAR_MOD_LATENCY-2] && !(|frame_start_r[4:1]) && !last_block;
//last_block is too late for pre_want_r1, moving upsteram
// pre_want_r1 <= chn_en && !frame_done_r && busy_r && par_mod_r[PAR_MOD_LATENCY-2] && !(|frame_start_r[4:1]);
pre_want_r1 <= !chn_rst && !frame_done_r && busy_r && par_mod_r[PAR_MOD_LATENCY-2] && !(|frame_start_r[4:1]);
if (mrst) par_mod_r<=0;
else if (pgm_param_w ||
......
/*!
* <b>Module:</b>mcntrl_tiled_linear_rw
* @file mcntrl_tiled_linear_rw.v
* @date 2015-02-03
* @author Andrey Filippov
*
* @brief Organize paged R/W from DDR3 memory in tiled order
* with window support
* Tiles spreading over two different frames is not yet supported (needed for
* line-scan mode in JPEG (JP4 - OK)
*
* @copyright Copyright (c) 2015 Elphel, Inc.
*
* <b>License:</b>
*
* mcntrl_tiled_linear_rw.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.
*
* mcntrl_tiled_linear_rw.v 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 <http://www.gnu.org/licenses/> .
*
* Additional permission under GNU GPL version 3 section 7:
* If you modify this Program, or any covered work, by linking or combining it
* with independent modules provided by the FPGA vendor only (this permission
* does not extend to any 3-rd party modules, "soft cores" or macros) under
* different license terms solely for the purpose of generating binary "bitstream"
* files and/or simulating the code, the copyright holders of this Program give
* you the right to distribute the covered work without those independent modules
* as long as the source code for them is available from the FPGA vendor free of
* charge, and there is no dependence on any encrypted modules for simulating of
* the combined code. This permission applies to you if the distributed code
* contains all the components and scripts required to completely simulate it
* with at least one of the Free Software programs.
*/
`timescale 1ns/1ps
`define REPORT_FRAME_NUMBER 1
`undef DEBUG_MCNTRL_TILED_EXTRA_STATUS
module mcntrl_tiled_linear_rw#(
parameter ADDRESS_NUMBER= 15,
parameter COLADDR_NUMBER= 10,
parameter FRAME_WIDTH_BITS= 13, // Maximal frame width - 8-word (16 bytes) bursts
parameter FRAME_HEIGHT_BITS= 16, // Maximal frame height
parameter MAX_TILE_WIDTH= 6, // number of bits to specify maximal tile (width-1) (6 -> 64). Used as NUM_XFER_BITS in LINEAR mode
parameter MAX_TILE_HEIGHT= 6, // number of bits to specify maximal tile (height-1) (6 -> 64)
parameter LAST_FRAME_BITS= 16, // number of bits in frame counter (before rolls over)
parameter MCNTRL_TILED_ADDR= 'h120,
parameter MCNTRL_TILED_MASK= 'h7f0, // both channels 0 and 1
parameter MCNTRL_TILED_MODE= 'h0, // set mode register: {byte32,keep_open,extra_pages[1:0],write_mode,enable,!reset}
parameter MCNTRL_TILED_STATUS_CNTRL= 'h1, // control status reporting
parameter MCNTRL_TILED_STARTADDR= 'h2, // 22-bit frame start address (3 CA LSBs==0. BA==0)
parameter MCNTRL_TILED_FRAME_SIZE= 'h3, // 22-bit frame start address increment (3 CA LSBs==0. BA==0)
parameter MCNTRL_TILED_FRAME_LAST= 'h4, // 16-bit last frame number in the buffer
parameter MCNTRL_TILED_FRAME_FULL_WIDTH='h5, // Padded line length (8-row increment), in 8-bursts (16 bytes)
parameter MCNTRL_TILED_WINDOW_WH= 'h6, // low word - 13-bit window width (0->'h4000), high word - 16-bit frame height (0->'h10000)
parameter MCNTRL_TILED_WINDOW_X0Y0= 'h7, // low word - 13-bit window left, high word - 16-bit window top
parameter MCNTRL_TILED_WINDOW_STARTXY= 'h8, // low word - 13-bit start X (relative to window), high word - 16-bit start y
// Start XY can be used when read command to start from the middle
// TODO: Add number of blocks to R/W? (blocks can be different) - total length?
// Read back current address (for debugging)?
parameter MCNTRL_TILED_TILE_WHS= 'h9, // low byte - 6-bit tile width in 8-bursts, second byte - tile height (0 - > 64),
// 3-rd byte - vertical step (to control tile vertical overlap)
parameter MCNTRL_TILED_STATUS_REG_ADDR= 'h5,
parameter MCNTRL_TILED_PENDING_CNTR_BITS=2, // Number of bits to count pending trasfers, currently 2 is enough, but may increase
// if memory controller will allow programming several sequences in advance to
// spread long-programming (tiled) over fast-programming (linear) requests.
// But that should not be too big to maintain 2-level priorities
parameter MCNTRL_TILED_FRAME_PAGE_RESET =1'b0, // reset internal page number to zero at the frame start (false - only when hard/soft reset)
// bits in mode control word
parameter MCONTR_LINTILE_NRESET = 0, // reset if 0
parameter MCONTR_LINTILE_EN = 1, // enable requests
parameter MCONTR_LINTILE_WRITE = 2, // write to memory mode
parameter MCONTR_LINTILE_EXTRAPG = 3, // extra pages (over 1) needed by the client simultaneously
parameter MCONTR_LINTILE_EXTRAPG_BITS = 2, // number of bits to use for extra pages
parameter MCONTR_LINTILE_KEEP_OPEN = 5, // keep banks open (will be used only if number of rows <= 8)
parameter MCONTR_LINTILE_BYTE32 = 6, // use 32-byte wide columns in each tile (false - 16-byte)
parameter MCONTR_LINTILE_LINEAR = 7, // Use linear mode instead of tiled
parameter MCONTR_LINTILE_RST_FRAME = 8, // reset frame number
parameter MCONTR_LINTILE_SINGLE = 9, // read/write a single page
parameter MCONTR_LINTILE_REPEAT = 10, // read/write pages until disabled
parameter MCONTR_LINTILE_DIS_NEED = 11, // disable 'need' request
// parameter MCONTR_LINTILE_SKIP_LATE = 12, // skip actual R/W operation when it is too late, advance pointers NEW: Copied from LINEAR
parameter MCONTR_LINTILE_COPY_FRAME = 13, // copy frame number from the master channel (single event, not a persistent mode)
parameter MCONTR_LINTILE_ABORT_LATE = 14 // abort frame if not finished by the new frame sync (wait pending memory)
)(
input mrst,
input mclk,
// programming interface
input [7:0] cmd_ad, // byte-serial command address/data (up to 6 bytes: AL-AH-D0-D1-D2-D3
input cmd_stb, // strobe (with first byte) for the command a/d
output [7:0] status_ad, // byte-wide address/data
output status_rq, // request to send downstream (last byte with rq==0)
input status_start, // acknowledge of address (first byte) from downsteram
input frame_start, // resets page, x,y, and initiates transfer requests (in write mode will wait for next_page)
output frame_start_conf, // frame start modified by memory controller. Normally delayed by 1 cycle,
// or more if memory transactions are to be finished
input next_page, // page was read/written from/to 4*1kB on-chip buffer
output frame_done, // single-cycle pulse when the full frame (window) was transferred to/from DDR3 memory
output frame_finished,// turns on and stays on after frame_done
// optional I/O for channel synchronization
// after the last tile in a frame, before starting a new frame line_unfinished will point to non-existent (too high) line in the same frame
output [FRAME_HEIGHT_BITS-1:0] line_unfinished, // number of the current (unfinished ) line, RELATIVE TO FRAME, NOT WINDOW.
input suspend, // suspend transfers (from external line number comparator)
output [LAST_FRAME_BITS-1:0] frame_number, // current frame number (for multi-frame ranges)
output frames_in_sync, // frame number valid for bonded mode //LINEAR: frame_set, // frame number is just set to a new value (can be used by slave to sync)
input [LAST_FRAME_BITS-1:0] master_frame, // current frame number of a master channel // LINEAR: nothing
input master_set, // master frame number set (1-st cycle when new value is valid) // LINEAR: nothing
output xfer_want, // "want" data transfer
output xfer_need, // "need" - really need a transfer (only 1 page/ room for 1 page left in a buffer), want should still be set.
input xfer_grant, // sequencer programming access granted, deassert wait/need
// LINEAR: output xfer_reject, // reject granted access (when skipping) (not used for compressor)
//
output xfer_start_lin_rd, // LINEAR: initiate a transfer (next cycle after xfer_grant), following signals (up to xfer_partial) are valid
output xfer_start_lin_wr, // LINEAR: initiate a transfer (next cycle after xfer_grant), following signals (up to xfer_partial) are valid
output xfer_start_rd, // initiate a transfer (next cycle after xfer_grant), following signals (up to xfer_partial) are valid // LINEAR: DNU
output xfer_start_wr, // initiate a transfer (next cycle after xfer_grant), following signals (up to xfer_partial) are valid // LINEAR: DNU
output xfer_start32_rd, // initiate a transfer to 32-byte wide colums scanning in each tile // LINEAR: DNU
output xfer_start32_wr, // initiate a transfer to 32-byte wide colums scanning in each tile // LINEAR: DNU
output [2:0] xfer_bank, // start bank address
output [ADDRESS_NUMBER-1:0] xfer_row, // memory row
output [COLADDR_NUMBER-4:0] xfer_col, // start memory column in 8-bursts
output [FRAME_WIDTH_BITS:0] rowcol_inc, // increment row+col (after bank) for the new scan line in 8-bursts (externally pad with 0)
output [MAX_TILE_WIDTH-1:0] num_rows_m1, // number of rows to read minus 1
output [MAX_TILE_HEIGHT-1:0] num_cols_m1, // number of 16-pixel columns to read (rows first, then columns) - 1
output keep_open, // (programmable bit)keep banks open (for <=8 banks only // LINEAR: DNU
// LINEAR: [NUM_XFER_BITS-1:0] xfer_num128, // number of 128-bit words to transfer (8*16 bits) - full bursts of 8 ( 0 - maximal length, 64)
output [MAX_TILE_WIDTH-1:0] xfer_num128, // number of 128-bit words to transfer (8*16 bits) - full bursts of 8 ( 0 - maximal length, 64)
// assign xfer_num128= num_cols_r[NUM_XFER_BITS-1:0]; // One bit less!
output xfer_partial, // partial tile (first of 2) , sequencer will not generate page_next at the end of block
input xfer_page_done, // transfer to/from the buffer finished (partial transfers should not generate), use rpage_nxt_chn@mclk
output xfer_page_rst_wr, // reset buffer internal page - at each frame start or when specifically reset (write to memory channel), @posedge
output xfer_page_rst_rd // reset buffer internal page - at each frame start or when specifically reset (read memory channel), @negedge
);
// FIXME: not all tile heights are valid (because of the banks)
//MAX_TILE_WIDTH
localparam NUM_RC_BURST_BITS=ADDRESS_NUMBER+COLADDR_NUMBER-3; //to spcify row and col8 == 22
localparam MPY_WIDTH= NUM_RC_BURST_BITS; // 22
localparam PAR_MOD_LATENCY= 9; // TODO: Find actual worst-case latency for:
reg [FRAME_WIDTH_BITS-1:0] curr_x; // (calculated) start of transfer x (relative to window left)
reg [FRAME_HEIGHT_BITS-1:0] curr_y; // (calculated) start of transfer y (relative to window top)
reg [FRAME_HEIGHT_BITS:0] next_y; // (calculated) next row number
reg [NUM_RC_BURST_BITS-1:0] line_start_addr;// (calculated) Line start (in {row,col8} in burst8
reg [COLADDR_NUMBER-4:0] line_start_page_left; // number of 8-burst left in the memory page from the start of the frame line (LINEAR: DNU)
// calculating full width from the frame width
//WARNING: [Synth 8-3936] Found unconnected internal register 'frame_y_reg' and it is trimmed from '16' to '3' bits. [memctrl/mcntrl_tiled_linear_rw.v:307]
// Throblem seems to be that frame_y8_r_reg (load of trimmed bits of the frame_y_reg) is (as intended) absorbed into DSP48. The lower 3 bits are used
// outside of the DSP 48. "dont_touch" seems to work here
`ifndef IGNORE_ATTR
(* keep = "true" *)
`endif
reg [FRAME_HEIGHT_BITS-1:0] frame_y; // current line number referenced to the frame top
reg [FRAME_WIDTH_BITS-1:0] frame_x; // current column number referenced to the frame left
reg [FRAME_HEIGHT_BITS-4:0] frame_y8_r; // (13 bits) current row with bank removed, latency2 (to be absorbed when inferred DSP multipler)
reg [FRAME_WIDTH_BITS:0] frame_full_width_r; // (14 bit) register to be absorbed by MPY
reg [MPY_WIDTH-1:0] mul_rslt;
reg [NUM_RC_BURST_BITS-1:0] start_addr_r; // 22 bit - to be absorbed by DSP
reg [3 * 3 - 1:0] bank_reg;
wire [FRAME_WIDTH_BITS+FRAME_HEIGHT_BITS-3:0] mul_rslt_w;
reg [FRAME_WIDTH_BITS:0] row_left; // number of 8-bursts left in the current row
reg last_in_row;
reg [COLADDR_NUMBER-3:0] mem_page_left; // number of 8-bursts left in the pointed memory page
// (LINEAR: DNU)
reg [MAX_TILE_WIDTH:0] lim_by_tile_width; // number of bursts left limited by the longest transfer (currently 64) (LINEAR: DNU)
wire [COLADDR_NUMBER-3:0] remainder_tile_width; // number of bursts postponed to the next partial tile (because of the page crossing) MSB-sign
reg continued_tile; // this is a continued tile (caused by page crossing) - only once
reg [MAX_TILE_WIDTH-1:0] leftover_cols; // valid with continued_tile, number of columns left
// (TILED: DNU)
// reg [NUM_XFER_BITS:0] lim_by_xfer; // number of bursts left limited by the longest transfer (currently 64) - using lim_by_tile_width for lim_by_xfer
// reg [MAX_TILE_WIDTH:0] lim_by_tile_width; // number of bursts left limited by the longest transfer (currently 64)
// wire [COLADDR_NUMBER-3:0] remainder_in_xfer ;// Use remainder_tile_width; // number of bursts postponed to the next partial tile (because of the page crossing) MSB-sign
// TODO: in linear mode use continued_tile instead of continued_xfer !
/// reg continued_xfer; //continued_tile; // this is a continued tile (caused by page crossing) - only once
// reg [NUM_XFER_BITS-1:0] leftover; //[MAX_TILE_WIDTH-1:0] leftover_cols; // valid with continued_tile, number of columns left
// LINEAR using leftover_cols instead of leftover
// TODO: LINEAR: use num_cols_r instead of xfer_num128_r
// reg [NUM_XFER_BITS:0] xfer_num128_r; // number of 128-bit words to transfer (8*16 bits) - full bursts of 8
// end of (TILED: DNU)
wire pgm_param_w; // program one of the parameters, invalidate calculated results for PAR_MOD_LATENCY
reg [2:0] xfer_start_r;
// (LINEAR: DNU)
reg xfer_start_rd_r;
reg xfer_start_wr_r;
reg xfer_start32_rd_r;
reg xfer_start32_wr_r;
// (TILED: DNU)
reg xfer_start_lin_rd_r;
reg xfer_start_lin_wr_r;
// end of (TILED: DNU)
reg [PAR_MOD_LATENCY-1:0] par_mod_r;
reg [PAR_MOD_LATENCY-1:0] recalc_r; // 1-hot CE for re-calculating registers
// SuppressWarnings VEditor unused
wire calc_valid; // calculated registers have valid values - just for simulation
wire chn_en; // enable requests by channel (continue ones in progress), enable frame_start inputs
wire chn_rst; // resets command, including fifo;
reg chn_rst_d; // delayed by 1 cycle do detect turning off
wire abort_en; // enable frame abort (mode register bit)
reg aborting_r; // waiting pending memory transactions at if the frame was not finished at frame sync
reg aborting_d; // aborting_r delayed by 1 cycle // (LINEAR: DNU)
// LINEAR: wire with the same name wire frame_start_mod = (frame_start_late && !busy_r) || frame_start_delayed; // when frame_start_delayed it will completely miss a frame_start_late
reg frame_start_mod; // either original frame start pulse or delayed during abort (delayed by 1 cycle)
reg xfer_page_rst_r=1;
reg xfer_page_rst_pos=1;
reg xfer_page_rst_neg=1;
reg [2:0] page_cntr; // to maintain requests - difference between client requests and generated requests
// partial (truncated by memory page) generated requests should not count
wire cmd_wrmem; //= MCNTRL_TILED_WRITE_MODE; // 0: read from memory, 1:write to memory (change to parameter?) // (LINEAR: DNU)
wire [1:0] cmd_extra_pages; // external module needs more than 1 page
// wire skip_too_late; // from LINEAR
wire linear_mode; // use linear mode instead of tiles // (LINEAR: DNU)
wire byte32; // use 32-byte wide colums in each tile (0 - use 16-byte ones) // (LINEAR: DNU)
wire disable_need; // do not assert need, only want
wire repeat_frames; // mode bit
wire single_frame_w; // pulse
wire rst_frame_num_w;
wire set_copy_frame_num_w; // (LINEAR: DNU)
reg single_frame_r; // pulse
reg [1:0] rst_frame_num_r; // reset frame number/next start address
reg frame_en; // enable next frame
reg busy_r;
reg want_r;
reg want_d; // want_r delayed (no gap to pending_xfers)
reg need_r;
reg frame_done_r;
reg frame_finished_r;
wire last_in_row_w;
wire last_row_w;
reg last_block;
// MCNTRL_TILED_PENDING_CNTR_BITS == LINEAR:MCNTRL_SCANLINE_PENDING_CNTR_BITS
reg [MCNTRL_TILED_PENDING_CNTR_BITS-1:0] pending_xfers; // number of requested,. but not finished block transfers (to genearate frame done) // LINEAR:MCNTRL_SCANLINE_PENDING_CNTR_BITS
reg [NUM_RC_BURST_BITS-1:0] row_col_r;
reg [FRAME_HEIGHT_BITS-1:0] line_unfinished_relw_r;
reg [FRAME_HEIGHT_BITS-1:0] line_unfinished_r;
wire pre_want;
reg pre_want_r1; // LINEAR (equivalent)
`ifdef DEBUG_MCNTRL_TILED_EXTRA_STATUS
wire [13:0] status_data;
`else
`ifdef REPORT_FRAME_NUMBER
wire [LAST_FRAME_BITS+1:0] status_data;
`else
wire [1:0] status_data;
`endif
`endif
wire [3:0] cmd_a;
wire [31:0] cmd_data;
wire cmd_we;
wire set_mode_w;
wire set_status_w;
wire set_start_addr_w;
wire set_frame_size_w;
wire set_last_frame_w;
wire set_frame_width_w;
wire set_window_wh_w;
wire set_window_x0y0_w;
wire set_window_start_w;
wire set_tile_whs_w;
wire lsw13_zero=!(|cmd_data[FRAME_WIDTH_BITS-1:0]); // LSW 13 (FRAME_WIDTH_BITS) low bits are all 0 - set carry bit
wire msw_zero= !(|cmd_data[31:16]); // MSW all bits are 0 - set carry bit
wire tile_width_zero= !(|cmd_data[ 0+:MAX_TILE_WIDTH]); // (LINEAR: DNU)
wire tile_height_zero=!(|cmd_data[ 8+:MAX_TILE_HEIGHT]); // (LINEAR: DNU)
wire tile_vstep_zero= !(|cmd_data[16+:MAX_TILE_HEIGHT]); // (LINEAR: DNU)
reg [14:0] mode_reg;//mode register: {dis_need,repet,single,rst_frame,na,byte32,keep_open,extra_pages[1:0],write_mode,enable,!reset}
reg [NUM_RC_BURST_BITS-1:0] start_range_addr; // (programmed) First frame in range start (in {row,col8} in burst8, bank ==0
reg [NUM_RC_BURST_BITS-1:0] frame_size; // (programmed) First frame in range start (in {row,col8} in burst8, bank ==0
reg [LAST_FRAME_BITS-1:0] last_frame_number;
reg [NUM_RC_BURST_BITS-1:0] start_addr; // (programmed) Frame start (in {row,col8} in burst8, bank ==0
reg [NUM_RC_BURST_BITS-1:0] next_frame_start_addr;
reg [LAST_FRAME_BITS-1:0] frame_number_cntr;
reg [LAST_FRAME_BITS-1:0] frame_number_current;
reg is_last_frame;
reg [4:0] frame_start_r; // increased length to have time from line_unfinished to suspend (external)
// (LINEAR: DNU)
reg [MAX_TILE_WIDTH:0] tile_cols; // full number of columns in a tile (in bursts?)
reg [MAX_TILE_HEIGHT:0] tile_rows; // full number of rows in a tile
reg [MAX_TILE_HEIGHT:0] tile_vstep; // vertical step between rows of tiles
reg [MAX_TILE_WIDTH:0] num_cols_r; // full number of columns to transfer (not minus 1)
wire [MAX_TILE_WIDTH:0] num_cols_m1_w; // full number of columns to transfer minus 1 with extra bit
wire [MAX_TILE_HEIGHT:0] num_rows_m1_w; // full number of columns to transfer minus 1 with extra bit
// end of (LINEAR: DNU)
reg [FRAME_WIDTH_BITS:0] frame_full_width; // (programmed) increment combined row/col when moving to the next line
// frame_width rounded up to max transfer (half page) if frame_width> max transfer/2,
// otherwise (smaller widths) round up to the nearest power of 2
reg [FRAME_WIDTH_BITS:0] window_width; // (programmed) 0- max
reg [FRAME_HEIGHT_BITS:0] window_height; // (programmed) 0- max
reg [FRAME_WIDTH_BITS-1:0] window_x0; // (programmed) window left
reg [FRAME_HEIGHT_BITS-1:0] window_y0; // (programmed) window top
reg [FRAME_WIDTH_BITS-1:0] start_x; // (programmed) normally 0, copied to curr_x on frame_start
reg [FRAME_HEIGHT_BITS-1:0] start_y; // (programmed) normally 0, copied to curr_y on frame_start
// (LINEAR: DNU)
reg xfer_page_done_d; // next cycle after xfer_page_done
reg frame_master_pend; // set frame counter from the master frame number at next master_set
reg set_frame_from_master; // single-clock copy frame counter from the master channel
reg frames_in_sync_r;
// (TILED: DNU)
// reg xfer_done_d; // xfer_done delayed by 1 cycle (also includes xfer_skipped)
// reg [MCNTRL_SCANLINE_DLY_WIDTH-1:0] start_delay; // how much to delay frame start
// reg [MCNTRL_SCANLINE_DLY_WIDTH:0] start_delay_cntr = {MCNTRL_SCANLINE_DLY_WIDTH+1{1'b1}}; // start delay counter
// reg frame_start_late;
// wire set_start_delay_w;
// end of (TILED: DNU)
reg buf_reset_pend; // reset buffer page at next (late)frame sync (compressor should be disabled
// if total number of pages in a frame is not multiple of 4
wire chn_dis_delayed = chn_rst || (!chn_en && !busy_r); // reset if real reset or disabled and frame finished
`ifdef REPORT_FRAME_NUMBER
reg [LAST_FRAME_BITS-1:0] done_frame_number;
`endif
assign frames_in_sync = frames_in_sync_r; // (LINEAR: DNU)
assign frame_number = frame_number_current;
assign set_mode_w = cmd_we && (cmd_a== MCNTRL_TILED_MODE);
assign set_status_w = cmd_we && (cmd_a== MCNTRL_TILED_STATUS_CNTRL);
assign set_start_addr_w = cmd_we && (cmd_a== MCNTRL_TILED_STARTADDR);
assign set_frame_size_w = cmd_we && (cmd_a== MCNTRL_TILED_FRAME_SIZE);
assign set_last_frame_w = cmd_we && (cmd_a== MCNTRL_TILED_FRAME_LAST);
assign set_frame_width_w = cmd_we && (cmd_a== MCNTRL_TILED_FRAME_FULL_WIDTH);
assign set_window_wh_w = cmd_we && (cmd_a== MCNTRL_TILED_WINDOW_WH);
assign set_window_x0y0_w = cmd_we && (cmd_a== MCNTRL_TILED_WINDOW_X0Y0);
assign set_window_start_w = cmd_we && (cmd_a== MCNTRL_TILED_WINDOW_STARTXY);
assign set_tile_whs_w = cmd_we && (cmd_a== MCNTRL_TILED_TILE_WHS); // (LINEAR: DNU)
// assign set_start_delay_w = cmd_we && (cmd_a== MCNTRL_SCANLINE_START_DELAY); // (TILED: DNU)
assign single_frame_w = cmd_we && (cmd_a== MCNTRL_TILED_MODE) && cmd_data[MCONTR_LINTILE_SINGLE];
assign rst_frame_num_w = cmd_we && (cmd_a== MCNTRL_TILED_MODE) && cmd_data[MCONTR_LINTILE_RST_FRAME];
assign set_copy_frame_num_w = cmd_we && (cmd_a== MCNTRL_TILED_MODE) && cmd_data[MCONTR_LINTILE_COPY_FRAME]; // self-clearing bit // (LINEAR: DNU)
assign frame_start_conf = frame_start_r[3]; // frame_number valid ; // (LINEAR: DNU)
// assign frame_run = busy_r; // (TILED: DNU)
// assign frame_set = frame_start_r[3]; // (TILED: DNU)
// Set parameter registers
always @(posedge mclk) begin
if (mrst) mode_reg <= 0;
else if (set_mode_w) mode_reg <= cmd_data[14:0]; // [5:0];
if (mrst) single_frame_r <= 0;
else single_frame_r <= single_frame_w;
if (mrst) rst_frame_num_r <= 0;
else rst_frame_num_r <= {rst_frame_num_r[0], rst_frame_num_w}; // resetting only at specific command
if (mrst) start_range_addr <= 0;
else if (set_start_addr_w) start_range_addr <= cmd_data[NUM_RC_BURST_BITS-1:0];
if (mrst) frame_size <= 0;
else if (set_start_addr_w) frame_size <= 1; // default number of frames - just one
else if (set_frame_size_w) frame_size <= cmd_data[NUM_RC_BURST_BITS-1:0];
if (mrst) last_frame_number <= 0;
else if (set_last_frame_w) last_frame_number <= cmd_data[LAST_FRAME_BITS-1:0];
if (mrst) frame_full_width <= 0;
else if (set_frame_width_w) frame_full_width <= {lsw13_zero,cmd_data[FRAME_WIDTH_BITS-1:0]};
if (mrst) is_last_frame <= 0;
else is_last_frame <= frame_number_cntr >= last_frame_number; // trying to make it safe
`ifdef REPORT_FRAME_NUMBER
if (mrst) done_frame_number <= 0;
else if (frame_done_r) done_frame_number <= frame_number_cntr;
`endif
if (mrst) frame_start_r <= 0;
else frame_start_r <= {frame_start_r[3:0], frame_start_mod & frame_en}; // frame_start // LINEAR: frame_start_mod wire, not reg - compare?
if (!chn_en) frame_en <= 0;
else if (single_frame_r || repeat_frames) frame_en <= 1;
else if (frame_start_mod) frame_en <= 0; // LINEAR: frame_start_late
// (LINEAR: DNU)
if (mrst ||master_set) frame_master_pend <= 0;
else if (set_copy_frame_num_w) frame_master_pend <= 1;
// after channel was disabled frame number reported is incorrect, until updated by master_set
// Without this signal compressor was reading data between the time source frame number was updated and this one.
if (chn_dis_delayed) frames_in_sync_r <= 0; // do not invalidate frames_in_sync_r until busy_r is off
else if (frame_start_r[3]) frames_in_sync_r <= 1; // to match line_unfinished
// end of (LINEAR: DNU)
// will reset buffer page at next frame start
if (mrst ||frame_start_r[0]) buf_reset_pend <= 0;
else if (rst_frame_num_r[0]) buf_reset_pend <= 1;
set_frame_from_master <= master_set && frame_master_pend; // (LINEAR: DNU)
if (mrst) frame_number_cntr <= 0;
else if (rst_frame_num_r[0]) frame_number_cntr <= 0;
else if (set_frame_from_master) frame_number_cntr <= master_frame; // (LINEAR: DNU)
else if (frame_start_r[2]) frame_number_cntr <= is_last_frame?{LAST_FRAME_BITS{1'b0}}:(frame_number_cntr+1);
if (mrst) frame_number_current <= 0;
else if (rst_frame_num_r[0]) frame_number_current <= 0;
else if (frame_start_r[2]) frame_number_current <= frame_number_cntr;
if (mrst) next_frame_start_addr <= start_range_addr; // just to use rst
else if (rst_frame_num_r[1]) next_frame_start_addr <= start_range_addr;
else if (frame_start_r[2]) next_frame_start_addr <= is_last_frame? start_range_addr : (start_addr+frame_size);
if (mrst) start_addr <= start_range_addr; // just to use rst
else if (frame_start_r[0]) start_addr <= next_frame_start_addr;
if (mrst) begin
window_width <= 0;
window_height <= 0;
end else if (set_window_wh_w) begin
window_width <= {lsw13_zero,cmd_data[FRAME_WIDTH_BITS-1:0]};
window_height <= {msw_zero,cmd_data[FRAME_HEIGHT_BITS+15:16]};
end
// (LINEAR: DNU)
if (mrst) begin
tile_cols <= 0;
tile_rows <= 0;
tile_vstep <= 0;
end else if (set_tile_whs_w) begin
tile_cols <= {tile_width_zero, cmd_data[ 0+:MAX_TILE_WIDTH]};
tile_rows <= {tile_height_zero, cmd_data[ 8+:MAX_TILE_HEIGHT]};
tile_vstep <= {tile_vstep_zero, cmd_data[16+:MAX_TILE_HEIGHT]};
end
// end of (LINEAR: DNU)
if (mrst) begin
window_x0 <= 0;
window_y0 <= 0;
end else if (set_window_x0y0_w) begin
window_x0 <= cmd_data[FRAME_WIDTH_BITS-1:0];
window_y0 <=cmd_data[FRAME_HEIGHT_BITS+15:16];
end
if (mrst) begin
start_x <= 0;
start_y <= 0;
end else if (set_window_start_w) begin
start_x <= cmd_data[FRAME_WIDTH_BITS-1:0];
start_y <=cmd_data[FRAME_HEIGHT_BITS+15:16];
end
// (TILED: DNU)
// if (mrst) start_delay <= MCNTRL_SCANLINE_DLY_DEFAULT;
// else if (set_start_delay_w) start_delay <= cmd_data[MCNTRL_SCANLINE_DLY_WIDTH-1:0];
// if (mrst) start_delay_cntr <= {MCNTRL_SCANLINE_DLY_WIDTH+1{1'b1}};
// else if (frame_start) start_delay_cntr <= {1'b0, start_delay};
// else if (!start_delay_cntr[MCNTRL_SCANLINE_DLY_WIDTH]) start_delay_cntr <= start_delay_cntr - 1;
// frame_start_late <= start_delay_cntr == 0;
// end of (TILED: DNU)
end
assign mul_rslt_w= frame_y8_r * frame_full_width_r; // 5 MSBs will be discarded
assign xfer_num128= num_cols_r[MAX_TILE_WIDTH-1:0]; // One bit less! (TODO: for LINEAR)
// assign xfer_start= xfer_start_r[0];
assign xfer_start_lin_rd= xfer_start_lin_rd_r; // NEW
assign xfer_start_lin_wr= xfer_start_lin_wr_r; // NEW
assign xfer_start_rd= xfer_start_rd_r;
assign xfer_start_wr= xfer_start_wr_r;
assign xfer_start32_rd= xfer_start32_rd_r; // (LINEAR: DNU)
assign xfer_start32_wr= xfer_start32_wr_r; // (LINEAR: DNU)
assign calc_valid= par_mod_r[PAR_MOD_LATENCY-1]; // MSB, longest 0
assign xfer_page_rst_wr= xfer_page_rst_r; // MOVED to match LINEAR
assign xfer_page_rst_rd= xfer_page_rst_neg; // MOVED to match LINEAR
assign xfer_partial= xfer_limited_by_mem_page_r; // MOVED to match LINEAR
assign frame_done= frame_done_r;
assign frame_finished= frame_finished_r;
// Was, now using from linear - faster/equivalent
// assign pre_want= !chn_rst && busy_r && !want_r && !xfer_start_r[0] && calc_valid && !last_block && !suspend && !(|frame_start_r) && !aborting_r;
// LINEAR:
assign pre_want= pre_want_r1 && !want_r && !xfer_start_r[0] && !last_block && !suspend && !aborting_r;
assign last_in_row_w=(row_left=={{(FRAME_WIDTH_BITS-MAX_TILE_WIDTH){1'b0}},num_cols_r}); // what if it crosses page? OK, num_cols_r & row_left know that
// TODO: LINEAR: use num_cols_r instead of xfer_num128_r
// tiles must completely fit window
// all window should be covered (tiles may extend):
assign last_row_w= next_y >= window_height; // LINEAR: "++" instead of ">="
//window_m_tile_height
assign xfer_want= want_r;
assign xfer_need= need_r;
assign xfer_bank= bank_reg[2*3 +: 3]; // TODO: just a single reg layer
assign xfer_row= row_col_r[NUM_RC_BURST_BITS-1:COLADDR_NUMBER-3] ; // memory row
assign xfer_col= row_col_r[COLADDR_NUMBER-4:0]; // start memory column in 8-bursts
assign line_unfinished = line_unfinished_r;
assign chn_en = mode_reg[MCONTR_LINTILE_NRESET] & mode_reg[MCONTR_LINTILE_EN]; // enable requests by channel (continue ones in progress)
assign chn_rst = ~mode_reg[MCONTR_LINTILE_NRESET]; // resets command, including fifo;
assign cmd_wrmem = mode_reg[MCONTR_LINTILE_WRITE];// 0: read from memory, 1:write to memory
assign cmd_extra_pages = mode_reg[MCONTR_LINTILE_EXTRAPG+:MCONTR_LINTILE_EXTRAPG_BITS]; // external module needs more than 1 page
assign keep_open= mode_reg[MCONTR_LINTILE_KEEP_OPEN]; // keep banks open (will be used only if number of rows <= 8
assign byte32= mode_reg[MCONTR_LINTILE_BYTE32]; // use 32-byte wide columns in each tile (false - 16-byte)
assign linear_mode = mode_reg[MCONTR_LINTILE_BYTE32 ]; // use linear mode instead of the tiled
assign repeat_frames= mode_reg[MCONTR_LINTILE_REPEAT];
assign disable_need = mode_reg[MCONTR_LINTILE_DIS_NEED];
// assign skip_too_late = mode_reg[MCONTR_LINTILE_SKIP_LATE]; // from LINEAR
assign linear_mode = mode_reg[MCONTR_LINTILE_LINEAR]; // NEW
assign abort_en = mode_reg[MCONTR_LINTILE_ABORT_LATE];
`ifdef DEBUG_MCNTRL_TILED_EXTRA_STATUS
assign status_data= {frames_in_sync, suspend, last_row_w, last_in_row,line_unfinished[7:0], frame_finished_r, busy_r};
`else
`ifdef REPORT_FRAME_NUMBER
assign status_data= {done_frame_number, frame_finished_r, busy_r}; // TODO: Add second bit?
`else
assign status_data= {frame_finished_r, busy_r}; // TODO: Add second bit?
`endif
`endif
assign pgm_param_w= cmd_we;
// LINEAR: matched
assign rowcol_inc= frame_full_width;
assign num_cols_m1_w= num_cols_r-1;
assign num_rows_m1_w= tile_rows-1; // now number of rows == tile height
assign num_cols_m1= num_cols_m1_w[MAX_TILE_WIDTH-1:0]; // remove MSB
assign num_rows_m1= num_rows_m1_w[MAX_TILE_HEIGHT-1:0]; // remove MSB
assign remainder_tile_width = {EXTRA_BITS,lim_by_tile_width} - mem_page_left;
integer i;
localparam [COLADDR_NUMBER-3-MAX_TILE_WIDTH-1:0] EXTRA_BITS=0;
wire xfer_limited_by_mem_page;
reg xfer_limited_by_mem_page_r;
assign xfer_limited_by_mem_page= keep_open && (mem_page_left < {EXTRA_BITS,lim_by_tile_width}); // if not keep_open - no need to break
//LINEAR - start match
always @(posedge mclk) begin // TODO: Match latencies (is it needed?) Reduce consumption by CE?
// cycle 1
if (recalc_r[0]) begin
frame_x <= curr_x + window_x0;
frame_y <= curr_y + window_y0;
next_y <= curr_y + (linear_mode? 1 : tile_vstep); // LINEAR: next_y <= curr_y + 1;
row_left <= window_width - curr_x; // 14 bits - 13 bits
end
// registers to be absorbed in DSP block
frame_y8_r <= frame_y[FRAME_HEIGHT_BITS-1:3]; // lat=2 // if (recalc_r[2]) begin
frame_full_width_r <= frame_full_width; //(cycle 2) // if (recalc_r[2]) begin
start_addr_r <= start_addr; // // if (recalc_r[2]) begin
mul_rslt <= mul_rslt_w[MPY_WIDTH-1:0]; // frame_y8_r * frame_width_r; // 7 bits will be discarded lat=3; if (recalc_r[3]) begin
line_start_addr <= start_addr_r+mul_rslt; // lat=4 if (recalc_r[4]) begin
// TODO: Verify MPY/register timing above
if (recalc_r[5]) begin // cycle 6
row_col_r <= line_start_addr+frame_x;
line_start_page_left <= - line_start_addr[COLADDR_NUMBER-4:0]; // 7 bits
end
bank_reg[0 +: 3] <= frame_y[2:0]; //TODO: is it needed - a pipeline for the bank? - remove!
for (i=0; i<2; i = i+1)
bank_reg[(i+1)*3 +: 3] <= bank_reg[i*3 +: 3];
if (recalc_r[6]) begin // cycle 7
mem_page_left <= {1'b1,line_start_page_left} - frame_x[COLADDR_NUMBER-4:0];
/*
lim_by_tile_width <= (|row_left[FRAME_WIDTH_BITS:MAX_TILE_WIDTH] || (row_left[MAX_TILE_WIDTH:0] >= tile_cols))?
tile_cols:
row_left[MAX_TILE_WIDTH:0]; // 7 bits, max 'h40
lim_by_xfer <= (|row_left[FRAME_WIDTH_BITS:NUM_XFER_BITS])? // TODO: used in LINEAR
(1<<NUM_XFER_BITS):
row_left[NUM_XFER_BITS:0]; // 7 bits, max 'h40
*/
lim_by_tile_width <= (|row_left[FRAME_WIDTH_BITS:MAX_TILE_WIDTH] || (!linear_mode && (row_left[MAX_TILE_WIDTH:0] >= tile_cols)))?
(linear_mode ? {(MAX_TILE_WIDTH + 1){1'b1}} : tile_cols):
row_left[MAX_TILE_WIDTH:0]; // 7 bits, max 'h40
end
//LINEAR - start match
if (recalc_r[7]) begin // cycle 8
xfer_limited_by_mem_page_r <= xfer_limited_by_mem_page && !continued_tile; // LINEAR continued_xfer -> continued_tile
/*
num_cols_r<= continued_tile? // LINEAR xfer_num128_r<= continued_xfer?
{EXTRA_BITS,leftover_cols}: // LINEAR {EXTRA_BITS,leftover}:
(xfer_limited_by_mem_page?
mem_page_left[MAX_TILE_WIDTH:0]: // LINEAR: mem_page_left[NUM_XFER_BITS:0]:
lim_by_tile_width[MAX_TILE_WIDTH:0]); // LINEAR lim_by_xfer[NUM_XFER_BITS:0]);
leftover_cols <= remainder_tile_width[MAX_TILE_WIDTH-1:0]; // TODO: !!! LINEAR - see next line
// LINEAR: if (!continued_xfer) leftover <= remainder_in_xfer[NUM_XFER_BITS-1:0]; // {EXTRA_BITS, lim_by_xfer}-mem_page_left;
*/
num_cols_r<= continued_tile? // LINEAR xfer_num128_r<= continued_xfer?
{EXTRA_BITS,leftover_cols}: // LINEAR : using leftover instead of leftover_cols {EXTRA_BITS,leftover}:
(xfer_limited_by_mem_page?
mem_page_left[MAX_TILE_WIDTH:0]: // LINEAR: mem_page_left[NUM_XFER_BITS:0]:
lim_by_tile_width[MAX_TILE_WIDTH:0]); // LINEAR lim_by_xfer[NUM_XFER_BITS:0]);
if (!linear_mode || continued_tile) leftover_cols <= remainder_tile_width[MAX_TILE_WIDTH-1:0];
end
if (recalc_r[8]) begin // cycle 9
last_in_row <= last_in_row_w;
end
// LINEAR: matched
end
// now have row start address, bank and row_left ;
// calculate number to read (min of row_left, maximal xfer and what is left in the DDR3 page
wire start_not_partial= xfer_start_r[0] && !xfer_limited_by_mem_page_r;
always @(posedge mclk) begin
// acceletaring pre_want - copied from LINEAR (faster, equivalent), start matching
pre_want_r1 <= !chn_rst && !frame_done_r && busy_r && par_mod_r[PAR_MOD_LATENCY-2] && !(|frame_start_r[4:1]);
if (mrst) par_mod_r<=0;
else if (pgm_param_w ||
xfer_start_r[0] ||
chn_rst ||
frame_start_r[0]) par_mod_r<=0;
else par_mod_r <= {par_mod_r[PAR_MOD_LATENCY-2:0], 1'b1};
if (mrst) chn_rst_d <= 0;
else chn_rst_d <= chn_rst;
if (mrst) recalc_r<=0;
else if (chn_rst) recalc_r<=0;
else recalc_r <= {recalc_r[PAR_MOD_LATENCY-2:0],
((xfer_start_r[0] | frame_start_r[0]) & ~chn_rst) | pgm_param_w | (chn_rst_d & ~chn_rst)};
if (mrst) busy_r <= 0;
else if (chn_rst) busy_r <= 0;
else if (frame_start_r[0]) busy_r <= 1;
else if (frame_done_r) busy_r <= 0;
if (mrst) xfer_page_done_d <= 0;
else xfer_page_done_d <= xfer_page_done; // LINEAR: xfer_done_skipped;
if (mrst) xfer_start_r <= 0;
else xfer_start_r <= {xfer_start_r[1:0],xfer_grant && !chn_rst}; // LINEAR uses skip_run
// LINEAR matched
// TILED and TILED_LIN only:
if (mrst) xfer_start_rd_r <= 0;
else xfer_start_rd_r <= xfer_grant && !chn_rst && !cmd_wrmem && !byte32;
if (mrst) xfer_start_wr_r <= 0;
else xfer_start_wr_r <= xfer_grant && !chn_rst && cmd_wrmem && !byte32;
if (mrst) xfer_start32_rd_r <= 0;
else xfer_start32_rd_r <= xfer_grant && !chn_rst && !cmd_wrmem && byte32;
if (mrst) xfer_start32_wr_r <= 0;
else xfer_start32_wr_r <= xfer_grant && !chn_rst && cmd_wrmem && byte32;
if (mrst) xfer_start_lin_rd_r <= 0;
else xfer_start_lin_rd_r <= xfer_grant && !chn_rst && !cmd_wrmem && linear_mode;
if (mrst) xfer_start_lin_wr_r <= 0;
else xfer_start_lin_wr_r <= xfer_grant && !chn_rst && cmd_wrmem && linear_mode;
// end TILED
if (mrst) continued_tile <= 1'b0; // LINEAR: replace continued_xfer with continued_tile
else if (chn_rst) continued_tile <= 1'b0;
else if (frame_start_r[0]) continued_tile <= 1'b0;
else if (xfer_start_r[0]) continued_tile <= xfer_limited_by_mem_page_r; // only set after actual start if it was partial, not after parameter change
// LINEAR matching start
if (mrst || disable_need) need_r <= 0;
else if (chn_rst || xfer_grant) need_r <= 0; // LINEAR else if (chn_rst || xfer_grant || start_skip_r) need_r <= 0;
else if ((pre_want || want_r) && (page_cntr>=3)) need_r <= 1; // may raise need if want was already set
if (mrst) want_r <= 0;
else if (chn_rst || xfer_grant) want_r <= 0; // LINEAR else if (chn_rst || xfer_grant || start_skip_r) want_r <= 0;
else if (pre_want && (page_cntr>{1'b0,cmd_extra_pages})) want_r <= 1;
want_d <= want_r;
if (mrst) page_cntr <= 0;
// else if (frame_start_r[0]) page_cntr <= cmd_wrmem?0:4; // reset here, but compressor is not// LINEAR: not commented out
else if (xfer_page_rst_pos) page_cntr <= cmd_wrmem?0:4; // reset here, but compressor is not
else if ( start_not_partial && !next_page) page_cntr <= page_cntr - 1;
else if (!start_not_partial && next_page) page_cntr <= page_cntr + 1;
if (mrst) xfer_page_rst_r <= 1;
else xfer_page_rst_r <= chn_rst || (buf_reset_pend && (MCNTRL_TILED_FRAME_PAGE_RESET ? (frame_start_r[0] & cmd_wrmem):1'b0));
if (mrst) xfer_page_rst_pos <= 1;
else xfer_page_rst_pos <= chn_rst || (buf_reset_pend && (MCNTRL_TILED_FRAME_PAGE_RESET ? (frame_start_r[0] & ~cmd_wrmem):1'b0));
// increment x,y (two cycles)
// TODO: LINEAR: use num_cols_r instead of xfer_num128_r
if (mrst) curr_x <= 0;
else if (chn_rst || frame_start_r[0]) curr_x <= start_x;
else if (xfer_start_r[0]) curr_x <= last_in_row?0: curr_x + num_cols_r; // LINEAR: xfer_num128_r;
if (mrst) curr_y <= 0;
else if (chn_rst || frame_start_r[0]) curr_y <= start_y;
else if (xfer_start_r[0] && last_in_row) curr_y <= next_y[FRAME_HEIGHT_BITS-1:0];
if (mrst) last_block <= 0;
else if (chn_rst || !busy_r) last_block <= 0;
else if (xfer_start_r[0]) last_block <= last_row_w && last_in_row_w;
// start_not_partial is not generated when partial (first of 2, caused by a tile crossing memory page) transfer is requested
// here we need to cout all requests - partial or not
if (mrst) pending_xfers <= 0;
else if (chn_rst || !busy_r) pending_xfers <= 0;
else if ( xfer_start_r[0] && !xfer_page_done) pending_xfers <= pending_xfers + 1; // LINEAR use xfer_done_skipped
else if (!xfer_start_r[0] && xfer_page_done) pending_xfers <= pending_xfers - 1; // page done is not generated on partial (first) pages // LINEAR use xfer_done_skipped
if (mrst) frame_done_r <= 0;
else frame_done_r <= busy_r && (pending_xfers==0) &&
((last_block && xfer_page_done_d) || (aborting_r && !want_r && !want_d)); // LINEAR use xfer_done_d instead of xfer_page_done_d (same)
if (!busy_r) aborting_r <= 0;
else if (abort_en && busy_r && frame_start) aborting_r <= 1;
aborting_d <= aborting_r; // (LINEAR: DNU)
frame_start_mod <= (frame_start && !busy_r) || (aborting_d && !aborting_r); // LINEAR: wire with the same name wire
// turns and stays on (used in status)
if (mrst) frame_finished_r <= 0;
else if (chn_rst || frame_start_r[0]) frame_finished_r <= 0;
else if (frame_done_r) frame_finished_r <= 1;
//TODO: ALready modified to include linear mode
// TILED: if (recalc_r[0]) line_unfinished_relw_r <= curr_y + (cmd_wrmem ? 0: tile_rows);
// LINEAR: if (recalc_r[0]) line_unfinished_relw_r <= curr_y + (cmd_wrmem ? 0: 1);
if (recalc_r[0]) line_unfinished_relw_r <= curr_y + (cmd_wrmem ? 0: (linear_mode? 1: tile_rows));
if (mrst || (frame_start_mod || chn_dis_delayed)) line_unfinished_r <= {FRAME_HEIGHT_BITS{~cmd_wrmem}}; // lowest/highest value until valid
else if (recalc_r[2] && busy_r) line_unfinished_r <= line_unfinished_relw_r + window_y0;
// LINEAR matching end
end
always @ (negedge mclk) begin
xfer_page_rst_neg <= xfer_page_rst_pos;
end
cmd_deser #(
.ADDR (MCNTRL_TILED_ADDR),
.ADDR_MASK (MCNTRL_TILED_MASK),
.NUM_CYCLES (6),
.ADDR_WIDTH (4),
.DATA_WIDTH (32)
) cmd_deser_32bit_i (
.rst (1'b0), // input
.clk (mclk), // input
.srst (mrst), // input
.ad (cmd_ad), // input[7:0]
.stb (cmd_stb), // input
.addr (cmd_a), // output[15:0]
.data (cmd_data), // output[31:0]
.we (cmd_we) // output
);
status_generate #(
.STATUS_REG_ADDR (MCNTRL_TILED_STATUS_REG_ADDR),
`ifdef DEBUG_MCNTRL_TILED_EXTRA_STATUS
.PAYLOAD_BITS (14)
`else
`ifdef REPORT_FRAME_NUMBER
.PAYLOAD_BITS (2 + LAST_FRAME_BITS)
`else
.PAYLOAD_BITS (2)
`endif
`endif
) status_generate_i (
.rst (1'b0), // input
.clk (mclk), // input
.srst (mrst), // input
.we (set_status_w), // input
.wd (cmd_data[7:0]), // input[7:0]
.status (status_data), // input[25:0]
.ad (status_ad), // output[7:0]
.rq (status_rq), // output
.start (status_start) // input
);
endmodule
......@@ -1317,6 +1317,7 @@ assign axi_grst = axi_rst_pre;
.MCONTR_LINTILE_EXTRAPG_BITS (MCONTR_LINTILE_EXTRAPG_BITS),
.MCONTR_LINTILE_KEEP_OPEN (MCONTR_LINTILE_KEEP_OPEN),
.MCONTR_LINTILE_BYTE32 (MCONTR_LINTILE_BYTE32),
.MCONTR_LINTILE_LINEAR (MCONTR_LINTILE_LINEAR), // Use linear mode instead of tiled
.MCONTR_LINTILE_RST_FRAME (MCONTR_LINTILE_RST_FRAME),
.MCONTR_LINTILE_SINGLE (MCONTR_LINTILE_SINGLE),
.MCONTR_LINTILE_REPEAT (MCONTR_LINTILE_REPEAT),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment