lm32_instruction_unit.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 0
cd0b58aa6f83
child 8
07be9df9fee8
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_instruction_unit.v
philpem@0 19 // Title : Instruction unit
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 static branch prediction is added. Fetching of
philpem@0 27 // : instructions can also be altered by branches predicted in D
philpem@0 28 // : stage of pipeline, and mispredicted branches in the X and M
philpem@0 29 // : stages of the pipeline.
philpem@0 30 // Version : 3.2
philpem@0 31 // : EBRs use SYNC resets instead of ASYNC resets.
philpem@0 32 // Version : 3.3
philpem@0 33 // : Support for a non-cacheable Instruction Memory that has a
philpem@0 34 // : single-cycle access latency. This memory can be accessed by
philpem@0 35 // : data port of LM32 (so that debugger has access to it).
philpem@0 36 // Version : 3.4
philpem@0 37 // : No change
philpem@0 38 // Version : 3.5
philpem@0 39 // : Bug fix: Inline memory is correctly generated if it is not a
philpem@0 40 // : power-of-two.
philpem@0 41 // : Bug fix: Fixed a bug that caused LM32 (configured without
philpem@0 42 // : instruction cache) to lock up in to an infinite loop due to a
philpem@0 43 // : instruction bus error when EBA was set to instruction inline
philpem@0 44 // : memory.
philpem@0 45 // =============================================================================
philpem@0 46
philpem@0 47 `include "lm32_include.v"
philpem@0 48
philpem@0 49 /////////////////////////////////////////////////////
philpem@0 50 // Module interface
philpem@0 51 /////////////////////////////////////////////////////
philpem@0 52
philpem@0 53 module lm32_instruction_unit (
philpem@0 54 // ----- Inputs -------
philpem@0 55 clk_i,
philpem@0 56 rst_i,
philpem@0 57 // From pipeline
philpem@0 58 stall_a,
philpem@0 59 stall_f,
philpem@0 60 stall_d,
philpem@0 61 stall_x,
philpem@0 62 stall_m,
philpem@0 63 valid_f,
philpem@0 64 valid_d,
philpem@0 65 kill_f,
philpem@0 66 branch_predict_taken_d,
philpem@0 67 branch_predict_address_d,
philpem@0 68 `ifdef CFG_FAST_UNCONDITIONAL_BRANCH
philpem@0 69 branch_taken_x,
philpem@0 70 branch_target_x,
philpem@0 71 `endif
philpem@0 72 exception_m,
philpem@0 73 branch_taken_m,
philpem@0 74 branch_mispredict_taken_m,
philpem@0 75 branch_target_m,
philpem@0 76 `ifdef CFG_ICACHE_ENABLED
philpem@0 77 iflush,
philpem@0 78 `endif
philpem@0 79 `ifdef CFG_DCACHE_ENABLED
philpem@0 80 dcache_restart_request,
philpem@0 81 dcache_refill_request,
philpem@0 82 dcache_refilling,
philpem@0 83 `endif
philpem@0 84 `ifdef CFG_IROM_ENABLED
philpem@0 85 irom_store_data_m,
philpem@0 86 irom_address_xm,
philpem@0 87 irom_we_xm,
philpem@0 88 `endif
philpem@0 89 `ifdef CFG_IWB_ENABLED
philpem@0 90 // From Wishbone
philpem@0 91 i_dat_i,
philpem@0 92 i_ack_i,
philpem@0 93 i_err_i,
philpem@0 94 i_rty_i,
philpem@0 95 `endif
philpem@0 96 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 97 jtag_read_enable,
philpem@0 98 jtag_write_enable,
philpem@0 99 jtag_write_data,
philpem@0 100 jtag_address,
philpem@0 101 `endif
philpem@0 102 // ----- Outputs -------
philpem@0 103 // To pipeline
philpem@0 104 pc_f,
philpem@0 105 pc_d,
philpem@0 106 pc_x,
philpem@0 107 pc_m,
philpem@0 108 pc_w,
philpem@0 109 `ifdef CFG_ICACHE_ENABLED
philpem@0 110 icache_stall_request,
philpem@0 111 icache_restart_request,
philpem@0 112 icache_refill_request,
philpem@0 113 icache_refilling,
philpem@0 114 `endif
philpem@0 115 `ifdef CFG_IROM_ENABLED
philpem@0 116 irom_data_m,
philpem@0 117 `endif
philpem@0 118 `ifdef CFG_IWB_ENABLED
philpem@0 119 // To Wishbone
philpem@0 120 i_dat_o,
philpem@0 121 i_adr_o,
philpem@0 122 i_cyc_o,
philpem@0 123 i_sel_o,
philpem@0 124 i_stb_o,
philpem@0 125 i_we_o,
philpem@0 126 i_cti_o,
philpem@0 127 i_lock_o,
philpem@0 128 i_bte_o,
philpem@0 129 `endif
philpem@0 130 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 131 jtag_read_data,
philpem@0 132 jtag_access_complete,
philpem@0 133 `endif
philpem@0 134 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 135 bus_error_d,
philpem@0 136 `endif
philpem@0 137 `ifdef CFG_EBR_POSEDGE_REGISTER_FILE
philpem@0 138 instruction_f,
philpem@0 139 `endif
philpem@0 140 instruction_d
philpem@0 141 );
philpem@0 142
philpem@0 143 /////////////////////////////////////////////////////
philpem@0 144 // Parameters
philpem@0 145 /////////////////////////////////////////////////////
philpem@0 146
philpem@0 147 parameter associativity = 1; // Associativity of the cache (Number of ways)
philpem@0 148 parameter sets = 512; // Number of sets
philpem@0 149 parameter bytes_per_line = 16; // Number of bytes per cache line
philpem@0 150 parameter base_address = 0; // Base address of cachable memory
philpem@0 151 parameter limit = 0; // Limit (highest address) of cachable memory
philpem@0 152
philpem@0 153 // For bytes_per_line == 4, we set 1 so part-select range isn't reversed, even though not really used
philpem@0 154 localparam addr_offset_width = bytes_per_line == 4 ? 1 : clogb2(bytes_per_line)-1-2;
philpem@0 155 localparam addr_offset_lsb = 2;
philpem@0 156 localparam addr_offset_msb = (addr_offset_lsb+addr_offset_width-1);
philpem@0 157
philpem@0 158 /////////////////////////////////////////////////////
philpem@0 159 // Inputs
philpem@0 160 /////////////////////////////////////////////////////
philpem@0 161
philpem@0 162 input clk_i; // Clock
philpem@0 163 input rst_i; // Reset
philpem@0 164
philpem@0 165 input stall_a; // Stall A stage instruction
philpem@0 166 input stall_f; // Stall F stage instruction
philpem@0 167 input stall_d; // Stall D stage instruction
philpem@0 168 input stall_x; // Stall X stage instruction
philpem@0 169 input stall_m; // Stall M stage instruction
philpem@0 170 input valid_f; // Instruction in F stage is valid
philpem@0 171 input valid_d; // Instruction in D stage is valid
philpem@0 172 input kill_f; // Kill instruction in F stage
philpem@0 173
philpem@0 174 input branch_predict_taken_d; // Branch is predicted taken in D stage
philpem@0 175 input [`LM32_PC_RNG] branch_predict_address_d; // Branch target address
philpem@0 176
philpem@0 177 `ifdef CFG_FAST_UNCONDITIONAL_BRANCH
philpem@0 178 input branch_taken_x; // Branch instruction in X stage is taken
philpem@0 179 input [`LM32_PC_RNG] branch_target_x; // Target PC of X stage branch instruction
philpem@0 180 `endif
philpem@0 181 input exception_m;
philpem@0 182 input branch_taken_m; // Branch instruction in M stage is taken
philpem@0 183 input branch_mispredict_taken_m; // Branch instruction in M stage is mispredicted as taken
philpem@0 184 input [`LM32_PC_RNG] branch_target_m; // Target PC of M stage branch instruction
philpem@0 185
philpem@0 186 `ifdef CFG_ICACHE_ENABLED
philpem@0 187 input iflush; // Flush instruction cache
philpem@0 188 `endif
philpem@0 189 `ifdef CFG_DCACHE_ENABLED
philpem@0 190 input dcache_restart_request; // Restart instruction that caused a data cache miss
philpem@0 191 input dcache_refill_request; // Request to refill data cache
philpem@0 192 input dcache_refilling;
philpem@0 193 `endif
philpem@0 194
philpem@0 195 `ifdef CFG_IROM_ENABLED
philpem@0 196 input [`LM32_WORD_RNG] irom_store_data_m; // Data from load-store unit
philpem@0 197 input [`LM32_WORD_RNG] irom_address_xm; // Address from load-store unit
philpem@0 198 input irom_we_xm; // Indicates if memory operation is load or store
philpem@0 199 `endif
philpem@0 200
philpem@0 201 `ifdef CFG_IWB_ENABLED
philpem@0 202 input [`LM32_WORD_RNG] i_dat_i; // Instruction Wishbone interface read data
philpem@0 203 input i_ack_i; // Instruction Wishbone interface acknowledgement
philpem@0 204 input i_err_i; // Instruction Wishbone interface error
philpem@0 205 input i_rty_i; // Instruction Wishbone interface retry
philpem@0 206 `endif
philpem@0 207
philpem@0 208 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 209 input jtag_read_enable; // JTAG read memory request
philpem@0 210 input jtag_write_enable; // JTAG write memory request
philpem@0 211 input [`LM32_BYTE_RNG] jtag_write_data; // JTAG wrirte data
philpem@0 212 input [`LM32_WORD_RNG] jtag_address; // JTAG read/write address
philpem@0 213 `endif
philpem@0 214
philpem@0 215 /////////////////////////////////////////////////////
philpem@0 216 // Outputs
philpem@0 217 /////////////////////////////////////////////////////
philpem@0 218
philpem@0 219 output [`LM32_PC_RNG] pc_f; // F stage PC
philpem@0 220 reg [`LM32_PC_RNG] pc_f;
philpem@0 221 output [`LM32_PC_RNG] pc_d; // D stage PC
philpem@0 222 reg [`LM32_PC_RNG] pc_d;
philpem@0 223 output [`LM32_PC_RNG] pc_x; // X stage PC
philpem@0 224 reg [`LM32_PC_RNG] pc_x;
philpem@0 225 output [`LM32_PC_RNG] pc_m; // M stage PC
philpem@0 226 reg [`LM32_PC_RNG] pc_m;
philpem@0 227 output [`LM32_PC_RNG] pc_w; // W stage PC
philpem@0 228 reg [`LM32_PC_RNG] pc_w;
philpem@0 229
philpem@0 230 `ifdef CFG_ICACHE_ENABLED
philpem@0 231 output icache_stall_request; // Instruction cache stall request
philpem@0 232 wire icache_stall_request;
philpem@0 233 output icache_restart_request; // Request to restart instruction that cached instruction cache miss
philpem@0 234 wire icache_restart_request;
philpem@0 235 output icache_refill_request; // Instruction cache refill request
philpem@0 236 wire icache_refill_request;
philpem@0 237 output icache_refilling; // Indicates the icache is refilling
philpem@0 238 wire icache_refilling;
philpem@0 239 `endif
philpem@0 240
philpem@0 241 `ifdef CFG_IROM_ENABLED
philpem@0 242 output [`LM32_WORD_RNG] irom_data_m; // Data to load-store unit on load
philpem@0 243 wire [`LM32_WORD_RNG] irom_data_m;
philpem@0 244 `endif
philpem@0 245
philpem@0 246 `ifdef CFG_IWB_ENABLED
philpem@0 247 output [`LM32_WORD_RNG] i_dat_o; // Instruction Wishbone interface write data
philpem@0 248 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 249 reg [`LM32_WORD_RNG] i_dat_o;
philpem@0 250 `else
philpem@0 251 wire [`LM32_WORD_RNG] i_dat_o;
philpem@0 252 `endif
philpem@0 253 output [`LM32_WORD_RNG] i_adr_o; // Instruction Wishbone interface address
philpem@0 254 reg [`LM32_WORD_RNG] i_adr_o;
philpem@0 255 output i_cyc_o; // Instruction Wishbone interface cycle
philpem@0 256 reg i_cyc_o;
philpem@0 257 output [`LM32_BYTE_SELECT_RNG] i_sel_o; // Instruction Wishbone interface byte select
philpem@0 258 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 259 reg [`LM32_BYTE_SELECT_RNG] i_sel_o;
philpem@0 260 `else
philpem@0 261 wire [`LM32_BYTE_SELECT_RNG] i_sel_o;
philpem@0 262 `endif
philpem@0 263 output i_stb_o; // Instruction Wishbone interface strobe
philpem@0 264 reg i_stb_o;
philpem@0 265 output i_we_o; // Instruction Wishbone interface write enable
philpem@0 266 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 267 reg i_we_o;
philpem@0 268 `else
philpem@0 269 wire i_we_o;
philpem@0 270 `endif
philpem@0 271 output [`LM32_CTYPE_RNG] i_cti_o; // Instruction Wishbone interface cycle type
philpem@0 272 reg [`LM32_CTYPE_RNG] i_cti_o;
philpem@0 273 output i_lock_o; // Instruction Wishbone interface lock bus
philpem@0 274 reg i_lock_o;
philpem@0 275 output [`LM32_BTYPE_RNG] i_bte_o; // Instruction Wishbone interface burst type
philpem@0 276 wire [`LM32_BTYPE_RNG] i_bte_o;
philpem@0 277 `endif
philpem@0 278
philpem@0 279 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 280 output [`LM32_BYTE_RNG] jtag_read_data; // Data read for JTAG interface
philpem@0 281 reg [`LM32_BYTE_RNG] jtag_read_data;
philpem@0 282 output jtag_access_complete; // Requested memory access by JTAG interface is complete
philpem@0 283 wire jtag_access_complete;
philpem@0 284 `endif
philpem@0 285
philpem@0 286 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 287 output bus_error_d; // Indicates a bus error occured while fetching the instruction
philpem@0 288 reg bus_error_d;
philpem@0 289 `endif
philpem@0 290 `ifdef CFG_EBR_POSEDGE_REGISTER_FILE
philpem@0 291 output [`LM32_INSTRUCTION_RNG] instruction_f; // F stage instruction (only to have register indices extracted from)
philpem@0 292 wire [`LM32_INSTRUCTION_RNG] instruction_f;
philpem@0 293 `endif
philpem@0 294 output [`LM32_INSTRUCTION_RNG] instruction_d; // D stage instruction to be decoded
philpem@0 295 reg [`LM32_INSTRUCTION_RNG] instruction_d;
philpem@0 296
philpem@0 297 /////////////////////////////////////////////////////
philpem@0 298 // Internal nets and registers
philpem@0 299 /////////////////////////////////////////////////////
philpem@0 300
philpem@0 301 reg [`LM32_PC_RNG] pc_a; // A stage PC
philpem@0 302
philpem@0 303 `ifdef LM32_CACHE_ENABLED
philpem@0 304 reg [`LM32_PC_RNG] restart_address; // Address to restart from after a cache miss
philpem@0 305 `endif
philpem@0 306
philpem@0 307 `ifdef CFG_ICACHE_ENABLED
philpem@0 308 wire icache_read_enable_f; // Indicates if instruction cache miss is valid
philpem@0 309 wire [`LM32_PC_RNG] icache_refill_address; // Address that caused cache miss
philpem@0 310 reg icache_refill_ready; // Indicates when next word of refill data is ready to be written to cache
philpem@0 311 reg [`LM32_INSTRUCTION_RNG] icache_refill_data; // Next word of refill data, fetched from Wishbone
philpem@0 312 wire [`LM32_INSTRUCTION_RNG] icache_data_f; // Instruction fetched from instruction cache
philpem@0 313 wire [`LM32_CTYPE_RNG] first_cycle_type; // First Wishbone cycle type
philpem@0 314 wire [`LM32_CTYPE_RNG] next_cycle_type; // Next Wishbone cycle type
philpem@0 315 wire last_word; // Indicates if this is the last word in the cache line
philpem@0 316 wire [`LM32_PC_RNG] first_address; // First cache refill address
philpem@0 317 `else
philpem@0 318 `ifdef CFG_IWB_ENABLED
philpem@0 319 reg [`LM32_INSTRUCTION_RNG] wb_data_f; // Instruction fetched from Wishbone
philpem@0 320 `endif
philpem@0 321 `endif
philpem@0 322 `ifdef CFG_IROM_ENABLED
philpem@0 323 wire irom_select_a; // Indicates if A stage PC maps to a ROM address
philpem@0 324 reg irom_select_f; // Indicates if F stage PC maps to a ROM address
philpem@0 325 wire [`LM32_INSTRUCTION_RNG] irom_data_f; // Instruction fetched from ROM
philpem@0 326 `endif
philpem@0 327 `ifdef CFG_EBR_POSEDGE_REGISTER_FILE
philpem@0 328 `else
philpem@0 329 wire [`LM32_INSTRUCTION_RNG] instruction_f; // F stage instruction
philpem@0 330 `endif
philpem@0 331 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 332 reg bus_error_f; // Indicates if a bus error occured while fetching the instruction in the F stage
philpem@0 333 `endif
philpem@0 334
philpem@0 335 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 336 reg jtag_access; // Indicates if a JTAG WB access is in progress
philpem@0 337 `endif
philpem@0 338
philpem@0 339 /////////////////////////////////////////////////////
philpem@0 340 // Functions
philpem@0 341 /////////////////////////////////////////////////////
philpem@0 342
philpem@0 343 `include "lm32_functions.v"
philpem@0 344
philpem@0 345 /////////////////////////////////////////////////////
philpem@0 346 // Instantiations
philpem@0 347 /////////////////////////////////////////////////////
philpem@0 348
philpem@0 349 // Instruction ROM
philpem@0 350 `ifdef CFG_IROM_ENABLED
philpem@0 351 pmi_ram_dp_true
philpem@0 352 #(
philpem@0 353 // ----- Parameters -------
philpem@0 354 .pmi_family (`LATTICE_FAMILY),
philpem@0 355
philpem@0 356 //.pmi_addr_depth_a (1 << (clogb2(`CFG_IROM_LIMIT/4-`CFG_IROM_BASE_ADDRESS/4+1)-1)),
philpem@0 357 //.pmi_addr_width_a ((clogb2(`CFG_IROM_LIMIT/4-`CFG_IROM_BASE_ADDRESS/4+1)-1)),
philpem@0 358 //.pmi_data_width_a (`LM32_WORD_WIDTH),
philpem@0 359 //.pmi_addr_depth_b (1 << (clogb2(`CFG_IROM_LIMIT/4-`CFG_IROM_BASE_ADDRESS/4+1)-1)),
philpem@0 360 //.pmi_addr_width_b ((clogb2(`CFG_IROM_LIMIT/4-`CFG_IROM_BASE_ADDRESS/4+1)-1)),
philpem@0 361 //.pmi_data_width_b (`LM32_WORD_WIDTH),
philpem@0 362
philpem@0 363 .pmi_addr_depth_a (`CFG_IROM_LIMIT/4-`CFG_IROM_BASE_ADDRESS/4+1),
philpem@0 364 .pmi_addr_width_a (clogb2_v1(`CFG_IROM_LIMIT/4-`CFG_IROM_BASE_ADDRESS/4+1)),
philpem@0 365 .pmi_data_width_a (`LM32_WORD_WIDTH),
philpem@0 366 .pmi_addr_depth_b (`CFG_IROM_LIMIT/4-`CFG_IROM_BASE_ADDRESS/4+1),
philpem@0 367 .pmi_addr_width_b (clogb2_v1(`CFG_IROM_LIMIT/4-`CFG_IROM_BASE_ADDRESS/4+1)),
philpem@0 368 .pmi_data_width_b (`LM32_WORD_WIDTH),
philpem@0 369
philpem@0 370 .pmi_regmode_a ("noreg"),
philpem@0 371 .pmi_regmode_b ("noreg"),
philpem@0 372 .pmi_gsr ("enable"),
philpem@0 373 .pmi_resetmode ("sync"),
philpem@0 374 .pmi_init_file (`CFG_IROM_INIT_FILE),
philpem@0 375 .pmi_init_file_format (`CFG_IROM_INIT_FILE_FORMAT),
philpem@0 376 .module_type ("pmi_ram_dp_true")
philpem@0 377 )
philpem@0 378 ram (
philpem@0 379 // ----- Inputs -------
philpem@0 380 .ClockA (clk_i),
philpem@0 381 .ClockB (clk_i),
philpem@0 382 .ResetA (rst_i),
philpem@0 383 .ResetB (rst_i),
philpem@0 384 .DataInA ({32{1'b0}}),
philpem@0 385 .DataInB (irom_store_data_m),
philpem@0 386 .AddressA (pc_a[(clogb2(`CFG_IROM_LIMIT/4-`CFG_IROM_BASE_ADDRESS/4+1)-1)+2-1:2]),
philpem@0 387 .AddressB (irom_address_xm[(clogb2(`CFG_IROM_LIMIT/4-`CFG_IROM_BASE_ADDRESS/4+1)-1)+2-1:2]),
philpem@0 388 .ClockEnA (!stall_a),
philpem@0 389 .ClockEnB (!stall_x || !stall_m),
philpem@0 390 .WrA (`FALSE),
philpem@0 391 .WrB (irom_we_xm),
philpem@0 392 // ----- Outputs -------
philpem@0 393 .QA (irom_data_f),
philpem@0 394 .QB (irom_data_m)
philpem@0 395 );
philpem@0 396 `endif
philpem@0 397
philpem@0 398 `ifdef CFG_ICACHE_ENABLED
philpem@0 399 // Instruction cache
philpem@0 400 lm32_icache #(
philpem@0 401 .associativity (associativity),
philpem@0 402 .sets (sets),
philpem@0 403 .bytes_per_line (bytes_per_line),
philpem@0 404 .base_address (base_address),
philpem@0 405 .limit (limit)
philpem@0 406 ) icache (
philpem@0 407 // ----- Inputs -----
philpem@0 408 .clk_i (clk_i),
philpem@0 409 .rst_i (rst_i),
philpem@0 410 .stall_a (stall_a),
philpem@0 411 .stall_f (stall_f),
philpem@0 412 .branch_predict_taken_d (branch_predict_taken_d),
philpem@0 413 .valid_d (valid_d),
philpem@0 414 .address_a (pc_a),
philpem@0 415 .address_f (pc_f),
philpem@0 416 .read_enable_f (icache_read_enable_f),
philpem@0 417 .refill_ready (icache_refill_ready),
philpem@0 418 .refill_data (icache_refill_data),
philpem@0 419 .iflush (iflush),
philpem@0 420 // ----- Outputs -----
philpem@0 421 .stall_request (icache_stall_request),
philpem@0 422 .restart_request (icache_restart_request),
philpem@0 423 .refill_request (icache_refill_request),
philpem@0 424 .refill_address (icache_refill_address),
philpem@0 425 .refilling (icache_refilling),
philpem@0 426 .inst (icache_data_f)
philpem@0 427 );
philpem@0 428 `endif
philpem@0 429
philpem@0 430 /////////////////////////////////////////////////////
philpem@0 431 // Combinational Logic
philpem@0 432 /////////////////////////////////////////////////////
philpem@0 433
philpem@0 434 `ifdef CFG_ICACHE_ENABLED
philpem@0 435 // Generate signal that indicates when instruction cache misses are valid
philpem@0 436 assign icache_read_enable_f = (valid_f == `TRUE)
philpem@0 437 && (kill_f == `FALSE)
philpem@0 438 `ifdef CFG_DCACHE_ENABLED
philpem@0 439 && (dcache_restart_request == `FALSE)
philpem@0 440 `endif
philpem@0 441 `ifdef CFG_IROM_ENABLED
philpem@0 442 && (irom_select_f == `FALSE)
philpem@0 443 `endif
philpem@0 444 ;
philpem@0 445 `endif
philpem@0 446
philpem@0 447 // Compute address of next instruction to fetch
philpem@0 448 always @(*)
philpem@0 449 begin
philpem@0 450 // The request from the latest pipeline stage must take priority
philpem@0 451 `ifdef CFG_DCACHE_ENABLED
philpem@0 452 if (dcache_restart_request == `TRUE)
philpem@0 453 pc_a = restart_address;
philpem@0 454 else
philpem@0 455 `endif
philpem@0 456 if (branch_taken_m == `TRUE)
philpem@0 457 if ((branch_mispredict_taken_m == `TRUE) && (exception_m == `FALSE))
philpem@0 458 pc_a = pc_x;
philpem@0 459 else
philpem@0 460 pc_a = branch_target_m;
philpem@0 461 `ifdef CFG_FAST_UNCONDITIONAL_BRANCH
philpem@0 462 else if (branch_taken_x == `TRUE)
philpem@0 463 pc_a = branch_target_x;
philpem@0 464 `endif
philpem@0 465 else
philpem@0 466 if ( (valid_d == `TRUE) && (branch_predict_taken_d == `TRUE) )
philpem@0 467 pc_a = branch_predict_address_d;
philpem@0 468 else
philpem@0 469 `ifdef CFG_ICACHE_ENABLED
philpem@0 470 if (icache_restart_request == `TRUE)
philpem@0 471 pc_a = restart_address;
philpem@0 472 else
philpem@0 473 `endif
philpem@0 474 pc_a = pc_f + 1'b1;
philpem@0 475 end
philpem@0 476
philpem@0 477 // Select where instruction should be fetched from
philpem@0 478 `ifdef CFG_IROM_ENABLED
philpem@0 479 assign irom_select_a = ({pc_a, 2'b00} >= `CFG_IROM_BASE_ADDRESS) && ({pc_a, 2'b00} <= `CFG_IROM_LIMIT);
philpem@0 480 `endif
philpem@0 481
philpem@0 482 // Select instruction from selected source
philpem@0 483 `ifdef CFG_ICACHE_ENABLED
philpem@0 484 `ifdef CFG_IROM_ENABLED
philpem@0 485 assign instruction_f = irom_select_f == `TRUE ? irom_data_f : icache_data_f;
philpem@0 486 `else
philpem@0 487 assign instruction_f = icache_data_f;
philpem@0 488 `endif
philpem@0 489 `else
philpem@0 490 `ifdef CFG_IROM_ENABLED
philpem@0 491 `ifdef CFG_IWB_ENABLED
philpem@0 492 assign instruction_f = irom_select_f == `TRUE ? irom_data_f : wb_data_f;
philpem@0 493 `else
philpem@0 494 assign instruction_f = irom_data_f;
philpem@0 495 `endif
philpem@0 496 `else
philpem@0 497 assign instruction_f = wb_data_f;
philpem@0 498 `endif
philpem@0 499 `endif
philpem@0 500
philpem@0 501 // Unused/constant Wishbone signals
philpem@0 502 `ifdef CFG_IWB_ENABLED
philpem@0 503 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 504 `else
philpem@0 505 assign i_dat_o = 32'd0;
philpem@0 506 assign i_we_o = `FALSE;
philpem@0 507 assign i_sel_o = 4'b1111;
philpem@0 508 `endif
philpem@0 509 assign i_bte_o = `LM32_BTYPE_LINEAR;
philpem@0 510 `endif
philpem@0 511
philpem@0 512 `ifdef CFG_ICACHE_ENABLED
philpem@0 513 // Determine parameters for next cache refill Wishbone access
philpem@0 514 generate
philpem@0 515 case (bytes_per_line)
philpem@0 516 4:
philpem@0 517 begin
philpem@0 518 assign first_cycle_type = `LM32_CTYPE_END;
philpem@0 519 assign next_cycle_type = `LM32_CTYPE_END;
philpem@0 520 assign last_word = `TRUE;
philpem@0 521 assign first_address = icache_refill_address;
philpem@0 522 end
philpem@0 523 8:
philpem@0 524 begin
philpem@0 525 assign first_cycle_type = `LM32_CTYPE_INCREMENTING;
philpem@0 526 assign next_cycle_type = `LM32_CTYPE_END;
philpem@0 527 assign last_word = i_adr_o[addr_offset_msb:addr_offset_lsb] == 1'b1;
philpem@0 528 assign first_address = {icache_refill_address[`LM32_PC_WIDTH+2-1:addr_offset_msb+1], {addr_offset_width{1'b0}}};
philpem@0 529 end
philpem@0 530 16:
philpem@0 531 begin
philpem@0 532 assign first_cycle_type = `LM32_CTYPE_INCREMENTING;
philpem@0 533 assign next_cycle_type = i_adr_o[addr_offset_msb] == 1'b1 ? `LM32_CTYPE_END : `LM32_CTYPE_INCREMENTING;
philpem@0 534 assign last_word = i_adr_o[addr_offset_msb:addr_offset_lsb] == 2'b11;
philpem@0 535 assign first_address = {icache_refill_address[`LM32_PC_WIDTH+2-1:addr_offset_msb+1], {addr_offset_width{1'b0}}};
philpem@0 536 end
philpem@0 537 endcase
philpem@0 538 endgenerate
philpem@0 539 `endif
philpem@0 540
philpem@0 541 /////////////////////////////////////////////////////
philpem@0 542 // Sequential Logic
philpem@0 543 /////////////////////////////////////////////////////
philpem@0 544
philpem@0 545 // PC
philpem@0 546 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 547 begin
philpem@0 548 if (rst_i == `TRUE)
philpem@0 549 begin
philpem@0 550 pc_f <= (`CFG_EBA_RESET-4)/4;
philpem@0 551 pc_d <= {`LM32_PC_WIDTH{1'b0}};
philpem@0 552 pc_x <= {`LM32_PC_WIDTH{1'b0}};
philpem@0 553 pc_m <= {`LM32_PC_WIDTH{1'b0}};
philpem@0 554 pc_w <= {`LM32_PC_WIDTH{1'b0}};
philpem@0 555 end
philpem@0 556 else
philpem@0 557 begin
philpem@0 558 if (stall_f == `FALSE)
philpem@0 559 pc_f <= pc_a;
philpem@0 560 if (stall_d == `FALSE)
philpem@0 561 pc_d <= pc_f;
philpem@0 562 if (stall_x == `FALSE)
philpem@0 563 pc_x <= pc_d;
philpem@0 564 if (stall_m == `FALSE)
philpem@0 565 pc_m <= pc_x;
philpem@0 566 pc_w <= pc_m;
philpem@0 567 end
philpem@0 568 end
philpem@0 569
philpem@0 570 `ifdef LM32_CACHE_ENABLED
philpem@0 571 // Address to restart from after a cache miss has been handled
philpem@0 572 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 573 begin
philpem@0 574 if (rst_i == `TRUE)
philpem@0 575 restart_address <= {`LM32_PC_WIDTH{1'b0}};
philpem@0 576 else
philpem@0 577 begin
philpem@0 578 `ifdef CFG_DCACHE_ENABLED
philpem@0 579 `ifdef CFG_ICACHE_ENABLED
philpem@0 580 // D-cache restart address must take priority, otherwise instructions will be lost
philpem@0 581 if (dcache_refill_request == `TRUE)
philpem@0 582 restart_address <= pc_w;
philpem@0 583 else if ((icache_refill_request == `TRUE) && (!dcache_refilling) && (!dcache_restart_request))
philpem@0 584 restart_address <= icache_refill_address;
philpem@0 585 `else
philpem@0 586 if (dcache_refill_request == `TRUE)
philpem@0 587 restart_address <= pc_w;
philpem@0 588 `endif
philpem@0 589 `else
philpem@0 590 `ifdef CFG_ICACHE_ENABLED
philpem@0 591 if (icache_refill_request == `TRUE)
philpem@0 592 restart_address <= icache_refill_address;
philpem@0 593 `endif
philpem@0 594 `endif
philpem@0 595 end
philpem@0 596 end
philpem@0 597 `endif
philpem@0 598
philpem@0 599 // Record where instruction was fetched from
philpem@0 600 `ifdef CFG_IROM_ENABLED
philpem@0 601 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 602 begin
philpem@0 603 if (rst_i == `TRUE)
philpem@0 604 irom_select_f <= `FALSE;
philpem@0 605 else
philpem@0 606 begin
philpem@0 607 if (stall_f == `FALSE)
philpem@0 608 irom_select_f <= irom_select_a;
philpem@0 609 end
philpem@0 610 end
philpem@0 611 `endif
philpem@0 612
philpem@0 613 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 614 assign jtag_access_complete = (i_cyc_o == `TRUE) && ((i_ack_i == `TRUE) || (i_err_i == `TRUE)) && (jtag_access == `TRUE);
philpem@0 615 always @(*)
philpem@0 616 begin
philpem@0 617 case (jtag_address[1:0])
philpem@0 618 2'b00: jtag_read_data = i_dat_i[`LM32_BYTE_3_RNG];
philpem@0 619 2'b01: jtag_read_data = i_dat_i[`LM32_BYTE_2_RNG];
philpem@0 620 2'b10: jtag_read_data = i_dat_i[`LM32_BYTE_1_RNG];
philpem@0 621 2'b11: jtag_read_data = i_dat_i[`LM32_BYTE_0_RNG];
philpem@0 622 endcase
philpem@0 623 end
philpem@0 624 `endif
philpem@0 625
philpem@0 626 `ifdef CFG_IWB_ENABLED
philpem@0 627 // Instruction Wishbone interface
philpem@0 628 `ifdef CFG_ICACHE_ENABLED
philpem@0 629 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 630 begin
philpem@0 631 if (rst_i == `TRUE)
philpem@0 632 begin
philpem@0 633 i_cyc_o <= `FALSE;
philpem@0 634 i_stb_o <= `FALSE;
philpem@0 635 i_adr_o <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 636 i_cti_o <= `LM32_CTYPE_END;
philpem@0 637 i_lock_o <= `FALSE;
philpem@0 638 icache_refill_data <= {`LM32_INSTRUCTION_WIDTH{1'b0}};
philpem@0 639 icache_refill_ready <= `FALSE;
philpem@0 640 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 641 bus_error_f <= `FALSE;
philpem@0 642 `endif
philpem@0 643 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 644 i_we_o <= `FALSE;
philpem@0 645 i_sel_o <= 4'b1111;
philpem@0 646 jtag_access <= `FALSE;
philpem@0 647 `endif
philpem@0 648 end
philpem@0 649 else
philpem@0 650 begin
philpem@0 651 icache_refill_ready <= `FALSE;
philpem@0 652 // Is a cycle in progress?
philpem@0 653 if (i_cyc_o == `TRUE)
philpem@0 654 begin
philpem@0 655 // Has cycle completed?
philpem@0 656 if ((i_ack_i == `TRUE) || (i_err_i == `TRUE))
philpem@0 657 begin
philpem@0 658 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 659 if (jtag_access == `TRUE)
philpem@0 660 begin
philpem@0 661 i_cyc_o <= `FALSE;
philpem@0 662 i_stb_o <= `FALSE;
philpem@0 663 i_we_o <= `FALSE;
philpem@0 664 jtag_access <= `FALSE;
philpem@0 665 end
philpem@0 666 else
philpem@0 667 `endif
philpem@0 668 begin
philpem@0 669 if (last_word == `TRUE)
philpem@0 670 begin
philpem@0 671 // Cache line fill complete
philpem@0 672 i_cyc_o <= `FALSE;
philpem@0 673 i_stb_o <= `FALSE;
philpem@0 674 i_lock_o <= `FALSE;
philpem@0 675 end
philpem@0 676 // Fetch next word in cache line
philpem@0 677 i_adr_o[addr_offset_msb:addr_offset_lsb] <= i_adr_o[addr_offset_msb:addr_offset_lsb] + 1'b1;
philpem@0 678 i_cti_o <= next_cycle_type;
philpem@0 679 // Write fetched data into instruction cache
philpem@0 680 icache_refill_ready <= `TRUE;
philpem@0 681 icache_refill_data <= i_dat_i;
philpem@0 682 end
philpem@0 683 end
philpem@0 684 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 685 if (i_err_i == `TRUE)
philpem@0 686 begin
philpem@0 687 bus_error_f <= `TRUE;
philpem@0 688 $display ("Instruction bus error. Address: %x", i_adr_o);
philpem@0 689 end
philpem@0 690 `endif
philpem@0 691 end
philpem@0 692 else
philpem@0 693 begin
philpem@0 694 if ((icache_refill_request == `TRUE) && (icache_refill_ready == `FALSE))
philpem@0 695 begin
philpem@0 696 // Read first word of cache line
philpem@0 697 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 698 i_sel_o <= 4'b1111;
philpem@0 699 `endif
philpem@0 700 i_adr_o <= {first_address, 2'b00};
philpem@0 701 i_cyc_o <= `TRUE;
philpem@0 702 i_stb_o <= `TRUE;
philpem@0 703 i_cti_o <= first_cycle_type;
philpem@0 704 //i_lock_o <= `TRUE;
philpem@0 705 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 706 bus_error_f <= `FALSE;
philpem@0 707 `endif
philpem@0 708 end
philpem@0 709 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 710 else
philpem@0 711 begin
philpem@0 712 if ((jtag_read_enable == `TRUE) || (jtag_write_enable == `TRUE))
philpem@0 713 begin
philpem@0 714 case (jtag_address[1:0])
philpem@0 715 2'b00: i_sel_o <= 4'b1000;
philpem@0 716 2'b01: i_sel_o <= 4'b0100;
philpem@0 717 2'b10: i_sel_o <= 4'b0010;
philpem@0 718 2'b11: i_sel_o <= 4'b0001;
philpem@0 719 endcase
philpem@0 720 i_adr_o <= jtag_address;
philpem@0 721 i_dat_o <= {4{jtag_write_data}};
philpem@0 722 i_cyc_o <= `TRUE;
philpem@0 723 i_stb_o <= `TRUE;
philpem@0 724 i_we_o <= jtag_write_enable;
philpem@0 725 i_cti_o <= `LM32_CTYPE_END;
philpem@0 726 jtag_access <= `TRUE;
philpem@0 727 end
philpem@0 728 end
philpem@0 729 `endif
philpem@0 730 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 731 // Clear bus error when exception taken, otherwise they would be
philpem@0 732 // continually generated if exception handler is cached
philpem@0 733 `ifdef CFG_FAST_UNCONDITIONAL_BRANCH
philpem@0 734 if (branch_taken_x == `TRUE)
philpem@0 735 bus_error_f <= `FALSE;
philpem@0 736 `endif
philpem@0 737 if (branch_taken_m == `TRUE)
philpem@0 738 bus_error_f <= `FALSE;
philpem@0 739 `endif
philpem@0 740 end
philpem@0 741 end
philpem@0 742 end
philpem@0 743 `else
philpem@0 744 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 745 begin
philpem@0 746 if (rst_i == `TRUE)
philpem@0 747 begin
philpem@0 748 i_cyc_o <= `FALSE;
philpem@0 749 i_stb_o <= `FALSE;
philpem@0 750 i_adr_o <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 751 i_cti_o <= `LM32_CTYPE_END;
philpem@0 752 i_lock_o <= `FALSE;
philpem@0 753 wb_data_f <= {`LM32_INSTRUCTION_WIDTH{1'b0}};
philpem@0 754 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 755 bus_error_f <= `FALSE;
philpem@0 756 `endif
philpem@0 757 end
philpem@0 758 else
philpem@0 759 begin
philpem@0 760 // Is a cycle in progress?
philpem@0 761 if (i_cyc_o == `TRUE)
philpem@0 762 begin
philpem@0 763 // Has cycle completed?
philpem@0 764 if((i_ack_i == `TRUE) || (i_err_i == `TRUE))
philpem@0 765 begin
philpem@0 766 // Cycle complete
philpem@0 767 i_cyc_o <= `FALSE;
philpem@0 768 i_stb_o <= `FALSE;
philpem@0 769 // Register fetched instruction
philpem@0 770 wb_data_f <= i_dat_i;
philpem@0 771 end
philpem@0 772 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 773 if (i_err_i == `TRUE)
philpem@0 774 begin
philpem@0 775 bus_error_f <= `TRUE;
philpem@0 776 $display ("Instruction bus error. Address: %x", i_adr_o);
philpem@0 777 end
philpem@0 778 `endif
philpem@0 779 end
philpem@0 780 else
philpem@0 781 begin
philpem@0 782 // Wait for an instruction fetch from an external address
philpem@0 783 if ( (stall_a == `FALSE)
philpem@0 784 `ifdef CFG_IROM_ENABLED
philpem@0 785 && (irom_select_a == `FALSE)
philpem@0 786 `endif
philpem@0 787 )
philpem@0 788 begin
philpem@0 789 // Fetch instruction
philpem@0 790 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 791 i_sel_o <= 4'b1111;
philpem@0 792 `endif
philpem@0 793 i_adr_o <= {pc_a, 2'b00};
philpem@0 794 i_cyc_o <= `TRUE;
philpem@0 795 i_stb_o <= `TRUE;
philpem@0 796 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 797 bus_error_f <= `FALSE;
philpem@0 798 `endif
philpem@0 799 end
philpem@0 800 else
philpem@0 801 begin
philpem@0 802 if ( (stall_a == `FALSE)
philpem@0 803 `ifdef CFG_IROM_ENABLED
philpem@0 804 && (irom_select_a == `TRUE)
philpem@0 805 `endif
philpem@0 806 )
philpem@0 807 begin
philpem@0 808 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 809 bus_error_f <= `FALSE;
philpem@0 810 `endif
philpem@0 811 end
philpem@0 812 end
philpem@0 813 end
philpem@0 814 end
philpem@0 815 end
philpem@0 816 `endif
philpem@0 817 `endif
philpem@0 818
philpem@0 819 // Instruction register
philpem@0 820 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 821 begin
philpem@0 822 if (rst_i == `TRUE)
philpem@0 823 begin
philpem@0 824 instruction_d <= {`LM32_INSTRUCTION_WIDTH{1'b0}};
philpem@0 825 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 826 bus_error_d <= `FALSE;
philpem@0 827 `endif
philpem@0 828 end
philpem@0 829 else
philpem@0 830 begin
philpem@0 831 if (stall_d == `FALSE)
philpem@0 832 begin
philpem@0 833 instruction_d <= instruction_f;
philpem@0 834 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 835 bus_error_d <= bus_error_f;
philpem@0 836 `endif
philpem@0 837 end
philpem@0 838 end
philpem@0 839 end
philpem@0 840
philpem@0 841 endmodule