x393  1.0
FPGAcodeforElphelNC393camera
x393_tasks_pio_sequences.vh
Go to the documentation of this file.
1 /*!
2  * @file x393_tasks_pio_sequences.vh
3  * @date 2015-02-07
4  * @author Andrey Filippov
5  *
6  * @brief Simulation tasks for programming memory transaction
7  * sequences (controlles by PS)
8  *
9  * @copyright Copyright (c) 2015 Elphel, Inc.
10  *
11  * <b>License:</b>
12  *
13  * x393_tasks_pio_sequences.vh is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation, either version 3 of the License, or
16  * (at your option) any later version.
17  *
18  * x393_tasks_pio_sequences.vh is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program. If not, see <http://www.gnu.org/licenses/> .
25  *
26  * Additional permission under GNU GPL version 3 section 7:
27  * If you modify this Program, or any covered work, by linking or combining it
28  * with independent modules provided by the FPGA vendor only (this permission
29  * does not extend to any 3-rd party modules, "soft cores" or macros) under
30  * different license terms solely for the purpose of generating binary "bitstream"
31  * files and/or simulating the code, the copyright holders of this Program give
32  * you the right to distribute the covered work without those independent modules
33  * as long as the source code for them is available from the FPGA vendor free of
34  * charge, and there is no dependence on any encrypted modules for simulating of
35  * the combined code. This permission applies to you if the distributed code
36  * contains all the components and scripts required to completely simulate it
37  * with at least one of the Free Software programs.
38  */
39 task enable_reset_ps_pio; // control reset and enable of the PS PIO channel;
40  input en;
41  input rst;
42  begin
43  write_contol_register(MCNTRL_PS_ADDR + MCNTRL_PS_EN_RST, {30'b0,en,~rst});
44  end
45 endtask
46 
47 task set_read_block;
48  input [ 2:0] ba;
49  input [14:0] ra;
50  input [ 9:0] ca;
51  input sel;
52  reg [29:0] cmd_addr;
53  reg [31:0] data;
54  integer i;
55  begin
56  cmd_addr <= MCONTR_CMD_WR_ADDR + READ_BLOCK_OFFSET;
57 // activate
58  // addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
59  data <= func_encode_cmd( ra[14:0], ba[2:0], 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
60  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
61 // see if pause is needed . See when buffer read should be started - maybe before WR command
62  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
63  data <= func_encode_skip( 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
64  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
65 // first read
66 // read
67  // addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
68  data <= func_encode_cmd( {5'b0,ca[9:0]}, ba[2:0], 2, 0, 0, sel, 0, 0, 0, 1, 1, 0, 0, 0);
69  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
70 // nop
71  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
72  data <= func_encode_skip( 0, 0, ba[2:0], 0, 0, sel, 0, 0, 0, 1, 1, 0, 0);
73  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
74 //repeat remaining reads
75  for (i=1;i<64;i=i+1) begin
76 // read
77 // addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
78  data <= func_encode_cmd({5'b0,ca[9:0]}+(i<<3),ba[2:0],2, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0);
79  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
80  end
81 // nop - all 3 below are the same? - just repeat?
82  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
83  data <= func_encode_skip( 0, 0, ba[2:0], 0, 0, sel, 0, 0, 0, 1, 0, 0, 0);
84  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
85 // nop
86  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
87  data <= func_encode_skip( 0, 0, ba[2:0], 0, 0, sel, 0, 0, 0, 1, 0, 0, 0);
88  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
89 // nop
90  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
91  data <= func_encode_skip( 0, 0, ba[2:0], 0, 0, sel, 0, 0, 0, 1, 0, 0, 0);
92  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
93 // tRTP = 4*tCK is already satisfied, no skip here
94 // precharge, end of a page (B_RST)
95  // addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
96  data <= func_encode_cmd( ra[14:0], ba[2:0], 5, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1);
97  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
98  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
99  data <= func_encode_skip( 2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0);
100  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
101 // Turn off DCI, set DONE
102  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
103  data <= func_encode_skip( 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
104  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
105  end
106 endtask
107 
108 task set_write_block;
109  input[2:0]ba;
110  input[14:0]ra;
111  input[9:0]ca;
112  input sel;
113  reg[29:0] cmd_addr;
114  reg[31:0] data;
115  integer i;
116  begin
117  cmd_addr <= MCONTR_CMD_WR_ADDR + WRITE_BLOCK_OFFSET;
118 // activate
119  // addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
120  data <= func_encode_cmd( ra[14:0], ba[2:0], 4, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0);
121  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
122 // see if pause is needed . See when buffer read should be started - maybe before WR command
123  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
124  data <= func_encode_skip( 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0); // tRCD - 2 read bufs
125  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
126 // first write, 3 rd_buf
127 // write
128  // addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
129  data <= func_encode_cmd( {5'b0,ca[9:0]}, ba[2:0], 3, 1, 0, sel, 0, 0, 0, 0, 0, 1, 0, 0); // B_RD moved 1 cycle earlier
130  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
131 // nop 4-th rd_buf
132  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
133 // data <= func_encode_skip( 0, 0, ba[2:0], 1, 0, 1, 1, 1, 0, 1, 0, 1, 0);
134 // data <= func_encode_skip( 0, 0, ba[2:0], 1, 0, 0, 1, 1, 0, 0, 0, 1, 0);
135  data <= func_encode_skip( 0, 0, ba[2:0], 1, 0, 0, 0, 0, 0, 0, 0, 1, 0);
136  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
137 //repeat remaining writes
138  for (i = 1; i < 62; i = i + 1) begin
139 // write
140  // add bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
141  data <= func_encode_cmd( {5'b0,ca[9:0]}+(i<<3),ba[2:0],3, 1, 0, sel, 1, 1, 1, 0, 0, 1, 1, 0);
142  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
143  end
144  // add bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
145  data <= func_encode_cmd( {5'b0,ca[9:0]}+(62<<3),ba[2:0], 3, 1, 0, sel, 1, 1, 1, 0, 0, 1, 0, 0); // write w/o nop
146  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
147 // nop
148  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
149  data <= func_encode_skip( 0, 0, ba[2:0], 1, 0, sel, 1, 1, 1, 0, 0, 0, 0); // nop with buffer read off
150  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
151 
152 // One last write pair w/o buffer
153  // add bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
154  data <= func_encode_cmd( {5'b0,ca[9:0]}+(63<<3),ba[2:0], 3, 1, 0, sel, 1, 1, 1, 0, 0, 0, 1, 0); // write with nop
155  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
156 
157 // nop
158  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
159  data <= func_encode_skip( 0, 0, ba[2:0], 1, 0, 0, 1, 1, 1, 0, 0, 0, 0);
160  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
161 // nop
162  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
163  data <= func_encode_skip( 0, 0, ba[2:0], 1, 0, 0, 1, 1, 1, 0, 0, 0, 1); // removed B_RD 1 cycle earlier
164  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
165 // nop
166  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
167  data <= func_encode_skip( 0, 0, ba[2:0], 1, 0, 0, 1, 1, 1, 0, 0, 0, 0);
168  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
169 // ODT off, it has latency
170  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
171  data <= func_encode_skip( 2, 0, ba[2:0], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
172  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
173 // precharge, ODT off
174  // addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
175  data <= func_encode_cmd( ra[14:0], ba[2:0], 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
176  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
177  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
178  data <= func_encode_skip( 2, 0, ba[2:0], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
179  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
180 // Finalize, set DONE
181  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
182  data <= func_encode_skip( 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
183  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
184  end
185 endtask
186 
187 
188  // Set MR3, read nrep*8 words, save to buffer (port0). No ACTIVATE/PRECHARGE are needed/allowed
189 task set_read_pattern;
190  input integer nrep;
191 // input [ 2:0] ba;
192 // input [14:0] ra;
193 // input [ 9:0] ca;
194  reg[29:0] cmd_addr;
195  reg[31:0] data;
196  reg[17:0] mr3_norm;
197  reg[17:0] mr3_patt;
198  integer i;
199  begin
200  cmd_addr <= MCONTR_CMD_WR_ADDR + READ_PATTERN_OFFSET;
201 
202  mr3_norm <= ddr3_mr3(
203  1'h0, // mpr; // MPR mode: 0 - normal, 1 - dataflow from MPR
204  2'h0); // [1:0] mpr_rf; // MPR read function: 2'b00: predefined pattern 0101...
205  mr3_patt <= ddr3_mr3(
206  1'h1, // mpr; // MPR mode: 0 - normal, 1 - dataflow from MPR
207  2'h0); // [1:0] mpr_rf; // MPR read function: 2'b00: predefined pattern 0101...
208  @(posedge CLK);
209 // Set pattern mode
210  // addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
211  data <= func_encode_cmd(mr3_patt[14:0], mr3_patt[17:15], 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
212  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
213  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
214  data <= func_encode_skip( 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); // tMOD
215  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
216 // first read
217 // read
218  // addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
219  data <= func_encode_cmd( 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0);
220  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
221 // nop (combine with previous?)
222  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
223  data <= func_encode_skip( 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0);
224  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
225 //repeat remaining reads
226  for (i = 1; i < nrep; i = i + 1) begin
227  // addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
228  data <= func_encode_cmd( 0, 0, 2, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0);
229  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
230  end
231 // nop - all 3 below are the same? - just repeat?
232  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
233  data <= func_encode_skip( 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0); // was BUF WR
234  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
235 // nop
236  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
237  data <= func_encode_skip( 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0);
238  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
239 // nop
240  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
241  data <= func_encode_skip( 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0);
242  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
243 // nop, no write buffer - next page
244  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
245  data <= func_encode_skip( 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1);
246  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
247  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
248  data <= func_encode_skip( 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0);
249  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
250 // Turn off read pattern mode
251  // addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
252  data <= func_encode_cmd(mr3_norm[14:0], mr3_norm[17:15], 7, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0);
253  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
254 // tMOD (keep DCI enabled)
255  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
256  data <= func_encode_skip( 5, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0);
257  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
258 // Turn off DCI
259  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
260  data <= func_encode_skip( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
261  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
262 // Finalize (set DONE)
263  data <= func_encode_skip( 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
264  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
265  end
266 endtask
267 
268 
269 
270 task set_write_lev;
271  input[CMD_PAUSE_BITS-1:0]nrep;
272  reg[17:0] mr1_norm;
273  reg[17:0] mr1_wlev;
274  reg[29:0] cmd_addr;
275  reg[31:0] data;
276  reg[CMD_PAUSE_BITS-1:0] dqs_low_rpt;
277  reg[CMD_PAUSE_BITS-1:0] nrep_minus_1;
278  begin
279  dqs_low_rpt <= 8;
280  nrep_minus_1 <= nrep - 1;
281  mr1_norm <= ddr3_mr1(
282  1'h0, // qoff; // output enable: 0 - DQ, DQS operate in normal mode, 1 - DQ, DQS are disabled
283  1'h0, // tdqs; // termination data strobe (for x8 devices) 0 - disabled, 1 - enabled
284  3'h2, // [2:0] rtt; // on-die termination resistance: // 3'b010 - RZQ/2 (120 Ohm)
285  1'h0, // wlev; // write leveling
286  2'h0, // ods; // output drive strength: // 2'b00 - RZQ/6 - 40 Ohm
287  2'h0, // [1:0] al; // additive latency: 2'b00 - disabled (AL=0)
288  1'b0); // dll; // 0 - DLL enabled (normal), 1 - DLL disabled
289  mr1_wlev <= ddr3_mr1(
290  1'h0, // qoff; // output enable: 0 - DQ, DQS operate in normal mode, 1 - DQ, DQS are disabled
291  1'h0, // tdqs; // termination data strobe (for x8 devices) 0 - disabled, 1 - enabled
292  3'h2, // [2:0] rtt; // on-die termination resistance: // 3'b010 - RZQ/2 (120 Ohm)
293  1'h1, // wlev; // write leveling
294  2'h0, // ods; // output drive strength: // 2'b00 - RZQ/6 - 40 Ohm
295  2'h0, // [1:0] al; // additive latency: 2'b00 - disabled (AL=0)
296  1'b0); // dll; // 0 - DLL enabled (normal), 1 - DLL disabled
297  cmd_addr <= MCONTR_CMD_WR_ADDR + WRITELEV_OFFSET;
298 // Enter write leveling mode
299  @(posedge CLK)
300  // addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
301  data <= func_encode_cmd(mr1_wlev[14:0], mr1_wlev[17:15], 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
302  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
303  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
304  data <= func_encode_skip( 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); // tWLDQSEN=25tCK
305  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
306 // enable DQS output, keep it low (15 more tCK for the total of 40 tCK
307  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
308  data <= func_encode_skip(dqs_low_rpt, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0);
309  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
310 // Toggle DQS as needed for write leveling, write to buffer
311  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
312  data <= func_encode_skip(nrep_minus_1,0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0);
313  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
314 // continue toggling (5 times), but disable writing to buffer (used same wbuf latency as for read)
315  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
316  data <= func_encode_skip( 4, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0);
317  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
318  // Keep DCI (but not ODT) active ODT should be off befor MRS
319  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
320  data <= func_encode_skip( 2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0);
321  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
322  // exit write leveling mode, ODT off, DCI off
323  // addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
324  data <= func_encode_cmd(mr1_norm[14:0], mr1_norm[17:15], 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
325  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
326  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
327  data <= func_encode_skip( 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); // tMOD
328  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
329  // Finalize. See if DONE can be combined with B_RST, if not - insert earlier
330  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
331  data <= func_encode_skip( 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1); // can DONE be combined with B_RST?
332  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
333  end
334 endtask
335 
336 task set_refresh;
337  input[9:0]t_rfc; // =50 for tCK=2.5ns
338  input[7:0]t_refi; // 48/97 for normal, 8 - for simulation
339  reg[29:0] cmd_addr;
340  reg[31:0] data;
341  begin
342  cmd_addr <= MCONTR_CMD_WR_ADDR + REFRESH_OFFSET;
343  @(posedge CLK)
344  // addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
345  data <= func_encode_cmd( 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
346  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
347  // =50 tREFI=260 ns before next ACTIVATE or REFRESH, @2.5ns clock, @5ns cycle
348  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
349  data <= func_encode_skip( t_rfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
350  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
351 // Ready for normal operation
352  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
353  data <= func_encode_skip( 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
354  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
355 // write_contol_register(DLY_SET,0);
356  write_contol_register(MCONTR_TOP_16BIT_ADDR + MCONTR_TOP_16BIT_REFRESH_ADDRESS, REFRESH_OFFSET);
357  write_contol_register(MCONTR_TOP_16BIT_ADDR + MCONTR_TOP_16BIT_REFRESH_PERIOD, {24'h0,t_refi});
358  // enable refresh - should it be done here?
359 // write_contol_register(MCONTR_PHY_0BIT_ADDR + MCONTR_TOP_0BIT_REFRESH_EN + 1, 0);
360  end
361 endtask
362 
363 task set_mrs; // will also calibrate ZQ
364  input reset_dll;
365  reg[17:0] mr0;
366  reg[17:0] mr1;
367  reg[17:0] mr2;
368  reg[17:0] mr3;
369  reg[29:0] cmd_addr;
370  reg[31:0] data;
371  begin
372  mr0 <= ddr3_mr0(
373  1'h0, // pd; // precharge power down 0 - dll off (slow exit), 1 - dll on (fast exit)
374  3'h2, // [2:0] wr; // write recovery (encode ceil(tWR/tCK)) // 3'b010: 6
375  reset_dll, // dll_rst; // 1 - dll reset (self clearing bit)
376  4'h4, // [3:0] cl; // CAS latency: // 0100: 6 (time 15ns)
377  1'h0, // bt; // read burst type: 0 sequential (nibble), 1 - interleave
378  2'h0); // [1:0] bl; // burst length: // 2'b00 - fixed BL8
379 
380  mr1 <= ddr3_mr1(
381  1'h0, // qoff; // output enable: 0 - DQ, DQS operate in normal mode, 1 - DQ, DQS are disabled
382  1'h0, // tdqs; // termination data strobe (for x8 devices) 0 - disabled, 1 - enabled
383  3'h2, // [2:0] rtt; // on-die termination resistance: // 3'b010 - RZQ/2 (120 Ohm)
384  1'h0, // wlev; // write leveling
385  2'h0, // ods; // output drive strength: // 2'b00 - RZQ/6 - 40 Ohm
386  2'h0, // [1:0] al; // additive latency: 2'b00 - disabled (AL=0)
387  1'b0); // dll; // 0 - DLL enabled (normal), 1 - DLL disabled
388 
389  mr2 <= ddr3_mr2(
390  2'h0, // [1:0] rtt_wr; // Dynamic ODT : // 2'b00 - disabled, 2'b01 - RZQ/4 = 60 Ohm, 2'b10 - RZQ/2 = 120 Ohm
391  1'h0, // srt; // Self-refresh temperature 0 - normal (0-85C), 1 - extended (<=95C)
392  1'h0, // asr; // Auto self-refresh 0 - disabled (manual), 1 - enabled (auto)
393  3'h0); // [2:0] cwl; // CAS write latency:3'b000 5CK (tCK >= 2.5ns), 3'b001 6CK (1.875ns <= tCK < 2.5ns)
394 
395  mr3 <= ddr3_mr3(
396  1'h0, // mpr; // MPR mode: 0 - normal, 1 - dataflow from MPR
397  2'h0); // [1:0] mpr_rf; // MPR read function: 2'b00: predefined pattern 0101...
398  cmd_addr <= MCONTR_CMD_WR_ADDR + INITIALIZE_OFFSET;
399  @(posedge CLK)
400  $display("mr0=0x%x", mr0);
401  $display("mr1=0x%x", mr1);
402  $display("mr2=0x%x", mr2);
403  $display("mr3=0x%x", mr3);
404  // addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
405  data <= func_encode_cmd(mr2[14:0], mr2[17:15], 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
406  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
407  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
408  data <= func_encode_skip( 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
409  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
410  // addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
411  data <= func_encode_cmd(mr3[14:0], mr3[17:15], 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
412  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
413  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
414  data <= func_encode_skip( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
415  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
416  // addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
417  data <= func_encode_cmd(mr1[14:0], mr1[17:15], 7, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0); // SEL==1 - just testing?
418  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
419  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
420  data <= func_encode_skip( 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
421  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
422  // addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
423  data <= func_encode_cmd(mr0[14:0], mr0[17:15], 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
424  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
425  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
426  data <= func_encode_skip( 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
427  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
428  // encode ZQCL:
429  // addr bank RCW ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD NOP, B_RST
430  data <= func_encode_cmd(15'h400, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
431  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
432  // 512 clock cycles after ZQCL
433  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
434  data <= func_encode_skip( 256, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
435  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
436  // sequence done bit, skip length is ignored
437  // skip done bank ODT CKE SEL DQEN DQSEN DQSTGL DCI B_WR B_RD B_RST
438  data <= func_encode_skip( 10, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
439  @(posedge CLK) axi_write_single_w(cmd_addr, data); cmd_addr <= cmd_addr + 1;
440  end
441 endtask
442 
443  function [ADDRESS_NUMBER+2:0] ddr3_mr0;
444  input pd; // precharge power down 0 - dll off (slow exit), 1 - dll on (fast exit)
445  input [2:0] wr; // write recovery:
446  // 3'b000: 16
447  // 3'b001: 5
448  // 3'b010: 6
449  // 3'b011: 7
450  // 3'b100: 8
451  // 3'b101: 10
452  // 3'b110: 12
453  // 3'b111: 14
454  input dll_rst; // 1 - dll reset (self clearing bit)
455  input [3:0] cl; // CAS latency (>=15ns):
456  // 0000: reserved
457  // 0010: 5
458  // 0100: 6
459  // 0110: 7
460  // 1000: 8
461  // 1010: 9
462  // 1100: 10
463  // 1110: 11
464  // 0001: 12
465  // 0011: 13
466  // 0101: 14
467  input bt; // read burst type: 0 sequential (nibble), 1 - interleaved
468  input [1:0] bl; // burst length:
469  // 2'b00 - fixed BL8
470  // 2'b01 - 4 or 8 on-the-fly by A12
471  // 2'b10 - fixed BL4 (chop)
472  // 2'b11 - reserved
473  begin
474  ddr3_mr0 = {
475  3'b0,
476  {ADDRESS_NUMBER-13{1'b0}},
477  pd, // MR0.12
478  wr, // MR0.11_9
479  dll_rst, // MR0.8
480  1'b0, // MR0.7
481  cl[3:1], // MR0.6_4
482  bt, // MR0.3
483  cl[0], // MR0.2
484  bl[1:0]}; // MR0.1_0
485  end
486 
487  endfunction
488 
489  function [ADDRESS_NUMBER+2:0] ddr3_mr1;
490  input qoff; // output enable: 0 - DQ, DQS operate in normal mode, 1 - DQ, DQS are disabled
491  input tdqs; // termination data strobe (for x8 devices) 0 - disabled, 1 - enabled
492  input [2:0] rtt; // on-die termination resistance:
493  // 3'b000 - disabled
494  // 3'b001 - RZQ/4 (60 Ohm)
495  // 3'b010 - RZQ/2 (120 Ohm)
496  // 3'b011 - RZQ/6 (40 Ohm)
497  // 3'b100 - RZQ/12(20 Ohm)
498  // 3'b101 - RZQ/8 (30 Ohm)
499  // 3'b11x - reserved
500  input wlev; // write leveling
501  input [1:0] ods; // output drive strength:
502  // 2'b00 - RZQ/6 - 40 Ohm
503  // 2'b01 - RZQ/7 - 34 Ohm
504  // 2'b1x - reserved
505  input [1:0] al; // additive latency:
506  // 2'b00 - disabled (AL=0)
507  // 2'b01 - AL=CL-1;
508  // 2'b10 - AL=CL-2
509  // 2'b11 - reserved
510  input dll; // 0 - DLL enabled (normal), 1 - DLL disabled
511  begin
512  ddr3_mr1 = {
513  3'h1,
514  {ADDRESS_NUMBER-13{1'b0}},
515  qoff, // MR1.12
516  tdqs, // MR1.11
517  1'b0, // MR1.10
518  rtt[2], // MR1.9
519  1'b0, // MR1.8
520  wlev, // MR1.7
521  rtt[1], // MR1.6
522  ods[1], // MR1.5
523  al[1:0], // MR1.4_3
524  rtt[0], // MR1.2
525  ods[0], // MR1.1
526  dll}; // MR1.0
527  end
528  endfunction
529 
530  function [ADDRESS_NUMBER+2:0] ddr3_mr2;
531  input [1:0] rtt_wr; // Dynamic ODT :
532  // 2'b00 - disabled
533  // 2'b01 - RZQ/4 = 60 Ohm
534  // 2'b10 - RZQ/2 = 120 Ohm
535  // 2'b11 - reserved
536  input srt; // Self-refresh temperature 0 - normal (0-85C), 1 - extended (<=95C)
537  input asr; // Auto self-refresh 0 - disabled (manual), 1 - enabled (auto)
538  input [2:0] cwl; // CAS write latency:
539  // 3'b000 5CK ( tCK >= 2.5ns)
540  // 3'b001 6CK (1.875ns <= tCK < 2.5ns)
541  // 3'b010 7CK (1.5ns <= tCK < 1.875ns)
542  // 3'b011 8CK (1.25ns <= tCK < 1.5ns)
543  // 3'b100 9CK (1.071ns <= tCK < 1.25ns)
544  // 3'b101 10CK (0.938ns <= tCK < 1.071ns)
545  // 3'b11x reserved
546  begin
547  ddr3_mr2 = {
548  3'h2,
549  {ADDRESS_NUMBER-11{1'b0}},
550  rtt_wr[1:0], // MR2.10_9
551  1'b0, // MR2.8
552  srt, // MR2.7
553  asr, // MR2.6
554  cwl[2:0], // MR2.5_3
555  3'b0}; // MR2.2_0
556  end
557  endfunction
558 
559  function [ADDRESS_NUMBER+2:0] ddr3_mr3;
560  input mpr; // MPR mode: 0 - normal, 1 - dataflow from MPR
561  input [1:0] mpr_rf; // MPR read function:
562  // 2'b00: predefined pattern 0101...
563  // 2'b1x, 2'bx1 - reserved
564  begin
565  ddr3_mr3 = {
566  3'h3,
567  {ADDRESS_NUMBER-3{1'b0}},
568  mpr, // MR3.2
569  mpr_rf[1:0]}; // MR3.1_0
570  end
571  endfunction