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 4

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 4 slai
*
33 2 slai
*/
34
 
35
`timescale 1ps / 1ps
36
 
37
module ddr3_simple4#(
38
parameter MEM_DQ_WIDTH          =8,
39
parameter MEM_BA_WIDTH          =3,
40
parameter MEM_ROW_WIDTH         =13,
41
parameter MEM_COL_WIDTH         =13,
42 4 slai
parameter MEM_AL                =0,
43
parameter MEM_CWL               =8, //CWL
44
parameter MEM_CL                =6  //CL
45 2 slai
)(
46
input wire [MEM_ROW_WIDTH-1:0]   a,
47
input wire [ MEM_BA_WIDTH-1:0]   ba,
48 4 slai
input wire                      ck,
49
input wire                      ck_n,
50
input wire                      cke,
51
input wire                      cs_n,
52
input wire                      dm,
53
input wire                      ras_n,
54
input wire                      cas_n,
55
input wire                      we_n,
56
input wire                      reset_n,
57
inout wire [MEM_DQ_WIDTH-1:0]    dq,
58
inout wire                      dqs,
59
inout wire                      dqs_n,
60
input wire                      odt
61 2 slai
);
62
 
63 4 slai
//convert actual CL and CWL parameter to 
64 2 slai
 
65
//definitions
66 4 slai
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 2 slai
 
76
//mode registers
77
reg [31:0] mr0;
78
reg [31:0] mr2;
79
reg [31:0] mr3;
80
 
81
 
82
wire [35:0] write_add;
83
wire [35:0] read_add;
84
wire [3:0]  write_cmd;
85
wire [3:0]  read_cmd;
86
(* keep *)wire [(MEM_DQ_WIDTH*2)-1:0] read_data;
87
 
88
reg [ 2:0] last_bank;
89
reg [15:0] last_row;
90
reg [3:0] last_write_cmd;
91
reg [3:0] last_read_cmd;
92
reg [35:0] last_write_add;
93
reg [35:0] last_read_add;
94
 
95
reg        write_address12;
96
reg        read_address12;
97
 
98
//bank tracker
99
reg [MEM_ROW_WIDTH-1:0]opened_row[(2**MEM_BA_WIDTH)-1:0];
100
//row  tracker
101
 
102
wire [MEM_DQ_WIDTH-1:0]  dq_out;
103
reg  [MEM_DQ_WIDTH-1:0]  dq_in0;
104
 
105
(* keep *) wire [MEM_DQ_WIDTH-1:0] data_hi;
106
(* keep *) wire [MEM_DQ_WIDTH-1:0] data_lo;
107 4 slai
(* keep *) wire                   data_hi_dm;
108
(* keep *) wire                   data_lo_dm;
109 2 slai
//IDDR
110
my_iddrx8 iddrx8_inst(
111
        .clk(ck),
112
        .io(dq),
113
        .d0(data_lo),
114
        .d1(data_hi)
115
);
116
 
117
my_iddrx8 iddrx8_dm_inst(
118
        .clk(ck),
119
        .io(dm),
120
        .d0(data_lo_dm),
121
        .d1(data_hi_dm)
122
);
123
 
124
//ODDR
125
my_oddrx8 oddrx8_inst(
126
.clk(ck),
127
.d0(read_data[ MEM_DQ_WIDTH-1:0              ]),
128
.d1(read_data[(MEM_DQ_WIDTH*2)-1:MEM_DQ_WIDTH]),
129
.io(dq_out)
130
);
131
 
132
//double data rate
133
always @(posedge ck )
134
begin
135
if(reset_n==1'b0)
136
        begin
137
                last_bank     <=4'h0;
138
                last_row      <=16'h0000;
139
        end
140
else
141
begin
142
        case({cs_n,ras_n,cas_n,we_n})
143
        /*
144
        OPCODE_PRECHARGE        :begin
145 4 slai
                                        $display("t=%d,PRECHARGE",vip_clk);
146
                                end
147 2 slai
        */
148
        OPCODE_ACTIVATE         :begin
149 4 slai
                                        opened_row [ba] <={{(16-MEM_ROW_WIDTH){1'b0}},a[MEM_ROW_WIDTH-1:0]};
150
                                end
151 2 slai
        /*
152 4 slai
        OPCODE_DES              :begin
153
                                        $display("t=%d,DES",vip_clk);
154
                                end
155 2 slai
        OPCODE_MRS              :begin
156 4 slai
                                        $display("t=%d,MRS",vip_clk);
157
                                end
158 2 slai
        OPCODE_NOP              :begin
159 4 slai
                                        //$display("t=%d,NOP",vip_clk);
160
                                end
161 2 slai
        */
162
        OPCODE_READ             :begin
163 4 slai
                                        last_read_add   <={ba,opened_row[ba],{{(16-MEM_COL_WIDTH){1'b0}},a[MEM_COL_WIDTH-1:0]}};
164
                                        last_read_cmd   <=OPCODE_READ;
165
                                end
166 2 slai
        OPCODE_WRITE            :begin
167 4 slai
                                        last_write_add  <={ba,opened_row[ba],{{(16-MEM_COL_WIDTH){1'b0}},a[MEM_COL_WIDTH-1:0]}};
168
                                        last_write_cmd  <=OPCODE_WRITE;
169
                                end
170 2 slai
                                                        /*
171 4 slai
        OPCODE_ZQC              :begin
172
                                $display("t=%d,ZQC",vip_clk);
173
                                        end*/
174 2 slai
                default:begin
175
                                last_read_cmd   <=OPCODE_NOP;
176
                                last_write_cmd <=OPCODE_NOP;
177 4 slai
                        end
178 2 slai
        endcase
179
end // end reset        
180
end // end always@(*)
181
 
182
 
183
 
184
//cmd
185
//read
186
ddr3_sr4 #(
187 4 slai
.PIPE_LEN(MEM_CL)
188 2 slai
)ddr3_read_cmd_sr(
189
        .clk(ck),
190
        .shift_in(last_read_cmd),
191
        .shift_out(read_cmd)
192
);
193
//bank, row, col
194
ddr3_sr36 #(
195 4 slai
.PIPE_LEN(MEM_CL+1)
196 2 slai
)ddr3_read_add_sr(
197
        .clk(ck),
198
        .shift_in(last_read_add),
199
        .shift_out(read_add)
200
);
201
 
202
//cmd
203
//write
204
ddr3_sr4#(
205 4 slai
.PIPE_LEN(MEM_CWL)
206 2 slai
)ddr3_write_cmd_sr(
207
        .clk(ck),
208
        .shift_in(last_write_cmd),
209
        .shift_out(write_cmd)
210
);
211
 
212
//bank, row, col
213
ddr3_sr36#(
214 4 slai
.PIPE_LEN(MEM_CWL+1) //have to be a cycle late to wait for IDDR latency
215 2 slai
) ddr3_write_add_sr(
216
        .clk(ck),
217
        .shift_in(last_write_add),
218
        .shift_out(write_add)
219
);
220
 
221
 
222
//write fsm
223
localparam WR_D0        =4'd0;
224
localparam WR_D1        =4'd1;
225
localparam WR_D2        =4'd2;
226 4 slai
localparam WR_D3        =4'd3;
227
localparam WR_IDLE      =4'd5;
228 2 slai
reg [3:0] write_state;
229
reg              mem_we;
230
reg [2:0] write_col;
231
always@(posedge ck)
232
begin
233
        if(reset_n==1'b0)
234
                begin
235
                        write_state<=WR_IDLE;
236
                        mem_we<=1'b0;
237
                        write_col<=0;
238
                end
239
        else
240
                begin
241
                case(write_state)
242
                        WR_IDLE:begin
243
                        write_col<=0;
244
                        if(write_cmd==OPCODE_WRITE)
245
                                begin
246
                                        write_state<=WR_D0;
247
                                        mem_we<=1'b1;
248
                                end
249
                        else
250
                                begin
251
                                        write_state<=WR_IDLE;
252
                                        mem_we<=1'b0;
253
                                end
254
                        end
255
                        WR_D0:begin
256
                                write_address12<=write_add[12];
257
                                write_state<=WR_D1;
258
                                write_col<=write_col+1'b1;
259
                                $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);
260
                        end
261
                        WR_D1:begin
262
                                if(write_address12==1'b1)
263
                                        begin
264
                                                write_state<=WR_D2;
265
                                                write_col<=write_col+1'b1;
266
                                        end
267
                                else if (write_cmd==OPCODE_WRITE)
268
                                        begin
269
                                                write_state<=WR_D0;
270
                                                write_col<=0;
271
                                        end
272
                                else
273
                                        begin
274
                                                write_state<=WR_IDLE;
275
                                                mem_we<=1'b0;
276
                                        end
277
                                $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);
278
                        end
279
                        WR_D2:begin
280
                                write_state<=WR_D3;
281
                                write_col<=write_col+1'b1;
282
                                $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);
283
                        end
284
                        WR_D3:begin
285
                                $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);
286
 
287
                                //write_col<=write_col+1'b1;    
288
                                if (write_cmd==OPCODE_WRITE)
289
                                        begin
290
                                                write_state<=WR_D0;
291
                                                write_col<=0;
292
                                        end
293
                                else
294
                                        begin
295
                                                write_state<=WR_IDLE;
296
                                                mem_we<=1'b0;
297
                                        end
298
                        end
299
                endcase
300
                end //endif
301
end
302
 
303
 
304
//read fsm
305
localparam RD_D0        =4'd0;
306
localparam RD_D1        =4'd1;
307
localparam RD_D2        =4'd2;
308 4 slai
localparam RD_D3        =4'd3;
309
localparam RD_IDLE      =4'd5;
310 2 slai
 
311
reg [3:0] read_state;
312
reg [2:0] read_col;
313
reg              send_dq;
314
reg              send_dqs0;
315
reg              send_dqs1;
316
 
317
always@(posedge ck)
318
begin
319
        if(reset_n==1'b0)
320
                begin
321
                        read_state<=RD_IDLE;
322
                        read_col         <=0;
323
                        send_dq  <=0;
324
                end
325
        else
326
                begin
327
                        case(read_state)
328
                        RD_IDLE:begin
329
                        read_col<=0;
330
                        send_dq<=0;
331
                        if(read_cmd==OPCODE_READ)
332
                                begin
333
                                        read_state<=RD_D0;
334
                                end
335
                        else
336
                                begin
337
                                        read_state<=RD_IDLE;
338
                                end
339
                        end
340
                        RD_D0:begin
341
                                read_address12<=read_add[12];
342
                                read_state<=RD_D1;
343
                                read_col<=read_col+1'b1;
344
                                send_dq  <=1'b1;
345
                                $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]);
346
                        end
347
                        RD_D1:begin
348
                                if(read_address12==1'b1)
349
                                        begin
350
                                                read_state<=RD_D2;
351
                                                read_col<=read_col+1'b1;
352
                                        end
353
                                else if (read_cmd==OPCODE_READ)
354
                                        begin
355
                                                read_state<=RD_D0;
356
                                                read_col<=0;
357
                                                send_dq  <=1'b1;
358
                                        end
359
                                else
360
                                        begin
361
                                                read_state<=RD_IDLE;
362
                                                //send_dq        <=1'b0;
363
                                        end
364
                                $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]);
365
                        end
366
                        RD_D2:begin
367
                                read_state<=RD_D3;
368
                                read_col<=read_col+1'b1;
369
                                send_dq  <=1'b1;
370
                                $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]);
371
                        end
372
                        RD_D3:begin
373
                                //write_col<=write_col+1'b1;    
374
                                if (read_cmd==OPCODE_READ)
375
                                        begin
376
                                                read_state<=RD_D0;
377
                                                read_col<=0;
378
                                                send_dq  <=1'b1;
379
                                        end
380
                                else
381
                                        begin
382
                                                read_state<=RD_IDLE;
383
                                                read_col<=0;
384
                                                //send_dq        <=1'b0;
385
                                        end
386
                                        $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]);
387
                        end
388
                        endcase
389
                end
390
 
391
end //end always
392
 
393
//dqs fsm
394
always @(posedge ck_n)
395
begin
396
if(reset_n==1'b0)
397
        begin
398
                send_dqs1<=0;
399
                send_dqs0<=0;
400
        end
401
else
402
        begin
403
                if(read_cmd==OPCODE_READ)
404
                        begin
405
                                send_dqs1<=1'b1;
406
                        end
407
                else
408
                        begin
409
                                send_dqs1<=1'b0;
410
                        end
411
        end
412
send_dqs0<=send_dqs1;
413
end//end always
414
 
415
//ram here
416
dport_ram  #(
417 4 slai
        .DATA_WIDTH(MEM_DQ_WIDTH), //data_hi,data_lo
418 2 slai
        .ADDR_WIDTH(36)
419
)dport_ram_hi(
420
        .clk                    (ck),
421
        .di                     (data_hi),
422
        .read_addr      (read_add+read_col),
423
        .write_addr (write_add+write_col),
424
        .we                     (mem_we & data_hi_dm),
425
        .do                     (read_data[15:8])
426
);
427
 
428
dport_ram  #(
429 4 slai
        .DATA_WIDTH(MEM_DQ_WIDTH), //data_hi,data_lo
430 2 slai
        .ADDR_WIDTH(36)
431
)dport_ram_lo(
432
        .clk                    (ck),
433
        .di                     (data_lo),
434
        .read_addr      (read_add+read_col),
435
        .write_addr (write_add+write_col),
436
        .we                     (mem_we & data_lo_dm),
437
        .do                     (read_data[7:0])
438
);
439
assign dqs  =((send_dqs0==1'b1) || (send_dq==1'b1))?ck:1'bz;
440
assign dqs_n=((send_dqs0==1'b1) || (send_dq==1'b1))?ck_n:1'bz;
441
assign dq   = (send_dq==1'b1)?dq_out:8'hZZ;
442
 
443
/* utility functions to display information
444
*/
445 4 slai
 
446 2 slai
initial begin
447
        $timeformat (-9, 1, " ns", 1);
448
      end
449
 
450
always @(posedge ck )
451
begin
452
        case({cs_n,ras_n,cas_n,we_n})
453
 
454
        OPCODE_PRECHARGE        :begin
455 4 slai
                                        $display("%m: at time %t PRECHARGE ",$time);
456
                                end
457 2 slai
 
458
        OPCODE_ACTIVATE         :begin
459 4 slai
                                        $display("%m: at time %t ACTIVATE - BANK[%x]\tROW[%x]",$time,ba,a);
460
                                end
461 2 slai
 
462 4 slai
        OPCODE_DES              :begin
463
                                        $display("%m: at time %t DES ",$time);
464
                                end
465
        OPCODE_MRS      :begin
466
                                                        $display("%m: at time %t MRS - MR[%d]",$time,ba[1:0]);
467
                                                        case(ba[1:0])
468
                                                                2'b00:begin //MR0
469
                                                                        case(a[1:0]) // burst length
470
                                                                                2'b00:$display("%m\tBL = BL8 \(Fixed\)");
471
                                                                                2'b01:$display("%m\tBL = BC4/BL8 OTF");
472
                                                                                2'b10:$display("%m\tBL = BC4 (Fixed)");
473
                                                                                2'b11:$display("%m\tBL = Reserved");
474
                                                                        endcase
475
 
476
                                                                        case({a[6:4],a[2]}) //CAS Latency
477
                                                                                4'b0000:$display("%m\tCL = Reserved");
478
                                                                                4'b0010:$display("%m\tCL = 5");
479
                                                                                4'b0100:$display("%m\tCL = 6");
480
                                                                                4'b0110:$display("%m\tCL = 7");
481
                                                                                4'b1000:$display("%m\tCL = 8");
482
                                                                                4'b1010:$display("%m\tCL = 9");
483
                                                                                4'b1100:$display("%m\tCL = 10");
484
                                                                                4'b1111:$display("%m\tCL = 11(Optional for DD3-1600)");
485
                                                                                4'b0001:$display("%m\tCL = 12");
486
                                                                                4'b0011:$display("%m\tCL = 13");
487
                                                                                4'b0101:$display("%m\tCL = 14");
488
                                                                                4'b0111:$display("%m\tCL = Reserved for 15");
489
                                                                                4'b1001:$display("%m\tCL = Reserved for 16");
490
                                                                                4'b1011:$display("%m\tCL = Reserved");
491
                                                                                4'b1101:$display("%m\tCL = Reserved");
492
                                                                                4'b1111:$display("%m\tCL = Reserved");
493
                                                                        endcase
494
 
495
                                                                        case(a[11:9]) //Write Recover
496
                                                                                3'b000:$display("%m\tWR = 16^2(256 cycles)");
497
                                                                                3'b001:$display("%m\tWR =  5^2( 25 cycles)");
498
                                                                                3'b010:$display("%m\tWR =  6^2( 36 cycles)");
499
                                                                                3'b011:$display("%m\tWR =  7^2( 49 cycles)");
500
                                                                                3'b100:$display("%m\tWR =  8^2( 64 cycles)");
501
                                                                                3'b101:$display("%m\tWR = 10^2(100 cycles)");
502
                                                                                3'b110:$display("%m\tWR = 12^2(144 cycles)");
503
                                                                                3'b111:$display("%m\tWR = 14^2(196 cycles)");
504
                                                                        endcase
505
                                                                end//end MR0
506
                                                                2'b01:begin //MR1
507
                                                                end//end MR1
508
                                                                2'b10:begin //MR2
509
                                                                end//end MR2
510
                                                                2'b11:begin //MR3
511
                                                                end//end MR3
512
                                                        endcase //end which MRS
513
 
514
 
515
                                                end //end MRS
516 2 slai
        /*OPCODE_NOP            :begin
517 4 slai
                                        /$display("%m: at time %t WRITE ",$time);
518
                                end
519 2 slai
        */
520
        /*
521
        OPCODE_READ             :begin
522 4 slai
                                        $display("%m: at time %t READ - BANK[%x]\tROW[%x]\tCOL[%x]",$time,ba,last_row,a);
523
                                end
524 2 slai
        OPCODE_WRITE            :begin
525 4 slai
                                        $display("%m: at time %t WRITE - BANK[%x]\tROW[%x],\tCOL[%x]",$time,ba,last_row,a);
526
                                end
527 2 slai
        */
528 4 slai
        OPCODE_ZQC              :begin
529
                                        $display("%m: at time %t ZQC ",$time);
530
                                end
531 2 slai
        endcase
532
 
533
end // end always@(*)
534
/* end utility*/
535
 
536
endmodule

powered by: WebSVN 2.1.0

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