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