lm32_dcache.v

Mon, 05 Apr 2010 21:00:31 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Mon, 05 Apr 2010 21:00:31 +0100
changeset 6
a8e459b24c31
parent 3
b153470d41c5
permissions
-rw-r--r--

reduce size of caches to fit in DE1 FPGA

The default cache size makes the Icache and Dcache "just a bit" too big to
fit in the EP2C20 FPGA on the DE1 board. This commit reduces the Icache and
Dcache sizes to the defaults shown in the LatticeMico32 Processor Reference
Manual (pages 36 and 37).

philpem@0 1 // =============================================================================
philpem@0 2 // COPYRIGHT NOTICE
philpem@0 3 // Copyright 2006 (c) Lattice Semiconductor Corporation
philpem@0 4 // ALL RIGHTS RESERVED
philpem@0 5 // This confidential and proprietary software may be used only as authorised by
philpem@0 6 // a licensing agreement from Lattice Semiconductor Corporation.
philpem@0 7 // The entire notice above must be reproduced on all authorized copies and
philpem@0 8 // copies may only be made to the extent permitted by a licensing agreement from
philpem@0 9 // Lattice Semiconductor Corporation.
philpem@0 10 //
philpem@0 11 // Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
philpem@0 12 // 5555 NE Moore Court 408-826-6000 (other locations)
philpem@0 13 // Hillsboro, OR 97124 web : http://www.latticesemi.com/
philpem@0 14 // U.S.A email: techsupport@latticesemi.com
philpem@0 15 // =============================================================================/
philpem@0 16 // FILE DETAILS
philpem@0 17 // Project : LatticeMico32
philpem@0 18 // File : lm32_dcache.v
philpem@0 19 // Title : Data cache
philpem@0 20 // Dependencies : lm32_include.v
philpem@0 21 // Version : 6.1.17
philpem@0 22 // : Initial Release
philpem@0 23 // Version : 7.0SP2, 3.0
philpem@0 24 // : No Change
philpem@0 25 // Version : 3.1
philpem@0 26 // : Support for user-selected resource usage when implementing
philpem@0 27 // : cache memory. Additional parameters must be defined when
philpem@0 28 // : invoking lm32_ram.v
philpem@0 29 // =============================================================================
philpem@0 30
philpem@0 31 `include "lm32_include.v"
philpem@0 32
philpem@0 33 `ifdef CFG_DCACHE_ENABLED
philpem@0 34
philpem@0 35 `define LM32_DC_ADDR_OFFSET_RNG addr_offset_msb:addr_offset_lsb
philpem@0 36 `define LM32_DC_ADDR_SET_RNG addr_set_msb:addr_set_lsb
philpem@0 37 `define LM32_DC_ADDR_TAG_RNG addr_tag_msb:addr_tag_lsb
philpem@0 38 `define LM32_DC_ADDR_IDX_RNG addr_set_msb:addr_offset_lsb
philpem@0 39
philpem@0 40 `define LM32_DC_TMEM_ADDR_WIDTH addr_set_width
philpem@0 41 `define LM32_DC_TMEM_ADDR_RNG (`LM32_DC_TMEM_ADDR_WIDTH-1):0
philpem@0 42 `define LM32_DC_DMEM_ADDR_WIDTH (addr_offset_width+addr_set_width)
philpem@0 43 `define LM32_DC_DMEM_ADDR_RNG (`LM32_DC_DMEM_ADDR_WIDTH-1):0
philpem@0 44
philpem@0 45 `define LM32_DC_TAGS_WIDTH (addr_tag_width+1)
philpem@0 46 `define LM32_DC_TAGS_RNG (`LM32_DC_TAGS_WIDTH-1):0
philpem@0 47 `define LM32_DC_TAGS_TAG_RNG (`LM32_DC_TAGS_WIDTH-1):1
philpem@0 48 `define LM32_DC_TAGS_VALID_RNG 0
philpem@0 49
philpem@0 50 `define LM32_DC_STATE_RNG 2:0
philpem@0 51 `define LM32_DC_STATE_FLUSH 3'b001
philpem@0 52 `define LM32_DC_STATE_CHECK 3'b010
philpem@0 53 `define LM32_DC_STATE_REFILL 3'b100
philpem@0 54
philpem@0 55 /////////////////////////////////////////////////////
philpem@0 56 // Module interface
philpem@0 57 /////////////////////////////////////////////////////
philpem@0 58
philpem@0 59 module lm32_dcache (
philpem@0 60 // ----- Inputs -----
philpem@0 61 clk_i,
philpem@0 62 rst_i,
philpem@0 63 stall_a,
philpem@0 64 stall_x,
philpem@0 65 stall_m,
philpem@0 66 address_x,
philpem@0 67 address_m,
philpem@0 68 load_q_m,
philpem@0 69 store_q_m,
philpem@0 70 store_data,
philpem@0 71 store_byte_select,
philpem@0 72 refill_ready,
philpem@0 73 refill_data,
philpem@0 74 dflush,
philpem@0 75 // ----- Outputs -----
philpem@0 76 stall_request,
philpem@0 77 restart_request,
philpem@0 78 refill_request,
philpem@0 79 refill_address,
philpem@0 80 refilling,
philpem@0 81 load_data
philpem@0 82 );
philpem@0 83
philpem@0 84 /////////////////////////////////////////////////////
philpem@0 85 // Parameters
philpem@0 86 /////////////////////////////////////////////////////
philpem@0 87
philpem@0 88 parameter associativity = 1; // Associativity of the cache (Number of ways)
philpem@0 89 parameter sets = 512; // Number of sets
philpem@0 90 parameter bytes_per_line = 16; // Number of bytes per cache line
philpem@0 91 parameter base_address = 0; // Base address of cachable memory
philpem@0 92 parameter limit = 0; // Limit (highest address) of cachable memory
philpem@0 93
philpem@0 94 localparam addr_offset_width = clogb2(bytes_per_line)-1-2;
philpem@0 95 localparam addr_set_width = clogb2(sets)-1;
philpem@0 96 localparam addr_offset_lsb = 2;
philpem@0 97 localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1);
philpem@0 98 localparam addr_set_lsb = (addr_offset_msb+1);
philpem@0 99 localparam addr_set_msb = (addr_set_lsb+addr_set_width-1);
philpem@0 100 localparam addr_tag_lsb = (addr_set_msb+1);
philpem@0 101 localparam addr_tag_msb = clogb2(`CFG_DCACHE_LIMIT-`CFG_DCACHE_BASE_ADDRESS)-1;
philpem@0 102 localparam addr_tag_width = (addr_tag_msb-addr_tag_lsb+1);
philpem@0 103
philpem@0 104 /////////////////////////////////////////////////////
philpem@0 105 // Inputs
philpem@0 106 /////////////////////////////////////////////////////
philpem@0 107
philpem@0 108 input clk_i; // Clock
philpem@0 109 input rst_i; // Reset
philpem@0 110
philpem@0 111 input stall_a; // Stall A stage
philpem@0 112 input stall_x; // Stall X stage
philpem@0 113 input stall_m; // Stall M stage
philpem@0 114
philpem@0 115 input [`LM32_WORD_RNG] address_x; // X stage load/store address
philpem@0 116 input [`LM32_WORD_RNG] address_m; // M stage load/store address
philpem@0 117 input load_q_m; // Load instruction in M stage
philpem@0 118 input store_q_m; // Store instruction in M stage
philpem@0 119 input [`LM32_WORD_RNG] store_data; // Data to store
philpem@0 120 input [`LM32_BYTE_SELECT_RNG] store_byte_select; // Which bytes in store data should be modified
philpem@0 121
philpem@0 122 input refill_ready; // Indicates next word of refill data is ready
philpem@0 123 input [`LM32_WORD_RNG] refill_data; // Refill data
philpem@0 124
philpem@0 125 input dflush; // Indicates cache should be flushed
philpem@0 126
philpem@0 127 /////////////////////////////////////////////////////
philpem@0 128 // Outputs
philpem@0 129 /////////////////////////////////////////////////////
philpem@0 130
philpem@0 131 output stall_request; // Request pipeline be stalled because cache is busy
philpem@0 132 wire stall_request;
philpem@0 133 output restart_request; // Request to restart instruction that caused the cache miss
philpem@0 134 reg restart_request;
philpem@0 135 output refill_request; // Request a refill
philpem@0 136 reg refill_request;
philpem@0 137 output [`LM32_WORD_RNG] refill_address; // Address to refill from
philpem@0 138 reg [`LM32_WORD_RNG] refill_address;
philpem@0 139 output refilling; // Indicates if the cache is currently refilling
philpem@0 140 reg refilling;
philpem@0 141 output [`LM32_WORD_RNG] load_data; // Data read from cache
philpem@0 142 wire [`LM32_WORD_RNG] load_data;
philpem@0 143
philpem@0 144 /////////////////////////////////////////////////////
philpem@0 145 // Internal nets and registers
philpem@0 146 /////////////////////////////////////////////////////
philpem@0 147
philpem@0 148 wire read_port_enable; // Cache memory read port clock enable
philpem@0 149 wire write_port_enable; // Cache memory write port clock enable
philpem@0 150 wire [0:associativity-1] way_tmem_we; // Tag memory write enable
philpem@0 151 wire [0:associativity-1] way_dmem_we; // Data memory write enable
philpem@0 152 wire [`LM32_WORD_RNG] way_data[0:associativity-1]; // Data read from data memory
philpem@0 153 wire [`LM32_DC_TAGS_TAG_RNG] way_tag[0:associativity-1];// Tag read from tag memory
philpem@0 154 wire [0:associativity-1] way_valid; // Indicates which ways are valid
philpem@0 155 wire [0:associativity-1] way_match; // Indicates which ways matched
philpem@0 156 wire miss; // Indicates no ways matched
philpem@0 157
philpem@0 158 wire [`LM32_DC_TMEM_ADDR_RNG] tmem_read_address; // Tag memory read address
philpem@0 159 wire [`LM32_DC_TMEM_ADDR_RNG] tmem_write_address; // Tag memory write address
philpem@0 160 wire [`LM32_DC_DMEM_ADDR_RNG] dmem_read_address; // Data memory read address
philpem@0 161 wire [`LM32_DC_DMEM_ADDR_RNG] dmem_write_address; // Data memory write address
philpem@0 162 wire [`LM32_DC_TAGS_RNG] tmem_write_data; // Tag memory write data
philpem@0 163 reg [`LM32_WORD_RNG] dmem_write_data; // Data memory write data
philpem@0 164
philpem@0 165 reg [`LM32_DC_STATE_RNG] state; // Current state of FSM
philpem@0 166 wire flushing; // Indicates if cache is currently flushing
philpem@0 167 wire check; // Indicates if cache is currently checking for hits/misses
philpem@0 168 wire refill; // Indicates if cache is currently refilling
philpem@0 169
philpem@0 170 wire valid_store; // Indicates if there is a valid store instruction
philpem@0 171 reg [associativity-1:0] refill_way_select; // Which way should be refilled
philpem@0 172 reg [`LM32_DC_ADDR_OFFSET_RNG] refill_offset; // Which word in cache line should be refilled
philpem@0 173 wire last_refill; // Indicates when on last cycle of cache refill
philpem@0 174 reg [`LM32_DC_TMEM_ADDR_RNG] flush_set; // Which set is currently being flushed
philpem@0 175
philpem@0 176 genvar i, j;
philpem@0 177
philpem@0 178 /////////////////////////////////////////////////////
philpem@0 179 // Functions
philpem@0 180 /////////////////////////////////////////////////////
philpem@0 181
philpem@0 182 `include "lm32_functions.v"
philpem@0 183
philpem@0 184 /////////////////////////////////////////////////////
philpem@0 185 // Instantiations
philpem@0 186 /////////////////////////////////////////////////////
philpem@0 187
philpem@0 188 generate
philpem@0 189 for (i = 0; i < associativity; i = i + 1)
philpem@0 190 begin : memories
philpem@0 191 // Way data
philpem@0 192 if (`LM32_DC_DMEM_ADDR_WIDTH < 11)
philpem@0 193 begin : data_memories
philpem@0 194 lm32_ram
philpem@0 195 #(
philpem@0 196 // ----- Parameters -------
philpem@0 197 .data_width (32),
philpem@3 198 .address_width (`LM32_DC_DMEM_ADDR_WIDTH)
philpem@2 199 `ifdef PLATFORM_LATTICE
philpem@3 200 ,
philpem@2 201 `ifdef CFG_DCACHE_DAT_USE_DP_TRUE
philpem@0 202 .RAM_IMPLEMENTATION ("EBR"),
philpem@0 203 .RAM_TYPE ("RAM_DP_TRUE")
philpem@2 204 `else
philpem@2 205 `ifdef CFG_DCACHE_DAT_USE_SLICE
philpem@0 206 .RAM_IMPLEMENTATION ("SLICE")
philpem@2 207 `else
philpem@0 208 .RAM_IMPLEMENTATION ("AUTO")
philpem@2 209 `endif
philpem@0 210 `endif
philpem@0 211 `endif
philpem@0 212 ) way_0_data_ram
philpem@0 213 (
philpem@0 214 // ----- Inputs -------
philpem@0 215 .read_clk (clk_i),
philpem@0 216 .write_clk (clk_i),
philpem@0 217 .reset (rst_i),
philpem@0 218 .read_address (dmem_read_address),
philpem@0 219 .enable_read (read_port_enable),
philpem@0 220 .write_address (dmem_write_address),
philpem@0 221 .enable_write (write_port_enable),
philpem@0 222 .write_enable (way_dmem_we[i]),
philpem@0 223 .write_data (dmem_write_data),
philpem@0 224 // ----- Outputs -------
philpem@0 225 .read_data (way_data[i])
philpem@0 226 );
philpem@0 227 end
philpem@0 228 else
philpem@0 229 begin
philpem@0 230 for (j = 0; j < 4; j = j + 1)
philpem@0 231 begin : byte_memories
philpem@0 232 lm32_ram
philpem@0 233 #(
philpem@0 234 // ----- Parameters -------
philpem@0 235 .data_width (8),
philpem@3 236 .address_width (`LM32_DC_DMEM_ADDR_WIDTH)
philpem@3 237 `ifdef PLATFORM_LATTICE
philpem@3 238 ,
philpem@3 239 `ifdef CFG_DCACHE_DAT_USE_DP_TRUE
philpem@0 240 .RAM_IMPLEMENTATION ("EBR"),
philpem@0 241 .RAM_TYPE ("RAM_DP_TRUE")
philpem@3 242 `else
philpem@3 243 `ifdef CFG_DCACHE_DAT_USE_SLICE
philpem@0 244 .RAM_IMPLEMENTATION ("SLICE")
philpem@3 245 `else
philpem@0 246 .RAM_IMPLEMENTATION ("AUTO")
philpem@3 247 `endif
philpem@0 248 `endif
philpem@0 249 `endif
philpem@0 250 ) way_0_data_ram
philpem@0 251 (
philpem@0 252 // ----- Inputs -------
philpem@0 253 .read_clk (clk_i),
philpem@0 254 .write_clk (clk_i),
philpem@0 255 .reset (rst_i),
philpem@0 256 .read_address (dmem_read_address),
philpem@0 257 .enable_read (read_port_enable),
philpem@0 258 .write_address (dmem_write_address),
philpem@0 259 .enable_write (write_port_enable),
philpem@0 260 .write_enable (way_dmem_we[i] & (store_byte_select[j] | refill)),
philpem@0 261 .write_data (dmem_write_data[(j+1)*8-1:j*8]),
philpem@0 262 // ----- Outputs -------
philpem@0 263 .read_data (way_data[i][(j+1)*8-1:j*8])
philpem@0 264 );
philpem@0 265 end
philpem@0 266 end
philpem@0 267
philpem@0 268 // Way tags
philpem@0 269 lm32_ram
philpem@0 270 #(
philpem@0 271 // ----- Parameters -------
philpem@0 272 .data_width (`LM32_DC_TAGS_WIDTH),
philpem@3 273 .address_width (`LM32_DC_TMEM_ADDR_WIDTH)
philpem@3 274 `ifdef PLATFORM_LATTICE
philpem@3 275 ,
philpem@3 276 `ifdef CFG_DCACHE_DAT_USE_DP_TRUE
philpem@0 277 .RAM_IMPLEMENTATION ("EBR"),
philpem@0 278 .RAM_TYPE ("RAM_DP_TRUE")
philpem@3 279 `else
philpem@3 280 `ifdef CFG_DCACHE_DAT_USE_SLICE
philpem@0 281 .RAM_IMPLEMENTATION ("SLICE")
philpem@3 282 `else
philpem@0 283 .RAM_IMPLEMENTATION ("AUTO")
philpem@3 284 `endif
philpem@0 285 `endif
philpem@0 286 `endif
philpem@0 287 ) way_0_tag_ram
philpem@0 288 (
philpem@0 289 // ----- Inputs -------
philpem@0 290 .read_clk (clk_i),
philpem@0 291 .write_clk (clk_i),
philpem@0 292 .reset (rst_i),
philpem@0 293 .read_address (tmem_read_address),
philpem@0 294 .enable_read (read_port_enable),
philpem@0 295 .write_address (tmem_write_address),
philpem@0 296 .enable_write (`TRUE),
philpem@0 297 .write_enable (way_tmem_we[i]),
philpem@0 298 .write_data (tmem_write_data),
philpem@0 299 // ----- Outputs -------
philpem@0 300 .read_data ({way_tag[i], way_valid[i]})
philpem@0 301 );
philpem@0 302 end
philpem@0 303
philpem@0 304 endgenerate
philpem@0 305
philpem@0 306 /////////////////////////////////////////////////////
philpem@0 307 // Combinational logic
philpem@0 308 /////////////////////////////////////////////////////
philpem@0 309
philpem@0 310 // Compute which ways in the cache match the address being read
philpem@0 311 generate
philpem@0 312 for (i = 0; i < associativity; i = i + 1)
philpem@0 313 begin : match
philpem@0 314 assign way_match[i] = ({way_tag[i], way_valid[i]} == {address_m[`LM32_DC_ADDR_TAG_RNG], `TRUE});
philpem@0 315 end
philpem@0 316 endgenerate
philpem@0 317
philpem@0 318 // Select data from way that matched the address being read
philpem@0 319 generate
philpem@0 320 if (associativity == 1)
philpem@0 321 begin : data_1
philpem@0 322 assign load_data = way_data[0];
philpem@0 323 end
philpem@0 324 else if (associativity == 2)
philpem@0 325 begin : data_2
philpem@0 326 assign load_data = way_match[0] ? way_data[0] : way_data[1];
philpem@0 327 end
philpem@0 328 endgenerate
philpem@0 329
philpem@0 330 generate
philpem@0 331 if (`LM32_DC_DMEM_ADDR_WIDTH < 11)
philpem@0 332 begin
philpem@0 333 // Select data to write to data memories
philpem@0 334 always @(*)
philpem@0 335 begin
philpem@0 336 if (refill == `TRUE)
philpem@0 337 dmem_write_data = refill_data;
philpem@0 338 else
philpem@0 339 begin
philpem@0 340 dmem_write_data[`LM32_BYTE_0_RNG] = store_byte_select[0] ? store_data[`LM32_BYTE_0_RNG] : load_data[`LM32_BYTE_0_RNG];
philpem@0 341 dmem_write_data[`LM32_BYTE_1_RNG] = store_byte_select[1] ? store_data[`LM32_BYTE_1_RNG] : load_data[`LM32_BYTE_1_RNG];
philpem@0 342 dmem_write_data[`LM32_BYTE_2_RNG] = store_byte_select[2] ? store_data[`LM32_BYTE_2_RNG] : load_data[`LM32_BYTE_2_RNG];
philpem@0 343 dmem_write_data[`LM32_BYTE_3_RNG] = store_byte_select[3] ? store_data[`LM32_BYTE_3_RNG] : load_data[`LM32_BYTE_3_RNG];
philpem@0 344 end
philpem@0 345 end
philpem@0 346 end
philpem@0 347 else
philpem@0 348 begin
philpem@0 349 // Select data to write to data memories - FIXME: Should use different write ports on dual port RAMs, but they don't work
philpem@0 350 always @(*)
philpem@0 351 begin
philpem@0 352 if (refill == `TRUE)
philpem@0 353 dmem_write_data = refill_data;
philpem@0 354 else
philpem@0 355 dmem_write_data = store_data;
philpem@0 356 end
philpem@0 357 end
philpem@0 358 endgenerate
philpem@0 359
philpem@0 360 // Compute address to use to index into the data memories
philpem@0 361 generate
philpem@0 362 if (bytes_per_line > 4)
philpem@0 363 assign dmem_write_address = (refill == `TRUE)
philpem@0 364 ? {refill_address[`LM32_DC_ADDR_SET_RNG], refill_offset}
philpem@0 365 : address_m[`LM32_DC_ADDR_IDX_RNG];
philpem@0 366 else
philpem@0 367 assign dmem_write_address = (refill == `TRUE)
philpem@0 368 ? refill_address[`LM32_DC_ADDR_SET_RNG]
philpem@0 369 : address_m[`LM32_DC_ADDR_IDX_RNG];
philpem@0 370 endgenerate
philpem@0 371 assign dmem_read_address = address_x[`LM32_DC_ADDR_IDX_RNG];
philpem@0 372 // Compute address to use to index into the tag memories
philpem@0 373 assign tmem_write_address = (flushing == `TRUE)
philpem@0 374 ? flush_set
philpem@0 375 : refill_address[`LM32_DC_ADDR_SET_RNG];
philpem@0 376 assign tmem_read_address = address_x[`LM32_DC_ADDR_SET_RNG];
philpem@0 377
philpem@0 378 // Compute signal to indicate when we are on the last refill accesses
philpem@0 379 generate
philpem@0 380 if (bytes_per_line > 4)
philpem@0 381 assign last_refill = refill_offset == {addr_offset_width{1'b1}};
philpem@0 382 else
philpem@0 383 assign last_refill = `TRUE;
philpem@0 384 endgenerate
philpem@0 385
philpem@0 386 // Compute data and tag memory access enable
philpem@0 387 assign read_port_enable = (stall_x == `FALSE);
philpem@0 388 assign write_port_enable = (refill_ready == `TRUE) || !stall_m;
philpem@0 389
philpem@0 390 // Determine when we have a valid store
philpem@0 391 assign valid_store = (store_q_m == `TRUE) && (check == `TRUE);
philpem@0 392
philpem@0 393 // Compute data and tag memory write enables
philpem@0 394 generate
philpem@0 395 if (associativity == 1)
philpem@0 396 begin : we_1
philpem@0 397 assign way_dmem_we[0] = (refill_ready == `TRUE) || ((valid_store == `TRUE) && (way_match[0] == `TRUE));
philpem@0 398 assign way_tmem_we[0] = (refill_ready == `TRUE) || (flushing == `TRUE);
philpem@0 399 end
philpem@0 400 else
philpem@0 401 begin : we_2
philpem@0 402 assign way_dmem_we[0] = ((refill_ready == `TRUE) && (refill_way_select[0] == `TRUE)) || ((valid_store == `TRUE) && (way_match[0] == `TRUE));
philpem@0 403 assign way_dmem_we[1] = ((refill_ready == `TRUE) && (refill_way_select[1] == `TRUE)) || ((valid_store == `TRUE) && (way_match[1] == `TRUE));
philpem@0 404 assign way_tmem_we[0] = ((refill_ready == `TRUE) && (refill_way_select[0] == `TRUE)) || (flushing == `TRUE);
philpem@0 405 assign way_tmem_we[1] = ((refill_ready == `TRUE) && (refill_way_select[1] == `TRUE)) || (flushing == `TRUE);
philpem@0 406 end
philpem@0 407 endgenerate
philpem@0 408
philpem@0 409 // On the last refill cycle set the valid bit, for all other writes it should be cleared
philpem@0 410 assign tmem_write_data[`LM32_DC_TAGS_VALID_RNG] = ((last_refill == `TRUE) || (valid_store == `TRUE)) && (flushing == `FALSE);
philpem@0 411 assign tmem_write_data[`LM32_DC_TAGS_TAG_RNG] = refill_address[`LM32_DC_ADDR_TAG_RNG];
philpem@0 412
philpem@0 413 // Signals that indicate which state we are in
philpem@0 414 assign flushing = state[0];
philpem@0 415 assign check = state[1];
philpem@0 416 assign refill = state[2];
philpem@0 417
philpem@0 418 assign miss = (~(|way_match)) && (load_q_m == `TRUE) && (stall_m == `FALSE);
philpem@0 419 assign stall_request = (check == `FALSE);
philpem@0 420
philpem@0 421 /////////////////////////////////////////////////////
philpem@0 422 // Sequential logic
philpem@0 423 /////////////////////////////////////////////////////
philpem@0 424
philpem@0 425 // Record way selected for replacement on a cache miss
philpem@0 426 generate
philpem@0 427 if (associativity >= 2)
philpem@0 428 begin : way_select
philpem@0 429 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 430 begin
philpem@0 431 if (rst_i == `TRUE)
philpem@0 432 refill_way_select <= {{associativity-1{1'b0}}, 1'b1};
philpem@0 433 else
philpem@0 434 begin
philpem@0 435 if (refill_request == `TRUE)
philpem@0 436 refill_way_select <= {refill_way_select[0], refill_way_select[1]};
philpem@0 437 end
philpem@0 438 end
philpem@0 439 end
philpem@0 440 endgenerate
philpem@0 441
philpem@0 442 // Record whether we are currently refilling
philpem@0 443 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 444 begin
philpem@0 445 if (rst_i == `TRUE)
philpem@0 446 refilling <= `FALSE;
philpem@0 447 else
philpem@0 448 refilling <= refill;
philpem@0 449 end
philpem@0 450
philpem@0 451 // Instruction cache control FSM
philpem@0 452 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 453 begin
philpem@0 454 if (rst_i == `TRUE)
philpem@0 455 begin
philpem@0 456 state <= `LM32_DC_STATE_FLUSH;
philpem@0 457 flush_set <= {`LM32_DC_TMEM_ADDR_WIDTH{1'b1}};
philpem@0 458 refill_request <= `FALSE;
philpem@0 459 refill_address <= {`LM32_WORD_WIDTH{1'bx}};
philpem@0 460 restart_request <= `FALSE;
philpem@0 461 end
philpem@0 462 else
philpem@0 463 begin
philpem@0 464 case (state)
philpem@0 465
philpem@0 466 // Flush the cache
philpem@0 467 `LM32_DC_STATE_FLUSH:
philpem@0 468 begin
philpem@0 469 if (flush_set == {`LM32_DC_TMEM_ADDR_WIDTH{1'b0}})
philpem@0 470 state <= `LM32_DC_STATE_CHECK;
philpem@0 471 flush_set <= flush_set - 1'b1;
philpem@0 472 end
philpem@0 473
philpem@0 474 // Check for cache misses
philpem@0 475 `LM32_DC_STATE_CHECK:
philpem@0 476 begin
philpem@0 477 if (stall_a == `FALSE)
philpem@0 478 restart_request <= `FALSE;
philpem@0 479 if (miss == `TRUE)
philpem@0 480 begin
philpem@0 481 refill_request <= `TRUE;
philpem@0 482 refill_address <= address_m;
philpem@0 483 state <= `LM32_DC_STATE_REFILL;
philpem@0 484 end
philpem@0 485 else if (dflush == `TRUE)
philpem@0 486 state <= `LM32_DC_STATE_FLUSH;
philpem@0 487 end
philpem@0 488
philpem@0 489 // Refill a cache line
philpem@0 490 `LM32_DC_STATE_REFILL:
philpem@0 491 begin
philpem@0 492 refill_request <= `FALSE;
philpem@0 493 if (refill_ready == `TRUE)
philpem@0 494 begin
philpem@0 495 if (last_refill == `TRUE)
philpem@0 496 begin
philpem@0 497 restart_request <= `TRUE;
philpem@0 498 state <= `LM32_DC_STATE_CHECK;
philpem@0 499 end
philpem@0 500 end
philpem@0 501 end
philpem@0 502
philpem@0 503 endcase
philpem@0 504 end
philpem@0 505 end
philpem@0 506
philpem@0 507 generate
philpem@0 508 if (bytes_per_line > 4)
philpem@0 509 begin
philpem@0 510 // Refill offset
philpem@0 511 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 512 begin
philpem@0 513 if (rst_i == `TRUE)
philpem@0 514 refill_offset <= {addr_offset_width{1'b0}};
philpem@0 515 else
philpem@0 516 begin
philpem@0 517 case (state)
philpem@0 518
philpem@0 519 // Check for cache misses
philpem@0 520 `LM32_DC_STATE_CHECK:
philpem@0 521 begin
philpem@0 522 if (miss == `TRUE)
philpem@0 523 refill_offset <= {addr_offset_width{1'b0}};
philpem@0 524 end
philpem@0 525
philpem@0 526 // Refill a cache line
philpem@0 527 `LM32_DC_STATE_REFILL:
philpem@0 528 begin
philpem@0 529 if (refill_ready == `TRUE)
philpem@0 530 refill_offset <= refill_offset + 1'b1;
philpem@0 531 end
philpem@0 532
philpem@0 533 endcase
philpem@0 534 end
philpem@0 535 end
philpem@0 536 end
philpem@0 537 endgenerate
philpem@0 538
philpem@0 539 endmodule
philpem@0 540
philpem@0 541 `endif
philpem@0 542