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

Subversion Repositories hpdmc

[/] [hpdmc/] [trunk/] [hpdmc_ddr32/] [rtl/] [hpdmc_mgmt.v] - Blame information for rev 21

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 21 lekernel
/*
2
 * Milkymist VJ SoC
3
 * Copyright (C) 2007, 2008, 2009 Sebastien Bourdeauducq
4
 *
5
 * This program is free software: you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation, version 3 of the License.
8
 *
9
 * This program is distributed in the hope that it will be useful,
10
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 * GNU General Public License for more details.
13
 *
14
 * You should have received a copy of the GNU General Public License
15
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16
 */
17
 
18
module hpdmc_mgmt #(
19
        parameter sdram_depth = 26,
20
        parameter sdram_columndepth = 9
21
) (
22
        input sys_clk,
23
        input sdram_rst,
24
 
25
        input [2:0] tim_rp,
26
        input [2:0] tim_rcd,
27
        input [10:0] tim_refi,
28
        input [3:0] tim_rfc,
29
 
30
        input stb,
31
        input we,
32
        input [sdram_depth-3-1:0] address, /* in 64-bit words */
33
        output reg ack,
34
 
35
        output reg read,
36
        output reg write,
37
        output [3:0] concerned_bank,
38
        input read_safe,
39
        input write_safe,
40
        input [3:0] precharge_safe,
41
 
42
        output sdram_cs_n,
43
        output sdram_we_n,
44
        output sdram_cas_n,
45
        output sdram_ras_n,
46
        output [12:0] sdram_adr,
47
        output [1:0] sdram_ba
48
);
49
 
50
/*
51
 * Address Mapping :
52
 * |    ROW ADDRESS   |    BANK NUMBER    |  COL ADDRESS  | for 32-bit words
53
 * |depth-1 coldepth+2|coldepth+1 coldepth|coldepth-1    0|
54
 * (depth for 32-bit words, which is sdram_depth-2)
55
 */
56
 
57
parameter rowdepth = sdram_depth-2-1-(sdram_columndepth+2)+1;
58
 
59
wire [sdram_depth-2-1:0] address32 = {address, 1'b0};
60
 
61
wire [sdram_columndepth-1:0] col_address = address32[sdram_columndepth-1:0];
62
wire [1:0] bank_address = address32[sdram_columndepth+1:sdram_columndepth];
63
wire [rowdepth-1:0] row_address = address32[sdram_depth-2-1:sdram_columndepth+2];
64
 
65
reg [3:0] bank_address_onehot;
66
always @(*) begin
67
        case(bank_address)
68
                2'b00: bank_address_onehot <= 4'b0001;
69
                2'b01: bank_address_onehot <= 4'b0010;
70
                2'b10: bank_address_onehot <= 4'b0100;
71
                2'b11: bank_address_onehot <= 4'b1000;
72
        endcase
73
end
74
 
75
/* Track open rows */
76
reg [3:0] has_openrow;
77
reg [rowdepth-1:0] openrows[0:3];
78
reg [3:0] track_close;
79
reg [3:0] track_open;
80
 
81
always @(posedge sys_clk) begin
82
        if(sdram_rst) begin
83
                has_openrow = 4'h0;
84
        end else begin
85
                has_openrow = (has_openrow | track_open) & ~track_close;
86
 
87
                if(track_open[0]) openrows[0] <= row_address;
88
                if(track_open[1]) openrows[1] <= row_address;
89
                if(track_open[2]) openrows[2] <= row_address;
90
                if(track_open[3]) openrows[3] <= row_address;
91
        end
92
end
93
 
94
/* Bank precharge safety */
95
assign concerned_bank = bank_address_onehot;
96
wire current_precharge_safe =
97
         (precharge_safe[0] | ~bank_address_onehot[0])
98
        &(precharge_safe[1] | ~bank_address_onehot[1])
99
        &(precharge_safe[2] | ~bank_address_onehot[2])
100
        &(precharge_safe[3] | ~bank_address_onehot[3]);
101
 
102
 
103
/* Check for page hits */
104
wire bank_open = has_openrow[bank_address];
105
wire page_hit = bank_open & (openrows[bank_address] == row_address);
106
 
107
/* Address drivers */
108
reg sdram_adr_loadrow;
109
reg sdram_adr_loadcol;
110
reg sdram_adr_loadA10;
111
assign sdram_adr =
112
         ({13{sdram_adr_loadrow}}       & row_address)
113
        |({13{sdram_adr_loadcol}}       & col_address)
114
        |({13{sdram_adr_loadA10}}       & 13'd1024);
115
 
116
assign sdram_ba = bank_address;
117
 
118
/* Command drivers */
119
reg sdram_cs;
120
reg sdram_we;
121
reg sdram_cas;
122
reg sdram_ras;
123
assign sdram_cs_n = ~sdram_cs;
124
assign sdram_we_n = ~sdram_we;
125
assign sdram_cas_n = ~sdram_cas;
126
assign sdram_ras_n = ~sdram_ras;
127
 
128
/* Timing counters */
129
 
130
/* The number of clocks we must wait following a PRECHARGE command (usually tRP). */
131
reg [2:0] precharge_counter;
132
reg reload_precharge_counter;
133
wire precharge_done = (precharge_counter == 3'd0);
134
always @(posedge sys_clk) begin
135
        if(reload_precharge_counter)
136
                precharge_counter <= tim_rp;
137
        else if(~precharge_done)
138
                precharge_counter <= precharge_counter - 3'd1;
139
end
140
 
141
/* The number of clocks we must wait following an ACTIVATE command (usually tRCD). */
142
reg [2:0] activate_counter;
143
reg reload_activate_counter;
144
wire activate_done = (activate_counter == 3'd0);
145
always @(posedge sys_clk) begin
146
        if(reload_activate_counter)
147
                activate_counter <= tim_rcd;
148
        else if(~activate_done)
149
                activate_counter <= activate_counter - 3'd1;
150
end
151
 
152
/* The number of clocks we have left before we must refresh one row in the SDRAM array (usually tREFI). */
153
reg [10:0] refresh_counter;
154
reg reload_refresh_counter;
155
wire must_refresh = refresh_counter == 11'd0;
156
always @(posedge sys_clk) begin
157
        if(sdram_rst)
158
                refresh_counter <= 11'd0;
159
        else begin
160
                if(reload_refresh_counter)
161
                        refresh_counter <= tim_refi;
162
                else if(~must_refresh)
163
                        refresh_counter <= refresh_counter - 11'd1;
164
        end
165
end
166
 
167
/* The number of clocks we must wait following an AUTO REFRESH command (usually tRFC). */
168
reg [3:0] autorefresh_counter;
169
reg reload_autorefresh_counter;
170
wire autorefresh_done = (autorefresh_counter == 4'd0);
171
always @(posedge sys_clk) begin
172
        if(reload_autorefresh_counter)
173
                autorefresh_counter <= tim_rfc;
174
        else if(~autorefresh_done)
175
                autorefresh_counter <= autorefresh_counter - 4'd1;
176
end
177
 
178
/* FSM that pushes commands into the SDRAM */
179
 
180
reg [3:0] state;
181
reg [3:0] next_state;
182
 
183
parameter IDLE                  = 4'd0;
184
parameter ACTIVATE              = 4'd1;
185
parameter READ                  = 4'd2;
186
parameter WRITE                 = 4'd3;
187
parameter PRECHARGEALL          = 4'd4;
188
parameter AUTOREFRESH           = 4'd5;
189
parameter AUTOREFRESH_WAIT      = 4'd6;
190
 
191
always @(posedge sys_clk) begin
192
        if(sdram_rst)
193
                state <= IDLE;
194
        else begin
195
                //$display("state: %d -> %d", state, next_state);
196
                state <= next_state;
197
        end
198
end
199
 
200
always @(*) begin
201
        next_state = state;
202
 
203
        reload_precharge_counter = 1'b0;
204
        reload_activate_counter = 1'b0;
205
        reload_refresh_counter = 1'b0;
206
        reload_autorefresh_counter = 1'b0;
207
 
208
        sdram_cs = 1'b0;
209
        sdram_we = 1'b0;
210
        sdram_cas = 1'b0;
211
        sdram_ras = 1'b0;
212
 
213
        sdram_adr_loadrow = 1'b0;
214
        sdram_adr_loadcol = 1'b0;
215
        sdram_adr_loadA10 = 1'b0;
216
 
217
        track_close = 4'b0000;
218
        track_open = 4'b0000;
219
 
220
        read = 1'b0;
221
        write = 1'b0;
222
 
223
        ack = 1'b0;
224
 
225
        case(state)
226
                IDLE: begin
227
                        if(must_refresh)
228
                                next_state = PRECHARGEALL;
229
                        else begin
230
                                if(stb) begin
231
                                        if(page_hit) begin
232
                                                if(we) begin
233
                                                        if(write_safe) begin
234
                                                                /* Write */
235
                                                                sdram_cs = 1'b1;
236
                                                                sdram_ras = 1'b0;
237
                                                                sdram_cas = 1'b1;
238
                                                                sdram_we = 1'b1;
239
                                                                sdram_adr_loadcol = 1'b1;
240
 
241
                                                                write = 1'b1;
242
                                                                ack = 1'b1;
243
                                                        end
244
                                                end else begin
245
                                                        if(read_safe) begin
246
                                                                /* Read */
247
                                                                sdram_cs = 1'b1;
248
                                                                sdram_ras = 1'b0;
249
                                                                sdram_cas = 1'b1;
250
                                                                sdram_we = 1'b0;
251
                                                                sdram_adr_loadcol = 1'b1;
252
 
253
                                                                read = 1'b1;
254
                                                                ack = 1'b1;
255
                                                        end
256
                                                end
257
                                        end else begin
258
                                                if(bank_open) begin
259
                                                        if(current_precharge_safe) begin
260
                                                                /* Precharge Bank */
261
                                                                sdram_cs = 1'b1;
262
                                                                sdram_ras = 1'b1;
263
                                                                sdram_cas = 1'b0;
264
                                                                sdram_we = 1'b1;
265
 
266
                                                                track_close = bank_address_onehot;
267
                                                                reload_precharge_counter = 1'b1;
268
                                                                next_state = ACTIVATE;
269
                                                        end
270
                                                end else begin
271
                                                        /* Activate */
272
                                                        sdram_cs = 1'b1;
273
                                                        sdram_ras = 1'b1;
274
                                                        sdram_cas = 1'b0;
275
                                                        sdram_we = 1'b0;
276
                                                        sdram_adr_loadrow = 1'b1;
277
 
278
                                                        track_open = bank_address_onehot;
279
                                                        reload_activate_counter = 1'b1;
280
                                                        if(we)
281
                                                                next_state = WRITE;
282
                                                        else
283
                                                                next_state = READ;
284
                                                end
285
                                        end
286
                                end
287
                        end
288
                end
289
 
290
                ACTIVATE: begin
291
                        if(precharge_done) begin
292
                                sdram_cs = 1'b1;
293
                                sdram_ras = 1'b1;
294
                                sdram_cas = 1'b0;
295
                                sdram_we = 1'b0;
296
                                sdram_adr_loadrow = 1'b1;
297
 
298
                                track_open = bank_address_onehot;
299
                                reload_activate_counter = 1'b1;
300
                                if(we)
301
                                        next_state = WRITE;
302
                                else
303
                                        next_state = READ;
304
                        end
305
                end
306
                READ: begin
307
                        if(activate_done) begin
308
                                if(read_safe) begin
309
                                        sdram_cs = 1'b1;
310
                                        sdram_ras = 1'b0;
311
                                        sdram_cas = 1'b1;
312
                                        sdram_we = 1'b0;
313
                                        sdram_adr_loadcol = 1'b1;
314
 
315
                                        read = 1'b1;
316
                                        ack = 1'b1;
317
                                        next_state = IDLE;
318
                                end
319
                        end
320
                end
321
                WRITE: begin
322
                        if(activate_done) begin
323
                                if(write_safe) begin
324
                                        sdram_cs = 1'b1;
325
                                        sdram_ras = 1'b0;
326
                                        sdram_cas = 1'b1;
327
                                        sdram_we = 1'b1;
328
                                        sdram_adr_loadcol = 1'b1;
329
 
330
                                        write = 1'b1;
331
                                        ack = 1'b1;
332
                                        next_state = IDLE;
333
                                end
334
                        end
335
                end
336
 
337
                PRECHARGEALL: begin
338
                        if(precharge_safe == 4'b1111) begin
339
                                sdram_cs = 1'b1;
340
                                sdram_ras = 1'b1;
341
                                sdram_cas = 1'b0;
342
                                sdram_we = 1'b1;
343
                                sdram_adr_loadA10 = 1'b1;
344
 
345
                                reload_precharge_counter = 1'b1;
346
 
347
                                track_close = 4'b1111;
348
 
349
                                next_state = AUTOREFRESH;
350
                        end
351
                end
352
                AUTOREFRESH: begin
353
                        if(precharge_done) begin
354
                                sdram_cs = 1'b1;
355
                                sdram_ras = 1'b1;
356
                                sdram_cas = 1'b1;
357
                                sdram_we = 1'b0;
358
                                reload_refresh_counter = 1'b1;
359
                                reload_autorefresh_counter = 1'b1;
360
                                next_state = AUTOREFRESH_WAIT;
361
                        end
362
                end
363
                AUTOREFRESH_WAIT: begin
364
                        if(autorefresh_done)
365
                                next_state = IDLE;
366
                end
367
 
368
        endcase
369
end
370
 
371
endmodule

powered by: WebSVN 2.1.0

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