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