x393  1.0
FPGAcodeforElphelNC393camera
cmd_encod_tiled_32_rd.v
Go to the documentation of this file.
1 
45 `timescale 1ns/1ps
46 /*
47 TODO Comments from cmd_encod_tiled_rd, update
48 Minimal ACTIVATE period =4 Tcm or 10ns, so maximal no-miss rate is Tck=1.25 ns (800 MHz)
49 Minimal window of 4 ACTIVATE pulses - 16 Tck or 40 (40 ns), so one ACTIVATE per 8 Tck is still OK down to 1.25 ns
50 Reads are in 16-byte colums: 1 8-burst (16 bytes) in a row, then next row, bank inc first. Then (if needed) - next column
51 Number of rows should be >=5 (4 now for tCK=2.5ns to meet tRP (precharge to activate) of the same bank (tRP=13ns)
52 Can read less if just one column
53 TODO: Maybe allow less rows with different sequence (no autoprecharge/no activate?) Will not work if row crosses page boundary
54 number fo rows>1!
55 
56 Known issues:
57 1: Most tile heights cause timing violation. Valid height mod 8 can be 0,6,7 (1,2,3,4,5 - invalid - wrong - that was for tile16 mode)
58 2: With option "keep_open" there should be no page boundary crossings, caller only checks the first line, and if window full width
59  is not multiple of CAS page, page crossings can appear on other than first line (fix caller to use largest common divider of page and
60  frame full width? Seems easy to fix
61 */
62 
64  parameter ADDRESS_NUMBER= 15,
65  parameter COLADDR_NUMBER= 10,
66  parameter CMD_PAUSE_BITS= 10,
67  parameter CMD_DONE_BIT= 10, // VDT BUG: CMD_DONE_BIT is used in a function call parameter!
68  parameter FRAME_WIDTH_BITS= 13, // Maximal frame width - 8-word (16 bytes) bursts
69  parameter RSEL= 1'b1 // Late/early READ commands
70 ) (
71  input mrst,
72  input clk,
73 // programming interface
74  input [2:0] start_bank, // bank address
75  input [ADDRESS_NUMBER-1:0] start_row, // memory row
76  input [COLADDR_NUMBER-4:0] start_col, // start memory column in 8-bit bursts
77  input [FRAME_WIDTH_BITS:0] rowcol_inc_in, // increment {row.col} when bank rolls over, removed 3 LSBs (in 8-bursts)
78  input [5:0] num_rows_in_m1, // number of rows to read minus 1
79  input [5:0] num_cols_in_m1, // number of 32-pixel columns to read (rows first, then columns) - 1
80  //(for compatibility with cmd_encod_tiled, LSB will be ignored)
81  input keep_open_in, // keep banks open (for <=8 banks only
82  input skip_next_page_in, // do not reset external buffer (continue)
83  input start, // start generating commands
84  output reg [31:0] enc_cmd, // encoded command SuppressThisWarning VivadoSynthesis: [Synth 8-3332] Sequential element cmd_encod_tiled_32_rd.enc_cmd_reg[11:9,7:5,2] is unused and will be removed from module cmd_encod_tiled_32_rd.
85  output reg enc_wr, // write encoded command
86  output reg enc_done // encoding finished
87 );
88  localparam FULL_ADDR_NUMBER=ADDRESS_NUMBER+COLADDR_NUMBER; // excluding 3 CA lsb, but adding 3 bank
89  localparam ROM_WIDTH=10;
90  localparam ROM_DEPTH=4;
91 
92  localparam ENC_NOP= 0;
93  localparam ENC_BUF_WR= 1;
94  localparam ENC_DCI= 2;
95  localparam ENC_SEL= 3;
96  localparam ENC_CMD_SHIFT= 4; // [5:4] - command: 0 -= NOP, 1 - READ, 2 - PRECHARGE, 3 - ACTIVATE
97  localparam ENC_PAUSE_SHIFT=6; // [7:6] - 2- bit pause (for NOP commandes)
98  localparam ENC_PRE_DONE= 8;
99  localparam ENC_BUF_PGNEXT= 9;
100 
101  localparam ENC_CMD_NOP= 0; // 2-bit locally encoded commands
102  localparam ENC_CMD_READ= 1;
103 // localparam ENC_CMD_PRECHARGE=2;
104  localparam ENC_CMD_ACTIVATE= 2; // using autoprecharge, so no PRECHARGE is needed. When en_act==0, ENC_CMD_ACTIVATE-> ENC_CMD_NOP (delay should be 0)
105 // localparam REPEAT_ADDR=3;
106  localparam LOOP_FIRST= 4; // address of the first word in a loop
107  localparam LOOP_LAST= 6; // address of the last word in a loop
108  localparam CMD_NOP= 0; // 3-bit normal memory RCW commands (positive logic)
109  localparam CMD_READ= 2;
110 // localparam CMD_PRECHARGE=5;
111  localparam CMD_ACTIVATE= 4;
112 // localparam AUTOPRECHARGE_BIT=COLADDR_NUMBER;
113 
114  reg [ADDRESS_NUMBER-1:0] row; // memory row
115  reg [COLADDR_NUMBER-4:0] col; // start memory column in 8-bursts SuppressThisWarning VivadoSynthesis: [Synth 8-3332] Sequential element cmd_encod_tiled_32_rd.col_reg[0] is unused and will be removed from module cmd_encod_tiled_32_rd.
116  reg [2:0] bank; // memory bank;
117  reg [5:0] num_rows_m1; // number of rows in a tile minus 1
118  reg [5:0] num_cols128_m2; // number of r16-byte columns in a tile -2 (even columns) SuppressThisWarning VivadoSynthesis: [Synth 8-3332] Sequential element cmd_encod_tiled_32_rd.num_cols128_m2_reg[0] is unused and will be removed from module cmd_encod_tiled_32_rd.
119 // reg [FULL_ADDR_NUMBER-4:0] rowcol_inc; // increment {row.col} when bank rolls over, remove 3 LSBs (in 8-bursts)
120  reg [FRAME_WIDTH_BITS:0] rowcol_inc; // increment {row.col} when bank rolls over, remove 3 LSBs (in 8-bursts)
121 
122  reg keep_open;
124  reg gen_run;
125 // reg gen_run_d; // to output "done"?
126  reg [ROM_DEPTH-1:0] gen_addr; // will overrun as stop comes from ROM
127 
128  reg [ROM_WIDTH-1:0] rom_r;
129  wire pre_done;
130  wire [1:0] rom_cmd;
131  wire [1:0] rom_skip;
132  wire [2:0] full_cmd;
133 // reg done;
134 
135  reg [FULL_ADDR_NUMBER-4:0] top_rc; // top combined row,column,bank burst address (excludes 3 CA LSBs), valid/modified @pre_act
137  reg last_col;
138  wire pre_act; //1 cycle before optional ACTIVATE
139  wire pre_read; //1 cycle before READ command
140  reg [5:0] scan_row; // current row in a tile (valid @pre_act)
141  reg [5:0] scan_col; // current 16-byte column in a tile (valid @pre_act) SuppressThisWarning VivadoSynthesis: [Synth 8-3332] Sequential element cmd_encod_tiled_32_rd.scan_col_reg[0] is unused and will be removed from module cmd_encod_tiled_32_rd.
142  reg start_d; // start, delayed by 1 clocks
143  wire last_row;
144  reg [FULL_ADDR_NUMBER-1:0] row_col_bank; // RA,CA, BA - valid @pre_act;
145  wire [COLADDR_NUMBER-1:0] col_bank;// CA, BA - valid @ pre_read;
146 
149 
150  wire [2:0] next_bank_w;
151  wire [ADDRESS_NUMBER+COLADDR_NUMBER-4:0] next_rowcol_w; // next row/col when bank rolls over (in 8-bursts)
152 
154 
155  wire [FULL_ADDR_NUMBER-1:0] row_col_bank_next_w; // RA,CA, BA - valid @pre_act;
157  {top_rc,bank}: // can not work if ACTIVATE is next after ACTIVATE in the last row (single-row tile)
158  (&row_col_bank[2:0]? // bank==7
159  {next_rowcol_w,3'b0}:
161 
162 
163  assign pre_done=rom_r[ENC_PRE_DONE] && gen_run;
164 // assign rom_cmd= rom_r[ENC_CMD_SHIFT+:2] & {enable_act,1'b1}; // disable bit 1 if activate is disabled (not the first column)
165  assign rom_cmd= rom_r[ENC_CMD_SHIFT+:2]; // & {enable_act,1'b1}; // disable bit 1 if activate is disabled (not the first column)
166  assign rom_skip= rom_r[ENC_PAUSE_SHIFT+:2];
168 
169  assign last_row= (scan_row==num_rows_m1);
170  assign enable_act= first_col || !keep_open; // TODO: do not forget to zero addresses too (or they will become pause/done)
171  assign next_bank_w= row_col_bank[2:0]+1; //bank+1;
173 
174  assign pre_act= gen_run && rom_cmd[1]; //1 cycle before optional ACTIVATE
175  assign pre_read= rom_r[ENC_CMD_SHIFT]; //1 cycle before READ command
176 
177 
178  always @ (posedge clk) begin
179  if (mrst) gen_run <= 0;
180  else if (start_d) gen_run<= 1; // delaying
181  else if (pre_done) gen_run<= 0;
182 
183 // if (rst) gen_run_d <= 0;
184 // else gen_run_d <= gen_run;
185 
186  if (mrst) num_rows_m1 <= 0;
187  else if (start) num_rows_m1 <= num_rows_in_m1; // number of rows
188 
189  if (mrst) num_cols128_m2 <= 0;
190  else if (start) num_cols128_m2 <= num_cols_in_m1 & ~1; // number of r32-byte columns
191 
192  if (mrst) start_d <=0;
193  else start_d <= start;
194 
195  if (mrst) top_rc <= 0;
196  else if (start_d) top_rc <= {row,col}+2;
197  else if (pre_act && last_row) top_rc <= top_rc+2; // may increment RA
198 
199  if (mrst) row_col_bank <= 0;
200  else if (start_d) row_col_bank <= {row,col,bank}; // TODO: Use start_col,... and start, not start_d?
201 
203 
204 
205  if (mrst) scan_row <= 0;
206  else if (start_d) scan_row <= 0;
207  else if (pre_act) scan_row <= last_row?0:scan_row+1;
208 
209  if (mrst) scan_col <= 0;
210  else if (start_d) scan_col <= 0;
211  else if (pre_act && last_row) scan_col <= scan_col+2; // for ACTIVATE, not for READ
212 
213  if (mrst) first_col <= 0;
214  else if (start_d) first_col <= 1;
215  else if (pre_act && last_row) first_col <= 0;
216 
217  if (mrst) last_col <= 0;
218  else if (start_d) last_col <= num_cols128_m2==0; // if single column - will start with 1'b1;
219  else if (pre_act) last_col <= (scan_col==num_cols128_m2); // too early for READ ?
220 
221  if (mrst) enable_autopre <= 0;
222  else if (start_d) enable_autopre <= 0;
223  else if (pre_act) enable_autopre <= last_col || !keep_open; // delayed by 2 pre_act tacts form last_col, OK with a single column
224 
225  if (mrst) loop_continue<=0;
227 
228  if (mrst) gen_addr <= 0;
229  else if (!start_d && !gen_run) gen_addr <= 0;
230  else if ((gen_addr==LOOP_LAST) && !loop_continue) gen_addr <= LOOP_FIRST; // skip loop alltogeter
231  else gen_addr <= gen_addr+1; // not in a loop
232  end
233 
234  always @ (posedge clk) if (start) begin
235  row<=start_row;
236  col <= start_col & ~1;
237  bank <= start_bank;
239  keep_open <= keep_open_in && (|num_cols_in_m1[5:3] == 0);
241  end
242 
243  // ROM-based (registered output) encoded sequence
244  always @ (posedge clk) begin
245  if (mrst) rom_r <= 0; // TODO: make mrst cause gen_addr = 4'hf?
246  else case (gen_addr)
247  4'h0: rom_r <= (ENC_CMD_ACTIVATE << ENC_CMD_SHIFT) | (1 << ENC_NOP) | (1 << ENC_PAUSE_SHIFT); // here does not matter, just to work with masked ACTIVATE
248  4'h1: rom_r <= (ENC_CMD_ACTIVATE << ENC_CMD_SHIFT);
249  4'h2: rom_r <= (ENC_CMD_READ << ENC_CMD_SHIFT) | (1 << ENC_NOP) | (1 << ENC_BUF_WR) | (1 << ENC_DCI) | (RSEL << ENC_SEL);
250  4'h3: rom_r <= (ENC_CMD_READ << ENC_CMD_SHIFT) | (1 << ENC_BUF_WR) | (1 << ENC_DCI) | (RSEL << ENC_SEL);
251 // loop:
252  4'h4: rom_r <= (ENC_CMD_ACTIVATE << ENC_CMD_SHIFT) | (1 << ENC_BUF_WR) | (1 << ENC_DCI) | (RSEL << ENC_SEL);
253  4'h5: rom_r <= (ENC_CMD_READ << ENC_CMD_SHIFT) | (1 << ENC_NOP) | (1 << ENC_BUF_WR) | (1 << ENC_DCI) | (RSEL << ENC_SEL);
254  4'h6: rom_r <= (ENC_CMD_READ << ENC_CMD_SHIFT) | (1 << ENC_BUF_WR) | (1 << ENC_DCI) | (RSEL << ENC_SEL);
255 // end loop
256  4'h7: rom_r <= (ENC_CMD_NOP << ENC_CMD_SHIFT) | (1 << ENC_BUF_WR) | (1 << ENC_DCI) | (RSEL << ENC_SEL);
257  4'h8: rom_r <= (ENC_CMD_READ << ENC_CMD_SHIFT) | (1 << ENC_NOP) | (1 << ENC_BUF_WR) | (1 << ENC_DCI) | (RSEL << ENC_SEL);
258  4'h9: rom_r <= (ENC_CMD_READ << ENC_CMD_SHIFT) | (1 << ENC_BUF_WR) | (1 << ENC_DCI) | (RSEL << ENC_SEL);
259 // do not combine this NOP - ENC_CMD_READ + ENC_NOP enables autoprecharge
260  4'ha: rom_r <= (ENC_CMD_NOP << ENC_CMD_SHIFT) | (1 << ENC_BUF_WR) | (1 << ENC_DCI) | (RSEL << ENC_SEL);
261  4'hb: rom_r <= (ENC_CMD_NOP << ENC_CMD_SHIFT) | (1 << ENC_PAUSE_SHIFT) | (1 << ENC_DCI) | (RSEL << ENC_SEL);
262  4'hc: rom_r <= (ENC_CMD_NOP << ENC_CMD_SHIFT) | (1 << ENC_DCI) | (RSEL << ENC_SEL) | (1 << ENC_BUF_PGNEXT);
263  4'hd: rom_r <= (ENC_CMD_NOP << ENC_CMD_SHIFT) | (3 << ENC_PAUSE_SHIFT) | (1 << ENC_DCI);
264  4'he: rom_r <= (ENC_CMD_NOP << ENC_CMD_SHIFT) | (1 << ENC_PRE_DONE);
265  default:rom_r <= 0;
266  endcase
267  end
268  always @ (posedge clk) begin
269 
270  if (mrst) enc_wr <= 0;
271  else enc_wr <= gen_run; // || gen_run_d;
272 
273  if (mrst) enc_done <= 0;
274  else enc_done <= enc_wr && !gen_run; // !gen_run_d;
275 
276  if (mrst) enc_cmd <= 0;
277 // else if ((rom_cmd==0) || (rom_cmd[1] && !enable_act)) enc_cmd <= func_encode_skip ( // encode pause
278  else if (gen_run) begin
279  if (rom_cmd[0] || (rom_cmd[1] && enable_act)) enc_cmd <= func_encode_cmd ( // encode non-NOP command
280  rom_cmd[1]? // activate
281  row_col_bank[FULL_ADDR_NUMBER-1:COLADDR_NUMBER]: // top combined row,column,bank burst address (excludes 3 CA LSBs), valid/modified @pre_act
282  {{ADDRESS_NUMBER-COLADDR_NUMBER-1{1'b0}},
285  3'b0}, // [14:0] addr; // 15-bit row/column address
286  rom_cmd[1]?
287  row_col_bank[2:0]:
288  col_bank[2:0], //
289  full_cmd[2:0], // rcw; // RAS/CAS/WE, positive logic. full_cmd[0]==0 (never write/precharge) => enc_cmd_reg[11]==0
290  1'b0, // odt_en; // enable ODT
291  1'b0, // cke; // disable CKE
292  rom_r[ENC_SEL], // sel; // first/second half-cycle, other will be nop (cke+odt applicable to both)
293  1'b0, // dq_en; // enable (not tristate) DQ lines (internal timing sequencer for 0->1 and 1->0)
294  1'b0, // dqs_en; // enable (not tristate) DQS lines (internal timing sequencer for 0->1 and 1->0)
295  1'b0, // dqs_toggle; // enable toggle DQS according to the pattern
296  rom_r[ENC_DCI], // dci; // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
297  rom_r[ENC_BUF_WR], // buf_wr; // connect to external buffer (but only if not paused)
298  1'b0, // buf_rd; // connect to external buffer (but only if not paused)
299  rom_r[ENC_NOP], // nop; // add NOP after the current command, keep other data
300  rom_r[ENC_BUF_PGNEXT] && !skip_next_page); // buf_rst; // connect to external buffer (but only if not paused)
301  else enc_cmd <= func_encode_skip ( // encode pause
302  {{CMD_PAUSE_BITS-2{1'b0}},rom_skip[1:0]}, // skip; // number of extra cycles to skip (and keep all the other outputs)
303  pre_done, // done, // end of sequence
304  3'b0, // bank (here OK to be any)
305  1'b0, // odt_en; // enable ODT
306  1'b0, // cke; // disable CKE
307  rom_r[ENC_SEL], // sel; // first/second half-cycle, other will be nop (cke+odt applicable to both)
308  1'b0, // dq_en; // enable (not tristate) DQ lines (internal timing sequencer for 0->1 and 1->0)
309  1'b0, // dqs_en; // enable (not tristate) DQS lines (internal timing sequencer for 0->1 and 1->0)
310  1'b0, // dqs_toggle; // enable toggle DQS according to the pattern
311  rom_r[ENC_DCI], // dci; // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
312  rom_r[ENC_BUF_WR], // buf_wr; // connect to external buffer (but only if not paused)
313  1'b0, // buf_rd; // connect to external buffer (but only if not paused)
314  rom_r[ENC_BUF_PGNEXT] && !skip_next_page); // buf_rst; // connect to external buffer (but only if not paused)
315  end
316  end
318  .WIDTH(COLADDR_NUMBER)
319  ) fifo_2regs_i (
320  .mrst (mrst), // input
321  .clk (clk), // input
322  .din (row_col_bank[COLADDR_NUMBER-1:0]), // input[15:0]
323  .wr (pre_act), // input
324  .rd (pre_read && !rom_r[ENC_NOP]), // input - update only after the second READ
325  .srst (start_d), // input
326  .dout (col_bank) // output[15:0]
327  );
328 
365 
366  function [31:0] func_encode_cmd;
367  input [14:0] addr; // 15-bit row/column address
368  input [2:0] bank; // bank (here OK to be any)
369  input [2:0] rcw; // RAS/CAS/WE, positive logic
370  input odt_en; // enable ODT
371  input cke; // disable CKE
372  input sel; // first/second half-cycle, other will be nop (cke+odt applicable to both)
373  input dq_en; // enable (not tristate) DQ lines (internal timing sequencer for 0->1 and 1->0)
374  input dqs_en; // enable (not tristate) DQS lines (internal timing sequencer for 0->1 and 1->0)
375  input dqs_toggle; // enable toggle DQS according to the pattern
376  input dci; // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
377  input buf_wr; // connect to external buffer (but only if not paused)
378  input buf_rd; // connect to external buffer (but only if not paused)
379  input nop; // add NOP after the current command, keep other data
380  input buf_rst; // connect to external buffer (but only if not paused)
381  begin
382  func_encode_cmd={
383  addr[14:0], // 15-bit row/column address
384  bank [2:0], // bank
385  rcw[2:0], // RAS/CAS/WE
386  odt_en, // enable ODT
387  cke, // may be optimized (removed from here)?
388  sel, // first/second half-cycle, other will be nop (cke+odt applicable to both)
389  dq_en, // enable (not tristate) DQ lines (internal timing sequencer for 0->1 and 1->0)
390  dqs_en, // enable (not tristate) DQS lines (internal timing sequencer for 0->1 and 1->0)
391  dqs_toggle, // enable toggle DQS according to the pattern
392  dci, // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
393  buf_wr, // phy_buf_wr, // connect to external buffer (but only if not paused)
394  buf_rd, // phy_buf_rd, // connect to external buffer (but only if not paused)
395  nop, // add NOP after the current command, keep other data
396  buf_rst // Reserved for future use
397  };
398  end
399  endfunction
400 
401  function [31:0] func_encode_skip;
402  input [CMD_PAUSE_BITS-1:0] skip; // number of extra cycles to skip (and keep all the other outputs)
403  input done; // end of sequence
404  input [2:0] bank; // bank (here OK to be any)
405  input odt_en; // enable ODT
406  input cke; // disable CKE
407  input sel; // first/second half-cycle, other will be nop (cke+odt applicable to both)
408  input dq_en; // enable (not tristate) DQ lines (internal timing sequencer for 0->1 and 1->0)
409  input dqs_en; // enable (not tristate) DQS lines (internal timing sequencer for 0->1 and 1->0)
410  input dqs_toggle; // enable toggle DQS according to the pattern
411  input dci; // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
412  input buf_wr; // connect to external buffer (but only if not paused)
413  input buf_rd; // connect to external buffer (but only if not paused)
414  input buf_rst; // connect to external buffer (but only if not paused)
415  begin
416  func_encode_skip= func_encode_cmd (
417  {{14-CMD_DONE_BIT{1'b0}}, done, skip[CMD_PAUSE_BITS-1:0]}, // 15-bit row/column address
418  bank[2:0], // bank (here OK to be any)
419  3'b0, // RAS/CAS/WE, positive logic
420  odt_en, // enable ODT
421  cke, // disable CKE
422  sel, // first/second half-cycle, other will be nop (cke+odt applicable to both)
423  dq_en, // enable (not tristate) DQ lines (internal timing sequencer for 0->1 and 1->0)
424  dqs_en, // enable (not tristate) DQS lines (internal timing sequencer for 0->1 and 1->0)
425  dqs_toggle, // enable toggle DQS according to the pattern
426  dci, // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
427  buf_wr, // connect to external buffer (but only if not paused)
428  buf_rd, // connect to external buffer (but only if not paused)
429  1'b0, // nop
430  buf_rst);
431  end
432  endfunction
433 
434 
435 endmodule
436 
4138top_rcreg[FULL_ADDR_NUMBER-4:0]
4148col_bankwire[COLADDR_NUMBER-1:0]
[WIDTH-1:0] 10385din
Definition: fifo_2regs.v:47
4152next_rowcol_wwire[ADDRESS_NUMBER+COLADDR_NUMBER-4:0]
4123rowreg[ADDRESS_NUMBER-1:0]
4132gen_addrreg[ROM_DEPTH-1:0]
4154row_col_bank_next_wwire[FULL_ADDR_NUMBER-1:0]
4128rowcol_increg[FRAME_WIDTH_BITS:0]
4104FULL_ADDR_NUMBERADDRESS_NUMBER+COLADDR_NUMBER
[WIDTH-1:0] 10389dout
Definition: fifo_2regs.v:51
[ADDRESS_NUMBER-1:0] 4093start_row
4147row_col_bankreg[FULL_ADDR_NUMBER-1:0]
4124colreg[COLADDR_NUMBER-4:0]
4133rom_rreg[ROM_WIDTH-1:0]
[COLADDR_NUMBER-4:0] 4094start_col
[FRAME_WIDTH_BITS:0] 4095rowcol_inc_in