x393  1.0
FPGAcodeforElphelNC393camera
mcntrl_linear_rw.v
Go to the documentation of this file.
1 
40 `timescale 1ns/1ps
41 // TODO: ADD MCNTRL_SCANLINE_FRAME_PAGE_RESET to caller
43  parameter ADDRESS_NUMBER= 15,
44  parameter COLADDR_NUMBER= 10,
45  parameter NUM_XFER_BITS= 6, // number of bits to specify transfer length
46  parameter FRAME_WIDTH_BITS= 13, // Maximal frame width - 8-word (16 bytes) bursts
47  parameter FRAME_HEIGHT_BITS= 16, // Maximal frame height
48  parameter LAST_FRAME_BITS= 16, // number of bits in frame counter (before rolls over)
49  parameter MCNTRL_SCANLINE_ADDR= 'h120,
50  parameter MCNTRL_SCANLINE_MASK= 'h7f0, // both channels 0 and 1
51  parameter MCNTRL_SCANLINE_MODE= 'h0, // set mode register: {repet,single,rst_frame,na[2:0],extra_pages[1:0],write_mode,enable,!reset}
52  parameter MCNTRL_SCANLINE_STATUS_CNTRL= 'h1, // control status reporting
53  parameter MCNTRL_SCANLINE_STARTADDR= 'h2, // 22-bit frame start address (3 CA LSBs==0. BA==0)
54  parameter MCNTRL_SCANLINE_FRAME_SIZE= 'h3, // 22-bit frame start address increment (3 CA LSBs==0. BA==0)
55  parameter MCNTRL_SCANLINE_FRAME_LAST= 'h4, // 16-bit last frame number in the buffer
56  parameter MCNTRL_SCANLINE_FRAME_FULL_WIDTH='h5, // Padded line length (8-row increment), in 8-bursts (16 bytes)
57  parameter MCNTRL_SCANLINE_WINDOW_WH= 'h6, // low word - 13-bit window width (0->'h4000), high word - 16-bit frame height (0->'h10000)
58  parameter MCNTRL_SCANLINE_WINDOW_X0Y0= 'h7, // low word - 13-bit window left, high word - 16-bit window top
59  parameter MCNTRL_SCANLINE_WINDOW_STARTXY= 'h8, // low word - 13-bit start X (relative to window), high word - 16-bit start y
60  // Start XY can be used when read command to start from the middle
61  // TODO: Add number of blocks to R/W? (blocks can be different) - total length?
62  // Read back current address (for debugging)?
64  parameter MCNTRL_SCANLINE_PENDING_CNTR_BITS=2, // Number of bits to count pending trasfers, currently 2 is enough, but may increase
65  // if memory controller will allow programming several sequences in advance to
66  // spread long-programming (tiled) over fast-programming (linear) requests.
67  // But that should not be too big to maintain 2-level priorities
68  parameter MCNTRL_SCANLINE_FRAME_PAGE_RESET =1'b0, // reset internal page number to zero at the frame start (false - only when hard/soft reset)
69  // bits in mode control word
70  parameter MCONTR_LINTILE_NRESET = 0, // reset if 0
71  parameter MCONTR_LINTILE_EN = 1, // enable requests
72  parameter MCONTR_LINTILE_WRITE = 2, // write to memory mode
73  parameter MCONTR_LINTILE_EXTRAPG = 3, // extra pages (over 1) needed by the client simultaneously
74  parameter MCONTR_LINTILE_EXTRAPG_BITS = 2, // number of bits to use for extra pages
75  parameter MCONTR_LINTILE_RST_FRAME = 8, // reset frame number
76  parameter MCONTR_LINTILE_SINGLE = 9, // read/write a single page
77  parameter MCONTR_LINTILE_REPEAT = 10, // read/write pages until disabled
78  parameter MCONTR_LINTILE_DIS_NEED = 11, // disable 'need' request
79  parameter MCONTR_LINTILE_SKIP_LATE = 12 // skip actual R/W operation when it is too late, advance pointers
80 )(
81  input mrst,
82  input mclk,
83 // programming interface
84  input [7:0] cmd_ad, // byte-serial command address/data (up to 6 bytes: AL-AH-D0-D1-D2-D3
85  input cmd_stb, // strobe (with first byte) for the command a/d
86 
87  output [7:0] status_ad, // byte-wide address/data
88  output status_rq, // request to send downstream (last byte with rq==0)
89  input status_start, // acknowledge of address (first byte) from downsteram
90 
91  input frame_start, // resets page, x,y, and initiates transfer requests (in write mode will wait for next_page)
92  output frame_run, // @mclk - enable pixels from sesnor to memory buffer
93  input next_page, // page was read/written from/to 4*1kB on-chip buffer
94 // output page_ready, // == xfer_done, connect externally | Single-cycle pulse indicating that a page was read/written from/to DDR3 memory
95  output frame_done, // single-cycle pulse when the full frame (window) was transferred to/from DDR3 memory
96  output frame_finished,// turns on and stays on after frame_done
97 // optional I/O for channel synchronization
98 // after the last tile in a frame, before starting a new frame line_unfinished will point to non-existent (too high) line in the same frame
99  output [FRAME_HEIGHT_BITS-1:0] line_unfinished, // number of the current (unfinished ) line, RELATIVE TO FRAME, NOT WINDOW?.
100  input suspend, // suspend transfers (from external line number comparator)
101  output [LAST_FRAME_BITS-1:0] frame_number, // current frame number (for multi-frame ranges)
102  output xfer_want, // "want" data transfer
103  output xfer_need, // "need" - really need a transfer (only 1 page/ room for 1 page left in a buffer), want should still be set.
104  input xfer_grant, // sequencer programming access granted, deassert wait/need
105  output xfer_reject, // reject granted access (when skipping)
106  output xfer_start_rd, // initiate a transfer (next cycle after xfer_grant)
107  output xfer_start_wr, // initiate a transfer (next cycle after xfer_grant)
108  output [2:0] xfer_bank, // bank address
109  output [ADDRESS_NUMBER-1:0] xfer_row, // memory row
110  output [COLADDR_NUMBER-4:0] xfer_col, // start memory column in 8-bursts
111  output [NUM_XFER_BITS-1:0] xfer_num128, // number of 128-bit words to transfer (8*16 bits) - full bursts of 8 ( 0 - maximal length, 64)
112  output xfer_partial, // partial tile (first of 2) , sequencer will not generate page_next at the end of block
113  input xfer_done, // transfer to/from the buffer finished
114  output xfer_page_rst_wr, // reset buffer internal page - at each frame start or when specifically reset (write to memory channel), @posedge
115  output xfer_page_rst_rd, // reset buffer internal page - at each frame start or when specifically reset (read memory channel), @negedge
116  output reg xfer_skipped,
117  output cmd_wrmem
118 
119 `ifdef DEBUG_SENS_MEM_PAGES
120  ,input [1 : 0] dbg_rpage
121  ,input [1 : 0] dbg_wpage
122 `endif
123 
124 
125 );
126  localparam NUM_RC_BURST_BITS=ADDRESS_NUMBER+COLADDR_NUMBER-3; //to spcify row and col8 == 22
127  localparam MPY_WIDTH= NUM_RC_BURST_BITS; // 22
128  localparam PAR_MOD_LATENCY= 9; // TODO: Find actual worst-case latency for:
129  reg [FRAME_WIDTH_BITS-1:0] curr_x; // (calculated) start of transfer x (relative to window left)
130  reg [FRAME_HEIGHT_BITS-1:0] curr_y; // (calculated) start of transfer y (relative to window top)
131  reg [FRAME_HEIGHT_BITS:0] next_y; // (calculated) next row number
132  reg [NUM_RC_BURST_BITS-1:0] line_start_addr;// (calculated) Line start (in {row,col8} in burst8
133  // calculating full width from the frame width
134 // WARNING: [Synth 8-3936] Found unconnected internal register 'frame_y_reg' and it is trimmed from '16' to '3' bits. [memctrl/mcntrl_linear_rw.v:268]
135 // Throblem seems to be that frame_y8_r_reg (load of trimmed bits of the frame_y_reg) is (as intended) absorbed into DSP48. The lower 3 bits are used
136 // outside of the DSP 48. "dont_touch" seems to work here
137 `ifndef IGNORE_ATTR
138  (* keep = "true" *)
139 `endif
140  reg [FRAME_HEIGHT_BITS-1:0] frame_y; // current line number referenced to the frame top
141  reg [FRAME_WIDTH_BITS-1:0] frame_x; // current column number referenced to the frame left
142  reg [FRAME_HEIGHT_BITS-4:0] frame_y8_r; // (13 bits) current row with bank removed, latency2 (to be absorbed when inferred DSP multipler)
143  reg [FRAME_WIDTH_BITS:0] frame_full_width_r; // (14 bit) register to be absorbed by MPY
144  reg [MPY_WIDTH-1:0] mul_rslt;
145  reg [NUM_RC_BURST_BITS-1:0] start_addr_r; // 22 bit - to be absorbed by DSP
146 // reg [2:0] bank_reg [2:0];
147  reg [3 * 3 - 1:0] bank_reg;
149  reg [FRAME_WIDTH_BITS:0] row_left; // number of 8-bursts left in the current row
151  reg [COLADDR_NUMBER-3:0] mem_page_left; // number of 8-bursts left in the pointed memory page
152  reg [COLADDR_NUMBER-4:0] line_start_page_left; // number of 8-burst left in the memory page from the start of the frame line
153  reg [NUM_XFER_BITS:0] lim_by_xfer; // number of bursts left limited by the longest transfer (currently 64)
154 // reg [MAX_TILE_WIDTH:0] lim_by_tile_width; // number of bursts left limited by the longest transfer (currently 64)
155  wire [COLADDR_NUMBER-3:0] remainder_in_xfer ;//remainder_tile_width; // number of bursts postponed to the next partial tile (because of the page crossing) MSB-sign
156  reg continued_xfer; //continued_tile; // this is a continued tile (caused by page crossing) - only once
157  reg [NUM_XFER_BITS-1:0] leftover; //[MAX_TILE_WIDTH-1:0] leftover_cols; // valid with continued_tile, number of columns left
158 
159 
160 
161  reg [NUM_XFER_BITS:0] xfer_num128_r; // number of 128-bit words to transfer (8*16 bits) - full bursts of 8
162 // reg [NUM_XFER_BITS-1:0] xfer_num128_m1_r; // number of 128-bit words to transfer minus 1 (8*16 bits) - full bursts of 8
163  wire pgm_param_w; // program one of the parameters, invalidate calculated results for PAR_MOD_LATENCY
164  reg [2:0] xfer_start_r; // 1 hot started by xfer start only (not by parameter change)
166  reg xfer_start_wr_r;
168  reg [PAR_MOD_LATENCY-1:0] recalc_r; // 1-hot CE for re-calculating registers
169 // SuppressWarnings VEditor unused
170  wire calc_valid; // calculated registers have valid values
171  wire chn_en; // enable requests by channel (continue ones in progress), enable frame_start inputs
172  wire chn_rst; // resets command, including fifo;
173  reg chn_rst_d; // delayed by 1 cycle do detect turning off
174 // reg xfer_reset_page_r;
175  reg xfer_page_rst_r=1;
177  reg xfer_page_rst_neg=1;
178 
179  reg [2:0] page_cntr;
180 
181 // wire cmd_wrmem; //=MCNTRL_SCANLINE_WRITE_MODE; // 0: read from memory, 1:write to memory
182  wire [1:0] cmd_extra_pages; // external module needs more than 1 page
184  wire disable_need; // do not assert need, only want
185  wire repeat_frames; // mode bit
186  wire single_frame_w; // pulse
188  reg single_frame_r; // pulse
189  reg [1:0] rst_frame_num_r; // reset frame number/next start address
190  reg frame_en; // enable next frame
191 
192  reg busy_r;
193  reg want_r;
194  reg need_r;
196  reg frame_finished_r;
199 // wire last_block_w;
200  reg last_block;
201  reg [MCNTRL_SCANLINE_PENDING_CNTR_BITS-1:0] pending_xfers; // number of requested,. but not finished block transfers
203 // reg [2*FRAME_HEIGHT_BITS-1:0] line_unfinished_r;
206 
207  wire pre_want;
209  wire [1:0] status_data;
210  wire [3:0] cmd_a;
211  wire [31:0] cmd_data;
212  wire cmd_we;
213 
222  wire set_window_start_w;
223  wire lsw13_zero=!(|cmd_data[FRAME_WIDTH_BITS-1:0]); // LSW 13 (FRAME_WIDTH_BITS) low bits are all 0 - set carry bit
224  wire msw_zero= !(|cmd_data[31:16]); // MSW all bits are 0 - set carry bit
225 
226 
227  reg [12:0] mode_reg;//mode register: {dis_need,repet,single,rst_frame,na[2:0],extra_pages[1:0],write_mode,enable,!reset}
228 
229  reg [NUM_RC_BURST_BITS-1:0] start_range_addr; // (programmed) First frame in range start (in {row,col8} in burst8, bank ==0
230  reg [NUM_RC_BURST_BITS-1:0] frame_size; // (programmed) First frame in range start (in {row,col8} in burst8, bank ==0
232  reg [NUM_RC_BURST_BITS-1:0] start_addr; // (programmed) Frame start (in {row,col8} in burst8, bank ==0
236 
237  reg is_last_frame;
238 // reg [2:0] frame_start_r;
239  reg [4:0] frame_start_r; // increased length to have time from line_unfinished to suspend (external)
240 
241  reg [FRAME_WIDTH_BITS:0] frame_full_width; // (programmed) increment combined row/col when moving to the next line
242  // frame_width rounded up to max transfer (half page) if frame_width> max transfer/2,
243  // otherwise (smaller widths) round up to the nearest power of 2
244  reg [FRAME_WIDTH_BITS:0] window_width; // (programmed) 0- max
245  reg [FRAME_HEIGHT_BITS:0] window_height; // (programmed) 0- max
246  reg [FRAME_WIDTH_BITS-1:0] window_x0; // (programmed) window left
247  reg [FRAME_HEIGHT_BITS-1:0] window_y0; // (programmed) window top
248  reg [FRAME_WIDTH_BITS-1:0] start_x; // (programmed) normally 0, copied to curr_x on frame_start
249  reg [FRAME_HEIGHT_BITS-1:0] start_y; // (programmed) normally 0, copied to curr_y on frame_start
250  reg xfer_done_d; // xfer_done delayed by 1 cycle (also includes xfer_skipped)
252 
262 
265 
266  assign frame_run = busy_r;
267 
268  // Set parameter registers
269  always @(posedge mclk) begin
270  if (mrst) mode_reg <= 0;
271  else if (set_mode_w) mode_reg <= cmd_data[12:0]; // 4:0]; // [4:0];
272 
273  if (mrst) single_frame_r <= 0;
275 
276  if (mrst) rst_frame_num_r <= 0;
277  else rst_frame_num_r <= {rst_frame_num_r[0],
282 
283  if (mrst) start_range_addr <= 0;
285 
286  if (mrst) frame_size <= 0;
287  else if (set_start_addr_w) frame_size <= 1; // default number of frames - just one
289 
290  if (mrst) last_frame_number <= 0;
292 
293  if (mrst) frame_full_width <= 0;
295 
296  if (mrst) is_last_frame <= 0;
298 
299 // if (mrst) frame_start_r <= 0;
300 // else frame_start_r <= {frame_start_r[3:0], frame_start & frame_en};
301 
302  if (mrst) frame_en <= 0;
303  else if (single_frame_r || repeat_frames) frame_en <= 1;
304  else if (frame_start) frame_en <= 0;
305 
306  if (mrst) frame_number_cntr <= 0;
307  else if (rst_frame_num_r[0]) frame_number_cntr <= 0;
309 
310  if (mrst) frame_number_current <= 0;
311  else if (rst_frame_num_r[0]) frame_number_current <= 0;
313 
314  if (mrst) next_frame_start_addr <= start_range_addr; // just to use rst
317 
318  if (mrst) start_addr <= start_range_addr; // just to use rst
320 
321  if (mrst) begin
322  window_width <= 0;
323  window_height <= 0;
324  end else if (set_window_wh_w) begin
327  end
328 
329  if (mrst) begin
330  window_x0 <= 0;
331  window_y0 <= 0;
332  end else if (set_window_x0y0_w) begin
335  end
336 
337  if (mrst) begin
338  start_x <= 0;
339  start_y <= 0;
340  end else if (set_window_start_w) begin
343  end
344  end
345  assign mul_rslt_w= frame_y8_r * frame_full_width_r; // 5 MSBs will be discarded
349  assign calc_valid= par_mod_r[PAR_MOD_LATENCY-1]; // MSB, longest 0
352 
354 
355  assign frame_done= frame_done_r;
357 
358 // assign pre_want= chn_en && busy_r && !want_r && !xfer_start_r[0] && calc_valid && !last_block && !suspend && !(|frame_start_r);
359  // accelerating pre_want:
360 // assign pre_want= pre_want_r1 && !want_r && !xfer_start_r[0] && !suspend ;
361  // last_block was too late to inclusde in pre_want_r1, moving it here
362  assign pre_want= pre_want_r1 && !want_r && !xfer_start_r[0] && !suspend && !last_block;
363 
366  assign xfer_want= want_r;
367  assign xfer_need= need_r;
368  assign xfer_bank= bank_reg[3 * 2 +: 3]; // TODO: just a single reg layer
369  assign xfer_row= row_col_r[NUM_RC_BURST_BITS-1:COLADDR_NUMBER-3] ; // memory row
370  assign xfer_col= row_col_r[COLADDR_NUMBER-4:0]; // start memory column in 8-bursts
371  assign line_unfinished = line_unfinished_r; // [FRAME_HEIGHT_BITS +: FRAME_HEIGHT_BITS];
372  assign chn_en = mode_reg[MCONTR_LINTILE_NRESET] & mode_reg[MCONTR_LINTILE_EN]; // enable requests by channel (continue ones in progress)
373  assign chn_rst = ~mode_reg[MCONTR_LINTILE_NRESET]; // resets command, including fifo;
374  assign cmd_wrmem = mode_reg[MCONTR_LINTILE_WRITE];// 0: read from memory, 1:write to memory
375  assign cmd_extra_pages = mode_reg[MCONTR_LINTILE_EXTRAPG+:MCONTR_LINTILE_EXTRAPG_BITS]; // external module needs more than 1 page
379  assign status_data= {frame_finished_r, busy_r}; // TODO: Add second bit?
380  assign pgm_param_w= cmd_we;
383 
384  integer i;
387 // skipping pages that did not make it
388 // reg skip_tail; // skip end of frame if the next frame started (TBD)
389 // Now skip if write and >=4 or read and >=5 (read starts with 4 and may end with 4)
390 // Also if the next page signal is used by the source/dest of data, it should use reject pulse to advance external
391 // page counter
394  reg skip_run = 0; // run "skip" - advance addresses, but no actual read/write
396  reg frame_start_pending; // frame_start came before previous one was finished
399 
401  wire frame_start_mod = (frame_start && !busy_r) || frame_start_delayed; // when frame_start_delayed it will completely miss a frame_start
403  assign start_skip_w = skip_too_late && want_r && !xfer_grant && !skip_run &&
404  (((|page_cntr) && frame_start_pending) || ((page_cntr >= 4) && (cmd_wrmem || page_cntr[0]))); //&& busy_r && skip_run;
405  always @(posedge mclk) begin // Handling skip/reject
406  if (mrst) xfer_reject_r <= 0;
407  else xfer_reject_r <= xfer_grant && !chn_rst && skip_run;
408 
409 
410  if (mrst) xfer_start_r <= 0;
412 
413  if (mrst) xfer_start_rd_r <= 0;
415 
416  if (mrst) xfer_start_wr_r <= 0;
418 
419  if (mrst || recalc_r[PAR_MOD_LATENCY-1]) skip_run <= 0;
420  else if (start_skip_w) skip_run <= 1;
421 
422  if (mrst) start_skip_r <= 0;
423  else start_skip_r <= start_skip_w;
424 
425  if (mrst) xfer_skipped <= 0;
427 
428 // if (mrst || frame_start_delayed) frame_start_pending <= 0;
429  if (mrst) frame_start_pending <= 0;
430 // else frame_start_pending <= {frame_start_pending[0], busy_r && (frame_start_pending[0] | frame_start)};
432 
433  if (mrst) frame_start_pending_long <= 0;
435 
436  if (mrst) frame_start_r <= 0;
437 // else frame_start_r <= {frame_start_r[3:0], frame_start & frame_en};
439 
440  if (mrst || disable_need) need_r <= 0;
441  else if (chn_rst || xfer_grant || start_skip_r) need_r <= 0;
442  else if ((pre_want || want_r) && (page_cntr>=3)) need_r <= 1; // may raise need if want was already set
443 
444  if (mrst) want_r <= 0;
445  else if (chn_rst || xfer_grant || start_skip_r) want_r <= 0;
446  else if (pre_want && (page_cntr > {1'b0,cmd_extra_pages})) want_r <= 1;
447 
448  end
449 
450 /// Recalcualting just after starting request - preparing for the next one. Also happens after parameter change.
451 /// Should dppend only on the parameters updated separately (curr_x, curr_y)
452  always @(posedge mclk) begin // TODO: Match latencies (is it needed?) Reduce consumption by CE?
453  if (recalc_r[0]) begin // cycle 1
454  frame_x <= curr_x + window_x0;
455  frame_y <= curr_y + window_y0;
456  next_y <= curr_y + 1;
457  row_left <= window_width - curr_x; // 14 bits - 13 bits
458  end
459 // registers to be absorbed in DSP block
460  frame_y8_r <= frame_y[FRAME_HEIGHT_BITS-1:3]; // lat=2
463  mul_rslt <= mul_rslt_w[MPY_WIDTH-1:0]; // frame_y8_r * frame_width_r; // 7 bits will be discarded lat=3;
465 
466 // TODO: Verify MPY/register timing above
467  if (recalc_r[5]) begin // cycle 6
469 // line_start_page_left <= {COLADDR_NUMBER-3{1'b0}} - line_start_addr[COLADDR_NUMBER-4:0]; // 7 bits
471  end
472  bank_reg[0 +:3] <= frame_y[2:0]; //TODO: is it needed - a pipeline for the bank? - remove!
473  for (i=0;i<2; i = i+1)
474  bank_reg[(i+1)*3 +:3] <= bank_reg[i * 3 +: 3];
475 
476 
477  if (recalc_r[6]) begin // cycle 7
479 
481  (1<<NUM_XFER_BITS):
482  row_left[NUM_XFER_BITS:0]; // 7 bits, max 'h40
483  end
484  if (recalc_r[7]) begin // cycle 8
491  //xfer_num128_r depends on leftover only if continued_xfer (after first shortened actual xfer and will not change w/o xfers)
492  // and (next) leftover is only set if continued_xfer==0, so multiple runs without chnge of continued_xfer will not differ
493  if (!continued_xfer) leftover <= remainder_in_xfer[NUM_XFER_BITS-1:0]; // {EXTRA_BITS, lim_by_xfer}-mem_page_left;
494  end
495 
496  if (recalc_r[8]) begin // cycle 9
497  last_in_row <= last_in_row_w; //(row_left=={{(FRAME_WIDTH_BITS-NUM_XFER_BITS){1'b0}},xfer_num128_r});
498  end
499 
500 
501  end
503 // now have row start address, bank and row_left ;
504 // calculate number to read (min of row_left, maximal xfer and what is left in the DDR3 page
505  always @(posedge mclk) begin
506  // acceletaring pre_want
507 
508 // pre_want_r1 <= chn_en && !frame_done_r && busy_r && par_mod_r[PAR_MOD_LATENCY-2] && !(|frame_start_r[4:1]) && !last_block;
509  //last_block is too late for pre_want_r1, moving upsteram
511  if (mrst) par_mod_r<=0;
512  else if (pgm_param_w ||
513  xfer_start_r[0] ||
514  chn_rst ||
515  frame_start_r[0]) par_mod_r<=0;
516  else par_mod_r <= {par_mod_r[PAR_MOD_LATENCY-2:0], 1'b1};
517 
518  if (mrst) chn_rst_d <= 0;
519  else chn_rst_d <= chn_rst;
520 
521  if (mrst) recalc_r<=0;
522  else if (chn_rst) recalc_r<=0;
523  else recalc_r <= {recalc_r[PAR_MOD_LATENCY-2:0],
525 
526  if (mrst) busy_r <= 0;
527  else if (chn_rst) busy_r <= 0;
528  else if (frame_start_r[0]) busy_r <= 1;
529  else if (frame_done_r) busy_r <= 0;
530 
531  if (mrst) xfer_done_d <= 0;
533 
534 
535  if (mrst) continued_xfer <= 1'b0;
536  else if (chn_rst) continued_xfer <= 1'b0;
537  else if (frame_start_r[0]) continued_xfer <= 1'b0;
538  else if (xfer_start_r[0]) continued_xfer <= xfer_limited_by_mem_page_r; // only set after actual start if it was partial, not after parameter change
539 
540  // single cycle (sent out)
541  if (mrst) frame_done_r <= 0;
543 
544  // turns and stays on (used in status)
545  if (mrst) frame_finished_r <= 0;
546  else if (chn_rst || frame_start_r[0]) frame_finished_r <= 0;
547  else if (frame_done_r) frame_finished_r <= 1;
548 
549 
550 // if (mrst || disable_need) need_r <= 0;
551 // else if (chn_rst || xfer_grant || start_skip_r) need_r <= 0;
552 // else if ((pre_want || want_r) && (page_cntr>=3)) need_r <= 1; // may raise need if want was already set
553 
554 // if (mrst) want_r <= 0;
555 // else if (chn_rst || xfer_grant || start_skip_r) want_r <= 0;
556 // else if (pre_want && (page_cntr>{1'b0,cmd_extra_pages})) want_r <= 1;
557 
558  if (mrst) page_cntr <= 0;
559  else if (frame_start_r[0]) page_cntr <= cmd_wrmem?0:4; // What about last pages (like if only 1 page is needed)? Early frame end?
560  else if ( start_not_partial && !next_page) page_cntr <= page_cntr - 1;
561  else if (!start_not_partial && next_page) page_cntr <= page_cntr + 1;
562 
563  if (mrst) xfer_page_rst_r <= 1;
565 
566  if (mrst) xfer_page_rst_pos <= 1;
568 
569 
570 // increment x,y (two cycles)
571  if (mrst) curr_x <= 0;
572  else if (chn_rst || frame_start_r[0]) curr_x <= start_x;
573  else if (xfer_start_r[0]) curr_x <= last_in_row?0: curr_x + xfer_num128_r;
574 
575  if (mrst) curr_y <= 0;
576  else if (chn_rst || frame_start_r[0]) curr_y <= start_y;
577  else if (xfer_start_r[0] && last_in_row) curr_y <= next_y[FRAME_HEIGHT_BITS-1:0];
578 
579  if (mrst) last_block <= 0;
580  else if (chn_rst || !busy_r) last_block <= 0;
581  else if (xfer_start_r[0]) last_block <= last_row_w && last_in_row_w;
582 
583  if (mrst) pending_xfers <= 0;
584  else if (chn_rst || !busy_r) pending_xfers <= 0;
585  else if ( xfer_start_r[0] && !xfer_done_skipped) pending_xfers <= pending_xfers + 1;
587 
588  if (recalc_r[0]) line_unfinished_relw_r <= curr_y + (cmd_wrmem ? 0: 1);
589 
590 // if (mrst || (frame_start || !chn_en)) line_unfinished_r <= {FRAME_HEIGHT_BITS{~cmd_wrmem}}; // lowest/highest value until valid
591  if (mrst || (frame_start_mod || !chn_en)) line_unfinished_r <= {FRAME_HEIGHT_BITS{~cmd_wrmem}}; // lowest/highest value until valid
594 
595  end
596  always @ (negedge mclk) begin
598  end
599  cmd_deser #(
600  .ADDR (MCNTRL_SCANLINE_ADDR),
601  .ADDR_MASK (MCNTRL_SCANLINE_MASK),
602  .NUM_CYCLES (6),
603  .ADDR_WIDTH (4),
604  .DATA_WIDTH (32)
605  ) cmd_deser_32bit_i (
606  .rst (1'b0), //rst), // input
607  .clk (mclk), // input
608  .srst (mrst), // input
609  .ad (cmd_ad), // input[7:0]
610  .stb (cmd_stb), // input
611  .addr (cmd_a), // output[15:0]
612  .data (cmd_data), // output[31:0]
613  .we (cmd_we) // output
614  );
615  `ifdef DEBUG_SENS_MEM_PAGES
616  reg [1:0] dbg_cnt_snp;
617  reg [1:0] dbg_nxt_page;
618  reg dbg_busy_r2;
619  reg dbg_pre_want_r1;
620  reg [1:0] dbg_busy; // busy is toggling
621  reg [1:0] dbg_prewant; // pre_want_r1 is toggling
622 
623  // else if (!start_not_partial && next_page) page_cntr <= page_cntr + 1;
624  always @ (posedge mclk) begin
625  if (mrst) dbg_cnt_snp <= 0;
626  else if (start_not_partial) dbg_cnt_snp <= dbg_cnt_snp + 1;
627 
628  if (mrst) dbg_nxt_page <= 0;
629  else if (next_page) dbg_nxt_page <= dbg_nxt_page + 1;
630 
631  if (mrst) dbg_nxt_page <= 0;
632  else if (next_page) dbg_nxt_page <= dbg_nxt_page + 1;
633 
634  dbg_busy_r2 <= busy_r;
635  dbg_pre_want_r1 <=pre_want_r1;
636 
637  if (mrst) dbg_busy <= 0;
638  else if (busy_r && !dbg_busy_r2) dbg_busy <= dbg_busy + 1;
639 
640  if (mrst) dbg_prewant <= 0;
641  else if (pre_want_r1 && !dbg_pre_want_r1) dbg_prewant <= dbg_prewant + 1;
642  end
643 
644  `endif
645 
646  status_generate #(
647  .STATUS_REG_ADDR (MCNTRL_SCANLINE_STATUS_REG_ADDR),
648  `ifdef DEBUG_SENS_MEM_PAGES
649  .PAYLOAD_BITS (2 + 2 +2 + 2 + 2 + 2 +2 + 3 + 3 + MCNTRL_SCANLINE_PENDING_CNTR_BITS)
650  `else
651  .PAYLOAD_BITS (2)
652  `endif
653  ) status_generate_i (
654  .rst (1'b0), //rst), // input
655  .clk (mclk), // input
656  .srst (mrst), // input
657  .we (set_status_w), // input
658  .wd (cmd_data[7:0]), // input[7:0]
659  `ifdef DEBUG_SENS_MEM_PAGES
660  .status ({frame_en, page_cntr[2:0],
661  dbg_prewant[1:0], dbg_busy[1:0],
662  single_frame_r, repeat_frames, dbg_cnt_snp[1:0],
663  dbg_nxt_page[1:0], pending_xfers[1:0],
664  dbg_wpage[1:0], dbg_rpage[1:0],
665  status_data}), // input[25:0]
666  `else
667  .status (status_data), // input[25:0]
668  `endif
669  .ad (status_ad), // output[7:0]
670  .rq (status_rq), // output
671  .start (status_start) // input
672  );
673 endmodule
674 
675 
5335status_datawire[1:0]
5362window_heightreg[FRAME_HEIGHT_BITS:0]
5274NUM_RC_BURST_BITSADDRESS_NUMBER+COLADDR_NUMBER-3
5337cmd_datawire[31:0]
5356frame_number_cntrreg[LAST_FRAME_BITS-1:0]
5363window_x0reg[FRAME_WIDTH_BITS-1:0]
cmd_deser_32bit_i cmd_deser
[COLADDR_NUMBER-4:0] 5266xfer_col
5292line_start_page_leftreg[COLADDR_NUMBER-4:0]
5294remainder_in_xferwire[COLADDR_NUMBER-3:0]
5285mul_rsltreg[MPY_WIDTH-1:0]
5228MCNTRL_SCANLINE_WINDOW_X0Y0'h7
[LAST_FRAME_BITS-1:0] 5257frame_number
5312cmd_extra_pageswire[1:0]
5354start_addrreg[NUM_RC_BURST_BITS-1:0]
5302par_mod_rreg[PAR_MOD_LATENCY-1:0]
[NUM_XFER_BITS-1:0] 5267xfer_num128
[ADDR_MASK2!=0?2:ADDR_MASK1!=0?1:0:0] 9935we
Definition: cmd_deser.v:60
5296leftoverreg[NUM_XFER_BITS-1:0]
5222MCNTRL_SCANLINE_STATUS_CNTRL'h1
5377frame_start_pending_longreg[1:0]
5229MCNTRL_SCANLINE_WINDOW_STARTXY'h8
5288mul_rslt_wwire[FRAME_WIDTH_BITS+FRAME_HEIGHT_BITS-3:0]
5352frame_sizereg[NUM_RC_BURST_BITS-1:0]
[FRAME_HEIGHT_BITS-1:0] 5255line_unfinished
5293lim_by_xferreg[NUM_XFER_BITS:0]
5351start_range_addrreg[NUM_RC_BURST_BITS-1:0]
5284frame_full_width_rreg[FRAME_WIDTH_BITS:0]
5279next_yreg[FRAME_HEIGHT_BITS:0]
5364window_y0reg[FRAME_HEIGHT_BITS-1:0]
5278curr_yreg[FRAME_HEIGHT_BITS-1:0]
5231MCNTRL_SCANLINE_PENDING_CNTR_BITS2
status_generate_i status_generate
5289row_leftreg[FRAME_WIDTH_BITS:0]
5280line_start_addrreg[NUM_RC_BURST_BITS-1:0]
[DATA_WIDTH-1:0] 9934data
Definition: cmd_deser.v:59
5303recalc_rreg[PAR_MOD_LATENCY-1:0]
5365start_xreg[FRAME_WIDTH_BITS-1:0]
5226MCNTRL_SCANLINE_FRAME_FULL_WIDTH'h5
5232MCNTRL_SCANLINE_FRAME_PAGE_RESET1'b0
5275MPY_WIDTHNUM_RC_BURST_BITS
5319rst_frame_num_rreg[1:0]
5329pending_xfersreg[MCNTRL_SCANLINE_PENDING_CNTR_BITS-1:0]
5332line_unfinished_rreg[FRAME_HEIGHT_BITS-1:0]
5287bank_regreg[3*3-1:0]
[7:0] 9931ad
Definition: cmd_deser.v:56
5366start_yreg[FRAME_HEIGHT_BITS-1:0]
[ADDR_WIDTH-1:0] 9933addr
Definition: cmd_deser.v:58
[COLADDR_NUMBER-3-NUM_XFER_BITS-1:0] 5368EXTRA_BITS0
5277curr_xreg[FRAME_WIDTH_BITS-1:0]
5360frame_full_widthreg[FRAME_WIDTH_BITS:0]
5283frame_y8_rreg[FRAME_HEIGHT_BITS-4:0]
5291mem_page_leftreg[COLADDR_NUMBER-3:0]
5297xfer_num128_rreg[NUM_XFER_BITS:0]
5361window_widthreg[FRAME_WIDTH_BITS:0]
5282frame_xreg[FRAME_WIDTH_BITS-1:0]
5331line_unfinished_relw_rreg[FRAME_HEIGHT_BITS-1:0]
5286start_addr_rreg[NUM_RC_BURST_BITS-1:0]
[ADDRESS_NUMBER-1:0] 5265xfer_row
5230MCNTRL_SCANLINE_STATUS_REG_ADDR'h4
5281frame_yreg[FRAME_HEIGHT_BITS-1:0]
[ALL_BITS-1:0] 10777status
5353last_frame_numberreg[LAST_FRAME_BITS-1:0]
5330row_col_rreg[NUM_RC_BURST_BITS-1:0]
5357frame_number_currentreg[LAST_FRAME_BITS-1:0]
5355next_frame_start_addrreg[NUM_RC_BURST_BITS-1:0]