updated wiki url
[debian/gnuradio] / usrp2 / fpga / control_lib / dcache.v
1
2 module dcache
3   #(parameter AWIDTH=14,
4     parameter CWIDTH=6)
5     (input wb_clk_i,
6      input wb_rst_i,
7      
8      input [AWIDTH-1:0] dwb_adr_i,
9      input dwb_stb_i,
10      input dwb_we_i,
11      input [3:0] dwb_sel_i,
12      input [31:0] dwb_dat_i,
13      output [31:0] dwb_dat_o,
14      output dwb_ack_o,
15      
16      input [31:0] dram_dat_i,
17      output [31:0] dram_dat_o,
18      output [AWIDTH-1:0] dram_adr_o,
19      output dram_we_o,
20      output dram_en_o,
21      output [3:0] dram_sel_o );
22
23    localparam TAGWIDTH = AWIDTH-CWIDTH-2;
24    reg        stb_d1, ack_d1, miss_d1;
25    reg [AWIDTH-1:0] held_addr;
26    reg [31:0]       ddata [0:(1<<CWIDTH)-1];
27    reg [TAGWIDTH-1:0] dtags [0:(1<<CWIDTH)-1];
28    reg                dvalid [0:(1<<CWIDTH)-1];
29    
30    wire [CWIDTH-1:0]  rd_line, wr_line;
31    wire [TAGWIDTH-1:0] wr_tags;
32    wire                cache_write, invalidate;
33    wire [31:0]         wr_data;
34    
35    // /////////////////////////////////////
36    // Write into cache
37    integer            i;
38    always @(posedge wb_clk_i)
39      if(wb_rst_i)
40        for(i=0;i<(1<<CWIDTH);i=i+1)
41          dvalid[i] <= 0;
42      else
43        if(invalidate)
44          dvalid[wr_line] <= 1'b0;
45        else if(cache_write)
46          dvalid[wr_line] <= 1'b1;
47    
48    always @(posedge wb_clk_i)
49      if(cache_write)
50        begin
51           ddata[wr_line] <= wr_data;
52           dtags[wr_line] <= wr_tags;
53        end
54    
55    // //////////////////////////////////////
56    // Read from Cache
57    wire [TAGWIDTH-1:0] tag_out = dtags[rd_line];
58    wire                valid_out = dvalid[rd_line];
59    wire [31:0]         data_out = ddata[rd_line];
60    wire                cache_hit = valid_out & (tag_out == dwb_adr_i[AWIDTH-1:CWIDTH+2]);
61    wire                cache_miss = ~cache_hit;
62
63    // //////////////////////////////////////
64    // Handle 1-cycle delay of Block-RAM
65    always @(posedge wb_clk_i)
66      if(wb_rst_i)
67        stb_d1 <= 0;
68      else
69        stb_d1 <= dwb_stb_i;
70    
71    always @(posedge wb_clk_i)
72      if(wb_rst_i)
73        held_addr <= 0;
74      else
75        held_addr <= dwb_adr_i;
76    
77    always @(posedge wb_clk_i) 
78      if(wb_rst_i)
79        ack_d1 <= 1'b0;
80      else 
81        ack_d1 <= dwb_ack_o;
82
83    always @(posedge wb_clk_i) 
84      if(wb_rst_i)
85        miss_d1 <= 0;
86      else 
87        miss_d1 <= cache_miss;
88
89 `define DC_NOCACHE
90 //`define DC_BASIC
91 //`define DC_FORWARDING_DP
92 //`define DC_FORWARDING_SP
93 //`define DC_PREFETCH
94
95 `ifdef DC_NOCACHE
96    assign              dwb_dat_o = dram_dat_i;
97    assign              dwb_ack_o = dwb_stb_i & (dwb_we_i | (stb_d1 & ~ack_d1));
98    assign              dram_adr_o = dwb_adr_i;
99    assign              dram_en_o = dwb_stb_i;
100    assign              dram_dat_o = dwb_dat_i;
101    assign              dram_we_o = dwb_we_i;
102    assign              dram_sel_o = dwb_sel_i;         
103    assign              rd_line = 0;
104    assign              wr_line = 0;
105    assign              wr_tags = 0;
106    assign              wr_data = 0;
107    assign              cache_write = 0;
108    assign              invalidate = 0;         
109 `endif
110    
111 `ifdef DC_BASIC    // Very basic, no forwarding, 2 wait states on miss
112    assign              dwb_dat_o = data_out;
113    assign              dwb_ack_o = dwb_stb_i & cache_hit;
114    assign              dram_adr_o = dwb_adr_i;
115    assign              dram_en_o = dwb_stb_i;
116    assign              dram_dat_o = dwb_dat_i;
117    assign              dram_we_o = dwb_we_i;
118    assign              dram_sel_o = dwb_sel_i;         
119    assign              rd_line = dwb_adr_i[CWIDTH+1:2];
120    assign              wr_line = rd_line;
121    assign              wr_tags = dwb_adr_i[AWIDTH-1:CWIDTH+2];
122    assign              wr_data = dwb_we_i ? dwb_dat_i : dram_dat_i;
123    assign              cache_write = dwb_stb_i & (dwb_we_i | (stb_d1 & miss_d1));
124    assign              invalidate = dwb_we_i & ~(&dwb_sel_i);
125 `endif
126    
127 `ifdef DC_FORWARDING_DP   // Simple forwarding, 1 wait state on miss, dual-port ram
128    assign              dwb_dat_o = cache_hit ? data_out : dram_dat_i;
129    assign              dwb_ack_o = dwb_stb_i & (cache_hit | (stb_d1 & ~ack_d1));
130    assign              dram_adr_o = dwb_adr_i;
131    assign              dram_en_o = 1'b1;
132    assign              dram_dat_o = dwb_dat_i;
133    assign              dram_we_o = dwb_we_i;
134    assign              dram_sel_o = dwb_sel_i;         
135    assign              rd_line = dwb_adr_i[CWIDTH+1:2];
136    assign              wr_line = held_addr[CWIDTH+1:2];
137    assign              wr_tags = held_addr[AWIDTH-1:CWIDTH+2];         
138    assign              wr_data = dram_dat_i;
139    assign              cache_write = dwb_stb_i & stb_d1 & miss_d1 & ~ack_d1;
140    assign              invalidate = 0;         
141 `endif
142
143 `ifdef DC_FORWARDING_SP   // Simple forwarding, 1 wait state on miss, single-port ram
144    assign              dwb_dat_o = cache_hit ? data_out : dram_dat_i;
145    assign              dwb_ack_o = dwb_stb_i & (cache_hit | (stb_d1 & ~ack_d1));
146    assign              dram_adr_o = dwb_adr_i;
147    assign              dram_en_o = 1'b1;
148    assign              dram_dat_o = dwb_dat_i;
149    assign              dram_we_o = dwb_we_i;
150    assign              dram_sel_o = dwb_sel_i;         
151    assign              rd_line = dwb_adr_i[CWIDTH+1:2];
152    assign              wr_line = rd_line;
153    assign              wr_tags = dwb_adr_i[AWIDTH-1:CWIDTH+2];
154    assign              wr_data = dram_dat_i;
155    assign              cache_write = dwb_stb_i & stb_d1 & miss_d1 & ~ack_d1;
156    assign              invalidate = 0;         
157 `endif
158
159 `ifdef DC_PREFETCH   // Forwarding plus prefetch
160
161 `endif
162    
163    
164 endmodule // dcache
165