Commit db90602d authored by Andrey Filippov's avatar Andrey Filippov

porting jpeg/jp4 compressor

parent e412df6c
This diff is collapsed.
/*******************************************************************************
* Module: cmprs_frame_sync
* Date:2015-06-23
* Author: andrey
* Description: Synchronizes memory channels (sensor and compressor)
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* cmprs_frame_sync.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.
*
* cmprs_frame_sync.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 cmprs_frame_sync#(
parameter FRAME_HEIGHT_BITS= 16, // Maximal frame height
parameter LAST_FRAME_BITS= 16 // number of bits in frame counter (before rolls over)
)(
input rst,
input xclk, // global clock input, compressor single clock rate
// input xclk2x, // global clock input, compressor double clock rate, nominally rising edge aligned
input mclk, // global system/memory clock
input cmprs_en, // @mclk 0 resets immediately
output cmprs_en_extend, // @mclk keep compressor enabled for graceful shutdown
input cmprs_run, // @mclk enable propagation of vsync_late to frame_start_dst in bonded(sync to src) mode
input cmprs_standalone, // @mclk single-cycle: generate a single frame_start_dst in unbonded (not synchronized) mode.
// cmprs_run should be off
input sigle_frame_buf, // memory controller uses a single frame buffer (frame_number_* == 0), use other sync
input vsync_late, // @xclk delayed start of frame, @xclk. In 353 it was 16 lines after VACT active
// source channel should already start, some delay give time for sequencer commands
// that should arrive before it
input frame_started, // @xclk started first macroblock (checking for broken frames)
output frame_start_dst, // @mclk - trigger receive (tiled) memory channel (it will take care of single/repetitive
// this output either follows vsync_late (reclocks it) or generated in non-bonded mode
// (compress from memory)
input [FRAME_HEIGHT_BITS-1:0] line_unfinished_src,// number of the current (unfinished ) line, in the source (sensor) channel (RELATIVE TO FRAME, NOT WINDOW?)
input [LAST_FRAME_BITS-1:0] frame_number_src, // current frame number (for multi-frame ranges) in the source (sensor) channel
input frame_done_src, // single-cycle pulse when the full frame (window) was transferred to/from DDR3 memory
// frame_done_src is later than line_unfinished_src/ frame_number_src changes
// Used withe a single-frame buffers
input [FRAME_HEIGHT_BITS-1:0] line_unfinished, // number of the current (unfinished ) line in this (compressor) channel
input [LAST_FRAME_BITS-1:0] frame_number, // current frame number (for multi-frame ranges) in this (compressor channel
input frame_done, // input - single-cycle pulse when the full frame (window) was transferred to/from DDR3 memory
output reg suspend, // suspend reading data for this channel - waiting for the source data
output reg broken_frame // next frame start came before previous frame was read to compressor
);
wire vsync_late_mclk; // single mclk cycle, reclocked from vsync_late
wire frame_started_mclk;
reg bonded_mode;
reg frame_start_dst_r;
reg frames_differ; // src and dest point to different frames (single-frame buffer mode), disregard line_unfinished_*
reg frames_numbers_differ; // src and dest point to different frames (multi-frame buffer mode), disregard line_unfinished_*
reg line_numbers_sync; // src unfinished line number is > this unfinished line number
reg reading_frame; // compressor is reading frame data (make sure input is done before starting next frame, otherwise make it a broken frame
assign frame_start_dst = frame_start_dst_r;
always @ (posedge mclk) begin
frame_start_dst_r <= cmprs_en && (cmprs_run ? (vsync_late_mclk && !reading_frame) : cmprs_standalone);
if (!cmprs_en) bonded_mode <= 0;
else if (cmprs_run) bonded_mode <= 1;
else if (cmprs_standalone) bonded_mode <= 0;
if (!cmprs_en || !cmprs_run || vsync_late_mclk) frames_differ <= 0;
else if (frame_done_src) frames_differ <= 1'b1;
frames_numbers_differ <= frame_number_src != frame_number;
line_numbers_sync <= (line_unfinished_src > line_unfinished);
suspend <= !bonded_mode && ((sigle_frame_buf ? frames_differ : frames_numbers_differ) || line_numbers_sync);
if (!cmprs_en || frame_done || (cmprs_run && vsync_late_mclk)) reading_frame <= 0;
else if (frame_started_mclk) reading_frame <= 1;
broken_frame <= cmprs_en && cmprs_run && vsync_late_mclk && reading_frame; // single xclk pulse
end
pulse_cross_clock vsync_late_mclk_i (.rst(rst), .src_clk(xclk), .dst_clk(mclk), .in_pulse(vsync_late), .out_pulse(vsync_late_mclk),.busy());
pulse_cross_clock frame_started_i (.rst(rst), .src_clk(xclk), .dst_clk(mclk), .in_pulse(frame_started), .out_pulse(frame_started_mclk),.busy());
endmodule
......@@ -42,7 +42,7 @@ module cmprs_macroblock_buf_iface #(
input [12:0] n_block_rows_m1, // number of macroblock rows in a frame minus 1
input [ 5:0] mb_w_m1, // macroblock width minus 1 // 3 LSB not used
input [ 4:0] mb_hper, // macroblock horizontal period (8/16) // 3 LSB not used
input [ 1:0] tile_width, // memory tile width (can be 128 for monochrome JPEG) Can be 32/64/128: 0 - 16, 1 - 32, 2 - 64, 3 - 128
input [ 1:0] tile_width, // memory tile width (can be 128 for monochrome JPEG) Can be 32/64/128: 0 - 16, 1 - 32, 2 - 64, 3 - 128
input mb_pre_end_in, // from cmprs_pixel_buf_iface - just in time to start a new macroblock w/o gaps
input mb_release_buf, // send required "next_page" pulses to buffer. Having rather long minimal latency in the memory
......
This diff is collapsed.
......@@ -35,26 +35,31 @@
// s ynthesis attribute use_sync_set of stuffer is no;
// s ynthesis attribute use_sync_reset of stuffer is no;
// s ynthesis attribute use_clock_enable of stuffer is no;
// TODO:
// 1: Add FIFO buffer - with hclk on the read side
// 2: Get rid of imgptr - read addresses from the AFI module
// 3 Add multi-word status transmitter or just status transmit module for each compressor channel (29 bits are OK to read in multiple of 32-byte blocks
// Or make FIFO outside of the stuffer?
module stuffer393 (
input clk, // 2x pixel clock
input en, // enable, 0- reset
input clk, // 2x pixel clock
input en, // enable, 0- reset
input reset_data_counters, // reset data transfer counters (only when DMA and compressor are disabled)
input flush, // flush output data (fill byte with 0, long word with 0
input stb, // input data strobe
input [3:0] dl, // [3:0] number of bits to send (0 - 16) ??
input [15:0] d, // [15:0] input data to shift (only lower bits are valid)
input flush, // flush output data (fill byte with 0, long word with 0
input stb, // input data strobe
input [3:0] dl, // [3:0] number of bits to send (0 - 16) ??
input [15:0] d, // [15:0] input data to shift (only lower bits are valid)
// time stamping - will copy time at the end of color_first (later than the first hact after vact in the current froma, but before the next one
// and before the data is needed for output
input color_first, //
input [31:0] sec, // [31:0] number of seconds
input [19:0] usec, // [19:0] number of microseconds
output rdy, // enable huffman encoder to proceed. Used as CE for many huffman encoder registers
output reg [15:0] q, // [15:0] output data
output reg qv, // output data valid
output done,// reset by !en, goes high after some delay after flushing
output reg [23:0] imgptr, // [23:0]image pointer in 32-byte chunks
input [31:0] sec, // [31:0] number of seconds
input [19:0] usec, // [19:0] number of microseconds
output rdy, // enable huffman encoder to proceed. Used as CE for many huffman encoder registers
// outputs @ negedge clk
output reg [15:0] q, // [15:0] output data
output reg qv, // output data valid
output done, // reset by !en, goes high after some delay after flushing
output reg [23:0] imgptr, // [23:0]image pointer in 32-byte chunks
output reg flushing
`ifdef debug_stuffer
, output reg [3:0] etrax_dma_r, // [3:0] just for testing
......@@ -68,7 +73,7 @@ module stuffer393 (
`endif
reg [23:1] stage1; // stage 1 register (after right-shifting input data by 0..7 - actually left by 7..0)
wire [2:0] shift1; // shift amount for stage 1
wire [2:0] shift1; // shift amount for stage 1
reg [4:0] stage1_bits; // number of topmost invalid bits in stage1 register - 2 MSBs, use lower 3 stage2_bits
reg [4:0] stage1_length; // number of bits (1..16) in stage 1 register
......
......@@ -187,6 +187,7 @@
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 LAST_FRAME_BITS= 16, // number of bits in frame counter (before rolls over)
parameter MCNTRL_SCANLINE_CHN1_ADDR= 'h120,
parameter MCNTRL_SCANLINE_CHN3_ADDR= 'h130,
parameter MCNTRL_SCANLINE_MASK= 'h3f0, // both channels 0 and 1
......
......@@ -165,7 +165,8 @@ module mcntrl393 #(
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 FRAME_HEIGHT_BITS= 16, // Maximal frame height
parameter LAST_FRAME_BITS= 16, // number of bits in frame counter (before rolls over)
parameter MCNTRL_SCANLINE_CHN1_ADDR= 'h120,
parameter MCNTRL_SCANLINE_CHN3_ADDR= 'h130,
parameter MCNTRL_SCANLINE_MASK= 'h3f0, // both channels 0 and 1
......@@ -270,7 +271,7 @@ module mcntrl393 #(
output page_ready_chn1, // == xfer_done, connect externally | Single-cycle pulse indicating that a page was read/written from/to DDR3 memory
output frame_done_chn1, // 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_chn1, // number of the current (ufinished ) line, REALATIVE TO FRAME, NOT WINDOW?.
output [FRAME_HEIGHT_BITS-1:0] line_unfinished_chn1, // number of the current (unfinished ) line, RELATIVE TO FRAME, NOT WINDOW?.
input suspend_chn1, // suspend transfers (from external line number comparator)
// chn1 buffer interface, DDR3 memory read
......@@ -295,7 +296,8 @@ module mcntrl393 #(
output page_ready_chn2, // == xfer_done, connect externally | Single-cycle pulse indicating that a page was read/written from/to DDR3 memory
output frame_done_chn2, // 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_chn2, // number of the current (ufinished ) line, REALATIVE TO FRAME, NOT WINDOW?.
output [FRAME_HEIGHT_BITS-1:0] line_unfinished_chn2, // number of the current (unfinished ) line, RELATIVE TO FRAME, NOT WINDOW?.
output [LAST_FRAME_BITS-1:0] frame_number_chn2, // current frame number (for multi-frame ranges)
input suspend_chn2, // suspend transfers (from external line number comparator)
input frame_start_chn3, // resets page, x,y, and initiates transfer requests (in write mode will wait for next_page)
......@@ -303,7 +305,8 @@ module mcntrl393 #(
output page_ready_chn3, // == xfer_done, connect externally | Single-cycle pulse indicating that a page was read/written from/to DDR3 memory
output frame_done_chn3, // 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_chn3, // number of the current (ufinished ) line, REALATIVE TO FRAME, NOT WINDOW?.
output [FRAME_HEIGHT_BITS-1:0] line_unfinished_chn3, // number of the current (unfinished ) line, RELATIVE TO FRAME, NOT WINDOW?.
output [LAST_FRAME_BITS-1:0] frame_number_chn3, // current frame number (for multi-frame ranges)
input suspend_chn3, // suspend transfers (from external line number comparator)
// Channel 4 (tiled read)
input frame_start_chn4, // resets page, x,y, and initiates transfer requests (in write mode will wait for next_page)
......@@ -311,7 +314,8 @@ module mcntrl393 #(
output page_ready_chn4, // == xfer_done, connect externally | Single-cycle pulse indicating that a page was read/written from/to DDR3 memory
output frame_done_chn4, // 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_chn4, // number of the current (ufinished ) line, REALATIVE TO FRAME, NOT WINDOW?.
output [FRAME_HEIGHT_BITS-1:0] line_unfinished_chn4, // number of the current (unfinished ) line, RELATIVE TO FRAME, NOT WINDOW?.
output [LAST_FRAME_BITS-1:0] frame_number_chn4, // current frame number (for multi-frame ranges)
input suspend_chn4, // suspend transfers (from external line number comparator)
......@@ -943,6 +947,7 @@ module mcntrl393 #(
.NUM_XFER_BITS (NUM_XFER_BITS),
.FRAME_WIDTH_BITS (FRAME_WIDTH_BITS),
.FRAME_HEIGHT_BITS (FRAME_HEIGHT_BITS),
.LAST_FRAME_BITS (LAST_FRAME_BITS),
.MCNTRL_SCANLINE_ADDR (MCNTRL_SCANLINE_CHN1_ADDR),
.MCNTRL_SCANLINE_MASK (MCNTRL_SCANLINE_MASK),
.MCNTRL_SCANLINE_MODE (MCNTRL_SCANLINE_MODE),
......@@ -969,6 +974,7 @@ module mcntrl393 #(
.frame_finished (), // output
.line_unfinished (line_unfinished_chn1), // output[15:0]
.suspend (suspend_chn1), // input
.frame_number (), // output[15:0] - not used for this channel
.xfer_want (want_rq1), // output
.xfer_need (need_rq1), // output
.xfer_grant (channel_pgm_en1), // input
......@@ -991,6 +997,7 @@ module mcntrl393 #(
.NUM_XFER_BITS (NUM_XFER_BITS),
.FRAME_WIDTH_BITS (FRAME_WIDTH_BITS),
.FRAME_HEIGHT_BITS (FRAME_HEIGHT_BITS),
.LAST_FRAME_BITS (LAST_FRAME_BITS),
.MCNTRL_SCANLINE_ADDR (MCNTRL_SCANLINE_CHN3_ADDR),
.MCNTRL_SCANLINE_MASK (MCNTRL_SCANLINE_MASK),
.MCNTRL_SCANLINE_MODE (MCNTRL_SCANLINE_MODE),
......@@ -1017,6 +1024,7 @@ module mcntrl393 #(
.frame_finished (), // output
.line_unfinished (line_unfinished_chn3), // output[15:0]
.suspend (suspend_chn3), // input
.frame_number (frame_number_chn3),
.xfer_want (want_rq3), // output
.xfer_need (need_rq3), // output
.xfer_grant (channel_pgm_en3), // input
......@@ -1040,6 +1048,7 @@ module mcntrl393 #(
.FRAME_HEIGHT_BITS (FRAME_HEIGHT_BITS),
.MAX_TILE_WIDTH (MAX_TILE_WIDTH),
.MAX_TILE_HEIGHT (MAX_TILE_HEIGHT),
.LAST_FRAME_BITS (LAST_FRAME_BITS),
.MCNTRL_TILED_ADDR (MCNTRL_TILED_CHN2_ADDR),
.MCNTRL_TILED_MASK (MCNTRL_TILED_MASK),
.MCNTRL_TILED_MODE (MCNTRL_TILED_MODE),
......@@ -1067,6 +1076,7 @@ module mcntrl393 #(
.frame_finished (), // output
.line_unfinished (line_unfinished_chn2), // output[15:0]
.suspend (suspend_chn2), // input
.frame_number (frame_number_chn2),
.xfer_want (want_rq2), // output
.xfer_need (need_rq2), // output
.xfer_grant (channel_pgm_en2), // input
......@@ -1094,6 +1104,7 @@ module mcntrl393 #(
.FRAME_HEIGHT_BITS (FRAME_HEIGHT_BITS),
.MAX_TILE_WIDTH (MAX_TILE_WIDTH),
.MAX_TILE_HEIGHT (MAX_TILE_HEIGHT),
.LAST_FRAME_BITS (LAST_FRAME_BITS),
.MCNTRL_TILED_ADDR (MCNTRL_TILED_CHN4_ADDR),
.MCNTRL_TILED_MASK (MCNTRL_TILED_MASK),
.MCNTRL_TILED_MODE (MCNTRL_TILED_MODE),
......@@ -1121,6 +1132,7 @@ module mcntrl393 #(
.frame_finished (), // output
.line_unfinished (line_unfinished_chn4), // output[15:0]
.suspend (suspend_chn4), // input
.frame_number (frame_number_chn4),
.xfer_want (want_rq4), // output
.xfer_need (need_rq4), // output
.xfer_grant (channel_pgm_en4), // input
......
......@@ -27,7 +27,7 @@ module mcntrl_linear_rw #(
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 LAST_FRAME_BITS= 16, // number of bits in frame counter (before rolls over)
parameter LAST_FRAME_BITS= 16, // number of bits in frame counter (before rolls over)
parameter MCNTRL_SCANLINE_ADDR= 'h120,
parameter MCNTRL_SCANLINE_MASK= 'h3f0, // both channels 0 and 1
parameter MCNTRL_SCANLINE_MODE= 'h0, // set mode register: {repet,single,rst_frame,na[2:0],extra_pages[1:0],write_mode,enable,!reset}
......@@ -66,7 +66,8 @@ module mcntrl_linear_rw #(
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
output [FRAME_HEIGHT_BITS-1:0] line_unfinished, // number of the current (ufinished ) line, REALATIVE TO FRAME, NOT WINDOW?.
// 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 xfer_want, // "want" data transfer
......@@ -124,7 +125,7 @@ module mcntrl_linear_rw #(
reg [PAR_MOD_LATENCY-1:0] par_mod_r;
reg [PAR_MOD_LATENCY-1:0] recalc_r; // 1-hot CE for re-calculating registers
wire calc_valid; // calculated registers have valid values
wire chn_en; // enable requests by channle (continue ones in progress), enable frame_start inputs
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
// reg xfer_reset_page_r;
......@@ -182,8 +183,11 @@ module mcntrl_linear_rw #(
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 [2:0] frame_start_r;
// 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
// frame_width rounded up to max transfer (half page) if frame_width> max transfer/2,
......@@ -195,7 +199,7 @@ module mcntrl_linear_rw #(
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
reg xfer_done_d; // xfer_done delayed by 1 cycle;
assign frame_number = frame_number_cntr;
assign frame_number = frame_number_current;
assign set_mode_w = cmd_we && (cmd_a== MCNTRL_SCANLINE_MODE);
assign set_status_w = cmd_we && (cmd_a== MCNTRL_SCANLINE_STATUS_CNTRL);
......@@ -242,7 +246,7 @@ module mcntrl_linear_rw #(
else is_last_frame <= frame_number_cntr == last_frame_number;
if (rst) frame_start_r <= 0;
else frame_start_r <= {frame_start_r[1:0], frame_start & frame_en};
else frame_start_r <= {frame_start_r[3:0], frame_start & frame_en};
if (rst) frame_en <= 0;
else if (single_frame_r || repeat_frames) frame_en <= 1;
......@@ -252,6 +256,10 @@ module mcntrl_linear_rw #(
else if (rst_frame_num_r[0]) frame_number_cntr <= 0;
else if (frame_start_r[2]) frame_number_cntr <= is_last_frame?{LAST_FRAME_BITS{1'b0}}:(frame_number_cntr+1);
if (rst) 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 (rst) 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);
......@@ -296,7 +304,8 @@ module mcntrl_linear_rw #(
assign frame_done= frame_done_r;
assign frame_finished= frame_finished_r;
assign pre_want= chn_en && busy_r && !want_r && !xfer_start_r[0] && calc_valid && !last_block && !suspend && !frame_start_r[0];
// assign pre_want= chn_en && busy_r && !want_r && !xfer_start_r[0] && calc_valid && !last_block && !suspend && !frame_start_r[0];
assign pre_want= chn_en && busy_r && !want_r && !xfer_start_r[0] && calc_valid && !last_block && !suspend && !(|frame_start_r);
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;
......@@ -471,10 +480,11 @@ wire start_not_partial= xfer_start_r[0] && !xfer_limited_by_mem_page_r;
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_r[0]) line_unfinished_r[1] <= window_y0+start_y;
// else if (chn_rst || frame_start_r[0]) line_unfinished_r[1] <= window_y0+start_y;
else if (chn_rst || frame_start_r[2]) line_unfinished_r[1] <= window_y0+start_y; // _r[0] -> _r[2] to make it simultaneous with frame_number
// 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
// in write mode advance line number only when it is guaranteed it will be the first to actually access memory
else if (xfer_grant && cmd_wrmem) line_unfinished_r[1] <= line_unfinished_r[0];
end
......
......@@ -93,7 +93,7 @@ module mcntrl_ps_pio#(
wire set_en_rst; // set enable, reset register
reg [1:0] en_reset;//
wire chn_rst = ~en_reset[0]; // resets command, including fifo;
wire chn_en = &en_reset[1]; // enable requests by channle (continue ones in progress)
wire chn_en = &en_reset[1]; // enable requests by channel (continue ones in progress)
// reg mem_run; // sequencer pgm granted and set, waiting/executing memory transfer to/from buffur 0/1
wire busy;
wire short_busy; // does not include memory transaction
......
......@@ -4,6 +4,8 @@
* Author: andrey
* Description: 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 (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* mcntrl_tiled_rw.v is free software; you can redistribute it and/or modify
......@@ -22,7 +24,7 @@
`timescale 1ns/1ps
module mcntrl_tiled_rw#(
parameter ADDRESS_NUMBER= 15,
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
......@@ -69,7 +71,8 @@ module mcntrl_tiled_rw#(
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
output [FRAME_HEIGHT_BITS-1:0] line_unfinished, // number of the current (ufinished ) line, REALATIVE TO FRAME, NOT WINDOW?.
// 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 xfer_want, // "want" data transfer
......@@ -132,7 +135,7 @@ module mcntrl_tiled_rw#(
reg [PAR_MOD_LATENCY-1:0] par_mod_r;
reg [PAR_MOD_LATENCY-1:0] recalc_r; // 1-hot CE for re-calculating registers
wire calc_valid; // calculated registers have valid values
wire chn_en; // enable requests by channle (continue ones in progress), enable frame_start inputs
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
reg xfer_page_rst_r=1;
......@@ -162,8 +165,10 @@ module mcntrl_tiled_rw#(
reg last_block;
reg [MCNTRL_TILED_PENDING_CNTR_BITS-1:0] pending_xfers; // number of requested,. but not finished block transfers (to genearate frame done)
reg [NUM_RC_BURST_BITS-1:0] row_col_r;
reg [FRAME_HEIGHT_BITS-1:0] line_unfinished_r0;
reg [FRAME_HEIGHT_BITS-1:0] line_unfinished_r1;
// reg [FRAME_HEIGHT_BITS-1:0] line_unfinished_r0;
// reg [FRAME_HEIGHT_BITS-1:0] line_unfinished_r1;
reg [FRAME_HEIGHT_BITS-1:0] line_unfinished_r [1:0];
wire pre_want;
wire [1:0] status_data;
wire [3:0] cmd_a;
......@@ -197,8 +202,10 @@ module mcntrl_tiled_rw#(
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 [2:0] frame_start_r;
// reg [2:0] frame_start_r;
reg [4:0] frame_start_r; // increased length to have time from line_unfinished to suspend (external)
// reg rst_frame_num_d;
reg [MAX_TILE_WIDTH:0] tile_cols; // full number of columns in a tile
......@@ -221,7 +228,7 @@ module mcntrl_tiled_rw#(
reg [FRAME_HEIGHT_BITS-1:0] start_y; // (programmed) normally 0, copied to curr_y on frame_start
reg xfer_page_done_d; // next cycle after xfer_page_done
assign frame_number = frame_number_cntr;
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);
......@@ -271,7 +278,7 @@ module mcntrl_tiled_rw#(
else is_last_frame <= frame_number_cntr == last_frame_number;
if (rst) frame_start_r <= 0;
else frame_start_r <= {frame_start_r[1:0], frame_start & frame_en};
else frame_start_r <= {frame_start_r[3:0], frame_start & frame_en};
if (rst) frame_en <= 0;
else if (single_frame_r || repeat_frames) frame_en <= 1;
......@@ -280,6 +287,10 @@ module mcntrl_tiled_rw#(
if (rst) frame_number_cntr <= 0;
else if (rst_frame_num_r[0]) frame_number_cntr <= 0;
else if (frame_start_r[2]) frame_number_cntr <= is_last_frame?{LAST_FRAME_BITS{1'b0}}:(frame_number_cntr+1);
if (rst) 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 (rst) 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;
......@@ -334,7 +345,8 @@ module mcntrl_tiled_rw#(
assign calc_valid= par_mod_r[PAR_MOD_LATENCY-1]; // MSB, longest 0
assign frame_done= frame_done_r;
assign frame_finished= frame_finished_r;
assign pre_want= chn_en && busy_r && !want_r && !xfer_start_r[0] && calc_valid && !last_block && !suspend && !frame_start_r[0];
// assign pre_want= chn_en && busy_r && !want_r && !xfer_start_r[0] && calc_valid && !last_block && !suspend && !frame_start_r[0];
assign pre_want= chn_en && busy_r && !want_r && !xfer_start_r[0] && calc_valid && !last_block && !suspend && !(|frame_start_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
// assign last_row_w= next_y>=window_height; // (next_y==window_height) is faster, but will not forgive software errors
// tiles must completely fit window
......@@ -347,9 +359,9 @@ module mcntrl_tiled_rw#(
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 line_unfinished=line_unfinished_r1;
assign chn_en = &mode_reg[1:0]; // enable requests by channle (continue ones in progress)
assign line_unfinished=line_unfinished_r[1];
// assign line_unfinished=line_unfinished_r1;
assign chn_en = &mode_reg[1:0]; // enable requests by channel (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
......@@ -524,8 +536,7 @@ wire start_not_partial= xfer_start_r[0] && !xfer_limited_by_mem_page_r;
if (rst) 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;
//line_unfinished_r cmd_wrmem
/* //line_unfinished_r cmd_wrmem
if (rst) line_unfinished_r0 <= 0; //{FRAME_HEIGHT_BITS{1'b0}};
else if (chn_rst || frame_start_r[0]) line_unfinished_r0 <= window_y0+start_y;
else if (xfer_start_r[2]) line_unfinished_r0 <= window_y0+next_y[FRAME_HEIGHT_BITS-1:0]; // latency 2 from xfer_start
......@@ -536,6 +547,21 @@ wire start_not_partial= xfer_start_r[0] && !xfer_limited_by_mem_page_r;
else if (xfer_start_r[2] && !cmd_wrmem) line_unfinished_r1 <= 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 actually access memory
else if (xfer_grant && cmd_wrmem) line_unfinished_r1 <= line_unfinished_r0;
*/
//line_unfinished_r cmd_wrmem
if (rst) line_unfinished_r[0] <= 0; //{FRAME_HEIGHT_BITS{1'b0}};
else if (chn_rst || frame_start_r[0]) 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_r[0]) line_unfinished_r[1] <= window_y0+start_y;
else if (chn_rst || frame_start_r[2]) line_unfinished_r[1] <= window_y0+start_y; // _r[0] -> _r[2] to make it simultaneous with frame_number
// 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 actually access memory
else if (xfer_grant && cmd_wrmem) line_unfinished_r[1] <= line_unfinished_r[0];
end
always @ (negedge mclk) begin
......
......@@ -228,18 +228,21 @@ module x393 #(
wire page_ready_chn2; // output
wire frame_done_chn2; // output
wire[FRAME_HEIGHT_BITS-1:0] line_unfinished_chn2; // output[15:0]
wire [LAST_FRAME_BITS-1:0] frame_number_chn2; // output[15:0]
wire suspend_chn2; // input
wire frame_start_chn3; // input
wire next_page_chn3; // input
wire page_ready_chn3; // output
wire frame_done_chn3; // output
wire[FRAME_HEIGHT_BITS-1:0] line_unfinished_chn3; // output[15:0]
wire [LAST_FRAME_BITS-1:0] frame_number_chn3; // output[15:0]
wire suspend_chn3; // input
wire frame_start_chn4; // input
wire next_page_chn4; // input
wire page_ready_chn4; // output
wire frame_done_chn4; // output
wire[FRAME_HEIGHT_BITS-1:0] line_unfinished_chn4; // output[15:0]
wire [LAST_FRAME_BITS-1:0] frame_number_chn4; // output[15:0]
wire suspend_chn4; // input
reg axi_rst_pre=1'b1;
......@@ -636,6 +639,7 @@ BUFG bufg_axi_aclk_i (.O(axi_aclk),.I(fclk[0]));
.NUM_XFER_BITS (NUM_XFER_BITS),
.FRAME_WIDTH_BITS (FRAME_WIDTH_BITS),
.FRAME_HEIGHT_BITS (FRAME_HEIGHT_BITS),
.LAST_FRAME_BITS (LAST_FRAME_BITS),
.MCNTRL_SCANLINE_CHN1_ADDR (MCNTRL_SCANLINE_CHN1_ADDR),
.MCNTRL_SCANLINE_CHN3_ADDR (MCNTRL_SCANLINE_CHN3_ADDR),
.MCNTRL_SCANLINE_MASK (MCNTRL_SCANLINE_MASK),
......@@ -715,19 +719,22 @@ BUFG bufg_axi_aclk_i (.O(axi_aclk),.I(fclk[0]));
.next_page_chn2 (next_page_chn2), // input
.page_ready_chn2 (page_ready_chn2), // output
.frame_done_chn2 (frame_done_chn2), // output
.line_unfinished_chn2 (line_unfinished_chn2), // output[15:0]
.line_unfinished_chn2 (line_unfinished_chn2), // output[15:0]
.frame_number_chn2 (frame_number_chn2), // output[15:0]
.suspend_chn2 (suspend_chn2), // input
.frame_start_chn3 (frame_start_chn3), // input
.next_page_chn3 (next_page_chn3), // input
.page_ready_chn3 (page_ready_chn3), // output
.frame_done_chn3 (frame_done_chn3), // output
.line_unfinished_chn3 (line_unfinished_chn3), // output[15:0]
.frame_number_chn3 (frame_number_chn3), // output[15:0]
.suspend_chn3 (suspend_chn3), // input
.frame_start_chn4 (frame_start_chn4), // input
.next_page_chn4 (next_page_chn4), // input
.page_ready_chn4 (page_ready_chn4), // output
.frame_done_chn4 (frame_done_chn4), // output
.line_unfinished_chn4 (line_unfinished_chn4), // output[15:0]
.frame_number_chn4 (frame_number_chn4), // output[15:0]
.suspend_chn4 (suspend_chn4), // input
.SDRST (SDRST), // output
......
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