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 2

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

powered by: WebSVN 2.1.0

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