Mon, 05 Apr 2010 21:00:31 +0100
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 |