/******************************************************************************* * Module: jp_channel * Date:2015-06-10 * Author: Andrey Filippov * Description: Top module of JPEG/JP4 compressor channel * * Copyright (c) 2015 Elphel, Inc. * jp_channel.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. * * jp_channel.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 . *******************************************************************************/ `timescale 1ns/1ps module jp_channel#( parameter CMPRS_NUMBER = 0, parameter CMPRS_GROUP_ADDR = 'h600, parameter CMPRS_BASE_INC = 'h10, parameter CMPRS_STATUS_REG_BASE= 'h10, parameter CMPRS_HIFREQ_REG_BASE= 'h14, parameter CMPRS_STATUS_REG_INC= 1, parameter CMPRS_HIFREQ_REG_INC= 1, parameter CMPRS_MASK= 'h7f8, 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(data)..7(address) parameter TABLE_QUANTIZATION_INDEX = 0, parameter TABLE_CORING_INDEX = 1, parameter TABLE_FOCUS_INDEX = 2, parameter TABLE_HUFFMAN_INDEX = 3, 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_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 parameter CMPRS_TIMEOUT_BITS= 12, parameter CMPRS_TIMEOUT= 1000 // mclk cycles `ifdef DEBUG_RING ,parameter DEBUG_CMD_LATENCY = 2 //SuppressThisWarning VEditor - not used `endif )( // input rst, // global reset input xclk, // global clock input, compressor single clock rate input xclk2x, // global clock input, compressor double clock rate, nominally rising edge aligned input mrst, // @posedge mclk, sync reset input xrst, // @posedge xclk, sync reset input hrst, // @posedge xclk, sync reset // programming interface 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) // Buffer interface (buffer to be a part of the memory controller - it is connected there by a 64-bit data, here - by an 9-bit one input xfer_reset_page_rd, // from mcntrl_tiled_rw ( input buf_wpage_nxt, // advance to next page memory interface writes to input buf_we, // @!mclk write buffer from memory, increment write input [63:0] buf_din, // data out // output [11:0] buf_ra, // output buf_ren, // output buf_regen, // input [ 7:0] buf_di, input page_ready_chn, // single mclk (posedge) output next_page_chn, // single mclk (posedge): Done with the page in the buffer, memory controller may read more data // Master(sensor)/slave(compressor) synchronization signals 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 // statistics data was not used in late nc353 input dccout, //enable output of DC and HF components for brightness/color/focus adjustments input [2:0] hfc_sel, // [2:0] (for autofocus) only components with both spacial frequencies higher than specified will be added output statistics_dv, output [15:0] statistics_do, // Timestamp messages (@mclk) input ts_pre_stb, // @mclk - 1 cycle before receiving 8 bytes of timestamp data input [7:0] ts_data, // timestamp data (s0,s1,s2,s3,us0,us1,us2,us3==0) output eof_written_mclk, output stuffer_done_mclk, // output [31:0] hifreq, // accumulated high frequency components in a frame sub-window input vsync_late, // delayed start of frame, @mclk. 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 interface to the AFI mux input hclk, input fifo_rst, // reset FIFO (set read address to write, reset count) input fifo_ren, output [63:0] fifo_rdata, output fifo_eof, // single rclk pulse signalling EOF input eof_written, // confirm frame written ofer AFI to the system memory (single rclk pulse) output fifo_flush, // EOF, need to output all what is in FIFO (Stays active until enough data chunks are read) output flush_hclk, // output before writing last chunk - use it to suspend AFI to have // last burst marked as the last one (otherwise last may be empty if frame had %4==0 chunks) output [7:0] fifo_count // number of 32-byte chunks in FIFO `ifdef DEBUG_RING ,output debug_do, // output to the debug ring input debug_sl, // 0 - idle, (1,0) - shift, (1,1) - load // SuppressThisWarning VEditor - not used input debug_di // input from the debug ring `endif ); //`ifdef DEBUG_RING // assign debug_do = debug_di; // just temporarily to short-circuit the ring //`endif localparam CMPRS_ADDR = CMPRS_GROUP_ADDR + CMPRS_NUMBER * CMPRS_BASE_INC; localparam CMPRS_STATUS_REG_ADDR = CMPRS_STATUS_REG_BASE + CMPRS_NUMBER * CMPRS_STATUS_REG_INC; localparam CMPRS_HIFREQ_REG_ADDR = CMPRS_HIFREQ_REG_BASE + CMPRS_NUMBER * CMPRS_HIFREQ_REG_INC; wire [31:0] hifreq; // accumulated high frequency components in a frame sub-window was output, now - with status // Control signals to be defined wire frame_en; // if 0 - will reset logic immediately (but not page number) wire frame_start_xclk; // re-clocked, parameters are copied at this pulse wire stuffer_en; // extended enable to allow stuffer to gracefully finish 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 [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 [ 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; // 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) 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 wire [ 5:0] mb_h_m1; // macroblock height -1 wire [ 4:0] mb_hper; // macroblock horizontal period (8/16) // 3 LSB not used wire [ 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 wire tile_col_width; // 0 - 16 pixels, 1 -32 pixels // signals connecting modules: cmprs_macroblock_buf_iface_i and cmprs_pixel_buf_iface_i: wire mb_pre_end; // from cmprs_pixel_buf_iface - just in time to start a new macroblock w/o gaps wire mb_release_buf; // send required "next_page" pulses to buffer. Having rather long minimal latency in the memory // controller this can just be the same as mb_pre_end_in wire mb_pre_start; // 1 clock cycle before stream of addresses to the buffer wire [ 1:0] start_page; // page to read next tile from (or first of several pages) wire [ 6:0] macroblock_x; // macroblock left pixel x relative to a tile (page) Maximal page - 128 bytes wide // signals connecting modules: cmprs_macroblock_buf_iface_i and cmprs_buf_average: wire first_mb; // output reg wire last_mb; // output // signals connecting modules: cmprs_pixel_buf_iface_i and chn_rd_buf_i: // wire [ 7:0] buf_di; // data from the buffer // wire [11:0] buf_ra; // buffer read address (2 MSB - page number) wire [ 1:0] buf_rd; // buf {regen, re} wire [ 7:0] buf_pxd; // 8-bit pixel data from the memory buffer wire [11:0] buf_ra; // Memory buffer read address // signals connecting modules: chn_rd_buf_i and ???: wire [ 7:0] mb_data_out; // Macroblock data out in scanline order wire mb_pre_first_out; // Macroblock data out strobe - 1 cycle just before data valid // wire mb_data_valid; // Macroblock data out valid wire limit_diff = 1'b1; // as in the prototype - just a constant 1 // signals connecting modules: csconvert and cmprs_buf_average: wire [8:0] signed_y; // was y_in wire [8:0] signed_c; // was c_in wire [7:0] yaddrw; wire ywe; wire [7:0] caddrw; wire cwe; wire yc_pre_first_out; // pre first output from color converter (was pre_first_out) - last cycle of writing (may inc wpage // How they are used? Can it be average instead? wire [7:0] n000; // number of all 0 in macroblock (255 for 256), valid only for color JPEG wire [7:0] n255; // number of all 255 in macroblock (255 for 256), valid only for color JPEG // signals connecting modules: cmprs_buf_average and ???: wire [ 9:0] yc_nodc; // [9:0] data out (4:2:0) (signed, average=0) wire [ 8:0] yc_avr; // [8:0] DC (average value) - RAM output, no register. For Y components 9'h080..9'h07f, for C - 9'h100..9'h0ff! // wire yc_nodc_dv; // out data valid (will go high for at least 64 cycles) wire dct_start; // single-cycle mark of the first_r pixel in a 64 (8x8) - pixel block wire [ 2:0] color_tn; // [2:0] tile number 0..3 - Y, 4 - Cb, 5 - Cr (valid with start) wire color_first; // sending first_r MCU (valid @ ds) wire color_last; // sending last_r MCU (valid @ ds) // below signals valid at ds ( 1 later than tn, first_r, last_r) wire [2:0] component_num; //[2:0] - component number (YCbCr: 0 - Y, 1 - Cb, 2 - Cr, JP4: 0-1-2-3 in sequence (depends on shift) 4 - don't use wire component_color; // use color quantization table (YCbCR, jp4diff) wire component_first; // first this component in a frame (DC absolute, otherwise - difference to previous) 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 force_flush_long; /// wire enc_last; not used wire [15:0] enc_do; wire enc_dv; //TODO: use next signals for status // wire eof_written_mclk; // wire stuffer_done_mclk; wire stuffer_running_mclk; wire reading_frame; /// wire last_block; //huffman393 /// 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 last_block; // @negedge xxlk2x - used to copy timestamp in stuffer 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; wire stuffer_running; // @negedge xclk2x from registering timestamp until done wire [12:0] quant_do; wire quant_ds; wire [15:0] quant_dc_tdo;// MSB aligned coefficient for the DC component (used in focus module) wire [ 2:0] cmprs_qpage; wire [ 2:0] coring_num; reg dcc_en; wire [15:0] dccdata; // was not used in late nc353 wire dccvld; // was not used in late nc353 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); // assign buf_ren = buf_rd[0]; // assign buf_regen = buf_rd[1]; `ifdef DEBUG_RING reg [31:0] debug_fifo_in; reg [31:0] debug_fifo_out; reg [15:0] pre_start_cntr; reg [15:0] pre_end_cntr; reg debug_frame_done; reg [15:0] pages_requested; reg [15:0] pages_got; wire [1:0] dbg_add_invalid; wire dbg_mb_release_buf; reg [15:0] pages_needed; // count number requested reg [15:0] page_requests; // count regardless of how many requested reg dbg_stuffer_ext_running; reg dbg_reset_fifo; wire [3:0] etrax_dma; wire dbg_ts_rstb; // output wire [7:0] dbg_ts_dout; //output [7:0] wire [31:0] dbg_sec; wire [31:0] dbg_usec; wire dbg_flushing; reg dbg_flush_hclk; reg dbg_en_hclk; reg dbg_en_n2x; reg dbg_last_block_persist; wire dbg_test_lbw; wire dbg_gotLastBlock; wire dbg_frame_start_hclk; wire dbg_last_DCAC; reg dbg_gotLastBlock_persist; reg dbg_lastBlock_sent; wire dbg_fifo_or_full; wire dbg_comp_lastinmbo; wire [2:0] dbg_block_mem_ra; reg [15:0] dbg_stb_cntr; reg [15:0] dbg_zds_cntr; wire [2:0] dbg_block_mem_wa; wire [2:0] dbg_block_mem_wa_save; timestamp_to_parallel dbg_timestamp_to_parallel_i ( .clk (~xclk2x), // input .pre_stb (dbg_ts_rstb), // input .tdata (dbg_ts_dout), // input[7:0] .sec (dbg_sec), // output[31:0] reg .usec (dbg_usec), // output[19:0] reg .done() // output ); // cmprs_standalone - use to reset flush always @ (posedge ~xclk2x) begin dbg_reset_fifo <= fifo_rst; if (xrst2xn || dbg_reset_fifo) debug_fifo_in <= 0; else if (stuffer_dv) debug_fifo_in <= debug_fifo_in + 1; dbg_en_n2x <= stuffer_en; if (!dbg_en_n2x) dbg_last_block_persist <= 0; else if (last_block) dbg_last_block_persist <= 1; if (!dbg_en_n2x) dbg_gotLastBlock_persist <= 0; else if (dbg_gotLastBlock) dbg_gotLastBlock_persist <= 1; //dbg_last_block_persist end always @ (posedge hclk) begin if (hrst) debug_fifo_out <= 0; else if (fifo_rst) debug_fifo_out <= 0; // debug_fifo_in >> 2; else if (fifo_ren) debug_fifo_out <= debug_fifo_out + 1; dbg_en_hclk <= cmprs_en_mclk; if (!dbg_en_hclk || dbg_frame_start_hclk) dbg_flush_hclk <= 0; else if (flush_hclk) dbg_flush_hclk <= 1; end always @ (posedge mclk) begin if (!cmprs_en_mclk) pages_requested <= 0; else if (next_page_chn) pages_requested <= pages_requested + 1; if (!cmprs_en_mclk) pages_got <= 0; else if (page_ready_chn) pages_got <= pages_got + 1; if (!cmprs_en_mclk) debug_frame_done <= 0; else if (frame_done_dst) debug_frame_done <= 1; if (!cmprs_en_mclk || stuffer_done_mclk) dbg_stuffer_ext_running <= 0; else if (stuffer_running_mclk) dbg_stuffer_ext_running <= 1; end always @ (posedge xclk) begin if (!frame_en) pre_start_cntr <= 0; else if (mb_pre_start) pre_start_cntr <= pre_start_cntr + 1; if (!frame_en) pre_end_cntr <= 0; else if (mb_pre_end) pre_end_cntr <= pre_end_cntr + 1; if (!frame_en) pages_needed <= 0; else if (dbg_mb_release_buf) pages_needed <= pages_needed + {14'b0,dbg_add_invalid}; if (!frame_en) page_requests <= 0; else if (dbg_mb_release_buf) page_requests <= page_requests + 1; if (!frame_en) dbg_lastBlock_sent <= 0; else if (enc_dv && enc_do[15] && enc_do[14] && enc_do[12] ) dbg_lastBlock_sent <= 1; // else if enc_do[15:0] if (!frame_en) dbg_stb_cntr <= 0; else if (dct_start) dbg_stb_cntr <= dbg_stb_cntr + 1; if (!frame_en) dbg_zds_cntr <= 0; else if (focus_ds) dbg_zds_cntr <= dbg_zds_cntr + 1; end //frame_start_dst debug_slave #( .SHIFT_WIDTH (384), .READ_WIDTH (384), .WRITE_WIDTH (32), .DEBUG_CMD_LATENCY (DEBUG_CMD_LATENCY) ) debug_slave_i ( .mclk (mclk), // input .mrst (mrst), // input .debug_di (debug_di), // input .debug_sl (debug_sl), // input .debug_do (debug_do), // output .rd_data ({ dbg_usec, dbg_sec, 26'h0, dbg_block_mem_wa_save[2:0],dbg_block_mem_wa[2:0], dbg_zds_cntr[15:0], dbg_stb_cntr[15:0], pages_needed[15:0], page_requests[15:0], pre_end_cntr[15:0], pre_start_cntr[15:0], pages_got[15:0], pages_requested[15:0], dbg_comp_lastinmbo, dbg_block_mem_ra[2:0], debug_fifo_out[27:0], debug_fifo_in[31:0], color_last, dbg_last_block_persist, dbg_gotLastBlock, dbg_test_lbw, last_block, dbg_flush_hclk, dbg_flushing, stuffer_rdy, etrax_dma[3:0], dbg_stuffer_ext_running, stuffer_running_mclk, debug_frame_done, reading_frame, fifo_count[7:0], 2'b0, dbg_fifo_or_full, dbg_gotLastBlock_persist, dbg_lastBlock_sent, dbg_last_DCAC, sigle_frame_buf, suspend, frame_number_dst[15:0], line_unfinished_dst[15:0], frame_number_src[15:0], line_unfinished_src[15:0] }), // input[31:0] .wr_data (), // output[31:0] - not used .stb () // output - not used ); // wire [2:0] dbg_block_mem_wa; // wire [2:0] dbg_block_mem_wa_save; pulse_cross_clock dbg_fs_hclk_i ( .rst (!cmprs_en_mclk), .src_clk (mclk), .dst_clk (hclk), .in_pulse (frame_start_dst), .out_pulse (dbg_frame_start_hclk), .busy ()); `endif cmd_deser #( .ADDR (CMPRS_ADDR), .ADDR_MASK (CMPRS_MASK), .NUM_CYCLES (6), .ADDR_WIDTH (3), .DATA_WIDTH (32) ) cmd_deser_32bit_i ( .rst (1'b0), //rst), // input .clk (mclk), // input .srst (mrst), // 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 ); wire [2:0] status_data; cmprs_status cmprs_status_i ( .mclk (mclk), // input .eof_written (eof_written_mclk), // input .stuffer_running (stuffer_running_mclk), // input .reading_frame (reading_frame), // input .status (status_data) // output[2:0] ); status_generate #( .STATUS_REG_ADDR (CMPRS_STATUS_REG_ADDR), .PAYLOAD_BITS (3), .EXTRA_WORDS (1), .EXTRA_REG_ADDR (CMPRS_HIFREQ_REG_ADDR) ) status_generate_i ( .rst (1'b0), //rst), // input .clk (mclk), // input .srst (mrst), // input .we (set_status_w), // input .wd (cmd_data[7:0]), // input[7:0] .status ({hifreq,status_data}), // input[2:0] .ad (status_ad), // output[7:0] .rq (status_rq), // output .start (status_start) // input ); //hifreq // Port buffer - TODO: Move to memory controller mcntrl_buf_rd #( .LOG2WIDTH_RD(3) // 64 bit external interface ) chn_rd_buf_i ( .ext_clk (xclk), // input .ext_raddr (buf_ra), // input[11:0] .ext_rd (buf_rd[0]), // input .ext_regen (buf_rd[1]), // input .ext_data_out (buf_pxd), // output[7:0] .wclk (!mclk), // input .wpage_in (2'b0), // input[1:0] .wpage_set (xfer_reset_page_rd), // input TODO: Generate @ negedge mclk on frame start .page_next (buf_wpage_nxt), // input .page (), // output[1:0] .we (buf_we), // input .data_in (buf_din) // input[63:0] ); 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 .mrst (mrst), // input .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 .frame_start_xclk (frame_start_xclk), // re-clocked, parameters are copied during this pulse .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_en_late_xclk (stuffer_en), // output reg - extended enable to allow stuffer to gracefully finish .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? .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 (coring_num) // output[2:0] reg ); // set derived parameters from converter_type // wire [ 2:0] converter_type; // 0 - color18, 1 - color20, 2 - mono, 3 - jp4, 4 - jp4-diff, 7 - mono8 (not yet implemented) cmprs_tile_mode_decode #( // fully combinatorial .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_tile_mode_decode_i ( .converter_type (converter_type), // input[2:0] .mb_w_m1 (mb_w_m1), // output[5:0] reg .mb_h_m1 (mb_h_m1), // output[5:0] reg .mb_hper (mb_hper), // output[4:0] reg .tile_width (tile_width), // output[1:0] reg .tile_col_width (tile_col_width) // output reg ); cmprs_frame_sync #( .FRAME_HEIGHT_BITS (FRAME_HEIGHT_BITS), .LAST_FRAME_BITS (LAST_FRAME_BITS), .CMPRS_TIMEOUT_BITS (CMPRS_TIMEOUT_BITS), .CMPRS_TIMEOUT (CMPRS_TIMEOUT) ) cmprs_frame_sync_i ( // .rst (rst), // input .xclk (xclk), // input - global clock input, compressor single clock rate .mclk (mclk), // input - global system/memory clock .mrst (mrst), // input .xrst (xrst), // input .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 - @mclk 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 for 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 .stuffer_running (stuffer_running), // input .force_flush_long (force_flush_long), // output reg - @ mclk tried to start frame compression before the previous one was finished .stuffer_running_mclk(stuffer_running_mclk), // output .reading_frame (reading_frame) // output ); cmprs_macroblock_buf_iface cmprs_macroblock_buf_iface_i ( // .rst (rst), // input .xclk (xclk), // input .mclk (mclk), // input .mrst (mrst), // input .xrst (xrst), // input .xfer_reset_page_rd (xfer_reset_page_rd), // input .page_ready_chn (page_ready_chn), // input .next_page_chn (next_page_chn), // output .frame_en (frame_en), // input .frame_start_xclk (frame_start_xclk), // input@posedge xclk - parameters are copied @ this pulse .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] .mb_w_m1 (mb_w_m1), // input[5:0] // macroblock width minus 1 // 3 LSB not used here .mb_hper (mb_hper), // input[4:0] // macroblock horizontal period (8/16) // 3 LSB not used (set them 0) .tile_width (tile_width), // input[1:0] // memory tile width. Can be 32/64/128: 0 - 16, 1 - 32, 2 - 64, 3 - 128 .mb_pre_end_in (mb_pre_end), // input .mb_release_buf (mb_release_buf), // input .mb_pre_start_out (mb_pre_start), // output .start_page (start_page), // output[1:0] .macroblock_x (macroblock_x), // output[6:0] .first_mb (first_mb), // output reg .last_mb (last_mb) // output `ifdef DEBUG_RING ,.dbg_add_invalid (dbg_add_invalid), .dbg_mb_release_buf (dbg_mb_release_buf) `endif ); cmprs_pixel_buf_iface #( .CMPRS_PREEND_EARLY (6), // TODO:Check / Adjust .CMPRS_RELEASE_EARLY (16), .CMPRS_BUF_EXTRA_LATENCY (0), .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_pixel_buf_iface_i ( .xclk (xclk), // input .frame_en (frame_en), // input .buf_di (buf_pxd), // input[7:0] .buf_ra (buf_ra), // output[11:0] .buf_rd (buf_rd), // output[1:0] .converter_type (converter_type), // input[2:0] .mb_w_m1 (mb_w_m1), // input[5:0] .mb_h_m1 (mb_h_m1), // input[5:0] .tile_width (tile_width), // input[1:0] .tile_col_width (tile_col_width), // input .mb_pre_end (mb_pre_end), // output .mb_release_buf (mb_release_buf), // output .mb_pre_start (mb_pre_start), // input .start_page (start_page), // input[1:0] .macroblock_x (macroblock_x), // input[6:0] .data_out (mb_data_out), // output[7:0] // Macroblock data out in scanline order .pre_first_out (mb_pre_first_out), // output // Macroblock data out strobe - 1 cycle just before data valid == old pre_first_pixel? // .data_valid (mb_data_valid) // output // Macroblock data out valid .data_valid () // output // Macroblock data out valid Unused ); csconvert #( .CMPRS_COLOR18 (CMPRS_COLOR18), .CMPRS_COLOR20 (CMPRS_COLOR20), .CMPRS_MONO16 (CMPRS_MONO16), .CMPRS_JP4 (CMPRS_JP4), .CMPRS_JP4DIFF (CMPRS_JP4DIFF), .CMPRS_MONO8 (CMPRS_MONO8) ) csconvert_i ( .xclk (xclk), // input .frame_en (frame_en), // input .converter_type (converter_type), // input[2:0] .ignore_color (ignore_color), // input .scale_diff (scale_diff), // input .hdr (hdr), // input .limit_diff (limit_diff), // input .m_cb (m_cb), // input[9:0] .m_cr (m_cr), // input[9:0] .mb_din (mb_data_out), // input[7:0] .bayer_phase (bayer_phase), // input[1:0] .pre_first_in (mb_pre_first_out), // input .signed_y (signed_y), // output[8:0] reg .signed_c (signed_c), // output[8:0] reg .yaddrw (yaddrw), // output[7:0] reg .ywe (ywe), // output reg .caddrw (caddrw), // output[7:0] reg .cwe (cwe), // output reg .pre_first_out (yc_pre_first_out), // output reg .n000 (n000), // output[7:0] reg .n255 (n255) // output[7:0] reg ); cmprs_buf_average #( .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_buf_average_i ( .xclk (xclk), // input .frame_en (frame_en), // input .converter_type (converter_type), // input[2:0] .pre_first_in (mb_pre_first_out), // input .yc_pre_first_out (yc_pre_first_out), // input .bayer_phase (bayer_phase), // input[1:0] .jp4_dc_improved (jp4_dc_improved), // input .hdr (hdr), // 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] .ywe (ywe), // input .signed_y (signed_y), // input[8:0] .caddrw (caddrw), // input[7:0] .cwe (cwe), // input .signed_c (signed_c), // input[8:0] .do (yc_nodc), // output[9:0] .avr (yc_avr), // output[8:0] // .dv (yc_nodc_dv), // output .dv (), // output unused? .ds (dct_start), // output .tn (color_tn), // output[2:0] .first (color_first), // output reg .last (color_last), // output reg .component_num (component_num), // output[2:0] .component_color (component_color), // output .component_first (component_first), // output .component_lastinmb (component_lastinmb)// output reg ); // wire [ 9:0] yc_nodc; // [9:0] data out (4:2:0) (signed, average=0) ///TODO: Replace always@ with a module? wire dct_last_in; wire dct_pre_first_out; // wire dct_dv; wire [12:0] dct_out; //propagation of first block through compressor pipeline wire first_block_color=(color_tn[2:0]==3'h0) && color_first; // while color conversion, reg first_block_color_after; // after color conversion, reg first_block_dct; // after DCT wire first_block_quant; // after quantizer always @ (posedge xclk) begin if (dct_start) first_block_color_after <= first_block_color; if (dct_last_in) first_block_dct <= first_block_color_after; end xdct393 xdct393_i ( .clk (xclk), // input .en (frame_en), // input if zero will reset transpose memory page numbers .start (dct_start), // input single-cycle start pulse that goes with the first pixel data. Other 63 should follow .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 (), // 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(4'd0), .din(dct_pre_first_out), .dout(quant_start)); // dly=0+1 always @ (posedge xclk) 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 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 [ 3:0] tser_sel; // vector of individual table selects (decoded from the 8 MSBs of the table address) wire tser_qe = tser_sel[TABLE_QUANTIZATION_INDEX]; // write serialized table data to quantizer wire tser_ce = tser_sel[TABLE_CORING_INDEX]; // write serialized table data to coring wire tser_fe = tser_sel[TABLE_FOCUS_INDEX]; // write serialized table data to focusing wire tser_he = tser_sel[TABLE_HUFFMAN_INDEX]; // write serialized table data to Huffman //{tser_he,tser_fe,tser_ce,tser_qe} // As all commands are 32-bit data, all 4 bytes will be written to a designated table (usually 2 of 16-bit writes) table_ad_transmit #( .NUM_CHANNELS(4), .ADDR_BITS(3) ) table_ad_transmit_i ( .clk (mclk), // input @posedge .srst (mrst), // @posedge mclk .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 .chn_en (tser_sel) // output[0:0] reg - table 1-hot select outputs ); quantizer393 quantizer393_i ( .clk (xclk), // input .en (frame_en), // input .mclk (mclk), // input system clock, twqe, twce, ta,tdi - valid @posedge (ra, tdi - 2 cycles ahead (was negedge) .tser_qe (tser_qe), // input - write to a quantization table .tser_ce (tser_ce), // input - write to a coring table .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 .ctypei (component_color), // input component type input (Y/C) .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[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 .di (dct_out[12:0]), // input[12:0] - pixel data in (signed) .do (quant_do[12:0]), // output[12:0] - pixel data out (AC is only 9 bits long?) - changed to 10 .dv (), // output reg - data out valid .ds (quant_ds), // output reg - data out strobe (one ahead of the start of dv) .dc_tdo (quant_dc_tdo[15:0]), // output[15:0] reg - MSB aligned coefficient for the DC component (used in focus module) .dcc_en (dcc_en), // input - enable dcc (sync to beginning of a new frame) .hfc_sel (hfc_sel), // input[2:0] - hight frequency components select [2:0] (includes components with both numbers >=hfc_sel .color_first (color_first), // input - first MCU in a frame .coring_num (coring_num), // input[2:0] - coring table pair number (0..7) .dcc_vld (dccvld), // output reg - single cycle when dcc_data is valid .dcc_data (dccdata[15:0]), // output[15:0] - dc component data out (for reading by software) .n000 (n000), // input[7:0] - number of zero pixels (255 if 256) - to be multiplexed with dcc .n255 (n255) // input[7:0] - number of 0xff pixels (255 if 256) - to be multiplexed with dcc ); // focus sharp module calculates amount of high-frequency components and optioanlly overlays/replaces actual image wire [12:0] focus_do; // output[12:0] reg pixel data out, make timing ignore (valid 1.5 clk earlier that Quantizer output) wire focus_ds; // output reg data out strobe (one ahead of the start of dv) // TODO: Verify focus_sharp393: quantizer output (with strobes) is now 2 cycles later than in 353 (relative to xdct out). Seems to be OK. focus_sharp393 focus_sharp393_i ( .clk (xclk), // input - pixel clock .clk2x (xclk2x), // input 2x pixel clock .en (frame_en), // input .mclk (mclk), // input system clock to write tables .tser_we (tser_fe), // input - write to a focus sharpness table .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[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) .stb (dct_start), // input strobe that writes ctypei, dci .start (quant_start), // input marks first input pixel (needs 1 cycle delay from previous DCT stage) .di (dct_out), // input[12:0] pixel data in (signed) .quant_ds (quant_ds), // input quantizator ds .quant_d (quant_do[12:0]), // input[12:0] quantizator data output .quant_dc_tdo (quant_dc_tdo), // input[15:0] MSB aligned coefficient for the DC component (used in focus module) .do (focus_do[12:0]), // output[12:0] reg pixel data out, make timing ignore (valid 1.5 clk earlier that Quantizer output) .ds (focus_ds), // output reg data out strobe (one ahead of the start of dv) .hifreq (hifreq[31:0]) // output[31:0] reg accumulated high frequency components in a frame sub-window ); // Format DC components to be output as a mini-frame. Was not used in the late NC353 as the dma1 channel was use3d for IMU instead of dcc wire finish_dcc; wire [15:0] stuffer_do; wire stuffer_dv; wire stuffer_done; wire eof_written_xclk2xn; // re-sync to posedge xclk2x reg xrst2xn; always @ (negedge xclk2x) xrst2xn <= xrst; pulse_cross_clock finish_dcc_i (.rst(xrst2xn), .src_clk(~xclk2x), .dst_clk(xclk2x), .in_pulse(stuffer_done), .out_pulse(finish_dcc),.busy()); dcc_sync393 dcc_sync393_i ( .sclk (xclk2x), // input .dcc_en (dcc_en), // input xclk rising, sync with start of the frame .finish_dcc (finish_dcc), // input @ sclk rising .dcc_vld (dccvld), // input xclk rising .dcc_data (dccdata[15:0]), // input[15:0] @clk rising .statistics_dv (statistics_dv), // output reg .statistics_do (statistics_do[15:0]) // output[15:0] reg @ sclk ); // generate DC data/strobe for the direct output (re) using sdram channel3 buffering // encoderDCAC is updated to handle 13-bit signed data instead of the 12-bit. It will limit the values on ot's own encoderDCAC393 encoderDCAC393_i ( .clk (xclk), // input .en (frame_en), // input .lasti (color_last), // input - was "last MCU in a frame" (@ stb) .first_blocki (first_block_color), // input - first block in frame - save fifo write address (@ stb) .comp_numberi (component_num[2:0]), // input[2:0] - component number 0..2 in color, 0..3 - in jp4diff, >= 4 - don't use (@ stb) .comp_firsti (component_first), // input - first this component in a frame (reset DC) (@ stb) .comp_colori (component_color), // input - use color - huffman? (@ stb) .comp_lastinmbi (component_lastinmb), // input - last component in a macroblock (@ stb) is it needed? .stb (dct_start), // input - strobe that writes firsti, lasti, tni,average .zdi (focus_do[12:0]), // input[12:0] - zigzag-reordered data input .first_blockz (first_block_quant), // input - first block input (@zds) .zds (focus_ds), // input - strobe - one ahead of the DC component output `ifdef DEBUG_RING .last (dbg_last_DCAC), // output reg - not used `else .last (), // output reg - not used `endif .do (enc_do[15:0]), // output[15:0] reg .dv (enc_dv) // output reg `ifdef DEBUG_RING ,.comp_lastinmbo (dbg_comp_lastinmbo) ,.dbg_block_mem_ra (dbg_block_mem_ra) ,.dbg_block_mem_wa (dbg_block_mem_wa) ,.dbg_block_mem_wa_save (dbg_block_mem_wa_save) `else ,.comp_lastinmbo () ,.dbg_block_mem_ra () ,.dbg_block_mem_wa () ,.dbg_block_mem_wa_save () `endif ); // wire [2:0] dbg_block_mem_wa; // wire [2:0] dbg_block_mem_wa_save; huffman393 i_huffman ( .xclk (xclk), // input .xclk2x (xclk2x), // input .en (frame_en), // input .mclk (mclk), // input system clock to write tables .tser_we (tser_he), // input - write to a quantization table .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 .di (enc_do[15:0]), // input[15:0] - specially RLL prepared 16-bit data (to FIFO) .ds (enc_dv), // input - di valid strobe .rdy (stuffer_rdy), // input - receiver (bit stuffer) is ready to accept data .do (huff_do[15:0]), // output[15:0] reg .dl (huff_dl[3:0]), // output[3:0] reg .dv (huff_dv), // output reg .flush (flush), // output reg .last_block (last_block), // output reg `ifdef DEBUG_RING .test_lbw (dbg_test_lbw), // output reg ?? .gotLastBlock (dbg_gotLastBlock), // output ?? - unused (was for debug) `else .test_lbw (), // output reg ?? .gotLastBlock (), // output ?? - unused (was for debug) `endif .clk_flush (hclk), // input .flush_clk (flush_hclk), // output `ifdef DEBUG_RING .fifo_or_full (dbg_fifo_or_full) // FIFO output register full - just for debuging `else .fifo_or_full () // FIFO output register full - just for debuging `endif ); stuffer393 stuffer393_i ( // .rst (rst), // input .mclk (mclk), // input .mrst (mrst), // input .xrst (xrst), // input .last_block (last_block), // input @negedge xclk2x - use it to copy timestamp from fifo .ts_pre_stb (ts_pre_stb), // input 1 cycle before timestamp data, @mclk .ts_data (ts_data), // input[7:0] 8-byte timestamp data (s0,s1,s2,s3,us0,us1,us2,us3==0) .color_first (color_first), // input valid @xclk - only for sec/usec .fradv_clk (xclk), // input .clk (xclk2x), // input clock - uses negedge inside .en_in (stuffer_en), // .flush (flush), // input - flush output data (fill byte with 0, long word with FFs) .abort (force_flush_long), // @ any, extracts 0->1 and flushes .stb (huff_dv), // input .dl (huff_dl), // input[3:0] number of bits to send (0 - 16) (0-16??) .d (huff_do), // input[15:0] data to shift (only lower huff_dl bits are valid) // 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 .done (stuffer_done), // output `ifdef DEBUG_RING .flushing (dbg_flushing), // output reg Not used? `else .flushing (), // output reg Not used? `endif .running (stuffer_running) // from registering timestamp until done `ifdef DEBUG_RING , .dbg_etrax_dma (etrax_dma) ,.dbg_ts_rstb (dbg_ts_rstb) // output ,.dbg_ts_dout (dbg_ts_dout) //output [7:0] `endif `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 ); // Debugging - attaching new compressor module in parallel to the existing one wire [31:0] alt_stuffer_do; // SuppressThisWarning VEditor Unused wire alt_stuffer_dv; // SuppressThisWarning VEditor Unused wire alt_stuffer_done; // SuppressThisWarning VEditor Unused wire alt_stuffer_running; // SuppressThisWarning VEditor Unused huffman_stuffer_meta huffman_stuffer_meta_i ( .mclk (mclk), // input .mrst (mrst), // input .xclk (xclk), // input .en_huffman (frame_en), // input .en_stuffer (stuffer_en), // input .abort_stuffer (force_flush_long), // input .tser_we (tser_he), // input .tser_a_not_d (tser_a_not_d), // input .tser_d (tser_d), // input[7:0] .di (enc_do[15:0]), // input[15:0] .ds (enc_dv), // input .ts_pre_stb (ts_pre_stb), // input .ts_data (ts_data), // input[7:0] .color_first (color_first), // input valid @xclk - only for sec/usec .data_out (alt_stuffer_do), // output[31:0] .data_out_valid (alt_stuffer_dv), // output .done (alt_stuffer_done), // output .running (alt_stuffer_running) // output `ifdef DEBUG_RING ,.test_lbw (), // output .gotLastBlock (), // output // last block done - flush the rest bits .dbg_etrax_dma (), // output[3:0] .dbg_ts_rstb (), // output .dbg_ts_dout () //output[7:0] `endif ); /* ,output dbg_ts_rstb ,output [7:0] dbg_ts_dout */ pulse_cross_clock stuffer_done_mclk_i (.rst(xrst2xn), .src_clk(~xclk2x), .dst_clk(mclk), .in_pulse(stuffer_done), .out_pulse(stuffer_done_mclk),.busy()); cmprs_out_fifo cmprs_out_fifo_i ( // .rst (rst), // input mostly for simulation // source (stuffer) clock domain .wclk (~xclk2x), // input source clock (2x pixel clock, inverted) - same as stuffer out .wrst (xrst2xn), // input mostly for simulation .we (stuffer_dv), // @ posedge(~xclk2x) input write data from stuffer .wdata ({stuffer_do[7:0],stuffer_do[15:8]}), // input[15:0] data from stuffer module; .wa_rst (!stuffer_en), // input reset low address bits when stuffer is disabled (to make sure it is multiple of 32 bytes .wlast (stuffer_done), // input - written last 32 bytes of a frame (flush FIFO) - stuffer_done (has to be later than we) .eof_written_wclk (eof_written_xclk2xn), // output - AFI had transferred frame data to the system memory // AFI clock domain .rclk (hclk), // @posedge(hclk) input - AFI clock .rrst (hrst), // input - AFI clock .rst_fifo (fifo_rst), // input - reset FIFO (set read address to write, reset count) .ren (fifo_ren), // input - fifo read from AFI channel mux .rdata (fifo_rdata), // output[63:0] - data to AFI channel mux (latency == 2 from fifo_ren) .eof (fifo_eof), // output single hclk pulse signalling EOF .eof_written (eof_written), // input single hclk pulse confirming frame data is written to the system memory .flush_fifo (fifo_flush), // output level signalling that FIFO has data from the current frame (use short AXI burst if needed) .fifo_count (fifo_count) // output[7:0] - number of 32-byte chunks available in FIFO ); pulse_cross_clock eof_written_mclk_i (.rst(xrst2xn), .src_clk(~xclk2x), .dst_clk(mclk), .in_pulse(eof_written_xclk2xn), .out_pulse(eof_written_mclk),.busy()); // TODO: Add status module to combine/FF, re-clock status signals endmodule