rtl/lm32_dcache.v

Sat, 06 Aug 2011 01:32:07 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Sat, 06 Aug 2011 01:32:07 +0100
changeset 28
da23ab8ef7b4
parent 27
lm32_dcache.v@d6c693415d59
parent 24
lm32_dcache.v@c336e674a37e
permissions
-rw-r--r--

Merge LM32 v3.8 into local mainline

Changes in this release:
FEATURE: Support for dynamically switching EBA to DEBA via a GPIO
BUGFIX: EA now reports instruction which caused the data abort, rather than the instruction following it
STYLE: Update comments to refer to latest Lattice license

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