x393  1.0
FPGAcodeforElphelNC393camera
cmd_encod_tiled_32_wr.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 WSEL= 1'b0
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  //(for compatibility with cmd_encod_tiled, LSB will be ignored)
79  input [5:0] num_rows_in_m1, // number of rows to read minus 1
80  input [5:0] num_cols_in_m1, // number of 16-pixel columns to read (rows first, then columns) - 1
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
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=13;
90  localparam ROM_DEPTH=4;
91  localparam ENC_NOP= 0;
92  localparam ENC_BUF_RD= 1;
93  localparam ENC_DQS_TOGGLE= 2;
94  localparam ENC_DQ_DQS_EN= 3;
95  localparam ENC_SEL= 4;
96  localparam ENC_ODT= 5;
97  localparam ENC_CMD_SHIFT= 6; // [7:6] - command: 0 -= NOP, 1 - WRITE, 2 - PRECHARGE, 3 - ACTIVATE
98  localparam ENC_PAUSE_SHIFT= 8; // [9:8] - 2- bit pause (for NOP commandes)
99  localparam ENC_PRE_DONE= 10;
100  localparam ENC_BUF_PGNEXT= 11;
101  localparam ENC_AUTOPRE= 12;
102 
103  localparam ENC_CMD_NOP= 0; // 2-bit locally encoded commands
104  localparam ENC_CMD_WRITE= 1;
105  localparam ENC_CMD_ACTIVATE= 2;
106 
107  localparam LOOP_FIRST= 6; // address of the first word in a loop
108  localparam LOOP_LAST= 8; // address of the last word in a loop
109 
110  localparam CMD_NOP= 0; // 3-bit normal memory RCW commands (positive logic)
111  localparam CMD_WRITE= 3;
112  localparam CMD_ACTIVATE= 4;
113 
114 
115  reg [ADDRESS_NUMBER-1:0] row; // memory row
116  reg [COLADDR_NUMBER-4:0] col; // start memory column in 8-bursts
117  reg [2:0] bank; // memory bank;
118  reg [5:0] num_rows_m1; // number of rows in a tile minus 1
119  reg [5:0] num_cols128_m1; // number of r16-byte columns in a tile -1 (actually -2 with LSB==0)
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_write; //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)
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_write;
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;
156 
157 // reg cut_buf_rd;
158 
159  // always @ (posedge clk) begin
160  // if (!gen_run) cut_buf_rd <= 0;
161  // else if ((gen_addr==(LOOP_LAST-1)) && !loop_continue) cut_buf_rd <= 1;
162  // end
163 
165  {top_rc,bank}: // can not work if ACTIVATE is next after ACTIVATE in the last row (single-row tile)
166  (&row_col_bank[2:0]? // bank==7
167  {next_rowcol_w,3'b0}:
169 
170 
171  assign pre_done=rom_r[ENC_PRE_DONE] && gen_run;
172  assign rom_cmd= rom_r[ENC_CMD_SHIFT+:2]; // & {enable_act,1'b1}; // disable bit 1 if activate is disabled (not the first column)
173  assign rom_skip= rom_r[ENC_PAUSE_SHIFT+:2];
175 
176  assign last_row= (scan_row==num_rows_m1);
177  assign enable_act= first_col || !keep_open; // TODO: do not forget to zero addresses too (or they will become pause/done)
178  assign next_bank_w= row_col_bank[2:0]+1; //bank+1;
180 
181  assign pre_act= gen_run && rom_cmd[1]; //1 cycle before optional ACTIVATE
182  assign pre_write= rom_r[ENC_CMD_SHIFT]; //1 cycle before READ command
183 
184 
185  always @ (posedge clk) begin
186  if (mrst) gen_run <= 0;
187  else if (start_d) gen_run<= 1; // delaying
188  else if (pre_done) gen_run<= 0;
189 
190 
191  if (mrst) num_rows_m1 <= 0;
192  else if (start) num_rows_m1 <= num_rows_in_m1; // number of rows
193 
194  if (mrst) num_cols128_m1 <= 0;
195  else if (start) num_cols128_m1 <= num_cols_in_m1 & ~1; // number of r16-byte columns (without LSB - number of 32-byte columns)
196 
197  if (mrst) start_d <=0;
198  else start_d <= start;
199 
200  if (mrst) top_rc <= 0;
201  else if (start_d) top_rc <= {row,col}+2;
202  else if (pre_act && last_row) top_rc <= top_rc+2; // may increment RA
203 
204  if (mrst) row_col_bank <= 0;
205  else if (start_d) row_col_bank <= {row,col,bank}; // TODO: Use start_col,... and start, not start_d?
207 
208 
209  if (mrst) scan_row <= 0;
210  else if (start_d) scan_row <= 0;
211  else if (pre_act) scan_row <= last_row?0:scan_row+1;
212 
213  if (mrst) scan_col <= 0;
214  else if (start_d) scan_col <= 0;
215  else if (pre_act && last_row) scan_col <= scan_col+2; // for ACTIVATE, not for READ
216 
217  if (mrst) first_col <= 0;
218  else if (start_d) first_col <= 1;
219  else if (pre_act && last_row) first_col <= 0;
220 
221  if (mrst) last_col <= 0;
222  else if (start_d) last_col <= num_cols128_m1==0; // if single column - will start with 1'b1;
223  else if (pre_act) last_col <= (scan_col==num_cols128_m1); // too early for READ ?
224 
225  if (mrst) enable_autopre <= 0;
226  else if (start_d) enable_autopre <= 0;
227  else if (pre_act) enable_autopre <= last_col || !keep_open; // delayed by 2 pre_act tacts form last_col, OK with a single column
228 
229  if (mrst) loop_continue<=0;
231 
232  if (mrst) gen_addr <= 0;
233  else if (!start_d && !gen_run) gen_addr <= 0;
234  else if ((gen_addr==LOOP_LAST) && !loop_continue) gen_addr <= LOOP_FIRST; // skip loop alltogeter
235  else gen_addr <= gen_addr+1; // not in a loop
236  end
237 
238  always @ (posedge clk) if (start) begin
239  row<=start_row;
240  col <= start_col & ~1;
241  bank <= start_bank;
243  keep_open <= keep_open_in && (|num_cols_in_m1[5:3] == 0);
245  end
246 
247  // ROM-based (registered output) encoded sequence
248  always @ (posedge clk) begin
249  if (mrst) rom_r <= 0;
250  else case (gen_addr)
251  4'h0: rom_r <= (ENC_CMD_ACTIVATE << ENC_CMD_SHIFT) | (1 << ENC_BUF_RD) ; // here does not matter, just to work with masked ACTIVATE
252  4'h1: rom_r <= (ENC_CMD_NOP << ENC_CMD_SHIFT) | (1 << ENC_BUF_RD) ;
253  4'h2: rom_r <= (ENC_CMD_ACTIVATE << ENC_CMD_SHIFT) | (1 << ENC_BUF_RD) | (WSEL << ENC_SEL);
254  4'h3: rom_r <= (ENC_CMD_WRITE << ENC_CMD_SHIFT) | (1 << ENC_BUF_RD) | (WSEL << ENC_SEL) | (1 << ENC_ODT);
255 // 4'h4: rom_r <= (ENC_CMD_NOP << ENC_CMD_SHIFT) | (1 << ENC_BUF_RD) | (WSEL << ENC_SEL) | (1 << ENC_ODT) | (1 << ENC_DQ_DQS_EN);
256  4'h4: rom_r <= (ENC_CMD_NOP << ENC_CMD_SHIFT) | (1 << ENC_BUF_RD) | (WSEL << ENC_SEL) | (1 << ENC_ODT);
257  4'h5: rom_r <= (ENC_CMD_WRITE << ENC_CMD_SHIFT) | (1 << ENC_AUTOPRE) | (1 << ENC_BUF_RD) | (WSEL << ENC_SEL) | (1 << ENC_ODT) | (1 << ENC_DQ_DQS_EN) | (1 << ENC_DQS_TOGGLE);
258 // loop
259  4'h6: rom_r <= (ENC_CMD_ACTIVATE << ENC_CMD_SHIFT) | (1 << ENC_BUF_RD) | (WSEL << ENC_SEL) | (1 << ENC_ODT) | (1 << ENC_DQ_DQS_EN) | (1 << ENC_DQS_TOGGLE);
260  4'h7: rom_r <= (ENC_CMD_WRITE << ENC_CMD_SHIFT) | (1 << ENC_NOP) | (1 << ENC_BUF_RD) | (WSEL << ENC_SEL) | (1 << ENC_ODT) | (1 << ENC_DQ_DQS_EN) | (1 << ENC_DQS_TOGGLE);
261  4'h8: rom_r <= (ENC_CMD_WRITE << ENC_CMD_SHIFT) | (1 << ENC_AUTOPRE) | (1 << ENC_BUF_RD) | (WSEL << ENC_SEL) | (1 << ENC_ODT) | (1 << ENC_DQ_DQS_EN) | (1 << ENC_DQS_TOGGLE);
262 // end loop
263  4'h9: rom_r <= (ENC_CMD_NOP << ENC_CMD_SHIFT) | (1 << ENC_BUF_RD) | (WSEL << ENC_SEL) | (1 << ENC_ODT) | (1 << ENC_DQ_DQS_EN) | (1 << ENC_DQS_TOGGLE);
264  4'ha: rom_r <= (ENC_CMD_WRITE << ENC_CMD_SHIFT) | (1 << ENC_BUF_RD) | (WSEL << ENC_SEL) | (1 << ENC_ODT) | (1 << ENC_DQ_DQS_EN) | (1 << ENC_DQS_TOGGLE);
265  4'hb: rom_r <= (ENC_CMD_NOP << ENC_CMD_SHIFT) | (WSEL << ENC_SEL) | (1 << ENC_ODT) | (1 << ENC_DQ_DQS_EN) | (1 << ENC_DQS_TOGGLE);
266  4'hc: rom_r <= (ENC_CMD_WRITE << ENC_CMD_SHIFT) | (1 << ENC_AUTOPRE) | (1 << ENC_BUF_PGNEXT) | (WSEL << ENC_SEL) | (1 << ENC_ODT) | (1 << ENC_DQ_DQS_EN) | (1 << ENC_DQS_TOGGLE);
267  4'hd: rom_r <= (ENC_CMD_NOP << ENC_CMD_SHIFT) | (3 << ENC_PAUSE_SHIFT) | (WSEL << ENC_SEL) | (1 << ENC_ODT) | (1 << ENC_DQ_DQS_EN) | (1 << ENC_DQS_TOGGLE);
268  4'he: rom_r <= (ENC_CMD_NOP << ENC_CMD_SHIFT) | (3 << ENC_PAUSE_SHIFT);
269  4'hf: rom_r <= (ENC_CMD_NOP << ENC_CMD_SHIFT) | (1 << ENC_PRE_DONE);
270  default:rom_r <= 0;
271  endcase
272  end
273 
274  always @ (posedge clk) begin
275 
276  if (mrst) enc_wr <= 0;
277  else enc_wr <= gen_run; // || gen_run_d; *****
278 
279  if (mrst) enc_done <= 0;
280  else enc_done <= enc_wr && !gen_run; // !gen_run_d; *****
281 
282  if (mrst) enc_cmd <= 0;
283  else if (gen_run) begin
284  if (rom_cmd[0] || (rom_cmd[1] && enable_act)) enc_cmd <= func_encode_cmd ( // encode non-NOP command
285  rom_cmd[1]? // activate
286  row_col_bank[FULL_ADDR_NUMBER-1:COLADDR_NUMBER]: // top combined row,column,bank burst address (excludes 3 CA LSBs), valid/modified @pre_act
287  {{ADDRESS_NUMBER-COLADDR_NUMBER-1{1'b0}},
288  enable_autopre & rom_r[ENC_AUTOPRE], // all writes w/o NOP are first writes, autoprecharge only fro the second ones
290  3'b0}, // [14:0] addr; // 15-bit row/column address
291  rom_cmd[1]?
292  row_col_bank[2:0]:
293  col_bank[2:0], //
294  full_cmd[2:0], // rcw; // RAS/CAS/WE, positive logic
295  rom_r[ENC_ODT], // odt_en; // enable ODT
296  1'b0, // cke; // disable CKE
297  rom_r[ENC_SEL], // sel; // first/second half-cycle, other will be nop (cke+odt applicable to both)
298  rom_r[ENC_DQ_DQS_EN], // dq_en; // enable (not tristate) DQ lines (internal timing sequencer for 0->1 and 1->0)
299  rom_r[ENC_DQ_DQS_EN], // dqs_en; // enable (not tristate) DQS lines (internal timing sequencer for 0->1 and 1->0)
300  rom_r[ENC_DQS_TOGGLE], // dqs_toggle; // enable toggle DQS according to the pattern
301  1'b0, // dci; // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
302  1'b0, // buf_wr; // connect to external buffer (but only if not paused)
303 // rom_r[ENC_BUF_RD] && !cut_buf_rd, // buf_rd; // connect to external buffer (but only if not paused)
304  rom_r[ENC_BUF_RD], // buf_rd; // connect to external buffer (but only if not paused)
305  rom_r[ENC_NOP], // nop; // add NOP after the current command, keep other data
306  rom_r[ENC_BUF_PGNEXT] && !skip_next_page);// buf_rst; // connect to external buffer (but only if not paused)
307  else enc_cmd <= func_encode_skip ( // encode pause
308  {{CMD_PAUSE_BITS-2{1'b0}},rom_skip[1:0]}, // skip; // number of extra cycles to skip (and keep all the other outputs)
309  pre_done, // done // end of sequence ****
310  3'b0, // bank (here OK to be any)
311  rom_r[ENC_ODT], // odt_en; // enable ODT
312  1'b0, // cke; // disable CKE
313  rom_r[ENC_SEL], // sel; // first/second half-cycle, other will be nop (cke+odt applicable to both)
314  rom_r[ENC_DQ_DQS_EN], // dq_en; // enable (not tristate) DQ lines (internal timing sequencer for 0->1 and 1->0)
315  rom_r[ENC_DQ_DQS_EN], // dqs_en; // enable (not tristate) DQS lines (internal timing sequencer for 0->1 and 1->0)
316  rom_r[ENC_DQS_TOGGLE], // dqs_toggle; // enable toggle DQS according to the pattern
317  1'b0, // dci; // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
318  1'b0, // buf_wr; // connect to external buffer (but only if not paused)
319 // rom_r[ENC_BUF_RD] && !cut_buf_rd, // buf_rd; // connect to external buffer (but only if not paused)
320  rom_r[ENC_BUF_RD], // buf_rd; // connect to external buffer (but only if not paused)
321  rom_r[ENC_BUF_PGNEXT] && !skip_next_page);// buf_rst; // connect to external buffer (but only if not paused)
322  end
323  end
325  .WIDTH(COLADDR_NUMBER)
326  ) fifo_2regs_i (
327  .mrst (mrst), // input
328  .clk (clk), // input
329  .din (row_col_bank[COLADDR_NUMBER-1:0]), // input[15:0]
330  .wr(pre_act), // input
331  .rd(pre_write && rom_r[ENC_AUTOPRE]), // input
332  .srst(start_d), // input
333  .dout(col_bank) // output[15:0]
334  );
371 
372  function [31:0] func_encode_cmd;
373  input [14:0] addr; // 15-bit row/column address
374  input [2:0] bank; // bank (here OK to be any)
375  input [2:0] rcw; // RAS/CAS/WE, positive logic
376  input odt_en; // enable ODT
377  input cke; // disable CKE
378  input sel; // first/second half-cycle, other will be nop (cke+odt applicable to both)
379  input dq_en; // enable (not tristate) DQ lines (internal timing sequencer for 0->1 and 1->0)
380  input dqs_en; // enable (not tristate) DQS lines (internal timing sequencer for 0->1 and 1->0)
381  input dqs_toggle; // enable toggle DQS according to the pattern
382  input dci; // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
383  input buf_wr; // connect to external buffer (but only if not paused)
384  input buf_rd; // connect to external buffer (but only if not paused)
385  input nop; // add NOP after the current command, keep other data
386  input buf_rst; // connect to external buffer (but only if not paused)
387  begin
388  func_encode_cmd={
389  addr[14:0], // 15-bit row/column address
390  bank [2:0], // bank
391  rcw[2:0], // RAS/CAS/WE
392  odt_en, // enable ODT
393  cke, // may be optimized (removed from here)?
394  sel, // first/second half-cycle, other will be nop (cke+odt applicable to both)
395  dq_en, // enable (not tristate) DQ lines (internal timing sequencer for 0->1 and 1->0)
396  dqs_en, // enable (not tristate) DQS lines (internal timing sequencer for 0->1 and 1->0)
397  dqs_toggle, // enable toggle DQS according to the pattern
398  dci, // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
399  buf_wr, // phy_buf_wr, // connect to external buffer (but only if not paused)
400  buf_rd, // phy_buf_rd, // connect to external buffer (but only if not paused)
401  nop, // add NOP after the current command, keep other data
402  buf_rst // Reserved for future use
403  };
404  end
405  endfunction
406 
407  function [31:0] func_encode_skip;
408  input [CMD_PAUSE_BITS-1:0] skip; // number of extra cycles to skip (and keep all the other outputs)
409  input done; // end of sequence
410  input [2:0] bank; // bank (here OK to be any)
411  input odt_en; // enable ODT
412  input cke; // disable CKE
413  input sel; // first/second half-cycle, other will be nop (cke+odt applicable to both)
414  input dq_en; // enable (not tristate) DQ lines (internal timing sequencer for 0->1 and 1->0)
415  input dqs_en; // enable (not tristate) DQS lines (internal timing sequencer for 0->1 and 1->0)
416  input dqs_toggle; // enable toggle DQS according to the pattern
417  input dci; // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
418  input buf_wr; // connect to external buffer (but only if not paused)
419  input buf_rd; // connect to external buffer (but only if not paused)
420  input buf_rst; // connect to external buffer (but only if not paused)
421  begin
422  func_encode_skip= func_encode_cmd (
423  {{14-CMD_DONE_BIT{1'b0}}, done, skip[CMD_PAUSE_BITS-1:0]}, // 15-bit row/column address
424  bank[2:0], // bank (here OK to be any)
425  3'b0, // RAS/CAS/WE, positive logic
426  odt_en, // enable ODT
427  cke, // disable CKE
428  sel, // first/second half-cycle, other will be nop (cke+odt applicable to both)
429  dq_en, // enable (not tristate) DQ lines (internal timing sequencer for 0->1 and 1->0)
430  dqs_en, // enable (not tristate) DQS lines (internal timing sequencer for 0->1 and 1->0)
431  dqs_toggle, // enable toggle DQS according to the pattern
432  dci, // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
433  buf_wr, // connect to external buffer (but only if not paused)
434  buf_rd, // connect to external buffer (but only if not paused)
435  1'b0, // nop
436  buf_rst);
437  end
438  endfunction
439 
440 
441 endmodule
442 
4228colreg[COLADDR_NUMBER-4:0]
[WIDTH-1:0] 10385din
Definition: fifo_2regs.v:47
[ADDRESS_NUMBER-1:0] 4194start_row
4236gen_addrreg[ROM_DEPTH-1:0]
4205FULL_ADDR_NUMBERADDRESS_NUMBER+COLADDR_NUMBER
4251row_col_bankreg[FULL_ADDR_NUMBER-1:0]
4227rowreg[ADDRESS_NUMBER-1:0]
4232rowcol_increg[FRAME_WIDTH_BITS:0]
[COLADDR_NUMBER-4:0] 4195start_col
4242top_rcreg[FULL_ADDR_NUMBER-4:0]
4258row_col_bank_next_wwire[FULL_ADDR_NUMBER-1:0]
[WIDTH-1:0] 10389dout
Definition: fifo_2regs.v:51
[FRAME_WIDTH_BITS:0] 4196rowcol_inc_in
4252col_bankwire[COLADDR_NUMBER-1:0]
4256next_rowcol_wwire[ADDRESS_NUMBER+COLADDR_NUMBER-4:0]
4237rom_rreg[ROM_WIDTH-1:0]