x393  1.0
FPGAcodeforElphelNC393camera
cmprs_pixel_buf_iface.v
Go to the documentation of this file.
1 
41 `timescale 1ns/1ps
42 
44  parameter CMPRS_PREEND_EARLY = 6, // TODO: adjust according to cmprs_macroblock_buf_iface latency. In
45  // color18 mode this should be later than end of address run - (6*64>18*18)
46  // "0" would generate pulse at eth same time as next macro mb_pre_start
47  parameter CMPRS_RELEASE_EARLY = 16, // set to minimal actual latency in memory read, but not more than
48  parameter CMPRS_BUF_EXTRA_LATENCY = 0, // extra register layers insered between the buffer and this module
49  parameter CMPRS_COLOR18 = 0, // JPEG 4:2:0 with 18x18 overlapping tiles for de-bayer
50  parameter CMPRS_COLOR20 = 1, // JPEG 4:2:0 with 18x18 overlapping tiles for de-bayer (not implemented)
51  parameter CMPRS_MONO16 = 2, // JPEG 4:2:0 with 16x16 non-overlapping tiles, color components zeroed
52  parameter CMPRS_JP4 = 3, // JP4 mode with 16x16 macroblocks
53  parameter CMPRS_JP4DIFF = 4, // JP4DIFF mode TODO: see if correct
54  parameter CMPRS_MONO8 = 7 // Regular JPEG monochrome with 8x8 macroblocks (not yet implemented)
55 
56  )(
57  input xclk, // global clock input, compressor single clock rate
58  input frame_en, // if 0 - will reset logic immediately (but not page number)
59  // buffer interface, DDR3 memory read
60  input [ 7:0] buf_di, // data from the buffer
61  output [11:0] buf_ra, // buffer read address (2 MSB - page number)
62  output [ 1:0] buf_rd, // buf {regen, re}
63  // if running - will not restart a new frame if 0.
64  input [ 2:0] converter_type, // 0 - color18, 1 - color20, 2 - mono, 3 - jp4, 4 - jp4-diff, 7 - mono8 (not yet implemented)
65  input [ 5:0] mb_w_m1, // macroblock width minus 1
66  input [ 5:0] mb_h_m1, // macroblock height minus 1
67  input [ 1:0] tile_width, // memory tile width (can be 128 for monochrome JPEG) Can be 32/64/128: 0 - 16, 1 - 32, 2 - 64, 3 - 128
68  input tile_col_width, // 0 - 16 pixels, 1 -32 pixels
69  // Tiles/macroblocks level (from cmprs_macroblock_buf_iface)
70  output mb_pre_end, // just in time to start a new macroblock w/o gaps
71  output mb_release_buf, // send required "next_page" pulses to buffer. Having rather long minimal latency in the memory
72  // controller this can just be the same as mb_pre_end_in
73  input mb_pre_start, // 1 clock cycle before stream of addresses to the buffer
74  input [ 1:0] start_page, // page to read next tile from (or first of several pages)
75  input [ 6:0] macroblock_x, // macroblock left pixel x relative to a tile (page) Maximal page - 128 bytes wide.
76  // valid 3 cycles before mb_pre_start
77  output reg [ 7:0] data_out, //
78  output pre_first_out, // For each macroblock in a frame
79  output pre2_first_out, // 1 cycle before pre_first_out
80  output reg data_valid //
81 );
82  localparam PERIOD_COLOR18 = 384; // >18*18, limited by 6*64 (macroblocks)
83  localparam PERIOD_COLOR20 = 400; // limited by the 20x20 padded macroblock
84  localparam PERIOD_MONO16 = 384; // 6*64 - sends 2 of zeroed blobks
85  localparam PERIOD_JP4 = 256; // 4*64 - exact match
86  localparam PERIOD_JP4DIFF = 256; // TODO: see if correct
87  localparam PERIOD_MONO8 = 64; // 1*64 - exact match - not yet implemented (normal mono JPEG)
88 
89 
91 // reg [ 7:0] do_r;
92  reg [11:0] bufa_r; // buffer read address (2 MSB - page number)
93  reg [11:0] row_sa; // row start address
94  reg [ 9:0] tile_sa; // tile start address for the same row (w/o page number) for continuing row
95  // to the next tile. Valid @ first column (first column is always from the start tile)
96  reg [ 9:4] col_inc; // address increment when crossing tile column (1 + (macroblock_height - 1) * tile_column_width)
97  // inc by 1 - always
98  reg [ 5:0] cols_left;
99  reg [ 5:0] rows_left;
100  reg [ 6:0] tile_x; // horizontal position in a tile
101  reg [ 4:0] column_x; // horizontal position in a column (0..31 or 0..15)
102  reg last_col; // macroblock last column
103  reg first_col; // macroblock first column
104  reg last_row; // macroblock last row
105 
106  wire addr_run_end; // generate last cycle of address run
107  wire [ 6:0] tile_width_or; // set unused msb to all 1
108  wire [ 4:0] column_width_or;// set unused msb to all 1
109  wire last_in_col; // last pixel in a tile column
110  wire last_in_tile; // last pixel in a tile
111 
112  reg [ 8:0] period_cntr;
116 
117  reg [ 2:0] mb_col_number; // number of tile column where macrobloc starts - valid 2 cycles before mb_pre_start
118  wire [ 9:0] extra_start_addr_w = mb_col_number * mb_h_m1; //added to mb_start_addr when non-zero column
119  reg [ 5:0] extra_start_addr_r;
120 // reg [ 5:0] mb_h; // macroblock height (lost MSB - OK)
121  reg [ 9:0] mb_start_addr; // was macroblock_x, noccrected for multi-column. valid with mb_pre_start
122 
123  assign buf_ra = bufa_r;
124  assign tile_width_or= tile_width[1]?(tile_width[0]?0:'h40):(tile_width[0]?'h60:'h70);
125  assign column_width_or = tile_col_width? 0: 'h10;
126  assign last_in_col = &column_x;
127  assign last_in_tile = &tile_x;
128  assign addr_run_end = last_col && last_row;
129 
130  assign mb_pre_end = mb_pre_end_r;
132  assign buf_rd = buf_re[1:0];
133 // assign data_out = do_r;
134  assign pre_first_out = pre_first_out_r[0];
135  assign pre2_first_out = pre_first_out_r[1];
136 
137  always @(posedge xclk) begin
138 // mb_h <= mb_h_m1+1; // macroblock height
141  mb_start_addr <= {3'b0,macroblock_x} + {extra_start_addr_r,4'b0};
142 
143  if (!frame_en) buf_re[0] <= 0;
144  else if (mb_pre_start) buf_re[0] <= 1'b1;
145  else if (addr_run_end) buf_re[0] <= 1'b0;
146 
147  if (!frame_en) buf_re[CMPRS_BUF_EXTRA_LATENCY+3:1] <= 0;
149 
150  // Buffer data read:
152 //mb_pre_start
153  if (!frame_en) pre_first_out_r <= 0;
155 // else pre_first_out_r <= buf_re[CMPRS_BUF_EXTRA_LATENCY+1] && ! buf_re[CMPRS_BUF_EXTRA_LATENCY+2];
156 
157 // if (!frame_en) pre2_first_out <= 0;
158 // else pre2_first_out <= buf_re[CMPRS_BUF_EXTRA_LATENCY + 0] && ! buf_re[CMPRS_BUF_EXTRA_LATENCY + 1];
159 
161  else if (last_col) rows_left <= rows_left - 1;
162 
164  else if (buf_re[0]) cols_left <= cols_left - 1;
165 
166  if (!frame_en) buf_re[CMPRS_BUF_EXTRA_LATENCY+2:1] <= 0;
167 
168 // if (buf_re[0]) last_col <= 0; // ????
169  if (!buf_re[0]) last_col <= 0;
170  else last_col <= (cols_left == 1);
171 
172 // if (buf_re[0]) last_row <= 0;
173  if (!buf_re[0]) last_row <= 0;
174  else if (last_col) last_row <= (rows_left == 1);
175 
176  first_col <= (mb_pre_start || (last_col && !last_row));
177 
178 // if (mb_pre_start) row_sa <= {start_page,3'b0,mb_start_addr}; // macroblock_x};
179  if (mb_pre_start) row_sa <= {start_page,mb_start_addr}; // macroblock_x};
180  else if (first_col) row_sa <= row_sa + (tile_col_width ? 12'h20:12'h10);
181 
182  if (mb_pre_start) tile_sa <= 0;
183  else if (last_col) tile_sa <= tile_sa + (tile_col_width ? 10'h20:10'h10);
184 
185  if (mb_pre_start) col_inc[9:4] <= (tile_col_width ?{mb_h_m1[4:0],1'b0} : {mb_h_m1}); // valid at first column
186 
188  else if (buf_re[0]) column_x <= (column_x + 1) | column_width_or;
189 
190  if (mb_pre_start || last_col) tile_x <= {2'b0,macroblock_x[4:0]} | tile_width_or;
191  else if (buf_re[0]) tile_x <= (tile_x+1) | tile_width_or;
192 
193  if (mb_pre_start) bufa_r[11:10] <= start_page;
194  else if (last_col) bufa_r[11:10] <= row_sa[11:10]; // start_page;
195  else if (last_in_tile) bufa_r[11:10] <= bufa_r[11:10] + 1;
196 
197  // Most time critical - calculation of the buffer address
198 // if (mb_pre_start) bufa_r[9:0] <= {3'b0,mb_start_addr}; // macroblock_x};
199  if (mb_pre_start) bufa_r[9:0] <= {mb_start_addr}; // macroblock_x};
200  else if (last_col) bufa_r[9:0] <= row_sa[9:0]; // 'bx next cycle after AFTER mb_pre_start
201  else if (last_in_tile) bufa_r[9:0] <= tile_sa;
202  else if (buf_re[0]) bufa_r[9:0] <= bufa_r[9:0] + {last_in_col?col_inc[9:4]:6'b0,4'b1};
203 
204  // now just generate delayed outputs
205  if (!frame_en) period_cntr <= 0;
206  else if (mb_pre_start) begin
207  case (converter_type[2:0])
208  CMPRS_COLOR18: period_cntr <= PERIOD_COLOR18 - 1; // period = 384 - limited by 6*64, not by 18x18
214  default: period_cntr <= 'bx;
215  endcase
216  end else if (|period_cntr) period_cntr <= period_cntr - 1;
217 
218  if (!frame_en) mb_pre_end_r <= 0;
220 
221  if (!frame_en) mb_release_buf_r <= 0;
223 
225 
226  end
227 `ifdef SIMULATION
228  reg [8:0] sim_dout_cntr;
229  always @(posedge xclk) begin
230  if (!data_valid) sim_dout_cntr <= 0;
231  else sim_dout_cntr <= sim_dout_cntr + 1;
232  if (data_valid) begin
233  $display("CMPRS INPUT %x:%x @ %t",sim_dout_cntr, data_out, $time);
234  end
235  end
236 `endif
237 
238 endmodule
239 
1764buf_rereg[CMPRS_BUF_EXTRA_LATENCY+3:0]
1784pre_first_out_rreg[CMPRS_BUF_EXTRA_LATENCY+2:0]