1// 2// Copyright 2011 Ettus Research LLC 3// 4// This program is free software: you can redistribute it and/or modify 5// it under the terms of the GNU General Public License as published by 6// the Free Software Foundation, either version 3 of the License, or 7// (at your option) any later version. 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 19module dcache 20 #(parameter AWIDTH=14, 21 parameter CWIDTH=6) 22 (input wb_clk_i, 23 input wb_rst_i, 24 25 input [AWIDTH-1:0] dwb_adr_i, 26 input dwb_stb_i, 27 input dwb_we_i, 28 input [3:0] dwb_sel_i, 29 input [31:0] dwb_dat_i, 30 output [31:0] dwb_dat_o, 31 output dwb_ack_o, 32 33 input [31:0] dram_dat_i, 34 output [31:0] dram_dat_o, 35 output [AWIDTH-1:0] dram_adr_o, 36 output dram_we_o, 37 output dram_en_o, 38 output [3:0] dram_sel_o ); 39 40 localparam TAGWIDTH = AWIDTH-CWIDTH-2; 41 reg stb_d1, ack_d1, miss_d1; 42 reg [AWIDTH-1:0] held_addr; 43 reg [31:0] ddata [0:(1<<CWIDTH)-1]; 44 reg [TAGWIDTH-1:0] dtags [0:(1<<CWIDTH)-1]; 45 reg dvalid [0:(1<<CWIDTH)-1]; 46 47 wire [CWIDTH-1:0] rd_line, wr_line; 48 wire [TAGWIDTH-1:0] wr_tags; 49 wire cache_write, invalidate; 50 wire [31:0] wr_data; 51 52 // ///////////////////////////////////// 53 // Write into cache 54 integer i; 55 always @(posedge wb_clk_i) 56 if(wb_rst_i) 57 for(i=0;i<(1<<CWIDTH);i=i+1) 58 dvalid[i] <= 0; 59 else 60 if(invalidate) 61 dvalid[wr_line] <= 1'b0; 62 else if(cache_write) 63 dvalid[wr_line] <= 1'b1; 64 65 always @(posedge wb_clk_i) 66 if(cache_write) 67 begin 68 ddata[wr_line] <= wr_data; 69 dtags[wr_line] <= wr_tags; 70 end 71 72 // ////////////////////////////////////// 73 // Read from Cache 74 wire [TAGWIDTH-1:0] tag_out = dtags[rd_line]; 75 wire valid_out = dvalid[rd_line]; 76 wire [31:0] data_out = ddata[rd_line]; 77 wire cache_hit = valid_out & (tag_out == dwb_adr_i[AWIDTH-1:CWIDTH+2]); 78 wire cache_miss = ~cache_hit; 79 80 // ////////////////////////////////////// 81 // Handle 1-cycle delay of Block-RAM 82 always @(posedge wb_clk_i) 83 if(wb_rst_i) 84 stb_d1 <= 0; 85 else 86 stb_d1 <= dwb_stb_i; 87 88 always @(posedge wb_clk_i) 89 if(wb_rst_i) 90 held_addr <= 0; 91 else 92 held_addr <= dwb_adr_i; 93 94 always @(posedge wb_clk_i) 95 if(wb_rst_i) 96 ack_d1 <= 1'b0; 97 else 98 ack_d1 <= dwb_ack_o; 99 100 always @(posedge wb_clk_i) 101 if(wb_rst_i) 102 miss_d1 <= 0; 103 else 104 miss_d1 <= cache_miss; 105 106`define DC_NOCACHE 107//`define DC_BASIC 108//`define DC_FORWARDING_DP 109//`define DC_FORWARDING_SP 110//`define DC_PREFETCH 111 112`ifdef DC_NOCACHE 113 assign dwb_dat_o = dram_dat_i; 114 assign dwb_ack_o = dwb_stb_i & (dwb_we_i | (stb_d1 & ~ack_d1)); 115 assign dram_adr_o = dwb_adr_i; 116 assign dram_en_o = dwb_stb_i; 117 assign dram_dat_o = dwb_dat_i; 118 assign dram_we_o = dwb_we_i; 119 assign dram_sel_o = dwb_sel_i; 120 assign rd_line = 0; 121 assign wr_line = 0; 122 assign wr_tags = 0; 123 assign wr_data = 0; 124 assign cache_write = 0; 125 assign invalidate = 0; 126`endif 127 128`ifdef DC_BASIC // Very basic, no forwarding, 2 wait states on miss 129 assign dwb_dat_o = data_out; 130 assign dwb_ack_o = dwb_stb_i & cache_hit; 131 assign dram_adr_o = dwb_adr_i; 132 assign dram_en_o = dwb_stb_i; 133 assign dram_dat_o = dwb_dat_i; 134 assign dram_we_o = dwb_we_i; 135 assign dram_sel_o = dwb_sel_i; 136 assign rd_line = dwb_adr_i[CWIDTH+1:2]; 137 assign wr_line = rd_line; 138 assign wr_tags = dwb_adr_i[AWIDTH-1:CWIDTH+2]; 139 assign wr_data = dwb_we_i ? dwb_dat_i : dram_dat_i; 140 assign cache_write = dwb_stb_i & (dwb_we_i | (stb_d1 & miss_d1)); 141 assign invalidate = dwb_we_i & ~(&dwb_sel_i); 142`endif 143 144`ifdef DC_FORWARDING_DP // Simple forwarding, 1 wait state on miss, dual-port ram 145 assign dwb_dat_o = cache_hit ? data_out : dram_dat_i; 146 assign dwb_ack_o = dwb_stb_i & (cache_hit | (stb_d1 & ~ack_d1)); 147 assign dram_adr_o = dwb_adr_i; 148 assign dram_en_o = 1'b1; 149 assign dram_dat_o = dwb_dat_i; 150 assign dram_we_o = dwb_we_i; 151 assign dram_sel_o = dwb_sel_i; 152 assign rd_line = dwb_adr_i[CWIDTH+1:2]; 153 assign wr_line = held_addr[CWIDTH+1:2]; 154 assign wr_tags = held_addr[AWIDTH-1:CWIDTH+2]; 155 assign wr_data = dram_dat_i; 156 assign cache_write = dwb_stb_i & stb_d1 & miss_d1 & ~ack_d1; 157 assign invalidate = 0; 158`endif 159 160`ifdef DC_FORWARDING_SP // Simple forwarding, 1 wait state on miss, single-port ram 161 assign dwb_dat_o = cache_hit ? data_out : dram_dat_i; 162 assign dwb_ack_o = dwb_stb_i & (cache_hit | (stb_d1 & ~ack_d1)); 163 assign dram_adr_o = dwb_adr_i; 164 assign dram_en_o = 1'b1; 165 assign dram_dat_o = dwb_dat_i; 166 assign dram_we_o = dwb_we_i; 167 assign dram_sel_o = dwb_sel_i; 168 assign rd_line = dwb_adr_i[CWIDTH+1:2]; 169 assign wr_line = rd_line; 170 assign wr_tags = dwb_adr_i[AWIDTH-1:CWIDTH+2]; 171 assign wr_data = dram_dat_i; 172 assign cache_write = dwb_stb_i & stb_d1 & miss_d1 & ~ack_d1; 173 assign invalidate = 0; 174`endif 175 176`ifdef DC_PREFETCH // Forwarding plus prefetch 177 178`endif 179 180 181endmodule // dcache 182 183