x393  1.0
FPGAcodeforElphelNC393camera
cmprs_buf_average.v
Go to the documentation of this file.
1 
41 `timescale 1ns/1ps
42 // TODO:Clean up even more - remove signals that are not related to calculating/subtracting averages
44  parameter CMPRS_COLOR18 = 0, // JPEG 4:2:0 with 18x18 overlapping tiles for de-bayer
45  parameter CMPRS_COLOR20 = 1, // JPEG 4:2:0 with 18x18 overlapping tiles for de-bayer (not implemented)
46  parameter CMPRS_MONO16 = 2, // JPEG 4:2:0 with 16x16 non-overlapping tiles, color components zeroed
47  parameter CMPRS_JP4 = 3, // JP4 mode with 16x16 macroblocks
48  parameter CMPRS_JP4DIFF = 4, // JP4DIFF mode TODO: see if correct
49  parameter CMPRS_MONO8 = 7 // Regular JPEG monochrome with 8x8 macroblocks (not yet implemented)
50 )(
51  input xclk, // global clock input, compressor single clock rate
52  input frame_en,
53  input [2:0] converter_type, // valid @ pre_first_in
54  input pre_first_in, // marks the first input pixel from the external memory buffer
55  input yc_pre_first_out, // pre first output from color converter(s) to the Y/C buffers (was pre_first_out)
56  input [ 1:0] bayer_phase, // valid @ pre_first_in
57  input jp4_dc_improved,// valid @ pre_first_in
58  input hdr, // valid @ pre_first_in
59  input subtract_dc_in, // valid @ pre_first_in: enable subtracting of DC component
60  input first_mb_in, // valid @ pre_first_in - reading first macroblock
61  input last_mb_in, // valid @ pre_first_in - reading last macroblock
62 
63  input [ 7:0] yaddrw,
64  input ywe,
65  input [ 8:0] signed_y,
66  input [ 7:0] caddrw,
67  input cwe,
68  input [ 8:0] signed_c,
69  output [ 9:0] do, // [9:0] data out (4:2:0) (signed, average=0)
70  // When is it valid?
71  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!
72  output dv, // out data valid (will go high for at least 64 cycles)
73  output ds, // single-cycle mark of the first_r pixel in a 64 (8x8) - pixel block
74  output [ 2:0] tn, // [2:0] tile number 0..3 - Y, 4 - Cb, 5 - Cr (valid with start)
75  output reg first, // sending first_r MCU (valid @ ds)
76  output reg last, // sending last_r MCU (valid @ ds)
77 // below signals valid at ds ( 1 later than tn, first_r, last_r)
78  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
79  output component_color, // use color quantization table (YCbCR, jp4diff)
80  output component_first, // first_r this component in a frame (DC absolute, otherwise - difference to previous)
81  output reg component_lastinmb // last_r component in a macroblock;
82 );
83 
84  wire [5:0] component_numsLS; // component_num[0] vs tn
85  wire [5:0] component_numsMS; // component_num[1] vs tn
86  wire [5:0] component_numsHS; // component_num[2] vs tn
87  wire [5:0] component_colorsS; // use color quantization table (YCbCR, jp4diff)
88  wire [5:0] component_firstsS; // first_r this component in a frame (DC absolute, otherwise - difference to previous)
89 
90  reg [5:0] component_numsL; // component_num[0] vs tn
91  reg [5:0] component_numsM; // component_num[1] vs tn
92  reg [5:0] component_numsH; // component_num[2] vs tn
93  reg [5:0] component_colors; // use color quantization table (YCbCR, jp4diff)
94  reg [5:0] component_firsts; // first_r this component in a frame (DC absolute, otherwise - difference to previous)
95 
96  // Y and C components buffer filled in by color conversion module
97 
98  reg [1:0] wpage; // page (0/1) where data is being written to (both Y and CbCr)
99  reg [1:0] rpage; // page (0/1) from where data is sent out ( both Y and CbCr)
100  reg [8:0] raddr; // output address of buffer memories (MSB selects Y(0)/CbCr(1))
101  wire four_blocks; // decoded from converter_type
102  reg four_blocks_rd; // 4 blocks/macroblock, valid with raddr
103  wire [1:0] y_ren; // read enable for Y buffer ([0] - ren, [1] - regen)
104  wire [1:0] c_ren; // read enable for C buffer ([0] - ren, [1] - regen)
105  reg y_ren_r; // regen for Y buffer
106  reg c_ren_r; // regen for C buffer
107  wire [8:0] y_out; // data output from Y block buffer, valid @
108  wire [8:0] c_out; // data output from C block buffer, valid @
113  wire color_enable_d;// delay by 2 clocks to match data
115  wire pre_last_mb;
116 
117 // Copied from old code - check/fix it
118  reg [3:0] accYen;
119  reg [1:0] accCen; // individual accumulator enable (includes clearing)
120  reg [3:0] accYfirst;
121  reg [1:0] accCfirst; // add to zero, instead of to acc @ acc*en
122  reg [8:0] preAccY, preAccC; // registered data from color converters, matching acc selection latency
125  wire cs_first_out_late; // delay by 16 cycles - safe for overlap to set subrtact_dc mode
127  wire [3:0] pre_accYdone;
128  wire [1:0] pre_accCdone; // need to make sure that pre_accCdone do_r not happen with pre_accYdone
129  reg [3:0] accYrun;
130  reg [1:0] accCrun;
131 // reg [3:0] accYdone; // only bit 0 is used as a start of output
132  reg accYdone; // only bit 0 is used as a start of output
134  reg [1:0] avrY_wa, pre_avrY_wa;
137  reg avr_we; // Write to memory that stores average value
138  reg [8:0] avermem[0:15]; // average values memory - 2 pages (MSB) of 6 block values
139  wire [3:0] avr_wa= {avrPage_wa,accYdoneAny?{1'b0,avrY_wa[1:0]}:{2'b10,avrC_wa}};
140  reg [3:0] avr_ra; // read address for "average" memory
141  reg [8:0] avr_r; // registered output data from average memory (simultaneouis with regsitered buffer data)
142  // truncating average values
143  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]);
144  wire [8:0] avrC_di= avrC_wa ?accC1[14:6]:accC0[14:6];
145 
146  reg [1:0] buf_sel;
147  reg [9:0] pre_do;
148  reg [9:0] do_r;
149  reg dv_pre3; //3 cycles ahead of dv (data valid)
150  reg ds_pre3; //3 cycles ahead of ds (data strobe - first cycle of dv)
151 
153  reg raddr_updateBlock; // first_r in block, after last_r also. Should be when *_r match the currently selected converter for the macroblock
154  reg ccv_out_start_d; // ccv_out_start delayed by 1 clock to match time of raddr_updateBlock
155 
156  reg [ 2:0] converter_type_r;
157  reg ccv_out_start; // find the best way to calculate (maybe just a common counter with different presets)
158  // active 1 clk before start or reading blocks
159 
160  // accCntr* counters after the first value will be set to 1 (was 0 before)
161  assign pre_accYdone[3:0] = {(accCntrY3[5:0] == 6'h3f) ? 1'b1 : 1'b0,
162  (accCntrY2[5:0] == 6'h3f) ? 1'b1 : 1'b0,
163  (accCntrY1[5:0] == 6'h3f) ? 1'b1 : 1'b0,
164  (accCntrY0[5:0] == 6'h3f) ? 1'b1 : 1'b0} & accYen[3:0];
165  assign pre_accCdone[1:0] = {(accCntrC1[5:0] == 6'h3f) ? 1'b1 : 1'b0,
166  (accCntrC0[5:0] == 6'h3f) ? 1'b1 : 1'b0} & accCen[1:0];
167 
168  assign y_ren={y_ren_r,!raddr[8]};
169  assign c_ren={c_ren_r,raddr[8] && !raddr[7]};
170 
171  // assign output signals
172  assign avr = avr_r; // avermem[avr_ra[3:0]];
173  assign do = do_r;
174  assign tn[2:0] = raddr[8:6];
175 // component_num,component_color,component_first for different converters vs tn (1 bit per tn (0..5)
177  assign component_color = component_colors[0];
178  assign component_first = component_firsts[0];
179 
180  // Calculate average values for each block, count them to know when all 64 are ready, store trunctaed result in 9*16 memory
181  always @ (posedge xclk) begin
183  if (ywe) preAccY[8:0] <= signed_y[8:0];
184  if (cwe) preAccC[8:0] <= signed_c[8:0];
185  accYen[3:0] <= {4{frame_en & ywe}} & { yaddrw[7] & yaddrw[6],
186  yaddrw[7] & ~yaddrw[6],
187  ~yaddrw[7] & yaddrw[6],
188  ~yaddrw[7] & ~yaddrw[6]};
189  accCen[1:0] <= {2{frame_en & cwe}} & { caddrw[6],
190  ~caddrw[6]};
191  accYfirst[3:0] <= {4{cs_first_out}} | (accYfirst[3:0] & ~accYen[3:0]);
192  accCfirst[1:0] <= {2{cs_first_out}} | (accCfirst[1:0] & ~accCen[1:0]);
193  if (accYen[0]) accY0[14:0]<= (accYfirst[0]?15'h0:accY0[14:0]) + {{6{preAccY[8]}},preAccY[8:0]};
194  if (accYen[1]) accY1[14:0]<= (accYfirst[1]?15'h0:accY1[14:0]) + {{6{preAccY[8]}},preAccY[8:0]};
195  if (accYen[2]) accY2[14:0]<= (accYfirst[2]?15'h0:accY2[14:0]) + {{6{preAccY[8]}},preAccY[8:0]};
196  if (accYen[3]) accY3[14:0]<= (accYfirst[3]?15'h0:accY3[14:0]) + {{6{preAccY[8]}},preAccY[8:0]};
197  if (accCen[0]) accC0[14:0]<= (accCfirst[0]?15'h0:accC0[14:0]) + {{6{preAccC[8]}},preAccC[8:0]};
198  if (accCen[1]) accC1[14:0]<= (accCfirst[1]?15'h0:accC1[14:0]) + {{6{preAccC[8]}},preAccC[8:0]};
199 
200  if (!frame_en) accCntrY0[5:0]<= 6'h0;
201  else if (accYen[0]) accCntrY0[5:0]<= (accYfirst[0]?6'h1:(accCntrY0[5:0]+1)); // was set to 0 before
202 
203  if (!frame_en) accCntrY1[5:0]<= 6'h0;
204  else if (accYen[1]) accCntrY1[5:0]<= (accYfirst[1]?6'h1:(accCntrY1[5:0]+1));
205 
206  if (!frame_en) accCntrY2[5:0]<= 6'h0;
207  else if (accYen[2]) accCntrY2[5:0]<= (accYfirst[2]?6'h1:(accCntrY2[5:0]+1));
208 
209  if (!frame_en) accCntrY3[5:0]<= 6'h0;
210  else if (accYen[3]) accCntrY3[5:0]<= (accYfirst[3]?6'h1:(accCntrY3[5:0]+1));
211 
212  if (!frame_en) accCntrC0[5:0]<= 6'h0;
213  else if (accCen[0]) accCntrC0[5:0]<= (accCfirst[0]?6'h1:(accCntrC0[5:0]+1));
214 
215  if (!frame_en) accCntrC1[5:0]<= 6'h0;
216  else if (accCen[1]) accCntrC1[5:0]<= (accCfirst[1]?6'h1:(accCntrC1[5:0]+1));
217 
218  accYrun[3:0] <= {4{frame_en}} & ((accYfirst[3:0] & accYen[3:0]) | (accYrun[3:0] & ~pre_accYdone[3:0]));
219  accCrun[1:0] <= {2{frame_en}} & ((accCfirst[1:0] & accCen[1:0]) | (accCrun[1:0] & ~pre_accCdone[1:0]));
220 
221 // accYdone[3:0] <= pre_accYdone[3:0] & accYrun[3:0];
222  accYdone <= pre_accYdone[0] & accYrun[0];
223  accYdoneAny <= |(pre_accYdone[3:0] & accYrun[3:0]);
224  avr_we <= |(pre_accYdone[3:0] & accYrun[3:0]) || |(pre_accCdone[1:0] & accCrun[1:0]);
225 
226  // Delay write addresses to find write address of the block for which average value is recorded
227  pre_avrY_wa[1:0] <= yaddrw[7:6];
228  avrY_wa[1:0] <= pre_avrY_wa[1:0];
229  pre_avrC_wa <= caddrw[ 6];
230  avrC_wa <= pre_avrC_wa;
231  pre_avrPage_wa <= wpage[0];
233 
234  if (avr_we) avermem[avr_wa[3:0]] <= subtract_dc?(accYdoneAny?avrY_di[8:0]:avrC_di[8:0]):9'h0;
235 
236  end
237 
238  always @(posedge xclk) begin
239  if (!frame_en) wpage <= 0;
240  else if (yc_pre_first_out) wpage <= wpage + 1; // will start from 1, not 0. Maybe changed to there strobe - end of writing
241 
242  if (!frame_en || pre_first_in) first <= 0;
243  else if (ccv_out_start) first <= pre_first_mb;
244 
245  if (ccv_out_start) begin
246  rpage[1:0] <= wpage[1:0];
248 // first <= pre_first_mb;
249  last <= pre_last_mb;
250  color_enable <= pre_color_enable; // valid with address
251  end
252 
253  // read buffers timing
254  // Is it that raddr[8:7] == 2'b11 means "disable
255  if (!frame_en) raddr[8:0] <= 9'h180;
256  else if (ccv_out_start) raddr[8:0] <= 0;
257  else if (!raddr[8] || (!four_blocks_rd && !raddr[7])) raddr[8:0] <= raddr[8:0]+1; // for 4 blocks - count for 0,1; 6 blocks - 0,1,2
258 
259  // Reading output data and combining with the average values
260 
261  y_ren_r <= y_ren[0];
262  c_ren_r <= c_ren[0];
263 
265 
266  avr_ra[3:0] <= {rpage[0],raddr[8:6]};
267  avr_r <= avermem[avr_ra[3:0]];
268 
269  buf_sel <= {buf_sel[0],raddr[8]};
270  pre_do[9:0] <= buf_sel[1]?(color_enable_d?({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]});
271  do_r[9:0] <= pre_do[9:0];
272 
273  raddr_lastInBlock <= frame_en && (raddr[5:0]==6'h3e);
276 
277  if (!frame_en) dv_pre3 <= 0;
278  else if (raddr_updateBlock) dv_pre3 <= !raddr[8] || (!four_blocks_rd && !raddr[7]);
279 
280  ds_pre3 <= raddr_updateBlock && (!raddr[8] || (!four_blocks_rd && !raddr[7]));
281 
282  // generate blobk type data
283  // Shift registers - generating block attributes to be used later in compressor
284  if (raddr_updateBlock) begin
285  if (ccv_out_start_d) begin // ccv_out_start_d valid with raddr_updateBlock
286  component_numsL[5:0] <= component_numsLS[5:0];
287  component_numsM[5:0] <= component_numsMS[5:0];
288  component_numsH[5:0] <= component_numsHS[5:0];
289  component_colors[5:0] <= component_colorsS[5:0];
290  component_firsts[5:0] <= pre_first_mb? component_firstsS[5:0]:6'h0;
291  end else begin
292  component_numsL[5:0] <= {1'b0,component_numsL[5:1]};
293  component_numsM[5:0] <= {1'b0,component_numsM[5:1]};
294  component_numsH[5:0] <= {1'b0,component_numsH[5:1]};
295  component_colors[5:0] <= {1'b0,component_colors[5:1]};
296  component_firsts[5:0] <= {1'b0,component_firsts[5:1]};
297  end
298  end
299  component_lastinmb <= tn[0] && (four_blocks_rd? tn[1] : tn[2]); // last component in a macroblock;
300  end
301 
302  // when to start reading out data from the buffer
303  always @ (posedge xclk) if (pre_first_in)begin
305  end
306  always @ (posedge xclk) begin
307  case (converter_type_r)
308  CMPRS_COLOR18: ccv_out_start <= (yaddrw[7:0]==8'hc4); //TODO: adjust to minimal latency?
309  CMPRS_COLOR20: ccv_out_start <= (yaddrw[7:0]==8'hc4); //TODO: adjust to minimal latency?
311  CMPRS_JP4: ccv_out_start <= accYdone; //[0];
314  default: ccv_out_start <= accYdone; //[0];
315  endcase
316  end
317 
318  // delay from the start of data output from color converter to copy subtract_dc to be valid when average values are set
319  dly_16 #(.WIDTH(1)) i_cs_first_out_late (.clk(xclk),.rst(1'b0), .dly(4'd15), .din(cs_first_out), .dout(cs_first_out_late));
320  dly_16 #(.WIDTH(1)) i_color_enable_d (.clk(xclk),.rst(1'b0), .dly( 4'd1), .din(color_enable), .dout(color_enable_d));
321  dly_16 #(.WIDTH(1)) i_dv (.clk(xclk),.rst(1'b0), .dly( 4'd2), .din(dv_pre3), .dout(dv));
322  dly_16 #(.WIDTH(1)) i_ds (.clk(xclk),.rst(1'b0), .dly( 4'd2), .din(ds_pre3), .dout(ds));
323 
328  .CMPRS_JP4 (CMPRS_JP4),
331  ) cmprs_tile_mode2_decode_i (
332  .xclk (xclk), // input
333  .pre_first_in (pre_first_in), // input
334  .converter_type (converter_type), // input[2:0]
335  .bayer_phase (bayer_phase), // input[1:0]
336  .jp4_dc_improved (jp4_dc_improved), // input
337  .hdr (hdr), // input
338  .subtract_dc_in (subtract_dc_in), // input
339  .first_mb_in (first_mb_in), // input
340  .last_mb_in (last_mb_in), // input
341  .four_blocks (four_blocks), // output reg
342  .subtract_dc (pre_subtract_dc), // output reg
343  .first_mb (pre_first_mb), // output reg
344  .last_mb (pre_last_mb), // output reg
345  .color_enable (pre_color_enable), // prevent JPEG random colors
346  .component_numsL (component_numsLS), // output[5:0] reg
347  .component_numsM (component_numsMS), // output[5:0] reg
348  .component_numsH (component_numsHS), // output[5:0] reg
349  .component_colors (component_colorsS), // output[5:0] reg
350  .component_first (component_firstsS) // output[5:0] reg
351  );
352 
354  .REGISTERS (1), // will need to delay output strobe(s) by 1
355  .LOG2WIDTH_WR (3),
356  .LOG2WIDTH_RD (3),
357  .DUMMY (0)
358  ) i_y_buff (
359  .rclk (xclk), // input
360  .raddr ({1'b0,rpage[1:0],raddr[7:0]}), // input[11:0]
361  .ren (y_ren[0]), // input // TODO: modify to read only when needed
362  .regen (y_ren[1]), // input
363  .data_out (y_out[8:0]), // output[8:0]
364  .wclk (xclk), // input
365  .waddr ({1'b0,wpage[1:0],yaddrw[7:0]}), // input[11:0]
366  .we (ywe), // input
367  .web (4'hf), // input[7:0]
368  .data_in (signed_y[8:0]) // input[9:0]
369  );
370 
372  .REGISTERS (1), // will need to delay output strobe(s) by 1
373  .LOG2WIDTH_WR (3),
374  .LOG2WIDTH_RD (3),
375  .DUMMY (0)
376  ) i_CrCb_buff (
377  .rclk (xclk), // input
378  .raddr ({1'b0,rpage[1:0],raddr[7:0]}), // input[11:0]
379  .ren (c_ren[0]), // input // TODO: modify to read only when needed
380  .regen (c_ren[1]), // input
381  .data_out (c_out[8:0]), // output[8:0]
382  .wclk (xclk), // input
383  .waddr ({1'b0,wpage[1:0],caddrw[7:0]}), // input[11:0]
384  .we (cwe), // input
385  .web (4'hf), // input[7:0]
386  .data_in (signed_c[8:0]) // input[71:0]
387  );
388 
389 
390 endmodule
391 
10332clk
Definition: dly_16.v:44
1401component_numsHSwire[5:0]
cmprs_tile_mode2_decode_i cmprs_tile_mode2_decode
1400component_numsMSwire[5:0]
1407component_colorsreg[5:0]
[9 << LOG2WIDTH_WR-3-1:0] 11679data_in
[WIDTH-1:0] 10336dout
Definition: dly_16.v:48
[0:15] 1460avermemreg[8:0]
1399component_numsLSwire[5:0]
[WIDTH-1:0] 10335din
Definition: dly_16.v:47
i_CrCb_buff ram18p_var_w_var_r
[9 << LOG2WIDTH_RD-3-1:0] 11674data_out
1408component_firstsreg[5:0]
[13-LOG2WIDTH_RD:0] 11671raddr
1402component_colorsSwire[5:0]
1403component_firstsSwire[5:0]
[13-LOG2WIDTH_WR:0] 11676waddr
10333rst
Definition: dly_16.v:45
[3:0] 10334dly
Definition: dly_16.v:46