lm32_load_store_unit.v

Sat, 06 Aug 2011 01:26:56 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Sat, 06 Aug 2011 01:26:56 +0100
changeset 27
d6c693415d59
parent 26
73de224304c1
permissions
-rwxr-xr-x

remove synthesis delay entities to ease merge

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_load_store_unit.v
philpem@0 40 // Title : Load and store unit
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 // : Instead of disallowing an instruction cache miss on a data cache
philpem@0 48 // : miss, both can now occur at the same time. If both occur at same
philpem@0 49 // : time, then restart address is the address of instruction that
philpem@0 50 // : caused data cache miss.
philpem@0 51 // Version : 3.2
philpem@0 52 // : EBRs use SYNC resets instead of ASYNC resets.
philpem@0 53 // Version : 3.3
philpem@0 54 // : Support for new non-cacheable Data Memory that is accessible by
philpem@0 55 // : the data port and has a one cycle access latency.
philpem@0 56 // Version : 3.4
philpem@0 57 // : No change
philpem@0 58 // Version : 3.5
philpem@0 59 // : Bug fix: Inline memory is correctly generated if it is not a
philpem@0 60 // : power-of-two
philpem@0 61 // =============================================================================
philpem@0 62
philpem@0 63 `include "lm32_include.v"
philpem@0 64
philpem@0 65 /////////////////////////////////////////////////////
philpem@0 66 // Module interface
philpem@0 67 /////////////////////////////////////////////////////
philpem@0 68
philpem@0 69 module lm32_load_store_unit (
philpem@0 70 // ----- Inputs -------
philpem@0 71 clk_i,
philpem@0 72 rst_i,
philpem@0 73 // From pipeline
philpem@0 74 stall_a,
philpem@0 75 stall_x,
philpem@0 76 stall_m,
philpem@0 77 kill_m,
philpem@0 78 exception_m,
philpem@0 79 store_operand_x,
philpem@0 80 load_store_address_x,
philpem@0 81 load_store_address_m,
philpem@0 82 load_store_address_w,
philpem@0 83 load_x,
philpem@0 84 store_x,
philpem@0 85 load_q_x,
philpem@0 86 store_q_x,
philpem@0 87 load_q_m,
philpem@0 88 store_q_m,
philpem@0 89 sign_extend_x,
philpem@0 90 size_x,
philpem@0 91 `ifdef CFG_DCACHE_ENABLED
philpem@0 92 dflush,
philpem@0 93 `endif
philpem@0 94 `ifdef CFG_IROM_ENABLED
philpem@0 95 irom_data_m,
philpem@0 96 `endif
philpem@0 97 // From Wishbone
philpem@0 98 d_dat_i,
philpem@0 99 d_ack_i,
philpem@0 100 d_err_i,
philpem@0 101 d_rty_i,
philpem@0 102 // ----- Outputs -------
philpem@0 103 // To pipeline
philpem@0 104 `ifdef CFG_DCACHE_ENABLED
philpem@0 105 dcache_refill_request,
philpem@0 106 dcache_restart_request,
philpem@0 107 dcache_stall_request,
philpem@0 108 dcache_refilling,
philpem@0 109 `endif
philpem@0 110 `ifdef CFG_IROM_ENABLED
philpem@0 111 irom_store_data_m,
philpem@0 112 irom_address_xm,
philpem@0 113 irom_we_xm,
philpem@0 114 irom_stall_request_x,
philpem@0 115 `endif
philpem@0 116 load_data_w,
philpem@0 117 stall_wb_load,
philpem@0 118 // To Wishbone
philpem@0 119 d_dat_o,
philpem@0 120 d_adr_o,
philpem@0 121 d_cyc_o,
philpem@0 122 d_sel_o,
philpem@0 123 d_stb_o,
philpem@0 124 d_we_o,
philpem@0 125 d_cti_o,
philpem@0 126 d_lock_o,
philpem@0 127 d_bte_o
philpem@0 128 );
philpem@0 129
philpem@0 130 /////////////////////////////////////////////////////
philpem@0 131 // Parameters
philpem@0 132 /////////////////////////////////////////////////////
philpem@0 133
philpem@0 134 parameter associativity = 1; // Associativity of the cache (Number of ways)
philpem@0 135 parameter sets = 512; // Number of sets
philpem@0 136 parameter bytes_per_line = 16; // Number of bytes per cache line
philpem@0 137 parameter base_address = 0; // Base address of cachable memory
philpem@0 138 parameter limit = 0; // Limit (highest address) of cachable memory
philpem@0 139
philpem@0 140 // For bytes_per_line == 4, we set 1 so part-select range isn't reversed, even though not really used
philpem@0 141 localparam addr_offset_width = bytes_per_line == 4 ? 1 : clogb2(bytes_per_line)-1-2;
philpem@0 142 localparam addr_offset_lsb = 2;
philpem@0 143 localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1);
philpem@0 144
philpem@0 145 /////////////////////////////////////////////////////
philpem@0 146 // Inputs
philpem@0 147 /////////////////////////////////////////////////////
philpem@0 148
philpem@0 149 input clk_i; // Clock
philpem@0 150 input rst_i; // Reset
philpem@0 151
philpem@0 152 input stall_a; // A stage stall
philpem@0 153 input stall_x; // X stage stall
philpem@0 154 input stall_m; // M stage stall
philpem@0 155 input kill_m; // Kill instruction in M stage
philpem@0 156 input exception_m; // An exception occured in the M stage
philpem@0 157
philpem@0 158 input [`LM32_WORD_RNG] store_operand_x; // Data read from register to store
philpem@0 159 input [`LM32_WORD_RNG] load_store_address_x; // X stage load/store address
philpem@0 160 input [`LM32_WORD_RNG] load_store_address_m; // M stage load/store address
philpem@0 161 input [1:0] load_store_address_w; // W stage load/store address (only least two significant bits are needed)
philpem@0 162 input load_x; // Load instruction in X stage
philpem@0 163 input store_x; // Store instruction in X stage
philpem@0 164 input load_q_x; // Load instruction in X stage
philpem@0 165 input store_q_x; // Store instruction in X stage
philpem@0 166 input load_q_m; // Load instruction in M stage
philpem@0 167 input store_q_m; // Store instruction in M stage
philpem@0 168 input sign_extend_x; // Whether load instruction in X stage should sign extend or zero extend
philpem@0 169 input [`LM32_SIZE_RNG] size_x; // Size of load or store (byte, hword, word)
philpem@0 170
philpem@0 171 `ifdef CFG_DCACHE_ENABLED
philpem@0 172 input dflush; // Flush the data cache
philpem@0 173 `endif
philpem@0 174
philpem@0 175 `ifdef CFG_IROM_ENABLED
philpem@0 176 input [`LM32_WORD_RNG] irom_data_m; // Data from Instruction-ROM
philpem@0 177 `endif
philpem@0 178
philpem@0 179 input [`LM32_WORD_RNG] d_dat_i; // Data Wishbone interface read data
philpem@0 180 input d_ack_i; // Data Wishbone interface acknowledgement
philpem@0 181 input d_err_i; // Data Wishbone interface error
philpem@0 182 input d_rty_i; // Data Wishbone interface retry
philpem@0 183
philpem@0 184 /////////////////////////////////////////////////////
philpem@0 185 // Outputs
philpem@0 186 /////////////////////////////////////////////////////
philpem@0 187
philpem@0 188 `ifdef CFG_DCACHE_ENABLED
philpem@0 189 output dcache_refill_request; // Request to refill data cache
philpem@0 190 wire dcache_refill_request;
philpem@0 191 output dcache_restart_request; // Request to restart the instruction that caused a data cache miss
philpem@0 192 wire dcache_restart_request;
philpem@0 193 output dcache_stall_request; // Data cache stall request
philpem@0 194 wire dcache_stall_request;
philpem@0 195 output dcache_refilling;
philpem@0 196 wire dcache_refilling;
philpem@0 197 `endif
philpem@0 198
philpem@0 199 `ifdef CFG_IROM_ENABLED
philpem@0 200 output irom_store_data_m; // Store data to Instruction ROM
philpem@0 201 wire [`LM32_WORD_RNG] irom_store_data_m;
philpem@0 202 output [`LM32_WORD_RNG] irom_address_xm; // Load/store address to Instruction ROM
philpem@0 203 wire [`LM32_WORD_RNG] irom_address_xm;
philpem@0 204 output irom_we_xm; // Write-enable of 2nd port of Instruction ROM
philpem@0 205 wire irom_we_xm;
philpem@0 206 output irom_stall_request_x; // Stall instruction in D stage
philpem@0 207 wire irom_stall_request_x;
philpem@0 208 `endif
philpem@0 209
philpem@0 210 output [`LM32_WORD_RNG] load_data_w; // Result of a load instruction
philpem@0 211 reg [`LM32_WORD_RNG] load_data_w;
philpem@0 212 output stall_wb_load; // Request to stall pipeline due to a load from the Wishbone interface
philpem@0 213 reg stall_wb_load;
philpem@0 214
philpem@0 215 output [`LM32_WORD_RNG] d_dat_o; // Data Wishbone interface write data
philpem@0 216 reg [`LM32_WORD_RNG] d_dat_o;
philpem@0 217 output [`LM32_WORD_RNG] d_adr_o; // Data Wishbone interface address
philpem@0 218 reg [`LM32_WORD_RNG] d_adr_o;
philpem@0 219 output d_cyc_o; // Data Wishbone interface cycle
philpem@0 220 reg d_cyc_o;
philpem@0 221 output [`LM32_BYTE_SELECT_RNG] d_sel_o; // Data Wishbone interface byte select
philpem@0 222 reg [`LM32_BYTE_SELECT_RNG] d_sel_o;
philpem@0 223 output d_stb_o; // Data Wishbone interface strobe
philpem@0 224 reg d_stb_o;
philpem@0 225 output d_we_o; // Data Wishbone interface write enable
philpem@0 226 reg d_we_o;
philpem@0 227 output [`LM32_CTYPE_RNG] d_cti_o; // Data Wishbone interface cycle type
philpem@0 228 reg [`LM32_CTYPE_RNG] d_cti_o;
philpem@0 229 output d_lock_o; // Date Wishbone interface lock bus
philpem@0 230 reg d_lock_o;
philpem@0 231 output [`LM32_BTYPE_RNG] d_bte_o; // Data Wishbone interface burst type
philpem@0 232 wire [`LM32_BTYPE_RNG] d_bte_o;
philpem@0 233
philpem@0 234 /////////////////////////////////////////////////////
philpem@0 235 // Internal nets and registers
philpem@0 236 /////////////////////////////////////////////////////
philpem@0 237
philpem@0 238 // Microcode pipeline registers - See inputs for description
philpem@0 239 reg [`LM32_SIZE_RNG] size_m;
philpem@0 240 reg [`LM32_SIZE_RNG] size_w;
philpem@0 241 reg sign_extend_m;
philpem@0 242 reg sign_extend_w;
philpem@0 243 reg [`LM32_WORD_RNG] store_data_x;
philpem@0 244 reg [`LM32_WORD_RNG] store_data_m;
philpem@0 245 reg [`LM32_BYTE_SELECT_RNG] byte_enable_x;
philpem@0 246 reg [`LM32_BYTE_SELECT_RNG] byte_enable_m;
philpem@0 247 wire [`LM32_WORD_RNG] data_m;
philpem@0 248 reg [`LM32_WORD_RNG] data_w;
philpem@0 249
philpem@0 250 `ifdef CFG_DCACHE_ENABLED
philpem@0 251 wire dcache_select_x; // Select data cache to load from / store to
philpem@0 252 reg dcache_select_m;
philpem@0 253 wire [`LM32_WORD_RNG] dcache_data_m; // Data read from cache
philpem@0 254 wire [`LM32_WORD_RNG] dcache_refill_address; // Address to refill data cache from
philpem@0 255 reg dcache_refill_ready; // Indicates the next word of refill data is ready
philpem@0 256 wire [`LM32_CTYPE_RNG] first_cycle_type; // First Wishbone cycle type
philpem@0 257 wire [`LM32_CTYPE_RNG] next_cycle_type; // Next Wishbone cycle type
philpem@0 258 wire last_word; // Indicates if this is the last word in the cache line
philpem@0 259 wire [`LM32_WORD_RNG] first_address; // First cache refill address
philpem@0 260 `endif
philpem@0 261 `ifdef CFG_DRAM_ENABLED
philpem@0 262 wire dram_select_x; // Select data RAM to load from / store to
philpem@0 263 reg dram_select_m;
philpem@0 264 reg dram_bypass_en; // RAW in data RAM; read latched (bypass) value rather than value from memory
philpem@0 265 reg [`LM32_WORD_RNG] dram_bypass_data; // Latched value of store'd data to data RAM
philpem@0 266 wire [`LM32_WORD_RNG] dram_data_out; // Data read from data RAM
philpem@0 267 wire [`LM32_WORD_RNG] dram_data_m; // Data read from data RAM: bypass value or value from memory
philpem@0 268 wire [`LM32_WORD_RNG] dram_store_data_m; // Data to write to RAM
philpem@0 269 `endif
philpem@0 270 wire wb_select_x; // Select Wishbone to load from / store to
philpem@0 271 `ifdef CFG_IROM_ENABLED
philpem@0 272 wire irom_select_x; // Select instruction ROM to load from / store to
philpem@0 273 reg irom_select_m;
philpem@0 274 `endif
philpem@0 275 reg wb_select_m;
philpem@0 276 reg [`LM32_WORD_RNG] wb_data_m; // Data read from Wishbone
philpem@0 277 reg wb_load_complete; // Indicates when a Wishbone load is complete
philpem@0 278
philpem@0 279 /////////////////////////////////////////////////////
philpem@0 280 // Functions
philpem@0 281 /////////////////////////////////////////////////////
philpem@0 282
philpem@0 283 `include "lm32_functions.v"
philpem@0 284
philpem@0 285 /////////////////////////////////////////////////////
philpem@0 286 // Instantiations
philpem@0 287 /////////////////////////////////////////////////////
philpem@0 288
philpem@0 289 `ifdef CFG_DRAM_ENABLED
philpem@0 290 // Data RAM
philpem@0 291 pmi_ram_dp_true
philpem@0 292 #(
philpem@0 293 // ----- Parameters -------
philpem@0 294 .pmi_family (`LATTICE_FAMILY),
philpem@0 295
philpem@0 296 //.pmi_addr_depth_a (1 << (clogb2(`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1)-1)),
philpem@0 297 //.pmi_addr_width_a ((clogb2(`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1)-1)),
philpem@0 298 //.pmi_data_width_a (`LM32_WORD_WIDTH),
philpem@0 299 //.pmi_addr_depth_b (1 << (clogb2(`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1)-1)),
philpem@0 300 //.pmi_addr_width_b ((clogb2(`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1)-1)),
philpem@0 301 //.pmi_data_width_b (`LM32_WORD_WIDTH),
philpem@0 302
philpem@0 303 .pmi_addr_depth_a (`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1),
philpem@0 304 .pmi_addr_width_a (clogb2_v1(`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1)),
philpem@0 305 .pmi_data_width_a (`LM32_WORD_WIDTH),
philpem@0 306 .pmi_addr_depth_b (`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1),
philpem@0 307 .pmi_addr_width_b (clogb2_v1(`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1)),
philpem@0 308 .pmi_data_width_b (`LM32_WORD_WIDTH),
philpem@0 309
philpem@0 310 .pmi_regmode_a ("noreg"),
philpem@0 311 .pmi_regmode_b ("noreg"),
philpem@0 312 .pmi_gsr ("enable"),
philpem@0 313 .pmi_resetmode ("sync"),
philpem@0 314 .pmi_init_file (`CFG_DRAM_INIT_FILE),
philpem@0 315 .pmi_init_file_format (`CFG_DRAM_INIT_FILE_FORMAT),
philpem@0 316 .module_type ("pmi_ram_dp_true")
philpem@0 317 )
philpem@0 318 ram (
philpem@0 319 // ----- Inputs -------
philpem@0 320 .ClockA (clk_i),
philpem@0 321 .ClockB (clk_i),
philpem@0 322 .ResetA (rst_i),
philpem@0 323 .ResetB (rst_i),
philpem@0 324 .DataInA ({32{1'b0}}),
philpem@0 325 .DataInB (dram_store_data_m),
philpem@26 326 .AddressA (load_store_address_x[clogb2_v1(`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1)+2-1:2]),
philpem@26 327 .AddressB (load_store_address_m[clogb2_v1(`CFG_DRAM_LIMIT/4-`CFG_DRAM_BASE_ADDRESS/4+1)+2-1:2]),
philpem@0 328 // .ClockEnA (!stall_x & (load_x | store_x)),
philpem@0 329 .ClockEnA (!stall_x),
philpem@0 330 .ClockEnB (!stall_m),
philpem@0 331 .WrA (`FALSE),
philpem@0 332 .WrB (store_q_m & dram_select_m),
philpem@0 333 // ----- Outputs -------
philpem@0 334 .QA (dram_data_out),
philpem@0 335 .QB ()
philpem@0 336 );
philpem@0 337
philpem@0 338 /*----------------------------------------------------------------------
philpem@0 339 EBRs cannot perform reads from location 'written to' on the same clock
philpem@0 340 edge. Therefore bypass logic is required to latch the store'd value
philpem@0 341 and use it for the load (instead of value from memory).
philpem@0 342 ----------------------------------------------------------------------*/
philpem@0 343 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 344 if (rst_i == `TRUE)
philpem@0 345 begin
philpem@27 346 dram_bypass_en <= `FALSE;
philpem@27 347 dram_bypass_data <= 0;
philpem@0 348 end
philpem@0 349 else
philpem@0 350 begin
philpem@0 351 if (stall_x == `FALSE)
philpem@27 352 dram_bypass_data <= dram_store_data_m;
philpem@0 353
philpem@0 354 if ( (stall_m == `FALSE)
philpem@0 355 && (stall_x == `FALSE)
philpem@0 356 && (store_q_m == `TRUE)
philpem@0 357 && ( (load_x == `TRUE)
philpem@0 358 || (store_x == `TRUE)
philpem@0 359 )
philpem@0 360 && (load_store_address_x[(`LM32_WORD_WIDTH-1):2] == load_store_address_m[(`LM32_WORD_WIDTH-1):2])
philpem@0 361 )
philpem@27 362 dram_bypass_en <= `TRUE;
philpem@0 363 else
philpem@0 364 if ( (dram_bypass_en == `TRUE)
philpem@0 365 && (stall_x == `FALSE)
philpem@0 366 )
philpem@27 367 dram_bypass_en <= `FALSE;
philpem@0 368 end
philpem@0 369
philpem@0 370 assign dram_data_m = dram_bypass_en ? dram_bypass_data : dram_data_out;
philpem@0 371 `endif
philpem@0 372
philpem@0 373 `ifdef CFG_DCACHE_ENABLED
philpem@0 374 // Data cache
philpem@0 375 lm32_dcache #(
philpem@0 376 .associativity (associativity),
philpem@0 377 .sets (sets),
philpem@0 378 .bytes_per_line (bytes_per_line),
philpem@0 379 .base_address (base_address),
philpem@0 380 .limit (limit)
philpem@0 381 ) dcache (
philpem@0 382 // ----- Inputs -----
philpem@0 383 .clk_i (clk_i),
philpem@0 384 .rst_i (rst_i),
philpem@0 385 .stall_a (stall_a),
philpem@0 386 .stall_x (stall_x),
philpem@0 387 .stall_m (stall_m),
philpem@0 388 .address_x (load_store_address_x),
philpem@0 389 .address_m (load_store_address_m),
philpem@0 390 .load_q_m (load_q_m & dcache_select_m),
philpem@0 391 .store_q_m (store_q_m & dcache_select_m),
philpem@0 392 .store_data (store_data_m),
philpem@0 393 .store_byte_select (byte_enable_m & {4{dcache_select_m}}),
philpem@0 394 .refill_ready (dcache_refill_ready),
philpem@0 395 .refill_data (wb_data_m),
philpem@0 396 .dflush (dflush),
philpem@0 397 // ----- Outputs -----
philpem@0 398 .stall_request (dcache_stall_request),
philpem@0 399 .restart_request (dcache_restart_request),
philpem@0 400 .refill_request (dcache_refill_request),
philpem@0 401 .refill_address (dcache_refill_address),
philpem@0 402 .refilling (dcache_refilling),
philpem@0 403 .load_data (dcache_data_m)
philpem@0 404 );
philpem@0 405 `endif
philpem@0 406
philpem@0 407 /////////////////////////////////////////////////////
philpem@0 408 // Combinational Logic
philpem@0 409 /////////////////////////////////////////////////////
philpem@0 410
philpem@0 411 // Select where data should be loaded from / stored to
philpem@0 412 `ifdef CFG_DRAM_ENABLED
philpem@0 413 assign dram_select_x = (load_store_address_x >= `CFG_DRAM_BASE_ADDRESS)
philpem@0 414 && (load_store_address_x <= `CFG_DRAM_LIMIT);
philpem@0 415 `endif
philpem@0 416
philpem@0 417 `ifdef CFG_IROM_ENABLED
philpem@0 418 assign irom_select_x = (load_store_address_x >= `CFG_IROM_BASE_ADDRESS)
philpem@0 419 && (load_store_address_x <= `CFG_IROM_LIMIT);
philpem@0 420 `endif
philpem@0 421
philpem@0 422 `ifdef CFG_DCACHE_ENABLED
philpem@0 423 assign dcache_select_x = (load_store_address_x >= `CFG_DCACHE_BASE_ADDRESS)
philpem@0 424 && (load_store_address_x <= `CFG_DCACHE_LIMIT)
philpem@0 425 `ifdef CFG_DRAM_ENABLED
philpem@0 426 && (dram_select_x == `FALSE)
philpem@0 427 `endif
philpem@0 428 `ifdef CFG_IROM_ENABLED
philpem@0 429 && (irom_select_x == `FALSE)
philpem@0 430 `endif
philpem@0 431 ;
philpem@0 432 `endif
philpem@0 433
philpem@0 434 assign wb_select_x = `TRUE
philpem@0 435 `ifdef CFG_DCACHE_ENABLED
philpem@0 436 && !dcache_select_x
philpem@0 437 `endif
philpem@0 438 `ifdef CFG_DRAM_ENABLED
philpem@0 439 && !dram_select_x
philpem@0 440 `endif
philpem@0 441 `ifdef CFG_IROM_ENABLED
philpem@0 442 && !irom_select_x
philpem@0 443 `endif
philpem@0 444 ;
philpem@0 445
philpem@0 446 // Make sure data to store is in correct byte lane
philpem@0 447 always @(*)
philpem@0 448 begin
philpem@0 449 case (size_x)
philpem@0 450 `LM32_SIZE_BYTE: store_data_x = {4{store_operand_x[7:0]}};
philpem@0 451 `LM32_SIZE_HWORD: store_data_x = {2{store_operand_x[15:0]}};
philpem@0 452 `LM32_SIZE_WORD: store_data_x = store_operand_x;
philpem@0 453 default: store_data_x = {`LM32_WORD_WIDTH{1'bx}};
philpem@0 454 endcase
philpem@0 455 end
philpem@0 456
philpem@0 457 // Generate byte enable accoring to size of load or store and address being accessed
philpem@0 458 always @(*)
philpem@0 459 begin
philpem@0 460 casez ({size_x, load_store_address_x[1:0]})
philpem@0 461 {`LM32_SIZE_BYTE, 2'b11}: byte_enable_x = 4'b0001;
philpem@0 462 {`LM32_SIZE_BYTE, 2'b10}: byte_enable_x = 4'b0010;
philpem@0 463 {`LM32_SIZE_BYTE, 2'b01}: byte_enable_x = 4'b0100;
philpem@0 464 {`LM32_SIZE_BYTE, 2'b00}: byte_enable_x = 4'b1000;
philpem@0 465 {`LM32_SIZE_HWORD, 2'b1?}: byte_enable_x = 4'b0011;
philpem@0 466 {`LM32_SIZE_HWORD, 2'b0?}: byte_enable_x = 4'b1100;
philpem@0 467 {`LM32_SIZE_WORD, 2'b??}: byte_enable_x = 4'b1111;
philpem@0 468 default: byte_enable_x = 4'bxxxx;
philpem@0 469 endcase
philpem@0 470 end
philpem@0 471
philpem@0 472 `ifdef CFG_DRAM_ENABLED
philpem@0 473 // Only replace selected bytes
philpem@0 474 assign dram_store_data_m[`LM32_BYTE_0_RNG] = byte_enable_m[0] ? store_data_m[`LM32_BYTE_0_RNG] : dram_data_m[`LM32_BYTE_0_RNG];
philpem@0 475 assign dram_store_data_m[`LM32_BYTE_1_RNG] = byte_enable_m[1] ? store_data_m[`LM32_BYTE_1_RNG] : dram_data_m[`LM32_BYTE_1_RNG];
philpem@0 476 assign dram_store_data_m[`LM32_BYTE_2_RNG] = byte_enable_m[2] ? store_data_m[`LM32_BYTE_2_RNG] : dram_data_m[`LM32_BYTE_2_RNG];
philpem@0 477 assign dram_store_data_m[`LM32_BYTE_3_RNG] = byte_enable_m[3] ? store_data_m[`LM32_BYTE_3_RNG] : dram_data_m[`LM32_BYTE_3_RNG];
philpem@0 478 `endif
philpem@0 479
philpem@0 480 `ifdef CFG_IROM_ENABLED
philpem@0 481 // Only replace selected bytes
philpem@0 482 assign irom_store_data_m[`LM32_BYTE_0_RNG] = byte_enable_m[0] ? store_data_m[`LM32_BYTE_0_RNG] : irom_data_m[`LM32_BYTE_0_RNG];
philpem@0 483 assign irom_store_data_m[`LM32_BYTE_1_RNG] = byte_enable_m[1] ? store_data_m[`LM32_BYTE_1_RNG] : irom_data_m[`LM32_BYTE_1_RNG];
philpem@0 484 assign irom_store_data_m[`LM32_BYTE_2_RNG] = byte_enable_m[2] ? store_data_m[`LM32_BYTE_2_RNG] : irom_data_m[`LM32_BYTE_2_RNG];
philpem@0 485 assign irom_store_data_m[`LM32_BYTE_3_RNG] = byte_enable_m[3] ? store_data_m[`LM32_BYTE_3_RNG] : irom_data_m[`LM32_BYTE_3_RNG];
philpem@0 486 `endif
philpem@0 487
philpem@0 488 `ifdef CFG_IROM_ENABLED
philpem@0 489 // Instead of implementing a byte-addressable instruction ROM (for store byte instruction),
philpem@0 490 // a load-and-store architecture is used wherein a 32-bit value is loaded, the requisite
philpem@0 491 // byte is replaced, and the whole 32-bit value is written back
philpem@0 492
philpem@0 493 assign irom_address_xm = ((irom_select_m == `TRUE) && (store_q_m == `TRUE))
philpem@0 494 ? load_store_address_m
philpem@0 495 : load_store_address_x;
philpem@0 496
philpem@0 497 // All store instructions perform a write operation in the M stage
philpem@0 498 assign irom_we_xm = (irom_select_m == `TRUE)
philpem@0 499 && (store_q_m == `TRUE);
philpem@0 500
philpem@0 501 // A single port in instruction ROM is available to load-store unit for doing loads/stores.
philpem@0 502 // Since every store requires a load (in X stage) and then a store (in M stage), we cannot
philpem@0 503 // allow load (or store) instructions sequentially after the store instructions to proceed
philpem@0 504 // until the store instruction has vacated M stage (i.e., completed the store operation)
philpem@0 505 assign irom_stall_request_x = (irom_select_x == `TRUE)
philpem@0 506 && (store_q_x == `TRUE);
philpem@0 507 `endif
philpem@0 508
philpem@0 509 `ifdef CFG_DCACHE_ENABLED
philpem@0 510 `ifdef CFG_DRAM_ENABLED
philpem@0 511 `ifdef CFG_IROM_ENABLED
philpem@0 512 // WB + DC + DRAM + IROM
philpem@0 513 assign data_m = wb_select_m == `TRUE
philpem@0 514 ? wb_data_m
philpem@0 515 : dram_select_m == `TRUE
philpem@0 516 ? dram_data_m
philpem@0 517 : irom_select_m == `TRUE
philpem@0 518 ? irom_data_m
philpem@0 519 : dcache_data_m;
philpem@0 520 `else
philpem@0 521 // WB + DC + DRAM
philpem@0 522 assign data_m = wb_select_m == `TRUE
philpem@0 523 ? wb_data_m
philpem@0 524 : dram_select_m == `TRUE
philpem@0 525 ? dram_data_m
philpem@0 526 : dcache_data_m;
philpem@0 527 `endif
philpem@0 528 `else
philpem@0 529 `ifdef CFG_IROM_ENABLED
philpem@0 530 // WB + DC + IROM
philpem@0 531 assign data_m = wb_select_m == `TRUE
philpem@0 532 ? wb_data_m
philpem@0 533 : irom_select_m == `TRUE
philpem@0 534 ? irom_data_m
philpem@0 535 : dcache_data_m;
philpem@0 536 `else
philpem@0 537 // WB + DC
philpem@0 538 assign data_m = wb_select_m == `TRUE
philpem@0 539 ? wb_data_m
philpem@0 540 : dcache_data_m;
philpem@0 541 `endif
philpem@0 542 `endif
philpem@0 543 `else
philpem@0 544 `ifdef CFG_DRAM_ENABLED
philpem@0 545 `ifdef CFG_IROM_ENABLED
philpem@0 546 // WB + DRAM + IROM
philpem@0 547 assign data_m = wb_select_m == `TRUE
philpem@0 548 ? wb_data_m
philpem@0 549 : dram_select_m == `TRUE
philpem@0 550 ? dram_data_m
philpem@0 551 : irom_data_m;
philpem@0 552 `else
philpem@0 553 // WB + DRAM
philpem@0 554 assign data_m = wb_select_m == `TRUE
philpem@0 555 ? wb_data_m
philpem@0 556 : dram_data_m;
philpem@0 557 `endif
philpem@0 558 `else
philpem@0 559 `ifdef CFG_IROM_ENABLED
philpem@0 560 // WB + IROM
philpem@0 561 assign data_m = wb_select_m == `TRUE
philpem@0 562 ? wb_data_m
philpem@0 563 : irom_data_m;
philpem@0 564 `else
philpem@0 565 // WB
philpem@0 566 assign data_m = wb_data_m;
philpem@0 567 `endif
philpem@0 568 `endif
philpem@0 569 `endif
philpem@0 570
philpem@0 571 // Sub-word selection and sign/zero-extension for loads
philpem@0 572 always @(*)
philpem@0 573 begin
philpem@0 574 casez ({size_w, load_store_address_w[1:0]})
philpem@0 575 {`LM32_SIZE_BYTE, 2'b11}: load_data_w = {{24{sign_extend_w & data_w[7]}}, data_w[7:0]};
philpem@0 576 {`LM32_SIZE_BYTE, 2'b10}: load_data_w = {{24{sign_extend_w & data_w[15]}}, data_w[15:8]};
philpem@0 577 {`LM32_SIZE_BYTE, 2'b01}: load_data_w = {{24{sign_extend_w & data_w[23]}}, data_w[23:16]};
philpem@0 578 {`LM32_SIZE_BYTE, 2'b00}: load_data_w = {{24{sign_extend_w & data_w[31]}}, data_w[31:24]};
philpem@0 579 {`LM32_SIZE_HWORD, 2'b1?}: load_data_w = {{16{sign_extend_w & data_w[15]}}, data_w[15:0]};
philpem@0 580 {`LM32_SIZE_HWORD, 2'b0?}: load_data_w = {{16{sign_extend_w & data_w[31]}}, data_w[31:16]};
philpem@0 581 {`LM32_SIZE_WORD, 2'b??}: load_data_w = data_w;
philpem@0 582 default: load_data_w = {`LM32_WORD_WIDTH{1'bx}};
philpem@0 583 endcase
philpem@0 584 end
philpem@0 585
philpem@0 586 // Unused/constant Wishbone signals
philpem@0 587 assign d_bte_o = `LM32_BTYPE_LINEAR;
philpem@0 588
philpem@0 589 `ifdef CFG_DCACHE_ENABLED
philpem@0 590 // Generate signal to indicate last word in cache line
philpem@0 591 generate
philpem@0 592 case (bytes_per_line)
philpem@0 593 4:
philpem@0 594 begin
philpem@0 595 assign first_cycle_type = `LM32_CTYPE_END;
philpem@0 596 assign next_cycle_type = `LM32_CTYPE_END;
philpem@0 597 assign last_word = `TRUE;
philpem@0 598 assign first_address = {dcache_refill_address[`LM32_WORD_WIDTH-1:2], 2'b00};
philpem@0 599 end
philpem@0 600 8:
philpem@0 601 begin
philpem@0 602 assign first_cycle_type = `LM32_CTYPE_INCREMENTING;
philpem@0 603 assign next_cycle_type = `LM32_CTYPE_END;
philpem@0 604 assign last_word = (&d_adr_o[addr_offset_msb:addr_offset_lsb]) == 1'b1;
philpem@0 605 assign first_address = {dcache_refill_address[`LM32_WORD_WIDTH-1:addr_offset_msb+1], {addr_offset_width{1'b0}}, 2'b00};
philpem@0 606 end
philpem@0 607 16:
philpem@0 608 begin
philpem@0 609 assign first_cycle_type = `LM32_CTYPE_INCREMENTING;
philpem@0 610 assign next_cycle_type = d_adr_o[addr_offset_msb] == 1'b1 ? `LM32_CTYPE_END : `LM32_CTYPE_INCREMENTING;
philpem@0 611 assign last_word = (&d_adr_o[addr_offset_msb:addr_offset_lsb]) == 1'b1;
philpem@0 612 assign first_address = {dcache_refill_address[`LM32_WORD_WIDTH-1:addr_offset_msb+1], {addr_offset_width{1'b0}}, 2'b00};
philpem@0 613 end
philpem@0 614 endcase
philpem@0 615 endgenerate
philpem@0 616 `endif
philpem@0 617
philpem@0 618 /////////////////////////////////////////////////////
philpem@0 619 // Sequential Logic
philpem@0 620 /////////////////////////////////////////////////////
philpem@0 621
philpem@0 622 // Data Wishbone interface
philpem@0 623 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 624 begin
philpem@0 625 if (rst_i == `TRUE)
philpem@0 626 begin
philpem@27 627 d_cyc_o <= `FALSE;
philpem@27 628 d_stb_o <= `FALSE;
philpem@27 629 d_dat_o <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 630 d_adr_o <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 631 d_sel_o <= {`LM32_BYTE_SELECT_WIDTH{`FALSE}};
philpem@27 632 d_we_o <= `FALSE;
philpem@27 633 d_cti_o <= `LM32_CTYPE_END;
philpem@27 634 d_lock_o <= `FALSE;
philpem@27 635 wb_data_m <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 636 wb_load_complete <= `FALSE;
philpem@27 637 stall_wb_load <= `FALSE;
philpem@0 638 `ifdef CFG_DCACHE_ENABLED
philpem@27 639 dcache_refill_ready <= `FALSE;
philpem@0 640 `endif
philpem@0 641 end
philpem@0 642 else
philpem@0 643 begin
philpem@0 644 `ifdef CFG_DCACHE_ENABLED
philpem@0 645 // Refill ready should only be asserted for a single cycle
philpem@27 646 dcache_refill_ready <= `FALSE;
philpem@0 647 `endif
philpem@0 648 // Is a Wishbone cycle already in progress?
philpem@0 649 if (d_cyc_o == `TRUE)
philpem@0 650 begin
philpem@0 651 // Is the cycle complete?
philpem@0 652 if ((d_ack_i == `TRUE) || (d_err_i == `TRUE))
philpem@0 653 begin
philpem@0 654 `ifdef CFG_DCACHE_ENABLED
philpem@0 655 if ((dcache_refilling == `TRUE) && (!last_word))
philpem@0 656 begin
philpem@0 657 // Fetch next word of cache line
philpem@27 658 d_adr_o[addr_offset_msb:addr_offset_lsb] <= d_adr_o[addr_offset_msb:addr_offset_lsb] + 1'b1;
philpem@0 659 end
philpem@0 660 else
philpem@0 661 `endif
philpem@0 662 begin
philpem@0 663 // Refill/access complete
philpem@27 664 d_cyc_o <= `FALSE;
philpem@27 665 d_stb_o <= `FALSE;
philpem@27 666 d_lock_o <= `FALSE;
philpem@0 667 end
philpem@0 668 `ifdef CFG_DCACHE_ENABLED
philpem@27 669 d_cti_o <= next_cycle_type;
philpem@0 670 // If we are performing a refill, indicate to cache next word of data is ready
philpem@27 671 dcache_refill_ready <= dcache_refilling;
philpem@0 672 `endif
philpem@0 673 // Register data read from Wishbone interface
philpem@27 674 wb_data_m <= d_dat_i;
philpem@0 675 // Don't set when stores complete - otherwise we'll deadlock if load in m stage
philpem@27 676 wb_load_complete <= !d_we_o;
philpem@0 677 end
philpem@0 678 // synthesis translate_off
philpem@0 679 if (d_err_i == `TRUE)
philpem@0 680 $display ("Data bus error. Address: %x", d_adr_o);
philpem@0 681 // synthesis translate_on
philpem@0 682 end
philpem@0 683 else
philpem@0 684 begin
philpem@0 685 `ifdef CFG_DCACHE_ENABLED
philpem@0 686 if (dcache_refill_request == `TRUE)
philpem@0 687 begin
philpem@0 688 // Start cache refill
philpem@27 689 d_adr_o <= first_address;
philpem@27 690 d_cyc_o <= `TRUE;
philpem@27 691 d_sel_o <= {`LM32_WORD_WIDTH/8{`TRUE}};
philpem@27 692 d_stb_o <= `TRUE;
philpem@27 693 d_we_o <= `FALSE;
philpem@27 694 d_cti_o <= first_cycle_type;
philpem@27 695 //d_lock_o <= `TRUE;
philpem@0 696 end
philpem@0 697 else
philpem@0 698 `endif
philpem@0 699 if ( (store_q_m == `TRUE)
philpem@0 700 && (stall_m == `FALSE)
philpem@0 701 `ifdef CFG_DRAM_ENABLED
philpem@0 702 && (dram_select_m == `FALSE)
philpem@0 703 `endif
philpem@0 704 `ifdef CFG_IROM_ENABLED
philpem@0 705 && (irom_select_m == `FALSE)
philpem@0 706 `endif
philpem@0 707 )
philpem@0 708 begin
philpem@0 709 // Data cache is write through, so all stores go to memory
philpem@27 710 d_dat_o <= store_data_m;
philpem@27 711 d_adr_o <= load_store_address_m;
philpem@27 712 d_cyc_o <= `TRUE;
philpem@27 713 d_sel_o <= byte_enable_m;
philpem@27 714 d_stb_o <= `TRUE;
philpem@27 715 d_we_o <= `TRUE;
philpem@27 716 d_cti_o <= `LM32_CTYPE_END;
philpem@0 717 end
philpem@0 718 else if ( (load_q_m == `TRUE)
philpem@0 719 && (wb_select_m == `TRUE)
philpem@0 720 && (wb_load_complete == `FALSE)
philpem@0 721 // stall_m will be TRUE, because stall_wb_load will be TRUE
philpem@0 722 )
philpem@0 723 begin
philpem@0 724 // Read requested address
philpem@27 725 stall_wb_load <= `FALSE;
philpem@27 726 d_adr_o <= load_store_address_m;
philpem@27 727 d_cyc_o <= `TRUE;
philpem@27 728 d_sel_o <= byte_enable_m;
philpem@27 729 d_stb_o <= `TRUE;
philpem@27 730 d_we_o <= `FALSE;
philpem@27 731 d_cti_o <= `LM32_CTYPE_END;
philpem@0 732 end
philpem@0 733 end
philpem@0 734 // Clear load/store complete flag when instruction leaves M stage
philpem@0 735 if (stall_m == `FALSE)
philpem@27 736 wb_load_complete <= `FALSE;
philpem@0 737 // When a Wishbone load first enters the M stage, we need to stall it
philpem@0 738 if ((load_q_x == `TRUE) && (wb_select_x == `TRUE) && (stall_x == `FALSE))
philpem@27 739 stall_wb_load <= `TRUE;
philpem@0 740 // Clear stall request if load instruction is killed
philpem@0 741 if ((kill_m == `TRUE) || (exception_m == `TRUE))
philpem@27 742 stall_wb_load <= `FALSE;
philpem@0 743 end
philpem@0 744 end
philpem@0 745
philpem@0 746 // Pipeline registers
philpem@0 747
philpem@0 748 // X/M stage pipeline registers
philpem@0 749 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 750 begin
philpem@0 751 if (rst_i == `TRUE)
philpem@0 752 begin
philpem@27 753 sign_extend_m <= `FALSE;
philpem@27 754 size_m <= 2'b00;
philpem@27 755 byte_enable_m <= `FALSE;
philpem@27 756 store_data_m <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 757 `ifdef CFG_DCACHE_ENABLED
philpem@27 758 dcache_select_m <= `FALSE;
philpem@0 759 `endif
philpem@0 760 `ifdef CFG_DRAM_ENABLED
philpem@27 761 dram_select_m <= `FALSE;
philpem@0 762 `endif
philpem@0 763 `ifdef CFG_IROM_ENABLED
philpem@27 764 irom_select_m <= `FALSE;
philpem@0 765 `endif
philpem@27 766 wb_select_m <= `FALSE;
philpem@0 767 end
philpem@0 768 else
philpem@0 769 begin
philpem@0 770 if (stall_m == `FALSE)
philpem@0 771 begin
philpem@27 772 sign_extend_m <= sign_extend_x;
philpem@27 773 size_m <= size_x;
philpem@27 774 byte_enable_m <= byte_enable_x;
philpem@27 775 store_data_m <= store_data_x;
philpem@0 776 `ifdef CFG_DCACHE_ENABLED
philpem@27 777 dcache_select_m <= dcache_select_x;
philpem@0 778 `endif
philpem@0 779 `ifdef CFG_DRAM_ENABLED
philpem@27 780 dram_select_m <= dram_select_x;
philpem@0 781 `endif
philpem@0 782 `ifdef CFG_IROM_ENABLED
philpem@27 783 irom_select_m <= irom_select_x;
philpem@0 784 `endif
philpem@27 785 wb_select_m <= wb_select_x;
philpem@0 786 end
philpem@0 787 end
philpem@0 788 end
philpem@0 789
philpem@0 790 // M/W stage pipeline registers
philpem@0 791 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 792 begin
philpem@0 793 if (rst_i == `TRUE)
philpem@0 794 begin
philpem@27 795 size_w <= 2'b00;
philpem@27 796 data_w <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 797 sign_extend_w <= `FALSE;
philpem@0 798 end
philpem@0 799 else
philpem@0 800 begin
philpem@27 801 size_w <= size_m;
philpem@27 802 data_w <= data_m;
philpem@27 803 sign_extend_w <= sign_extend_m;
philpem@0 804 end
philpem@0 805 end
philpem@0 806
philpem@0 807 /////////////////////////////////////////////////////
philpem@0 808 // Behavioural Logic
philpem@0 809 /////////////////////////////////////////////////////
philpem@0 810
philpem@0 811 // synthesis translate_off
philpem@0 812
philpem@0 813 // Check for non-aligned loads or stores
philpem@0 814 always @(posedge clk_i)
philpem@0 815 begin
philpem@0 816 if (((load_q_m == `TRUE) || (store_q_m == `TRUE)) && (stall_m == `FALSE))
philpem@0 817 begin
philpem@0 818 if ((size_m === `LM32_SIZE_HWORD) && (load_store_address_m[0] !== 1'b0))
philpem@0 819 $display ("Warning: Non-aligned halfword access. Address: 0x%0x Time: %0t.", load_store_address_m, $time);
philpem@0 820 if ((size_m === `LM32_SIZE_WORD) && (load_store_address_m[1:0] !== 2'b00))
philpem@0 821 $display ("Warning: Non-aligned word access. Address: 0x%0x Time: %0t.", load_store_address_m, $time);
philpem@0 822 end
philpem@0 823 end
philpem@0 824
philpem@0 825 // synthesis translate_on
philpem@0 826
philpem@0 827 endmodule