Root/lm32/logic/sakc/rtl/wb_ddr/wb_ddr.v

1//----------------------------------------------------------------------------
2// Wishbone DDR Controller
3//
4// (c) Joerg Bornschein (<jb@capsec.org>)
5//----------------------------------------------------------------------------
6
7`include "ddr_include.v"
8
9module wb_ddr
10#(
11    parameter clk_freq = 100000000,
12    parameter clk_multiply = 12,
13    parameter clk_divide = 5,
14    parameter phase_shift = 0,
15    parameter wait200_init = 26
16) (
17    input clk,
18    input reset,
19    // DDR ports
20    output [2:0] ddr_clk,
21    output [2:0] ddr_clk_n,
22    input ddr_clk_fb,
23    output ddr_ras_n,
24    output ddr_cas_n,
25    output ddr_we_n,
26    output [1:0] ddr_cke,
27    output [1:0] ddr_cs_n,
28    output [ `A_RNG] ddr_a,
29    output [ `BA_RNG] ddr_ba,
30    inout [ `DQ_RNG] ddr_dq,
31    inout [`DQS_RNG] ddr_dqs,
32    output [ `DM_RNG] ddr_dm,
33    // Wishbone Slave Interface
34    input [`WB_ADR_RNG] wb_adr_i,
35    input [`WB_DAT_RNG] wb_dat_i,
36    output reg [`WB_DAT_RNG] wb_dat_o,
37    input [`WB_SEL_RNG] wb_sel_i,
38    input wb_cyc_i,
39    input wb_stb_i,
40    input wb_we_i,
41    output reg wb_ack_o,
42    // XXX Temporary DCM control input XXX
43    output ps_ready,
44    input ps_up,
45    input ps_down,
46    // XXX probe wires XXX
47    output probe_clk,
48    input [7:0] probe_sel,
49    output reg [7:0] probe
50);
51
52//----------------------------------------------------------------------------
53// Wishbone handling
54//----------------------------------------------------------------------------
55wire wb_rd = wb_stb_i & wb_cyc_i & ~wb_we_i;
56wire wb_wr = wb_stb_i & wb_cyc_i & wb_we_i;
57
58wire [`WB_WORD_RNG] wb_adr_word = wb_adr_i[`WB_WORD_RNG]; // word in bufferline
59wire [`WB_SET_RNG] wb_adr_set = wb_adr_i[`WB_SET_RNG]; // index into wayX_ram
60wire [`WB_TAG_RNG] wb_adr_tag = wb_adr_i[`WB_TAG_RNG]; // more significant bits
61
62//----------------------------------------------------------------------------
63// TAG RAM (2-way set assioziative)
64//----------------------------------------------------------------------------
65wire [`TAG_LINE_RNG] tag_load;
66wire [`TAG_LINE_RNG] tag_store;
67wire tag_we;
68
69wire [`WB_TAG_RNG] tag_load_set0 = tag_load[`TAG_LINE_TAG0_RNG];
70wire [`WB_TAG_RNG] tag_load_set1 = tag_load[`TAG_LINE_TAG1_RNG];
71wire tag_load_dirty0 = tag_load[`TAG_LINE_DIRTY0_RNG];
72wire tag_load_dirty1 = tag_load[`TAG_LINE_DIRTY1_RNG];
73wire tag_load_lru = tag_load[`TAG_LINE_LRU_RNG];
74
75reg [`WB_TAG_RNG] tag_store_set0;
76reg [`WB_TAG_RNG] tag_store_set1;
77reg tag_store_dirty0;
78reg tag_store_dirty1;
79reg tag_store_lru;
80
81assign tag_store[`TAG_LINE_TAG0_RNG] = tag_store_set0;
82assign tag_store[`TAG_LINE_TAG1_RNG] = tag_store_set1;
83assign tag_store[`TAG_LINE_DIRTY0_RNG] = tag_store_dirty0;
84assign tag_store[`TAG_LINE_DIRTY1_RNG] = tag_store_dirty1;
85assign tag_store[`TAG_LINE_LRU_RNG] = tag_store_lru;
86
87wire [`WB_SET_RNG] ls_tag_adr;
88wire [`TAG_LINE_RNG] ls_tag_load;
89reg [`TAG_LINE_RNG] ls_tag_store;
90reg ls_tag_we;
91
92dpram #(
93    .adr_width( 7 ),
94    .dat_width( 33 )
95) tag_ram (
96    .clk ( clk ),
97    //
98    .adr0( wb_adr_set ),
99    .dout0( tag_load ),
100    .din0( tag_store ),
101    .we0( tag_we ),
102    //
103    .adr1( ls_tag_adr ),
104    .dout1( ls_tag_load ),
105    .din1( ls_tag_store ),
106    .we1( ls_tag_we )
107);
108
109wire tag_load_match0 = (tag_load_set0 == wb_adr_tag);
110wire tag_load_match1 = (tag_load_set1 == wb_adr_tag);
111wire tag_load_match = tag_load_match0 | tag_load_match1;
112
113//----------------------------------------------------------------------------
114// Buffer cache ram (2 ways)
115//----------------------------------------------------------------------------
116wire [8:0] wayX_adr = { wb_adr_set, wb_adr_word };
117
118wire [`WAY_LINE_RNG] way0_load, way1_load;
119wire [`WAY_LINE_RNG] wayX_store;
120
121wire [31:0] way0_load_dat = way0_load[`WAY_DAT_RNG];
122wire [31:0] way1_load_dat = way1_load[`WAY_DAT_RNG];
123wire [3:0] way0_load_valid = way0_load[`WAY_VALID_RNG];
124wire [3:0] way1_load_valid = way1_load[`WAY_VALID_RNG];
125
126wire way0_we;
127wire way1_we;
128reg [31:0] wayX_store_dat;
129reg [3:0] wayX_store_valid;
130
131assign wayX_store[`WAY_DAT_RNG] = wayX_store_dat;
132assign wayX_store[`WAY_VALID_RNG] = wayX_store_valid;
133
134wire [8:0] ls_wayX_adr;
135wire [`WAY_LINE_RNG] ls_way0_load;
136wire [`WAY_LINE_RNG] ls_way1_load;
137wire [`WAY_LINE_RNG] ls_wayX_store;
138wire ls_way0_we;
139wire ls_way1_we;
140reg ls_wayX_we;
141
142wire way0_sel_valid = ( (~way0_load_valid & wb_sel_i) == 'b0);
143wire way1_sel_valid = ( (~way1_load_valid & wb_sel_i) == 'b0);
144wire wayX_sel_valid = (tag_load_match0) ? way0_sel_valid : way1_sel_valid;
145
146// synthesis attribute ram_style of way0_ram is block
147dpram #(
148    .adr_width( 9 ),
149    .dat_width( 36 )
150) way0_ram (
151    .clk( clk ),
152    //
153    .adr0( wayX_adr ),
154    .dout0( way0_load ),
155    .din0( wayX_store ),
156    .we0( way0_we ),
157    //
158    .adr1( ls_wayX_adr ),
159    .dout1( ls_way0_load ),
160    .we1( ls_way0_we ),
161    .din1( ls_wayX_store )
162);
163
164// synthesis attribute ram_style of way1_ram is block
165dpram #(
166    .adr_width( 9 ),
167    .dat_width( 36 )
168) way1_ram (
169    .clk( clk ),
170    //
171    .adr0( wayX_adr ),
172    .dout0( way1_load ),
173    .din0( wayX_store ),
174    .we0( way1_we ),
175    //
176    .adr1( ls_wayX_adr ),
177    .dout1( ls_way1_load ),
178    .we1( ls_way1_we ),
179    .din1( ls_wayX_store )
180);
181
182//----------------------------------------------------------------------------
183// Write/update buffer cache from wishbone side
184//----------------------------------------------------------------------------
185wire store_to_way0 = tag_load_lru & ~tag_load_dirty0; // store new data into way0? XXX spill_done XXX
186wire store_to_way1 = ~tag_load_lru & ~tag_load_dirty1; // store new data into way1? XXX spill_done XXX
187wire store_to_way = store_to_way0 | store_to_way1;
188
189reg update_lru0; //
190reg update_lru1;
191
192reg update_way0; //
193reg update_way1;
194
195assign way0_we = update_way0;
196assign way1_we = update_way1;
197assign tag_we = way0_we | way1_we | update_lru0 | update_lru1;
198
199//----------------------------------------------------------------------------
200// MUX wayX_store input
201//----------------------------------------------------------------------------
202
203integer i;
204always @(*)
205begin
206/*
207    for(i=0; i<4; i=i+1) begin
208        if (wb_sel_i[i]) begin
209            wayX_store_dat[8*i+7:8*i] = wb_dat_i[8*i+7:8*i];
210            wayX_store_valid[i] = 1;
211        end else if (update_way0) begin
212            wayX_store_dat[8*i+7:8*i] = way0_load_dat[8*i+7:8*i];
213            wayX_store_valid[i] = way0_load_valid[i];
214        end else begin
215            wayX_store_dat[8*i+7:8*i] = way1_load_dat[8*i+7:8*i];
216            wayX_store_valid[i] = way1_load_valid[i];
217        end
218    end
219*/
220
221    if (wb_sel_i[0]) begin
222        wayX_store_dat[8*0+7:8*0] = wb_dat_i[8*0+7:8*0];
223        wayX_store_valid[0] = 1;
224    end else if (update_way0) begin
225        wayX_store_dat[8*0+7:8*0] = way0_load_dat[8*0+7:8*0];
226        wayX_store_valid[0] = way0_load_valid[0];
227    end else begin
228        wayX_store_dat[8*0+7:8*0] = way1_load_dat[8*0+7:8*0];
229        wayX_store_valid[0] = way1_load_valid[0];
230    end
231
232    if (wb_sel_i[1]) begin
233        wayX_store_dat[8*1+7:8*1] = wb_dat_i[8*1+7:8*1];
234        wayX_store_valid[1] = 1;
235    end else if (update_way0) begin
236        wayX_store_dat[8*1+7:8*1] = way0_load_dat[8*1+7:8*1];
237        wayX_store_valid[1] = way0_load_valid[1];
238    end else begin
239        wayX_store_dat[8*1+7:8*1] = way1_load_dat[8*1+7:8*1];
240        wayX_store_valid[1] = way1_load_valid[1];
241    end
242
243    if (wb_sel_i[2]) begin
244        wayX_store_dat[8*2+7:8*2] = wb_dat_i[8*2+7:8*2];
245        wayX_store_valid[2] = 1;
246    end else if (update_way0) begin
247        wayX_store_dat[8*2+7:8*2] = way0_load_dat[8*2+7:8*2];
248        wayX_store_valid[2] = way0_load_valid[2];
249    end else begin
250        wayX_store_dat[8*2+7:8*2] = way1_load_dat[8*2+7:8*2];
251        wayX_store_valid[2] = way1_load_valid[2];
252    end
253
254    if (wb_sel_i[3]) begin
255        wayX_store_dat[8*3+7:8*3] = wb_dat_i[8*3+7:8*3];
256        wayX_store_valid[3] = 1;
257    end else if (update_way0) begin
258        wayX_store_dat[8*3+7:8*3] = way0_load_dat[8*3+7:8*3];
259        wayX_store_valid[3] = way0_load_valid[3];
260    end else begin
261        wayX_store_dat[8*3+7:8*3] = way1_load_dat[8*3+7:8*3];
262        wayX_store_valid[3] = way1_load_valid[3];
263    end
264end
265
266always @(*)
267begin
268    if (update_way0) begin
269        tag_store_set0 = wb_adr_tag;
270        tag_store_dirty0 = 1;
271    end else begin
272        tag_store_set0 = tag_load_set0;
273        tag_store_dirty0 = tag_load_dirty0;
274    end
275
276    if (update_way1) begin
277        tag_store_set1 = wb_adr_tag;
278        tag_store_dirty1 = 1;
279    end else begin
280        tag_store_set1 = tag_load_set1;
281        tag_store_dirty1 = tag_load_dirty1;
282    end
283
284    if (update_lru0)
285        tag_store_lru = 0;
286    else if (update_lru1)
287        tag_store_lru = 1;
288    else
289        tag_store_lru = tag_load_lru;
290end
291
292//----------------------------------------------------------------------------
293// Wishbone FSM
294//----------------------------------------------------------------------------
295reg ls_fill;
296reg ls_spill;
297reg ls_way;
298wire ls_busy;
299
300reg [`WB_TAG_RNG] ls_adr_tag;
301reg [`WB_SET_RNG] ls_adr_set;
302reg [`WB_WORD_RNG] ls_adr_word;
303
304reg [2:0] state;
305
306parameter s_idle = 0;
307parameter s_read = 1;
308parameter s_rspill = 2;
309parameter s_rfill = 3;
310parameter s_write = 4;
311parameter s_wspill = 5;
312
313// Syncronous part of FSM
314always @(posedge clk)
315begin
316    if (reset) begin
317        state <= s_idle;
318        ls_spill <= 0;
319        ls_fill <= 0;
320        ls_way <= 0;
321    end else begin
322        ls_fill <= 0;
323        ls_spill <= 0;
324
325        case (state)
326        s_idle: begin
327            if (wb_rd)
328                state <= s_read;
329
330            if (wb_wr)
331                state <= s_write;
332        end
333        s_read: begin
334            if ((tag_load_match0 & way0_sel_valid) | (tag_load_match1 & way1_sel_valid)) begin
335                state <= s_idle;
336            end else if (store_to_way & ~ls_busy) begin
337                state <= s_rfill;
338                ls_fill <= 1;
339                ls_way <= ~tag_load_lru;
340                ls_adr_tag <= wb_adr_tag;
341                ls_adr_set <= wb_adr_set;
342            end else if (~ls_busy) begin
343                state <= s_rspill;
344                ls_spill <= 1;
345                ls_way <= ~tag_load_lru;
346                ls_adr_set <= wb_adr_set;
347                if (tag_load_lru == 1)
348                    ls_adr_tag <= tag_load_set0;
349                else
350                    ls_adr_tag <= tag_load_set1;
351            end
352        end
353        s_rspill: begin
354            if (~ls_busy) begin
355                state <= s_rfill;
356                ls_fill <= 1;
357                ls_way <= ~tag_load_lru;
358                ls_adr_tag <= wb_adr_tag;
359                ls_adr_set <= wb_adr_set;
360            end
361        end
362        s_rfill: begin
363            if (tag_load_match & wayX_sel_valid)
364                state <= s_idle;
365        end
366        s_write: begin
367            if (tag_load_match | store_to_way) begin
368                state <= s_idle;
369            end else if (~ls_busy) begin
370                state <= s_wspill;
371                ls_spill <= 1;
372                ls_way <= ~tag_load_lru;
373                ls_adr_set <= wb_adr_set;
374                if (tag_load_lru == 1)
375                    ls_adr_tag <= tag_load_set0;
376                else
377                    ls_adr_tag <= tag_load_set1;
378            end
379        end
380        s_wspill: begin
381            if (tag_load_match | store_to_way) begin
382                state <= s_idle;
383            end
384        end
385        default:
386            state <= s_idle;
387        endcase
388    end
389end
390
391// Asyncronous part of FSM
392always @(*)
393begin
394    update_lru0 <= 0;
395    update_lru1 <= 0;
396    update_way0 <= 0;
397    update_way1 <= 0;
398    wb_dat_o <= 0;
399    wb_ack_o <= 0;
400
401    case (state)
402    s_idle: begin end
403    s_read: begin
404        if (tag_load_match0 & way0_sel_valid) begin
405            update_lru0 <= 1;
406            wb_dat_o <= way0_load_dat;
407            wb_ack_o <= 1;
408        end else if (tag_load_match1 & way1_sel_valid) begin
409            update_lru1 <= 1;
410            wb_dat_o <= way1_load_dat;
411            wb_ack_o <= 1;
412        end
413    end
414    s_write: begin
415        if (tag_load_match0 | store_to_way0) begin
416            update_lru0 <= 1;
417            update_way0 <= 1;
418            wb_ack_o <= 1;
419        end else if (tag_load_match1 | store_to_way1) begin
420            update_lru1 <= 1;
421            update_way1 <= 1;
422            wb_ack_o <= 1;
423        end
424    end
425    endcase
426end
427
428    
429
430//----------------------------------------------------------------------------
431// DDR Controller Engine (including clkgen, [rw]-path)
432//----------------------------------------------------------------------------
433reg fml_rd;
434reg fml_wr;
435wire fml_done;
436wire [`FML_ADR_RNG] fml_adr;
437wire [`FML_DAT_RNG] fml_wdat;
438wire [`FML_BE_RNG] fml_wbe;
439reg fml_wnext;
440reg fml_wnext2;
441wire fml_rempty;
442reg fml_rnext;
443wire [`FML_DAT_RNG] fml_rdat;
444
445ddr_ctrl #(
446    .phase_shift( phase_shift ),
447    .clk_multiply( clk_multiply ),
448    .clk_divide( clk_divide ),
449    .wait200_init( wait200_init )
450) ctrl0 (
451    .clk( clk ),
452    .reset( reset ),
453    // DDR Ports
454    .ddr_clk( ddr_clk ),
455    .ddr_clk_n( ddr_clk_n ),
456    .ddr_clk_fb( ddr_clk_fb ),
457    .ddr_ras_n( ddr_ras_n ),
458    .ddr_cas_n( ddr_cas_n ),
459    .ddr_we_n( ddr_we_n ),
460    .ddr_cke( ddr_cke ),
461    .ddr_cs_n( ddr_cs_n ),
462    .ddr_a( ddr_a ),
463    .ddr_ba( ddr_ba ),
464    .ddr_dq( ddr_dq ),
465    .ddr_dqs( ddr_dqs ),
466    .ddr_dm( ddr_dm ),
467    // FML (FastMemoryLink)
468    .fml_rd( fml_rd ),
469    .fml_wr( fml_wr ),
470    .fml_done( fml_done ),
471    .fml_adr( fml_adr ),
472    .fml_wdat( fml_wdat ),
473    .fml_wbe( fml_wbe ),
474    .fml_wnext( fml_wnext2 ),
475    .fml_rempty( fml_rempty ),
476    .fml_rdat( fml_rdat ),
477    .fml_rnext( fml_rnext ),
478    // DCM phase shift control
479    .ps_ready( ps_ready ),
480    .ps_up( ps_up ),
481    .ps_down( ps_down )
482);
483
484assign fml_adr = { ls_adr_tag, ls_adr_set };
485
486assign fml_wdat = (ls_way) ? ls_way1_load[`WAY_DAT_RNG] :
487                              ls_way0_load[`WAY_DAT_RNG];
488
489assign fml_wbe = (ls_way) ? ls_way1_load[`WAY_VALID_RNG] :
490                              ls_way0_load[`WAY_VALID_RNG];
491
492assign ls_tag_adr = { ls_adr_set };
493assign ls_wayX_adr = { ls_adr_set, ls_adr_word };
494assign ls_way0_we = ls_wayX_we & ~ls_way;
495assign ls_way1_we = ls_wayX_we & ls_way;
496
497assign ls_wayX_store[`WAY_DAT_RNG] = fml_rdat;
498assign ls_wayX_store[`WAY_VALID_RNG] = 4'b1111;
499
500
501//----------------------------------------------------------------------------
502// LS (Load and Store) Engine
503//----------------------------------------------------------------------------
504parameter l_idle = 0;
505parameter l_fill = 1;
506parameter l_spill = 2;
507parameter l_waitdone = 3;
508
509reg [2:0] ls_state;
510assign ls_busy = (ls_state != l_idle) || ls_fill || ls_spill;
511
512// Syncronous part FSM
513always @(posedge clk)
514begin
515    if (reset) begin
516        ls_state <= l_idle;
517        ls_adr_word <= 0;
518        fml_wr <= 0;
519        fml_rd <= 0;
520    end else begin
521        fml_wnext2 <= fml_wnext;
522
523        case (ls_state)
524        l_idle: begin
525            ls_adr_word <= 0;
526
527            if (ls_spill) begin
528                ls_state <= l_spill;
529                ls_adr_word <= ls_adr_word + 1;
530            end
531            if (ls_fill) begin
532                ls_state <= l_fill;
533                fml_rd <= 1;
534            end
535        end
536        l_spill: begin
537            ls_adr_word <= ls_adr_word + 1;
538
539            if (ls_adr_word == 3) begin
540                ls_state <= l_waitdone;
541                fml_wr <= 1;
542            end
543        end
544        l_waitdone: begin
545            ls_adr_word <= 0;
546            
547            if (fml_done) begin
548                ls_state <= l_idle;
549                fml_wr <= 0;
550            end
551        end
552        l_fill: begin
553            if (fml_done)
554                fml_rd <= 0;
555
556            if (~fml_rempty)
557                ls_adr_word <= ls_adr_word + 1;
558
559            if (~fml_rempty & (ls_adr_word == 3))
560                ls_state <= l_idle;
561        end
562        endcase
563    end
564end
565
566always @(*)
567begin
568    fml_wnext <= 0;
569    fml_rnext <= 0;
570    ls_tag_we <= 0;
571    ls_tag_store <= ls_tag_load;
572    ls_wayX_we <= 0;
573
574    case (ls_state)
575    l_idle: begin
576        if (ls_spill) begin
577            fml_wnext <= 1;
578        end
579    end
580    l_spill: begin
581        fml_wnext <= 1;
582    end
583    l_waitdone: begin
584        if (ls_way == 0)
585            ls_tag_store[`TAG_LINE_DIRTY0_RNG] <= 0;
586        else
587            ls_tag_store[`TAG_LINE_DIRTY1_RNG] <= 0;
588
589        if (fml_done)
590            ls_tag_we <= 1;
591    end
592    l_fill: begin
593        if (ls_way == 0) begin
594            ls_tag_store[`TAG_LINE_DIRTY0_RNG] <= 0;
595            ls_tag_store[`TAG_LINE_TAG0_RNG] <= ls_adr_tag;
596        end else begin
597            ls_tag_store[`TAG_LINE_DIRTY1_RNG] <= 0;
598            ls_tag_store[`TAG_LINE_TAG1_RNG] <= ls_adr_tag;
599        end
600
601        if (~fml_rempty) begin
602            ls_wayX_we <= 1;
603            fml_rnext <= 1;
604        end
605
606        if (~fml_rempty & (ls_adr_word == 3))
607            ls_tag_we <= 1;
608    end
609    endcase
610end
611
612always @(posedge clk)
613begin
614    if (ls_fill)
615        $display ("At time %t WB_DDR fill cacheline: TAG = %h, SET = %h)", $time, ls_adr_tag, ls_adr_set);
616
617    if (ls_spill)
618        $display ("At time %t WB_DDR spill cacheline: TAG = %h, SET = %h)", $time, ls_adr_tag, ls_adr_set);
619end
620
621endmodule
622

Archive Download this file

Branches:
master



interactive