x393  1.0
FPGAcodeforElphelNC393camera
cmd_encod_linear_wr.v
Go to the documentation of this file.
1 
40 `timescale 1ns/1ps
41 
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 CMD_PAUSE_BITS= 10,
47  parameter CMD_DONE_BIT= 10, // VDT BUG: CMD_DONE_BIT is used in a function call parameter!
48  parameter WSEL= 1'b0
49 ) (
50  input mrst,
51  input clk,
52 // programming interface
53  input [2:0] bank_in, // bank address
54  input [ADDRESS_NUMBER-1:0] row_in, // memory row
55  input [COLADDR_NUMBER-4:0] start_col, // start memory column (3 LSBs should be 0?)
56  input [NUM_XFER_BITS-1:0] num128_in, // number of 128-bit words to transfer (8*16 bits) - full burst of 8 (0 - full 64)
57  input skip_next_page_in, // do not reset external buffer (continue)
58  input start, // start generating commands
59  output reg [31:0] enc_cmd, // encoded command SuppressThisWarning VivadoSynthesis [Synth 8-3332] Sequential element cmd_encod_linear_wr.enc_cmd_reg[9,6,4:3] is unused and will be removed from module cmd_encod_linear_wr.
60  output reg enc_wr, // write encoded command
61  output reg enc_done // encoding finished
62 );
63  localparam ROM_WIDTH=12;
64  localparam ROM_DEPTH=4;
65 
66  localparam ENC_NOP= 0;
67  localparam ENC_BUF_RD= 1;
68  localparam ENC_DQS_TOGGLE= 2;
69  localparam ENC_DQ_DQS_EN= 3;
70  localparam ENC_SEL= 4;
71  localparam ENC_ODT= 5;
72  localparam ENC_CMD_SHIFT= 6; // [7:6] - command: 0 -= NOP, 1 - WRITE, 2 - PRECHARGE, 3 - ACTIVATE
73  localparam ENC_PAUSE_SHIFT= 8; // [9:8] - 2- bit pause (for NOP commandes)
74  localparam ENC_PRE_DONE= 10;
75  localparam ENC_BUF_PGNEXT= 11;
76 
77  localparam ENC_CMD_NOP= 0; // 2-bit locally encoded commands
78  localparam ENC_CMD_WRITE= 1;
79  localparam ENC_CMD_PRECHARGE=2;
80  localparam ENC_CMD_ACTIVATE= 3;
81 
82 // read buffer is always at addr 0 and 1,
83  localparam REPEAT_ADDR= 5; // loop here (2-cycle command write)
84  localparam PRELAST_WRITE_ADDR='h6; // jump here (from 4) if only 2 writes are needed (are fall from 4 wnen 1 write is left
85  localparam LAST_WRITE_ADDR= 'h8; // jump here (from 4) if only 2 writes are needed (are fall from 4 wnen 1 write is left
86  localparam NO_WRITE_ADDR= 'ha; // jump here (from 4) if only 1 write is needed
87  localparam WRITE_ADDR1= 3;
88  localparam WRITE_ADDR2= 5;
89 // localparam WRITE_ADDR3= 6;
90 // localparam WRITE_ADDR4= 8;
91  localparam CUT_SINGLE_ADDR= 2; // cut read buffer after this address if only one burst is needed
92  localparam CUT_DUAL_ADDR= 4; // cut read buffer after this address if two bursts are needed
93 
94 
95 
96 
97  localparam CMD_NOP= 0; // 3-bit normal memory RCW commands (positive logic)
98  localparam CMD_WRITE= 3;
99  localparam CMD_PRECHARGE=5;
100  localparam CMD_ACTIVATE= 4;
101 
102  reg [ADDRESS_NUMBER-1:0] row; // memory row
103  reg [COLADDR_NUMBER-4:0] col; // start memory column (3 LSBs should be 0?) // VDT BUG: col is used as a function call parameter!
104  reg [2:0] bank; // memory bank;
105  reg [NUM_XFER_BITS:0] num128; // number of 128-bit words to transfer
107 
108  reg gen_run;
109 // reg gen_run_d;
110  reg [ROM_DEPTH-1:0] gen_addr; // will overrun as stop comes from ROM
111 
112  reg [ROM_WIDTH-1:0] rom_r; // SuppressThisWarning VivadoSynthesis: [Synth 8-3332] Sequential element cmd_encod_linear_wr.rom_r_reg[8] is unused and will be removed from module cmd_encod_linear_wr.
113  wire pre_done;
114  wire [1:0] rom_cmd;
115  wire [1:0] rom_skip;
116  wire [2:0] full_cmd;
117 // reg done;
118  reg start_d;
121  reg single_write; // only one burst has to be written
122  reg dual_write; // Two bursts have to be written
123  reg few_write; //write 1,2 or 3 bursts
124  wire write_addr_w; // gen_addr that generates write commands
125  reg [ROM_DEPTH-1:0] jump_gen_addr; // will overrun as stop comes from ROM SuppressThisWarning VivadoSynthesis: [Synth 8-3332] Sequential element cmd_encod_linear_wr.jump_gen_addr_reg[0] is unused and will be removed from module cmd_encod_linear_wr.
126 
127  assign pre_done=rom_r[ENC_PRE_DONE] && gen_run;
128  assign rom_cmd= rom_r[ENC_CMD_SHIFT+:2];
129  assign rom_skip= rom_r[ENC_PAUSE_SHIFT+:2];
131 // prepare jump address? and bufrd during 2,3
132  assign write_addr_w= (gen_addr==WRITE_ADDR1) || (gen_addr==WRITE_ADDR2); // do not need to update after WRITE_ADDR2
133 // make num128 7-bits to accommodate 64!
134  always @ (posedge clk) begin
135  start_d <= start;
137  end
138  always @ (posedge clk) begin
139 
140  if (mrst) gen_run <= 0;
141  else if (start) gen_run<= 1;
142  else if (pre_done) gen_run<= 0;
143 
144  if (mrst) gen_addr <= 0;
145  else if (!start && !gen_run) gen_addr <= 0;
146  else if ((gen_addr==(REPEAT_ADDR-1)) && few_write) gen_addr <= jump_gen_addr;
147  else if ((gen_addr !=REPEAT_ADDR) || (num128[NUM_XFER_BITS:2]==0)) gen_addr <= gen_addr+1; // not in a loop
148 
149 //counting loops
150  if (mrst) num128 <= 0;
151  else if (start) num128 <= {(num128_in==0)?1'b1:1'b0,num128_in};
152  else if (!gen_run) num128 <= 0; //
153  else if (write_addr_w) num128 <= num128 -1;
154 
155  if (mrst) single_write <= 0;
156  else if (start_d) single_write <= (num128[NUM_XFER_BITS:1]==0); // could not be 0
157 
158  if (mrst) dual_write <= 0;
159  else if (start_d) dual_write <= (num128==2);
160 
161  if (mrst) few_write <= 0;
162  else if (start_d) few_write <=(num128[NUM_XFER_BITS:2]==0); // (0,)1,2 or3
163 
164  if (mrst) jump_gen_addr <= 0;
166 
167  end
168 
169  always @ (posedge clk) if (start) begin
170  row<=row_in;
171  bank <= bank_in;
173  end
174 
175  always @ (posedge clk) begin
176  if (start) col <= start_col;
177  else if (rom_cmd==ENC_CMD_WRITE) col <= col+1;
178  end
179 
180  // ROM-based (registered output) encoded sequence
181  // TODO: Remove last ENC_BUF_RD
182  always @ (posedge clk) begin
183  if (mrst) rom_r <= 0;
184  else case (gen_addr)
185  4'h0: rom_r <= (ENC_CMD_ACTIVATE << ENC_CMD_SHIFT) | (1 << ENC_BUF_RD);// | (1 << ENC_NOP);
186  4'h1: rom_r <= (ENC_CMD_NOP << ENC_CMD_SHIFT) | (1 << ENC_BUF_RD);
187  4'h2: rom_r <= (ENC_CMD_NOP << ENC_CMD_SHIFT) | (1 << ENC_BUF_RD);
188  4'h3: rom_r <= (ENC_CMD_WRITE << ENC_CMD_SHIFT) | (1 << ENC_BUF_RD) | (WSEL << ENC_SEL) | (1 << ENC_ODT); // single cycle
189 // 4'h4: rom_r <= (ENC_CMD_NOP << ENC_CMD_SHIFT) | (1 << ENC_BUF_RD) | (1 << ENC_DQ_DQS_EN) | (1 << ENC_ODT); // single cycle
190  4'h4: rom_r <= (ENC_CMD_NOP << ENC_CMD_SHIFT) | (1 << ENC_BUF_RD) | (1 << ENC_ODT); // single cycle
191 // next may loop
192  4'h5: rom_r <= (ENC_CMD_WRITE << ENC_CMD_SHIFT) | (1 << ENC_NOP) | (1 << ENC_BUF_RD) | (1 << ENC_DQS_TOGGLE) | (1 << ENC_DQ_DQS_EN) | (WSEL << ENC_SEL) | (1 << ENC_ODT); // dual cycle
193  4'h6: rom_r <= (ENC_CMD_WRITE << ENC_CMD_SHIFT) | (1 << ENC_BUF_RD) | (1 << ENC_DQS_TOGGLE) | (1 << ENC_DQ_DQS_EN) | (WSEL << ENC_SEL) | (1 << ENC_ODT); // dual cycle
194  4'h7: rom_r <= (ENC_CMD_NOP << ENC_CMD_SHIFT) | (1 << ENC_DQS_TOGGLE) | (1 << ENC_DQ_DQS_EN) | (WSEL << ENC_SEL) | (1 << ENC_ODT);
195  4'h8: rom_r <= (ENC_CMD_WRITE << ENC_CMD_SHIFT) | (1 << ENC_DQS_TOGGLE) | (1 << ENC_DQ_DQS_EN) | (WSEL << ENC_SEL) | (1 << ENC_ODT); // dual cycle
196  4'h9: rom_r <= (ENC_CMD_NOP << ENC_CMD_SHIFT) | (1 << ENC_DQS_TOGGLE) | (1 << ENC_DQ_DQS_EN) | (1 << ENC_ODT);
197  4'ha: rom_r <= (ENC_CMD_NOP << ENC_CMD_SHIFT) | (2 << ENC_PAUSE_SHIFT) | (1 << ENC_DQS_TOGGLE) | (1 << ENC_DQ_DQS_EN) | (1 << ENC_ODT);
198  4'hb: rom_r <= (ENC_CMD_NOP << ENC_CMD_SHIFT) | (2 << ENC_PAUSE_SHIFT);
199  4'hc: rom_r <= (ENC_CMD_PRECHARGE << ENC_CMD_SHIFT) | (1 << ENC_BUF_PGNEXT);
200  4'hd: rom_r <= (ENC_CMD_NOP << ENC_CMD_SHIFT) | (2 << ENC_PAUSE_SHIFT);
201  4'he: rom_r <= (ENC_CMD_NOP << ENC_CMD_SHIFT) | (1 << ENC_PRE_DONE);
202  default:rom_r <= 0;
203  endcase
204  end
205  always @ (posedge clk) begin
206 
207  if (mrst) enc_wr <= 0;
208  else enc_wr <= gen_run; // || gen_run_d;
209 
210  if (mrst) enc_done <= 0;
211 // else enc_done <= enc_wr || !gen_run_d;
212  else enc_done <= enc_wr && !gen_run; // !gen_run_d;
213 
214  if (mrst) enc_cmd <= 0;
215  else if (gen_run) begin
216  if (rom_cmd==0) enc_cmd <= func_encode_skip ( // encode pause
217  {{CMD_PAUSE_BITS-2{1'b0}},rom_skip[1:0]}, // skip; // number of extra cycles to skip (and keep all the other outputs)
218  pre_done, // done, // end of sequence
219  bank[2:0], // bank (here OK to be any)
220  rom_r[ENC_ODT], // odt_en; // enable ODT
221  1'b0, // cke; // disable CKE
222  rom_r[ENC_SEL], // sel; // first/second half-cycle, other will be nop (cke+odt applicable to both)
223  rom_r[ENC_DQ_DQS_EN], // dq_en; // enable (not tristate) DQ lines (internal timing sequencer for 0->1 and 1->0)
224  rom_r[ENC_DQ_DQS_EN], // dqs_en; // enable (not tristate) DQS lines (internal timing sequencer for 0->1 and 1->0)
225  rom_r[ENC_DQS_TOGGLE], // dqs_toggle; // enable toggle DQS according to the pattern
226  1'b0, // dci; // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
227  1'b0, // buf_wr; // connect to external buffer (but only if not paused)
228  rom_r[ENC_BUF_RD] && !cut_buf_rd, //buf_rd;// connect to external buffer (but only if not paused)
229  rom_r[ENC_BUF_PGNEXT] && !skip_next_page); // buf_rst; // connect to external buffer (but only if not paused)
230  else enc_cmd <= func_encode_cmd ( // encode non-NOP command
231  rom_cmd[1]?
232  row:
233  {{ADDRESS_NUMBER-COLADDR_NUMBER{1'b0}},col[COLADDR_NUMBER-4:0],3'b0}, // [14:0] addr; // 15-bit row/column address
234  bank[2:0], // bank (here OK to be any)
235  full_cmd[2:0], // rcw; // RAS/CAS/WE, positive logic
236  rom_r[ENC_ODT], // odt_en; // enable ODT
237  1'b0, // cke; // disable CKE
238  rom_r[ENC_SEL], // sel; // first/second half-cycle, other will be nop (cke+odt applicable to both)
239  rom_r[ENC_DQ_DQS_EN], // dq_en; // enable (not tristate) DQ lines (internal timing sequencer for 0->1 and 1->0)
240  rom_r[ENC_DQ_DQS_EN], // dqs_en; // enable (not tristate) DQS lines (internal timing sequencer for 0->1 and 1->0)
241  rom_r[ENC_DQS_TOGGLE], // dqs_toggle; // enable toggle DQS according to the pattern
242  1'b0, // dci; // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
243  1'b0, // buf_wr; // connect to external buffer (but only if not paused)
244  rom_r[ENC_BUF_RD] && !cut_buf_rd, //buf_rd;// connect to external buffer (but only if not paused)
245  rom_r[ENC_NOP], // nop; // add NOP after the current command, keep other data
246  rom_r[ENC_BUF_PGNEXT] && !skip_next_page); // buf_rst; // connect to external buffer (but only if not paused)
247  end
248  end
249 
250 
251 // move to include?/*!
252  * @file x393_mcontr_encode_cmd.vh
253  * @date 2015-02-09
254  * @author Andrey Filippov
255  *
256  * @brief Functions used to encode memory controller sequences
257  *
258  * @copyright Copyright (c) 2015 Elphel, Inc.
259  *
260  * <b>License:</b>
261  *
262  * x393_mcontr_encode_cmd.vh is free software; you can redistribute it and/or modify
263  * it under the terms of the GNU General Public License as published by
264  * the Free Software Foundation, either version 3 of the License, or
265  * (at your option) any later version.
266  *
267  * x393_mcontr_encode_cmd.vh is distributed in the hope that it will be useful,
268  * but WITHOUT ANY WARRANTY; without even the implied warranty of
269  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
270  * GNU General Public License for more details.
271  *
272  * You should have received a copy of the GNU General Public License
273  * along with this program. If not, see <http://www.gnu.org/licenses/> .
274  *
275  * Additional permission under GNU GPL version 3 section 7:
276  * If you modify this Program, or any covered work, by linking or combining it
277  * with independent modules provided by the FPGA vendor only (this permission
278  * does not extend to any 3-rd party modules, "soft cores" or macros) under
279  * different license terms solely for the purpose of generating binary "bitstream"
280  * files and/or simulating the code, the copyright holders of this Program give
281  * you the right to distribute the covered work without those independent modules
282  * as long as the source code for them is available from the FPGA vendor free of
283  * charge, and there is no dependence on any encrypted modules for simulating of
284  * the combined code. This permission applies to you if the distributed code
285  * contains all the components and scripts required to completely simulate it
286  * with at least one of the Free Software programs.
287  */
288 
289  function [31:0] func_encode_cmd;
290  input [14:0] addr; // 15-bit row/column address
291  input [2:0] bank; // bank (here OK to be any)
292  input [2:0] rcw; // RAS/CAS/WE, positive logic
293  input odt_en; // enable ODT
294  input cke; // disable CKE
295  input sel; // first/second half-cycle, other will be nop (cke+odt applicable to both)
296  input dq_en; // enable (not tristate) DQ lines (internal timing sequencer for 0->1 and 1->0)
297  input dqs_en; // enable (not tristate) DQS lines (internal timing sequencer for 0->1 and 1->0)
298  input dqs_toggle; // enable toggle DQS according to the pattern
299  input dci; // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
300  input buf_wr; // connect to external buffer (but only if not paused)
301  input buf_rd; // connect to external buffer (but only if not paused)
302  input nop; // add NOP after the current command, keep other data
303  input buf_rst; // connect to external buffer (but only if not paused)
304  begin
305  func_encode_cmd={
306  addr[14:0], // 15-bit row/column address
307  bank [2:0], // bank
308  rcw[2:0], // RAS/CAS/WE
309  odt_en, // enable ODT
310  cke, // may be optimized (removed from here)?
311  sel, // first/second half-cycle, other will be nop (cke+odt applicable to both)
312  dq_en, // enable (not tristate) DQ lines (internal timing sequencer for 0->1 and 1->0)
313  dqs_en, // enable (not tristate) DQS lines (internal timing sequencer for 0->1 and 1->0)
314  dqs_toggle, // enable toggle DQS according to the pattern
315  dci, // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
316  buf_wr, // phy_buf_wr, // connect to external buffer (but only if not paused)
317  buf_rd, // phy_buf_rd, // connect to external buffer (but only if not paused)
318  nop, // add NOP after the current command, keep other data
319  buf_rst // Reserved for future use
320  };
321  end
322  endfunction
323 
324  function [31:0] func_encode_skip;
325  input [CMD_PAUSE_BITS-1:0] skip; // number of extra cycles to skip (and keep all the other outputs)
326  input done; // end of sequence
327  input [2:0] bank; // bank (here OK to be any)
328  input odt_en; // enable ODT
329  input cke; // disable CKE
330  input sel; // first/second half-cycle, other will be nop (cke+odt applicable to both)
331  input dq_en; // enable (not tristate) DQ lines (internal timing sequencer for 0->1 and 1->0)
332  input dqs_en; // enable (not tristate) DQS lines (internal timing sequencer for 0->1 and 1->0)
333  input dqs_toggle; // enable toggle DQS according to the pattern
334  input dci; // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
335  input buf_wr; // connect to external buffer (but only if not paused)
336  input buf_rd; // connect to external buffer (but only if not paused)
337  input buf_rst; // connect to external buffer (but only if not paused)
338  begin
339  func_encode_skip= func_encode_cmd (
340  {{14-CMD_DONE_BIT{1'b0}}, done, skip[CMD_PAUSE_BITS-1:0]}, // 15-bit row/column address
341  bank[2:0], // bank (here OK to be any)
342  3'b0, // RAS/CAS/WE, positive logic
343  odt_en, // enable ODT
344  cke, // disable CKE
345  sel, // first/second half-cycle, other will be nop (cke+odt applicable to both)
346  dq_en, // enable (not tristate) DQ lines (internal timing sequencer for 0->1 and 1->0)
347  dqs_en, // enable (not tristate) DQS lines (internal timing sequencer for 0->1 and 1->0)
348  dqs_toggle, // enable toggle DQS according to the pattern
349  dci, // DCI disable, both DQ and DQS lines (internal logic and timing sequencer for 0->1 and 1->0)
350  buf_wr, // connect to external buffer (but only if not paused)
351  buf_rd, // connect to external buffer (but only if not paused)
352  1'b0, // nop
353  buf_rst);
354  end
355  endfunction
356 
357 
358 endmodule
359 
4065colreg[COLADDR_NUMBER-4:0]
[NUM_XFER_BITS-1:0] 4030num128_in
[COLADDR_NUMBER-4:0] 4029start_col
4071rom_rreg[ROM_WIDTH-1:0]
4067num128reg[NUM_XFER_BITS:0]
4070gen_addrreg[ROM_DEPTH-1:0]
4064rowreg[ADDRESS_NUMBER-1:0]
4083jump_gen_addrreg[ROM_DEPTH-1:0]
[ADDRESS_NUMBER-1:0] 4028row_in