OpenCores
URL https://opencores.org/ocsvn/ddr3_synthesizable_bfm/ddr3_synthesizable_bfm/trunk

Subversion Repositories ddr3_synthesizable_bfm

[/] [ddr3_synthesizable_bfm/] [trunk/] [rtl/] [ddr3_simple4.v] - Blame information for rev 3

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 slai
/*
2
*DDR3 Simple Synthesizable Memory BFM
3
*2010-2011 sclai <laikos@yahoo.com>
4
*
5
*This library is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU Lesser General Public License as published by
7
* the Free Software Foundation; either version 2.1 of the License,
8
* or (at your option) any later version.
9
*
10
* This library is distributed in the hope that it will be useful, but
11
* WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* Lesser General Public License for more details.
14
*
15
* You should have received a copy of the GNU Lesser General Public
16
* License along with this library; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
18
* USA
19
*
20
*
21 3 slai
*  Simple implementation of DDR3 Memory
22 2 slai
*  will only reponse to write and read request
23
*  parameter
24
*  count start from t0,t2,t2...
25
*  ck _|-|_|-|_|-|_|-|_
26
*
27
*  cs#---|___|---------
28
*
29
*        |   |    |
30
*        t0  t1  t2 ....
31
*
32
*/
33
 
34
`timescale 1ps / 1ps
35
 
36
module ddr3_simple4#(
37
parameter MEM_DQ_WIDTH          =8,
38
parameter MEM_BA_WIDTH          =3,
39
parameter MEM_ROW_WIDTH         =13,
40
parameter MEM_COL_WIDTH         =13,
41
parameter MEM_TRTP                      =6,
42
parameter MEM_TRCD                      =11,
43
parameter MEM_TWL                               =8,
44
parameter MEM_TRL                               =6,
45
parameter MEM_ACT_CMD           =7 //activates to command
46
)(
47
input wire [MEM_ROW_WIDTH-1:0]   a,
48
input wire [ MEM_BA_WIDTH-1:0]   ba,
49
input wire                                                              ck,
50
input wire                                                              ck_n,
51
input wire                                                              cke,
52
input wire                                                              cs_n,
53
input wire                                                              dm,
54
input wire                                                              ras_n,
55
input wire                                                              cas_n,
56
input wire                                                              we_n,
57
input wire                                                              reset_n,
58
inout wire      [MEM_DQ_WIDTH-1:0]       dq,
59
inout wire                                                              dqs,
60
inout wire                                                              dqs_n,
61
input wire                                                              odt
62
);
63
 
64
 
65
//definitions
66
localparam         OPCODE_PRECHARGE             = 4'b0010;
67
localparam              OPCODE_ACTIVATE                 = 4'b0011;
68
localparam              OPCODE_WRITE                    = 4'b0100;
69
localparam              OPCODE_READ                = 4'b0101;
70
localparam              OPCODE_MRS                         = 4'b0000;
71
localparam              OPCODE_REFRESH          = 4'b0001;
72
localparam              OPCODE_DES                         = 4'b1000;
73
localparam              OPCODE_ZQC                         = 4'b0110;
74
localparam              OPCODE_NOP                         = 4'b0111;
75
 
76
localparam  BL8 = 1'b1;
77
localparam  BC4 = 1'b0;
78
 
79
 
80
//mode registers
81
reg [31:0] mr0;
82
reg [31:0] mr2;
83
reg [31:0] mr3;
84
 
85
 
86
wire [35:0] write_add;
87
wire [35:0] read_add;
88
wire [3:0]  write_cmd;
89
wire [3:0]  read_cmd;
90
(* keep *)wire [(MEM_DQ_WIDTH*2)-1:0] read_data;
91
 
92
reg [ 2:0] last_bank;
93
reg [15:0] last_row;
94
reg [3:0] last_write_cmd;
95
reg [3:0] last_read_cmd;
96
reg [35:0] last_write_add;
97
reg [35:0] last_read_add;
98
 
99
reg        write_address12;
100
reg        read_address12;
101
 
102
//bank tracker
103
reg [MEM_ROW_WIDTH-1:0]opened_row[(2**MEM_BA_WIDTH)-1:0];
104
//row  tracker
105
 
106
wire [MEM_DQ_WIDTH-1:0]  dq_out;
107
reg  [MEM_DQ_WIDTH-1:0]  dq_in0;
108
 
109
(* keep *) wire [MEM_DQ_WIDTH-1:0] data_hi;
110
(* keep *) wire [MEM_DQ_WIDTH-1:0] data_lo;
111
(* keep *) wire                                           data_hi_dm;
112
(* keep *) wire                                                   data_lo_dm;
113
//IDDR
114
my_iddrx8 iddrx8_inst(
115
        .clk(ck),
116
        .io(dq),
117
        .d0(data_lo),
118
        .d1(data_hi)
119
);
120
 
121
my_iddrx8 iddrx8_dm_inst(
122
        .clk(ck),
123
        .io(dm),
124
        .d0(data_lo_dm),
125
        .d1(data_hi_dm)
126
);
127
 
128
//ODDR
129
my_oddrx8 oddrx8_inst(
130
.clk(ck),
131
.d0(read_data[ MEM_DQ_WIDTH-1:0              ]),
132
.d1(read_data[(MEM_DQ_WIDTH*2)-1:MEM_DQ_WIDTH]),
133
.io(dq_out)
134
);
135
 
136
//double data rate
137
always @(posedge ck )
138
begin
139
if(reset_n==1'b0)
140
        begin
141
                last_bank     <=4'h0;
142
                last_row      <=16'h0000;
143
        end
144
else
145
begin
146
        case({cs_n,ras_n,cas_n,we_n})
147
        /*
148
        OPCODE_PRECHARGE        :begin
149
                                                                $display("t=%d,PRECHARGE",vip_clk);
150
                                                        end
151
        */
152
        OPCODE_ACTIVATE         :begin
153
                                                                opened_row [ba] <={{(16-MEM_ROW_WIDTH){1'b0}},a[MEM_ROW_WIDTH-1:0]};
154
                                                        end
155
        /*
156
        OPCODE_DES                      :begin
157
                                                                $display("t=%d,DES",vip_clk);
158
                                                        end
159
        OPCODE_MRS              :begin
160
                                                                $display("t=%d,MRS",vip_clk);
161
                                                        end
162
        OPCODE_NOP              :begin
163
                                                                //$display("t=%d,NOP",vip_clk);
164
                                                        end
165
        */
166
        OPCODE_READ             :begin
167
                                                                last_read_add   <={ba,opened_row[ba],{{(16-MEM_COL_WIDTH){1'b0}},a[MEM_COL_WIDTH-1:0]}};
168
                                                                last_read_cmd   <=OPCODE_READ;
169
                                                        end
170
        OPCODE_WRITE            :begin
171
                                                                last_write_add  <={ba,opened_row[ba],{{(16-MEM_COL_WIDTH){1'b0}},a[MEM_COL_WIDTH-1:0]}};
172
                                                                last_write_cmd  <=OPCODE_WRITE;
173
                                                        end
174
                                                        /*
175
        OPCODE_ZQC                      :begin
176
                                                                $display("t=%d,ZQC",vip_clk);
177
                                                        end*/
178
                default:begin
179
                                last_read_cmd   <=OPCODE_NOP;
180
                                last_write_cmd <=OPCODE_NOP;
181
                                end
182
        endcase
183
end // end reset        
184
end // end always@(*)
185
 
186
 
187
 
188
//cmd
189
//read
190
ddr3_sr4 #(
191
.PIPE_LEN(MEM_TRL)
192
)ddr3_read_cmd_sr(
193
        .clk(ck),
194
        .shift_in(last_read_cmd),
195
        .shift_out(read_cmd)
196
);
197
//bank, row, col
198
ddr3_sr36 #(
199
.PIPE_LEN(MEM_TRL+1)
200
)ddr3_read_add_sr(
201
        .clk(ck),
202
        .shift_in(last_read_add),
203
        .shift_out(read_add)
204
);
205
 
206
//cmd
207
//write
208
ddr3_sr4#(
209
.PIPE_LEN(MEM_TWL)
210
)ddr3_write_cmd_sr(
211
        .clk(ck),
212
        .shift_in(last_write_cmd),
213
        .shift_out(write_cmd)
214
);
215
 
216
//bank, row, col
217
ddr3_sr36#(
218
.PIPE_LEN(MEM_TWL+1) //have to be a cycle late to wait for IDDR latency
219
) ddr3_write_add_sr(
220
        .clk(ck),
221
        .shift_in(last_write_add),
222
        .shift_out(write_add)
223
);
224
 
225
 
226
//write fsm
227
localparam WR_D0        =4'd0;
228
localparam WR_D1        =4'd1;
229
localparam WR_D2        =4'd2;
230
localparam WR_D3  =4'd3;
231
localparam WR_IDLE=4'd5;
232
reg [3:0] write_state;
233
reg              mem_we;
234
reg [2:0] write_col;
235
always@(posedge ck)
236
begin
237
        if(reset_n==1'b0)
238
                begin
239
                        write_state<=WR_IDLE;
240
                        mem_we<=1'b0;
241
                        write_col<=0;
242
                end
243
        else
244
                begin
245
                case(write_state)
246
                        WR_IDLE:begin
247
                        write_col<=0;
248
                        if(write_cmd==OPCODE_WRITE)
249
                                begin
250
                                        write_state<=WR_D0;
251
                                        mem_we<=1'b1;
252
                                end
253
                        else
254
                                begin
255
                                        write_state<=WR_IDLE;
256
                                        mem_we<=1'b0;
257
                                end
258
                        end
259
                        WR_D0:begin
260
                                write_address12<=write_add[12];
261
                                write_state<=WR_D1;
262
                                write_col<=write_col+1'b1;
263
                                $display("%m: at time %t\tWRITE BANK[%x]\tROW[%x]\tCOL[%x]\tWR D0: %x-%x",$time,write_add[34:32],write_add[31:16],write_add[15:0],data_hi,data_lo);
264
                        end
265
                        WR_D1:begin
266
                                if(write_address12==1'b1)
267
                                        begin
268
                                                write_state<=WR_D2;
269
                                                write_col<=write_col+1'b1;
270
                                        end
271
                                else if (write_cmd==OPCODE_WRITE)
272
                                        begin
273
                                                write_state<=WR_D0;
274
                                                write_col<=0;
275
                                        end
276
                                else
277
                                        begin
278
                                                write_state<=WR_IDLE;
279
                                                mem_we<=1'b0;
280
                                        end
281
                                $display("%m: at time %t\tWRITE BANK[%x]\tROW[%x]\tCOL[%x]\tWR D1: %x-%x",$time,write_add[34:32],write_add[31:16],write_add[15:0],data_hi,data_lo);
282
                        end
283
                        WR_D2:begin
284
                                write_state<=WR_D3;
285
                                write_col<=write_col+1'b1;
286
                                $display("%m: at time %t\tWRITE BANK[%x]\tROW[%x]\tCOL[%x]\tWR D2: %x-%x",$time,write_add[34:32],write_add[31:16],write_add[15:0],data_hi,data_lo);
287
                        end
288
                        WR_D3:begin
289
                                $display("%m: at time %t\tWRITE BANK[%x]\tROW[%x]\tCOL[%x]\tWR D3: %x-%x",$time,write_add[34:32],write_add[31:16],write_add[15:0],data_hi,data_lo);
290
 
291
                                //write_col<=write_col+1'b1;    
292
                                if (write_cmd==OPCODE_WRITE)
293
                                        begin
294
                                                write_state<=WR_D0;
295
                                                write_col<=0;
296
                                        end
297
                                else
298
                                        begin
299
                                                write_state<=WR_IDLE;
300
                                                mem_we<=1'b0;
301
                                        end
302
                        end
303
                endcase
304
                end //endif
305
end
306
 
307
 
308
//read fsm
309
localparam RD_D0        =4'd0;
310
localparam RD_D1        =4'd1;
311
localparam RD_D2        =4'd2;
312
localparam RD_D3  =4'd3;
313
localparam RD_IDLE=4'd5;
314
 
315
reg [3:0] read_state;
316
reg [2:0] read_col;
317
reg              send_dq;
318
reg              send_dqs0;
319
reg              send_dqs1;
320
 
321
always@(posedge ck)
322
begin
323
        if(reset_n==1'b0)
324
                begin
325
                        read_state<=RD_IDLE;
326
                        read_col         <=0;
327
                        send_dq  <=0;
328
                end
329
        else
330
                begin
331
                        case(read_state)
332
                        RD_IDLE:begin
333
                        read_col<=0;
334
                        send_dq<=0;
335
                        if(read_cmd==OPCODE_READ)
336
                                begin
337
                                        read_state<=RD_D0;
338
                                end
339
                        else
340
                                begin
341
                                        read_state<=RD_IDLE;
342
                                end
343
                        end
344
                        RD_D0:begin
345
                                read_address12<=read_add[12];
346
                                read_state<=RD_D1;
347
                                read_col<=read_col+1'b1;
348
                                send_dq  <=1'b1;
349
                                $display("%m: at time %t\tREAD BANK[%x]\tROW[%x]\tCOL[%x]\tRD D0",$time,read_add[34:32],read_add[31:16],read_add[15:0]);
350
                        end
351
                        RD_D1:begin
352
                                if(read_address12==1'b1)
353
                                        begin
354
                                                read_state<=RD_D2;
355
                                                read_col<=read_col+1'b1;
356
                                        end
357
                                else if (read_cmd==OPCODE_READ)
358
                                        begin
359
                                                read_state<=RD_D0;
360
                                                read_col<=0;
361
                                                send_dq  <=1'b1;
362
                                        end
363
                                else
364
                                        begin
365
                                                read_state<=RD_IDLE;
366
                                                //send_dq        <=1'b0;
367
                                        end
368
                                $display("%m: at time %t\tREAD BANK[%x]\tROW[%x]\tCOL[%x]\tRD D1",$time,read_add[34:32],read_add[31:16],read_add[15:0]);
369
                        end
370
                        RD_D2:begin
371
                                read_state<=RD_D3;
372
                                read_col<=read_col+1'b1;
373
                                send_dq  <=1'b1;
374
                                $display("%m: at time %t\tREAD BANK[%x]\tROW[%x]\tCOL[%x]\tRD D2",$time,read_add[34:32],read_add[31:16],read_add[15:0]);
375
                        end
376
                        RD_D3:begin
377
                                //write_col<=write_col+1'b1;    
378
                                if (read_cmd==OPCODE_READ)
379
                                        begin
380
                                                read_state<=RD_D0;
381
                                                read_col<=0;
382
                                                send_dq  <=1'b1;
383
                                        end
384
                                else
385
                                        begin
386
                                                read_state<=RD_IDLE;
387
                                                read_col<=0;
388
                                                //send_dq        <=1'b0;
389
                                        end
390
                                        $display("%m: at time %t\tREAD BANK[%x]\tROW[%x]\tCOL[%x]\tRD D3",$time,read_add[34:32],read_add[31:16],read_add[15:0]);
391
                        end
392
                        endcase
393
                end
394
 
395
end //end always
396
 
397
//dqs fsm
398
always @(posedge ck_n)
399
begin
400
if(reset_n==1'b0)
401
        begin
402
                send_dqs1<=0;
403
                send_dqs0<=0;
404
        end
405
else
406
        begin
407
                if(read_cmd==OPCODE_READ)
408
                        begin
409
                                send_dqs1<=1'b1;
410
                        end
411
                else
412
                        begin
413
                                send_dqs1<=1'b0;
414
                        end
415
        end
416
send_dqs0<=send_dqs1;
417
end//end always
418
 
419
//ram here
420
dport_ram  #(
421
        .DATA_WIDTH(8), //data_hi,data_lo
422
        .ADDR_WIDTH(36)
423
)dport_ram_hi(
424
        .clk                    (ck),
425
        .di                     (data_hi),
426
        .read_addr      (read_add+read_col),
427
        .write_addr (write_add+write_col),
428
        .we                     (mem_we & data_hi_dm),
429
        .do                     (read_data[15:8])
430
);
431
 
432
dport_ram  #(
433
        .DATA_WIDTH(8), //data_hi,data_lo
434
        .ADDR_WIDTH(36)
435
)dport_ram_lo(
436
        .clk                    (ck),
437
        .di                     (data_lo),
438
        .read_addr      (read_add+read_col),
439
        .write_addr (write_add+write_col),
440
        .we                     (mem_we & data_lo_dm),
441
        .do                     (read_data[7:0])
442
);
443
assign dqs  =((send_dqs0==1'b1) || (send_dq==1'b1))?ck:1'bz;
444
assign dqs_n=((send_dqs0==1'b1) || (send_dq==1'b1))?ck_n:1'bz;
445
assign dq   = (send_dq==1'b1)?dq_out:8'hZZ;
446
 
447
/* utility functions to display information
448
*/
449
initial begin
450
        $timeformat (-9, 1, " ns", 1);
451
      end
452
 
453
always @(posedge ck )
454
begin
455
        case({cs_n,ras_n,cas_n,we_n})
456
 
457
        OPCODE_PRECHARGE        :begin
458
                                                                $display("%m: at time %t PRECHARGE ",$time);
459
                                                        end
460
 
461
        OPCODE_ACTIVATE         :begin
462
                                                                $display("%m: at time %t ACTIVATE - BANK[%x]\tROW[%x]",$time,ba,a);
463
                                                        end
464
 
465
        OPCODE_DES                      :begin
466
                                                                $display("%m: at time %t DES ",$time);
467
                                                        end
468
        OPCODE_MRS              :begin
469
                                                                $display("%m: at time %t MRS ",$time);
470
                                                        end
471
        /*OPCODE_NOP            :begin
472
                                                                /$display("%m: at time %t WRITE ",$time);
473
                                                        end
474
        */
475
        /*
476
        OPCODE_READ             :begin
477
                                                                $display("%m: at time %t READ - BANK[%x]\tROW[%x]\tCOL[%x]",$time,ba,last_row,a);
478
                                                        end
479
        OPCODE_WRITE            :begin
480
                                                                $display("%m: at time %t WRITE - BANK[%x]\tROW[%x],\tCOL[%x]",$time,ba,last_row,a);
481
                                                        end
482
        */
483
        OPCODE_ZQC                      :begin
484
                                                                $display("%m: at time %t ZQC ",$time);
485
                                                        end
486
        endcase
487
 
488
end // end always@(*)
489
/* end utility*/
490
 
491
endmodule

powered by: WebSVN 2.1.0

© copyright 1999-2023 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.