Initial commit of OpenSPARC T2 design and verification files.
[OpenSPARC-T2-DV] / verif / model / verilog / mem / dram / dimm.v
CommitLineData
86530b38
AT
1// ========== Copyright Header Begin ==========================================
2//
3// OpenSPARC T2 Processor File: dimm.v
4// Copyright (C) 1995-2007 Sun Microsystems, Inc. All Rights Reserved
5// 4150 Network Circle, Santa Clara, California 95054, U.S.A.
6//
7// * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
8//
9// This program is free software; you can redistribute it and/or modify
10// it under the terms of the GNU General Public License as published by
11// the Free Software Foundation; version 2 of the License.
12//
13// This program is distributed in the hope that it will be useful,
14// but WITHOUT ANY WARRANTY; without even the implied warranty of
15// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16// GNU General Public License for more details.
17//
18// You should have received a copy of the GNU General Public License
19// along with this program; if not, write to the Free Software
20// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21//
22// For the avoidance of doubt, and except that if any non-GPL license
23// choice is available it will apply instead, Sun elects to use only
24// the General Public License version 2 (GPLv2) at this time for any
25// software where a choice of GPL license versions is made
26// available with the language indicating that GPLv2 or any later version
27// may be used, or where a choice of which version of the GPL is applied is
28// otherwise unspecified.
29//
30// Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
31// CA 95054 USA or visit www.sun.com if you need additional information or
32// have any questions.
33//
34// ========== Copyright Header End ============================================
35`timescale 1ps/1ps
36
37// `define DIMM_DEB
38
39//----------------------------------------------------------------------
40// Functional DIMM model, Only Read/Write supported
41//----------------------------------------------------------------------
42
43module dimm(// inputs
44 clk, cs, ras, cas, we, ba, addr, cs_sel,
45 // inouts
46 dataq, ecc, dqs, dm_rdqs
47 );
48
49 parameter addr_width=17,
50`ifdef DRAM_BANK_BITS2
51 bank_width=2,
52`else
53 bank_width=3,
54`endif
55 dqs_width=1;
56
57 // inputs
58 input [2:0] clk;
59 input [1:0] cs;
60 input ras, cas, we;
61 input [(bank_width-1):0] ba;
62 input [(addr_width-1):0] addr;
63 input [7:0] cs_sel;
64
65 // inouts
66`ifdef X4
67 inout [3:0] dataq;
68`endif
69
70`ifdef X8
71 inout [7:0] dataq;
72`endif
73
74 inout [7:0] ecc;
75 inout [(dqs_width-1):0] dqs, dm_rdqs;
76
77 // Local variables
78
79 integer datah, handle, ecch; // Handles for memory model
80 parameter colm_width = 11;
81 parameter total_width = bank_width + addr_width + colm_width;
82 parameter bank_count = (1 << bank_width);
83 parameter depth = 31;
84 parameter dly = 400;
85
86 // wires
87
88 wire [3:0] ReadLat, ReadLat1, WriteLat;
89
90 wire dram_init_done=1;
91
92 // Registers
93
94 reg [(colm_width-1):0] ColAddr;
95 reg [3:0] dataq_out;
96 reg [3:0] dataq_d;
97 reg [7:0] ecc_out;
98 reg [7:0] ecc_d;
99 reg [depth:0] read_queue;
100 reg [depth:0] write_queue;
101 reg [3:0] AlignLat, BurstLen, CasLat;
102
103 reg [(total_width-1):0] rd_addr_queue [depth:0];
104 reg [(total_width-1):0] wr_addr_queue [depth:0];
105 reg [(addr_width-1):0] RowAddr [(bank_count-1):0];
106 reg [5:0] dv_cnt;
107
108 reg dataq_oe;
109 reg dqs_oe;
110 reg dqs_out;
111
112 // Delayed versions of the inputs
113
114 reg [1:0] cs_d;
115 reg ras_d, cas_d, we_d;
116 reg [(bank_width-1):0] ba_d;
117 reg [(addr_width-1):0] addr_d;
118
119 integer n;
120
121//----------------------------------------------------------------------
122// Drive outputs
123//----------------------------------------------------------------------
124
125 assign dataq = (dataq_oe == 1'b1) ? dataq_out : {4{1'bz}};
126 assign ecc = (dataq_oe == 1'b1) ? ecc_out : {8{1'bz}};
127 assign dqs = (dqs_oe == 1'b1) ? {dqs_width{dqs_out}} : {dqs_width{1'bz}};
128 assign dm_rdqs = (dqs_oe == 1'b1) ? {dqs_width{dqs_out}} : {dqs_width{1'bz}};
129
130//----------------------------------------------------------------------
131// Model setup
132//----------------------------------------------------------------------
133 initial
134 begin
135 if (!$value$plusargs("SYSTEM_DV_MATCH=%d", dv_cnt)) begin
136 dv_cnt = 2 ;
137 end
138 dv_cnt = dv_cnt-1;
139 end
140
141 `ifdef SYSTEM_DV_MATCH
142 assign ReadLat = AlignLat+CasLat+dv_cnt; // set DV_CNT = 2
143 assign ReadLat1= AlignLat+CasLat;
144 assign WriteLat = ReadLat1-1;
145 `else
146 assign ReadLat = AlignLat+CasLat;
147 assign WriteLat = ReadLat-1;
148 `endif
149
150//----------------------------------------------------------------------
151// Registered / Delayed versions of inputs
152//----------------------------------------------------------------------
153 always @ (posedge clk[0])
154 begin
155 ba_d <= #dly ba;
156 addr_d <= #dly addr;
157 cs_d <= #dly cs;
158 ras_d <= #dly ras;
159 cas_d <= #dly cas;
160 we_d <= #dly we;
161 end
162 always @ (posedge dqs[0] or negedge dqs[0])
163 begin
164 dataq_d <= #dly dataq;
165 ecc_d <= #dly ecc;
166 end
167//----------------------------------------------------------------------
168// Positive edge clock
169//----------------------------------------------------------------------
170
171 always @ (posedge clk[0])
172 begin
173
174 if ({cs_d[0], ras_d, cas_d, we_d} == 4'b0101) // Read
175 begin
176`ifdef DIMM_DEB
177 $display("%d: %m dimm read addr %x",$time,addr_d);
178`endif
179 ColAddr = {addr_d[colm_width:11],addr_d[9:0]};
180 for (n=0; n<BurstLen; n=n+1) begin
181 read_queue[2*ReadLat+n] <= #dly 1'b1;
182
183 if ( BurstLen == 8 )
184 rd_addr_queue[2*ReadLat+n] <= #dly {RowAddr[ba_d], ColAddr[10:3], ba_d,
185 ColAddr[2:0] + n[2:0]};
186 else
187 rd_addr_queue[2*ReadLat+n] <= #dly {RowAddr[ba_d], ColAddr[10:2], ba_d,
188 ColAddr[1:0] + n[1:0]};
189
190 end
191 end
192 else if ({cs_d[0], ras_d, cas_d, we_d} == 4'b0100) // Write
193 begin
194`ifdef DIMM_DEB
195 $display("%d: %m dimm write addr %x",$time,addr_d);
196`endif
197 ColAddr = {addr_d[colm_width:11],addr_d[9:0]};
198 for (n=0; n<BurstLen; n=n+1) begin
199 write_queue[2*WriteLat+n+1] <= #dly 1'b1;
200
201 if ( BurstLen == 8 )
202 wr_addr_queue[2*WriteLat+n+1] <= #dly
203 {RowAddr[ba_d], ColAddr[10:3], ba_d, ColAddr[2:0] + n[2:0]};
204 else
205 wr_addr_queue[2*WriteLat+n+1] <= #dly
206 {RowAddr[ba_d], ColAddr[10:2], ba_d, ColAddr[1:0] + n[1:0]};
207
208 end
209 end
210 else if ({cs_d[0], ras_d, cas_d, we_d} == 4'b0011) // RAS
211 begin
212`ifdef DIMM_DEB
213 $display("%d: %m dimm act addr %x ba %x",$time,addr_d,ba_d);
214`endif
215 RowAddr[ba_d] = addr_d;
216 end
217 else if ({cs_d[0], ras_d, cas_d, we_d} == 4'b0000) // Setup
218 begin
219`ifdef DIMM_DEB
220 $display("%d: %m dimm Setup addr %x ba %x",$time,addr_d,ba_d);
221`endif
222 if (ba_d == 0)
223 begin
224 BurstLen = (1 << addr_d[2:0]);
225 CasLat = addr_d[6:4];
226`ifdef DIMM_DEB
227 $display("%d: %m dimm BurstLen %x CasLat %x",$time,BurstLen,CasLat);
228`endif
229 end
230 else if (ba_d == 1)
231 begin
232 AlignLat = addr_d[5:3];
233`ifdef DIMM_DEB
234 $display("%d: %m dimm AlignLat set %x",$time,AlignLat);
235`endif
236 end
237 end
238
239 end // always
240
241//----------------------------------------------------------------------
242// Positive and Negative Edge for DDR
243//----------------------------------------------------------------------
244 always @ (posedge clk[0] or negedge clk[0])
245 begin
246 for (n=0; n<depth; n=n+1)
247 begin
248 read_queue[n] = read_queue[n+1];
249 rd_addr_queue[n] = rd_addr_queue[n+1];
250 wr_addr_queue[n] = wr_addr_queue[n+1];
251 write_queue[n] = write_queue[n+1];
252 end
253
254 if (read_queue[5] === 1'b1) dqs_oe <= 1'b1;
255 else if (read_queue[3] === 1'b0)
256 begin
257 dqs_out <= 1'b0;
258 dqs_oe <= 1'b0;
259 end
260
261 if (read_queue[3] === 1'b1)
262 begin
263 {dataq_out} = Read_mem(rd_addr_queue[3]);
264 dataq_oe <= 1'b1;
265 dqs_out <= ~dqs_out;
266 dqs_oe <= 1'b1;
267 end else begin
268 dataq_oe <= 1'b0;
269 end
270
271 if (write_queue[2] === 1'b1)
272 begin
273 Write_mem(wr_addr_queue[2],{dataq_d});
274 end
275
276 end
277//----------------------------------------------------------------------
278// Read function
279//----------------------------------------------------------------------
280 function [3:0] Read_mem;
281
282 input [(total_width-1):0] faddr;
283 reg [3:0] data;
284
285 begin
286 $read_mem(handle, data[3:0], faddr, cs_sel);
287 //$read_mem(datah+1, data[7:4], faddr, cs_sel);
288 //$read_mem(datah+2, data[11:8], faddr, cs_sel);
289 //$read_mem(datah+3, data[15:12], faddr, cs_sel);
290 //$read_mem(datah+4, data[19:16], faddr, cs_sel);
291 //$read_mem(datah+5, data[23:20], faddr, cs_sel);
292 //$read_mem(datah+6, data[27:24], faddr, cs_sel);
293 //$read_mem(datah+7, data[31:28], faddr, cs_sel);
294 //$read_mem(datah+8, data[35:32], faddr, cs_sel);
295 //$read_mem(datah+9, data[39:36], faddr, cs_sel);
296 //$read_mem(datah+10, data[43:40], faddr, cs_sel);
297 //$read_mem(datah+11, data[47:44], faddr, cs_sel);
298 //$read_mem(datah+12, data[51:48], faddr, cs_sel);
299 //$read_mem(datah+13, data[55:52], faddr, cs_sel);
300 //$read_mem(datah+14, data[59:56], faddr, cs_sel);
301 //$read_mem(datah+15, data[63:60], faddr, cs_sel);
302 //$read_mem(ecch, data[67:64], faddr, cs_sel);
303 //$read_mem(ecch+1, data[71:68], faddr, cs_sel);
304
305 Read_mem = data;
306`ifdef DIMM_DEB
307 $display("%d: %m dimm Read_mem addr %x Data %x \n",$time,faddr,data);
308`endif
309 end
310
311 endfunction
312
313
314//----------------------------------------------------------------------
315// Write task
316//----------------------------------------------------------------------
317 task Write_mem;
318 input [(total_width-1):0] faddr;
319 input [3:0] data;
320
321 begin
322 $write_mem(handle, data[3:0], faddr, cs_sel);
323 //$write_mem(datah+1, data[7:4], faddr, cs_sel);
324 //$write_mem(datah+2, data[11:8], faddr, cs_sel);
325 //$write_mem(datah+3, data[15:12], faddr, cs_sel);
326 //$write_mem(datah+4, data[19:16], faddr, cs_sel);
327 //$write_mem(datah+5, data[23:20], faddr, cs_sel);
328 //$write_mem(datah+6, data[27:24], faddr, cs_sel);
329 //$write_mem(datah+7, data[31:28], faddr, cs_sel);
330 //$write_mem(datah+8, data[35:32], faddr, cs_sel);
331 //$write_mem(datah+9, data[39:36], faddr, cs_sel);
332 //$write_mem(datah+10, data[43:40], faddr, cs_sel);
333 //$write_mem(datah+11, data[47:44], faddr, cs_sel);
334 //$write_mem(datah+12, data[51:48], faddr, cs_sel);
335 //$write_mem(datah+13, data[55:52], faddr, cs_sel);
336 //$write_mem(datah+14, data[59:56], faddr, cs_sel);
337 //$write_mem(datah+15, data[63:60], faddr, cs_sel);
338 //$write_mem(ecch, data[67:64], faddr, cs_sel);
339 //$write_mem(ecch+1, data[71:68], faddr, cs_sel);
340
341`ifdef DIMM_DEB
342 $display("%d: %m dimm Write_mem addr %x Data %x \n",$time,faddr,data);
343`endif
344 end
345
346 endtask
347
348//----------------------------------------------------------------------
349// Initialization
350//----------------------------------------------------------------------
351 initial begin
352 dataq_oe = 0;
353 dqs_oe = 0;
354 dqs_out = 1'b0;
355 dataq_out = 64'b0;
356 ecc_out = 8'b0;
357 for (n=0; n<depth; n=n+1)
358 begin
359 read_queue[n] = 1'b0;
360 rd_addr_queue[n] = {total_width{1'b0}};
361 wr_addr_queue[n] = {total_width{1'b0}};
362 write_queue[n] = 1'b0;
363 end
364 read_queue[depth] = 1'b0;
365 end
366//----------------------------------------------------------------------
367
368endmodule