Commit 0adb43af authored by Andrey Filippov's avatar Andrey Filippov

Added more code: Farme level scanline memory interface with window,...

Added more code: Farme level scanline memory interface with window, multiplexor for multiple channels sharing the same linear R/W command encoder
parent f175bfdf
......@@ -6,18 +6,22 @@
// chn 0 is read from memory
`define def_enable_mem_chn0
`define def_read_mem_chn0
`undef def_scanline_chn0
// chn 1 is write to memory
`define def_enable_mem_chn1
`undef def_read_mem_chn1
`undef def_scanline_chn1
// chn 2 is read from memory
`define def_enable_mem_chn2
`define def_read_mem_chn2
`define def_scanline_chn2
// chn 3 is write to memory
`define def_enable_mem_chn3
`undef def_read_mem_chn3
`define def_scanline_chn3
// chn 4 is disabled
`undef def_enable_mem_chn4
......
......@@ -57,7 +57,7 @@
parameter MCONTR_TOP_16BIT_REFRESH_ADDRESS= 'h2, // 10 bits refresh address in the sequencer (PL) memory
parameter MCONTR_TOP_16BIT_STATUS_CNTRL= 'h3, // 8 bits - write to status control (and debug?)
0x1100..11ff - 16-bit per-channel memory control
0x1100..11ff - 32-bit per-channel memory control
0x1100..110f - control of memory channels 0,1 - PS-controlled sequences
parameter MCNTRL_PS_ADDR= 'h100,
parameter MCNTRL_PS_MASK= 'h3e0, // both channels 0 and 1
......@@ -69,6 +69,30 @@
parameter MCNTRL_PS_STATUS_CNTRL= 'h2,
============= Add the following (addresses will vary for individual channels)
parameter ADDRESS_NUMBER= 15,
parameter COLADDR_NUMBER= 10,
parameter NUM_XFER_BITS= 6, // number of bits to specify transfer length
parameter FRAME_WIDTH_BITS= 13, // Maximal frame width - 8-word (16 bytes) bursts
parameter FRAME_HEIGHT_BITS= 16, // Maximal frame height
parameter MCNTRL_SCANLINE_ADDR= 'h120,
parameter MCNTRL_SCANLINE_MASK= 'h3f0, // both channels 0 and 1
parameter MCNTRL_SCANLINE_MODE= 'h0, // set mode register: {extra_pages[1:0],write_mode,enable,!reset}
parameter MCNTRL_SCANLINE_STATUS_CNTRL= 'h1, // control status reporting
parameter MCNTRL_SCANLINE_STARTADDR= 'h2, // 22-bit frame start address (3 CA LSBs==0. BA==0)
parameter MCNTRL_SCANLINE_FRAME_FULL_WIDTH='h3, // Padded line length (8-row increment), in 8-bursts (16 bytes)
parameter MCNTRL_SCANLINE_WINDOW_WH= 'h4, // low word - 13-bit window width (0->'n4000), high word - 16-bit frame height (0->'h10000)
parameter MCNTRL_SCANLINE_WINDOW_X0Y0= 'h5, // low word - 13-bit window left, high word - 16-bit window top
parameter MCNTRL_SCANLINE_WINDOW_STARTXY= 'h6, // 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 (fro debugging)?
parameter MCNTRL_SCANLINE_STATUS_REG_ADDR= 'h4,
// Status read address
parameter STATUS_ADDR = 'h1400, // AXI write address of status read registers
parameter STATUS_ADDR_MASK = 'h1400, // AXI write address of status registers
......
/*******************************************************************************
* Module: cmd_encod_linear_mux
* Date:2015-01-31
* Author: andrey
* Description: Multiplex parameters from multiple channels sharing the same
* linear command encoder (cmd_encod_linear_rd or cmd_encod_linear_wr)
* Latency 1 clcok cycle
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* cmd_encod_linear_mux.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.
*
* cmd_encod_linear_mux.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/> .
*******************************************************************************/
`timescale 1ns/1ps
module cmd_encod_linear_mux#(
parameter ADDRESS_NUMBER= 15,
parameter COLADDR_NUMBER= 10
) (
input clk,
`ifdef def_scanline_chn0
input [2:0] bank0, // bank address
input [ADDRESS_NUMBER-1:0] row0, // memory row
input [COLADDR_NUMBER-4:0] start_col0, // start memory column in 8-bursts
input [5:0] num128_0, // number of 128-bit words to transfer (8*16 bits) - full bursts of 8 ( 0 - maximal length, 64)
input start0, // start generating commands
`endif
`ifdef def_scanline_chn1
input [2:0] bank1, // bank address
input [ADDRESS_NUMBER-1:0] row1, // memory row
input [COLADDR_NUMBER-4:0] start_col1, // start memory column in 8-bursts
input [5:0] num128_1, // number of 128-bit words to transfer (8*16 bits) - full bursts of 8 ( 0 - maximal length, 64)
input start1, // start generating commands
`endif
`ifdef def_scanline_chn2
input [2:0] bank2, // bank address
input [ADDRESS_NUMBER-1:0] row2, // memory row
input [COLADDR_NUMBER-4:0] start_col2, // start memory column in 8-bursts
input [5:0] num128_2, // number of 128-bit words to transfer (8*16 bits) - full bursts of 8 ( 0 - maximal length, 64)
input start2, // start generating commands
`endif
`ifdef def_scanline_chn3
input [2:0] bank3, // bank address
input [ADDRESS_NUMBER-1:0] row3, // memory row
input [COLADDR_NUMBER-4:0] start_col3, // start memory column in 8-bursts
input [5:0] num128_3, // number of 128-bit words to transfer (8*16 bits) - full bursts of 8 ( 0 - maximal length, 64)
input start3, // start generating commands
`endif
`ifdef def_scanline_chn4
input [2:0] bank4, // bank address
input [ADDRESS_NUMBER-1:0] row4, // memory row
input [COLADDR_NUMBER-4:0] start_col4, // start memory column in 8-bursts
input [5:0] num128_4, // number of 128-bit words to transfer (8*16 bits) - full bursts of 8 ( 0 - maximal length, 64)
input start4, // start generating commands
`endif
`ifdef def_scanline_chn5
input [2:0] bank5, // bank address
input [ADDRESS_NUMBER-1:0] row5, // memory row
input [COLADDR_NUMBER-4:0] start_col5, // start memory column in 8-bursts
input [5:0] num128_5, // number of 128-bit words to transfer (8*16 bits) - full bursts of 8 ( 0 - maximal length, 64)
input start5, // start generating commands
`endif
`ifdef def_scanline_chn6
input [2:0] bank6, // bank address
input [ADDRESS_NUMBER-1:0] row6, // memory row
input [COLADDR_NUMBER-4:0] start_col6, // start memory column in 8-bursts
input [5:0] num128_6, // number of 128-bit words to transfer (8*16 bits) - full bursts of 8 ( 0 - maximal length, 64)
input start6, // start generating commands
`endif
`ifdef def_scanline_chn7
input [2:0] bank7, // bank address
input [ADDRESS_NUMBER-1:0] row7, // memory row
input [COLADDR_NUMBER-4:0] start_col7, // start memory column in 8-bursts
input [5:0] num128_7, // number of 128-bit words to transfer (8*16 bits) - full bursts of 8 ( 0 - maximal length, 64)
input start7, // start generating commands
`endif
`ifdef def_scanline_chn8
input [2:0] bank8, // bank address
input [ADDRESS_NUMBER-1:0] row8, // memory row
input [COLADDR_NUMBER-4:0] start_col8, // start memory column in 8-bursts
input [5:0] num128_8, // number of 128-bit words to transfer (8*16 bits) - full bursts of 8 ( 0 - maximal length, 64)
input start8, // start generating commands
`endif
`ifdef def_scanline_chn9
input [2:0] bank9, // bank address
input [ADDRESS_NUMBER-1:0] row9, // memory row
input [COLADDR_NUMBER-4:0] start_col9, // start memory column in 8-bursts
input [5:0] num128_9, // number of 128-bit words to transfer (8*16 bits) - full bursts of 8 ( 0 - maximal length, 64)
input start9, // start generating commands
`endif
`ifdef def_scanline_chn10
input [2:0] bank10, // bank address
input [ADDRESS_NUMBER-1:0] row10, // memory row
input [COLADDR_NUMBER-4:0] start_col10, // start memory column in 8-bursts
input [5:0] num128_10, // number of 128-bit words to transfer (8*16 bits) - full bursts of 8 ( 0 - maximal length, 64)
input start10, // start generating commands
`endif
`ifdef def_scanline_chn11
input [2:0] bank11, // bank address
input [ADDRESS_NUMBER-1:0] row11, // memory row
input [COLADDR_NUMBER-4:0] start_col11, // start memory column in 8-bursts
input [5:0] num128_11, // number of 128-bit words to transfer (8*16 bits) - full bursts of 8 ( 0 - maximal length, 64)
input start11, // start generating commands
`endif
`ifdef def_scanline_chn12
input [2:0] bank12, // bank address
input [ADDRESS_NUMBER-1:0] row12, // memory row
input [COLADDR_NUMBER-4:0] start_col12, // start memory column in 8-bursts
input [5:0] num128_12, // number of 128-bit words to transfer (8*16 bits) - full bursts of 8 ( 0 - maximal length, 64)
input start12, // start generating commands
`endif
`ifdef def_scanline_chn13
input [2:0] bank13, // bank address
input [ADDRESS_NUMBER-1:0] row13, // memory row
input [COLADDR_NUMBER-4:0] start_col13, // start memory column in 8-bursts
input [5:0] num128_13, // number of 128-bit words to transfer (8*16 bits) - full bursts of 8 ( 0 - maximal length, 64)
input start13, // start generating commands
`endif
`ifdef def_scanline_chn14
input [2:0] bank14, // bank address
input [ADDRESS_NUMBER-1:0] row14, // memory row
input [COLADDR_NUMBER-4:0] start_col14, // start memory column in 8-bursts
input [5:0] num128_14, // number of 128-bit words to transfer (8*16 bits) - full bursts of 8 ( 0 - maximal length, 64)
input start14, // start generating commands
`endif
`ifdef def_scanline_chn15
input [2:0] bank15, // bank address
input [ADDRESS_NUMBER-1:0] row15, // memory row
input [COLADDR_NUMBER-4:0] start_col15, // start memory column in 8-bursts
input [5:0] num128_15, // number of 128-bit words to transfer (8*16 bits) - full bursts of 8 ( 0 - maximal length, 64)
input start15, // start generating commands
`endif
output [2:0] bank, // bank address
output [ADDRESS_NUMBER-1:0] row, // memory row
output [COLADDR_NUMBER-4:0] start_col, // start memory column in 8-bursts
output [5:0] num128, // number of 128-bit words to transfer (8*16 bits) - full bursts of 8 ( 0 - maximal length, 64)
output start // start generating commands
);
reg [2:0] bank_r; // bank address
reg [ADDRESS_NUMBER-1:0] row_r; // memory row
reg [COLADDR_NUMBER-4:0] start_col_r;// start memory column in 8-bursts
reg [5:0] num128_r; // number of 128-bit words to transfer (8*16 bits) - full bursts of 8 ( 0 - maximal length, 64)
reg start_r; // start generating commands
wire [2:0] bank_w; // bank address
wire [ADDRESS_NUMBER-1:0] row_w; // memory row
wire [COLADDR_NUMBER-4:0] start_col_w;// start memory column in 8-bursts
wire [5:0] num128_w; // number of 128-bit words to transfer (8*16 bits) - full bursts of 8 ( 0 - maximal length, 64)
wire start_w; // start generating commands
localparam PAR_WIDTH=3+ADDRESS_NUMBER+COLADDR_NUMBER-3+6+1;
localparam [PAR_WIDTH-1:0] PAR_DEFAULT=0;
assign bank = bank_r;
assign row = row_r;
assign start_col = start_col_r;
assign num128 = num128_r;
assign start = start_r;
assign {bank_w, row_w, start_col_w, num128_w, start_w} = 0
`ifdef def_scanline_chn0
| (start0?{bank0, row0, start_col0, num128_0,1'b1}:PAR_DEFAULT)
`endif
`ifdef def_scanline_chn1
| (start1?{bank1, row1, start_col1, num128_1,1'b1}:PAR_DEFAULT)
`endif
`ifdef def_scanline_chn2
| (start2?{bank2, row2, start_col2, num128_2,1'b1}:PAR_DEFAULT)
`endif
`ifdef def_scanline_chn3
| (start3?{bank3, row3, start_col3, num128_3,1'b1}:PAR_DEFAULT)
`endif
`ifdef def_scanline_chn4
| (start4?{bank4, row4, start_col4, num128_4,1'b1}:PAR_DEFAULT)
`endif
`ifdef def_scanline_chn5
| (start5?{bank5, row5, start_col5, num128_5,1'b1}:PAR_DEFAULT)
`endif
`ifdef def_scanline_chn6
| (start6?{bank6, row6, start_col6, num128_6,1'b1}:PAR_DEFAULT)
`endif
`ifdef def_scanline_chn7
| (start7?{bank7, row7, start_col7, num128_7,1'b1}:PAR_DEFAULT)
`endif
`ifdef def_scanline_chn8
| (start8?{bank8, row8, start_col8, num128_8,1'b1}:PAR_DEFAULT)
`endif
`ifdef def_scanline_chn9
| (start9?{bank9, row9, start_col9, num128_9,1'b1}:PAR_DEFAULT)
`endif
`ifdef def_scanline_chn10
| (start10?{bank10, row10, start_col10, num128_10,1'b1}:PAR_DEFAULT)
`endif
`ifdef def_scanline_chn11
| (start11?{bank11, row11, start_col11, num128_11,1'b1}:PAR_DEFAULT)
`endif
`ifdef def_scanline_chn12
| (start12?{bank12, row12, start_col12, num128_12,1'b1}:PAR_DEFAULT)
`endif
`ifdef def_scanline_chn13
| (start13?{bank13, row13, start_col13, num128_13,1'b1}:PAR_DEFAULT)
`endif
`ifdef def_scanline_chn14
| (start14?{bank14, row14, start_col14, num128_14,1'b1}:PAR_DEFAULT)
`endif
`ifdef def_scanline_chn15
| (start15?{bank15, row15, start_col15, num128_15,1'b1}:PAR_DEFAULT)
`endif
;
always @ (posedge clk) begin
if (start_w) begin
bank_r <= bank_w;
row_r <= row_w;
start_col_r <= start_col_w;
num128_r <= num128_w;
end
start_r <= start_w;
end
endmodule
......@@ -45,7 +45,7 @@ module cmd_encod_linear_rd #(
input [2:0] bank_in, // bank address
input [ADDRESS_NUMBER-1:0] row_in, // memory row
input [COLADDR_NUMBER-4:0] start_col, // start memory column in 8-bursts
input [5:0] num128_in, // number of 128-bit words to transfer (8*16 bits) - full burst of 8
input [5:0] num128_in, // number of 128-bit words to transfer (8*16 bits) - full bursts of 8 ( 0 - maximal length, 64)
input start, // start generating commands
output reg [31:0] enc_cmd, // encoded commnad
output reg enc_wr, // write encoded command
......
/*******************************************************************************
* Module: mcntrl_linear_rw
* Date:2015-01-29
* Author: andrey
* Description: Organize paged R/W from DDR3 memory in scan-line order
* with window support
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* mcntrl_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_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/> .
*******************************************************************************/
`timescale 1ns/1ps
module mcntrl_linear_rw #(
parameter ADDRESS_NUMBER= 15,
parameter COLADDR_NUMBER= 10,
parameter NUM_XFER_BITS= 6, // number of bits to specify transfer length
parameter FRAME_WIDTH_BITS= 13, // Maximal frame width - 8-word (16 bytes) bursts
parameter FRAME_HEIGHT_BITS= 16, // Maximal frame height
parameter MCNTRL_SCANLINE_ADDR= 'h120,
parameter MCNTRL_SCANLINE_MASK= 'h3f0, // both channels 0 and 1
parameter MCNTRL_SCANLINE_MODE= 'h0, // set mode register: {extra_pages[1:0],write_mode,enable,!reset}
parameter MCNTRL_SCANLINE_STATUS_CNTRL= 'h1, // control status reporting
parameter MCNTRL_SCANLINE_STARTADDR= 'h2, // 22-bit frame start address (3 CA LSBs==0. BA==0)
parameter MCNTRL_SCANLINE_FRAME_FULL_WIDTH='h3, // Padded line length (8-row increment), in 8-bursts (16 bytes)
parameter MCNTRL_SCANLINE_WINDOW_WH= 'h4, // low word - 13-bit window width (0->'n4000), high word - 16-bit frame height (0->'h10000)
parameter MCNTRL_SCANLINE_WINDOW_X0Y0= 'h5, // low word - 13-bit window left, high word - 16-bit window top
parameter MCNTRL_SCANLINE_WINDOW_STARTXY= 'h6, // 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 (fro debugging)?
parameter MCNTRL_SCANLINE_STATUS_REG_ADDR= 'h4,
parameter MCNTRL_SCANLINE_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
)(
input rst,
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)
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
// optional I/O for channel synchronization
output [FRAME_HEIGHT_BITS-1:0] line_unfinished, // number of the current (ufinished ) line, REALATIVE TO FRAME, NOT WINDOW?.
input suspend, // suspend transfers (from external line number comparator)
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
output xfer_start, // initiate a transfer (next cycle after xfer_grant)
output [2:0] xfer_bank, // 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 [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)
input xfer_done, // transfer to/from the buffer finished
output [1:0] xfer_page // page number for transfer (goes to channel buffer memory-side adderss)
);
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= 7; // 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
// calculating full width from the frame width
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 [2:0] bank_reg [2:0];
wire [FRAME_WIDTH_BITS+FRAME_HEIGHT_BITS-3:0] mul_rslt_w;
// wire [2:0] cur_bank;
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 [NUM_XFER_BITS:0] lim_by_xfer; // number of bursts left limited by the longest transfer (currently 64)
reg [NUM_XFER_BITS:0] xfer_num128_r; // number of 128-bit words to transfer (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;
reg [PAR_MOD_LATENCY-1:0] par_mod_r;
wire calc_valid; // calculated registers have valid values
wire chn_en; // enable requests by channle (continue ones in progress)
wire chn_rst; // resets command, including fifo;
reg [1:0] xfer_page_r;
reg [2:0] page_cntr;
wire cmd_wrmem; // 0: read from memory, 1:write to memory
wire [1:0] cmd_extra_pages; // external module needs more than 1 page
reg busy_r;
reg want_r;
reg need_r;
reg frame_done_r;
wire last_in_row_w;
wire last_row_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;
reg [FRAME_HEIGHT_BITS-1:0] line_unfinished_r [1:0];
wire pre_want;
wire [1:0] status_data;
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_width_w;
wire set_window_wh_w;
wire set_window_x0y0_w;
wire set_window_start_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 msw13_zero=!cmd_data[FRAME_WIDTH_BITS+15:16]; // MSW 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
reg [4:0] mode_reg;//mode register: {extra_pages[1:0],write_mode,enable,!reset}
reg [NUM_RC_BURST_BITS-1:0] start_addr; // (programmed) Frame start (in {row,col8} in burst8, bank ==0
// reg [FRAME_WIDTH_BITS:0] frame_width; // (programmed) 0- max
//FIXME!!!!!!!!
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
assign set_mode_w = cmd_we && (cmd_a== MCNTRL_SCANLINE_MODE);
assign set_status_w = cmd_we && (cmd_a== MCNTRL_SCANLINE_STATUS_CNTRL);
assign set_start_addr_w = cmd_we && (cmd_a== MCNTRL_SCANLINE_STARTADDR);
assign set_frame_width_w = cmd_we && (cmd_a== MCNTRL_SCANLINE_FRAME_FULL_WIDTH);
assign set_window_wh_w = cmd_we && (cmd_a== MCNTRL_SCANLINE_WINDOW_WH);
assign set_window_x0y0_w = cmd_we && (cmd_a== MCNTRL_SCANLINE_WINDOW_X0Y0);
assign set_window_start_w = cmd_we && (cmd_a== MCNTRL_SCANLINE_WINDOW_STARTXY);
// Sett parameter registers
always @(posedge rst or posedge mclk) begin
if (rst) mode_reg <= 0;
else if (set_mode_w) mode_reg <= cmd_data[4:0];
if (rst) start_addr <= 0;
else if (set_start_addr_w) start_addr <= cmd_data[NUM_RC_BURST_BITS-1:0];
if (rst) frame_full_width <= 0;
else if (set_frame_width_w) frame_full_width <= {msw13_zero,cmd_data[FRAME_WIDTH_BITS-1:0]};
if (rst) 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
if (rst) 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 (rst) 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
end
assign mul_rslt_w= frame_y8_r * frame_full_width_r; // 5 MSBs will be discarded
assign xfer_num128= xfer_num128_r[NUM_XFER_BITS-1:0];
assign xfer_start= xfer_start_r[0];
assign calc_valid= par_mod_r[PAR_MOD_LATENCY-1]; // MSB, longest 0
assign xfer_page= xfer_page_r;
assign frame_done= frame_done_r;
assign pre_want= chn_en && busy_r && !want_r && !xfer_start_r[0] && calc_valid && !last_block && !suspend;
assign last_in_row_w=(row_left=={{(FRAME_WIDTH_BITS-NUM_XFER_BITS){1'b0}},xfer_num128_r});
assign last_row_w= next_y==window_height;
assign xfer_want= want_r;
assign xfer_need= need_r;
assign xfer_bank= bank_reg[2]; // 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[1];
assign chn_en = &mode_reg[1:0]; // enable requests by channle (continue ones in progress)
assign chn_rst = ~mode_reg[0]; // resets command, including fifo;
assign cmd_wrmem = mode_reg[2];// 0: read from memory, 1:write to memory
assign cmd_extra_pages = mode_reg[4:3]; // external module needs more than 1 page
assign status_data= {1'b0, busy_r}; // TODO: Add second bit?
assign pgm_param_w= cmd_we;
integer i;
localparam EXTRA_BITS={COLADDR_NUMBER-3-COLADDR_NUMBER-3{1'b0}};
always @(posedge mclk) begin // TODO: Match latencies (is it needed?) Reduce consumption by CE?
frame_x <= curr_x + window_x0;
frame_y <= curr_y + window_y0;
next_y <= curr_y + 1;
row_left <= window_width - curr_x; // 14 bits - 13 bits
mem_page_left <= (1 << (COLADDR_NUMBER-3)) - frame_x[COLADDR_NUMBER-4:0];
lim_by_xfer <= (|row_left[FRAME_WIDTH_BITS:NUM_XFER_BITS])?(1<<NUM_XFER_BITS):row_left[NUM_XFER_BITS:0]; // 7 bits, max 'h40
xfer_num128_r<= (mem_page_left> {{EXTRA_BITS{1'b0}},lim_by_xfer})? mem_page_left[NUM_XFER_BITS:0]:lim_by_xfer[NUM_XFER_BITS:0];
// VDT bug? next line gives a warning
// xfer_num128_r<= (mem_page_left> {{COLADDR_NUMBER-3-COLADDR_NUMBER-3{1'b0}},lim_by_xfer})?mem_page_left[NUM_XFER_BITS-1:0]:lim_by_xfer[NUM_XFER_BITS-1:0];
last_in_row <= last_in_row_w;
frame_y8_r <= frame_y[FRAME_HEIGHT_BITS-1:3]; // lat=2
frame_full_width_r <= frame_full_width;
start_addr_r <= start_addr;
mul_rslt <= mul_rslt_w[MPY_WIDTH-1:0]; // frame_y8_r * frame_width_r; // 7 bits will be discarded lat=3;
line_start_addr <= start_addr_r+mul_rslt; // lat=4
row_col_r <= line_start_addr+frame_x;
bank_reg[0] <= 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] <= bank_reg[i];
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
always @(posedge rst or posedge mclk) begin
if (rst) par_mod_r<=0;
else if (pgm_param_w || xfer_start_r[0] || chn_rst) par_mod_r<=0;
else par_mod_r <= {par_mod_r[PAR_MOD_LATENCY-2:0], 1'b1};
if (rst) busy_r <= 0;
else if (chn_rst) busy_r <= 0;
else if (frame_start) busy_r <= 1;
else if (frame_done_r) busy_r <= 0;
if (rst) xfer_start_r <= 0;
else xfer_start_r <= {xfer_start_r[1:0],xfer_grant && !chn_rst};
if (rst) need_r <= 0;
else if (chn_rst || xfer_grant) need_r <= 0;
else if (pre_want && (page_cntr>=3)) need_r <= 1;
if (rst) want_r <= 0;
else if (chn_rst || xfer_grant) want_r <= 0;
else if (pre_want && (page_cntr>{1'b0,cmd_extra_pages})) want_r <= 1;
if (rst) page_cntr <= 0;
else if (frame_start) page_cntr <= cmd_wrmem?0:4;
else if ( xfer_start_r[0] && !next_page) page_cntr <= page_cntr + 1;
else if (!xfer_start_r[0] && next_page) page_cntr <= page_cntr - 1;
if (rst) xfer_page_r <= 0;
// else if (chn_rst || frame_start) xfer_page_r <= 0; // TODO: Check if it is better to keep xfer_page_r on frame start?
else if (chn_rst ) xfer_page_r <= 0; // TODO: Check if it is better to reset xfer_page_r on frame start? to zero?
else if (xfer_done) xfer_page_r <= xfer_page_r+1;
// increment x,y (two cycles)
if (rst) curr_x <= 0;
else if (chn_rst || frame_start) curr_x <= start_x;
else if (xfer_start_r[0]) curr_x <= last_in_row?0: curr_x + xfer_num128_r;
if (rst) curr_y <= 0;
else if (chn_rst || frame_start) curr_y <= start_y;
else if (xfer_start_r[0] && last_in_row) curr_y <= next_y[FRAME_HEIGHT_BITS-1:0];
if (rst) last_block <= 0;
else if (chn_rst || !busy_r) last_block <= 0;
else if (last_row_w && last_in_row_w) last_block <= 1;
if (rst) pending_xfers <= 0;
else if (chn_rst || !busy_r) pending_xfers <= 0;
else if ( xfer_start_r[0] && !xfer_done) pending_xfers <= pending_xfers + 1;
else if (!xfer_start_r[0] && xfer_done) pending_xfers <= pending_xfers - 1;
if (rst) frame_done_r <= 0;
else frame_done_r <= busy_r && last_block && xfer_done && (pending_xfers==0);
//line_unfinished_r cmd_wrmem
if (rst) line_unfinished_r[0] <= 0; //{FRAME_HEIGHT_BITS{1'b0}};
else if (chn_rst || frame_start) line_unfinished_r[0] <= window_y0+start_y;
else if (xfer_start_r[2]) line_unfinished_r[0] <= window_y0+next_y[FRAME_HEIGHT_BITS-1:0]; // latency 2 from xfer_start
if (rst) line_unfinished_r[1] <= 0; //{FRAME_HEIGHT_BITS{1'b0}};
else if (chn_rst || frame_start) line_unfinished_r[1] <= window_y0+start_y;
// in read mode advance line number ASAP
else if (xfer_start_r[2] && !cmd_wrmem) line_unfinished_r[1] <= window_y0+next_y[FRAME_HEIGHT_BITS-1:0]; // latency 2 from xfer_start
// in write mode advance line number only when it is guaranteed it will be the first to acyually access memory
else if (xfer_grant && cmd_wrmem) line_unfinished_r[1] <= line_unfinished_r[0];
end
cmd_deser #(
.ADDR (MCNTRL_SCANLINE_ADDR),
.ADDR_MASK (MCNTRL_SCANLINE_MASK),
.NUM_CYCLES (6),
.ADDR_WIDTH (4),
.DATA_WIDTH (32)
) cmd_deser_32bit_i (
.rst (rst), // input
.clk (mclk), // 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_SCANLINE_STATUS_REG_ADDR),
.PAYLOAD_BITS (2)
) status_generate_i (
.rst (rst), // input
.clk (mclk), // 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
......@@ -85,7 +85,7 @@ module mcntrl_ps_pio#(
// Port memory buffer (4 pages each, R/W fixed, port 0 - AXI read from DDR, port 1 - AXI write to DDR
// generate 16-bit data commands (and set defaults to registers)
wire [4:0] cmd_a;
wire [15:0] cmd_data;
wire [31:0] cmd_data;
wire cmd_we;
wire [1:0] status_data;
......@@ -98,8 +98,8 @@ module mcntrl_ps_pio#(
wire set_status_w;
wire set_en_rst; // set enable, reset register
reg [1:0] en_reset;//
wire chn_en = en_reset[1]; // enable requests by channle (continue ones in progress)
wire chn_rst = ~en_reset[0]; // resets command, including fifo;
wire chn_en = &en_reset[1]; // enable requests by channle (continue ones in progress)
reg mem_run; // sequencere pgm granted and set, waiting/executing memory transfer to/from buffur 0/1
wire busy;
wire start;
......@@ -113,7 +113,7 @@ module mcntrl_ps_pio#(
reg cmd_set;
assign busy= want_rq0 || need_rq0 ||want_rq1 || need_rq1 || mem_run;
assign start= !chn_rst && chn_en && !busy && cmd_nempty;
assign start= chn_en && !busy && cmd_nempty;
assign seq_data0= cmd_seq_a;
assign seq_set0=cmd_set;
assign status_data= {cmd_half_full,cmd_nempty | busy};
......@@ -161,10 +161,10 @@ module mcntrl_ps_pio#(
cmd_deser #(
.ADDR (MCNTRL_PS_ADDR),
.ADDR_MASK (MCNTRL_PS_MASK),
.NUM_CYCLES (4),
.NUM_CYCLES (6),
.ADDR_WIDTH (5),
.DATA_WIDTH (16)
) cmd_deser_mcontr_16bit_i (
.DATA_WIDTH (32)
) cmd_deser_mcontr_32bit_i (
.rst (rst), // input
.clk (mclk), // input
.ad (cmd_ad), // input[7:0]
......
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