Commit 72dc592d authored by Andrey Filippov's avatar Andrey Filippov

started porting jpeg/jp4 compressor code

parent 1f464a83
...@@ -62,77 +62,77 @@ ...@@ -62,77 +62,77 @@
<link> <link>
<name>vivado_logs/VivadoBitstream.log</name> <name>vivado_logs/VivadoBitstream.log</name>
<type>1</type> <type>1</type>
<location>/home/andrey/git/x393/vivado_logs/VivadoBitstream-20150506105443622.log</location> <location>/home/andrey/git/x393/vivado_logs/VivadoBitstream-20150609094851488.log</location>
</link> </link>
<link> <link>
<name>vivado_logs/VivadoOpt.log</name> <name>vivado_logs/VivadoOpt.log</name>
<type>1</type> <type>1</type>
<location>/home/andrey/git/x393/vivado_logs/VivadoOpt-20150506105443622.log</location> <location>/home/andrey/git/x393/vivado_logs/VivadoOpt-20150609094851488.log</location>
</link> </link>
<link> <link>
<name>vivado_logs/VivadoOptPhys.log</name> <name>vivado_logs/VivadoOptPhys.log</name>
<type>1</type> <type>1</type>
<location>/home/andrey/git/x393/vivado_logs/VivadoOptPhys-20150506105443622.log</location> <location>/home/andrey/git/x393/vivado_logs/VivadoOptPhys-20150609094851488.log</location>
</link> </link>
<link> <link>
<name>vivado_logs/VivadoOptPower.log</name> <name>vivado_logs/VivadoOptPower.log</name>
<type>1</type> <type>1</type>
<location>/home/andrey/git/x393/vivado_logs/VivadoOptPower-20150506105443622.log</location> <location>/home/andrey/git/x393/vivado_logs/VivadoOptPower-20150609094851488.log</location>
</link> </link>
<link> <link>
<name>vivado_logs/VivadoPlace.log</name> <name>vivado_logs/VivadoPlace.log</name>
<type>1</type> <type>1</type>
<location>/home/andrey/git/x393/vivado_logs/VivadoPlace-20150506105443622.log</location> <location>/home/andrey/git/x393/vivado_logs/VivadoPlace-20150609094851488.log</location>
</link> </link>
<link> <link>
<name>vivado_logs/VivadoRoute.log</name> <name>vivado_logs/VivadoRoute.log</name>
<type>1</type> <type>1</type>
<location>/home/andrey/git/x393/vivado_logs/VivadoRoute-20150506105443622.log</location> <location>/home/andrey/git/x393/vivado_logs/VivadoRoute-20150609094851488.log</location>
</link> </link>
<link> <link>
<name>vivado_logs/VivadoSynthesis.log</name> <name>vivado_logs/VivadoSynthesis.log</name>
<type>1</type> <type>1</type>
<location>/home/andrey/git/x393/vivado_logs/VivadoSynthesis-20150506104713443.log</location> <location>/home/andrey/git/x393/vivado_logs/VivadoSynthesis-20150609094617774.log</location>
</link> </link>
<link> <link>
<name>vivado_logs/VivadoTimimgSummaryReportImplemented.log</name> <name>vivado_logs/VivadoTimimgSummaryReportImplemented.log</name>
<type>1</type> <type>1</type>
<location>/home/andrey/git/x393/vivado_logs/VivadoTimimgSummaryReportImplemented-20150506105443622.log</location> <location>/home/andrey/git/x393/vivado_logs/VivadoTimimgSummaryReportImplemented-20150609094851488.log</location>
</link> </link>
<link> <link>
<name>vivado_logs/VivadoTimimgSummaryReportSynthesis.log</name> <name>vivado_logs/VivadoTimimgSummaryReportSynthesis.log</name>
<type>1</type> <type>1</type>
<location>/home/andrey/git/x393/vivado_logs/VivadoTimimgSummaryReportSynthesis-20150506104713443.log</location> <location>/home/andrey/git/x393/vivado_logs/VivadoTimimgSummaryReportSynthesis-20150609094617774.log</location>
</link> </link>
<link> <link>
<name>vivado_logs/VivadoTimingReportImplemented.log</name> <name>vivado_logs/VivadoTimingReportImplemented.log</name>
<type>1</type> <type>1</type>
<location>/home/andrey/git/x393/vivado_logs/VivadoTimingReportImplemented-20150506105443622.log</location> <location>/home/andrey/git/x393/vivado_logs/VivadoTimingReportImplemented-20150609094851488.log</location>
</link> </link>
<link> <link>
<name>vivado_logs/VivadoTimingReportSynthesis.log</name> <name>vivado_logs/VivadoTimingReportSynthesis.log</name>
<type>1</type> <type>1</type>
<location>/home/andrey/git/x393/vivado_logs/VivadoTimingReportSynthesis-20150506104713443.log</location> <location>/home/andrey/git/x393/vivado_logs/VivadoTimingReportSynthesis-20150609094617774.log</location>
</link> </link>
<link> <link>
<name>vivado_state/x393-opt-phys.dcp</name> <name>vivado_state/x393-opt-phys.dcp</name>
<type>1</type> <type>1</type>
<location>/home/andrey/git/x393/vivado_state/x393-opt-phys-20150506105443622.dcp</location> <location>/home/andrey/git/x393/vivado_state/x393-opt-phys-20150609094851488.dcp</location>
</link> </link>
<link> <link>
<name>vivado_state/x393-place.dcp</name> <name>vivado_state/x393-place.dcp</name>
<type>1</type> <type>1</type>
<location>/home/andrey/git/x393/vivado_state/x393-place-20150506105443622.dcp</location> <location>/home/andrey/git/x393/vivado_state/x393-place-20150609094851488.dcp</location>
</link> </link>
<link> <link>
<name>vivado_state/x393-route.dcp</name> <name>vivado_state/x393-route.dcp</name>
<type>1</type> <type>1</type>
<location>/home/andrey/git/x393/vivado_state/x393-route-20150506105443622.dcp</location> <location>/home/andrey/git/x393/vivado_state/x393-route-20150609094851488.dcp</location>
</link> </link>
<link> <link>
<name>vivado_state/x393-synth.dcp</name> <name>vivado_state/x393-synth.dcp</name>
<type>1</type> <type>1</type>
<location>/home/andrey/git/x393/vivado_state/x393-synth-20150506104713443.dcp</location> <location>/home/andrey/git/x393/vivado_state/x393-synth-20150609094617774.dcp</location>
</link> </link>
</linkedResources> </linkedResources>
</projectDescription> </projectDescription>
/*******************************************************************************
* Module: color_proc393
* Date:2015-06-10
* Author: andrey
* Description: Color processor for JPEG 4:2:0/JP4
* Updating from the earlier 2002-2010 version
*
* Copyright (c) 2002-2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* color_proc393.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.
*
* color_proc393.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
`define DEBUG_COMPRESSOR
module color_proc393 (
input clk, // pixel clock (1/2 system clock - 80MHz)
input en, // Enable (0 will reset states)
input en_sdc, // enable subtracting of DC component
input go, // pulse to star/restart (needed for each frame, repeat generated by the caller)
input [25:0] nblocks, // ***** was [17:0] number of 16x16 blocks to read (valid @ "go" pulse)
output eot, // single-cycle end of transfer pulse
input [ 9:0] m_cb, // [9:0] scale for CB - default 0.564 (10'h90)
input [ 9:0] m_cr, // [9:0] scale for CB - default 0.713 (10'hb6)
input memWasInit, // memory channel2 was just initialized - reset page address (at posedge clk)
input [ 7:0] di, // [7:0]
output [11:0] sdram_a, // ***** was [10:0] (MSB - SDRAM buffer page number)
input sdram_rdy, // SDRAM buffer ready
output sdram_next, // request to read a page to SDRAM buffer
output inc_sdrama, // enable read sdram buffer
output inc_sdrama_d,// ***** NEW regen sdram buffer (delay by 1 clock
input noMoreData, // used as alternative to end frame input (possibly broken frame)
output dv_raw, // data valid for di (for testing to bypass color conversion - use di[7:0])
input ignore_color, //zero Cb/Cr components
input four_blocks, // use only 6 blocks for the output, not 6
input jp4_dc_improved, // in JP4 mode, compare DC coefficients to the same color ones
input [ 1:0] tile_margin, // margins around 16x16 tiles (0/1/2)
input [ 2:0] tile_shift, // tile shift from top left corner
input [ 2:0] converter_type, // 0 - color18, 1 - color20, 2 - mono, 3 - jp4, 4 - jp4-diff
input scale_diff, // divide differences by 2 (to fit in 8-bit range)
input hdr, // second green absolute, not difference
output [ 9:0] do, // [9:0] data out (4:2:0) (signed, average=0)
output [ 8:0] avr, // [8:0] DC (average value) - RAM output, no register. For Y components 9'h080..9'h07f, for C - 9'h100..9'h0ff!
output dv, // out data valid (will go high for at least 64 cycles)
output ds, // single-cycle mark of the first_r pixel in a 64 (8x8) - pixel block
output [ 2:0] tn, // [2:0] tile number 0..3 - Y, 4 - Cb, 5 - Cr (valid with start)
output first, // sending first_r MCU (valid @ ds)
output last, // sending last_r MCU (valid @ ds)
output [ 7:0] n000, // [7:0] number of zero pixels (255 if 256)
output [ 7:0] n255, // [7:0] number of 0xff pixels (255 if 256)
input [ 1:0] bayer_phase, //[1:0]) bayer color filter phase 0:(GR/BG), 1:(RG/GB), 2: (BG/GR), 3: (GB/RG)
// below signals valid at ds ( 1 later than tn, first_r, last_r)
output [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
output component_color, // use color quantization table (YCbCR, jp4diff)
output component_first, // first_r this component in a frame (DC absolute, otherwise - difference to previous)
output component_lastinmb // last_r component in a macroblock;
`ifdef DEBUG_COMPRESSOR
,output bcntrIsZero
,output [25:0] bcntr
`endif
);
wire [8:0] y_out; // data from buffer
wire [8:0] c_out; // data from buffer
reg [1:0] wpage; // page (0/1) where data is being written to (both Y and CbCr)
reg [1:0] rpage; // page (0/1) from where data is sent out ( both Y and CbCr)
reg sdram_next_r;
reg [25:0] bcntr_r; // down counter of blocks left
reg bcntrIsZero_r; // one cycle of bcntr_r[]==0
reg eot_r;
reg ccv_start_en; //
reg ccv_out_start,ccv_out_start_d; // start output of YCbCr from buffers
reg [8:0] raddr; // output address of buffer memories (MSB selects Y(0)/CbCr(1))
reg raddr8_d; // raddr[8] delayed by 1 clock to control bram regen
reg dv0; // "dv0" - one cycle ahead of "dv" to compensate for "do_r" register latency
reg ds0; // "ds0" - one cycle ahead of "ds" to compensate for "do_r" register latency
// reg [8:0] do_r;
// reg [8:0] pre_do;
reg [9:0] do_r;
reg [9:0] pre_do;
reg [1:0] pre_dv, pre_ds;
reg dv_raw_r;
// 16x8 dual port RAM
reg buf_sel;
reg willbe_first;
reg first_r,first0;
reg last_r,last0;
reg [4:0] preline; // number of line in a tile, down counter (0x13->0, 0x11->0, 0x0f->0), 1 cycles ahead of data from SDRAM
reg [4:0] prepix; // number of pixel in a line in a tile, down counter (0x13->0, 0x11->0, 0x0f->0)
reg [1:0] sdram_a9_page;
reg [8:0] sdram_a9;
reg [8:0] seq_cntr; // master
wire [4:0] tile_size;
wire [8:0] macroblock_period_minus1;
wire all_ready;
reg preline_was_0;
reg pre_start_of_line;
reg pre_first_pixel;
reg [8:0] sdrama_top_left; // address of top left corner to be processed
reg [2:0] sdrama_line_inc; // increment amount when proceeding to next tile line
reg [1:0] inc_sdrama_r;
reg last_from_sdram; // reading last_r byte from SDRAM
reg first_pixel; // reading first_r pixel to color converter (di will be evailable next cycle)
reg tim2next;
reg [8:0] y_in, c_in;
reg [7:0] yaddrw, caddrw;
reg ywe, cwe;
reg color_enable, pre_color_enable;// prevent random colors in monochrome/JP46 modes (pre_* - sync input)
reg cs_pre_first_out; // clear color accumulators
wire [7:0] conv18_y_in, conv20_y_in, mono_y_in, jp4_y_in;
wire [8:0] jp4diff_y_in, conv18_c_in, conv20_c_in;
wire [7:0] conv18_yaddrw, conv20_yaddrw, mono_yaddrw, jp4_yaddrw, jp4diff_yaddrw;
wire [6:0] conv18_caddrw, conv20_caddrw;
wire conv18_ywe, conv18_cwe, conv20_ywe, conv20_cwe, mono_ywe, jp4_ywe, jp4diff_ywe;
wire conv18_pre_first_out, conv20_pre_first_out, mono_pre_first_out, jp4_pre_first_out, jp4diff_pre_first_out;
reg [4:0] en_converters;
reg [2:0] converter_type_r;
reg ignore_color_r;
reg jp4_dc_improved_r;
reg four_blocks_r;
reg scale_diff_r;
reg hdr_r;
reg [1:0] tile_margin_r;
// reg [2:0] tile_shift_r;
reg [1:0] bayer_phase_r;
reg [3:0] bayer_phase_onehot;
reg raddr_lastInBlock;
reg raddr_updateBlock; // first_r in block, after last_r also. Should be when *_r match the currently selected converter for the macroblock
// component_num,component_color,component_first for different converters vs tn (1 bit per tn (0..5)
reg component_lastinmb_r; // last_r component in a macroblock;
reg [5:0] component_numsL, component_numsLS; // component_num[0] vs tn
reg [5:0] component_numsM, component_numsMS; // component_num[1] vs tn
reg [5:0] component_numsH, component_numsHS; // component_num[2] vs tn
reg [5:0] component_colors, component_colorsS; // use color quantization table (YCbCR, jp4diff)
reg [5:0] component_firsts, component_firstsS; // first_r this component in a frame (DC absolute, otherwise - difference to previous)
reg eof_rq; // request to end frame if there will be no more data
`ifdef DEBUG_COMPRESSOR
assign bcntr = bcntr_r;
assign bcntrIsZero= bcntrIsZero_r;
`endif
assign component_lastinmb=component_lastinmb_r;
assign sdram_a = {sdram_a9_page[1:0],sdram_a9[8:0]};
assign tn[2:0] = raddr[8:6];
assign sdram_next = sdram_next_r;
assign inc_sdrama = inc_sdrama_r[0];
assign inc_sdrama_d = inc_sdrama_r[1];
assign eot = eot_r;
assign first = first_r;
assign last = last_r;
assign dv_raw = dv_raw_r;
assign do = do_r;
assign dv = pre_dv[1];
assign ds = pre_ds[1];
assign component_num[2:0]= {component_numsH[0],component_numsM[0],component_numsL[0]};
assign component_color = component_colors[0];
assign component_first = component_firsts[0];
assign all_ready = sdram_rdy && ccv_start_en;
assign macroblock_period_minus1[8:0] = four_blocks?(tile_margin[1]?9'h18f:(tile_margin[0]?9'h143:9'h0ff)):(tile_margin[1]?9'h18f:9'h17f);
assign tile_size[4:0] = tile_margin[1]?5'h13:(tile_margin[0]?5'h11:5'h0f);
always @ (posedge clk) begin
if (!en) seq_cntr[8:0] <=9'h0;
else if (seq_cntr[8:0]!=0) seq_cntr[8:0] <= seq_cntr[8:0] -1;
else if (all_ready) seq_cntr[8:0] <= macroblock_period_minus1;
preline_was_0 <= (preline[4:0]==5'h0);
if ((seq_cntr[8:0]==0) || ((prepix[4:0]==0) && !preline_was_0) ) prepix[4:0] <= tile_size[4:0];
else if (prepix[4:0]!=0) prepix[4:0] <= prepix[4:0] - 1;
if (seq_cntr[8:0]==0) preline[4:0] <= tile_size[4:0];
else if ((prepix[4:0]==0) && !preline_was_0) preline[4:0] <= preline[4:0] - 1;
pre_start_of_line <= ((seq_cntr[8:0]==0) || ((prepix[4:0]==0) && !preline_was_0) );
pre_first_pixel <= en && (seq_cntr[8:0]==9'h0) && all_ready;
case (tile_shift[2:0])
3'h0: sdrama_top_left[8:0] <= 9'h0;
3'h1: sdrama_top_left[8:0] <= 9'h15;
3'h2: sdrama_top_left[8:0] <= 9'h2a;
3'h3: sdrama_top_left[8:0] <= 9'h3f;
3'h4: sdrama_top_left[8:0] <= 9'h54;
endcase
case (tile_margin[1:0])
2'h0: sdrama_line_inc[2:0] <= 3'h5;
2'h1: sdrama_line_inc[2:0] <= 3'h3;
2'h2: sdrama_line_inc[2:0] <= 3'h1;
endcase
first_pixel <= pre_first_pixel;
last_from_sdram <= en & preline_was_0 && (prepix[4:0]==0);
inc_sdrama_r <= en & (pre_first_pixel || (inc_sdrama_r && !last_from_sdram ));
if (pre_first_pixel) sdram_a9[8:0] <= sdrama_top_left[8:0];
else if (inc_sdrama_r) sdram_a9[8:0] <= sdram_a9[8:0] + (pre_start_of_line ? sdrama_line_inc[2:0] : 3'h1);
if (!en || memWasInit) sdram_a9_page[1:0] <= 2'h0;
else if (last_from_sdram && inc_sdrama_r) sdram_a9_page[1:0] <= sdram_a9_page[1:0]+1;
// wpage[1:0] valid with ywe
if (cs_pre_first_out) wpage[1:0] <= sdram_a9_page[1:0]; // copy page from SDRAM buffer
// register control modes to be valid while overlapping
if (pre_first_pixel) begin
converter_type_r [2:0] <= converter_type[2:0];
ignore_color_r <= ignore_color;
jp4_dc_improved_r <= jp4_dc_improved;
four_blocks_r <= four_blocks;
scale_diff_r <= scale_diff;
hdr_r <= hdr;
tile_margin_r[1:0] <= tile_margin[1:0];
bayer_phase_r[1:0] <= bayer_phase[1:0];
bayer_phase_onehot[3:0]<={(bayer_phase[1:0]==2'h3)?1'b1:1'b0,
(bayer_phase[1:0]==2'h2)?1'b1:1'b0,
(bayer_phase[1:0]==2'h1)?1'b1:1'b0,
(bayer_phase[1:0]==2'h0)?1'b1:1'b0};
end
if (!en) en_converters[4:0] <= 0;
else if (pre_first_pixel)
en_converters[4:0]<= {(converter_type[2:0]==3'h4)?1'b1:1'b0,
(converter_type[2:0]==3'h3)?1'b1:1'b0,
(converter_type[2:0]==3'h2)?1'b1:1'b0,
(converter_type[2:0]==3'h1)?1'b1:1'b0,
(converter_type[2:0]==3'h0)?1'b1:1'b0};
end
// new
//cs_pre_first_out
reg [3:0] accYen;
reg [1:0] accCen; // individual accumulator enable (includes clearing)
reg [3:0] accYfirst;
reg [1:0] accCfirst; // add to zero, instead of to acc @ acc*en
reg [8:0] preAccY, preAccC; // registered data from color converters, matching acc selection latency
reg [14:0] accY0,accY1,accY2,accY3,accC0,accC1;
reg cs_first_out;
reg [5:0] accCntrY0,accCntrY1,accCntrY2,accCntrY3,accCntrC0,accCntrC1;
wire [3:0] pre_accYdone;
wire [1:0] pre_accCdone; // need to make sure that pre_accCdone do_r not happen with pre_accYdone
reg [3:0] accYrun;
reg [1:0] accCrun;
reg [3:0] accYdone;
reg accYdoneAny;
reg [1:0] avrY_wa, pre_avrY_wa;
reg avrC_wa, pre_avrC_wa;
reg avrPage_wa, pre_avrPage_wa;
reg avr_we;
reg [8:0] avermem[0:15];
wire [3:0] avr_wa= {avrPage_wa,accYdoneAny?{1'b0,avrY_wa[1:0]}:{2'b10,avrC_wa}};
reg [3:0] avr_ra; // read address
wire [8:0] avrY_di= avrY_wa[1] ? (avrY_wa[0]?accY3[14:6]:accY2[14:6]):(avrY_wa[0]?accY1[14:6]:accY0[14:6]);
wire [8:0] avrC_di= avrC_wa ?accC1[14:6]:accC0[14:6];
assign avr = avermem[avr_ra[3:0]];
assign pre_accYdone[3:0] = {(accCntrY3[5:0]==6'h3e)?1'b1:1'b0,(accCntrY2[5:0]==6'h3e)?1'b1:1'b0,(accCntrY1[5:0]==6'h3e)?1'b1:1'b0,(accCntrY0[5:0]==6'h3e)?1'b1:1'b0} & accYen[3:0];
assign pre_accCdone[1:0] = { (accCntrC1[5:0]==6'h3e)?1'b1:1'b0,(accCntrC0[5:0]==6'h3e)?1'b1:1'b0} & accCen[1:0];
always @ (posedge clk) begin
cs_first_out<=cs_pre_first_out;
if (ywe) preAccY[8:0] <= y_in[8:0];
if (cwe) preAccC[8:0] <= c_in[8:0];
accYen[3:0] <= {4{en & ywe}} & {yaddrw[7] & yaddrw[6], yaddrw[7] & ~yaddrw[6],~ yaddrw[7] & yaddrw[6], ~yaddrw[7] & ~yaddrw[6]};
accCen[1:0] <= {2{en & cwe}} & {caddrw[6], ~caddrw[6]};
accYfirst[3:0] <= {4{cs_first_out}} | (accYfirst[3:0] & ~accYen[3:0]);
accCfirst[1:0] <= {2{cs_first_out}} | (accCfirst[1:0] & ~accCen[1:0]);
if (accYen[0]) accY0[14:0]<= (accYfirst[0]?15'h0:accY0[14:0]) + {{6{preAccY[8]}},preAccY[8:0]};
if (accYen[1]) accY1[14:0]<= (accYfirst[1]?15'h0:accY1[14:0]) + {{6{preAccY[8]}},preAccY[8:0]};
if (accYen[2]) accY2[14:0]<= (accYfirst[2]?15'h0:accY2[14:0]) + {{6{preAccY[8]}},preAccY[8:0]};
if (accYen[3]) accY3[14:0]<= (accYfirst[3]?15'h0:accY3[14:0]) + {{6{preAccY[8]}},preAccY[8:0]};
if (accCen[0]) accC0[14:0]<= (accCfirst[0]?15'h0:accC0[14:0]) + {{6{preAccC[8]}},preAccC[8:0]};
if (accCen[1]) accC1[14:0]<= (accCfirst[1]?15'h0:accC1[14:0]) + {{6{preAccC[8]}},preAccC[8:0]};
if (!en) accCntrY0[5:0]<= 6'h0; else if (accYen[0]) accCntrY0[5:0]<= (accYfirst[0]?6'h0:(accCntrY0[5:0]+1));
if (!en) accCntrY1[5:0]<= 6'h0; else if (accYen[1]) accCntrY1[5:0]<= (accYfirst[1]?6'h0:(accCntrY1[5:0]+1));
if (!en) accCntrY2[5:0]<= 6'h0; else if (accYen[2]) accCntrY2[5:0]<= (accYfirst[2]?6'h0:(accCntrY2[5:0]+1));
if (!en) accCntrY3[5:0]<= 6'h0; else if (accYen[3]) accCntrY3[5:0]<= (accYfirst[3]?6'h0:(accCntrY3[5:0]+1));
if (!en) accCntrC0[5:0]<= 6'h0; else if (accCen[0]) accCntrC0[5:0]<= (accCfirst[0]?6'h0:(accCntrC0[5:0]+1));
if (!en) accCntrC1[5:0]<= 6'h0; else if (accCen[1]) accCntrC1[5:0]<= (accCfirst[1]?6'h0:(accCntrC1[5:0]+1));
accYrun[3:0] <= {4{en}} & ((accYfirst[3:0] & accYen[3:0]) | (accYrun[3:0] & ~pre_accYdone[3:0]));
accCrun[1:0] <= {2{en}} & ((accCfirst[1:0] & accCen[1:0]) | (accCrun[1:0] & ~pre_accCdone[1:0]));
accYdone[3:0] <= pre_accYdone[3:0] & accYrun[3:0];
accYdoneAny <= |(pre_accYdone[3:0] & accYrun[3:0]);
avr_we <= |(pre_accYdone[3:0] & accYrun[3:0]) || |(pre_accCdone[1:0] & accCrun[1:0]);
pre_avrY_wa[1:0] <= yaddrw[7:6];
avrY_wa[1:0] <= pre_avrY_wa[1:0];
pre_avrC_wa <= caddrw[ 6];
avrC_wa <= pre_avrC_wa;
pre_avrPage_wa <= wpage[0];
avrPage_wa <= pre_avrPage_wa;
if (avr_we) avermem[avr_wa[3:0]] <= en_sdc?(accYdoneAny?avrY_di[8:0]:avrC_di[8:0]):9'h0;
avr_ra[3:0] <= {rpage[0],raddr[8:6]};
raddr8_d <= raddr[8];
end
reg transfer_ended=0; /// there was already EOT pulse for the current frame
always @ (posedge clk) begin
transfer_ended <= bcntrIsZero_r && (transfer_ended || eot_r);
/*+*/ tim2next <= (seq_cntr[8:0]=='h10); // rather arbitrary number - sdram buffer should in no case be actually overwritten before data read out
// it may depend on relation between SDRAM clk frequency (75MHz) and this clk (variable? 30MHz)
eof_rq <= (tim2next && !bcntrIsZero_r) || (eof_rq && !(inc_sdrama_r || transfer_ended));
ccv_start_en <= en && !eot_r && (ccv_start_en || go); //FIXME: Still uncaught problem: SDRAM ready occurs before go_single!
bcntrIsZero_r <= (bcntr_r==0);
sdram_next_r <= tim2next && ~sdram_next_r;
eot_r <= !transfer_ended && !eot_r && bcntrIsZero_r && (tim2next || (eof_rq && noMoreData));
if (go) bcntr_r <= nblocks;
else if (noMoreData) bcntr_r <= 0;
else if (sdram_next_r && !bcntrIsZero_r) bcntr_r <= bcntr_r-1;
if (ccv_out_start) rpage[1:0] <=wpage[1:0];
if (ccv_out_start) color_enable <= pre_color_enable;
ccv_out_start_d <= ccv_out_start;
raddr_lastInBlock <= en && (raddr[5:0]==6'h3e);
raddr_updateBlock <= raddr_lastInBlock || ccv_out_start;
if (ccv_out_start || !en) raddr[8:0] <= {!en,!en,7'h0}; // 9'h180/9'h000;
else if (!raddr[8] || (!four_blocks_r && !raddr[7])) raddr[8:0] <= raddr[8:0]+1; // for 4 blocks - count for 0,1; 6 blocks - 0,1,2
dv0 <= en && raddr_updateBlock?(!raddr[8] || (!four_blocks_r && !raddr[7])):dv0;
ds0 <= raddr_updateBlock && (!raddr[8] || (!four_blocks_r && !raddr[7]));
buf_sel <= raddr[8];
pre_do[9:0] <= buf_sel?(color_enable?({c_out[8],c_out[8:0]}-{avr[8],avr[8:0]}):10'b0):({y_out[8],y_out[8:0]}-{avr[8],avr[8:0]});
//color_enable
do_r[9:0] <= pre_do[9:0];
dv_raw_r <= inc_sdrama_r && en;
if (go) willbe_first <= 1'b1;
else if (first_pixel) willbe_first <= 1'b0;
if (first_pixel) begin
first0 <= willbe_first;
last0 <= (bcntr_r[17:0]==18'b0);
end
if (ccv_out_start) begin
first_r <= first0;
last_r <= last0;
end
// 8x8 memory to hold average values
pre_dv[1:0] <= {pre_dv[0],dv0};
pre_ds[1:0] <= {pre_ds[0],ds0};
// Shift registers - generating block attributes to be used later in compressor
if (raddr_updateBlock) begin
if (ccv_out_start_d) begin
component_numsL[5:0] <= component_numsLS[5:0];
component_numsM[5:0] <= component_numsMS[5:0];
component_numsH[5:0] <= component_numsHS[5:0];
component_colors[5:0] <= component_colorsS[5:0];
component_firsts[5:0] <= first0? component_firstsS[5:0]:6'h0; // here we may use first0 that is one cycle earlier and ends much earlier
end else begin
component_numsL[5:0] <= {1'b0,component_numsL[5:1]};
component_numsM[5:0] <= {1'b0,component_numsM[5:1]};
component_numsH[5:0] <= {1'b0,component_numsH[5:1]};
component_colors[5:0] <= {1'b0,component_colors[5:1]};
component_firsts[5:0] <= {1'b0,component_firsts[5:1]};
end
end
component_lastinmb_r <= tn[0] && (four_blocks_r? tn[1] : tn[2]); // last_r component in a macroblock;
end
// average for each block should be calculated before the data goes to output output
always @ (posedge clk) case (converter_type_r[2:0])
3'h0:begin //color 18
cs_pre_first_out <= conv18_pre_first_out;
y_in[8:0] <= {conv18_y_in[7],conv18_y_in[7:0]};
ywe <= conv18_ywe;
yaddrw[7:0] <= {conv18_yaddrw[7],conv18_yaddrw[3],conv18_yaddrw[6:4],conv18_yaddrw[2:0]};
c_in[8:0] <= {conv18_c_in[8:0]};
cwe <= conv18_cwe;
pre_color_enable <= 1'b1;
caddrw[7:0] <= {1'b0,conv18_caddrw[6:0]};
ccv_out_start <= (conv18_yaddrw[7:0]==8'hc5); //TODO: adjust to minimal latency?
component_numsLS <= 6'h10; // component_num [0]
component_numsMS <= 6'h20; // component_num [1]
component_numsHS <= 6'h00; // component_num [2]
component_colorsS <= 6'h30; // use color quantization table (YCbCR, jp4diff)
component_firstsS <= 6'h31; // first_r this component in a frame (DC absolute, otherwise - difference to previous)
end
3'h1:begin //color 20
cs_pre_first_out <= conv20_pre_first_out;
y_in[8:0] <= {conv20_y_in[7],conv20_y_in[7:0]};
ywe <= conv20_ywe;
yaddrw[7:0] <= {conv20_yaddrw[7],conv20_yaddrw[3],conv20_yaddrw[6:4],conv20_yaddrw[2:0]};
c_in[8:0] <= {conv20_c_in[8:0]};
cwe <= conv20_cwe;
pre_color_enable <= 1'b1;
caddrw[7:0] <= {1'b0,conv20_caddrw[6:0]};
ccv_out_start <= (conv20_yaddrw[7:0]==8'hc5); //TODO: adjust to minimal latency?
component_numsLS <= 6'h10; // component_num [0]
component_numsMS <= 6'h20; // component_num [1]
component_numsHS <= 6'h3f; // component_num [2]
component_colorsS <= 6'h30; // use color quantization table (YCbCR, jp4diff)
component_firstsS <= 6'h31; // first_r this component in a frame (DC absolute, otherwise - difference to previous)
end
3'h2:begin //mono
cs_pre_first_out <= mono_pre_first_out;
y_in[8:0] <= {mono_y_in[7],mono_y_in[7:0]};
ywe <= mono_ywe;
yaddrw[7:0] <= {mono_yaddrw[7],mono_yaddrw[3],mono_yaddrw[6:4],mono_yaddrw[2:0]};
c_in[8:0] <= 9'h0;
cwe <= 1'b0;
pre_color_enable <= 1'b0;
caddrw[7:0] <= 8'h0;
ccv_out_start <= accYdone[0];
component_numsLS <= 6'h10; // component_num [0]
component_numsMS <= 6'h20; // component_num [1]
component_numsHS <= 6'h30; // component_num [2]
component_colorsS <= 6'h30; // use color quantization table (YCbCR, jp4diff)
component_firstsS <= 6'h31; // first_r this component in a frame (DC absolute, otherwise - difference to previous)
end
3'h3:begin // jp4
cs_pre_first_out <= jp4_pre_first_out;
y_in[8:0] <= {jp4_y_in[7],jp4_y_in[7:0]};
ywe <= jp4_ywe;
yaddrw[7:0] <= {jp4_yaddrw[7],jp4_yaddrw[3],jp4_yaddrw[6:4],jp4_yaddrw[2:0]};
c_in[8:0] <= 9'h0;
cwe <= 1'b0;
pre_color_enable <= 1'b0;
caddrw[7:0] <= 8'h0;
ccv_out_start <= accYdone[0];
component_numsLS <= jp4_dc_improved_r?6'h0a:6'h10; // LSb of component_num
component_numsMS <= jp4_dc_improved_r?6'h0c:6'h20; // MSb of component_num
component_numsHS <= 6'h30; // component_num [2]
component_colorsS <= 6'h30; // use color quantization table (YCbCR, jp4diff)
component_firstsS <= jp4_dc_improved_r?6'h3f:6'h31; // first_r this component in a frame (DC absolute, otherwise - difference to previous)
end
3'h4:begin //jp4diff
cs_pre_first_out <= jp4diff_pre_first_out;
y_in[8:0] <= {jp4diff_y_in[8:0]};
ywe <= jp4diff_ywe;
yaddrw[7:0] <= {jp4diff_yaddrw[7],jp4diff_yaddrw[3],jp4diff_yaddrw[6:4],jp4diff_yaddrw[2:0]};
c_in[8:0] <= 9'h0;
cwe <= 1'b0;
pre_color_enable <= 1'b0;
caddrw[7:0] <= 8'h0;
ccv_out_start <= accYdone[0];
component_numsLS <= 6'h0a; // LSb of component_num
component_numsMS <= 6'h0c; // MSb of component_num
component_numsHS <= 6'h30; // component_num [2]
component_colorsS <= {2'h3,~bayer_phase_onehot[3:0] | (hdr_r? {~bayer_phase_onehot[1:0],~bayer_phase_onehot[3:2]} : 4'h0)}; // use color quantization table (YCbCR, jp4diff)
component_firstsS <= 6'h3f; // first_r this component in a frame (DC absolute, otherwise - difference to previous)
end
endcase
wire limit_diff=1'b1;
csconvert18 i_csconvert18 (
.RST (!en_converters[0]),
.CLK (clk),
.mono (ignore_color_r),
.limit_diff (limit_diff), // 1 - limit color outputs to -128/+127 range, 0 - let them be limited downstream
.m_cb (m_cb[9:0]), // [9:0] scale for CB - default 0.564 (10'h90)
.m_cr (m_cr[9:0]), // [9:0] scale for CB - default 0.713 (10'hb6)
.din (di[7:0]),
.pre_first_in (first_pixel),
.signed_y (conv18_y_in[7:0]),
.q (conv18_c_in[8:0]),
.yaddr (conv18_yaddrw[7:0]), //
.ywe (conv18_ywe),
.caddr (conv18_caddrw[6:0]),
.cwe (conv18_cwe),
.pre_first_out (conv18_pre_first_out),
.bayer_phase (bayer_phase_r[1:0]),
.n000 (n000[7:0]), // TODO:remove ?
.n255 (n255[7:0]));
csconvert_mono i_csconvert_mono (
.en (en_converters[2]),
.clk (clk),
.din (di[7:0]),
.pre_first_in (first_pixel),
.y_out (mono_y_in[7:0]),
.yaddr (mono_yaddrw[7:0]),
.ywe (mono_ywe),
.pre_first_out(mono_pre_first_out));
csconvert_jp4 i_csconvert_jp4 (
.en (en_converters[3]),
.clk (clk),
.din (di[7:0]),
.pre_first_in (first_pixel),
.y_out (jp4_y_in[7:0]),
.yaddr (jp4_yaddrw[7:0]),
.ywe (jp4_ywe),
.pre_first_out (jp4_pre_first_out));
csconvert_jp4diff i_csconvert_jp4diff (
.en (en_converters[4]),
.clk (clk),
.scale_diff (scale_diff_r),
.hdr (hdr_r),
.din (di[7:0]),
.pre_first_in (first_pixel),
.y_out (jp4diff_y_in[8:0]),
.yaddr (jp4diff_yaddrw[7:0]),
.ywe (jp4diff_ywe),
.pre_first_out (jp4diff_pre_first_out),
.bayer_phase (bayer_phase_r[1:0]));
//TODO: temporary plugs, until module for 20x20 is created
// will be wrong, of course
assign conv20_y_in[7:0]= conv18_y_in[7:0];
assign conv20_yaddrw[7:0]= conv18_yaddrw[7:0];
assign conv20_ywe= conv18_ywe;
assign conv20_c_in[8:0]= conv18_c_in[8:0];
assign conv20_caddrw[6:0]= conv18_caddrw[6:0];
assign conv20_cwe= conv18_cwe;
assign conv20_pre_first_out= conv18_pre_first_out;
// currently only 8 bits are used in the memories
ramp_var_w_var_r #(
.REGISTERS (1), // will need to delay output strobe(s) by 1
.LOG2WIDTH_WR (3),
.LOG2WIDTH_RD (3),
.DUMMY (0)
) i_y_buff (
.rclk (clk), // input
.raddr ({2'b0,rpage[1:0],raddr[7:0]}), // input[11:0]
.ren (!raddr[8]), // input
.regen (!raddr8_d), // input
.data_out (y_out[8:0]), // output[8:0]
.wclk (clk), // input
.waddr ({2'b0,wpage[1:0],yaddrw[7:0]}), // input[11:0]
.we (ywe), // input
.web (8'hf), // input[7:0]
.data_in (y_in[8:0]) // input[9:0]
);
ramp_var_w_var_r #(
.REGISTERS (1), // will need to delay output strobe(s) by 1
.LOG2WIDTH_WR (3),
.LOG2WIDTH_RD (3),
.DUMMY (0)
) i_CrCb_buff (
.rclk (clk), // input
.raddr ({2'b0,rpage[1:0],raddr[7:0]}), // input[11:0]
.ren (raddr[8]), // input
.regen (raddr8_d), // input
.data_out (c_out[8:0]), // output[8:0]
.wclk (clk), // input
.waddr ({2'b0,wpage[1:0],yaddrw[7:0]}), // input[11:0]
.we (ywe), // input
.web (8'hf), // input[7:0]
.data_in (y_in[8:0]) // input[71:0]
);
/*
RAMB16_S9_S9 i_y_buff (
.DOA(), // Port A 8-bit Data Output
.DOPA(), // Port A 8-bit Parity Output
.ADDRA({1'b0,wpage[1:0],yaddrw[7:0]}), // Port A 11-bit Address Input
.CLKA(clk), // Port A Clock
.DIA(y_in[7:0]), // Port A 8-bit Data Input
.DIPA(y_in[8]), // Port A 1-bit parity Input
.ENA(ywe), // Port A RAM Enable Input
.SSRA(1'b0), // Port A Synchronous Set/Reset Input
.WEA(1'b1), // Port A Write Enable Input
.DOB(y_out[7:0]), // Port B 8-bit Data Output
.DOPB(y_out[8]), // Port B 1-bit Parity Output
.ADDRB({1'b0,rpage[1:0],raddr[7:0]}), // Port B 11-bit Address Input
.CLKB(clk), // Port B Clock
.DIB(8'h0), // Port B 8-bit Data Input
.DIPB(1'h0), // Port-B 1-bit parity Input
.ENB(!raddr[8]), // PortB RAM Enable Input
.SSRB(1'b0), // Port B Synchronous Set/Reset Input
.WEB(1'b0) // Port B Write Enable Input
);
RAMB16_S9_S9 i_CrCb_buff (
.DOA(), // Port A 8-bit Data Output
.DOPA(), // Port A 8-bit Parity Output
.ADDRA({1'b0,wpage[1:0],caddrw[7:0]}), // Port A 11-bit Address Input
.CLKA(clk), // Port A Clock
.DIA(c_in[7:0]), // Port A 8-bit Data Input
.DIPA(c_in[8]), // Port A 1-bit parity Input
.ENA(cwe), // Port A RAM Enable Input
.SSRA(1'b0), // Port A Synchronous Set/Reset Input
.WEA(1'b1), // Port A Write Enable Input
.DOB(c_out[7:0]), // Port B 8-bit Data Output
.DOPB(c_out[8]), // Port B 1-bit Parity Output
.ADDRB({1'b0,rpage[1:0],raddr[7:0]}), // Port B 11-bit Address Input
.CLKB(clk), // Port B Clock
.DIB(8'h0), // Port B 8-bit Data Input
.DIPB(1'h0), // Port-B 1-bit parity Input
.ENB(raddr[8]), // PortB RAM Enable Input
.SSRB(1'b0), // Port B Synchronous Set/Reset Input
.WEB(1'b0) // Port B Write Enable Input
);
*/
endmodule
/*
** -----------------------------------------------------------------------------**
** csconvert18a.v
**
** Color space converter (bayer-> YCbCr 4:2:1) for JPEG compressor
**
** Copyright (C) 2002-20015 Elphel, Inc
**
** -----------------------------------------------------------------------------**
** This file is part of X393
** X393 is free software - hardware description language (HDL) code.
**
** This program 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.
**
** This program 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/>.
** -----------------------------------------------------------------------------**
**
*/
// 2015: Updating for 393, removing old SRL16 primitives
/*
09/07/2002 Andrey Filippov
Compared to spreadsheet simulation. Y - matches, CbCr in ~25% give result one less than spreadsheet simulation.
It is always odd and s.s. gives next even
TODO: optimize sequencing counters and possibly add some extra bits - as to calculate int((a+b+c+d)/4)
instead of int((int((a+b)/2)+int((c+d)/2))/2)
Color space converter processes one MCU at a time. It receives 18x18 8-bit bayer pixels (now it is always in (GR/BG)
sequence). With some latency it will produce 16x16x8 bit Y data (could be some artifacts on the borders) in scan-line
sequence and clock rate and Cb and Cr at the same time at half rate, so 4:2:0 will be generated at the same
time.
update: now it processes overlapping tiles (18x18) to avoid problems on the MCU boarders
Y= 0.299*R+0.587*G+0.114*B
Cb=-0.168*R-0.3313*G+0.5*B = 0.564*(B-Y)+128
Cr=0.5*R-0.4187*G-0.0813*B = 0.713*(R-Y)+128
For Bayer array (GR/BG)(bayer_phase[1:0]==0), and pixels P[Y,X]:
R[0,0]=0.5* (P[0,-1]+P[0,1])
R[0,1]= P[0,1]
R[1,0]=0.25*(P[0,-1]+P[0,1]+P[2,-1]+P[2,1])
R[1,1]=0.5 *(P[0,1] +P[2,1])
G[0,0]= P[0,0]
G[0,1]=0.25*(P[-1,1]+P[0,0]+P[0,2]+P[1,1])
G[1,0]=0.25*(P[0,0]+P[1,-1]+P[1,1]+P[2,0])
G[1,1]= P[1,1]
B[0,0]=0.5* (P[-1,0]+P[1,0])
B[0,1]=0.25*(P[-1,0]+P[-1,2]+P[1,0]+P[1,2])
B[1,0]= P[1,0]
B[1,1]=0.5* (P[1,0]+P[1,2])
Y[0,0]=0.299*0.5*(P[0,-1]+P[0,1]) + 0.587*P[0,0] + 0.114*0.5* (P[-1,0]+P[1,0])
Y[0,1]=0.299*P[0,1]+0.587*0.25*(P[-1,1]+P[0,0]+P[0,2]+P[1,1])+0.114*0.25*(P[-1,0]+P[-1,2]+P[1,0]+P[1,2])
Y[1,0]=0.299*0.25*(P[0,-1]+P[0,1]+P[2,-1]+P[2,1])+0.587*0.25*(P[0,0]+P[1,-1]+P[1,1]+P[2,0])+0.114*P[1,0]
Y[1,1]=0.299*0.5 *(P[0,1] +P[2,1])+0.587*P[1,1]+0.114*0.5* (P[1,0]+P[1,2])
Y[0,0]=(0x96*P[0,0]+ 0x4d*((P[0,-1]+P[0,1])/2) + 0x1d*((P[-1,0]+P[1,0])/2))>>8
Y[0,1]=(0x4d*P[0,1]+ 0x96*((P[-1,1]+P[0,0]+P[0,2]+P[1,1])/4)+ 0x1d*((P[-1,0]+P[-1,2]+P[1,0]+P[1,2])/4))>>8
Y[1,0]=(0x1d*P[1,0]+ 0x96*((P[0,0]+P[1,-1]+P[1,1]+P[2,0])/4)+ 0x4d*((P[0,-1]+P[0,1]+P[2,-1]+P[2,1])/4))>>8
Y[1,1]=(0x96*P[1,1]+ 0x1d*((P[1,0]+P[1,2])/2) + 0x4d*((P[0,1] +P[2,1])/2)))>>8
Cb and Cy are needed 1 for each 4 pixels (4:2:0)
(YC= 0.299*P[0,1]+0.587*(0.5*P[0,0]+P[1,1])+0.114*P[1,0] )
Cb=0.564*(P[1,0]-(0.299*P[0,1]+0.587*0.5*(P[0,0]+P[1,1])+0.114*P[1,0]))+128
Cr=0.713*(P[0,1]-(0.299*P[0,1]+0.587*0.5*(P[0,0]+P[1,1])+0.114*P[1,0]))+128
Cb=0.564*(P[1,0]-(0.299*P[0,1]+0.587*0.5*(P[0,0]+P[1,1])+0.114*P[1,0]))+128=
0.564*P[1,0]-0.299*0.564*P[0,1]-0.587*0.564*0.5*(P[0,0]+P[1,1])-0.114*0.564*P[1,0]))+128=
0.564*P[1,0]-0.168636*P[0,1]-0.165534*P[0,0]-0.165534*P[1,1]-0.064638*P[1,0]+128=
0.499362*P[1,0]-0.168636*P[0,1]-0.165534*P[0,0]-0.165534*P[1,1]+128=
-0.165534*P[0,0] -0.168636*P[0,1] +0.499362*P[1,0] -0.165534*P[1,1]+ 128=
(-256*0.165534*P[0,0] -256*0.168636*P[0,1] +256*0.499362*P[1,0] -256*0.165534*P[1,1])>>8+ 128=
(-42.5*P[0,0] -43*P[0,1] +128*P[1,0] -42.5*P[1,1])>>8+ 128=
(-85*((P[0,0]+P[1,1])/2) -43*P[0,1] +128*P[1,0])>>8+ 128=
(-0x55*((P[0,0]+P[1,1])/2) -2b*P[0,1] +P[1,0]<<7)>>8+ 0x80=
(-0x55*((P[0,0]+P[1,1])/2) -2b*P[0,1])>>8 +P[1,0]>>1 +0x80=
Cr=0.713*(P[0,1]-(0.299*P[0,1]+0.587*0.5*(P[0,0]+P[1,1])+0.114*P[1,0]))+128=
0.713* P[0,1]- 0.713*0.299*P[0,1] - 0.713*0.587*0.5*P[0,0]- 0.713*0.587*0.5*P[1,1] -0.713*0.114*P[1,0]+128=
0.713* P[0,1]- 0.213187*P[0,1] - 0.2092655*P[0,0]- 0.2092655*P[1,1] -0.081282*P[1,0]+128=
0.499813* P[0,1] -0.2092655*P[0,0] -0.2092655*P[1,1] -0.081282*P[1,0]+128=
-0.2092655*P[0,0] +0.499813* P[0,1] -0.081282*P[1,0] -0.2092655*P[1,1] +128=
(-256*0.2092655*P[0,0] +256*0.499813* P[0,1] -256*0.081282*P[1,0] -256*0.2092655*P[1,1])>>8 +128=
(-54*P[0,0] +128* P[0,1] -21*P[1,0] -54*P[1,1])>>8 +128= // rounded up, sum=129 -> decreasing
(-53.5*P[0,0] +128* P[0,1] -21*P[1,0] -53.5*P[1,1])>>8 +128=
(-107*((P[0,0]+P[1,1])/2) +P[0,1]<<7 -21*P[1,0])>>8 +128=
(-0x6b*((P[0,0]+P[1,1])/2) +P[0,1]<<7 -0x15*P[1,0])>>8 +0x80=
(-0x6b*((P[0,0]+P[1,1])/2) -0x15*P[1,0])>>8 +P[0,1]>>1 +0x80=
*/ /*
For Bayer array (RG/GB)(bayer_phase[1:0]==1), and pixels P[Y,X]:
R[0,0]= P[0,0]
R[0,1]=0.5 *(P[0,0]+P[0,2])
R[1,0]=0.5 *(P[0,0]+P[2,0])
R[1,1]=0.25*(P[0,0]+P[0,2]+P[2,0]+P[2,2])
G[0,0]=0.25*(P[-1,0]+P[0,-1]+P[0,1]+P[1,0])
G[0,1]= P[0,1]
G[1,0]= P[1,0]
G[1,1]=0.25*(P[0,1]+P[1,0]+P[1,2]+P[2,1])
B[0,0]=0.25*(P[-1,-1]+P[-1,1]+P[1,-1]+P[1,1])
B[0,1]=0.5* (P[-1,1]+P[1,1])
B[1,0]=0.5* (P[1,-1]+P[1,1])
B[1,1]= P[1,1]
Y[0,0]=0.299*P[0,0] + 0.587*0.25*(P[-1,0]+P[0,-1]+P[0,1]+P[1,0]) + 0.114*0.25*(P[-1,-1]+P[-1,1]+P[1,-1]+P[1,1])
Y[0,1]=0.299*0.5 *(P[0,0]+P[0,2])+0.587*P[0,1]+0.114*0.5* (P[-1,1]+P[1,1])
Y[1,0]=0.299*0.5 *(P[0,0]+P[2,0])+0.587*P[1,0]+0.114*0.5* (P[1,-1]+P[1,1])
Y[1,1]=0.299*0.25*(P[0,0]+P[0,2]+P[2,0]+P[2,2])+0.587*0.25*(P[0,1]+P[1,0]+P[1,2]+P[2,1])+0.114*P[1,1]
Y[0,0]=(0x4d*P[0,0]+ 0x96*((P[-1,0]+P[0,-1]+P[0,1]+P[1,0])/4) + 0x1d*((P[-1,-1]+P[-1,1]+P[1,-1]+P[1,1])/4))>>8
Y[0,1]=(0x96*P[0,1]+ 0x4d*((P[0,0]+P[0,2])/2)+ 0x1d*((P[-1,1]+P[1,1])/2))>>8
Y[1,0]=(0x96*P[1,0]+ 0x4d*((P[0,0]+P[2,0])/2)+ 0x1d*((P[1,-1]+P[1,1])/2))>>8
Y[1,1]=(0x1d*P[1,1]+ 0x96*((P[0,1]+P[1,0]+P[1,2]+P[2,1])/4) + 0x4d*((P[0,0]+P[0,2]+P[2,0]+P[2,2])/4)))>>8
Cb and Cy are needed 1 for each 4 pixels (4:2:0)
(YC= 0.299*P[0,0]+0.587*(0.5*P[0,1]+P[1,0])+0.114*P[1,1] )
Cb=0.564*(P[1,1]-(0.299*P[0,0]+0.587*0.5*(P[0,1]+P[1,0])+0.114*P[1,1]))+128
Cr=0.713*(P[0,0]-(0.299*P[0,0]+0.587*0.5*(P[0,1]+P[1,0])+0.114*P[1,1]))+128
Cb=0.564*(P[1,1]-(0.299*P[0,0]+0.587*0.5*(P[0,1]+P[1,0])+0.114*P[1,1]))+128=
(-0x55*((P[0,1]+P[1,0])/2) -2b*P[0,0] +P[1,1]<<7)>>8+ 0x80=
(-0x55*((P[0,1]+P[1,0])/2) -2b*P[0,0])>>8 +P[1,1]>>1 +0x80=
Cr=0.713*(P[0,0]-(0.299*P[0,0]+0.587*0.5*(P[0,1]+P[1,0])+0.114*P[1,1]))+128=
(-0x6b*((P[0,1]+P[1,0])/2) +P[0,0]<<7 -0x15*P[1,1])>>8 +0x80=
(-0x6b*((P[0,1]+P[1,0])/2) -0x15*P[1,1])>>8 +P[0,0]>>1 +0x80=
----
*/ /*
For Bayer array (BG/GR)(bayer_phase[1:0]==2), and pixels P[Y,X]:
R[0,0]=0.25*(P[-1,-1]+P[-1,1]+P[1,-1]+P[1,1])
R[0,1]=0.5 *(P[-1,1] +P[1,1])
R[1,0]=0.5* (P[1,-1]+P[1,1])
R[1,1]= P[1,1]
G[0,0]=0.25*(P[-1,0]+P[0,-1]+P[0,1]+P[1,0])
G[0,1]= P[0,1]
G[1,0]= P[1,0]
G[1,1]=0.25*(P[0,1]+P[1,0]+P[1,2]+P[2,1])
B[0,0]= P[0,0]
B[0,1]=0.5* (P[0,0]+P[0,2])
B[1,0]=0.5* (P[0,0]+P[2,0])
B[1,1]=0.25*(P[0,0]+P[0,2]+P[2,0]+P[2,2])
Y[0,0]=0.299*0.25*(P[-1,-1]+P[-1,1]+P[1,-1]+P[1,1]) + 0.587*0.25*(P[-1,0]+P[0,-1]+P[0,1]+P[1,0]) + 0.114* P[0,0]
Y[0,1]=0.299*0.5 *(P[-1,1] +P[1,1])+0.587*P[0,1]+0.114*0.5* (P[0,0]+P[0,2])
Y[1,0]=0.299*0.5* (P[1,-1]+P[1,1])+0.587*P[1,0]+0.114*0.5* (P[0,0]+P[2,0])
Y[1,1]=0.299*P[1,1]+0.587*0.25*(P[0,1]+P[1,0]+P[1,2]+P[2,1])+0.114*0.25*(P[0,0]+P[0,2]+P[2,0]+P[2,2])
Y[0,0]=(0x1d*P[0,0]+ 0x96*((P[-1,0]+P[0,-1]+P[0,1]+P[1,0])/4)+ 0x4d*((P[-1,-1]+P[-1,1]+P[1,-1]+P[1,1])/4))>>8
Y[0,1]=(0x96*P[0,1]+ 0x4d*((P[-1,1] +P[1,1])/2)+ 0x1d*((P[0,0]+P[0,2])/2))>>8
Y[1,0]=(0x96*P[1,0]+ 0x4d*((P[1,-1]+P[1,1])/2)+ 0x1d*((P[0,0]+P[2,0])/2))>>8
Y[1,1]=(0x4d*P[1,1]+ 0x96*((P[0,1]+P[1,0]+P[1,2]+P[2,1])/4) + 0x1d*((P[0,0]+P[0,2]+P[2,0]+P[2,2])/4)))>>8
Cb and Cy are needed 1 for each 4 pixels (4:2:0)
(YC= 0.299*P[1,1]+0.587*(0.5*P[1,0]+P[0,1])+0.114*P[0,0] )
Cb=0.564*(P[0,0]-(0.299*P[1,1]+0.587*0.5*(P[1,0]+P[0,1])+0.114*P[0,0]))+128
Cr=0.713*(P[1,1]-(0.299*P[1,1]+0.587*0.5*(P[1,0]+P[0,1])+0.114*P[0,0]))+128
Cb=0.564*(P[0,0]-(0.299*P[1,1]+0.587*0.5*(P[1,0]+P[0,1])+0.114*P[0,0]))+128=
(-0x55*((P[1,0]+P[0,1])/2) -2b*P[1,1] +P[0,0]<<7)>>8+ 0x80=
(-0x55*((P[1,0]+P[0,1])/2) -2b*P[1,1])>>8 +P[0,0]>>1 +0x80=
Cr=0.713*(P[1,1]-(0.299*P[1,1]+0.587*0.5*(P[1,0]+P[0,1])+0.114*P[0,0]))+128=
(-0x6b*((P[1,0]+P[0,1])/2) +P[1,1]<<7 -0x15*P[0,0])>>8 +0x80=
(-0x6b*((P[1,0]+P[0,1])/2) -0x15*P[0,0])>>8 +P[1,1]>>1 +0x80=
----
*/ /*
For Bayer array (GB/RG)(bayer_phase[1:0]==3), and pixels P[Y,X]:
R[0,0]=0.5 *(P[-1,0]+P[1,0])
R[0,1]=0.25*(P[-1,0]+P[-1,2]+P[1,0]+P[1,2])
R[1,0]= P[1,0]
R[1,1]=0.5 *(P[1,0]+P[1,2])
G[0,0]= P[0,0]
G[0,1]=0.25*(P[-1,1]+P[0,0]+P[0,2]+P[1,1])
G[1,0]=0.25*(P[0,0]+P[1,-1]+P[1,1]+P[2,0])
G[1,1]= P[1,1]
B[0,0]=0.5* (P[0,-1]+P[0,1])
B[0,1]= P[0,1]
B[1,0]=0.25*(P[0,-1]+P[0,1]+P[2,-1]+P[2,1])
B[1,1]=0.5* (P[0,1]+P[2,1])
Y[0,0]=0.299*0.5 *(P[-1,0]+P[1,0]) + 0.587*P[0,0] + 0.114*0.5* (P[0,-1]+P[0,1])
Y[0,1]=0.299*0.25*(P[-1,0]+P[-1,2]+P[1,0]+P[1,2])+0.587*0.25*(P[-1,1]+P[0,0]+P[0,2]+P[1,1])+0.114*P[0,1]
Y[1,0]=0.299*P[1,0]+0.587*0.25*(P[0,-1]+P[0,1]+P[2,-1]+P[2,1])+0.114*0.25*(P[0,-1]+P[0,1]+P[2,-1]+P[2,1])
Y[1,1]=0.299*0.5 *(P[1,0]+P[1,2])+0.587*P[1,1]+0.114*0.5* (P[0,1]+P[2,1])
Y[0,0]=(0x96*P[0,0]+ 0x4d*((P[-1,0]+P[1,0])/2) + 0x1d*((P[0,-1]+P[0,1])/2))>>8
Y[0,1]=(0x1d*P[0,1]+ 0x96*((P[-1,1]+P[0,0]+P[0,2]+P[1,1])/4)+ 0x4d*((P[-1,0]+P[-1,2]+P[1,0]+P[1,2])/4))>>8
Y[1,0]=(0x4d*P[1,0]+ 0x96*((P[0,0]+P[1,-1]+P[1,1]+P[2,0])/4)+ 0x1d*((P[0,-1]+P[0,1]+P[2,-1]+P[2,1])/4))>>8
Y[1,1]=(0x96*P[1,1]+ 0x4d*((P[1,0]+P[1,2])/2 + 0x1d*((P[0,1] +P[2,1])/2)))>>8
Cb and Cy are needed 1 for each 4 pixels (4:2:0)
(YC= 0.299*P[1,0]+0.587*(0.5*P[1,1]+P[0,0])+0.114*P[0,1] )
Cb=0.564*(P[0,1]-(0.299*P[1,0]+0.587*0.5*(P[1,1]+P[0,0])+0.114*P[0,1]))+128
Cr=0.713*(P[1,0]-(0.299*P[1,0]+0.587*0.5*(P[1,1]+P[0,0])+0.114*P[0,1]))+128
Cb=0.564*(P[0,1]-(0.299*P[1,0]+0.587*0.5*(P[1,1]+P[0,0])+0.114*P[0,1]))+128=
(-0x55*((P[1,1]+P[0,0])/2) -2b*P[1,0] +P[0,1]<<7)>>8+ 0x80=
(-0x55*((P[1,1]+P[0,0])/2) -2b*P[1,0])>>8 +P[0,1]>>1 +0x80=
Cr=0.713*(P[1,0]-(0.299*P[1,0]+0.587*0.5*(P[1,1]+P[0,0])+0.114*P[0,1]))+128=
(-0x6b*((P[1,1]+P[0,0])/2) +P[1,0]<<7 -0x15*P[0,1])>>8 +0x80=
(-0x6b*((P[1,1]+P[0,0])/2) -0x15*P[0,1])>>8 +P[1,0]>>1 +0x80=
----
*/
/* 02/24/2003 - modified to include bypass for monochrome mode*/
/* 06/29/2004 - added counting of pixels with value of 0 and 255 (limited to 255 to use just 8 bits) */
//05.07.2008 - latency included here
module csconvert18a(
input RST,
input CLK,
input mono,
input limit_diff, // 1 - limit color outputs to -128/+127 range, 0 - let them be limited downstream
input [ 9:0] m_cb, // [9:0] scale for CB - default 0.564 (10'h90)
input [ 9:0] m_cr, // [9:0] scale for CB - default 0.713 (10'hb6)
input [ 7:0] din, // input bayer data in scanline sequence, GR/BG sequence
input pre_first_in, // marks the first input pixel
output [ 7:0] signed_y, // - now signed char, -128(black) to +127 (white)
output [ 8:0] q, // new, q is just signed char
output [ 7:0] yaddr, // address for the external buffer memory to write 16x16x8bit Y data
output ywe, // wrire enable of Y data
output [ 6:0] caddr, // address for the external buffer memory 2x8x8x8bit Cb+Cr data (MSB=0 - Cb, 1 - Cr)
output cwe, // write enable for CbCr data
output pre_first_out,
input [ 1:0] bayer_phase,
output [ 7:0] n000,
output [ 7:0] n255);
// Was: s ynthesis attribute shreg_extract of csconvert18a is yes;"
wire ystrt,nxtline;
reg [7:0] yaddr_r; // address for the external buffer memory to write 16x16x8bit Y data
reg ywe_r; // wrire enable of Y data
reg [6:0] caddr_r; // address for the external buffer memory 2x8x8x8bit Cb+Cr data (MSB=0 - Cb, 1 - Cr)
reg cwe_r; // write enable for CbCr data
reg odd_pix; // odd pixel (assumes even number of pixels in a line
reg odd_line; // odd line
reg pix_green;// (was "odd_pix==odd_line", now modified with bayer_phase[1:0]: bayer_phase[1]^bayer_phase[0]^(odd_pix==odd_line)
reg y_eq_0, y_eq_255;
reg [7:0] n000_r;
reg [7:0] n255_r;
wire [1:0] strt_dly;
wire strt;
reg [7:0] signed_y_r;
assign pre_first_out=ystrt;
assign n000 = n000_r;
assign n255 = n255_r;
assign signed_y = signed_y_r; // - now signed char, -128(black) to +127 (white)
assign yaddr = yaddr_r;
assign ywe = ywe_r;
assign caddr = caddr_r;
assign cwe = cwe_r;
dly_16 #(.WIDTH(1)) i_strt_dly0 (.clk(CLK),.rst(1'b0), .dly(15), .din(pre_first_in), .dout(strt_dly[0]));
dly_16 #(.WIDTH(1)) i_strt_dly1 (.clk(CLK),.rst(1'b0), .dly(15), .din(strt_dly[0]), .dout(strt_dly[1]));
dly_16 #(.WIDTH(1)) i_strt (.clk(CLK),.rst(1'b0), .dly( 4), .din(strt_dly[1]), .dout(strt));
// SRL16 i_strt_dly0 (.Q(strt_dly[0]), .D(pre_first_in), .CLK(CLK), .A0(1'b1), .A1(1'b1), .A2(1'b1), .A3(1'b1)); // dly=15+1
// SRL16 i_strt_dly1 (.Q(strt_dly[1]), .D(strt_dly[0]), .CLK(CLK), .A0(1'b1), .A1(1'b1), .A2(1'b1), .A3(1'b1)); // dly=15+1
// SRL16 i_strt (.Q(strt), .D(strt_dly[1]), .CLK(CLK), .A0(1'b0), .A1(1'b0), .A2(1'b1), .A3(1'b0)); // dly=4+1
dly_16 #(.WIDTH(1)) i_ystrt (.clk(CLK),.rst(1'b0), .dly(5), .din(strt), .dout(ystrt));
dly_16 #(.WIDTH(1)) i_nxtline (.clk(CLK),.rst(1'b0), .dly(1), .din(!RST && ywe_r && (yaddr_r[3:0]==4'hf) && (yaddr_r[7:4]!=4'hf)), .dout(nxtline));
// SRL16 i_ystrt (.Q(ystrt), .D(strt), .CLK(CLK), .A0(1'b1), .A1(1'b0), .A2(1'b1), .A3(1'b0)); // dly=5+1
// SRL16 i_nxtline(.Q(nxtline),.D(!RST && ywe_r && (yaddr_r[3:0]==4'hf) && (yaddr_r[7:4]!=4'hf)), .CLK(CLK), .A0(1'b1), .A1(1'b0), .A2(1'b0), .A3(1'b0)); // dly=1+1
always @ (posedge CLK) begin
ywe_r <= !RST && (ystrt || nxtline || (ywe_r && (yaddr_r[3:0]!=4'hf)));
yaddr_r[7:4] <= (RST || strt)? 4'h0: (nxtline?(yaddr_r[7:4]+1):yaddr_r[7:4]);
yaddr_r[3:0] <= ywe_r? (yaddr_r[3:0]+1):4'h0;
odd_pix <= RST || strt || ~odd_pix;
if (RST || strt) odd_line <= 1'b0;
else if (yaddr_r[3:0]==4'hd) odd_line <= ~odd_line;
if (RST || strt) pix_green <=bayer_phase[1]^bayer_phase[0];
else pix_green <=~(yaddr_r[3:0]==4'hd)^pix_green;
end
// First block generates 2 8-bit values (latency=3)- pixel (p2) and average value of previous and next pixel in the same
// row (pa). For the first pixel that "average" equals to next pixel, for the last - previous
reg [7:0] p0;
reg [7:0] p1;
reg [7:0] pd0;
reg [7:0] pa0;
wire [8:0] ppa;
always @ (posedge CLK) p0 <= din[7:0];
always @ (posedge CLK) p1 <= p0[7:0];
// always @ (posedge CLK) pd0 <= p1[7:0];
always @ (posedge RST or posedge CLK) if (RST) pd0 <= 8'b0; else pd0 <= p1[7:0]; // generates more effective than with 2-bit SRs (line above)
assign ppa[8:0]={1'b0,pd0}+{1'b0,p0};
always @ (posedge CLK) pa0 <=ppa[8:1]; //loosing 1 bit here!
// next - 2 pairs of 8 bit wide 16-bit long serial-in, serial out shift registers. Verify implementation - Should use 32 LUTs
// update 06/10/2004 - make an output pd_c[7:0] 2 cycles after pd_1[7:0] for color processing without additional resources
reg [17:0] pd_10,pd_11,pd_12,pd_13,pd_14,pd_15,pd_16,pd_17;
// reg [17:0] pd_20,pd_21,pd_22,pd_23,pd_24,pd_25,pd_26,pd_27;
reg [7:0] pd1_dly;
reg [7:0] pdc;
reg [15:0] pd_20,pd_21,pd_22,pd_23,pd_24,pd_25,pd_26,pd_27;
reg [17:0] pa_10,pa_11,pa_12,pa_13,pa_14,pa_15,pa_16,pa_17;
reg [17:0] pa_20,pa_21,pa_22,pa_23,pa_24,pa_25,pa_26,pa_27;
wire [7:0] pd1;
wire [7:0] pd2;
wire [7:0] pa1;
wire [7:0] pa2;
assign pd1={pd_17[17],pd_16[17],pd_15[17],pd_14[17],pd_13[17],pd_12[17],pd_11[17],pd_10[17]};
assign pd2={pd_27[15],pd_26[15],pd_25[15],pd_24[15],pd_23[15],pd_22[15],pd_21[15],pd_20[15]};
assign pa1={pa_17[17],pa_16[17],pa_15[17],pa_14[17],pa_13[17],pa_12[17],pa_11[17],pa_10[17]};
assign pa2={pa_27[17],pa_26[17],pa_25[17],pa_24[17],pa_23[17],pa_22[17],pa_21[17],pa_20[17]};
always @ (posedge CLK) pd_10 <= {pd_10[16:0],pd0[0]};
always @ (posedge CLK) pd_11 <= {pd_11[16:0],pd0[1]};
always @ (posedge CLK) pd_12 <= {pd_12[16:0],pd0[2]};
always @ (posedge CLK) pd_13 <= {pd_13[16:0],pd0[3]};
always @ (posedge CLK) pd_14 <= {pd_14[16:0],pd0[4]};
always @ (posedge CLK) pd_15 <= {pd_15[16:0],pd0[5]};
always @ (posedge CLK) pd_16 <= {pd_16[16:0],pd0[6]};
always @ (posedge CLK) pd_17 <= {pd_17[16:0],pd0[7]};
always @ (posedge CLK) pd1_dly[7:0] <= pd1[7:0];
always @ (posedge CLK) pdc[7:0] <= pd1_dly[7:0];
always @ (posedge CLK) pd_20 <= {pd_20[14:0],pdc[0]};
always @ (posedge CLK) pd_21 <= {pd_21[14:0],pdc[1]};
always @ (posedge CLK) pd_22 <= {pd_22[14:0],pdc[2]};
always @ (posedge CLK) pd_23 <= {pd_23[14:0],pdc[3]};
always @ (posedge CLK) pd_24 <= {pd_24[14:0],pdc[4]};
always @ (posedge CLK) pd_25 <= {pd_25[14:0],pdc[5]};
always @ (posedge CLK) pd_26 <= {pd_26[14:0],pdc[6]};
always @ (posedge CLK) pd_27 <= {pd_27[14:0],pdc[7]};
always @ (posedge CLK) pa_10 <= {pa_10[16:0],pa0[0]};
always @ (posedge CLK) pa_11 <= {pa_11[16:0],pa0[1]};
always @ (posedge CLK) pa_12 <= {pa_12[16:0],pa0[2]};
always @ (posedge CLK) pa_13 <= {pa_13[16:0],pa0[3]};
always @ (posedge CLK) pa_14 <= {pa_14[16:0],pa0[4]};
always @ (posedge CLK) pa_15 <= {pa_15[16:0],pa0[5]};
always @ (posedge CLK) pa_16 <= {pa_16[16:0],pa0[6]};
always @ (posedge CLK) pa_17 <= {pa_17[16:0],pa0[7]};
always @ (posedge CLK) pa_20 <= {pa_20[16:0],pa_10[17]};
always @ (posedge CLK) pa_21 <= {pa_21[16:0],pa_11[17]};
always @ (posedge CLK) pa_22 <= {pa_22[16:0],pa_12[17]};
always @ (posedge CLK) pa_23 <= {pa_23[16:0],pa_13[17]};
always @ (posedge CLK) pa_24 <= {pa_24[16:0],pa_14[17]};
always @ (posedge CLK) pa_25 <= {pa_25[16:0],pa_15[17]};
always @ (posedge CLK) pa_26 <= {pa_26[16:0],pa_16[17]};
always @ (posedge CLK) pa_27 <= {pa_27[16:0],pa_17[17]};
wire [7:0] pd_prev= pd2[7:0];
wire [7:0] pd_next= pd0[7:0];
wire [7:0] pa_prev= pa2[7:0];
wire [7:0] pa_next= pa0[7:0];
// now the result Y calculation depends on the pixel position (bx,by). It consists of 3 terms, each with different coefficient.
// first term always includes pd1[7:0]
// if (bx[1]==by[1]) // 00 or 11
// second term is pa1, third - (pd0+pd2)/2
// else
// second term is (pa1 + (pd0+pd2)/2)/2, third - (pa0+pa2)/2
reg [7:0] m1;
reg [7:0] m2;
reg [7:0] m3;
wire [8:0] pd02s= {1'b0,pd_prev[7:0]}+{1'b0,pd_next[7:0]}; // will use pd02s[8:1]
wire [8:0] pa1pd02s={1'b0,pa1[7:0]}+{1'b0,pd02s[8:1]}; // will use pa1pd02s[8:1]
wire [8:0] pa02s= {1'b0,pa_prev[7:0]}+{1'b0,pa_next[7:0]}; // will use pa02s[8:1]
always @ (posedge CLK) m1 <= pd1[7:0];
// always @ (posedge CLK) m2 <= (odd_pix==odd_line)? pa1[7:0] : pa1pd02s[8:1];
// always @ (posedge CLK) m3 <= (odd_pix==odd_line)? pd02s[8:1] : pa02s[8:1];
always @ (posedge CLK) m2 <= pix_green? pa1[7:0] : pa1pd02s[8:1];
always @ (posedge CLK) m3 <= pix_green? pd02s[8:1] : pa02s[8:1];
/*
Y[0,0]=(0x96*P[0,0]+ 0x4d*((P[0,-1]+P[0,1])/2) + 0x1d*((P[-1,0]+P[1,0])/2))>>8
Y[0,1]=(0x4d*P[0,1]+ 0x96*((P[-1,1]+P[0,0]+P[0,2]+P[1,1])/4)+ 0x1d*((P[-1,0]+P[-1,2]+P[1,0]+P[1,2])/4))>>8
Y[1,0]=(0x1d*P[1,0]+ 0x96*((P[0,0]+P[1,-1]+P[1,1]+P[2,0])/4)+ 0x4d*((P[0,-1]+P[0,1]+P[2,-1]+P[2,1])/4))>>8
Y[1,1]=(0x96*P[1,1]+ 0x1d*((P[1,0]+P[1,2])/2 + 0x4d*((P[0,1] +P[2,1])/2)))>>8
+-----+--------+-------+-------+-------+-------+-------+
| | (0) | | | * | * | * * |
| | G R | * | * + * | + | * + * | + |
| | B G | | | * | * | * * |
+-----+--------+-------+-------+-------+-------+-------+
| 0 | P[0,0] | 0x96 | 0x4d | 0x1d | | |
| +--------+-------+-------+-------+-------+-------+
| G R | P[0,1] | 0x4d | | | 0x96 | 0x1d |
| +--------+-------+-------+-------+-------+-------+
| B G | P[1,0] | 0x1d | | | 0x96 | 0x4d |
| +--------+-------+-------+-------+-------+-------+
| | P[1,1] | 0x96 | 0x1d | 0x4d | | |
+-----+--------+-------+-------+-------+-------+-------+
| 1 | P[0,0] | 0x4d | | | 0x96 | 0x1d |
| +--------+-------+-------+-------+-------+-------+
| R G | P[0,1] | 0x96 | 0x4d | 0x1d | | |
| +--------+-------+-------+-------+-------+-------+
| G B | P[1,0] | 0x96 | 0x1d | 0x4d | | |
| +--------+-------+-------+-------+-------+-------+
| | P[1,1] | 0x1d | | | 0x96 | 0x4d |
+-----+--------+-------+-------+-------+-------+-------+
| 2 | P[0,0] | 0x1d | | | 0x96 | 0x4d |
| +--------+-------+-------+-------+-------+-------+
| B G | P[0,1] | 0x96 | 0x1d | 0x4d | | |
| +--------+-------+-------+-------+-------+-------+
| G R | P[1,0] | 0x96 | 0x4d | 0x1d | | |
| +--------+-------+-------+-------+-------+-------+
| | P[1,1] | 0x4d | | | 0x96 | 0x1d |
+-----+--------+-------+-------+-------+-------+-------+
| 3 | P[0,0] | 0x96 | 0x1d | 0x4d | | |
| +--------+-------+-------+-------+-------+-------+
| G B | P[0,1] | 0x1d | | | 0x96 | 0x4d |
| +--------+-------+-------+-------+-------+-------+
| R G | P[1,0] | 0x4d | | | 0x96 | 0x1d |
| +--------+-------+-------+-------+-------+-------+
| | P[1,1] | 0x96 | 0x4d | 0x1d | | |
+-----+--------+-------+-------+-------+-------+-------+
*/
reg [7:0] k1;
reg [7:0] k2;
reg [7:0] k3;
always @ (posedge CLK) case ({bayer_phase[1:0],odd_line,odd_pix})
// 0 - GR/BG
4'b0000: begin
k1<=8'h96;
k2<=8'h4d;
k3<=8'h1d;
end
4'b0001: begin
k1<=8'h4d;
k2<=8'h96;
k3<=8'h1d;
end
4'b0010: begin
k1<=8'h1d;
k2<=8'h96;
k3<=8'h4d;
end
4'b0011: begin
k1<=8'h96;
k2<=8'h1d;
k3<=8'h4d;
end
// 1 - RG/GB
4'b0100: begin
k1<=8'h4d;
k2<=8'h96;
k3<=8'h1d;
end
4'b0101: begin
k1<=8'h96;
k2<=8'h4d;
k3<=8'h1d;
end
4'b0110: begin
k1<=8'h96;
k2<=8'h1d;
k3<=8'h4d;
end
4'b0111: begin
k1<=8'h1d;
k2<=8'h96;
k3<=8'h4d;
end
// 2 - BG/GR
4'b1000: begin
k1<=8'h1d;
k2<=8'h96;
k3<=8'h4d;
end
4'b1001: begin
k1<=8'h96;
k2<=8'h1d;
k3<=8'h4d;
end
4'b1010: begin
k1<=8'h96;
k2<=8'h4d;
k3<=8'h1d;
end
4'b1011: begin
k1<=8'h4d;
k2<=8'h96;
k3<=8'h1d;
end
// 3 - GB/RG
4'b1100: begin
k1<=8'h96;
k2<=8'h1d;
k3<=8'h4d;
end
4'b1101: begin
k1<=8'h1d;
k2<=8'h96;
k3<=8'h4d;
end
4'b1110: begin
k1<=8'h4d;
k2<=8'h96;
k3<=8'h1d;
end
4'b1111: begin
k1<=8'h96;
k2<=8'h4d;
k3<=8'h1d;
end
endcase
wire [15:0] mm1=m1[7:0]*k1[7:0];
wire [15:0] mm2=m2[7:0]*k2[7:0];
wire [15:0] mm3=m3[7:0]*k3[7:0];
reg [7:0] y;
reg [7:0] y0; // bypass in monochrome mode
// wire [7:0] y0; // bypass in monochrome mode
reg [15:0] y1,y2,y3;
wire [15:0] y_sum =y1+y2+y3;
always @ (posedge CLK) y0 <= m1;
always @ (posedge CLK) y1 <= mm1;
always @ (posedge CLK) y2 <= mm2;
always @ (posedge CLK) y3 <= mm3;
// making y output signed -128..+127
wire [7:0] pre_y= mono ? y0 : (y_sum[15:8]+y_sum[7]);
always @ (posedge CLK) y[7:0] <= pre_y[7:0];
always @ (posedge CLK) signed_y_r[7:0] <= {~pre_y[7], pre_y[6:0]};
// Try easier and hope better algorithm of color extractions that should perform better on gradients.
// It will rely on the fact that Y is already calculated, so instead of processing 4 pixels it will
// calculate Cb for "B" pixel, and Cr - for "R", subtracting calculated "Y" for that pixel.
//Cb = 0.564*(B-Y)+128
//Cr = 0.713*(R-Y)+128
// First - delay pd1[7:0] by 2 clock periods - to match "Y" output (one ahead, actually)
// It is better to implement it earlier - while calculating pd2 - anyway it had to be delayed by 18 (16+2) form pd1 - make it in 2 stages 2 +16
// pdc[7:0] - one cycle ahead of the "Y" for each pixel
// Try multiplication by constant without the register for that constant, just 2:1 mux. Still use aregister for the other operand (is it needed?)
reg [7:0] cbcrmult1;
//wire [7:0] cbcrmult2; // 1 of 2 constants - should be valid during ywe_r and 1 more cycle ("use_cr"
wire [9:0] cbcrmult2; // 1 of 2 constants - should be valid during ywe_r and 1 more cycle ("use_cr"
//wire [15:0] cbcrmulto; // output of 8x8 multiplier
wire [17:0] cbcrmulto; // output of 8x8 multiplier
// ignoring overflow we do not need extra bits
// high saturation can cause overflow, but we have very limited resources in model 313 to port back to
//reg [8:0] cbcrmultr; // 1 extra bit for precision (before subtraction)
reg [10:0] cbcrmultr; // 1 extra bit for precision (before subtraction)
//reg [8:0] cbcr; // after subraction (with extra bit preserved)
reg [10:0] cbcr; // after subraction (with extra bit preserved)
reg sel_cbcrmult1; // 0 - use pdc[7:0], 1 - use y[7:0]. Should be valid 1 cycle ahead of ywe_r!
reg use_cr; // in this line cr is calculated. Valid during ywe_r and 1 cycle after
reg sub_y; // output accumulator/subtractor. 0 - load new data, 1 - subtract. Walid 2 cycles after ywe_r
wire cwe0; // preliminary cwe_r (to be modulated by odd/even pixels)
reg cstrt; //ystrt dealyed by 1
reg cnxt; // nxtline delayed by 1
always @ (posedge CLK) begin
if (~(ywe_r || ystrt || nxtline)) sel_cbcrmult1 <= ~(bayer_phase[1] ^ bayer_phase[0] ^ odd_line);
else sel_cbcrmult1 <= ~sel_cbcrmult1;
sub_y <= ~sel_cbcrmult1;
cbcrmult1 <= sel_cbcrmult1?y[7:0]:pdc[7:0];
cbcrmult1 <= sel_cbcrmult1?y[7:0]:pdc[7:0];
if (~ywe_r) use_cr <= ~(bayer_phase[1] ^ odd_line);
end
assign cbcrmult2=use_cr?m_cr:m_cb; // maybe will need a register? (use_cr will still be good as it is valid early)
assign cbcrmulto=cbcrmult1*cbcrmult2;
// will preserve extra bit, but do not need to add half of the truncated MSB - on average there will be no shift after subtraction
always @ (posedge CLK) begin
cbcrmultr[10:0] <= cbcrmulto[17:7];
cbcr[10:0] <= sub_y? (cbcr[10:0]-cbcrmultr[10:0]+ 1'b1):cbcrmultr[10:0];
end
//limit_diff
// Here 0 is shifted to 0x80
// new, q is signed char
assign q[8:0]= ((cbcr[10]==cbcr[9]) && (!limit_diff || (cbcr[10]==cbcr[8])))? cbcr[9:1]: {cbcr[10],limit_diff?cbcr[10]:(~cbcr[10]),{7{~cbcr[10]}}};
dly_16 #(.WIDTH(1)) i_cwe0 (.clk(CLK),.rst(1'b0), .dly(1), .din(ywe_r), .dout(cwe0));
//SRL16 i_cwe0 (.D(ywe_r ), .Q(cwe0), .A0(1'b1), .A1(1'b0), .A2(1'b0), .A3(1'b0), .CLK(CLK)); // dly=2=1+1
always @ (posedge CLK) begin
cstrt <= ystrt;
cnxt <= nxtline;
cwe_r <= cwe0 && sub_y;
caddr_r[2:0]<= cwe0?(caddr_r[2:0]+cwe_r):3'b0;
if (cstrt) caddr_r[6] <= ~bayer_phase[1];
else if (cnxt) caddr_r[6] <= ~caddr_r[6];
if (cstrt) caddr_r[5:3] <=3'b0;
else if (cnxt) caddr_r[5:3] <=(bayer_phase[1]^caddr_r[6])? caddr_r[5:3]:(caddr_r[5:3]+1);
end
always @ (posedge CLK) begin
y_eq_0 <= (y0[7:0] == 8'h0);
y_eq_255 <= (y0[7:0] == 8'hff);
if (strt) n000_r[7:0] <= 8'h0;
else if ((n000_r[7:0]!=8'hff) && y_eq_0 && ywe_r) n000_r[7:0] <= n000_r[7:0]+1;
if (strt) n255_r[7:0] <= 8'h0;
else if ((n255_r[7:0]!=8'hff) && y_eq_255 && ywe_r) n255_r[7:0] <= n255_r[7:0]+1;
end
endmodule
/*******************************************************************************
* Module: csconvert_jp4
* Date:2015-06-10
* Author: andrey
* Description: Color conversion for JP4 mode
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* csconvert_jp4.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.
*
* csconvert_jp4.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 csconvert_jp4 (en,
clk,
din,
pre_first_in,
y_out,
yaddr,
ywe,
pre_first_out);
input en;
input clk; // clock
input [7:0] din; // input data in scanline sequence
input pre_first_in; // marks the first input pixel
output [7:0] y_out; // output Y (16x16) in scanline sequence. Valid if ys active
output [7:0] yaddr; // address for the external buffer memory to write 16x16x8bit Y data
output ywe; // wrire enable of Y data
output pre_first_out;
wire pre_first_out= pre_first_in;
wire [7:0] y_out= {~din[7],din[6:0]};
reg [7:0] yaddr_cntr;
reg ywe;
wire [7:0] yaddr= {yaddr_cntr[4],yaddr_cntr[7:5],yaddr_cntr[0],yaddr_cntr[3:1]};
always @ (posedge clk) begin
ywe <= en & (pre_first_in || (ywe && (yaddr[7:0] !=8'hff)));
if (!en || pre_first_in) yaddr_cntr[7:0] <= 8'h0;
else if (ywe) yaddr_cntr[7:0] <= yaddr_cntr[7:0] + 1;
end
endmodule
/*******************************************************************************
* Module: csconvert_jp4diff
* Date:2015-06-10
* Author: andrey
* Description: Color conversion for JP4 differential
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* csconvert_jp4diff.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.
*
* csconvert_jp4diff.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 csconvert_jp4diff (en,
clk,
scale_diff, // divide differences by 2 (to fit in 8-bit range)
hdr, // second green absolute, not difference
din,
pre_first_in,
y_out,
yaddr,
ywe,
pre_first_out,
bayer_phase);
// Was s ynthesis attribute shreg_extract of csconvert_jp4diff is yes;
input en;
input clk; // clock
input scale_diff;
input hdr;
input [7:0] din; // input data in scanline sequence
input pre_first_in; // marks the first input pixel
output [8:0] y_out; // output Y (16x16) in scanline sequence. Valid if ys active
output [7:0] yaddr; // address for the external buffer memory to write 16x16x8bit Y data
output ywe; // wrire enable of Y data
output pre_first_out;
input [1:0] bayer_phase; // selected pixel will be absolute, others - difference
reg pre_first_out;
reg [2:0] pre2_first_out;
reg [8:0] y_out;
reg [8:0] pre_y_out;
reg [7:0] yaddr_cntr;
reg [7:0] pre_yaddr_cntr;
reg [7:0] pre2_yaddr_cntr;
reg ywe;
reg [2:0] pre_ywe;
reg [7:0] yaddr;
reg dly_1;
reg [14:0] dly_16;
reg dly_17;
// wire start_out=bayer_phase[1]?(bayer_phase[0]?dly_17:dly_16):(bayer_phase[0]?dly_1:pre_first_in);
wire start_out=bayer_phase[1]?(bayer_phase[0]?dly_17:dly_16[14]):(bayer_phase[0]?dly_1:pre_first_in);
reg [7:0] iadr;
reg iadr_run;
reg [1:0] mux_plus_sel;
reg [2:0] mux_minus_sel;
reg hdr_bit;
reg [1:0] scale_color;
reg [1:0] is_color;
reg [7:0] mux_plus;
reg [7:0] mux_minus;
reg [7:0] dd0;
reg [7:0] dd1;
wire [7:0] dd16;
reg [7:0] dd17;
reg [14:0] ddsr0,ddsr1,ddsr2,ddsr3,ddsr4,ddsr5,ddsr6,ddsr7;
wire [8:0] scaled_pre_y_out= (scale_color[1])? +{pre_y_out[8],pre_y_out[8:1]}: pre_y_out[8:0];
assign dd16[7:0]={ddsr7[14],ddsr6[14],ddsr5[14],ddsr4[14],ddsr3[14],ddsr2[14],ddsr1[14],ddsr0[14]};
always @ (posedge clk) begin
dly_1 <= pre_first_in;
dly_17 <= dly_16[14];
dly_16[14:0] <= {dly_16[13:0],dly_1};
pre2_first_out[2:0]<= {pre2_first_out[1:0], start_out};
pre_first_out<= pre2_first_out[2];
iadr_run <= en & (start_out || (iadr_run && (iadr[7:0]!=8'hff)));
pre_ywe[2:0] <= {pre_ywe[1:0],iadr_run};
ywe <= pre_ywe[2];
if (!en || start_out) iadr[7:0] <= 8'h0;
else if (iadr_run) iadr[7:0] <= iadr[7:0] + 1;
pre2_yaddr_cntr[7:0] <= iadr[7:0];
pre_yaddr_cntr [7:0] <= pre2_yaddr_cntr[7:0];
yaddr_cntr[7:0] <= pre_yaddr_cntr[7:0];
yaddr[7:0] <= {yaddr_cntr[4],yaddr_cntr[7:5],yaddr_cntr[0],yaddr_cntr[3:1]};
case ({bayer_phase[1:0],iadr[4],iadr[0]} )
4'b0000: begin mux_plus_sel <= 2'h0; mux_minus_sel <= 3'h4; hdr_bit <=1'h0; end
4'b0001: begin mux_plus_sel <= 2'h0; mux_minus_sel <= 3'h1; hdr_bit <=1'h0; end
4'b0010: begin mux_plus_sel <= 2'h0; mux_minus_sel <= 3'h2; hdr_bit <=1'h0; end
4'b0011: begin mux_plus_sel <= 2'h0; mux_minus_sel <= 3'h3; hdr_bit <=1'h1; end
4'b0100: begin mux_plus_sel <= 2'h1; mux_minus_sel <= 3'h0; hdr_bit <=1'h0; end
4'b0101: begin mux_plus_sel <= 2'h1; mux_minus_sel <= 3'h4; hdr_bit <=1'h0; end
4'b0110: begin mux_plus_sel <= 2'h1; mux_minus_sel <= 3'h2; hdr_bit <=1'h1; end
4'b0111: begin mux_plus_sel <= 2'h1; mux_minus_sel <= 3'h3; hdr_bit <=1'h0; end
4'b1000: begin mux_plus_sel <= 2'h2; mux_minus_sel <= 3'h0; hdr_bit <=1'h0; end
4'b1001: begin mux_plus_sel <= 2'h2; mux_minus_sel <= 3'h1; hdr_bit <=1'h1; end
4'b1010: begin mux_plus_sel <= 2'h2; mux_minus_sel <= 3'h4; hdr_bit <=1'h0; end
4'b1011: begin mux_plus_sel <= 2'h2; mux_minus_sel <= 3'h3; hdr_bit <=1'h0; end
4'b1100: begin mux_plus_sel <= 2'h3; mux_minus_sel <= 3'h0; hdr_bit <=1'h1; end
4'b1101: begin mux_plus_sel <= 2'h3; mux_minus_sel <= 3'h1; hdr_bit <=1'h0; end
4'b1110: begin mux_plus_sel <= 2'h3; mux_minus_sel <= 3'h2; hdr_bit <=1'h0; end
4'b1111: begin mux_plus_sel <= 2'h3; mux_minus_sel <= 3'h4; hdr_bit <=1'h0; end
endcase
if (pre_ywe[0]) case (mux_plus_sel[1:0])
2'h0: mux_plus[7:0] <= dd0 [7:0];
2'h1: mux_plus[7:0] <= dd1 [7:0];
2'h2: mux_plus[7:0] <= dd16[7:0];
2'h3: mux_plus[7:0] <= dd17[7:0];
endcase
if (pre_ywe[0]) casex ({mux_minus_sel[2] | (hdr_bit & hdr), mux_minus_sel[1:0]})
3'h0: mux_minus[7:0] <= dd0 [7:0];
3'h1: mux_minus[7:0] <= dd1 [7:0];
3'h2: mux_minus[7:0] <= dd16[7:0];
3'h3: mux_minus[7:0] <= dd17[7:0];
3'b1xx: mux_minus[7:0] <= 8'h0;
endcase
is_color[1:0] <= {is_color[0], ~(mux_minus_sel[2] | (hdr_bit & hdr))}; // 1 for color components (diffs) ([0] valid at pre_ywe[1])
scale_color[1:0] <= {scale_color[0], ~(mux_minus_sel[2] | (hdr_bit & hdr)) & scale_diff}; // 1 for color components (diffs) ([0] valid at pre_ywe[1])
if (pre_ywe[1]) pre_y_out[8:0] <= {1'b0,mux_plus[7:0]} - {1'b0,mux_minus[7:0]};
y_out[8:0] <= scaled_pre_y_out[8:0] - {1'h0, ~is_color[1],7'h0}; // subtract 0x80 from Y components (make them -128+127)
dd0[7:0] <= din [7:0];
dd1[7:0] <= dd0 [7:0];
ddsr0[14:0] <= {ddsr0[13:0],dd1[0]};
ddsr1[14:0] <= {ddsr1[13:0],dd1[1]};
ddsr2[14:0] <= {ddsr2[13:0],dd1[2]};
ddsr3[14:0] <= {ddsr3[13:0],dd1[3]};
ddsr4[14:0] <= {ddsr4[13:0],dd1[4]};
ddsr5[14:0] <= {ddsr5[13:0],dd1[5]};
ddsr6[14:0] <= {ddsr6[13:0],dd1[6]};
ddsr7[14:0] <= {ddsr7[13:0],dd1[7]};
dd17[7:0] <= dd16 [7:0];
end
endmodule
/*******************************************************************************
* Module: csconvert_mono
* Date:2015-06-10
* Author: andrey
* Description: Convert JPEG monochrome
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* csconvert_mono.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.
*
* csconvert_mono.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 csconvert_mono (en,
clk,
din,
pre_first_in,
y_out,
yaddr,
ywe,
pre_first_out);
input en;
input clk; // clock
input [7:0] din; // input data in scanline sequence
input pre_first_in; // marks the first input pixel
output [7:0] y_out; // output Y (16x16) in scanline sequence. Valid if ys active
output [7:0] yaddr; // address for the external buffer memory to write 16x16x8bit Y data
output ywe; // wrire enable of Y data
output pre_first_out;
wire pre_first_out= pre_first_in;
// wire [7:0] y_out= din[7:0];
wire [7:0] y_out= {~din[7],din[6:0]};
reg [7:0] yaddr;
reg ywe;
always @ (posedge clk) begin
ywe <= en & (pre_first_in || (ywe && (yaddr[7:0] !=8'hff)));
if (!en || pre_first_in) yaddr[7:0] <= 8'h0;
else if (ywe) yaddr[7:0] <= yaddr[7:0] + 1;
end
endmodule
/*******************************************************************************
* Module: jp_channel
* Date:2015-06-10
* Author: andrey
* Description: Top module of JPEG/JP4 compressor channel
*
* Copyright (c) 2015 <set up in Preferences-Verilog/VHDL Editor-Templates> .
* 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 <http://www.gnu.org/licenses/> .
*******************************************************************************/
`timescale 1ns/1ps
module jp_channel#(
)(
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
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)
);
// Port 1rd (read DDR to AFI) buffer, linear
mcntrl_buf_rd #(
.LOG2WIDTH_RD(6) // 64 bit external interface
) chn1rd_buf_i (
.ext_clk (hclk), // input
.ext_raddr ({read_page,buf_in_line64[6:0]}), // input[8:0]
.ext_rd (bufrd_rd[0]), // input
.ext_regen (bufrd_rd[1]), // input
.ext_data_out (afi_wdata), // output[63: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_wr), // input
.data_in (buf_wdata) // input[63:0]
);
endmodule
...@@ -424,7 +424,7 @@ module histogram_saxi#( ...@@ -424,7 +424,7 @@ module histogram_saxi#(
); );
ram_var_w_var_r #( ram_var_w_var_r #(
.REGISTERS(0), .REGISTERS(1),
.LOG2WIDTH_WR(5), .LOG2WIDTH_WR(5),
.LOG2WIDTH_RD(5), .LOG2WIDTH_RD(5),
.DUMMY(0) .DUMMY(0)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment