Commit db90602d authored by Andrey Filippov's avatar Andrey Filippov

porting jpeg/jp4 compressor

parent e412df6c
/*******************************************************************************
* Module: cmprs_cmd_decode
* Date:2015-06-23
* Author: andrey
* Description: Decode compressor command/modes, reclock some signals
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* cmprs_cmd_decode.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_cmd_decode.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
//From 353:
// [23] == 1 - set focus mode
// [22:21] 0 - none
// 1 - replace
// 2 - combine for all image
// 3 - combine in window only
// [20] == 1 - set Bayer shift
// [19:18] Bayer shift
// [17] == 1 - set compressor shift
// [16:14] compressor shift
// [13]==1 - enable color modes
// [12:9]== 0 - color, 4:2:0
// 1 - monochrome, 6/4 blocks (as 4:2:0)
// 2 - jp4, 6 blocks, original
// 3 - jp4, 6 blocks, dc -improved
// 4 - mono, 4 blocks (but still not actual monochrome JPEG as the blocks are scanned in 2x2 macroblocks)
// 5 - jp4, 4 blocks, dc-improved
// 6 - jp4, differential
// 7 - 15 - reserved
// [8:7] == 0,1 - NOP, 2 - disable, 3 - enable subtracting of average value (DC component), bypassing DCT
// [6] == 1 - enable quantization bank select, 0 - disregard bits [5:3]
// [5:3] = quantization page number (0..7)
// [2]== 1 - enable on/off control:
// [1:0]== 0 - reset compressor, stop immediately
// 1 - enable compressor, disable repetitive mode
// 2 - enable compressor, compress single frame
// 3 - enable compressor, enable repetitive mode
//
//Modified for 393:
// [23] == 1 - set focus mode
// [22:21] 0 - none
// 1 - replace
// 2 - combine for all image
// 3 - combine in window only
// [20] == 1 - set Bayer shift
// [19:18] Bayer shift
// [17:16] - unused
// [15] == 1 - set single/multi frame mode
// [14] 0 - multiframe (compare frame numbers for 'suspend' output)
// 1 - single frame buffer
// [13]== 1 - enable color modes
// [12:9]== 0 - color, 4:2:0
// 1 - monochrome, 6/4 blocks (as 4:2:0)
// 2 - jp4, 6 blocks, original
// 3 - jp4, 6 blocks, dc -improved
// 4 - mono, 4 blocks (but still not actual monochrome JPEG as the blocks are scanned in 2x2 macroblocks)
// 5 - jp4, 4 blocks, dc-improved
// 6 - jp4, differential
// 7 - 15 - reserved
// [8:7] == 0,1 - NOP, 2 - disable, 3 - enable subtracting of average value (DC component), bypassing DCT
// [6] == 1 - enable quantization bank select, 0 - disregard bits [5:3]
// [5:3] = quantization page number (0..7)
// [2]== 1 - enable compressor on/off control:
// [1:0]== 0 - reset compressor, stop immediately
// 1 - disable compression of the new frames, finish any already started
// 2 - enable compressor, compress single frame from memory (async)
// 3 - enable compressor, enable synchronous compression mode
module cmprs_cmd_decode#(
// Bit-fields in compressor control word
parameter CMPRS_CBIT_RUN = 2, // bit # to control compressor run modes
parameter CMPRS_CBIT_RUN_BITS = 2, // number of bits to control compressor run modes
parameter CMPRS_CBIT_QBANK = 6, // bit # to control quantization table page
parameter CMPRS_CBIT_QBANK_BITS = 3, // number of bits to control quantization table page
parameter CMPRS_CBIT_DCSUB = 8, // bit # to control extracting DC components bypassing DCT
parameter CMPRS_CBIT_DCSUB_BITS = 1, // bit # to control extracting DC components bypassing DCT
parameter CMPRS_CBIT_CMODE = 13, // bit # to control compressor color modes
parameter CMPRS_CBIT_CMODE_BITS = 4, // number of bits to control compressor color modes
parameter CMPRS_CBIT_FRAMES = 15, // bit # to control compressor multi/single frame buffer modes
parameter CMPRS_CBIT_FRAMES_BITS = 1, // number of bits to control compressor multi/single frame buffer modes
parameter CMPRS_CBIT_BAYER = 20, // bit # to control compressor Bayer shift mode
parameter CMPRS_CBIT_BAYER_BITS = 2, // number of bits to control compressor Bayer shift mode
parameter CMPRS_CBIT_FOCUS = 23, // bit # to control compressor focus display mode
parameter CMPRS_CBIT_FOCUS_BITS = 2, // number of bits to control compressor focus display mode
// compressor bit-fields decode
parameter CMPRS_CBIT_RUN_RST = 2'h0, // reset compressor, stop immediately
// parameter CMPRS_CBIT_RUN_DISABLE = 2'h1, // disable compression of the new frames, finish any already started
parameter CMPRS_CBIT_RUN_STANDALONE = 2'h2, // enable compressor, compress single frame from memory (async)
parameter CMPRS_CBIT_RUN_ENABLE = 2'h3, // enable compressor, enable synchronous compression mode
parameter CMPRS_CBIT_CMODE_JPEG18 = 4'h0, // color 4:2:0
parameter CMPRS_CBIT_CMODE_MONO6 = 4'h1, // mono 4:2:0 (6 blocks)
parameter CMPRS_CBIT_CMODE_JP46 = 4'h2, // jp4, 6 blocks, original
parameter CMPRS_CBIT_CMODE_JP46DC = 4'h3, // jp4, 6 blocks, dc -improved
parameter CMPRS_CBIT_CMODE_JPEG20 = 4'h4, // mono, 4 blocks (but still not actual monochrome JPEG as the blocks are scanned in 2x2 macroblocks)
parameter CMPRS_CBIT_CMODE_JP4 = 4'h5, // jp4, 4 blocks, dc-improved
parameter CMPRS_CBIT_CMODE_JP4DC = 4'h6, // jp4, 4 blocks, dc-improved
parameter CMPRS_CBIT_CMODE_JP4DIFF = 4'h7, // jp4, 4 blocks, differential
parameter CMPRS_CBIT_CMODE_JP4DIFFHDR = 4'h8, // jp4, 4 blocks, differential, hdr
parameter CMPRS_CBIT_CMODE_JP4DIFFDIV2 = 4'h9, // jp4, 4 blocks, differential, divide by 2
parameter CMPRS_CBIT_CMODE_JP4DIFFHDRDIV2 = 4'ha, // jp4, 4 blocks, differential, hdr,divide by 2
parameter CMPRS_CBIT_CMODE_MONO1 = 4'hb, // mono JPEG (not yet implemented)
parameter CMPRS_CBIT_CMODE_MONO4 = 4'he, // mono 4 blocks
parameter CMPRS_CBIT_FRAMES_SINGLE = 0, //1, // use a single-frame buffer for images
parameter CMPRS_COLOR18 = 0, // JPEG 4:2:0 with 18x18 overlapping tiles for de-bayer
parameter CMPRS_COLOR20 = 1, // JPEG 4:2:0 with 18x18 overlapping tiles for de-bayer (not implemented)
parameter CMPRS_MONO16 = 2, // JPEG 4:2:0 with 16x16 non-overlapping tiles, color components zeroed
parameter CMPRS_JP4 = 3, // JP4 mode with 16x16 macroblocks
parameter CMPRS_JP4DIFF = 4, // JP4DIFF mode TODO: see if correct
parameter CMPRS_MONO8 = 7, // Regular JPEG monochrome with 8x8 macroblocks (not yet implemented)
parameter CMPRS_FRMT_MBCM1 = 0, // bit # of number of macroblock columns minus 1 field in format word
parameter CMPRS_FRMT_MBCM1_BITS = 13, // number of bits in number of macroblock columns minus 1 field in format word
parameter CMPRS_FRMT_MBRM1 = 13, // bit # of number of macroblock rows minus 1 field in format word
parameter CMPRS_FRMT_MBRM1_BITS = 13, // number of bits in number of macroblock rows minus 1 field in format word
parameter CMPRS_FRMT_LMARG = 26, // bit # of left margin field in format word
parameter CMPRS_FRMT_LMARG_BITS = 5, // number of bits in left margin field in format word
parameter CMPRS_CSAT_CB = 0, // bit # of number of blue scale field in color saturation word
parameter CMPRS_CSAT_CB_BITS = 10, // number of bits in blue scale field in color saturation word
parameter CMPRS_CSAT_CR = 12, // bit # of number of red scale field in color saturation word
parameter CMPRS_CSAT_CR_BITS = 10, // number of bits in red scale field in color saturation word
parameter CMPRS_CORING_BITS = 3 // number of bits in coring mode
)(
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 ctrl_we, // input - @mclk control register write enable
input format_we, // input - @mclk write number of tiles and left margin
input color_sat_we, // input - @mclk write color saturation values
input coring_we, // input - @mclk write coring values
// rs, // 0 - bit modes,
// // 1 - write ntiles;
input [31:0] di, // [15:0] data from CPU (sync to negedge sclk)
// cr_w, // data written to cr (1 cycle long) - just to reset legacy IRQ
// ntiles,//[17:0] - number of tiles in a frame to process
input frame_start, // @mclk
// outputs sync @ posedge mclk:
output cmprs_en_mclk, // @mclk 0 resets immediately
input cmprs_en_extend, // @mclk keep compressor enabled for graceful shutdown
output reg cmprs_run_mclk, // @mclk enable propagation of vsync_late to frame_start_dst in bonded(sync to src) mode
output reg cmprs_standalone, // @mclk single-cycle: generate a single frame_start_dst in unbonded (not synchronized) mode.
// cmprs_run should be off
output reg sigle_frame_buf, // memory controller uses a single frame buffer (frame_number_* == 0), use other sync
// outputs sync @ posedge xclk:
output reg cmprs_en_xclk, // enable compressor, extends control fields for graceful shutdown
// cmprs_start, // single cycle when single or constant compression is turned on
// cmprs_repeat,// high in repetitive mode
// outputs @posedge xclk, frozen when the new frame is requested
output reg [ 2:0] cmprs_qpage, // [2:0] - quantizator page number (0..7)
output reg cmprs_dcsub, // subtract dc level before DCT, restore later
// output reg [ 3:0] cmprs_mode, // [3:0] - compressor mode
// cmprs_shift, // tile shift from top left corner
output reg [ 1:0] cmprs_fmode, //[1:0] - focus mode
output reg [ 1:0] bayer_shift, // additional shift to bayer mosaic
output reg ignore_color,
output reg four_blocks,
output reg jp4_dc_improved,
output reg [ 2:0] converter_type, // 0 - color18, 1 - color20, 2 - mono, 3 - jp4, 4 - jp4-diff
output reg scale_diff,
output reg hdr,
output reg [CMPRS_FRMT_LMARG_BITS-1:0] left_marg, // left margin (for not-yet-implemented) mono JPEG (8 lines tile row) can need 7 bits (mod 32 - tile)
output reg [CMPRS_FRMT_MBCM1_BITS-1:0] n_blocks_in_row_m1, // number of macroblocks in a macroblock row minus 1
output reg [CMPRS_FRMT_MBRM1_BITS-1:0] n_block_rows_m1, // number of macroblock rows in a frame minus 1
output reg [CMPRS_CSAT_CB_BITS-1:0] color_sat_cb, // scale for Cb color component (color saturation)
output reg [CMPRS_CSAT_CR_BITS-1:0] color_sat_cr, // scale for Cr color component (color saturation)
output reg [CMPRS_CORING_BITS-1:0] coring // scale for Cb color component (color saturation)
);
// input is_compressing, // high from start of compressing till EOT (sync to posedge clk)
// abort_compress,
// input stuffer_done_mclk,
// output reg force_flush); // abort compress - generate flush pulse, force end of image over DMA, update counter
reg [30:0] di_r;
reg ctrl_we_r;
reg format_we_r;
reg color_sat_we_r;
reg coring_we_r;
reg cmprs_en_mclk_r;
wire ctrl_we_xclk; // single xclk pulse after ctrl_we_r (or use just ctrl_we, not ctrl_we_r)
wire format_we_xclk; // @xclk write number of tiles and left margin
wire color_sat_we_xclk; // @xclk write color saturation values
wire coring_we_xclk; // @xclk write coring values
reg [ 2:0] cmprs_qpage_mclk; // [2:0] - quantizator page number (0..7)
reg cmprs_dcsub_mclk; // subtract dc level before DCT, restore later
reg [ 3:0] cmprs_mode_mclk; // [3:0] - compressor mode
reg [ 1:0] cmprs_fmode_mclk; //[1:0] - focus mode
reg [ 1:0] bayer_shift_mclk; // additional shift to bayer mosaic
reg [30:0] format_mclk; // left margin and macroblock rows/columns
reg [23:0] color_sat_mclk; // color saturation values (only 10 LSB in each 12 are used
reg [ 2:0] coring_mclk; // color saturation values (only 10 LSB in each 12 are used
reg [ 2:0] cmprs_qpage_xclk; // [2:0] - quantizator page number (0..7)
reg cmprs_dcsub_xclk; // subtract dc level before DCT, restore later
reg [ 3:0] cmprs_mode_xclk; // [3:0] - compressor mode
reg [ 1:0] cmprs_fmode_xclk; //[1:0] - focus mode
reg [ 1:0] bayer_shift_xclk; // additional shift to bayer mosaic
reg [30:0] format_xclk; // left margin and macroblock rows/columns
reg [23:0] color_sat_xclk; // color saturation values (only 10 LSB in each 12 are used
reg [ 2:0] coring_xclk; // color saturation values (only 10 LSB in each 12 are used
wire frame_start_xclk;
assign cmprs_en_mclk = cmprs_en_mclk_r;
always @ (posedge rst or posedge mclk) begin
if (rst) ctrl_we_r <= 0;
else ctrl_we_r <= ctrl_we;
if (rst) format_we_r <= 0;
else format_we_r <= format_we;
if (rst) color_sat_we_r <= 0;
else color_sat_we_r <= color_sat_we;
if (rst) coring_we_r <= 0;
else coring_we_r <= coring_we;
if (rst) di_r <= 0;
else if (ctrl_we || format_we || color_sat_we || coring_we) di_r <= di[30:0];
if (rst) cmprs_en_mclk_r <= 0;
else if (ctrl_we_r && di_r[CMPRS_CBIT_RUN]) cmprs_en_mclk_r <= (di_r[CMPRS_CBIT_RUN-1 -:CMPRS_CBIT_RUN_BITS] != CMPRS_CBIT_RUN_RST);
if (rst) cmprs_run_mclk <= 0;
else if (ctrl_we_r && di_r[CMPRS_CBIT_RUN]) cmprs_run_mclk <= (di_r[CMPRS_CBIT_RUN-1 -:CMPRS_CBIT_RUN_BITS] == CMPRS_CBIT_RUN_ENABLE);
if (rst) cmprs_standalone <= 0;
else if (ctrl_we_r) cmprs_standalone <= ctrl_we_r && di_r[CMPRS_CBIT_RUN] && (di_r[CMPRS_CBIT_RUN-1 -:CMPRS_CBIT_RUN_BITS] == CMPRS_CBIT_RUN_STANDALONE);
if (rst) sigle_frame_buf <= 0;
else if (ctrl_we_r && di_r[CMPRS_CBIT_FRAMES]) sigle_frame_buf <= (di_r[CMPRS_CBIT_FRAMES-1 -:CMPRS_CBIT_FRAMES_BITS] == CMPRS_CBIT_FRAMES_SINGLE);
if (rst) cmprs_qpage_mclk <= 0;
else if (ctrl_we_r && di_r[CMPRS_CBIT_QBANK]) cmprs_qpage_mclk <= di_r[CMPRS_CBIT_QBANK-1 -:CMPRS_CBIT_QBANK_BITS];
if (rst) cmprs_dcsub_mclk <= 0;
else if (ctrl_we_r && di_r[CMPRS_CBIT_DCSUB]) cmprs_dcsub_mclk <= di_r[CMPRS_CBIT_DCSUB-1 -:CMPRS_CBIT_DCSUB_BITS];
if (rst) cmprs_mode_mclk <= 0;
else if (ctrl_we_r && di_r[CMPRS_CBIT_CMODE]) cmprs_mode_mclk <= di_r[CMPRS_CBIT_CMODE-1 -:CMPRS_CBIT_CMODE_BITS];
if (rst) cmprs_fmode_mclk <= 0;
else if (ctrl_we_r && di_r[CMPRS_CBIT_FOCUS]) cmprs_fmode_mclk <= di_r[CMPRS_CBIT_FOCUS-1 -:CMPRS_CBIT_FOCUS_BITS];
if (rst) bayer_shift_mclk <= 0;
else if (ctrl_we_r && di_r[CMPRS_CBIT_BAYER]) bayer_shift_mclk <= di_r[CMPRS_CBIT_BAYER-1 -:CMPRS_CBIT_BAYER_BITS];
if (rst) format_mclk <= 0;
else if (format_we_r) format_mclk <= di_r[30:0];
if (rst) color_sat_mclk <= 0;
else if (color_sat_we_r) color_sat_mclk <= di_r[23:0];
if (rst) coring_mclk <= 0;
else if (coring_we_r) coring_mclk <= di_r[2:0];
end
// re-clock to compressor clock
always @ (posedge xclk) if (ctrl_we_xclk) begin
cmprs_en_xclk <= cmprs_en_mclk_r || cmprs_en_extend;
cmprs_qpage_xclk <= cmprs_qpage_mclk;
cmprs_dcsub_xclk <= cmprs_dcsub_mclk;
cmprs_mode_xclk <= cmprs_mode_mclk;
cmprs_fmode_xclk <= cmprs_fmode_mclk;
bayer_shift_xclk <= bayer_shift_mclk;
end
always @ (posedge xclk) begin
if (format_we_xclk) format_xclk <= format_mclk;
if (color_sat_we_xclk) color_sat_xclk <= color_sat_mclk;
if (coring_we_xclk) coring_xclk <= coring_mclk;
end
always @ (posedge xclk) if (frame_start_xclk) begin
cmprs_qpage <= cmprs_qpage_xclk;
cmprs_dcsub <= cmprs_dcsub_xclk;
cmprs_fmode <= cmprs_fmode_xclk;
bayer_shift <= bayer_shift_xclk;
left_marg <= format_xclk[CMPRS_FRMT_LMARG +: CMPRS_FRMT_LMARG_BITS];
n_block_rows_m1 <= format_xclk[CMPRS_FRMT_MBRM1 +: CMPRS_FRMT_MBRM1_BITS];
n_blocks_in_row_m1 <= format_xclk[CMPRS_FRMT_MBCM1 +: CMPRS_FRMT_MBCM1_BITS];
color_sat_cr <= color_sat_xclk[CMPRS_CSAT_CR +: CMPRS_CSAT_CR_BITS];
color_sat_cb <= color_sat_xclk[CMPRS_CSAT_CB +: CMPRS_CSAT_CB_BITS];
coring <= coring_xclk;
// Will infer ROM
case (cmprs_mode_xclk[3:0])
CMPRS_CBIT_CMODE_MONO6: begin //monochrome, (4:2:0),
ignore_color <= 1;
four_blocks <= 0;
jp4_dc_improved <= 0;
converter_type[2:0] <= CMPRS_MONO16; // 0 - color18, 1 - color20, 2 - mono, 3 - jp4, 4 - jp4-diff
scale_diff <=0;
hdr <=0;
end
CMPRS_CBIT_CMODE_JPEG18: begin //color, 4:2:0, 18x18(old)
ignore_color <= 0;
four_blocks <= 0;
jp4_dc_improved <= 0;
converter_type[2:0] <= CMPRS_COLOR18; // 0 - color18, 1 - color20, 2 - mono, 3 - jp4, 4 - jp4-diff
scale_diff <=0;
hdr <=0;
end
CMPRS_CBIT_CMODE_JP46: begin // jp4, original (4:2:0),
ignore_color <= 1;
four_blocks <= 0;
jp4_dc_improved <= 0;
converter_type[2:0] <= CMPRS_JP4; // 0 - color18, 1 - color20, 2 - mono, 3 - jp4, 4 - jp4-diff
scale_diff <=0;
hdr <=0;
end
CMPRS_CBIT_CMODE_JP46DC: begin // jp4, dc -improved (4:2:0),
ignore_color <= 1;
four_blocks <= 0;
jp4_dc_improved <= 1;
converter_type[2:0] <= CMPRS_JP4; // 0 - color18, 1 - color20, 2 - mono, 3 - jp4, 4 - jp4-diff
scale_diff <=0;
hdr <=0;
end
CMPRS_CBIT_CMODE_JPEG20: begin // color, 4:2:0, 20x20, middle of the tile (not yet implemented)
ignore_color <= 0;
four_blocks <= 0;
jp4_dc_improved <= 0;
converter_type[2:0] <= CMPRS_COLOR20; // 0 - color18, 1 - color20, 2 - mono, 3 - jp4, 4 - jp4-diff
scale_diff <=0;
hdr <=0;
end
CMPRS_CBIT_CMODE_JP4: begin // jp4, 4 blocks, (legacy)
ignore_color <= 1;
four_blocks <= 1;
jp4_dc_improved <= 0;
converter_type[2:0] <= CMPRS_JP4; // 0 - color18, 1 - color20, 2 - mono, 3 - jp4, 4 - jp4-diff
scale_diff <=0;
hdr <=0;
end
CMPRS_CBIT_CMODE_JP4DC: begin // jp4, 4 blocks, dc -improved
ignore_color <= 1;
four_blocks <= 1;
jp4_dc_improved <= 1;
converter_type[2:0] <= CMPRS_JP4; // 0 - color18, 1 - color20, 2 - mono, 3 - jp4, 4 - jp4-diff
scale_diff <=0;
hdr <=0;
end
CMPRS_CBIT_CMODE_JP4DIFF: begin // jp4, 4 blocks, differential
ignore_color <= 1;
four_blocks <= 1;
jp4_dc_improved <= 0;
converter_type[2:0] <= CMPRS_JP4DIFF; // 0 - color18, 1 - color20, 2 - mono, 3 - jp4, 4 - jp4-diff
scale_diff <=0;
hdr <=0;
end
CMPRS_CBIT_CMODE_JP4DIFFHDR: begin // jp4, 4 blocks, differential, hdr
ignore_color <= 1;
four_blocks <= 1;
jp4_dc_improved <= 0;
converter_type[2:0] <= CMPRS_JP4DIFF; // 0 - color18, 1 - color20, 2 - mono, 3 - jp4, 4 - jp4-diff
scale_diff <=0;
hdr <=1;
end
CMPRS_CBIT_CMODE_JP4DIFFDIV2: begin // jp4, 4 blocks, differential, divide diff by 2
ignore_color <= 1;
four_blocks <= 1;
jp4_dc_improved <= 0;
converter_type[2:0] <= CMPRS_JP4DIFF; // 0 - color18, 1 - color20, 2 - mono, 3 - jp4, 4 - jp4-diff
scale_diff <=1;
hdr <=0;
end
CMPRS_CBIT_CMODE_JP4DIFFHDRDIV2: begin // jp4, 4 blocks, differential, hdr, divide diff by 2
ignore_color <= 1;
four_blocks <= 1;
jp4_dc_improved <= 0;
converter_type[2:0] <= CMPRS_JP4DIFF; // 0 - color18, 1 - color20, 2 - mono, 3 - jp4, 4 - jp4-diff
scale_diff <=1;
hdr <=1;
end
CMPRS_CBIT_CMODE_MONO4: begin // mono, 4 blocks
ignore_color <= 1;
four_blocks <= 1;
jp4_dc_improved <= 0;
converter_type[2:0] <= CMPRS_MONO16; // 0 - color18, 1 - color20, 2 - mono, 3 - jp4, 4 - jp4-diff
end
CMPRS_CBIT_CMODE_MONO1: begin // mono, 1 block
ignore_color <= 1;
four_blocks <= 1;
jp4_dc_improved <= 0;
converter_type[2:0] <= CMPRS_MONO8; // 0 - color18, 1 - color20, 2 - mono, 3 - jp4, 4 - jp4-diff
end
default: begin //
ignore_color <= 'bx;
four_blocks <= 'bx;
jp4_dc_improved <= 'bx;
converter_type[2:0] <= 'bx;
end
endcase
end
//frame_start_xclk
pulse_cross_clock ctrl_we_xclk_i (.rst(rst), .src_clk(mclk), .dst_clk(xclk), .in_pulse(ctrl_we_r), .out_pulse(ctrl_we_xclk),.busy());
pulse_cross_clock format_we_xclk_i (.rst(rst), .src_clk(mclk), .dst_clk(xclk), .in_pulse(format_we_r), .out_pulse(format_we_xclk),.busy());
pulse_cross_clock color_sat_we_xclk_i (.rst(rst), .src_clk(mclk), .dst_clk(xclk), .in_pulse(color_sat_we_r), .out_pulse(color_sat_we_xclk),.busy());
pulse_cross_clock coring__we_xclk_i (.rst(rst), .src_clk(mclk), .dst_clk(xclk), .in_pulse(coring_we_r), .out_pulse(coring_we_xclk),.busy());
pulse_cross_clock frame_start_xclk_i (.rst(rst), .src_clk(mclk), .dst_clk(xclk), .in_pulse(frame_start), .out_pulse(frame_start_xclk),.busy());
endmodule
/*******************************************************************************
* 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
......@@ -21,20 +21,80 @@
`timescale 1ns/1ps
module jp_channel#(
parameter CMPRS_ADDR= 'h120, //TODO: assign valid adderss
parameter CMPRS_MASK= 'h3f8,
parameter CMPRS_CONTROL_REG= 0,
parameter CMPRS_STATUS_CNTRL= 1,
parameter CMPRS_FORMAT= 2,
parameter CMPRS_COLOR_SATURATION= 3,
parameter CMPRS_CORING_MODE= 4,
parameter CMPRS_TABLES= 6, // 6..7
parameter CMPRS_STATUS_REG_ADDR= 'h10, //TODO: assign valid adderss
parameter FRAME_HEIGHT_BITS= 16, // Maximal frame height
parameter LAST_FRAME_BITS= 16, // number of bits in frame counter (before rolls over)
// Bit-fields in compressor control word
parameter CMPRS_CBIT_RUN = 2, // bit # to control compressor run modes
parameter CMPRS_CBIT_RUN_BITS = 2, // number of bits to control compressor run modes
parameter CMPRS_CBIT_QBANK = 6, // bit # to control quantization table page
parameter CMPRS_CBIT_QBANK_BITS = 3, // number of bits to control quantization table page
parameter CMPRS_CBIT_DCSUB = 8, // bit # to control extracting DC components bypassing DCT
parameter CMPRS_CBIT_DCSUB_BITS = 1, // bit # to control extracting DC components bypassing DCT
parameter CMPRS_CBIT_CMODE = 13, // bit # to control compressor color modes
parameter CMPRS_CBIT_CMODE_BITS = 4, // number of bits to control compressor color modes
parameter CMPRS_CBIT_FRAMES = 15, // bit # to control compressor multi/single frame buffer modes
parameter CMPRS_CBIT_FRAMES_BITS = 1, // number of bits to control compressor multi/single frame buffer modes
parameter CMPRS_CBIT_BAYER = 20, // bit # to control compressor Bayer shift mode
parameter CMPRS_CBIT_BAYER_BITS = 2, // number of bits to control compressor Bayer shift mode
parameter CMPRS_CBIT_FOCUS = 23, // bit # to control compressor focus display mode
parameter CMPRS_CBIT_FOCUS_BITS = 2, // number of bits to control compressor focus display mode
// compressor bit-fields decode
parameter CMPRS_CBIT_RUN_RST = 2'h0, // reset compressor, stop immediately
// parameter CMPRS_CBIT_RUN_DISABLE = 2'h1, // disable compression of the new frames, finish any already started
parameter CMPRS_CBIT_RUN_STANDALONE = 2'h2, // enable compressor, compress single frame from memory (async)
parameter CMPRS_CBIT_RUN_ENABLE = 2'h3, // enable compressor, enable synchronous compression mode
parameter CMPRS_CBIT_CMODE_JPEG18 = 4'h0, // color 4:2:0
parameter CMPRS_CBIT_CMODE_MONO6 = 4'h1, // mono 4:2:0 (6 blocks)
parameter CMPRS_CBIT_CMODE_JP46 = 4'h2, // jp4, 6 blocks, original
parameter CMPRS_CBIT_CMODE_JP46DC = 4'h3, // jp4, 6 blocks, dc -improved
parameter CMPRS_CBIT_CMODE_JPEG20 = 4'h4, // mono, 4 blocks (but still not actual monochrome JPEG as the blocks are scanned in 2x2 macroblocks)
parameter CMPRS_CBIT_CMODE_JP4 = 4'h5, // jp4, 4 blocks, dc-improved
parameter CMPRS_CBIT_CMODE_JP4DC = 4'h6, // jp4, 4 blocks, dc-improved
parameter CMPRS_CBIT_CMODE_JP4DIFF = 4'h7, // jp4, 4 blocks, differential
parameter CMPRS_CBIT_CMODE_JP4DIFFHDR = 4'h8, // jp4, 4 blocks, differential, hdr
parameter CMPRS_CBIT_CMODE_JP4DIFFDIV2 = 4'h9, // jp4, 4 blocks, differential, divide by 2
parameter CMPRS_CBIT_CMODE_JP4DIFFHDRDIV2 = 4'ha, // jp4, 4 blocks, differential, hdr,divide by 2
parameter CMPRS_CBIT_CMODE_MONO1 = 4'hb, // mono JPEG (not yet implemented)
parameter CMPRS_CBIT_CMODE_MONO4 = 4'he, // mono 4 blocks
parameter CMPRS_CBIT_FRAMES_SINGLE = 0, //1, // use a single-frame buffer for images
parameter CMPRS_COLOR18 = 0, // JPEG 4:2:0 with 18x18 overlapping tiles for de-bayer
parameter CMPRS_COLOR20 = 1, // JPEG 4:2:0 with 18x18 overlapping tiles for de-bayer (not implemented)
parameter CMPRS_MONO16 = 2, // JPEG 4:2:0 with 16x16 non-overlapping tiles, color components zeroed
parameter CMPRS_JP4 = 3, // JP4 mode with 16x16 macroblocks
parameter CMPRS_JP4DIFF = 4, // JP4DIFF mode TODO: see if correct
parameter CMPRS_MONO8 = 7 // Regular JPEG monochrome with 8x8 macroblocks (not yet implemented)
parameter CMPRS_MONO8 = 7, // Regular JPEG monochrome with 8x8 macroblocks (not yet implemented)
parameter CMPRS_FRMT_MBCM1 = 0, // bit # of number of macroblock columns minus 1 field in format word
parameter CMPRS_FRMT_MBCM1_BITS = 13, // number of bits in number of macroblock columns minus 1 field in format word
parameter CMPRS_FRMT_MBRM1 = 13, // bit # of number of macroblock rows minus 1 field in format word
parameter CMPRS_FRMT_MBRM1_BITS = 13, // number of bits in number of macroblock rows minus 1 field in format word
parameter CMPRS_FRMT_LMARG = 26, // bit # of left margin field in format word
parameter CMPRS_FRMT_LMARG_BITS = 5, // number of bits in left margin field in format word
parameter CMPRS_CSAT_CB = 0, // bit # of number of blue scale field in color saturation word
parameter CMPRS_CSAT_CB_BITS = 10, // number of bits in blue scale field in color saturation word
parameter CMPRS_CSAT_CR = 12, // bit # of number of red scale field in color saturation word
parameter CMPRS_CSAT_CR_BITS = 10, // number of bits in red scale field in color saturation word
parameter CMPRS_CORING_BITS = 3 // number of bits in coring mode
)(
input rst,
input xclk, // global clock input, compressor single clock rate
input xclk2x, // global clock input, compressor double clock rate, nominally rising edge aligned
// programming interface
input mclk, // global clock, half DDR3 clock, synchronizes all I/O through the command port
input [7:0] cmd_ad_in, // byte-serial command address/data (up to 6 bytes: AL-AH-D0-D1-D2-D3
input cmd_stb_in, // strobe (with first byte) for the command a/d
input mclk, // global system/memory clock
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, // status address/data - up to 5 bytes: A - {seq,status[1:0]} - status[2:9] - status[10:17] - status[18:25]
output status_rq, // input request to send status downstream
input status_start, // Acknowledge of the first status packet byte (address)
......@@ -49,31 +109,51 @@ module jp_channel#(
output next_page_chn, // single mclk (posedge): Done with the page in the buffer, memory controller may read more data
// statistics data was not used in late nc353
output statistics_dv,
output [15:0] statistics_do
output [15:0] statistics_do,
input [31:0] sec,
input [19:0] usec,
// input [ 1:0] bayer_phase, // shared with sensor channel - remove!
input vsync_late, // 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
output frame_start_dst, // @mclk - trigger receive (tiledc) memory channel (it will take care of single/repetitive
// these 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_dst,// number of the current (unfinished ) line in this (compressor) channel
input [LAST_FRAME_BITS-1:0] frame_number_dst, // current frame number (for multi-frame ranges) in this (compressor channel
input frame_done_dst, // single-cycle pulse when the full frame (window) was transferred to/from DDR3 memory
// use as 'eot_real' in 353
output suspend // suspend reading data for this channel - waiting for the source data
);
// Control signals to be defined
wire frame_en; // if 0 - will reset logic immediately (but not page number)
wire frame_go; // start frame: if idle, will start reading data (if available),
wire frame_go=frame_en; // start frame: if idle, will start reading data (if available),
// if running - will not restart a new frame if 0.
wire [ 4:0] left_marg; // left margin (for not-yet-implemented) mono JPEG (8 lines tile row) can need 7 bits (mod 32 - tile)
wire [12:0] n_blocks_in_row_m1; // number of macroblocks in a macroblock row minus 1
wire [12:0] n_block_rows_m1; // number of macroblock rows in a frame minus 1
wire [CMPRS_FRMT_LMARG_BITS-1:0] left_marg; // left margin (for not-yet-implemented) mono JPEG (8 lines tile row) can need 7 bits (mod 32 - tile)
wire [CMPRS_FRMT_MBCM1_BITS-1:0] n_blocks_in_row_m1; // number of macroblocks in a macroblock row minus 1
wire [CMPRS_FRMT_MBRM1_BITS-1:0] n_block_rows_m1; // number of macroblock rows in a frame minus 1
wire ignore_color; // zero Cb/Cr components (TODO: maybe include into converter_type?)
wire [ 1:0] bayer_phase; // [1:0]) bayer color filter phase 0:(GR/BG), 1:(RG/GB), 2: (BG/GR), 3: (GB/RG)
wire four_blocks; // use only 6 blocks for the output, not 6
wire jp4_dc_improved; // in JP4 mode, compare DC coefficients to the same color ones
wire [ 1:0] tile_margin; // margins around 16x16 tiles (0/1/2)
wire [ 2:0] tile_shift; // tile shift from top left corner
// wire [ 1:0] tile_margin; // margins around 16x16 tiles (0/1/2)
// wire [ 2:0] tile_shift; // tile shift from top left corner
wire [ 2:0] converter_type; // 0 - color18, 1 - color20, 2 - mono, 3 - jp4, 4 - jp4-diff, 7 - mono8 (not yet implemented)
wire scale_diff; // divide differences by 2 (to fit in 8-bit range)
wire hdr; // second green absolute, not difference
wire subtract_dc_in; // subtract/restore DC components
wire [ 9:0] m_cb; // [9:0] scale for CB - default 0.564 (10'h90)
wire [ 9:0] m_cr; // [9:0] scale for CB - default 0.713 (10'hb6)
wire subtract_dc; // subtract/restore DC components
wire [CMPRS_CSAT_CB_BITS-1:0] m_cb; // [9:0] scale for CB - default 0.564 (10'h90)
wire [CMPRS_CSAT_CR_BITS-1:0] m_cr; // [9:0] scale for CR - default 0.713 (10'hb6)
reg [ 1:0] cmprs_fmode_this; // focusing/overlay mode
wire [ 1:0] cmprs_fmode; // focusing/overlay mode
//TODO: assign next 5 values from converter_type[2:0]
wire [ 5:0] mb_w_m1; // macroblock width minus 1 // 3 LSB not used, SHOULD BE SET to 3'b111
......@@ -140,7 +220,46 @@ module jp_channel#(
wire component_lastinmb; // last_r component in a macroblock;
// control signals valid @ mclk
wire cmprs_en_extend; // extend cmprs_en_xclk to include flushing
wire cmprs_en_mclk; // resets immediately
wire cmprs_run_mclk; // enable propagation of vsync_late to frame_start_dst in bonded(sync to src) mode
wire cmprs_standalone; // single-cycle: generate a single frame_start_dst in unbonded (not synchronized) mode. cmprs_run should be off
wire sigle_frame_buf; // input - memory controller uses a single frame buffer (frame_number_* == 0), use other sync
wire stuffer_done_mclk;
wire broken_frame; // @ mclk tried to start frame compression before the previous one was finished
wire last_block;
wire test_lbw;
wire stuffer_rdy; // receiver (bit stuffer) is ready to accept data;
wire [15:0] huff_do; // output[15:0] reg
wire [3:0] huff_dl; // output[3:0] reg
wire huff_dv; // output reg
wire flush; // output reg @ negedge xclk2x
wire force_flush; // @ negedge xclk2x
wire [31:0] cmd_data; // 32-bit data to write to tables and registers(LSB first) - from cmd_deser
wire cmd_we; // control register write enable
wire [2:0] cmd_a; // control register write enable
wire set_ctrl_reg_w;
wire set_status_w;
wire set_format_w;
wire set_color_saturation_w;
wire set_coring_w;
wire set_tables_w;
assign set_ctrl_reg_w = cmd_we && (cmd_a== CMPRS_CONTROL_REG);
assign set_status_w = cmd_we && (cmd_a== CMPRS_STATUS_CNTRL);
assign set_format_w = cmd_we && (cmd_a== CMPRS_FORMAT);
assign set_color_saturation_w = cmd_we && (cmd_a== CMPRS_COLOR_SATURATION);
assign set_coring_w = cmd_we && (cmd_a== CMPRS_CORING_MODE);
assign set_tables_w = cmd_we && ((cmd_a & 6)== CMPRS_TABLES);
// re-clock single-pulse broken_frame@mclk to force_flush@negedge xclk2x
pulse_cross_clock force_flush_i (.rst(rst), .src_clk(mclk), .dst_clk(~xclk2x), .in_pulse(broken_frame), .out_pulse(force_flush),.busy());
// set derived parameters from converter_type
......@@ -180,6 +299,156 @@ module jp_channel#(
.data_in (buf_wdata) // input[63:0]
);
cmd_deser #(
.ADDR (CMPRS_ADDR),
.ADDR_MASK (CMPRS_MASK),
.NUM_CYCLES (6),
.ADDR_WIDTH (3),
.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[3:0]
.data (cmd_data), // output[31:0]
.we (cmd_we) // output
);
status_generate #(
.STATUS_REG_ADDR (CMPRS_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
);
cmprs_cmd_decode #(
.CMPRS_CBIT_RUN (CMPRS_CBIT_RUN),
.CMPRS_CBIT_RUN_BITS (CMPRS_CBIT_RUN_BITS),
.CMPRS_CBIT_QBANK (CMPRS_CBIT_QBANK),
.CMPRS_CBIT_QBANK_BITS (CMPRS_CBIT_QBANK_BITS),
.CMPRS_CBIT_DCSUB (CMPRS_CBIT_DCSUB),
.CMPRS_CBIT_DCSUB_BITS (CMPRS_CBIT_DCSUB_BITS),
.CMPRS_CBIT_CMODE (CMPRS_CBIT_CMODE),
.CMPRS_CBIT_CMODE_BITS (CMPRS_CBIT_CMODE_BITS),
.CMPRS_CBIT_FRAMES (CMPRS_CBIT_FRAMES),
.CMPRS_CBIT_FRAMES_BITS (CMPRS_CBIT_FRAMES_BITS),
.CMPRS_CBIT_BAYER (CMPRS_CBIT_BAYER),
.CMPRS_CBIT_BAYER_BITS (CMPRS_CBIT_BAYER_BITS),
.CMPRS_CBIT_FOCUS (CMPRS_CBIT_FOCUS),
.CMPRS_CBIT_FOCUS_BITS (CMPRS_CBIT_FOCUS_BITS),
.CMPRS_CBIT_RUN_RST (CMPRS_CBIT_RUN_RST),
.CMPRS_CBIT_RUN_STANDALONE (CMPRS_CBIT_RUN_STANDALONE),
.CMPRS_CBIT_RUN_ENABLE (CMPRS_CBIT_RUN_ENABLE),
.CMPRS_CBIT_CMODE_JPEG18 (CMPRS_CBIT_CMODE_JPEG18),
.CMPRS_CBIT_CMODE_MONO6 (CMPRS_CBIT_CMODE_MONO6),
.CMPRS_CBIT_CMODE_JP46 (CMPRS_CBIT_CMODE_JP46),
.CMPRS_CBIT_CMODE_JP46DC (CMPRS_CBIT_CMODE_JP46DC),
.CMPRS_CBIT_CMODE_JPEG20 (CMPRS_CBIT_CMODE_JPEG20),
.CMPRS_CBIT_CMODE_JP4 (CMPRS_CBIT_CMODE_JP4),
.CMPRS_CBIT_CMODE_JP4DC (CMPRS_CBIT_CMODE_JP4DC),
.CMPRS_CBIT_CMODE_JP4DIFF (CMPRS_CBIT_CMODE_JP4DIFF),
.CMPRS_CBIT_CMODE_JP4DIFFHDR (CMPRS_CBIT_CMODE_JP4DIFFHDR),
.CMPRS_CBIT_CMODE_JP4DIFFDIV2 (CMPRS_CBIT_CMODE_JP4DIFFDIV2),
.CMPRS_CBIT_CMODE_JP4DIFFHDRDIV2 (CMPRS_CBIT_CMODE_JP4DIFFHDRDIV2),
.CMPRS_CBIT_CMODE_MONO1 (CMPRS_CBIT_CMODE_MONO1),
.CMPRS_CBIT_CMODE_MONO4 (CMPRS_CBIT_CMODE_MONO4),
.CMPRS_CBIT_FRAMES_SINGLE (CMPRS_CBIT_FRAMES_SINGLE),
.CMPRS_COLOR18 (CMPRS_COLOR18),
.CMPRS_COLOR20 (CMPRS_COLOR20),
.CMPRS_MONO16 (CMPRS_MONO16),
.CMPRS_JP4 (CMPRS_JP4),
.CMPRS_JP4DIFF (CMPRS_JP4DIFF),
.CMPRS_MONO8 (CMPRS_MONO8),
.CMPRS_FRMT_MBCM1 (CMPRS_FRMT_MBCM1),
.CMPRS_FRMT_MBCM1_BITS (CMPRS_FRMT_MBCM1_BITS),
.CMPRS_FRMT_MBRM1 (CMPRS_FRMT_MBRM1),
.CMPRS_FRMT_MBRM1_BITS (CMPRS_FRMT_MBRM1_BITS),
.CMPRS_FRMT_LMARG (CMPRS_FRMT_LMARG),
.CMPRS_FRMT_LMARG_BITS (CMPRS_FRMT_LMARG_BITS),
.CMPRS_CSAT_CB (CMPRS_CSAT_CB),
.CMPRS_CSAT_CB_BITS (CMPRS_CSAT_CB_BITS),
.CMPRS_CSAT_CR (CMPRS_CSAT_CR),
.CMPRS_CSAT_CR_BITS (CMPRS_CSAT_CR_BITS),
.CMPRS_CORING_BITS (CMPRS_CORING_BITS)
) cmprs_cmd_decode_i (
.rst (rst), // input
.xclk (xclk), // input - global clock input, compressor single clock rate
.mclk (mclk), // input - global system/memory clock
.ctrl_we (set_ctrl_reg_w), // input - control register write enable
.format_we (set_format_w), // input - write number of tiles and left margin
.color_sat_we (set_color_saturation_w), // input - write color saturation values
.coring_we (set_coring_w), // input - write color saturation values
.di (cmd_data), // input[31:0] - 32-bit data to write to control register (24LSB are used)
.frame_start (frame_start_dst), // input @mclk
.cmprs_en_mclk (cmprs_en_mclk), // output
.cmprs_en_extend (cmprs_en_extend), // input
.cmprs_run_mclk (cmprs_run_mclk), // output reg
.cmprs_standalone (cmprs_standalone), // output reg
.sigle_frame_buf (sigle_frame_buf), // output reg
.cmprs_en_xclk (frame_en), // output reg
.cmprs_qpage (cmprs_qpage), // output[2:0] reg
.cmprs_dcsub (subtract_dc), // output reg
.cmprs_fmode (cmprs_fmode), // output[1:0] reg
.bayer_shift (bayer_phase), // output[1:0] reg
.ignore_color (ignore_color), // output reg
.four_blocks (four_blocks), // output reg Not used?
.jp4_dc_improved (jp4_dc_improved), // output reg
.converter_type (converter_type), // output[2:0] reg
.scale_diff (scale_diff), // output reg
.hdr (hdr), // output reg
.left_marg (left_marg), // output[4:0] reg
.n_blocks_in_row_m1 (n_blocks_in_row_m1), // output[12:0] reg
.n_block_rows_m1 (n_block_rows_m1), // output[12:0] reg
.color_sat_cb (m_cb), // output[9:0] reg
.color_sat_cr (m_cr), // output[9:0] reg
.coring () // output[2:0] reg
);
cmprs_frame_sync #(
.FRAME_HEIGHT_BITS (FRAME_HEIGHT_BITS),
.LAST_FRAME_BITS (LAST_FRAME_BITS)
) cmprs_frame_sync_i (
.rst (rst), // input
.xclk (xclk), // input - global clock input, compressor single clock rate
.mclk (mclk), // input - global system/memory clock
.cmprs_en (cmprs_en_mclk), // input - @mclk 0 resets immediately
.cmprs_en_extend (cmprs_en_extend), // output
.cmprs_run (cmprs_run_mclk), // input - @mclk enable propagation of vsync_late to frame_start_dst in bonded(sync to src) mode
.cmprs_standalone (cmprs_standalone), // input - @mclk single-cycle: generate a single frame_start_dst in unbonded (not synchronized) mode.
// cmprs_run should be off
.sigle_frame_buf (sigle_frame_buf), // input - memory controller uses a single frame buffer (frame_number_* == 0), use other sync
.vsync_late (vsync_late), // input - @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
.frame_started (first_mb && mb_pre_start), // @xclk started first macroblock (checking fro broken frames)
.frame_start_dst (frame_start_dst), // output reg @mclk - trigger receive (tiled) memory channel (it will take care of
// single/repetitive modes itself this output either follows vsync_late (reclocks it)
// or generated in non-bonded mode (compress from memory once)
.line_unfinished_src(line_unfinished_src), // input[15:0] - number of the current (unfinished ) line, in the source (sensor) channel
.frame_number_src (frame_number_src), // input[15:0] - current frame number (for multi-frame ranges) in the source (sensor) channel
.frame_done_src (frame_done_src), // input - 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
.line_unfinished (line_unfinished_dst), // input[15:0] - number of the current (unfinished ) line in this (compressor) channel
.frame_number (frame_number_dst), // input[15:0] - current frame number (for multi-frame ranges) in this (compressor channel
.frame_done (frame_done_dst), // input - single-cycle pulse when the full frame (window) was transferred to/from DDR3 memory
.suspend (suspend), // output reg - suspend reading data for this channel - waiting for the source data
.broken_frame (broken_frame) // output reg - @ mclk tried to start frame compression before the previous one was finished
);
// 353's eot ~= broken_frame || frame_done_dst
cmprs_macroblock_buf_iface cmprs_macroblock_buf_iface_i (
.rst (rst), // input
.xclk (xclk), // input
......@@ -188,7 +457,7 @@ module jp_channel#(
.page_ready_chn (page_ready_chn), // input
.next_page_chn (next_page_chn), // output
.frame_en (frame_en), // input
.frame_go (frame_go), // input
.frame_go (frame_go), // input - do not use - assign to frame_en? Running frames can be controlled by other means
.left_marg (left_marg), // input[4:0]
.n_blocks_in_row_m1 (n_blocks_in_row_m1), // input[12:0]
.n_block_rows_m1 (n_block_rows_m1), // input[12:0]
......@@ -285,7 +554,7 @@ module jp_channel#(
.bayer_phase (bayer_phase), // input[1:0]
.jp4_dc_improved (jp4_dc_improved), // input
.hdr (hdr), // input
.subtract_dc_in (subtract_dc_in), // input
.subtract_dc_in (subtract_dc), // input
.first_mb_in (first_mb), // input - calculate in cmprs_macroblock_buf_iface
.last_mb_in (last_mb), // input - calculate in cmprs_macroblock_buf_iface
.yaddrw (yaddrw), // input[7:0]
......@@ -310,7 +579,7 @@ module jp_channel#(
wire dct_last_in;
wire dct_pre_first_out;
wire dct_dv;
// wire dct_dv;
wire [12:0] dct_out;
......@@ -335,13 +604,14 @@ module jp_channel#(
.xin (yc_nodc), // input[9:0]
.last_in (dct_last_in), // output reg output high during input of the last of 64 pixels in a 8x8 block //
.pre_first_out (dct_pre_first_out), // outpu 1 cycle ahead of the first output in a 64 block
.dv (dct_dv), // output data output valid. Will go high on the 94-th cycle after the start (now - on 95-th?)
// .dv (dct_dv), // output data output valid. Will go high on the 94-th cycle after the start (now - on 95-th?)
.dv (), // not used: output data output valid. Will go high on the 94-th cycle after the start (now - on 95-th?)
.d_out (dct_out) // output[12:0]
);
wire quant_start;
dly_16 #(.WIDTH(1)) i_quant_start (.clk(xclk),.rst(1'b0), .dly(0), .din(dct_pre_first_out), .dout(quant_start)); // dly=0+1
reg [ 2:0] cmprs_qpage_this;
reg [ 2:0] cmprs_qpage;
wire first_block_quant;
wire [12:0] quant_do;
wire quant_ds;
......@@ -360,9 +630,8 @@ module jp_channel#(
end
wire table_a_not_d; // writing table address /not data (a[0] from cmd_deser)
wire table_we; // writing to tables (decoded stb from cmd_deser)
wire [31:0] table_di; // 32-bit data to write to tables (LSB first) - from cmd_deser
// wire table_a_not_d; // writing table address /not data (a[0] from cmd_deser)
// wire table_we; // writing to tables (decoded stb from cmd_deser)
wire tser_a_not_d; // address/not data distributed to submodules
wire [ 7:0] tser_d; // byte-wide serialized tables address/data to submodules
wire tser_qe; // write serialized table data to quantizer
......@@ -375,9 +644,9 @@ module jp_channel#(
.ADDR_BITS(3)
) table_ad_transmit_i (
.clk (mclk), // input @posedge
.a_not_d_in (table_a_not_d), // input writing table address /not data (a[0] from cmd_deser)
.we (table_we), // input writing to tables (decoded stb from cmd_deser)
.din (table_di), // input[31:0] 32-bit data to serialize/write to tables (LSB first) - from cmd_deser
.a_not_d_in (cmd_a[0]), // input writing table address /not data (a[0] from cmd_deser)
.we (set_tables_w), // input writing to tables (decoded stb from cmd_deser)
.din (cmd_data), // input[31:0] 32-bit data to serialize/write to tables (LSB first) - from cmd_deser
.ser_d (tser_d), // output[7:0] byte-wide serialized tables address/data to submodules
.a_not_d (tser_a_not_d), // output reg address/not data distributed to submodules
.chn_en ({tser_he,tser_fe,tser_ce,tser_qe}) // output[0:0] reg - table 1-hot select outputs
......@@ -397,7 +666,7 @@ module jp_channel#(
.dci (yc_avr), // input[8:0] - average value in a block - subtracted before DCT. now normal signed number
.first_stb (first_block_color), // input - this is first stb pulse in a frame
.stb (dct_start), // input - strobe that writes ctypei, dci
.tsi (cmprs_qpage_this[2:0]), // input[2:0] - table (quality) select [2:0]
.tsi (cmprs_qpage[2:0]), // input[2:0] - table (quality) select [2:0]
.pre_start (dct_pre_first_out), // input - marks first input pixel (one before)
.first_in (first_block_dct), // input - first block in (valid @ start)
.first_out (first_block_quant), // output reg - valid @ ds
......@@ -431,7 +700,7 @@ module jp_channel#(
.tser_a_not_d (tser_a_not_d), // input - address/not data to tables
.tser_d (tser_d), // input[7:0] - byte-wide data to tables
.mode (cmprs_fmode_this[1:0]), // input[1:0] focus mode (combine image with focus info) - 0 - none, 1 - replace, 2 - combine all, 3 - combine woi
.mode (cmprs_fmode[1:0]), // input[1:0] focus mode (combine image with focus info) - 0 - none, 1 - replace, 2 - combine all, 3 - combine woi
.firsti (color_first), // input first macroblock
.lasti (color_last), // input last macroblock
.tni (color_tn[2:0]), // input[2:0] block number in a macronblock - 0..3 - Y, >=4 - color (sync to stb)
......@@ -484,13 +753,6 @@ module jp_channel#(
.dv (enc_dv) // output reg
);
wire last_block;
wire test_lbw;
wire stuffer_rdy; // receiver (bit stuffer) is ready to accept data;
wire [15:0] huff_do; // output[15:0] reg
wire [3:0] huff_dl; // output[3:0] reg
wire huff_dv; // output reg
wire flush; // output reg
huffman393 i_huffman (
.xclk (xclk), // input
......@@ -560,6 +822,7 @@ module jp_channel#(
.color_first(color_first), // input
.sec(sec[31:0]), // input[31:0]
.usec(usec[19:0]), // input[19:0]
// outputs valid @negedge xclk2x
.rdy(stuffer_rdy), // output - enable huffman encoder to proceed. Used as CE for many huffman encoder registers
.q(stuffer_do), // output[15:0] reg - output data
.qv(stuffer_dv), // output reg - output data valid
......@@ -573,98 +836,8 @@ module jp_channel#(
`endif
);
/*
stuffer i_stuffer (.clk(clk2x), //clock - uses negedge inside
.en(cmprs_en_2x_n), // enable, 0- reset
.reset_data_counters(reset_data_counters[1]), // reset data transfer counters (only when DMA and compressor are disabled)
.flush(flush || force_flush), // flush output data (fill byte with 0, long word with FFs
.stb(huff_dv), // input data strobe
.dl(huff_dl), // [3:0] number of bits to send (0 - 16)
.d(huff_do), // [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
.color_first(color_first), //
.sec(sec[31:0]),
.usec(usec[19:0]),
.rdy(stuffer_rdy), // enable huffman encoder to proceed. Used as CE for many huffman encoder registers
.q(stuffer_do), // [15:0] output data
.qv(stuffer_dv), // output data valid
.done(stuffer_done),
.imgptr (imgptr[23:0]), // [23:0]image pointer in 32-byte chunks
.flushing(stuffer_flushing)
`ifdef debug_stuffer
,.etrax_dma_r(tst_stuf_etrax[3:0]) // [3:0] just for testing
,.test_cntr(test_cntr[3:0])
,.test_cntr1(test_cntr1[7:0])
`endif
);
dcc_sync i_dcc_sync(//.clk(clk),
.sclk(clk2x),
.dcc_en(dcc_en), // clk rising, sync with start of the frame
.finish_dcc(finish_dcc), // sclk rising
.dcc_vld(dccvld), // clk rising
.dcc_data(dccdata[15:0]), //[15:0] clk risimg
.statistics_dv(statistics_dv), //sclk
.statistics_do(statistics_do[15:0])//[15:0] sclk
);
//TODO: compact table
focus_sharp i_focus_sharp(.clk(clk), // pixel clock
.en(cmprs_en), // enable (0 resets counter)
.sclk(clk2x), // system clock, twe, ta,tdi - valid @negedge (ra, tdi - 2 cycles ahead
.twe(twfe), // enable write to a table
.ta(ta[9:0]), // [9:0] table address
.tdi(di[15:0]), // [15:0] table data in (8 LSBs - quantization data)
.mode(cmprs_fmode_this[1:0]), // focus mode (combine image with focus info) - 0 - none, 1 - replace, 2 - combine all, 3 - combine woi
// .stren(focus_strength),
.firsti(color_first), // first macroblock
.lasti(color_last), // last macroblock
.tni(color_tn[2:0]), // block number in a macronblock - 0..3 - Y, >=4 - color (sync to stb)
.stb(dct_start), // strobe that writes ctypei, dci
.start(quant_start),// marks first input pixel (needs 1 cycle delay from previous DCT stage)
.di(dct_out[12:0]), // [11:0] pixel data in (signed)
.quant_ds(quant_ds), // quantizator data strobe (1 before DC)
.quant_d(quant_do[12:0]), // quantizator data output
.quant_dc_tdo(quant_dc_tdo[15:0]), //[15:0], MSB aligned coefficient for the DC component (used in focus module)
// .quant_dc_tdo_stb(quant_dc_tdo_stb),
.do(focus_do[12:0]), // [11:0] pixel data out (AC is only 9 bits long?) - changed to 10
.ds(focus_ds), // data out strobe (one ahead of the start of dv)
.hifreq(hifreq[31:0]) //[31:0]) // accumulated high frequency components in a frame sub-window
);
xdct i_xdct ( .clk(clk), // top level module
.en(cmprs_en), // if zero will reset transpose memory page numbers
.start(dct_start), // single-cycle start pulse that goes with the first pixel data. Other 63 should follow
.xin(color_d[9:0]), // [7:0] - input data
.last_in(dct_last_in), // output high during input of the last of 64 pixels in a 8x8 block //
.pre_first_out(dct_pre_first_out),// 1 cycle ahead of the first output in a 64 block
.dv(dct_dv), // data output valid. Will go high on the 94-th cycle after the start
.d_out(dct_out[12:0]));// [12:0]output data
// probably dcc things are not needed anymore
always @ (posedge clk) quant_start <= dct_pre_first_out;
always @ (posedge clk) begin
if (!dccout) dcc_en <=1'b0;
else if (dct_start && color_first && (color_tn[2:0]==3'b001)) dcc_en <=1'b1; // 3'b001 - closer to the first "start" in quantizator
end
wire [15:0] quant_dc_tdo;// MSB aligned coefficient for the DC component (used in focus module)
wire [2:0] coring_num;
FDE_1 i_coring_num0 (.C(clk2x),.CE(wr_quantizer_mode),.D(di[ 0]),.Q(coring_num[0]));
FDE_1 i_coring_num1 (.C(clk2x),.CE(wr_quantizer_mode),.D(di[ 1]),.Q(coring_num[1]));
FDE_1 i_coring_num2 (.C(clk2x),.CE(wr_quantizer_mode),.D(di[ 2]),.Q(coring_num[2]));
pulse_cross_clock stuffer_done_mclk_i (.rst(rst), .src_clk(~xclk2x), .dst_clk(mclk), .in_pulse(stuffer_done), .out_pulse(stuffer_done_mclk),.busy());
*/
endmodule
......@@ -35,7 +35,11 @@
// 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
......@@ -51,9 +55,10 @@ module stuffer393 (
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 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
......
......@@ -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
......
......@@ -166,6 +166,7 @@ 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 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
......
......@@ -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
......@@ -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;
......@@ -281,6 +288,10 @@ module mcntrl_tiled_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);
......@@ -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),
......@@ -716,18 +720,21 @@ BUFG bufg_axi_aclk_i (.O(axi_aclk),.I(fclk[0]));
.page_ready_chn2 (page_ready_chn2), // output
.frame_done_chn2 (frame_done_chn2), // output
.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