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_cpu.v |
philpem@0 | 40 | // Title : Top-level of CPU. |
philpem@0 | 41 | // Dependencies : lm32_include.v |
philpem@0 | 42 | // |
philpem@26 | 43 | // Version 3.8 |
philpem@26 | 44 | // 1. Feature: Support for dynamically switching EBA to DEBA via a GPIO. |
philpem@26 | 45 | // 2. Bug: EA now reports instruction that caused the data abort, rather than |
philpem@26 | 46 | // next instruction. |
philpem@26 | 47 | // |
philpem@0 | 48 | // Version 3.4 |
philpem@0 | 49 | // 1. Bug Fix: In a tight infinite loop (add, sw, bi) incoming interrupts were |
philpem@0 | 50 | // never serviced. |
philpem@0 | 51 | // |
philpem@0 | 52 | // Version 3.3 |
philpem@0 | 53 | // 1. Feature: Support for memory that is tightly coupled to processor core, and |
philpem@0 | 54 | // has a single-cycle access latency (same as caches). Instruction port has |
philpem@0 | 55 | // access to a dedicated physically-mapped memory. Data port has access to |
philpem@0 | 56 | // a dedicated physically-mapped memory. In order to be able to manipulate |
philpem@0 | 57 | // values in both these memories via the debugger, these memories also |
philpem@0 | 58 | // interface with the data port of LM32. |
philpem@0 | 59 | // 2. Feature: Extended Configuration Register |
philpem@0 | 60 | // 3. Bug Fix: Removed port names that conflict with keywords reserved in System- |
philpem@0 | 61 | // Verilog. |
philpem@0 | 62 | // |
philpem@0 | 63 | // Version 3.2 |
philpem@0 | 64 | // 1. Bug Fix: Single-stepping a load/store to invalid address causes debugger to |
philpem@0 | 65 | // hang. At the same time CPU fails to register data bus error exception. Bug |
philpem@0 | 66 | // is caused because (a) data bus error exception occurs after load/store has |
philpem@0 | 67 | // passed X stage and next sequential instruction (e.g., brk) is already in X |
philpem@0 | 68 | // stage, and (b) data bus error exception had lower priority than, say, brk |
philpem@0 | 69 | // exception. |
philpem@0 | 70 | // 2. Bug Fix: If a brk (or scall/eret/bret) sequentially follows a load/store to |
philpem@0 | 71 | // invalid location, CPU will fail to register data bus error exception. The |
philpem@0 | 72 | // solution is to stall scall/eret/bret/brk instructions in D pipeline stage |
philpem@0 | 73 | // until load/store has completed. |
philpem@0 | 74 | // 3. Feature: Enable precise identification of load/store that causes seg fault. |
philpem@0 | 75 | // 4. SYNC resets used for register file when implemented in EBRs. |
philpem@0 | 76 | // |
philpem@0 | 77 | // Version 3.1 |
philpem@0 | 78 | // 1. Feature: LM32 Register File can now be mapped in to on-chip block RAM (EBR) |
philpem@0 | 79 | // instead of distributed memory by enabling the option in LM32 GUI. |
philpem@0 | 80 | // 2. Feature: LM32 also adds a static branch predictor to improve branch |
philpem@0 | 81 | // performance. All immediate-based forward-pointing branches are predicted |
philpem@0 | 82 | // not-taken. All immediate-based backward-pointing branches are predicted taken. |
philpem@0 | 83 | // |
philpem@0 | 84 | // Version 7.0SP2, 3.0 |
philpem@0 | 85 | // No Change |
philpem@0 | 86 | // |
philpem@0 | 87 | // Version 6.1.17 |
philpem@0 | 88 | // Initial Release |
philpem@0 | 89 | // ============================================================================= |
philpem@0 | 90 | |
philpem@0 | 91 | `include "lm32_include.v" |
philpem@0 | 92 | |
philpem@0 | 93 | ///////////////////////////////////////////////////// |
philpem@0 | 94 | // Module interface |
philpem@0 | 95 | ///////////////////////////////////////////////////// |
philpem@0 | 96 | |
philpem@0 | 97 | module lm32_cpu ( |
philpem@0 | 98 | // ----- Inputs ------- |
philpem@0 | 99 | clk_i, |
philpem@0 | 100 | `ifdef CFG_EBR_NEGEDGE_REGISTER_FILE |
philpem@0 | 101 | clk_n_i, |
philpem@0 | 102 | `endif |
philpem@0 | 103 | rst_i, |
philpem@26 | 104 | `ifdef CFG_DEBUG_ENABLED |
philpem@26 | 105 | `ifdef CFG_ALTERNATE_EBA |
philpem@26 | 106 | at_debug, |
philpem@26 | 107 | `endif |
philpem@26 | 108 | `endif |
philpem@0 | 109 | // From external devices |
philpem@0 | 110 | `ifdef CFG_INTERRUPTS_ENABLED |
philpem@0 | 111 | interrupt_n, |
philpem@0 | 112 | `endif |
philpem@0 | 113 | // From user logic |
philpem@0 | 114 | `ifdef CFG_USER_ENABLED |
philpem@0 | 115 | user_result, |
philpem@0 | 116 | user_complete, |
philpem@0 | 117 | `endif |
philpem@0 | 118 | `ifdef CFG_JTAG_ENABLED |
philpem@0 | 119 | // From JTAG |
philpem@0 | 120 | jtag_clk, |
philpem@0 | 121 | jtag_update, |
philpem@0 | 122 | jtag_reg_q, |
philpem@0 | 123 | jtag_reg_addr_q, |
philpem@0 | 124 | `endif |
philpem@0 | 125 | `ifdef CFG_IWB_ENABLED |
philpem@0 | 126 | // Instruction Wishbone master |
philpem@0 | 127 | I_DAT_I, |
philpem@0 | 128 | I_ACK_I, |
philpem@0 | 129 | I_ERR_I, |
philpem@0 | 130 | I_RTY_I, |
philpem@0 | 131 | `endif |
philpem@0 | 132 | // Data Wishbone master |
philpem@0 | 133 | D_DAT_I, |
philpem@0 | 134 | D_ACK_I, |
philpem@0 | 135 | D_ERR_I, |
philpem@0 | 136 | D_RTY_I, |
philpem@0 | 137 | // ----- Outputs ------- |
philpem@0 | 138 | `ifdef CFG_TRACE_ENABLED |
philpem@0 | 139 | trace_pc, |
philpem@0 | 140 | trace_pc_valid, |
philpem@0 | 141 | trace_exception, |
philpem@0 | 142 | trace_eid, |
philpem@0 | 143 | trace_eret, |
philpem@0 | 144 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 145 | trace_bret, |
philpem@0 | 146 | `endif |
philpem@0 | 147 | `endif |
philpem@0 | 148 | `ifdef CFG_JTAG_ENABLED |
philpem@0 | 149 | jtag_reg_d, |
philpem@0 | 150 | jtag_reg_addr_d, |
philpem@0 | 151 | `endif |
philpem@0 | 152 | `ifdef CFG_USER_ENABLED |
philpem@0 | 153 | user_valid, |
philpem@0 | 154 | user_opcode, |
philpem@0 | 155 | user_operand_0, |
philpem@0 | 156 | user_operand_1, |
philpem@0 | 157 | `endif |
philpem@0 | 158 | `ifdef CFG_IWB_ENABLED |
philpem@0 | 159 | // Instruction Wishbone master |
philpem@0 | 160 | I_DAT_O, |
philpem@0 | 161 | I_ADR_O, |
philpem@0 | 162 | I_CYC_O, |
philpem@0 | 163 | I_SEL_O, |
philpem@0 | 164 | I_STB_O, |
philpem@0 | 165 | I_WE_O, |
philpem@0 | 166 | I_CTI_O, |
philpem@0 | 167 | I_LOCK_O, |
philpem@0 | 168 | I_BTE_O, |
philpem@0 | 169 | `endif |
philpem@0 | 170 | // Data Wishbone master |
philpem@0 | 171 | D_DAT_O, |
philpem@0 | 172 | D_ADR_O, |
philpem@0 | 173 | D_CYC_O, |
philpem@0 | 174 | D_SEL_O, |
philpem@0 | 175 | D_STB_O, |
philpem@0 | 176 | D_WE_O, |
philpem@0 | 177 | D_CTI_O, |
philpem@0 | 178 | D_LOCK_O, |
philpem@0 | 179 | D_BTE_O |
philpem@0 | 180 | ); |
philpem@0 | 181 | |
philpem@0 | 182 | ///////////////////////////////////////////////////// |
philpem@0 | 183 | // Parameters |
philpem@0 | 184 | ///////////////////////////////////////////////////// |
philpem@0 | 185 | |
philpem@0 | 186 | parameter eba_reset = `CFG_EBA_RESET; // Reset value for EBA CSR |
philpem@0 | 187 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 188 | parameter deba_reset = `CFG_DEBA_RESET; // Reset value for DEBA CSR |
philpem@0 | 189 | `endif |
philpem@0 | 190 | |
philpem@0 | 191 | `ifdef CFG_ICACHE_ENABLED |
philpem@0 | 192 | parameter icache_associativity = `CFG_ICACHE_ASSOCIATIVITY; // Associativity of the cache (Number of ways) |
philpem@0 | 193 | parameter icache_sets = `CFG_ICACHE_SETS; // Number of sets |
philpem@0 | 194 | parameter icache_bytes_per_line = `CFG_ICACHE_BYTES_PER_LINE; // Number of bytes per cache line |
philpem@0 | 195 | parameter icache_base_address = `CFG_ICACHE_BASE_ADDRESS; // Base address of cachable memory |
philpem@0 | 196 | parameter icache_limit = `CFG_ICACHE_LIMIT; // Limit (highest address) of cachable memory |
philpem@0 | 197 | `else |
philpem@0 | 198 | parameter icache_associativity = 1; |
philpem@0 | 199 | parameter icache_sets = 512; |
philpem@0 | 200 | parameter icache_bytes_per_line = 16; |
philpem@0 | 201 | parameter icache_base_address = 0; |
philpem@0 | 202 | parameter icache_limit = 0; |
philpem@0 | 203 | `endif |
philpem@0 | 204 | |
philpem@0 | 205 | `ifdef CFG_DCACHE_ENABLED |
philpem@0 | 206 | parameter dcache_associativity = `CFG_DCACHE_ASSOCIATIVITY; // Associativity of the cache (Number of ways) |
philpem@0 | 207 | parameter dcache_sets = `CFG_DCACHE_SETS; // Number of sets |
philpem@0 | 208 | parameter dcache_bytes_per_line = `CFG_DCACHE_BYTES_PER_LINE; // Number of bytes per cache line |
philpem@0 | 209 | parameter dcache_base_address = `CFG_DCACHE_BASE_ADDRESS; // Base address of cachable memory |
philpem@0 | 210 | parameter dcache_limit = `CFG_DCACHE_LIMIT; // Limit (highest address) of cachable memory |
philpem@0 | 211 | `else |
philpem@0 | 212 | parameter dcache_associativity = 1; |
philpem@0 | 213 | parameter dcache_sets = 512; |
philpem@0 | 214 | parameter dcache_bytes_per_line = 16; |
philpem@0 | 215 | parameter dcache_base_address = 0; |
philpem@0 | 216 | parameter dcache_limit = 0; |
philpem@0 | 217 | `endif |
philpem@0 | 218 | |
philpem@0 | 219 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 220 | parameter watchpoints = `CFG_WATCHPOINTS; // Number of h/w watchpoint CSRs |
philpem@0 | 221 | `else |
philpem@0 | 222 | parameter watchpoints = 0; |
philpem@0 | 223 | `endif |
philpem@0 | 224 | `ifdef CFG_ROM_DEBUG_ENABLED |
philpem@0 | 225 | parameter breakpoints = `CFG_BREAKPOINTS; // Number of h/w breakpoint CSRs |
philpem@0 | 226 | `else |
philpem@0 | 227 | parameter breakpoints = 0; |
philpem@0 | 228 | `endif |
philpem@0 | 229 | |
philpem@0 | 230 | `ifdef CFG_INTERRUPTS_ENABLED |
philpem@0 | 231 | parameter interrupts = `CFG_INTERRUPTS; // Number of interrupts |
philpem@0 | 232 | `else |
philpem@0 | 233 | parameter interrupts = 0; |
philpem@0 | 234 | `endif |
philpem@0 | 235 | |
philpem@0 | 236 | ///////////////////////////////////////////////////// |
philpem@0 | 237 | // Inputs |
philpem@0 | 238 | ///////////////////////////////////////////////////// |
philpem@0 | 239 | |
philpem@0 | 240 | input clk_i; // Clock |
philpem@0 | 241 | `ifdef CFG_EBR_NEGEDGE_REGISTER_FILE |
philpem@0 | 242 | input clk_n_i; // Inverted clock |
philpem@0 | 243 | `endif |
philpem@0 | 244 | input rst_i; // Reset |
philpem@0 | 245 | |
philpem@26 | 246 | `ifdef CFG_DEBUG_ENABLED |
philpem@26 | 247 | `ifdef CFG_ALTERNATE_EBA |
philpem@26 | 248 | input at_debug; // GPIO input that maps EBA to DEBA |
philpem@26 | 249 | `endif |
philpem@26 | 250 | `endif |
philpem@26 | 251 | |
philpem@0 | 252 | `ifdef CFG_INTERRUPTS_ENABLED |
philpem@0 | 253 | input [`LM32_INTERRUPT_RNG] interrupt_n; // Interrupt pins, active-low |
philpem@0 | 254 | `endif |
philpem@0 | 255 | |
philpem@0 | 256 | `ifdef CFG_USER_ENABLED |
philpem@0 | 257 | input [`LM32_WORD_RNG] user_result; // User-defined instruction result |
philpem@0 | 258 | input user_complete; // User-defined instruction execution is complete |
philpem@0 | 259 | `endif |
philpem@0 | 260 | |
philpem@0 | 261 | `ifdef CFG_JTAG_ENABLED |
philpem@0 | 262 | input jtag_clk; // JTAG clock |
philpem@0 | 263 | input jtag_update; // JTAG state machine is in data register update state |
philpem@0 | 264 | input [`LM32_BYTE_RNG] jtag_reg_q; |
philpem@0 | 265 | input [2:0] jtag_reg_addr_q; |
philpem@0 | 266 | `endif |
philpem@0 | 267 | |
philpem@0 | 268 | `ifdef CFG_IWB_ENABLED |
philpem@0 | 269 | input [`LM32_WORD_RNG] I_DAT_I; // Instruction Wishbone interface read data |
philpem@0 | 270 | input I_ACK_I; // Instruction Wishbone interface acknowledgement |
philpem@0 | 271 | input I_ERR_I; // Instruction Wishbone interface error |
philpem@0 | 272 | input I_RTY_I; // Instruction Wishbone interface retry |
philpem@0 | 273 | `endif |
philpem@0 | 274 | |
philpem@0 | 275 | input [`LM32_WORD_RNG] D_DAT_I; // Data Wishbone interface read data |
philpem@0 | 276 | input D_ACK_I; // Data Wishbone interface acknowledgement |
philpem@0 | 277 | input D_ERR_I; // Data Wishbone interface error |
philpem@0 | 278 | input D_RTY_I; // Data Wishbone interface retry |
philpem@0 | 279 | |
philpem@0 | 280 | ///////////////////////////////////////////////////// |
philpem@0 | 281 | // Outputs |
philpem@0 | 282 | ///////////////////////////////////////////////////// |
philpem@0 | 283 | |
philpem@0 | 284 | `ifdef CFG_TRACE_ENABLED |
philpem@0 | 285 | output [`LM32_PC_RNG] trace_pc; // PC to trace |
philpem@0 | 286 | reg [`LM32_PC_RNG] trace_pc; |
philpem@0 | 287 | output trace_pc_valid; // Indicates that a new trace PC is valid |
philpem@0 | 288 | reg trace_pc_valid; |
philpem@0 | 289 | output trace_exception; // Indicates an exception has occured |
philpem@0 | 290 | reg trace_exception; |
philpem@0 | 291 | output [`LM32_EID_RNG] trace_eid; // Indicates what type of exception has occured |
philpem@0 | 292 | reg [`LM32_EID_RNG] trace_eid; |
philpem@0 | 293 | output trace_eret; // Indicates an eret instruction has been executed |
philpem@0 | 294 | reg trace_eret; |
philpem@0 | 295 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 296 | output trace_bret; // Indicates a bret instruction has been executed |
philpem@0 | 297 | reg trace_bret; |
philpem@0 | 298 | `endif |
philpem@0 | 299 | `endif |
philpem@0 | 300 | |
philpem@0 | 301 | `ifdef CFG_JTAG_ENABLED |
philpem@0 | 302 | output [`LM32_BYTE_RNG] jtag_reg_d; |
philpem@0 | 303 | wire [`LM32_BYTE_RNG] jtag_reg_d; |
philpem@0 | 304 | output [2:0] jtag_reg_addr_d; |
philpem@0 | 305 | wire [2:0] jtag_reg_addr_d; |
philpem@0 | 306 | `endif |
philpem@0 | 307 | |
philpem@0 | 308 | `ifdef CFG_USER_ENABLED |
philpem@0 | 309 | output user_valid; // Indicates if user_opcode is valid |
philpem@0 | 310 | wire user_valid; |
philpem@0 | 311 | output [`LM32_USER_OPCODE_RNG] user_opcode; // User-defined instruction opcode |
philpem@0 | 312 | reg [`LM32_USER_OPCODE_RNG] user_opcode; |
philpem@0 | 313 | output [`LM32_WORD_RNG] user_operand_0; // First operand for user-defined instruction |
philpem@0 | 314 | wire [`LM32_WORD_RNG] user_operand_0; |
philpem@0 | 315 | output [`LM32_WORD_RNG] user_operand_1; // Second operand for user-defined instruction |
philpem@0 | 316 | wire [`LM32_WORD_RNG] user_operand_1; |
philpem@0 | 317 | `endif |
philpem@0 | 318 | |
philpem@0 | 319 | `ifdef CFG_IWB_ENABLED |
philpem@0 | 320 | output [`LM32_WORD_RNG] I_DAT_O; // Instruction Wishbone interface write data |
philpem@0 | 321 | wire [`LM32_WORD_RNG] I_DAT_O; |
philpem@0 | 322 | output [`LM32_WORD_RNG] I_ADR_O; // Instruction Wishbone interface address |
philpem@0 | 323 | wire [`LM32_WORD_RNG] I_ADR_O; |
philpem@0 | 324 | output I_CYC_O; // Instruction Wishbone interface cycle |
philpem@0 | 325 | wire I_CYC_O; |
philpem@0 | 326 | output [`LM32_BYTE_SELECT_RNG] I_SEL_O; // Instruction Wishbone interface byte select |
philpem@0 | 327 | wire [`LM32_BYTE_SELECT_RNG] I_SEL_O; |
philpem@0 | 328 | output I_STB_O; // Instruction Wishbone interface strobe |
philpem@0 | 329 | wire I_STB_O; |
philpem@0 | 330 | output I_WE_O; // Instruction Wishbone interface write enable |
philpem@0 | 331 | wire I_WE_O; |
philpem@0 | 332 | output [`LM32_CTYPE_RNG] I_CTI_O; // Instruction Wishbone interface cycle type |
philpem@0 | 333 | wire [`LM32_CTYPE_RNG] I_CTI_O; |
philpem@0 | 334 | output I_LOCK_O; // Instruction Wishbone interface lock bus |
philpem@0 | 335 | wire I_LOCK_O; |
philpem@0 | 336 | output [`LM32_BTYPE_RNG] I_BTE_O; // Instruction Wishbone interface burst type |
philpem@0 | 337 | wire [`LM32_BTYPE_RNG] I_BTE_O; |
philpem@0 | 338 | `endif |
philpem@0 | 339 | |
philpem@0 | 340 | output [`LM32_WORD_RNG] D_DAT_O; // Data Wishbone interface write data |
philpem@0 | 341 | wire [`LM32_WORD_RNG] D_DAT_O; |
philpem@0 | 342 | output [`LM32_WORD_RNG] D_ADR_O; // Data Wishbone interface address |
philpem@0 | 343 | wire [`LM32_WORD_RNG] D_ADR_O; |
philpem@0 | 344 | output D_CYC_O; // Data Wishbone interface cycle |
philpem@0 | 345 | wire D_CYC_O; |
philpem@0 | 346 | output [`LM32_BYTE_SELECT_RNG] D_SEL_O; // Data Wishbone interface byte select |
philpem@0 | 347 | wire [`LM32_BYTE_SELECT_RNG] D_SEL_O; |
philpem@0 | 348 | output D_STB_O; // Data Wishbone interface strobe |
philpem@0 | 349 | wire D_STB_O; |
philpem@0 | 350 | output D_WE_O; // Data Wishbone interface write enable |
philpem@0 | 351 | wire D_WE_O; |
philpem@0 | 352 | output [`LM32_CTYPE_RNG] D_CTI_O; // Data Wishbone interface cycle type |
philpem@0 | 353 | wire [`LM32_CTYPE_RNG] D_CTI_O; |
philpem@0 | 354 | output D_LOCK_O; // Date Wishbone interface lock bus |
philpem@0 | 355 | wire D_LOCK_O; |
philpem@0 | 356 | output [`LM32_BTYPE_RNG] D_BTE_O; // Data Wishbone interface burst type |
philpem@0 | 357 | wire [`LM32_BTYPE_RNG] D_BTE_O; |
philpem@0 | 358 | |
philpem@0 | 359 | ///////////////////////////////////////////////////// |
philpem@0 | 360 | // Internal nets and registers |
philpem@0 | 361 | ///////////////////////////////////////////////////// |
philpem@0 | 362 | |
philpem@0 | 363 | // Pipeline registers |
philpem@0 | 364 | |
philpem@0 | 365 | `ifdef LM32_CACHE_ENABLED |
philpem@0 | 366 | reg valid_a; // Instruction in A stage is valid |
philpem@0 | 367 | `endif |
philpem@0 | 368 | reg valid_f; // Instruction in F stage is valid |
philpem@0 | 369 | reg valid_d; // Instruction in D stage is valid |
philpem@0 | 370 | reg valid_x; // Instruction in X stage is valid |
philpem@0 | 371 | reg valid_m; // Instruction in M stage is valid |
philpem@0 | 372 | reg valid_w; // Instruction in W stage is valid |
philpem@0 | 373 | |
philpem@0 | 374 | wire q_x; |
philpem@0 | 375 | wire [`LM32_WORD_RNG] immediate_d; // Immediate operand |
philpem@0 | 376 | wire load_d; // Indicates a load instruction |
philpem@0 | 377 | reg load_x; |
philpem@0 | 378 | reg load_m; |
philpem@0 | 379 | wire load_q_x; |
philpem@0 | 380 | wire store_q_x; |
philpem@0 | 381 | wire store_d; // Indicates a store instruction |
philpem@0 | 382 | reg store_x; |
philpem@0 | 383 | reg store_m; |
philpem@0 | 384 | wire [`LM32_SIZE_RNG] size_d; // Size of load/store (byte, hword, word) |
philpem@0 | 385 | reg [`LM32_SIZE_RNG] size_x; |
philpem@0 | 386 | wire branch_d; // Indicates a branch instruction |
philpem@0 | 387 | wire branch_predict_d; // Indicates a branch is predicted |
philpem@0 | 388 | wire branch_predict_taken_d; // Indicates a branch is predicted taken |
philpem@0 | 389 | wire [`LM32_PC_RNG] branch_predict_address_d; // Address to which predicted branch jumps |
philpem@0 | 390 | wire [`LM32_PC_RNG] branch_target_d; |
philpem@0 | 391 | wire bi_unconditional; |
philpem@0 | 392 | wire bi_conditional; |
philpem@0 | 393 | reg branch_x; |
philpem@0 | 394 | reg branch_predict_x; |
philpem@0 | 395 | reg branch_predict_taken_x; |
philpem@0 | 396 | reg branch_m; |
philpem@0 | 397 | reg branch_predict_m; |
philpem@0 | 398 | reg branch_predict_taken_m; |
philpem@0 | 399 | wire branch_mispredict_taken_m; // Indicates a branch was mispredicted as taken |
philpem@0 | 400 | wire branch_flushX_m; // Indicates that instruction in X stage must be squashed |
philpem@0 | 401 | wire branch_reg_d; // Branch to register or immediate |
philpem@0 | 402 | wire [`LM32_PC_RNG] branch_offset_d; // Branch offset for immediate branches |
philpem@0 | 403 | reg [`LM32_PC_RNG] branch_target_x; // Address to branch to |
philpem@0 | 404 | reg [`LM32_PC_RNG] branch_target_m; |
philpem@0 | 405 | wire [`LM32_D_RESULT_SEL_0_RNG] d_result_sel_0_d; // Which result should be selected in D stage for operand 0 |
philpem@0 | 406 | wire [`LM32_D_RESULT_SEL_1_RNG] d_result_sel_1_d; // Which result should be selected in D stage for operand 1 |
philpem@0 | 407 | |
philpem@0 | 408 | wire x_result_sel_csr_d; // Select X stage result from CSRs |
philpem@0 | 409 | reg x_result_sel_csr_x; |
philpem@0 | 410 | `ifdef LM32_MC_ARITHMETIC_ENABLED |
philpem@0 | 411 | wire x_result_sel_mc_arith_d; // Select X stage result from multi-cycle arithmetic unit |
philpem@0 | 412 | reg x_result_sel_mc_arith_x; |
philpem@0 | 413 | `endif |
philpem@0 | 414 | `ifdef LM32_NO_BARREL_SHIFT |
philpem@0 | 415 | wire x_result_sel_shift_d; // Select X stage result from shifter |
philpem@0 | 416 | reg x_result_sel_shift_x; |
philpem@0 | 417 | `endif |
philpem@0 | 418 | `ifdef CFG_SIGN_EXTEND_ENABLED |
philpem@0 | 419 | wire x_result_sel_sext_d; // Select X stage result from sign-extend logic |
philpem@0 | 420 | reg x_result_sel_sext_x; |
philpem@0 | 421 | `endif |
philpem@0 | 422 | wire x_result_sel_logic_d; // Select X stage result from logic op unit |
philpem@0 | 423 | reg x_result_sel_logic_x; |
philpem@0 | 424 | `ifdef CFG_USER_ENABLED |
philpem@0 | 425 | wire x_result_sel_user_d; // Select X stage result from user-defined logic |
philpem@0 | 426 | reg x_result_sel_user_x; |
philpem@0 | 427 | `endif |
philpem@0 | 428 | wire x_result_sel_add_d; // Select X stage result from adder |
philpem@0 | 429 | reg x_result_sel_add_x; |
philpem@0 | 430 | wire m_result_sel_compare_d; // Select M stage result from comparison logic |
philpem@0 | 431 | reg m_result_sel_compare_x; |
philpem@0 | 432 | reg m_result_sel_compare_m; |
philpem@0 | 433 | `ifdef CFG_PL_BARREL_SHIFT_ENABLED |
philpem@0 | 434 | wire m_result_sel_shift_d; // Select M stage result from shifter |
philpem@0 | 435 | reg m_result_sel_shift_x; |
philpem@0 | 436 | reg m_result_sel_shift_m; |
philpem@0 | 437 | `endif |
philpem@0 | 438 | wire w_result_sel_load_d; // Select W stage result from load/store unit |
philpem@0 | 439 | reg w_result_sel_load_x; |
philpem@0 | 440 | reg w_result_sel_load_m; |
philpem@0 | 441 | reg w_result_sel_load_w; |
philpem@0 | 442 | `ifdef CFG_PL_MULTIPLY_ENABLED |
philpem@0 | 443 | wire w_result_sel_mul_d; // Select W stage result from multiplier |
philpem@0 | 444 | reg w_result_sel_mul_x; |
philpem@0 | 445 | reg w_result_sel_mul_m; |
philpem@0 | 446 | reg w_result_sel_mul_w; |
philpem@0 | 447 | `endif |
philpem@0 | 448 | wire x_bypass_enable_d; // Whether result is bypassable in X stage |
philpem@0 | 449 | reg x_bypass_enable_x; |
philpem@0 | 450 | wire m_bypass_enable_d; // Whether result is bypassable in M stage |
philpem@0 | 451 | reg m_bypass_enable_x; |
philpem@0 | 452 | reg m_bypass_enable_m; |
philpem@0 | 453 | wire sign_extend_d; // Whether to sign-extend or zero-extend |
philpem@0 | 454 | reg sign_extend_x; |
philpem@0 | 455 | wire write_enable_d; // Register file write enable |
philpem@0 | 456 | reg write_enable_x; |
philpem@0 | 457 | wire write_enable_q_x; |
philpem@0 | 458 | reg write_enable_m; |
philpem@0 | 459 | wire write_enable_q_m; |
philpem@0 | 460 | reg write_enable_w; |
philpem@0 | 461 | wire write_enable_q_w; |
philpem@0 | 462 | wire read_enable_0_d; // Register file read enable 0 |
philpem@0 | 463 | wire [`LM32_REG_IDX_RNG] read_idx_0_d; // Register file read index 0 |
philpem@0 | 464 | wire read_enable_1_d; // Register file read enable 1 |
philpem@0 | 465 | wire [`LM32_REG_IDX_RNG] read_idx_1_d; // Register file read index 1 |
philpem@0 | 466 | wire [`LM32_REG_IDX_RNG] write_idx_d; // Register file write index |
philpem@0 | 467 | reg [`LM32_REG_IDX_RNG] write_idx_x; |
philpem@0 | 468 | reg [`LM32_REG_IDX_RNG] write_idx_m; |
philpem@0 | 469 | reg [`LM32_REG_IDX_RNG] write_idx_w; |
philpem@0 | 470 | wire [`LM32_CSR_RNG] csr_d; // CSR read/write index |
philpem@0 | 471 | reg [`LM32_CSR_RNG] csr_x; |
philpem@0 | 472 | wire [`LM32_CONDITION_RNG] condition_d; // Branch condition |
philpem@0 | 473 | reg [`LM32_CONDITION_RNG] condition_x; |
philpem@0 | 474 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 475 | wire break_d; // Indicates a break instruction |
philpem@0 | 476 | reg break_x; |
philpem@0 | 477 | `endif |
philpem@0 | 478 | wire scall_d; // Indicates a scall instruction |
philpem@0 | 479 | reg scall_x; |
philpem@0 | 480 | wire eret_d; // Indicates an eret instruction |
philpem@0 | 481 | reg eret_x; |
philpem@0 | 482 | wire eret_q_x; |
philpem@0 | 483 | reg eret_m; |
philpem@0 | 484 | `ifdef CFG_TRACE_ENABLED |
philpem@0 | 485 | reg eret_w; |
philpem@0 | 486 | `endif |
philpem@0 | 487 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 488 | wire bret_d; // Indicates a bret instruction |
philpem@0 | 489 | reg bret_x; |
philpem@0 | 490 | wire bret_q_x; |
philpem@0 | 491 | reg bret_m; |
philpem@0 | 492 | `ifdef CFG_TRACE_ENABLED |
philpem@0 | 493 | reg bret_w; |
philpem@0 | 494 | `endif |
philpem@0 | 495 | `endif |
philpem@0 | 496 | wire csr_write_enable_d; // CSR write enable |
philpem@0 | 497 | reg csr_write_enable_x; |
philpem@0 | 498 | wire csr_write_enable_q_x; |
philpem@0 | 499 | `ifdef CFG_USER_ENABLED |
philpem@0 | 500 | wire [`LM32_USER_OPCODE_RNG] user_opcode_d; // User-defined instruction opcode |
philpem@0 | 501 | `endif |
philpem@0 | 502 | |
philpem@0 | 503 | `ifdef CFG_BUS_ERRORS_ENABLED |
philpem@0 | 504 | wire bus_error_d; // Indicates an bus error occured while fetching the instruction in this pipeline stage |
philpem@0 | 505 | reg bus_error_x; |
philpem@0 | 506 | reg data_bus_error_exception_m; |
philpem@0 | 507 | reg [`LM32_PC_RNG] memop_pc_w; |
philpem@0 | 508 | `endif |
philpem@0 | 509 | |
philpem@0 | 510 | reg [`LM32_WORD_RNG] d_result_0; // Result of instruction in D stage (operand 0) |
philpem@0 | 511 | reg [`LM32_WORD_RNG] d_result_1; // Result of instruction in D stage (operand 1) |
philpem@0 | 512 | reg [`LM32_WORD_RNG] x_result; // Result of instruction in X stage |
philpem@0 | 513 | reg [`LM32_WORD_RNG] m_result; // Result of instruction in M stage |
philpem@0 | 514 | reg [`LM32_WORD_RNG] w_result; // Result of instruction in W stage |
philpem@0 | 515 | |
philpem@0 | 516 | reg [`LM32_WORD_RNG] operand_0_x; // Operand 0 for X stage instruction |
philpem@0 | 517 | reg [`LM32_WORD_RNG] operand_1_x; // Operand 1 for X stage instruction |
philpem@0 | 518 | reg [`LM32_WORD_RNG] store_operand_x; // Data read from register to store |
philpem@0 | 519 | reg [`LM32_WORD_RNG] operand_m; // Operand for M stage instruction |
philpem@0 | 520 | reg [`LM32_WORD_RNG] operand_w; // Operand for W stage instruction |
philpem@0 | 521 | |
philpem@0 | 522 | // To/from register file |
philpem@0 | 523 | `ifdef CFG_EBR_POSEDGE_REGISTER_FILE |
philpem@0 | 524 | reg [`LM32_WORD_RNG] reg_data_live_0; |
philpem@0 | 525 | reg [`LM32_WORD_RNG] reg_data_live_1; |
philpem@0 | 526 | reg use_buf; // Whether to use reg_data_live or reg_data_buf |
philpem@0 | 527 | reg [`LM32_WORD_RNG] reg_data_buf_0; |
philpem@0 | 528 | reg [`LM32_WORD_RNG] reg_data_buf_1; |
philpem@0 | 529 | `endif |
philpem@0 | 530 | `ifdef LM32_EBR_REGISTER_FILE |
philpem@0 | 531 | `else |
philpem@0 | 532 | reg [`LM32_WORD_RNG] registers[0:(1<<`LM32_REG_IDX_WIDTH)-1]; // Register file |
philpem@0 | 533 | `endif |
philpem@0 | 534 | wire [`LM32_WORD_RNG] reg_data_0; // Register file read port 0 data |
philpem@0 | 535 | wire [`LM32_WORD_RNG] reg_data_1; // Register file read port 1 data |
philpem@0 | 536 | reg [`LM32_WORD_RNG] bypass_data_0; // Register value 0 after bypassing |
philpem@0 | 537 | reg [`LM32_WORD_RNG] bypass_data_1; // Register value 1 after bypassing |
philpem@0 | 538 | wire reg_write_enable_q_w; |
philpem@0 | 539 | |
philpem@0 | 540 | reg interlock; // Indicates pipeline should be stalled because of a read-after-write hazzard |
philpem@0 | 541 | |
philpem@0 | 542 | wire stall_a; // Stall instruction in A pipeline stage |
philpem@0 | 543 | wire stall_f; // Stall instruction in F pipeline stage |
philpem@0 | 544 | wire stall_d; // Stall instruction in D pipeline stage |
philpem@0 | 545 | wire stall_x; // Stall instruction in X pipeline stage |
philpem@0 | 546 | wire stall_m; // Stall instruction in M pipeline stage |
philpem@0 | 547 | |
philpem@0 | 548 | // To/from adder |
philpem@0 | 549 | wire adder_op_d; // Whether to add or subtract |
philpem@0 | 550 | reg adder_op_x; |
philpem@0 | 551 | reg adder_op_x_n; // Inverted version of adder_op_x |
philpem@0 | 552 | wire [`LM32_WORD_RNG] adder_result_x; // Result from adder |
philpem@0 | 553 | wire adder_overflow_x; // Whether a signed overflow occured |
philpem@0 | 554 | wire adder_carry_n_x; // Whether a carry was generated |
philpem@0 | 555 | |
philpem@0 | 556 | // To/from logical operations unit |
philpem@0 | 557 | wire [`LM32_LOGIC_OP_RNG] logic_op_d; // Which operation to perform |
philpem@0 | 558 | reg [`LM32_LOGIC_OP_RNG] logic_op_x; |
philpem@0 | 559 | wire [`LM32_WORD_RNG] logic_result_x; // Result of logical operation |
philpem@0 | 560 | |
philpem@0 | 561 | `ifdef CFG_SIGN_EXTEND_ENABLED |
philpem@0 | 562 | // From sign-extension unit |
philpem@0 | 563 | wire [`LM32_WORD_RNG] sextb_result_x; // Result of byte sign-extension |
philpem@0 | 564 | wire [`LM32_WORD_RNG] sexth_result_x; // Result of half-word sign-extenstion |
philpem@0 | 565 | wire [`LM32_WORD_RNG] sext_result_x; // Result of sign-extension specified by instruction |
philpem@0 | 566 | `endif |
philpem@0 | 567 | |
philpem@0 | 568 | // To/from shifter |
philpem@0 | 569 | `ifdef CFG_PL_BARREL_SHIFT_ENABLED |
philpem@0 | 570 | `ifdef CFG_ROTATE_ENABLED |
philpem@0 | 571 | wire rotate_d; // Whether we should rotate or shift |
philpem@0 | 572 | reg rotate_x; |
philpem@0 | 573 | `endif |
philpem@0 | 574 | wire direction_d; // Which direction to shift in |
philpem@0 | 575 | reg direction_x; |
philpem@0 | 576 | wire [`LM32_WORD_RNG] shifter_result_m; // Result of shifter |
philpem@0 | 577 | `endif |
philpem@0 | 578 | `ifdef CFG_MC_BARREL_SHIFT_ENABLED |
philpem@0 | 579 | wire shift_left_d; // Indicates whether to perform a left shift or not |
philpem@0 | 580 | wire shift_left_q_d; |
philpem@0 | 581 | wire shift_right_d; // Indicates whether to perform a right shift or not |
philpem@0 | 582 | wire shift_right_q_d; |
philpem@0 | 583 | `endif |
philpem@0 | 584 | `ifdef LM32_NO_BARREL_SHIFT |
philpem@0 | 585 | wire [`LM32_WORD_RNG] shifter_result_x; // Result of single-bit right shifter |
philpem@0 | 586 | `endif |
philpem@0 | 587 | |
philpem@0 | 588 | // To/from multiplier |
philpem@0 | 589 | `ifdef LM32_MULTIPLY_ENABLED |
philpem@0 | 590 | wire [`LM32_WORD_RNG] multiplier_result_w; // Result from multiplier |
philpem@0 | 591 | `endif |
philpem@0 | 592 | `ifdef CFG_MC_MULTIPLY_ENABLED |
philpem@0 | 593 | wire multiply_d; // Indicates whether to perform a multiply or not |
philpem@0 | 594 | wire multiply_q_d; |
philpem@0 | 595 | `endif |
philpem@0 | 596 | |
philpem@0 | 597 | // To/from divider |
philpem@0 | 598 | `ifdef CFG_MC_DIVIDE_ENABLED |
philpem@0 | 599 | wire divide_d; // Indicates whether to perform a divider or not |
philpem@0 | 600 | wire divide_q_d; |
philpem@0 | 601 | wire modulus_d; |
philpem@0 | 602 | wire modulus_q_d; |
philpem@0 | 603 | wire divide_by_zero_x; // Indicates an attempt was made to divide by zero |
philpem@0 | 604 | `endif |
philpem@0 | 605 | |
philpem@0 | 606 | // To from multi-cycle arithmetic unit |
philpem@0 | 607 | `ifdef LM32_MC_ARITHMETIC_ENABLED |
philpem@0 | 608 | wire mc_stall_request_x; // Multi-cycle arithmetic unit stall request |
philpem@0 | 609 | wire [`LM32_WORD_RNG] mc_result_x; |
philpem@0 | 610 | `endif |
philpem@0 | 611 | |
philpem@0 | 612 | // From CSRs |
philpem@0 | 613 | `ifdef CFG_INTERRUPTS_ENABLED |
philpem@0 | 614 | wire [`LM32_WORD_RNG] interrupt_csr_read_data_x;// Data read from interrupt CSRs |
philpem@0 | 615 | `endif |
philpem@0 | 616 | wire [`LM32_WORD_RNG] cfg; // Configuration CSR |
philpem@0 | 617 | wire [`LM32_WORD_RNG] cfg2; // Extended Configuration CSR |
philpem@0 | 618 | `ifdef CFG_CYCLE_COUNTER_ENABLED |
philpem@0 | 619 | reg [`LM32_WORD_RNG] cc; // Cycle counter CSR |
philpem@0 | 620 | `endif |
philpem@0 | 621 | reg [`LM32_WORD_RNG] csr_read_data_x; // Data read from CSRs |
philpem@0 | 622 | |
philpem@0 | 623 | // To/from instruction unit |
philpem@0 | 624 | wire [`LM32_PC_RNG] pc_f; // PC of instruction in F stage |
philpem@0 | 625 | wire [`LM32_PC_RNG] pc_d; // PC of instruction in D stage |
philpem@0 | 626 | wire [`LM32_PC_RNG] pc_x; // PC of instruction in X stage |
philpem@0 | 627 | wire [`LM32_PC_RNG] pc_m; // PC of instruction in M stage |
philpem@0 | 628 | wire [`LM32_PC_RNG] pc_w; // PC of instruction in W stage |
philpem@0 | 629 | `ifdef CFG_TRACE_ENABLED |
philpem@0 | 630 | reg [`LM32_PC_RNG] pc_c; // PC of last commited instruction |
philpem@0 | 631 | `endif |
philpem@0 | 632 | `ifdef CFG_EBR_POSEDGE_REGISTER_FILE |
philpem@0 | 633 | wire [`LM32_INSTRUCTION_RNG] instruction_f; // Instruction in F stage |
philpem@0 | 634 | `endif |
philpem@0 | 635 | //pragma attribute instruction_d preserve_signal true |
philpem@0 | 636 | //pragma attribute instruction_d preserve_driver true |
philpem@0 | 637 | wire [`LM32_INSTRUCTION_RNG] instruction_d; // Instruction in D stage |
philpem@0 | 638 | `ifdef CFG_ICACHE_ENABLED |
philpem@0 | 639 | wire iflush; // Flush instruction cache |
philpem@0 | 640 | wire icache_stall_request; // Stall pipeline because instruction cache is busy |
philpem@0 | 641 | wire icache_restart_request; // Restart instruction that caused an instruction cache miss |
philpem@0 | 642 | wire icache_refill_request; // Request to refill instruction cache |
philpem@0 | 643 | wire icache_refilling; // Indicates the instruction cache is being refilled |
philpem@0 | 644 | `endif |
philpem@0 | 645 | `ifdef CFG_IROM_ENABLED |
philpem@0 | 646 | wire [`LM32_WORD_RNG] irom_store_data_m; // Store data to instruction ROM |
philpem@0 | 647 | wire [`LM32_WORD_RNG] irom_address_xm; // Address to instruction ROM from load-store unit |
philpem@0 | 648 | wire [`LM32_WORD_RNG] irom_data_m; // Load data from instruction ROM |
philpem@0 | 649 | wire irom_we_xm; // Indicates data needs to be written to instruction ROM |
philpem@0 | 650 | wire irom_stall_request_x; // Indicates D stage needs to be stalled on a store to instruction ROM |
philpem@0 | 651 | `endif |
philpem@0 | 652 | |
philpem@0 | 653 | // To/from load/store unit |
philpem@0 | 654 | `ifdef CFG_DCACHE_ENABLED |
philpem@0 | 655 | wire dflush_x; // Flush data cache |
philpem@0 | 656 | reg dflush_m; |
philpem@0 | 657 | wire dcache_stall_request; // Stall pipeline because data cache is busy |
philpem@0 | 658 | wire dcache_restart_request; // Restart instruction that caused a data cache miss |
philpem@0 | 659 | wire dcache_refill_request; // Request to refill data cache |
philpem@0 | 660 | wire dcache_refilling; // Indicates the data cache is being refilled |
philpem@0 | 661 | `endif |
philpem@0 | 662 | wire [`LM32_WORD_RNG] load_data_w; // Result of a load instruction |
philpem@0 | 663 | wire stall_wb_load; // Stall pipeline because of a load via the data Wishbone interface |
philpem@0 | 664 | |
philpem@0 | 665 | // To/from JTAG interface |
philpem@0 | 666 | `ifdef CFG_JTAG_ENABLED |
philpem@0 | 667 | `ifdef CFG_JTAG_UART_ENABLED |
philpem@0 | 668 | wire [`LM32_WORD_RNG] jtx_csr_read_data; // Read data for JTX CSR |
philpem@0 | 669 | wire [`LM32_WORD_RNG] jrx_csr_read_data; // Read data for JRX CSR |
philpem@0 | 670 | `endif |
philpem@0 | 671 | `ifdef CFG_HW_DEBUG_ENABLED |
philpem@0 | 672 | wire jtag_csr_write_enable; // Debugger CSR write enable |
philpem@0 | 673 | wire [`LM32_WORD_RNG] jtag_csr_write_data; // Data to write to specified CSR |
philpem@0 | 674 | wire [`LM32_CSR_RNG] jtag_csr; // Which CSR to write |
philpem@0 | 675 | wire jtag_read_enable; |
philpem@0 | 676 | wire [`LM32_BYTE_RNG] jtag_read_data; |
philpem@0 | 677 | wire jtag_write_enable; |
philpem@0 | 678 | wire [`LM32_BYTE_RNG] jtag_write_data; |
philpem@0 | 679 | wire [`LM32_WORD_RNG] jtag_address; |
philpem@0 | 680 | wire jtag_access_complete; |
philpem@0 | 681 | `endif |
philpem@0 | 682 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 683 | wire jtag_break; // Request from debugger to raise a breakpoint |
philpem@0 | 684 | `endif |
philpem@0 | 685 | `endif |
philpem@0 | 686 | |
philpem@0 | 687 | // Hazzard detection |
philpem@0 | 688 | wire raw_x_0; // RAW hazzard between instruction in X stage and read port 0 |
philpem@0 | 689 | wire raw_x_1; // RAW hazzard between instruction in X stage and read port 1 |
philpem@0 | 690 | wire raw_m_0; // RAW hazzard between instruction in M stage and read port 0 |
philpem@0 | 691 | wire raw_m_1; // RAW hazzard between instruction in M stage and read port 1 |
philpem@0 | 692 | wire raw_w_0; // RAW hazzard between instruction in W stage and read port 0 |
philpem@0 | 693 | wire raw_w_1; // RAW hazzard between instruction in W stage and read port 1 |
philpem@0 | 694 | |
philpem@0 | 695 | // Control flow |
philpem@0 | 696 | wire cmp_zero; // Result of comparison is zero |
philpem@0 | 697 | wire cmp_negative; // Result of comparison is negative |
philpem@0 | 698 | wire cmp_overflow; // Comparison produced an overflow |
philpem@0 | 699 | wire cmp_carry_n; // Comparison produced a carry, inverted |
philpem@0 | 700 | reg condition_met_x; // Condition of branch instruction is met |
philpem@0 | 701 | reg condition_met_m; |
philpem@0 | 702 | `ifdef CFG_FAST_UNCONDITIONAL_BRANCH |
philpem@0 | 703 | wire branch_taken_x; // Branch is taken in X stage |
philpem@0 | 704 | `endif |
philpem@0 | 705 | wire branch_taken_m; // Branch is taken in M stage |
philpem@0 | 706 | |
philpem@0 | 707 | wire kill_f; // Kill instruction in F stage |
philpem@0 | 708 | wire kill_d; // Kill instruction in D stage |
philpem@0 | 709 | wire kill_x; // Kill instruction in X stage |
philpem@0 | 710 | wire kill_m; // Kill instruction in M stage |
philpem@0 | 711 | wire kill_w; // Kill instruction in W stage |
philpem@0 | 712 | |
philpem@0 | 713 | reg [`LM32_PC_WIDTH+2-1:8] eba; // Exception Base Address (EBA) CSR |
philpem@0 | 714 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 715 | reg [`LM32_PC_WIDTH+2-1:8] deba; // Debug Exception Base Address (DEBA) CSR |
philpem@0 | 716 | `endif |
philpem@0 | 717 | reg [`LM32_EID_RNG] eid_x; // Exception ID in X stage |
philpem@0 | 718 | `ifdef CFG_TRACE_ENABLED |
philpem@0 | 719 | reg [`LM32_EID_RNG] eid_m; // Exception ID in M stage |
philpem@0 | 720 | reg [`LM32_EID_RNG] eid_w; // Exception ID in W stage |
philpem@0 | 721 | `endif |
philpem@0 | 722 | |
philpem@0 | 723 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 724 | `ifdef LM32_SINGLE_STEP_ENABLED |
philpem@0 | 725 | wire dc_ss; // Is single-step enabled |
philpem@0 | 726 | `endif |
philpem@0 | 727 | wire dc_re; // Remap all exceptions |
philpem@0 | 728 | wire exception_x; // An exception occured in the X stage |
philpem@0 | 729 | reg exception_m; // An instruction that caused an exception is in the M stage |
philpem@0 | 730 | wire debug_exception_x; // Indicates if a debug exception has occured |
philpem@0 | 731 | reg debug_exception_m; |
philpem@0 | 732 | reg debug_exception_w; |
philpem@0 | 733 | wire debug_exception_q_w; |
philpem@0 | 734 | wire non_debug_exception_x; // Indicates if a non debug exception has occured |
philpem@0 | 735 | reg non_debug_exception_m; |
philpem@0 | 736 | reg non_debug_exception_w; |
philpem@0 | 737 | wire non_debug_exception_q_w; |
philpem@0 | 738 | `else |
philpem@0 | 739 | wire exception_x; // Indicates if a debug exception has occured |
philpem@0 | 740 | reg exception_m; |
philpem@0 | 741 | reg exception_w; |
philpem@0 | 742 | wire exception_q_w; |
philpem@0 | 743 | `endif |
philpem@0 | 744 | |
philpem@0 | 745 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 746 | `ifdef CFG_JTAG_ENABLED |
philpem@0 | 747 | wire reset_exception; // Indicates if a reset exception has occured |
philpem@0 | 748 | `endif |
philpem@0 | 749 | `endif |
philpem@0 | 750 | `ifdef CFG_INTERRUPTS_ENABLED |
philpem@0 | 751 | wire interrupt_exception; // Indicates if an interrupt exception has occured |
philpem@0 | 752 | `endif |
philpem@0 | 753 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 754 | wire breakpoint_exception; // Indicates if a breakpoint exception has occured |
philpem@0 | 755 | wire watchpoint_exception; // Indicates if a watchpoint exception has occured |
philpem@0 | 756 | `endif |
philpem@0 | 757 | `ifdef CFG_BUS_ERRORS_ENABLED |
philpem@0 | 758 | wire instruction_bus_error_exception; // Indicates if an instruction bus error exception has occured |
philpem@0 | 759 | wire data_bus_error_exception; // Indicates if a data bus error exception has occured |
philpem@0 | 760 | `endif |
philpem@0 | 761 | `ifdef CFG_MC_DIVIDE_ENABLED |
philpem@0 | 762 | wire divide_by_zero_exception; // Indicates if a divide by zero exception has occured |
philpem@0 | 763 | `endif |
philpem@0 | 764 | wire system_call_exception; // Indicates if a system call exception has occured |
philpem@0 | 765 | |
philpem@0 | 766 | `ifdef CFG_BUS_ERRORS_ENABLED |
philpem@0 | 767 | reg data_bus_error_seen; // Indicates if a data bus error was seen |
philpem@0 | 768 | `endif |
philpem@0 | 769 | |
philpem@0 | 770 | ///////////////////////////////////////////////////// |
philpem@0 | 771 | // Functions |
philpem@0 | 772 | ///////////////////////////////////////////////////// |
philpem@0 | 773 | |
philpem@0 | 774 | `include "lm32_functions.v" |
philpem@0 | 775 | |
philpem@0 | 776 | ///////////////////////////////////////////////////// |
philpem@0 | 777 | // Instantiations |
philpem@0 | 778 | ///////////////////////////////////////////////////// |
philpem@0 | 779 | |
philpem@0 | 780 | // Instruction unit |
philpem@0 | 781 | lm32_instruction_unit #( |
philpem@0 | 782 | .associativity (icache_associativity), |
philpem@0 | 783 | .sets (icache_sets), |
philpem@0 | 784 | .bytes_per_line (icache_bytes_per_line), |
philpem@0 | 785 | .base_address (icache_base_address), |
philpem@0 | 786 | .limit (icache_limit) |
philpem@0 | 787 | ) instruction_unit ( |
philpem@0 | 788 | // ----- Inputs ------- |
philpem@0 | 789 | .clk_i (clk_i), |
philpem@0 | 790 | .rst_i (rst_i), |
philpem@26 | 791 | `ifdef CFG_DEBUG_ENABLED |
philpem@26 | 792 | `ifdef CFG_ALTERNATE_EBA |
philpem@26 | 793 | .at_debug (at_debug), |
philpem@26 | 794 | `endif |
philpem@26 | 795 | `endif |
philpem@0 | 796 | // From pipeline |
philpem@0 | 797 | .stall_a (stall_a), |
philpem@0 | 798 | .stall_f (stall_f), |
philpem@0 | 799 | .stall_d (stall_d), |
philpem@0 | 800 | .stall_x (stall_x), |
philpem@0 | 801 | .stall_m (stall_m), |
philpem@0 | 802 | .valid_f (valid_f), |
philpem@0 | 803 | .valid_d (valid_d), |
philpem@0 | 804 | .kill_f (kill_f), |
philpem@0 | 805 | .branch_predict_taken_d (branch_predict_taken_d), |
philpem@0 | 806 | .branch_predict_address_d (branch_predict_address_d), |
philpem@0 | 807 | `ifdef CFG_FAST_UNCONDITIONAL_BRANCH |
philpem@0 | 808 | .branch_taken_x (branch_taken_x), |
philpem@0 | 809 | .branch_target_x (branch_target_x), |
philpem@0 | 810 | `endif |
philpem@0 | 811 | .exception_m (exception_m), |
philpem@0 | 812 | .branch_taken_m (branch_taken_m), |
philpem@0 | 813 | .branch_mispredict_taken_m (branch_mispredict_taken_m), |
philpem@0 | 814 | .branch_target_m (branch_target_m), |
philpem@0 | 815 | `ifdef CFG_ICACHE_ENABLED |
philpem@0 | 816 | .iflush (iflush), |
philpem@0 | 817 | `endif |
philpem@0 | 818 | `ifdef CFG_IROM_ENABLED |
philpem@0 | 819 | .irom_store_data_m (irom_store_data_m), |
philpem@0 | 820 | .irom_address_xm (irom_address_xm), |
philpem@0 | 821 | .irom_we_xm (irom_we_xm), |
philpem@0 | 822 | `endif |
philpem@0 | 823 | `ifdef CFG_DCACHE_ENABLED |
philpem@0 | 824 | .dcache_restart_request (dcache_restart_request), |
philpem@0 | 825 | .dcache_refill_request (dcache_refill_request), |
philpem@0 | 826 | .dcache_refilling (dcache_refilling), |
philpem@0 | 827 | `endif |
philpem@0 | 828 | `ifdef CFG_IWB_ENABLED |
philpem@0 | 829 | // From Wishbone |
philpem@0 | 830 | .i_dat_i (I_DAT_I), |
philpem@0 | 831 | .i_ack_i (I_ACK_I), |
philpem@0 | 832 | .i_err_i (I_ERR_I), |
philpem@0 | 833 | `endif |
philpem@0 | 834 | `ifdef CFG_HW_DEBUG_ENABLED |
philpem@0 | 835 | .jtag_read_enable (jtag_read_enable), |
philpem@0 | 836 | .jtag_write_enable (jtag_write_enable), |
philpem@0 | 837 | .jtag_write_data (jtag_write_data), |
philpem@0 | 838 | .jtag_address (jtag_address), |
philpem@0 | 839 | `endif |
philpem@0 | 840 | // ----- Outputs ------- |
philpem@0 | 841 | // To pipeline |
philpem@0 | 842 | .pc_f (pc_f), |
philpem@0 | 843 | .pc_d (pc_d), |
philpem@0 | 844 | .pc_x (pc_x), |
philpem@0 | 845 | .pc_m (pc_m), |
philpem@0 | 846 | .pc_w (pc_w), |
philpem@0 | 847 | `ifdef CFG_ICACHE_ENABLED |
philpem@0 | 848 | .icache_stall_request (icache_stall_request), |
philpem@0 | 849 | .icache_restart_request (icache_restart_request), |
philpem@0 | 850 | .icache_refill_request (icache_refill_request), |
philpem@0 | 851 | .icache_refilling (icache_refilling), |
philpem@0 | 852 | `endif |
philpem@0 | 853 | `ifdef CFG_IROM_ENABLED |
philpem@0 | 854 | .irom_data_m (irom_data_m), |
philpem@0 | 855 | `endif |
philpem@0 | 856 | `ifdef CFG_IWB_ENABLED |
philpem@0 | 857 | // To Wishbone |
philpem@0 | 858 | .i_dat_o (I_DAT_O), |
philpem@0 | 859 | .i_adr_o (I_ADR_O), |
philpem@0 | 860 | .i_cyc_o (I_CYC_O), |
philpem@0 | 861 | .i_sel_o (I_SEL_O), |
philpem@0 | 862 | .i_stb_o (I_STB_O), |
philpem@0 | 863 | .i_we_o (I_WE_O), |
philpem@0 | 864 | .i_cti_o (I_CTI_O), |
philpem@0 | 865 | .i_lock_o (I_LOCK_O), |
philpem@0 | 866 | .i_bte_o (I_BTE_O), |
philpem@0 | 867 | `endif |
philpem@0 | 868 | `ifdef CFG_HW_DEBUG_ENABLED |
philpem@0 | 869 | .jtag_read_data (jtag_read_data), |
philpem@0 | 870 | .jtag_access_complete (jtag_access_complete), |
philpem@0 | 871 | `endif |
philpem@0 | 872 | `ifdef CFG_BUS_ERRORS_ENABLED |
philpem@0 | 873 | .bus_error_d (bus_error_d), |
philpem@0 | 874 | `endif |
philpem@0 | 875 | `ifdef CFG_EBR_POSEDGE_REGISTER_FILE |
philpem@0 | 876 | .instruction_f (instruction_f), |
philpem@0 | 877 | `endif |
philpem@0 | 878 | .instruction_d (instruction_d) |
philpem@0 | 879 | ); |
philpem@0 | 880 | |
philpem@0 | 881 | // Instruction decoder |
philpem@0 | 882 | lm32_decoder decoder ( |
philpem@0 | 883 | // ----- Inputs ------- |
philpem@0 | 884 | .instruction (instruction_d), |
philpem@0 | 885 | // ----- Outputs ------- |
philpem@0 | 886 | .d_result_sel_0 (d_result_sel_0_d), |
philpem@0 | 887 | .d_result_sel_1 (d_result_sel_1_d), |
philpem@0 | 888 | .x_result_sel_csr (x_result_sel_csr_d), |
philpem@0 | 889 | `ifdef LM32_MC_ARITHMETIC_ENABLED |
philpem@0 | 890 | .x_result_sel_mc_arith (x_result_sel_mc_arith_d), |
philpem@0 | 891 | `endif |
philpem@0 | 892 | `ifdef LM32_NO_BARREL_SHIFT |
philpem@0 | 893 | .x_result_sel_shift (x_result_sel_shift_d), |
philpem@0 | 894 | `endif |
philpem@0 | 895 | `ifdef CFG_SIGN_EXTEND_ENABLED |
philpem@0 | 896 | .x_result_sel_sext (x_result_sel_sext_d), |
philpem@0 | 897 | `endif |
philpem@0 | 898 | .x_result_sel_logic (x_result_sel_logic_d), |
philpem@0 | 899 | `ifdef CFG_USER_ENABLED |
philpem@0 | 900 | .x_result_sel_user (x_result_sel_user_d), |
philpem@0 | 901 | `endif |
philpem@0 | 902 | .x_result_sel_add (x_result_sel_add_d), |
philpem@0 | 903 | .m_result_sel_compare (m_result_sel_compare_d), |
philpem@0 | 904 | `ifdef CFG_PL_BARREL_SHIFT_ENABLED |
philpem@0 | 905 | .m_result_sel_shift (m_result_sel_shift_d), |
philpem@0 | 906 | `endif |
philpem@0 | 907 | .w_result_sel_load (w_result_sel_load_d), |
philpem@0 | 908 | `ifdef CFG_PL_MULTIPLY_ENABLED |
philpem@0 | 909 | .w_result_sel_mul (w_result_sel_mul_d), |
philpem@0 | 910 | `endif |
philpem@0 | 911 | .x_bypass_enable (x_bypass_enable_d), |
philpem@0 | 912 | .m_bypass_enable (m_bypass_enable_d), |
philpem@0 | 913 | .read_enable_0 (read_enable_0_d), |
philpem@0 | 914 | .read_idx_0 (read_idx_0_d), |
philpem@0 | 915 | .read_enable_1 (read_enable_1_d), |
philpem@0 | 916 | .read_idx_1 (read_idx_1_d), |
philpem@0 | 917 | .write_enable (write_enable_d), |
philpem@0 | 918 | .write_idx (write_idx_d), |
philpem@0 | 919 | .immediate (immediate_d), |
philpem@0 | 920 | .branch_offset (branch_offset_d), |
philpem@0 | 921 | .load (load_d), |
philpem@0 | 922 | .store (store_d), |
philpem@0 | 923 | .size (size_d), |
philpem@0 | 924 | .sign_extend (sign_extend_d), |
philpem@0 | 925 | .adder_op (adder_op_d), |
philpem@0 | 926 | .logic_op (logic_op_d), |
philpem@0 | 927 | `ifdef CFG_PL_BARREL_SHIFT_ENABLED |
philpem@0 | 928 | .direction (direction_d), |
philpem@0 | 929 | `endif |
philpem@0 | 930 | `ifdef CFG_MC_BARREL_SHIFT_ENABLED |
philpem@0 | 931 | .shift_left (shift_left_d), |
philpem@0 | 932 | .shift_right (shift_right_d), |
philpem@0 | 933 | `endif |
philpem@0 | 934 | `ifdef CFG_MC_MULTIPLY_ENABLED |
philpem@0 | 935 | .multiply (multiply_d), |
philpem@0 | 936 | `endif |
philpem@0 | 937 | `ifdef CFG_MC_DIVIDE_ENABLED |
philpem@0 | 938 | .divide (divide_d), |
philpem@0 | 939 | .modulus (modulus_d), |
philpem@0 | 940 | `endif |
philpem@0 | 941 | .branch (branch_d), |
philpem@0 | 942 | .bi_unconditional (bi_unconditional), |
philpem@0 | 943 | .bi_conditional (bi_conditional), |
philpem@0 | 944 | .branch_reg (branch_reg_d), |
philpem@0 | 945 | .condition (condition_d), |
philpem@0 | 946 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 947 | .break_opcode (break_d), |
philpem@0 | 948 | `endif |
philpem@0 | 949 | .scall (scall_d), |
philpem@0 | 950 | .eret (eret_d), |
philpem@0 | 951 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 952 | .bret (bret_d), |
philpem@0 | 953 | `endif |
philpem@0 | 954 | `ifdef CFG_USER_ENABLED |
philpem@0 | 955 | .user_opcode (user_opcode_d), |
philpem@0 | 956 | `endif |
philpem@0 | 957 | .csr_write_enable (csr_write_enable_d) |
philpem@0 | 958 | ); |
philpem@0 | 959 | |
philpem@0 | 960 | // Load/store unit |
philpem@0 | 961 | lm32_load_store_unit #( |
philpem@0 | 962 | .associativity (dcache_associativity), |
philpem@0 | 963 | .sets (dcache_sets), |
philpem@0 | 964 | .bytes_per_line (dcache_bytes_per_line), |
philpem@0 | 965 | .base_address (dcache_base_address), |
philpem@0 | 966 | .limit (dcache_limit) |
philpem@0 | 967 | ) load_store_unit ( |
philpem@0 | 968 | // ----- Inputs ------- |
philpem@0 | 969 | .clk_i (clk_i), |
philpem@0 | 970 | .rst_i (rst_i), |
philpem@0 | 971 | // From pipeline |
philpem@0 | 972 | .stall_a (stall_a), |
philpem@0 | 973 | .stall_x (stall_x), |
philpem@0 | 974 | .stall_m (stall_m), |
philpem@0 | 975 | .kill_m (kill_m), |
philpem@0 | 976 | .exception_m (exception_m), |
philpem@0 | 977 | .store_operand_x (store_operand_x), |
philpem@0 | 978 | .load_store_address_x (adder_result_x), |
philpem@0 | 979 | .load_store_address_m (operand_m), |
philpem@0 | 980 | .load_store_address_w (operand_w[1:0]), |
philpem@0 | 981 | .load_x (load_x), |
philpem@0 | 982 | .store_x (store_x), |
philpem@0 | 983 | .load_q_x (load_q_x), |
philpem@0 | 984 | .store_q_x (store_q_x), |
philpem@0 | 985 | .load_q_m (load_q_m), |
philpem@0 | 986 | .store_q_m (store_q_m), |
philpem@0 | 987 | .sign_extend_x (sign_extend_x), |
philpem@0 | 988 | .size_x (size_x), |
philpem@0 | 989 | `ifdef CFG_DCACHE_ENABLED |
philpem@0 | 990 | .dflush (dflush_m), |
philpem@0 | 991 | `endif |
philpem@0 | 992 | `ifdef CFG_IROM_ENABLED |
philpem@0 | 993 | .irom_data_m (irom_data_m), |
philpem@0 | 994 | `endif |
philpem@0 | 995 | // From Wishbone |
philpem@0 | 996 | .d_dat_i (D_DAT_I), |
philpem@0 | 997 | .d_ack_i (D_ACK_I), |
philpem@0 | 998 | .d_err_i (D_ERR_I), |
philpem@22 | 999 | .d_rty_i (D_RTY_I), |
philpem@0 | 1000 | // ----- Outputs ------- |
philpem@0 | 1001 | // To pipeline |
philpem@0 | 1002 | `ifdef CFG_DCACHE_ENABLED |
philpem@0 | 1003 | .dcache_refill_request (dcache_refill_request), |
philpem@0 | 1004 | .dcache_restart_request (dcache_restart_request), |
philpem@0 | 1005 | .dcache_stall_request (dcache_stall_request), |
philpem@0 | 1006 | .dcache_refilling (dcache_refilling), |
philpem@0 | 1007 | `endif |
philpem@0 | 1008 | `ifdef CFG_IROM_ENABLED |
philpem@0 | 1009 | .irom_store_data_m (irom_store_data_m), |
philpem@0 | 1010 | .irom_address_xm (irom_address_xm), |
philpem@0 | 1011 | .irom_we_xm (irom_we_xm), |
philpem@0 | 1012 | .irom_stall_request_x (irom_stall_request_x), |
philpem@0 | 1013 | `endif |
philpem@0 | 1014 | .load_data_w (load_data_w), |
philpem@0 | 1015 | .stall_wb_load (stall_wb_load), |
philpem@0 | 1016 | // To Wishbone |
philpem@0 | 1017 | .d_dat_o (D_DAT_O), |
philpem@0 | 1018 | .d_adr_o (D_ADR_O), |
philpem@0 | 1019 | .d_cyc_o (D_CYC_O), |
philpem@0 | 1020 | .d_sel_o (D_SEL_O), |
philpem@0 | 1021 | .d_stb_o (D_STB_O), |
philpem@0 | 1022 | .d_we_o (D_WE_O), |
philpem@0 | 1023 | .d_cti_o (D_CTI_O), |
philpem@0 | 1024 | .d_lock_o (D_LOCK_O), |
philpem@0 | 1025 | .d_bte_o (D_BTE_O) |
philpem@0 | 1026 | ); |
philpem@0 | 1027 | |
philpem@0 | 1028 | // Adder |
philpem@0 | 1029 | lm32_adder adder ( |
philpem@0 | 1030 | // ----- Inputs ------- |
philpem@0 | 1031 | .adder_op_x (adder_op_x), |
philpem@0 | 1032 | .adder_op_x_n (adder_op_x_n), |
philpem@0 | 1033 | .operand_0_x (operand_0_x), |
philpem@0 | 1034 | .operand_1_x (operand_1_x), |
philpem@0 | 1035 | // ----- Outputs ------- |
philpem@0 | 1036 | .adder_result_x (adder_result_x), |
philpem@0 | 1037 | .adder_carry_n_x (adder_carry_n_x), |
philpem@0 | 1038 | .adder_overflow_x (adder_overflow_x) |
philpem@0 | 1039 | ); |
philpem@0 | 1040 | |
philpem@0 | 1041 | // Logic operations |
philpem@0 | 1042 | lm32_logic_op logic_op ( |
philpem@0 | 1043 | // ----- Inputs ------- |
philpem@0 | 1044 | .logic_op_x (logic_op_x), |
philpem@0 | 1045 | .operand_0_x (operand_0_x), |
philpem@0 | 1046 | |
philpem@0 | 1047 | .operand_1_x (operand_1_x), |
philpem@0 | 1048 | // ----- Outputs ------- |
philpem@0 | 1049 | .logic_result_x (logic_result_x) |
philpem@0 | 1050 | ); |
philpem@0 | 1051 | |
philpem@0 | 1052 | `ifdef CFG_PL_BARREL_SHIFT_ENABLED |
philpem@0 | 1053 | // Pipelined barrel-shifter |
philpem@0 | 1054 | lm32_shifter shifter ( |
philpem@0 | 1055 | // ----- Inputs ------- |
philpem@0 | 1056 | .clk_i (clk_i), |
philpem@0 | 1057 | .rst_i (rst_i), |
philpem@0 | 1058 | .stall_x (stall_x), |
philpem@0 | 1059 | .direction_x (direction_x), |
philpem@0 | 1060 | .sign_extend_x (sign_extend_x), |
philpem@0 | 1061 | .operand_0_x (operand_0_x), |
philpem@0 | 1062 | .operand_1_x (operand_1_x), |
philpem@0 | 1063 | // ----- Outputs ------- |
philpem@0 | 1064 | .shifter_result_m (shifter_result_m) |
philpem@0 | 1065 | ); |
philpem@0 | 1066 | `endif |
philpem@0 | 1067 | |
philpem@0 | 1068 | `ifdef CFG_PL_MULTIPLY_ENABLED |
philpem@0 | 1069 | // Pipeline fixed-point multiplier |
philpem@0 | 1070 | lm32_multiplier multiplier ( |
philpem@0 | 1071 | // ----- Inputs ------- |
philpem@0 | 1072 | .clk_i (clk_i), |
philpem@0 | 1073 | .rst_i (rst_i), |
philpem@0 | 1074 | .stall_x (stall_x), |
philpem@0 | 1075 | .stall_m (stall_m), |
philpem@0 | 1076 | .operand_0 (d_result_0), |
philpem@0 | 1077 | .operand_1 (d_result_1), |
philpem@0 | 1078 | // ----- Outputs ------- |
philpem@0 | 1079 | .result (multiplier_result_w) |
philpem@0 | 1080 | ); |
philpem@0 | 1081 | `endif |
philpem@0 | 1082 | |
philpem@0 | 1083 | `ifdef LM32_MC_ARITHMETIC_ENABLED |
philpem@0 | 1084 | // Multi-cycle arithmetic |
philpem@0 | 1085 | lm32_mc_arithmetic mc_arithmetic ( |
philpem@0 | 1086 | // ----- Inputs ------- |
philpem@0 | 1087 | .clk_i (clk_i), |
philpem@0 | 1088 | .rst_i (rst_i), |
philpem@0 | 1089 | .stall_d (stall_d), |
philpem@0 | 1090 | .kill_x (kill_x), |
philpem@0 | 1091 | `ifdef CFG_MC_DIVIDE_ENABLED |
philpem@0 | 1092 | .divide_d (divide_q_d), |
philpem@0 | 1093 | .modulus_d (modulus_q_d), |
philpem@0 | 1094 | `endif |
philpem@0 | 1095 | `ifdef CFG_MC_MULTIPLY_ENABLED |
philpem@0 | 1096 | .multiply_d (multiply_q_d), |
philpem@0 | 1097 | `endif |
philpem@0 | 1098 | `ifdef CFG_MC_BARREL_SHIFT_ENABLED |
philpem@0 | 1099 | .shift_left_d (shift_left_q_d), |
philpem@0 | 1100 | .shift_right_d (shift_right_q_d), |
philpem@0 | 1101 | .sign_extend_d (sign_extend_d), |
philpem@0 | 1102 | `endif |
philpem@0 | 1103 | .operand_0_d (d_result_0), |
philpem@0 | 1104 | .operand_1_d (d_result_1), |
philpem@0 | 1105 | // ----- Outputs ------- |
philpem@0 | 1106 | .result_x (mc_result_x), |
philpem@0 | 1107 | `ifdef CFG_MC_DIVIDE_ENABLED |
philpem@0 | 1108 | .divide_by_zero_x (divide_by_zero_x), |
philpem@0 | 1109 | `endif |
philpem@0 | 1110 | .stall_request_x (mc_stall_request_x) |
philpem@0 | 1111 | ); |
philpem@0 | 1112 | `endif |
philpem@0 | 1113 | |
philpem@0 | 1114 | `ifdef CFG_INTERRUPTS_ENABLED |
philpem@0 | 1115 | // Interrupt unit |
philpem@0 | 1116 | lm32_interrupt interrupt ( |
philpem@0 | 1117 | // ----- Inputs ------- |
philpem@0 | 1118 | .clk_i (clk_i), |
philpem@0 | 1119 | .rst_i (rst_i), |
philpem@0 | 1120 | // From external devices |
philpem@0 | 1121 | .interrupt_n (interrupt_n), |
philpem@0 | 1122 | // From pipeline |
philpem@0 | 1123 | .stall_x (stall_x), |
philpem@0 | 1124 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 1125 | .non_debug_exception (non_debug_exception_q_w), |
philpem@0 | 1126 | .debug_exception (debug_exception_q_w), |
philpem@0 | 1127 | `else |
philpem@0 | 1128 | .exception (exception_q_w), |
philpem@0 | 1129 | `endif |
philpem@0 | 1130 | .eret_q_x (eret_q_x), |
philpem@0 | 1131 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 1132 | .bret_q_x (bret_q_x), |
philpem@0 | 1133 | `endif |
philpem@0 | 1134 | .csr (csr_x), |
philpem@0 | 1135 | .csr_write_data (operand_1_x), |
philpem@0 | 1136 | .csr_write_enable (csr_write_enable_q_x), |
philpem@0 | 1137 | // ----- Outputs ------- |
philpem@0 | 1138 | .interrupt_exception (interrupt_exception), |
philpem@0 | 1139 | // To pipeline |
philpem@0 | 1140 | .csr_read_data (interrupt_csr_read_data_x) |
philpem@0 | 1141 | ); |
philpem@0 | 1142 | `endif |
philpem@0 | 1143 | |
philpem@0 | 1144 | `ifdef CFG_JTAG_ENABLED |
philpem@0 | 1145 | // JTAG interface |
philpem@0 | 1146 | lm32_jtag jtag ( |
philpem@0 | 1147 | // ----- Inputs ------- |
philpem@0 | 1148 | .clk_i (clk_i), |
philpem@0 | 1149 | .rst_i (rst_i), |
philpem@0 | 1150 | // From JTAG |
philpem@0 | 1151 | .jtag_clk (jtag_clk), |
philpem@0 | 1152 | .jtag_update (jtag_update), |
philpem@0 | 1153 | .jtag_reg_q (jtag_reg_q), |
philpem@0 | 1154 | .jtag_reg_addr_q (jtag_reg_addr_q), |
philpem@0 | 1155 | // From pipeline |
philpem@0 | 1156 | `ifdef CFG_JTAG_UART_ENABLED |
philpem@0 | 1157 | .csr (csr_x), |
philpem@0 | 1158 | .csr_write_data (operand_1_x), |
philpem@0 | 1159 | .csr_write_enable (csr_write_enable_q_x), |
philpem@0 | 1160 | .stall_x (stall_x), |
philpem@0 | 1161 | `endif |
philpem@0 | 1162 | `ifdef CFG_HW_DEBUG_ENABLED |
philpem@0 | 1163 | .jtag_read_data (jtag_read_data), |
philpem@0 | 1164 | .jtag_access_complete (jtag_access_complete), |
philpem@0 | 1165 | `endif |
philpem@0 | 1166 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 1167 | .exception_q_w (debug_exception_q_w || non_debug_exception_q_w), |
philpem@0 | 1168 | `endif |
philpem@0 | 1169 | // ----- Outputs ------- |
philpem@0 | 1170 | // To pipeline |
philpem@0 | 1171 | `ifdef CFG_JTAG_UART_ENABLED |
philpem@0 | 1172 | .jtx_csr_read_data (jtx_csr_read_data), |
philpem@0 | 1173 | .jrx_csr_read_data (jrx_csr_read_data), |
philpem@0 | 1174 | `endif |
philpem@0 | 1175 | `ifdef CFG_HW_DEBUG_ENABLED |
philpem@0 | 1176 | .jtag_csr_write_enable (jtag_csr_write_enable), |
philpem@0 | 1177 | .jtag_csr_write_data (jtag_csr_write_data), |
philpem@0 | 1178 | .jtag_csr (jtag_csr), |
philpem@0 | 1179 | .jtag_read_enable (jtag_read_enable), |
philpem@0 | 1180 | .jtag_write_enable (jtag_write_enable), |
philpem@0 | 1181 | .jtag_write_data (jtag_write_data), |
philpem@0 | 1182 | .jtag_address (jtag_address), |
philpem@0 | 1183 | `endif |
philpem@0 | 1184 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 1185 | .jtag_break (jtag_break), |
philpem@0 | 1186 | .jtag_reset (reset_exception), |
philpem@0 | 1187 | `endif |
philpem@0 | 1188 | // To JTAG |
philpem@0 | 1189 | .jtag_reg_d (jtag_reg_d), |
philpem@0 | 1190 | .jtag_reg_addr_d (jtag_reg_addr_d) |
philpem@0 | 1191 | ); |
philpem@0 | 1192 | `endif |
philpem@0 | 1193 | |
philpem@0 | 1194 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 1195 | // Debug unit |
philpem@0 | 1196 | lm32_debug #( |
philpem@0 | 1197 | .breakpoints (breakpoints), |
philpem@0 | 1198 | .watchpoints (watchpoints) |
philpem@0 | 1199 | ) hw_debug ( |
philpem@0 | 1200 | // ----- Inputs ------- |
philpem@0 | 1201 | .clk_i (clk_i), |
philpem@0 | 1202 | .rst_i (rst_i), |
philpem@0 | 1203 | .pc_x (pc_x), |
philpem@0 | 1204 | .load_x (load_x), |
philpem@0 | 1205 | .store_x (store_x), |
philpem@0 | 1206 | .load_store_address_x (adder_result_x), |
philpem@0 | 1207 | .csr_write_enable_x (csr_write_enable_q_x), |
philpem@0 | 1208 | .csr_write_data (operand_1_x), |
philpem@0 | 1209 | .csr_x (csr_x), |
philpem@0 | 1210 | `ifdef CFG_HW_DEBUG_ENABLED |
philpem@0 | 1211 | .jtag_csr_write_enable (jtag_csr_write_enable), |
philpem@0 | 1212 | .jtag_csr_write_data (jtag_csr_write_data), |
philpem@0 | 1213 | .jtag_csr (jtag_csr), |
philpem@0 | 1214 | `endif |
philpem@0 | 1215 | `ifdef LM32_SINGLE_STEP_ENABLED |
philpem@0 | 1216 | .eret_q_x (eret_q_x), |
philpem@0 | 1217 | .bret_q_x (bret_q_x), |
philpem@0 | 1218 | .stall_x (stall_x), |
philpem@0 | 1219 | .exception_x (exception_x), |
philpem@0 | 1220 | .q_x (q_x), |
philpem@0 | 1221 | `ifdef CFG_DCACHE_ENABLED |
philpem@0 | 1222 | .dcache_refill_request (dcache_refill_request), |
philpem@0 | 1223 | `endif |
philpem@0 | 1224 | `endif |
philpem@0 | 1225 | // ----- Outputs ------- |
philpem@0 | 1226 | `ifdef LM32_SINGLE_STEP_ENABLED |
philpem@0 | 1227 | .dc_ss (dc_ss), |
philpem@0 | 1228 | `endif |
philpem@0 | 1229 | .dc_re (dc_re), |
philpem@0 | 1230 | .bp_match (bp_match), |
philpem@0 | 1231 | .wp_match (wp_match) |
philpem@0 | 1232 | ); |
philpem@0 | 1233 | `endif |
philpem@0 | 1234 | |
philpem@0 | 1235 | // Register file |
philpem@0 | 1236 | |
philpem@0 | 1237 | `ifdef CFG_EBR_POSEDGE_REGISTER_FILE |
philpem@0 | 1238 | /*---------------------------------------------------------------------- |
philpem@0 | 1239 | Register File is implemented using EBRs. There can be three accesses to |
philpem@0 | 1240 | the register file in each cycle: two reads and one write. On-chip block |
philpem@0 | 1241 | RAM has two read/write ports. To accomodate three accesses, two on-chip |
philpem@0 | 1242 | block RAMs are used (each register file "write" is made to both block |
philpem@0 | 1243 | RAMs). |
philpem@0 | 1244 | |
philpem@0 | 1245 | One limitation of the on-chip block RAMs is that one cannot perform a |
philpem@0 | 1246 | read and write to same location in a cycle (if this is done, then the |
philpem@0 | 1247 | data read out is indeterminate). |
philpem@0 | 1248 | ----------------------------------------------------------------------*/ |
philpem@0 | 1249 | wire [31:0] regfile_data_0, regfile_data_1; |
philpem@0 | 1250 | reg [31:0] w_result_d; |
philpem@0 | 1251 | reg regfile_raw_0, regfile_raw_0_nxt; |
philpem@0 | 1252 | reg regfile_raw_1, regfile_raw_1_nxt; |
philpem@0 | 1253 | |
philpem@0 | 1254 | /*---------------------------------------------------------------------- |
philpem@0 | 1255 | Check if read and write is being performed to same register in current |
philpem@0 | 1256 | cycle? This is done by comparing the read and write IDXs. |
philpem@0 | 1257 | ----------------------------------------------------------------------*/ |
philpem@0 | 1258 | always @(reg_write_enable_q_w or write_idx_w or instruction_f) |
philpem@0 | 1259 | begin |
philpem@0 | 1260 | if (reg_write_enable_q_w |
philpem@0 | 1261 | && (write_idx_w == instruction_f[25:21])) |
philpem@0 | 1262 | regfile_raw_0_nxt = 1'b1; |
philpem@0 | 1263 | else |
philpem@0 | 1264 | regfile_raw_0_nxt = 1'b0; |
philpem@0 | 1265 | |
philpem@0 | 1266 | if (reg_write_enable_q_w |
philpem@0 | 1267 | && (write_idx_w == instruction_f[20:16])) |
philpem@0 | 1268 | regfile_raw_1_nxt = 1'b1; |
philpem@0 | 1269 | else |
philpem@0 | 1270 | regfile_raw_1_nxt = 1'b0; |
philpem@0 | 1271 | end |
philpem@0 | 1272 | |
philpem@0 | 1273 | /*---------------------------------------------------------------------- |
philpem@0 | 1274 | Select latched (delayed) write value or data from register file. If |
philpem@0 | 1275 | read in previous cycle was performed to register written to in same |
philpem@0 | 1276 | cycle, then latched (delayed) write value is selected. |
philpem@0 | 1277 | ----------------------------------------------------------------------*/ |
philpem@0 | 1278 | always @(regfile_raw_0 or w_result_d or regfile_data_0) |
philpem@0 | 1279 | if (regfile_raw_0) |
philpem@0 | 1280 | reg_data_live_0 = w_result_d; |
philpem@0 | 1281 | else |
philpem@0 | 1282 | reg_data_live_0 = regfile_data_0; |
philpem@0 | 1283 | |
philpem@0 | 1284 | /*---------------------------------------------------------------------- |
philpem@0 | 1285 | Select latched (delayed) write value or data from register file. If |
philpem@0 | 1286 | read in previous cycle was performed to register written to in same |
philpem@0 | 1287 | cycle, then latched (delayed) write value is selected. |
philpem@0 | 1288 | ----------------------------------------------------------------------*/ |
philpem@0 | 1289 | always @(regfile_raw_1 or w_result_d or regfile_data_1) |
philpem@0 | 1290 | if (regfile_raw_1) |
philpem@0 | 1291 | reg_data_live_1 = w_result_d; |
philpem@0 | 1292 | else |
philpem@0 | 1293 | reg_data_live_1 = regfile_data_1; |
philpem@0 | 1294 | |
philpem@0 | 1295 | /*---------------------------------------------------------------------- |
philpem@0 | 1296 | Latch value written to register file |
philpem@0 | 1297 | ----------------------------------------------------------------------*/ |
philpem@0 | 1298 | always @(posedge clk_i `CFG_RESET_SENSITIVITY) |
philpem@0 | 1299 | if (rst_i == `TRUE) |
philpem@0 | 1300 | begin |
philpem@26 | 1301 | regfile_raw_0 <= #1 1'b0; |
philpem@26 | 1302 | regfile_raw_1 <= #1 1'b0; |
philpem@26 | 1303 | w_result_d <= #1 32'b0; |
philpem@0 | 1304 | end |
philpem@0 | 1305 | else |
philpem@0 | 1306 | begin |
philpem@26 | 1307 | regfile_raw_0 <= #1 regfile_raw_0_nxt; |
philpem@26 | 1308 | regfile_raw_1 <= #1 regfile_raw_1_nxt; |
philpem@26 | 1309 | w_result_d <= #1 w_result; |
philpem@0 | 1310 | end |
philpem@0 | 1311 | |
philpem@0 | 1312 | /*---------------------------------------------------------------------- |
philpem@0 | 1313 | Register file instantiation as Pseudo-Dual Port EBRs. |
philpem@0 | 1314 | ----------------------------------------------------------------------*/ |
philpem@0 | 1315 | pmi_ram_dp |
philpem@0 | 1316 | #( |
philpem@0 | 1317 | // ----- Parameters ----- |
philpem@0 | 1318 | .pmi_wr_addr_depth(1<<5), |
philpem@0 | 1319 | .pmi_wr_addr_width(5), |
philpem@0 | 1320 | .pmi_wr_data_width(32), |
philpem@0 | 1321 | .pmi_rd_addr_depth(1<<5), |
philpem@0 | 1322 | .pmi_rd_addr_width(5), |
philpem@0 | 1323 | .pmi_rd_data_width(32), |
philpem@0 | 1324 | .pmi_regmode("noreg"), |
philpem@0 | 1325 | .pmi_gsr("enable"), |
philpem@0 | 1326 | .pmi_resetmode("sync"), |
philpem@0 | 1327 | .pmi_init_file("none"), |
philpem@0 | 1328 | .pmi_init_file_format("binary"), |
philpem@0 | 1329 | .pmi_family(`LATTICE_FAMILY), |
philpem@0 | 1330 | .module_type("pmi_ram_dp") |
philpem@0 | 1331 | ) |
philpem@0 | 1332 | reg_0 |
philpem@0 | 1333 | ( |
philpem@0 | 1334 | // ----- Inputs ----- |
philpem@0 | 1335 | .Data(w_result), |
philpem@0 | 1336 | .WrAddress(write_idx_w), |
philpem@0 | 1337 | .RdAddress(instruction_f[25:21]), |
philpem@0 | 1338 | .WrClock(clk_i), |
philpem@0 | 1339 | .RdClock(clk_i), |
philpem@0 | 1340 | .WrClockEn(`TRUE), |
philpem@0 | 1341 | .RdClockEn(`TRUE), |
philpem@0 | 1342 | .WE(reg_write_enable_q_w), |
philpem@0 | 1343 | .Reset(rst_i), |
philpem@0 | 1344 | // ----- Outputs ----- |
philpem@0 | 1345 | .Q(regfile_data_0) |
philpem@0 | 1346 | ); |
philpem@0 | 1347 | |
philpem@0 | 1348 | pmi_ram_dp |
philpem@0 | 1349 | #( |
philpem@0 | 1350 | // ----- Parameters ----- |
philpem@0 | 1351 | .pmi_wr_addr_depth(1<<5), |
philpem@0 | 1352 | .pmi_wr_addr_width(5), |
philpem@0 | 1353 | .pmi_wr_data_width(32), |
philpem@0 | 1354 | .pmi_rd_addr_depth(1<<5), |
philpem@0 | 1355 | .pmi_rd_addr_width(5), |
philpem@0 | 1356 | .pmi_rd_data_width(32), |
philpem@0 | 1357 | .pmi_regmode("noreg"), |
philpem@0 | 1358 | .pmi_gsr("enable"), |
philpem@0 | 1359 | .pmi_resetmode("sync"), |
philpem@0 | 1360 | .pmi_init_file("none"), |
philpem@0 | 1361 | .pmi_init_file_format("binary"), |
philpem@0 | 1362 | .pmi_family(`LATTICE_FAMILY), |
philpem@0 | 1363 | .module_type("pmi_ram_dp") |
philpem@0 | 1364 | ) |
philpem@0 | 1365 | reg_1 |
philpem@0 | 1366 | ( |
philpem@0 | 1367 | // ----- Inputs ----- |
philpem@0 | 1368 | .Data(w_result), |
philpem@0 | 1369 | .WrAddress(write_idx_w), |
philpem@0 | 1370 | .RdAddress(instruction_f[20:16]), |
philpem@0 | 1371 | .WrClock(clk_i), |
philpem@0 | 1372 | .RdClock(clk_i), |
philpem@0 | 1373 | .WrClockEn(`TRUE), |
philpem@0 | 1374 | .RdClockEn(`TRUE), |
philpem@0 | 1375 | .WE(reg_write_enable_q_w), |
philpem@0 | 1376 | .Reset(rst_i), |
philpem@0 | 1377 | // ----- Outputs ----- |
philpem@0 | 1378 | .Q(regfile_data_1) |
philpem@0 | 1379 | ); |
philpem@0 | 1380 | `endif |
philpem@0 | 1381 | |
philpem@0 | 1382 | `ifdef CFG_EBR_NEGEDGE_REGISTER_FILE |
philpem@0 | 1383 | pmi_ram_dp |
philpem@0 | 1384 | #( |
philpem@0 | 1385 | // ----- Parameters ----- |
philpem@0 | 1386 | .pmi_wr_addr_depth(1<<5), |
philpem@0 | 1387 | .pmi_wr_addr_width(5), |
philpem@0 | 1388 | .pmi_wr_data_width(32), |
philpem@0 | 1389 | .pmi_rd_addr_depth(1<<5), |
philpem@0 | 1390 | .pmi_rd_addr_width(5), |
philpem@0 | 1391 | .pmi_rd_data_width(32), |
philpem@0 | 1392 | .pmi_regmode("noreg"), |
philpem@0 | 1393 | .pmi_gsr("enable"), |
philpem@0 | 1394 | .pmi_resetmode("sync"), |
philpem@0 | 1395 | .pmi_init_file("none"), |
philpem@0 | 1396 | .pmi_init_file_format("binary"), |
philpem@0 | 1397 | .pmi_family(`LATTICE_FAMILY), |
philpem@0 | 1398 | .module_type("pmi_ram_dp") |
philpem@0 | 1399 | ) |
philpem@0 | 1400 | reg_0 |
philpem@0 | 1401 | ( |
philpem@0 | 1402 | // ----- Inputs ----- |
philpem@0 | 1403 | .Data(w_result), |
philpem@0 | 1404 | .WrAddress(write_idx_w), |
philpem@0 | 1405 | .RdAddress(read_idx_0_d), |
philpem@0 | 1406 | .WrClock(clk_i), |
philpem@0 | 1407 | .RdClock(clk_n_i), |
philpem@0 | 1408 | .WrClockEn(`TRUE), |
philpem@0 | 1409 | .RdClockEn(stall_f == `FALSE), |
philpem@0 | 1410 | .WE(reg_write_enable_q_w), |
philpem@0 | 1411 | .Reset(rst_i), |
philpem@0 | 1412 | // ----- Outputs ----- |
philpem@0 | 1413 | .Q(reg_data_0) |
philpem@0 | 1414 | ); |
philpem@0 | 1415 | |
philpem@0 | 1416 | pmi_ram_dp |
philpem@0 | 1417 | #( |
philpem@0 | 1418 | // ----- Parameters ----- |
philpem@0 | 1419 | .pmi_wr_addr_depth(1<<5), |
philpem@0 | 1420 | .pmi_wr_addr_width(5), |
philpem@0 | 1421 | .pmi_wr_data_width(32), |
philpem@0 | 1422 | .pmi_rd_addr_depth(1<<5), |
philpem@0 | 1423 | .pmi_rd_addr_width(5), |
philpem@0 | 1424 | .pmi_rd_data_width(32), |
philpem@0 | 1425 | .pmi_regmode("noreg"), |
philpem@0 | 1426 | .pmi_gsr("enable"), |
philpem@0 | 1427 | .pmi_resetmode("sync"), |
philpem@0 | 1428 | .pmi_init_file("none"), |
philpem@0 | 1429 | .pmi_init_file_format("binary"), |
philpem@0 | 1430 | .pmi_family(`LATTICE_FAMILY), |
philpem@0 | 1431 | .module_type("pmi_ram_dp") |
philpem@0 | 1432 | ) |
philpem@0 | 1433 | reg_1 |
philpem@0 | 1434 | ( |
philpem@0 | 1435 | // ----- Inputs ----- |
philpem@0 | 1436 | .Data(w_result), |
philpem@0 | 1437 | .WrAddress(write_idx_w), |
philpem@0 | 1438 | .RdAddress(read_idx_1_d), |
philpem@0 | 1439 | .WrClock(clk_i), |
philpem@0 | 1440 | .RdClock(clk_n_i), |
philpem@0 | 1441 | .WrClockEn(`TRUE), |
philpem@0 | 1442 | .RdClockEn(stall_f == `FALSE), |
philpem@0 | 1443 | .WE(reg_write_enable_q_w), |
philpem@0 | 1444 | .Reset(rst_i), |
philpem@0 | 1445 | // ----- Outputs ----- |
philpem@0 | 1446 | .Q(reg_data_1) |
philpem@0 | 1447 | ); |
philpem@0 | 1448 | `endif |
philpem@0 | 1449 | |
philpem@0 | 1450 | |
philpem@0 | 1451 | ///////////////////////////////////////////////////// |
philpem@0 | 1452 | // Combinational Logic |
philpem@0 | 1453 | ///////////////////////////////////////////////////// |
philpem@0 | 1454 | |
philpem@0 | 1455 | `ifdef CFG_EBR_POSEDGE_REGISTER_FILE |
philpem@0 | 1456 | // Select between buffered and live data from register file |
philpem@0 | 1457 | assign reg_data_0 = use_buf ? reg_data_buf_0 : reg_data_live_0; |
philpem@0 | 1458 | assign reg_data_1 = use_buf ? reg_data_buf_1 : reg_data_live_1; |
philpem@0 | 1459 | `endif |
philpem@0 | 1460 | `ifdef LM32_EBR_REGISTER_FILE |
philpem@0 | 1461 | `else |
philpem@0 | 1462 | // Register file read ports |
philpem@0 | 1463 | assign reg_data_0 = registers[read_idx_0_d]; |
philpem@0 | 1464 | assign reg_data_1 = registers[read_idx_1_d]; |
philpem@0 | 1465 | `endif |
philpem@0 | 1466 | |
philpem@0 | 1467 | // Detect read-after-write hazzards |
philpem@0 | 1468 | assign raw_x_0 = (write_idx_x == read_idx_0_d) && (write_enable_q_x == `TRUE); |
philpem@0 | 1469 | assign raw_m_0 = (write_idx_m == read_idx_0_d) && (write_enable_q_m == `TRUE); |
philpem@0 | 1470 | assign raw_w_0 = (write_idx_w == read_idx_0_d) && (write_enable_q_w == `TRUE); |
philpem@0 | 1471 | assign raw_x_1 = (write_idx_x == read_idx_1_d) && (write_enable_q_x == `TRUE); |
philpem@0 | 1472 | assign raw_m_1 = (write_idx_m == read_idx_1_d) && (write_enable_q_m == `TRUE); |
philpem@0 | 1473 | assign raw_w_1 = (write_idx_w == read_idx_1_d) && (write_enable_q_w == `TRUE); |
philpem@0 | 1474 | |
philpem@0 | 1475 | // Interlock detection - Raise an interlock for RAW hazzards |
philpem@0 | 1476 | always @(*) |
philpem@0 | 1477 | begin |
philpem@0 | 1478 | if ( ( (x_bypass_enable_x == `FALSE) |
philpem@0 | 1479 | && ( ((read_enable_0_d == `TRUE) && (raw_x_0 == `TRUE)) |
philpem@0 | 1480 | || ((read_enable_1_d == `TRUE) && (raw_x_1 == `TRUE)) |
philpem@0 | 1481 | ) |
philpem@0 | 1482 | ) |
philpem@0 | 1483 | || ( (m_bypass_enable_m == `FALSE) |
philpem@0 | 1484 | && ( ((read_enable_0_d == `TRUE) && (raw_m_0 == `TRUE)) |
philpem@0 | 1485 | || ((read_enable_1_d == `TRUE) && (raw_m_1 == `TRUE)) |
philpem@0 | 1486 | ) |
philpem@0 | 1487 | ) |
philpem@0 | 1488 | ) |
philpem@0 | 1489 | interlock = `TRUE; |
philpem@0 | 1490 | else |
philpem@0 | 1491 | interlock = `FALSE; |
philpem@0 | 1492 | end |
philpem@0 | 1493 | |
philpem@0 | 1494 | // Bypass for reg port 0 |
philpem@0 | 1495 | always @(*) |
philpem@0 | 1496 | begin |
philpem@0 | 1497 | if (raw_x_0 == `TRUE) |
philpem@0 | 1498 | bypass_data_0 = x_result; |
philpem@0 | 1499 | else if (raw_m_0 == `TRUE) |
philpem@0 | 1500 | bypass_data_0 = m_result; |
philpem@0 | 1501 | else if (raw_w_0 == `TRUE) |
philpem@0 | 1502 | bypass_data_0 = w_result; |
philpem@0 | 1503 | else |
philpem@0 | 1504 | bypass_data_0 = reg_data_0; |
philpem@0 | 1505 | end |
philpem@0 | 1506 | |
philpem@0 | 1507 | // Bypass for reg port 1 |
philpem@0 | 1508 | always @(*) |
philpem@0 | 1509 | begin |
philpem@0 | 1510 | if (raw_x_1 == `TRUE) |
philpem@0 | 1511 | bypass_data_1 = x_result; |
philpem@0 | 1512 | else if (raw_m_1 == `TRUE) |
philpem@0 | 1513 | bypass_data_1 = m_result; |
philpem@0 | 1514 | else if (raw_w_1 == `TRUE) |
philpem@0 | 1515 | bypass_data_1 = w_result; |
philpem@0 | 1516 | else |
philpem@0 | 1517 | bypass_data_1 = reg_data_1; |
philpem@0 | 1518 | end |
philpem@0 | 1519 | |
philpem@0 | 1520 | /*---------------------------------------------------------------------- |
philpem@0 | 1521 | Branch prediction is performed in D stage of pipeline. Only PC-relative |
philpem@0 | 1522 | branches are predicted: forward-pointing conditional branches are not- |
philpem@0 | 1523 | taken, while backward-pointing conditional branches are taken. |
philpem@0 | 1524 | Unconditional branches are always predicted taken! |
philpem@0 | 1525 | ----------------------------------------------------------------------*/ |
philpem@0 | 1526 | assign branch_predict_d = bi_unconditional | bi_conditional; |
philpem@0 | 1527 | assign branch_predict_taken_d = bi_unconditional ? 1'b1 : (bi_conditional ? instruction_d[15] : 1'b0); |
philpem@0 | 1528 | |
philpem@0 | 1529 | // Compute branch target address: Branch PC PLUS Offset |
philpem@0 | 1530 | assign branch_target_d = pc_d + branch_offset_d; |
philpem@0 | 1531 | |
philpem@0 | 1532 | // Compute fetch address. Address of instruction sequentially after the |
philpem@0 | 1533 | // branch if branch is not taken. Target address of branch is branch is |
philpem@0 | 1534 | // taken |
philpem@0 | 1535 | assign branch_predict_address_d = branch_predict_taken_d ? branch_target_d : pc_f; |
philpem@0 | 1536 | |
philpem@0 | 1537 | // D stage result selection |
philpem@0 | 1538 | always @(*) |
philpem@0 | 1539 | begin |
philpem@0 | 1540 | d_result_0 = d_result_sel_0_d[0] ? {pc_f, 2'b00} : bypass_data_0; |
philpem@0 | 1541 | case (d_result_sel_1_d) |
philpem@0 | 1542 | `LM32_D_RESULT_SEL_1_ZERO: d_result_1 = {`LM32_WORD_WIDTH{1'b0}}; |
philpem@0 | 1543 | `LM32_D_RESULT_SEL_1_REG_1: d_result_1 = bypass_data_1; |
philpem@0 | 1544 | `LM32_D_RESULT_SEL_1_IMMEDIATE: d_result_1 = immediate_d; |
philpem@0 | 1545 | default: d_result_1 = {`LM32_WORD_WIDTH{1'bx}}; |
philpem@0 | 1546 | endcase |
philpem@0 | 1547 | end |
philpem@0 | 1548 | |
philpem@0 | 1549 | `ifdef CFG_USER_ENABLED |
philpem@0 | 1550 | // Operands for user-defined instructions |
philpem@0 | 1551 | assign user_operand_0 = operand_0_x; |
philpem@0 | 1552 | assign user_operand_1 = operand_1_x; |
philpem@0 | 1553 | `endif |
philpem@0 | 1554 | |
philpem@0 | 1555 | `ifdef CFG_SIGN_EXTEND_ENABLED |
philpem@0 | 1556 | // Sign-extension |
philpem@0 | 1557 | assign sextb_result_x = {{24{operand_0_x[7]}}, operand_0_x[7:0]}; |
philpem@0 | 1558 | assign sexth_result_x = {{16{operand_0_x[15]}}, operand_0_x[15:0]}; |
philpem@0 | 1559 | assign sext_result_x = size_x == `LM32_SIZE_BYTE ? sextb_result_x : sexth_result_x; |
philpem@0 | 1560 | `endif |
philpem@0 | 1561 | |
philpem@0 | 1562 | `ifdef LM32_NO_BARREL_SHIFT |
philpem@0 | 1563 | // Only single bit shift operations are supported when barrel-shifter isn't implemented |
philpem@0 | 1564 | assign shifter_result_x = {operand_0_x[`LM32_WORD_WIDTH-1] & sign_extend_x, operand_0_x[`LM32_WORD_WIDTH-1:1]}; |
philpem@0 | 1565 | `endif |
philpem@0 | 1566 | |
philpem@0 | 1567 | // Condition evaluation |
philpem@0 | 1568 | assign cmp_zero = operand_0_x == operand_1_x; |
philpem@0 | 1569 | assign cmp_negative = adder_result_x[`LM32_WORD_WIDTH-1]; |
philpem@0 | 1570 | assign cmp_overflow = adder_overflow_x; |
philpem@0 | 1571 | assign cmp_carry_n = adder_carry_n_x; |
philpem@0 | 1572 | always @(*) |
philpem@0 | 1573 | begin |
philpem@0 | 1574 | case (condition_x) |
philpem@0 | 1575 | `LM32_CONDITION_U1: condition_met_x = `TRUE; |
philpem@0 | 1576 | `LM32_CONDITION_U2: condition_met_x = `TRUE; |
philpem@0 | 1577 | `LM32_CONDITION_E: condition_met_x = cmp_zero; |
philpem@0 | 1578 | `LM32_CONDITION_NE: condition_met_x = !cmp_zero; |
philpem@0 | 1579 | `LM32_CONDITION_G: condition_met_x = !cmp_zero && (cmp_negative == cmp_overflow); |
philpem@0 | 1580 | `LM32_CONDITION_GU: condition_met_x = cmp_carry_n && !cmp_zero; |
philpem@0 | 1581 | `LM32_CONDITION_GE: condition_met_x = cmp_negative == cmp_overflow; |
philpem@0 | 1582 | `LM32_CONDITION_GEU: condition_met_x = cmp_carry_n; |
philpem@0 | 1583 | default: condition_met_x = 1'bx; |
philpem@0 | 1584 | endcase |
philpem@0 | 1585 | end |
philpem@0 | 1586 | |
philpem@0 | 1587 | // X stage result selection |
philpem@0 | 1588 | always @(*) |
philpem@0 | 1589 | begin |
philpem@0 | 1590 | x_result = x_result_sel_add_x ? adder_result_x |
philpem@0 | 1591 | : x_result_sel_csr_x ? csr_read_data_x |
philpem@0 | 1592 | `ifdef CFG_SIGN_EXTEND_ENABLED |
philpem@0 | 1593 | : x_result_sel_sext_x ? sext_result_x |
philpem@0 | 1594 | `endif |
philpem@0 | 1595 | `ifdef CFG_USER_ENABLED |
philpem@0 | 1596 | : x_result_sel_user_x ? user_result |
philpem@0 | 1597 | `endif |
philpem@0 | 1598 | `ifdef LM32_NO_BARREL_SHIFT |
philpem@0 | 1599 | : x_result_sel_shift_x ? shifter_result_x |
philpem@0 | 1600 | `endif |
philpem@0 | 1601 | `ifdef LM32_MC_ARITHMETIC_ENABLED |
philpem@0 | 1602 | : x_result_sel_mc_arith_x ? mc_result_x |
philpem@0 | 1603 | `endif |
philpem@0 | 1604 | : logic_result_x; |
philpem@0 | 1605 | end |
philpem@0 | 1606 | |
philpem@0 | 1607 | // M stage result selection |
philpem@0 | 1608 | always @(*) |
philpem@0 | 1609 | begin |
philpem@0 | 1610 | m_result = m_result_sel_compare_m ? {{`LM32_WORD_WIDTH-1{1'b0}}, condition_met_m} |
philpem@0 | 1611 | `ifdef CFG_PL_BARREL_SHIFT_ENABLED |
philpem@0 | 1612 | : m_result_sel_shift_m ? shifter_result_m |
philpem@0 | 1613 | `endif |
philpem@0 | 1614 | : operand_m; |
philpem@0 | 1615 | end |
philpem@0 | 1616 | |
philpem@0 | 1617 | // W stage result selection |
philpem@0 | 1618 | always @(*) |
philpem@0 | 1619 | begin |
philpem@0 | 1620 | w_result = w_result_sel_load_w ? load_data_w |
philpem@0 | 1621 | `ifdef CFG_PL_MULTIPLY_ENABLED |
philpem@0 | 1622 | : w_result_sel_mul_w ? multiplier_result_w |
philpem@0 | 1623 | `endif |
philpem@0 | 1624 | : operand_w; |
philpem@0 | 1625 | end |
philpem@0 | 1626 | |
philpem@0 | 1627 | `ifdef CFG_FAST_UNCONDITIONAL_BRANCH |
philpem@0 | 1628 | // Indicate when a branch should be taken in X stage |
philpem@0 | 1629 | assign branch_taken_x = (stall_x == `FALSE) |
philpem@0 | 1630 | && ( (branch_x == `TRUE) |
philpem@0 | 1631 | && ((condition_x == `LM32_CONDITION_U1) || (condition_x == `LM32_CONDITION_U2)) |
philpem@0 | 1632 | && (valid_x == `TRUE) |
philpem@0 | 1633 | && (branch_predict_x == `FALSE) |
philpem@0 | 1634 | ); |
philpem@0 | 1635 | `endif |
philpem@0 | 1636 | |
philpem@0 | 1637 | // Indicate when a branch should be taken in M stage (exceptions are a type of branch) |
philpem@0 | 1638 | assign branch_taken_m = (stall_m == `FALSE) |
philpem@0 | 1639 | && ( ( (branch_m == `TRUE) |
philpem@0 | 1640 | && (valid_m == `TRUE) |
philpem@0 | 1641 | && ( ( (condition_met_m == `TRUE) |
philpem@0 | 1642 | && (branch_predict_taken_m == `FALSE) |
philpem@0 | 1643 | ) |
philpem@0 | 1644 | || ( (condition_met_m == `FALSE) |
philpem@0 | 1645 | && (branch_predict_m == `TRUE) |
philpem@0 | 1646 | && (branch_predict_taken_m == `TRUE) |
philpem@0 | 1647 | ) |
philpem@0 | 1648 | ) |
philpem@0 | 1649 | ) |
philpem@0 | 1650 | || (exception_m == `TRUE) |
philpem@0 | 1651 | ); |
philpem@0 | 1652 | |
philpem@0 | 1653 | // Indicate when a branch in M stage is mispredicted as being taken |
philpem@0 | 1654 | assign branch_mispredict_taken_m = (condition_met_m == `FALSE) |
philpem@0 | 1655 | && (branch_predict_m == `TRUE) |
philpem@0 | 1656 | && (branch_predict_taken_m == `TRUE); |
philpem@0 | 1657 | |
philpem@0 | 1658 | // Indicate when a branch in M stage will cause flush in X stage |
philpem@0 | 1659 | assign branch_flushX_m = (stall_m == `FALSE) |
philpem@0 | 1660 | && ( ( (branch_m == `TRUE) |
philpem@0 | 1661 | && (valid_m == `TRUE) |
philpem@0 | 1662 | && ( (condition_met_m == `TRUE) |
philpem@0 | 1663 | || ( (condition_met_m == `FALSE) |
philpem@0 | 1664 | && (branch_predict_m == `TRUE) |
philpem@0 | 1665 | && (branch_predict_taken_m == `TRUE) |
philpem@0 | 1666 | ) |
philpem@0 | 1667 | ) |
philpem@0 | 1668 | ) |
philpem@0 | 1669 | || (exception_m == `TRUE) |
philpem@0 | 1670 | ); |
philpem@0 | 1671 | |
philpem@0 | 1672 | // Generate signal that will kill instructions in each pipeline stage when necessary |
philpem@0 | 1673 | assign kill_f = ( (valid_d == `TRUE) |
philpem@0 | 1674 | && (branch_predict_taken_d == `TRUE) |
philpem@0 | 1675 | ) |
philpem@0 | 1676 | || (branch_taken_m == `TRUE) |
philpem@0 | 1677 | `ifdef CFG_FAST_UNCONDITIONAL_BRANCH |
philpem@0 | 1678 | || (branch_taken_x == `TRUE) |
philpem@0 | 1679 | `endif |
philpem@0 | 1680 | `ifdef CFG_ICACHE_ENABLED |
philpem@0 | 1681 | || (icache_refill_request == `TRUE) |
philpem@0 | 1682 | `endif |
philpem@0 | 1683 | `ifdef CFG_DCACHE_ENABLED |
philpem@0 | 1684 | || (dcache_refill_request == `TRUE) |
philpem@0 | 1685 | `endif |
philpem@0 | 1686 | ; |
philpem@0 | 1687 | assign kill_d = (branch_taken_m == `TRUE) |
philpem@0 | 1688 | `ifdef CFG_FAST_UNCONDITIONAL_BRANCH |
philpem@0 | 1689 | || (branch_taken_x == `TRUE) |
philpem@0 | 1690 | `endif |
philpem@0 | 1691 | `ifdef CFG_ICACHE_ENABLED |
philpem@0 | 1692 | || (icache_refill_request == `TRUE) |
philpem@0 | 1693 | `endif |
philpem@0 | 1694 | `ifdef CFG_DCACHE_ENABLED |
philpem@0 | 1695 | || (dcache_refill_request == `TRUE) |
philpem@0 | 1696 | `endif |
philpem@0 | 1697 | ; |
philpem@0 | 1698 | assign kill_x = (branch_flushX_m == `TRUE) |
philpem@0 | 1699 | `ifdef CFG_DCACHE_ENABLED |
philpem@0 | 1700 | || (dcache_refill_request == `TRUE) |
philpem@0 | 1701 | `endif |
philpem@0 | 1702 | ; |
philpem@0 | 1703 | assign kill_m = `FALSE |
philpem@0 | 1704 | `ifdef CFG_DCACHE_ENABLED |
philpem@0 | 1705 | || (dcache_refill_request == `TRUE) |
philpem@0 | 1706 | `endif |
philpem@0 | 1707 | ; |
philpem@0 | 1708 | assign kill_w = `FALSE |
philpem@0 | 1709 | `ifdef CFG_DCACHE_ENABLED |
philpem@0 | 1710 | || (dcache_refill_request == `TRUE) |
philpem@0 | 1711 | `endif |
philpem@0 | 1712 | ; |
philpem@0 | 1713 | |
philpem@0 | 1714 | // Exceptions |
philpem@0 | 1715 | |
philpem@0 | 1716 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 1717 | assign breakpoint_exception = ( ( (break_x == `TRUE) |
philpem@0 | 1718 | || (bp_match == `TRUE) |
philpem@0 | 1719 | ) |
philpem@0 | 1720 | && (valid_x == `TRUE) |
philpem@0 | 1721 | ) |
philpem@0 | 1722 | `ifdef CFG_JTAG_ENABLED |
philpem@0 | 1723 | || (jtag_break == `TRUE) |
philpem@0 | 1724 | `endif |
philpem@0 | 1725 | ; |
philpem@0 | 1726 | `endif |
philpem@0 | 1727 | |
philpem@0 | 1728 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 1729 | assign watchpoint_exception = wp_match == `TRUE; |
philpem@0 | 1730 | `endif |
philpem@0 | 1731 | |
philpem@0 | 1732 | `ifdef CFG_BUS_ERRORS_ENABLED |
philpem@0 | 1733 | assign instruction_bus_error_exception = ( (bus_error_x == `TRUE) |
philpem@0 | 1734 | && (valid_x == `TRUE) |
philpem@0 | 1735 | ); |
philpem@0 | 1736 | assign data_bus_error_exception = data_bus_error_seen == `TRUE; |
philpem@0 | 1737 | `endif |
philpem@0 | 1738 | |
philpem@0 | 1739 | `ifdef CFG_MC_DIVIDE_ENABLED |
philpem@0 | 1740 | assign divide_by_zero_exception = divide_by_zero_x == `TRUE; |
philpem@0 | 1741 | `endif |
philpem@0 | 1742 | |
philpem@0 | 1743 | assign system_call_exception = ( (scall_x == `TRUE) |
philpem@0 | 1744 | `ifdef CFG_BUS_ERRORS_ENABLED |
philpem@0 | 1745 | && (valid_x == `TRUE) |
philpem@0 | 1746 | `endif |
philpem@0 | 1747 | ); |
philpem@0 | 1748 | |
philpem@0 | 1749 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 1750 | assign debug_exception_x = (breakpoint_exception == `TRUE) |
philpem@0 | 1751 | || (watchpoint_exception == `TRUE) |
philpem@0 | 1752 | ; |
philpem@0 | 1753 | |
philpem@0 | 1754 | assign non_debug_exception_x = (system_call_exception == `TRUE) |
philpem@0 | 1755 | `ifdef CFG_JTAG_ENABLED |
philpem@0 | 1756 | || (reset_exception == `TRUE) |
philpem@0 | 1757 | `endif |
philpem@0 | 1758 | `ifdef CFG_BUS_ERRORS_ENABLED |
philpem@0 | 1759 | || (instruction_bus_error_exception == `TRUE) |
philpem@0 | 1760 | || (data_bus_error_exception == `TRUE) |
philpem@0 | 1761 | `endif |
philpem@0 | 1762 | `ifdef CFG_MC_DIVIDE_ENABLED |
philpem@0 | 1763 | || (divide_by_zero_exception == `TRUE) |
philpem@0 | 1764 | `endif |
philpem@0 | 1765 | `ifdef CFG_INTERRUPTS_ENABLED |
philpem@0 | 1766 | || ( (interrupt_exception == `TRUE) |
philpem@0 | 1767 | `ifdef LM32_SINGLE_STEP_ENABLED |
philpem@0 | 1768 | && (dc_ss == `FALSE) |
philpem@0 | 1769 | `endif |
philpem@0 | 1770 | `ifdef CFG_BUS_ERRORS_ENABLED |
philpem@0 | 1771 | && (store_q_m == `FALSE) |
philpem@0 | 1772 | && (D_CYC_O == `FALSE) |
philpem@0 | 1773 | `endif |
philpem@0 | 1774 | ) |
philpem@0 | 1775 | `endif |
philpem@0 | 1776 | ; |
philpem@0 | 1777 | |
philpem@0 | 1778 | assign exception_x = (debug_exception_x == `TRUE) || (non_debug_exception_x == `TRUE); |
philpem@0 | 1779 | `else |
philpem@0 | 1780 | assign exception_x = (system_call_exception == `TRUE) |
philpem@0 | 1781 | `ifdef CFG_BUS_ERRORS_ENABLED |
philpem@0 | 1782 | || (instruction_bus_error_exception == `TRUE) |
philpem@0 | 1783 | || (data_bus_error_exception == `TRUE) |
philpem@0 | 1784 | `endif |
philpem@0 | 1785 | `ifdef CFG_MC_DIVIDE_ENABLED |
philpem@0 | 1786 | || (divide_by_zero_exception == `TRUE) |
philpem@0 | 1787 | `endif |
philpem@0 | 1788 | `ifdef CFG_INTERRUPTS_ENABLED |
philpem@0 | 1789 | || ( (interrupt_exception == `TRUE) |
philpem@0 | 1790 | `ifdef LM32_SINGLE_STEP_ENABLED |
philpem@0 | 1791 | && (dc_ss == `FALSE) |
philpem@0 | 1792 | `endif |
philpem@0 | 1793 | `ifdef CFG_BUS_ERRORS_ENABLED |
philpem@0 | 1794 | && (store_q_m == `FALSE) |
philpem@0 | 1795 | && (D_CYC_O == `FALSE) |
philpem@0 | 1796 | `endif |
philpem@0 | 1797 | ) |
philpem@0 | 1798 | `endif |
philpem@0 | 1799 | ; |
philpem@0 | 1800 | `endif |
philpem@0 | 1801 | |
philpem@0 | 1802 | // Exception ID |
philpem@0 | 1803 | always @(*) |
philpem@0 | 1804 | begin |
philpem@0 | 1805 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 1806 | `ifdef CFG_JTAG_ENABLED |
philpem@0 | 1807 | if (reset_exception == `TRUE) |
philpem@0 | 1808 | eid_x = `LM32_EID_RESET; |
philpem@0 | 1809 | else |
philpem@0 | 1810 | `endif |
philpem@0 | 1811 | `ifdef CFG_BUS_ERRORS_ENABLED |
philpem@0 | 1812 | if (data_bus_error_exception == `TRUE) |
philpem@0 | 1813 | eid_x = `LM32_EID_DATA_BUS_ERROR; |
philpem@0 | 1814 | else |
philpem@0 | 1815 | `endif |
philpem@0 | 1816 | if (breakpoint_exception == `TRUE) |
philpem@0 | 1817 | eid_x = `LM32_EID_BREAKPOINT; |
philpem@0 | 1818 | else |
philpem@0 | 1819 | `endif |
philpem@0 | 1820 | `ifdef CFG_BUS_ERRORS_ENABLED |
philpem@0 | 1821 | if (data_bus_error_exception == `TRUE) |
philpem@0 | 1822 | eid_x = `LM32_EID_DATA_BUS_ERROR; |
philpem@0 | 1823 | else |
philpem@0 | 1824 | if (instruction_bus_error_exception == `TRUE) |
philpem@0 | 1825 | eid_x = `LM32_EID_INST_BUS_ERROR; |
philpem@0 | 1826 | else |
philpem@0 | 1827 | `endif |
philpem@0 | 1828 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 1829 | if (watchpoint_exception == `TRUE) |
philpem@0 | 1830 | eid_x = `LM32_EID_WATCHPOINT; |
philpem@0 | 1831 | else |
philpem@0 | 1832 | `endif |
philpem@0 | 1833 | `ifdef CFG_MC_DIVIDE_ENABLED |
philpem@0 | 1834 | if (divide_by_zero_exception == `TRUE) |
philpem@0 | 1835 | eid_x = `LM32_EID_DIVIDE_BY_ZERO; |
philpem@0 | 1836 | else |
philpem@0 | 1837 | `endif |
philpem@0 | 1838 | `ifdef CFG_INTERRUPTS_ENABLED |
philpem@0 | 1839 | if ( (interrupt_exception == `TRUE) |
philpem@0 | 1840 | `ifdef LM32_SINGLE_STEP_ENABLED |
philpem@0 | 1841 | && (dc_ss == `FALSE) |
philpem@0 | 1842 | `endif |
philpem@0 | 1843 | ) |
philpem@0 | 1844 | eid_x = `LM32_EID_INTERRUPT; |
philpem@0 | 1845 | else |
philpem@0 | 1846 | `endif |
philpem@0 | 1847 | eid_x = `LM32_EID_SCALL; |
philpem@0 | 1848 | end |
philpem@0 | 1849 | |
philpem@0 | 1850 | // Stall generation |
philpem@0 | 1851 | |
philpem@0 | 1852 | assign stall_a = (stall_f == `TRUE); |
philpem@0 | 1853 | |
philpem@0 | 1854 | assign stall_f = (stall_d == `TRUE); |
philpem@0 | 1855 | |
philpem@0 | 1856 | assign stall_d = (stall_x == `TRUE) |
philpem@0 | 1857 | || ( (interlock == `TRUE) |
philpem@0 | 1858 | && (kill_d == `FALSE) |
philpem@0 | 1859 | ) |
philpem@0 | 1860 | || ( ( (eret_d == `TRUE) |
philpem@0 | 1861 | || (scall_d == `TRUE) |
philpem@0 | 1862 | || (bus_error_d == `TRUE) |
philpem@0 | 1863 | ) |
philpem@0 | 1864 | && ( (load_q_x == `TRUE) |
philpem@0 | 1865 | || (load_q_m == `TRUE) |
philpem@0 | 1866 | || (store_q_x == `TRUE) |
philpem@0 | 1867 | || (store_q_m == `TRUE) |
philpem@0 | 1868 | || (D_CYC_O == `TRUE) |
philpem@0 | 1869 | ) |
philpem@0 | 1870 | && (kill_d == `FALSE) |
philpem@0 | 1871 | ) |
philpem@0 | 1872 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 1873 | || ( ( (break_d == `TRUE) |
philpem@0 | 1874 | || (bret_d == `TRUE) |
philpem@0 | 1875 | ) |
philpem@0 | 1876 | && ( (load_q_x == `TRUE) |
philpem@0 | 1877 | || (store_q_x == `TRUE) |
philpem@0 | 1878 | || (load_q_m == `TRUE) |
philpem@0 | 1879 | || (store_q_m == `TRUE) |
philpem@0 | 1880 | || (D_CYC_O == `TRUE) |
philpem@0 | 1881 | ) |
philpem@0 | 1882 | && (kill_d == `FALSE) |
philpem@0 | 1883 | ) |
philpem@0 | 1884 | `endif |
philpem@0 | 1885 | || ( (csr_write_enable_d == `TRUE) |
philpem@0 | 1886 | && (load_q_x == `TRUE) |
philpem@0 | 1887 | ) |
philpem@0 | 1888 | ; |
philpem@0 | 1889 | |
philpem@0 | 1890 | assign stall_x = (stall_m == `TRUE) |
philpem@0 | 1891 | `ifdef LM32_MC_ARITHMETIC_ENABLED |
philpem@0 | 1892 | || ( (mc_stall_request_x == `TRUE) |
philpem@0 | 1893 | && (kill_x == `FALSE) |
philpem@0 | 1894 | ) |
philpem@0 | 1895 | `endif |
philpem@0 | 1896 | `ifdef CFG_IROM_ENABLED |
philpem@0 | 1897 | // Stall load/store instruction in D stage if there is an ongoing store |
philpem@0 | 1898 | // operation to instruction ROM in M stage |
philpem@0 | 1899 | || ( (irom_stall_request_x == `TRUE) |
philpem@0 | 1900 | && ( (load_d == `TRUE) |
philpem@0 | 1901 | || (store_d == `TRUE) |
philpem@0 | 1902 | ) |
philpem@0 | 1903 | ) |
philpem@0 | 1904 | `endif |
philpem@0 | 1905 | ; |
philpem@0 | 1906 | |
philpem@0 | 1907 | assign stall_m = (stall_wb_load == `TRUE) |
philpem@0 | 1908 | `ifdef CFG_SIZE_OVER_SPEED |
philpem@0 | 1909 | || (D_CYC_O == `TRUE) |
philpem@0 | 1910 | `else |
philpem@0 | 1911 | || ( (D_CYC_O == `TRUE) |
philpem@0 | 1912 | && ( (store_m == `TRUE) |
philpem@0 | 1913 | /* |
philpem@0 | 1914 | Bug: Following loop does not allow interrupts to be services since |
philpem@0 | 1915 | either D_CYC_O or store_m is always high during entire duration of |
philpem@0 | 1916 | loop. |
philpem@0 | 1917 | L1: addi r1, r1, 1 |
philpem@0 | 1918 | sw (r2,0), r1 |
philpem@0 | 1919 | bi L1 |
philpem@0 | 1920 | |
philpem@0 | 1921 | Introduce a single-cycle stall when a wishbone cycle is in progress |
philpem@0 | 1922 | and a new store instruction is in Execute stage and a interrupt |
philpem@0 | 1923 | exception has occured. This stall will ensure that D_CYC_O and |
philpem@0 | 1924 | store_m will both be low for one cycle. |
philpem@0 | 1925 | */ |
philpem@0 | 1926 | || ((store_x == `TRUE) && (interrupt_exception == `TRUE)) |
philpem@0 | 1927 | || (load_m == `TRUE) |
philpem@0 | 1928 | || (load_x == `TRUE) |
philpem@0 | 1929 | ) |
philpem@0 | 1930 | ) |
philpem@0 | 1931 | `endif |
philpem@0 | 1932 | `ifdef CFG_DCACHE_ENABLED |
philpem@0 | 1933 | || (dcache_stall_request == `TRUE) // Need to stall in case a taken branch is in M stage and data cache is only being flush, so wont be restarted |
philpem@0 | 1934 | `endif |
philpem@0 | 1935 | `ifdef CFG_ICACHE_ENABLED |
philpem@0 | 1936 | || (icache_stall_request == `TRUE) // Pipeline needs to be stalled otherwise branches may be lost |
philpem@0 | 1937 | || ((I_CYC_O == `TRUE) && ((branch_m == `TRUE) || (exception_m == `TRUE))) |
philpem@0 | 1938 | `else |
philpem@0 | 1939 | `ifdef CFG_IWB_ENABLED |
philpem@0 | 1940 | || (I_CYC_O == `TRUE) |
philpem@0 | 1941 | `endif |
philpem@0 | 1942 | `endif |
philpem@0 | 1943 | `ifdef CFG_USER_ENABLED |
philpem@0 | 1944 | || ( (user_valid == `TRUE) // Stall whole pipeline, rather than just X stage, where the instruction is, so we don't have to worry about exceptions (maybe) |
philpem@0 | 1945 | && (user_complete == `FALSE) |
philpem@0 | 1946 | ) |
philpem@0 | 1947 | `endif |
philpem@0 | 1948 | ; |
philpem@0 | 1949 | |
philpem@0 | 1950 | // Qualify state changing control signals |
philpem@0 | 1951 | `ifdef LM32_MC_ARITHMETIC_ENABLED |
philpem@0 | 1952 | assign q_d = (valid_d == `TRUE) && (kill_d == `FALSE); |
philpem@0 | 1953 | `endif |
philpem@0 | 1954 | `ifdef CFG_MC_BARREL_SHIFT_ENABLED |
philpem@0 | 1955 | assign shift_left_q_d = (shift_left_d == `TRUE) && (q_d == `TRUE); |
philpem@0 | 1956 | assign shift_right_q_d = (shift_right_d == `TRUE) && (q_d == `TRUE); |
philpem@0 | 1957 | `endif |
philpem@0 | 1958 | `ifdef CFG_MC_MULTIPLY_ENABLED |
philpem@0 | 1959 | assign multiply_q_d = (multiply_d == `TRUE) && (q_d == `TRUE); |
philpem@0 | 1960 | `endif |
philpem@0 | 1961 | `ifdef CFG_MC_DIVIDE_ENABLED |
philpem@0 | 1962 | assign divide_q_d = (divide_d == `TRUE) && (q_d == `TRUE); |
philpem@0 | 1963 | assign modulus_q_d = (modulus_d == `TRUE) && (q_d == `TRUE); |
philpem@0 | 1964 | `endif |
philpem@0 | 1965 | assign q_x = (valid_x == `TRUE) && (kill_x == `FALSE); |
philpem@0 | 1966 | assign csr_write_enable_q_x = (csr_write_enable_x == `TRUE) && (q_x == `TRUE); |
philpem@0 | 1967 | assign eret_q_x = (eret_x == `TRUE) && (q_x == `TRUE); |
philpem@0 | 1968 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 1969 | assign bret_q_x = (bret_x == `TRUE) && (q_x == `TRUE); |
philpem@0 | 1970 | `endif |
philpem@0 | 1971 | assign load_q_x = (load_x == `TRUE) |
philpem@0 | 1972 | && (q_x == `TRUE) |
philpem@0 | 1973 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 1974 | && (bp_match == `FALSE) |
philpem@0 | 1975 | `endif |
philpem@0 | 1976 | ; |
philpem@0 | 1977 | assign store_q_x = (store_x == `TRUE) |
philpem@0 | 1978 | && (q_x == `TRUE) |
philpem@0 | 1979 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 1980 | && (bp_match == `FALSE) |
philpem@0 | 1981 | `endif |
philpem@0 | 1982 | ; |
philpem@0 | 1983 | `ifdef CFG_USER_ENABLED |
philpem@0 | 1984 | assign user_valid = (x_result_sel_user_x == `TRUE) && (q_x == `TRUE); |
philpem@0 | 1985 | `endif |
philpem@0 | 1986 | assign q_m = (valid_m == `TRUE) && (kill_m == `FALSE) && (exception_m == `FALSE); |
philpem@0 | 1987 | assign load_q_m = (load_m == `TRUE) && (q_m == `TRUE); |
philpem@0 | 1988 | assign store_q_m = (store_m == `TRUE) && (q_m == `TRUE); |
philpem@0 | 1989 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 1990 | assign debug_exception_q_w = ((debug_exception_w == `TRUE) && (valid_w == `TRUE)); |
philpem@0 | 1991 | assign non_debug_exception_q_w = ((non_debug_exception_w == `TRUE) && (valid_w == `TRUE)); |
philpem@0 | 1992 | `else |
philpem@0 | 1993 | assign exception_q_w = ((exception_w == `TRUE) && (valid_w == `TRUE)); |
philpem@0 | 1994 | `endif |
philpem@0 | 1995 | // Don't qualify register write enables with kill, as the signal is needed early, and it doesn't matter if the instruction is killed (except for the actual write - but that is handled separately) |
philpem@0 | 1996 | assign write_enable_q_x = (write_enable_x == `TRUE) && (valid_x == `TRUE) && (branch_flushX_m == `FALSE); |
philpem@0 | 1997 | assign write_enable_q_m = (write_enable_m == `TRUE) && (valid_m == `TRUE); |
philpem@0 | 1998 | assign write_enable_q_w = (write_enable_w == `TRUE) && (valid_w == `TRUE); |
philpem@0 | 1999 | // The enable that actually does write the registers needs to be qualified with kill |
philpem@0 | 2000 | assign reg_write_enable_q_w = (write_enable_w == `TRUE) && (kill_w == `FALSE) && (valid_w == `TRUE); |
philpem@0 | 2001 | |
philpem@0 | 2002 | // Configuration (CFG) CSR |
philpem@0 | 2003 | assign cfg = { |
philpem@0 | 2004 | `LM32_REVISION, |
philpem@0 | 2005 | watchpoints[3:0], |
philpem@0 | 2006 | breakpoints[3:0], |
philpem@0 | 2007 | interrupts[5:0], |
philpem@0 | 2008 | `ifdef CFG_JTAG_UART_ENABLED |
philpem@0 | 2009 | `TRUE, |
philpem@0 | 2010 | `else |
philpem@0 | 2011 | `FALSE, |
philpem@0 | 2012 | `endif |
philpem@0 | 2013 | `ifdef CFG_ROM_DEBUG_ENABLED |
philpem@0 | 2014 | `TRUE, |
philpem@0 | 2015 | `else |
philpem@0 | 2016 | `FALSE, |
philpem@0 | 2017 | `endif |
philpem@0 | 2018 | `ifdef CFG_HW_DEBUG_ENABLED |
philpem@0 | 2019 | `TRUE, |
philpem@0 | 2020 | `else |
philpem@0 | 2021 | `FALSE, |
philpem@0 | 2022 | `endif |
philpem@0 | 2023 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 2024 | `TRUE, |
philpem@0 | 2025 | `else |
philpem@0 | 2026 | `FALSE, |
philpem@0 | 2027 | `endif |
philpem@0 | 2028 | `ifdef CFG_ICACHE_ENABLED |
philpem@0 | 2029 | `TRUE, |
philpem@0 | 2030 | `else |
philpem@0 | 2031 | `FALSE, |
philpem@0 | 2032 | `endif |
philpem@0 | 2033 | `ifdef CFG_DCACHE_ENABLED |
philpem@0 | 2034 | `TRUE, |
philpem@0 | 2035 | `else |
philpem@0 | 2036 | `FALSE, |
philpem@0 | 2037 | `endif |
philpem@0 | 2038 | `ifdef CFG_CYCLE_COUNTER_ENABLED |
philpem@0 | 2039 | `TRUE, |
philpem@0 | 2040 | `else |
philpem@0 | 2041 | `FALSE, |
philpem@0 | 2042 | `endif |
philpem@0 | 2043 | `ifdef CFG_USER_ENABLED |
philpem@0 | 2044 | `TRUE, |
philpem@0 | 2045 | `else |
philpem@0 | 2046 | `FALSE, |
philpem@0 | 2047 | `endif |
philpem@0 | 2048 | `ifdef CFG_SIGN_EXTEND_ENABLED |
philpem@0 | 2049 | `TRUE, |
philpem@0 | 2050 | `else |
philpem@0 | 2051 | `FALSE, |
philpem@0 | 2052 | `endif |
philpem@0 | 2053 | `ifdef LM32_BARREL_SHIFT_ENABLED |
philpem@0 | 2054 | `TRUE, |
philpem@0 | 2055 | `else |
philpem@0 | 2056 | `FALSE, |
philpem@0 | 2057 | `endif |
philpem@0 | 2058 | `ifdef CFG_MC_DIVIDE_ENABLED |
philpem@0 | 2059 | `TRUE, |
philpem@0 | 2060 | `else |
philpem@0 | 2061 | `FALSE, |
philpem@0 | 2062 | `endif |
philpem@0 | 2063 | `ifdef LM32_MULTIPLY_ENABLED |
philpem@0 | 2064 | `TRUE |
philpem@0 | 2065 | `else |
philpem@0 | 2066 | `FALSE |
philpem@0 | 2067 | `endif |
philpem@0 | 2068 | }; |
philpem@0 | 2069 | |
philpem@0 | 2070 | assign cfg2 = { |
philpem@0 | 2071 | 30'b0, |
philpem@0 | 2072 | `ifdef CFG_IROM_ENABLED |
philpem@0 | 2073 | `TRUE, |
philpem@0 | 2074 | `else |
philpem@0 | 2075 | `FALSE, |
philpem@0 | 2076 | `endif |
philpem@0 | 2077 | `ifdef CFG_DRAM_ENABLED |
philpem@0 | 2078 | `TRUE |
philpem@0 | 2079 | `else |
philpem@0 | 2080 | `FALSE |
philpem@0 | 2081 | `endif |
philpem@0 | 2082 | }; |
philpem@0 | 2083 | |
philpem@0 | 2084 | // Cache flush |
philpem@0 | 2085 | `ifdef CFG_ICACHE_ENABLED |
philpem@0 | 2086 | assign iflush = (csr_write_enable_d == `TRUE) |
philpem@0 | 2087 | && (csr_d == `LM32_CSR_ICC) |
philpem@0 | 2088 | && (stall_d == `FALSE) |
philpem@0 | 2089 | && (kill_d == `FALSE) |
philpem@0 | 2090 | && (valid_d == `TRUE); |
philpem@0 | 2091 | `endif |
philpem@0 | 2092 | `ifdef CFG_DCACHE_ENABLED |
philpem@0 | 2093 | assign dflush_x = (csr_write_enable_q_x == `TRUE) |
philpem@0 | 2094 | && (csr_x == `LM32_CSR_DCC); |
philpem@0 | 2095 | `endif |
philpem@0 | 2096 | |
philpem@0 | 2097 | // Extract CSR index |
philpem@0 | 2098 | assign csr_d = read_idx_0_d[`LM32_CSR_RNG]; |
philpem@0 | 2099 | |
philpem@0 | 2100 | // CSR reads |
philpem@0 | 2101 | always @(*) |
philpem@0 | 2102 | begin |
philpem@0 | 2103 | case (csr_x) |
philpem@0 | 2104 | `ifdef CFG_INTERRUPTS_ENABLED |
philpem@0 | 2105 | `LM32_CSR_IE, |
philpem@0 | 2106 | `LM32_CSR_IM, |
philpem@0 | 2107 | `LM32_CSR_IP: csr_read_data_x = interrupt_csr_read_data_x; |
philpem@0 | 2108 | `endif |
philpem@0 | 2109 | `ifdef CFG_CYCLE_COUNTER_ENABLED |
philpem@0 | 2110 | `LM32_CSR_CC: csr_read_data_x = cc; |
philpem@0 | 2111 | `endif |
philpem@0 | 2112 | `LM32_CSR_CFG: csr_read_data_x = cfg; |
philpem@0 | 2113 | `LM32_CSR_EBA: csr_read_data_x = {eba, 8'h00}; |
philpem@0 | 2114 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 2115 | `LM32_CSR_DEBA: csr_read_data_x = {deba, 8'h00}; |
philpem@0 | 2116 | `endif |
philpem@0 | 2117 | `ifdef CFG_JTAG_UART_ENABLED |
philpem@0 | 2118 | `LM32_CSR_JTX: csr_read_data_x = jtx_csr_read_data; |
philpem@0 | 2119 | `LM32_CSR_JRX: csr_read_data_x = jrx_csr_read_data; |
philpem@0 | 2120 | `endif |
philpem@0 | 2121 | `LM32_CSR_CFG2: csr_read_data_x = cfg2; |
philpem@0 | 2122 | |
philpem@0 | 2123 | default: csr_read_data_x = {`LM32_WORD_WIDTH{1'bx}}; |
philpem@0 | 2124 | endcase |
philpem@0 | 2125 | end |
philpem@0 | 2126 | |
philpem@0 | 2127 | ///////////////////////////////////////////////////// |
philpem@0 | 2128 | // Sequential Logic |
philpem@0 | 2129 | ///////////////////////////////////////////////////// |
philpem@0 | 2130 | |
philpem@0 | 2131 | // Exception Base Address (EBA) CSR |
philpem@0 | 2132 | always @(posedge clk_i `CFG_RESET_SENSITIVITY) |
philpem@0 | 2133 | begin |
philpem@0 | 2134 | if (rst_i == `TRUE) |
philpem@26 | 2135 | eba <= #1 eba_reset[`LM32_PC_WIDTH+2-1:8]; |
philpem@0 | 2136 | else |
philpem@0 | 2137 | begin |
philpem@0 | 2138 | if ((csr_write_enable_q_x == `TRUE) && (csr_x == `LM32_CSR_EBA) && (stall_x == `FALSE)) |
philpem@26 | 2139 | eba <= #1 operand_1_x[`LM32_PC_WIDTH+2-1:8]; |
philpem@0 | 2140 | `ifdef CFG_HW_DEBUG_ENABLED |
philpem@0 | 2141 | if ((jtag_csr_write_enable == `TRUE) && (jtag_csr == `LM32_CSR_EBA)) |
philpem@26 | 2142 | eba <= #1 jtag_csr_write_data[`LM32_PC_WIDTH+2-1:8]; |
philpem@0 | 2143 | `endif |
philpem@0 | 2144 | end |
philpem@0 | 2145 | end |
philpem@0 | 2146 | |
philpem@0 | 2147 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 2148 | // Debug Exception Base Address (DEBA) CSR |
philpem@0 | 2149 | always @(posedge clk_i `CFG_RESET_SENSITIVITY) |
philpem@0 | 2150 | begin |
philpem@0 | 2151 | if (rst_i == `TRUE) |
philpem@26 | 2152 | deba <= #1 deba_reset[`LM32_PC_WIDTH+2-1:8]; |
philpem@0 | 2153 | else |
philpem@0 | 2154 | begin |
philpem@0 | 2155 | if ((csr_write_enable_q_x == `TRUE) && (csr_x == `LM32_CSR_DEBA) && (stall_x == `FALSE)) |
philpem@26 | 2156 | deba <= #1 operand_1_x[`LM32_PC_WIDTH+2-1:8]; |
philpem@0 | 2157 | `ifdef CFG_HW_DEBUG_ENABLED |
philpem@0 | 2158 | if ((jtag_csr_write_enable == `TRUE) && (jtag_csr == `LM32_CSR_DEBA)) |
philpem@26 | 2159 | deba <= #1 jtag_csr_write_data[`LM32_PC_WIDTH+2-1:8]; |
philpem@0 | 2160 | `endif |
philpem@0 | 2161 | end |
philpem@0 | 2162 | end |
philpem@0 | 2163 | `endif |
philpem@0 | 2164 | |
philpem@0 | 2165 | // Cycle Counter (CC) CSR |
philpem@0 | 2166 | `ifdef CFG_CYCLE_COUNTER_ENABLED |
philpem@0 | 2167 | always @(posedge clk_i `CFG_RESET_SENSITIVITY) |
philpem@0 | 2168 | begin |
philpem@0 | 2169 | if (rst_i == `TRUE) |
philpem@26 | 2170 | cc <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@0 | 2171 | else |
philpem@26 | 2172 | cc <= #1 cc + 1'b1; |
philpem@0 | 2173 | end |
philpem@0 | 2174 | `endif |
philpem@0 | 2175 | |
philpem@0 | 2176 | `ifdef CFG_BUS_ERRORS_ENABLED |
philpem@0 | 2177 | // Watch for data bus errors |
philpem@0 | 2178 | always @(posedge clk_i `CFG_RESET_SENSITIVITY) |
philpem@0 | 2179 | begin |
philpem@0 | 2180 | if (rst_i == `TRUE) |
philpem@26 | 2181 | data_bus_error_seen <= #1 `FALSE; |
philpem@0 | 2182 | else |
philpem@0 | 2183 | begin |
philpem@0 | 2184 | // Set flag when bus error is detected |
philpem@0 | 2185 | if ((D_ERR_I == `TRUE) && (D_CYC_O == `TRUE)) |
philpem@26 | 2186 | data_bus_error_seen <= #1 `TRUE; |
philpem@0 | 2187 | // Clear flag when exception is taken |
philpem@0 | 2188 | if ((exception_m == `TRUE) && (kill_m == `FALSE)) |
philpem@26 | 2189 | data_bus_error_seen <= #1 `FALSE; |
philpem@0 | 2190 | end |
philpem@0 | 2191 | end |
philpem@0 | 2192 | `endif |
philpem@0 | 2193 | |
philpem@0 | 2194 | // Valid bits to indicate whether an instruction in a partcular pipeline stage is valid or not |
philpem@0 | 2195 | |
philpem@0 | 2196 | `ifdef CFG_ICACHE_ENABLED |
philpem@0 | 2197 | `ifdef CFG_DCACHE_ENABLED |
philpem@0 | 2198 | always @(*) |
philpem@0 | 2199 | begin |
philpem@0 | 2200 | if ( (icache_refill_request == `TRUE) |
philpem@0 | 2201 | || (dcache_refill_request == `TRUE) |
philpem@0 | 2202 | ) |
philpem@0 | 2203 | valid_a = `FALSE; |
philpem@0 | 2204 | else if ( (icache_restart_request == `TRUE) |
philpem@0 | 2205 | || (dcache_restart_request == `TRUE) |
philpem@0 | 2206 | ) |
philpem@0 | 2207 | valid_a = `TRUE; |
philpem@0 | 2208 | else |
philpem@0 | 2209 | valid_a = !icache_refilling && !dcache_refilling; |
philpem@0 | 2210 | end |
philpem@0 | 2211 | `else |
philpem@0 | 2212 | always @(*) |
philpem@0 | 2213 | begin |
philpem@0 | 2214 | if (icache_refill_request == `TRUE) |
philpem@0 | 2215 | valid_a = `FALSE; |
philpem@0 | 2216 | else if (icache_restart_request == `TRUE) |
philpem@0 | 2217 | valid_a = `TRUE; |
philpem@0 | 2218 | else |
philpem@0 | 2219 | valid_a = !icache_refilling; |
philpem@0 | 2220 | end |
philpem@0 | 2221 | `endif |
philpem@0 | 2222 | `else |
philpem@0 | 2223 | `ifdef CFG_DCACHE_ENABLED |
philpem@0 | 2224 | always @(*) |
philpem@0 | 2225 | begin |
philpem@0 | 2226 | if (dcache_refill_request == `TRUE) |
philpem@0 | 2227 | valid_a = `FALSE; |
philpem@0 | 2228 | else if (dcache_restart_request == `TRUE) |
philpem@0 | 2229 | valid_a = `TRUE; |
philpem@0 | 2230 | else |
philpem@0 | 2231 | valid_a = !dcache_refilling; |
philpem@0 | 2232 | end |
philpem@0 | 2233 | `endif |
philpem@0 | 2234 | `endif |
philpem@0 | 2235 | |
philpem@0 | 2236 | always @(posedge clk_i `CFG_RESET_SENSITIVITY) |
philpem@0 | 2237 | begin |
philpem@0 | 2238 | if (rst_i == `TRUE) |
philpem@0 | 2239 | begin |
philpem@26 | 2240 | valid_f <= #1 `FALSE; |
philpem@26 | 2241 | valid_d <= #1 `FALSE; |
philpem@26 | 2242 | valid_x <= #1 `FALSE; |
philpem@26 | 2243 | valid_m <= #1 `FALSE; |
philpem@26 | 2244 | valid_w <= #1 `FALSE; |
philpem@0 | 2245 | end |
philpem@0 | 2246 | else |
philpem@0 | 2247 | begin |
philpem@0 | 2248 | if ((kill_f == `TRUE) || (stall_a == `FALSE)) |
philpem@0 | 2249 | `ifdef LM32_CACHE_ENABLED |
philpem@26 | 2250 | valid_f <= #1 valid_a; |
philpem@0 | 2251 | `else |
philpem@26 | 2252 | valid_f <= #1 `TRUE; |
philpem@0 | 2253 | `endif |
philpem@0 | 2254 | else if (stall_f == `FALSE) |
philpem@26 | 2255 | valid_f <= #1 `FALSE; |
philpem@0 | 2256 | |
philpem@0 | 2257 | if (kill_d == `TRUE) |
philpem@26 | 2258 | valid_d <= #1 `FALSE; |
philpem@0 | 2259 | else if (stall_f == `FALSE) |
philpem@26 | 2260 | valid_d <= #1 valid_f & !kill_f; |
philpem@0 | 2261 | else if (stall_d == `FALSE) |
philpem@26 | 2262 | valid_d <= #1 `FALSE; |
philpem@0 | 2263 | |
philpem@0 | 2264 | if (stall_d == `FALSE) |
philpem@26 | 2265 | valid_x <= #1 valid_d & !kill_d; |
philpem@0 | 2266 | else if (kill_x == `TRUE) |
philpem@26 | 2267 | valid_x <= #1 `FALSE; |
philpem@0 | 2268 | else if (stall_x == `FALSE) |
philpem@26 | 2269 | valid_x <= #1 `FALSE; |
philpem@0 | 2270 | |
philpem@0 | 2271 | if (kill_m == `TRUE) |
philpem@26 | 2272 | valid_m <= #1 `FALSE; |
philpem@0 | 2273 | else if (stall_x == `FALSE) |
philpem@26 | 2274 | valid_m <= #1 valid_x & !kill_x; |
philpem@0 | 2275 | else if (stall_m == `FALSE) |
philpem@26 | 2276 | valid_m <= #1 `FALSE; |
philpem@0 | 2277 | |
philpem@0 | 2278 | if (stall_m == `FALSE) |
philpem@26 | 2279 | valid_w <= #1 valid_m & !kill_m; |
philpem@0 | 2280 | else |
philpem@26 | 2281 | valid_w <= #1 `FALSE; |
philpem@0 | 2282 | end |
philpem@0 | 2283 | end |
philpem@0 | 2284 | |
philpem@0 | 2285 | // Microcode pipeline registers |
philpem@0 | 2286 | always @(posedge clk_i `CFG_RESET_SENSITIVITY) |
philpem@0 | 2287 | begin |
philpem@0 | 2288 | if (rst_i == `TRUE) |
philpem@0 | 2289 | begin |
philpem@0 | 2290 | `ifdef CFG_USER_ENABLED |
philpem@26 | 2291 | user_opcode <= #1 {`LM32_USER_OPCODE_WIDTH{1'b0}}; |
philpem@0 | 2292 | `endif |
philpem@26 | 2293 | operand_0_x <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2294 | operand_1_x <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2295 | store_operand_x <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2296 | branch_target_x <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2297 | x_result_sel_csr_x <= #1 `FALSE; |
philpem@0 | 2298 | `ifdef LM32_MC_ARITHMETIC_ENABLED |
philpem@26 | 2299 | x_result_sel_mc_arith_x <= #1 `FALSE; |
philpem@0 | 2300 | `endif |
philpem@0 | 2301 | `ifdef LM32_NO_BARREL_SHIFT |
philpem@26 | 2302 | x_result_sel_shift_x <= #1 `FALSE; |
philpem@0 | 2303 | `endif |
philpem@0 | 2304 | `ifdef CFG_SIGN_EXTEND_ENABLED |
philpem@26 | 2305 | x_result_sel_sext_x <= #1 `FALSE; |
philpem@8 | 2306 | `endif |
philpem@26 | 2307 | x_result_sel_logic_x <= #1 `FALSE; |
philpem@0 | 2308 | `ifdef CFG_USER_ENABLED |
philpem@26 | 2309 | x_result_sel_user_x <= #1 `FALSE; |
philpem@0 | 2310 | `endif |
philpem@26 | 2311 | x_result_sel_add_x <= #1 `FALSE; |
philpem@26 | 2312 | m_result_sel_compare_x <= #1 `FALSE; |
philpem@0 | 2313 | `ifdef CFG_PL_BARREL_SHIFT_ENABLED |
philpem@26 | 2314 | m_result_sel_shift_x <= #1 `FALSE; |
philpem@0 | 2315 | `endif |
philpem@26 | 2316 | w_result_sel_load_x <= #1 `FALSE; |
philpem@0 | 2317 | `ifdef CFG_PL_MULTIPLY_ENABLED |
philpem@26 | 2318 | w_result_sel_mul_x <= #1 `FALSE; |
philpem@0 | 2319 | `endif |
philpem@26 | 2320 | x_bypass_enable_x <= #1 `FALSE; |
philpem@26 | 2321 | m_bypass_enable_x <= #1 `FALSE; |
philpem@26 | 2322 | write_enable_x <= #1 `FALSE; |
philpem@26 | 2323 | write_idx_x <= #1 {`LM32_REG_IDX_WIDTH{1'b0}}; |
philpem@26 | 2324 | csr_x <= #1 {`LM32_CSR_WIDTH{1'b0}}; |
philpem@26 | 2325 | load_x <= #1 `FALSE; |
philpem@26 | 2326 | store_x <= #1 `FALSE; |
philpem@26 | 2327 | size_x <= #1 {`LM32_SIZE_WIDTH{1'b0}}; |
philpem@26 | 2328 | sign_extend_x <= #1 `FALSE; |
philpem@26 | 2329 | adder_op_x <= #1 `FALSE; |
philpem@26 | 2330 | adder_op_x_n <= #1 `FALSE; |
philpem@26 | 2331 | logic_op_x <= #1 4'h0; |
philpem@0 | 2332 | `ifdef CFG_PL_BARREL_SHIFT_ENABLED |
philpem@26 | 2333 | direction_x <= #1 `FALSE; |
philpem@0 | 2334 | `endif |
philpem@0 | 2335 | `ifdef CFG_ROTATE_ENABLED |
philpem@26 | 2336 | rotate_x <= #1 `FALSE; |
philpem@0 | 2337 | |
philpem@0 | 2338 | `endif |
philpem@26 | 2339 | branch_x <= #1 `FALSE; |
philpem@26 | 2340 | branch_predict_x <= #1 `FALSE; |
philpem@26 | 2341 | branch_predict_taken_x <= #1 `FALSE; |
philpem@26 | 2342 | condition_x <= #1 `LM32_CONDITION_U1; |
philpem@0 | 2343 | `ifdef CFG_DEBUG_ENABLED |
philpem@26 | 2344 | break_x <= #1 `FALSE; |
philpem@0 | 2345 | `endif |
philpem@26 | 2346 | scall_x <= #1 `FALSE; |
philpem@26 | 2347 | eret_x <= #1 `FALSE; |
philpem@0 | 2348 | `ifdef CFG_DEBUG_ENABLED |
philpem@26 | 2349 | bret_x <= #1 `FALSE; |
philpem@0 | 2350 | `endif |
philpem@0 | 2351 | `ifdef CFG_BUS_ERRORS_ENABLED |
philpem@26 | 2352 | bus_error_x <= #1 `FALSE; |
philpem@26 | 2353 | data_bus_error_exception_m <= #1 `FALSE; |
philpem@0 | 2354 | `endif |
philpem@26 | 2355 | csr_write_enable_x <= #1 `FALSE; |
philpem@26 | 2356 | operand_m <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2357 | branch_target_m <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2358 | m_result_sel_compare_m <= #1 `FALSE; |
philpem@0 | 2359 | `ifdef CFG_PL_BARREL_SHIFT_ENABLED |
philpem@26 | 2360 | m_result_sel_shift_m <= #1 `FALSE; |
philpem@0 | 2361 | `endif |
philpem@26 | 2362 | w_result_sel_load_m <= #1 `FALSE; |
philpem@0 | 2363 | `ifdef CFG_PL_MULTIPLY_ENABLED |
philpem@26 | 2364 | w_result_sel_mul_m <= #1 `FALSE; |
philpem@0 | 2365 | `endif |
philpem@26 | 2366 | m_bypass_enable_m <= #1 `FALSE; |
philpem@26 | 2367 | branch_m <= #1 `FALSE; |
philpem@26 | 2368 | branch_predict_m <= #1 `FALSE; |
philpem@26 | 2369 | branch_predict_taken_m <= #1 `FALSE; |
philpem@26 | 2370 | exception_m <= #1 `FALSE; |
philpem@26 | 2371 | load_m <= #1 `FALSE; |
philpem@26 | 2372 | store_m <= #1 `FALSE; |
philpem@26 | 2373 | write_enable_m <= #1 `FALSE; |
philpem@26 | 2374 | write_idx_m <= #1 {`LM32_REG_IDX_WIDTH{1'b0}}; |
philpem@26 | 2375 | condition_met_m <= #1 `FALSE; |
philpem@0 | 2376 | `ifdef CFG_DCACHE_ENABLED |
philpem@26 | 2377 | dflush_m <= #1 `FALSE; |
philpem@0 | 2378 | `endif |
philpem@0 | 2379 | `ifdef CFG_DEBUG_ENABLED |
philpem@26 | 2380 | debug_exception_m <= #1 `FALSE; |
philpem@26 | 2381 | non_debug_exception_m <= #1 `FALSE; |
philpem@0 | 2382 | `endif |
philpem@26 | 2383 | operand_w <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2384 | w_result_sel_load_w <= #1 `FALSE; |
philpem@0 | 2385 | `ifdef CFG_PL_MULTIPLY_ENABLED |
philpem@26 | 2386 | w_result_sel_mul_w <= #1 `FALSE; |
philpem@0 | 2387 | `endif |
philpem@26 | 2388 | write_idx_w <= #1 {`LM32_REG_IDX_WIDTH{1'b0}}; |
philpem@26 | 2389 | write_enable_w <= #1 `FALSE; |
philpem@0 | 2390 | `ifdef CFG_DEBUG_ENABLED |
philpem@26 | 2391 | debug_exception_w <= #1 `FALSE; |
philpem@26 | 2392 | non_debug_exception_w <= #1 `FALSE; |
philpem@0 | 2393 | `else |
philpem@26 | 2394 | exception_w <= #1 `FALSE; |
philpem@0 | 2395 | `endif |
philpem@0 | 2396 | `ifdef CFG_BUS_ERRORS_ENABLED |
philpem@26 | 2397 | memop_pc_w <= #1 {`LM32_PC_WIDTH{1'b0}}; |
philpem@0 | 2398 | `endif |
philpem@0 | 2399 | end |
philpem@0 | 2400 | else |
philpem@0 | 2401 | begin |
philpem@0 | 2402 | // D/X stage registers |
philpem@0 | 2403 | |
philpem@0 | 2404 | if (stall_x == `FALSE) |
philpem@0 | 2405 | begin |
philpem@0 | 2406 | `ifdef CFG_USER_ENABLED |
philpem@26 | 2407 | user_opcode <= #1 user_opcode_d; |
philpem@0 | 2408 | `endif |
philpem@26 | 2409 | operand_0_x <= #1 d_result_0; |
philpem@26 | 2410 | operand_1_x <= #1 d_result_1; |
philpem@26 | 2411 | store_operand_x <= #1 bypass_data_1; |
philpem@26 | 2412 | branch_target_x <= #1 branch_reg_d == `TRUE ? bypass_data_0[`LM32_PC_RNG] : branch_target_d; |
philpem@26 | 2413 | x_result_sel_csr_x <= #1 x_result_sel_csr_d; |
philpem@0 | 2414 | `ifdef LM32_MC_ARITHMETIC_ENABLED |
philpem@26 | 2415 | x_result_sel_mc_arith_x <= #1 x_result_sel_mc_arith_d; |
philpem@0 | 2416 | `endif |
philpem@0 | 2417 | `ifdef LM32_NO_BARREL_SHIFT |
philpem@26 | 2418 | x_result_sel_shift_x <= #1 x_result_sel_shift_d; |
philpem@0 | 2419 | `endif |
philpem@0 | 2420 | `ifdef CFG_SIGN_EXTEND_ENABLED |
philpem@26 | 2421 | x_result_sel_sext_x <= #1 x_result_sel_sext_d; |
philpem@0 | 2422 | `endif |
philpem@26 | 2423 | x_result_sel_logic_x <= #1 x_result_sel_logic_d; |
philpem@0 | 2424 | `ifdef CFG_USER_ENABLED |
philpem@26 | 2425 | x_result_sel_user_x <= #1 x_result_sel_user_d; |
philpem@0 | 2426 | `endif |
philpem@26 | 2427 | x_result_sel_add_x <= #1 x_result_sel_add_d; |
philpem@26 | 2428 | m_result_sel_compare_x <= #1 m_result_sel_compare_d; |
philpem@0 | 2429 | `ifdef CFG_PL_BARREL_SHIFT_ENABLED |
philpem@26 | 2430 | m_result_sel_shift_x <= #1 m_result_sel_shift_d; |
philpem@0 | 2431 | `endif |
philpem@26 | 2432 | w_result_sel_load_x <= #1 w_result_sel_load_d; |
philpem@0 | 2433 | `ifdef CFG_PL_MULTIPLY_ENABLED |
philpem@26 | 2434 | w_result_sel_mul_x <= #1 w_result_sel_mul_d; |
philpem@0 | 2435 | `endif |
philpem@26 | 2436 | x_bypass_enable_x <= #1 x_bypass_enable_d; |
philpem@26 | 2437 | m_bypass_enable_x <= #1 m_bypass_enable_d; |
philpem@26 | 2438 | load_x <= #1 load_d; |
philpem@26 | 2439 | store_x <= #1 store_d; |
philpem@26 | 2440 | branch_x <= #1 branch_d; |
philpem@26 | 2441 | branch_predict_x <= #1 branch_predict_d; |
philpem@26 | 2442 | branch_predict_taken_x <= #1 branch_predict_taken_d; |
philpem@26 | 2443 | write_idx_x <= #1 write_idx_d; |
philpem@26 | 2444 | csr_x <= #1 csr_d; |
philpem@26 | 2445 | size_x <= #1 size_d; |
philpem@26 | 2446 | sign_extend_x <= #1 sign_extend_d; |
philpem@26 | 2447 | adder_op_x <= #1 adder_op_d; |
philpem@26 | 2448 | adder_op_x_n <= #1 ~adder_op_d; |
philpem@26 | 2449 | logic_op_x <= #1 logic_op_d; |
philpem@0 | 2450 | `ifdef CFG_PL_BARREL_SHIFT_ENABLED |
philpem@26 | 2451 | direction_x <= #1 direction_d; |
philpem@0 | 2452 | `endif |
philpem@0 | 2453 | `ifdef CFG_ROTATE_ENABLED |
philpem@26 | 2454 | rotate_x <= #1 rotate_d; |
philpem@0 | 2455 | `endif |
philpem@26 | 2456 | condition_x <= #1 condition_d; |
philpem@26 | 2457 | csr_write_enable_x <= #1 csr_write_enable_d; |
philpem@0 | 2458 | `ifdef CFG_DEBUG_ENABLED |
philpem@26 | 2459 | break_x <= #1 break_d; |
philpem@0 | 2460 | `endif |
philpem@26 | 2461 | scall_x <= #1 scall_d; |
philpem@0 | 2462 | `ifdef CFG_BUS_ERRORS_ENABLED |
philpem@26 | 2463 | bus_error_x <= #1 bus_error_d; |
philpem@0 | 2464 | `endif |
philpem@26 | 2465 | eret_x <= #1 eret_d; |
philpem@0 | 2466 | `ifdef CFG_DEBUG_ENABLED |
philpem@26 | 2467 | bret_x <= #1 bret_d; |
philpem@0 | 2468 | `endif |
philpem@26 | 2469 | write_enable_x <= #1 write_enable_d; |
philpem@0 | 2470 | end |
philpem@0 | 2471 | |
philpem@0 | 2472 | // X/M stage registers |
philpem@0 | 2473 | |
philpem@0 | 2474 | if (stall_m == `FALSE) |
philpem@0 | 2475 | begin |
philpem@26 | 2476 | operand_m <= #1 x_result; |
philpem@26 | 2477 | m_result_sel_compare_m <= #1 m_result_sel_compare_x; |
philpem@0 | 2478 | `ifdef CFG_PL_BARREL_SHIFT_ENABLED |
philpem@26 | 2479 | m_result_sel_shift_m <= #1 m_result_sel_shift_x; |
philpem@0 | 2480 | `endif |
philpem@0 | 2481 | if (exception_x == `TRUE) |
philpem@0 | 2482 | begin |
philpem@26 | 2483 | w_result_sel_load_m <= #1 `FALSE; |
philpem@0 | 2484 | `ifdef CFG_PL_MULTIPLY_ENABLED |
philpem@26 | 2485 | w_result_sel_mul_m <= #1 `FALSE; |
philpem@0 | 2486 | `endif |
philpem@0 | 2487 | end |
philpem@0 | 2488 | else |
philpem@0 | 2489 | begin |
philpem@26 | 2490 | w_result_sel_load_m <= #1 w_result_sel_load_x; |
philpem@0 | 2491 | `ifdef CFG_PL_MULTIPLY_ENABLED |
philpem@26 | 2492 | w_result_sel_mul_m <= #1 w_result_sel_mul_x; |
philpem@0 | 2493 | `endif |
philpem@0 | 2494 | end |
philpem@26 | 2495 | m_bypass_enable_m <= #1 m_bypass_enable_x; |
philpem@0 | 2496 | `ifdef CFG_PL_BARREL_SHIFT_ENABLED |
philpem@0 | 2497 | `endif |
philpem@26 | 2498 | load_m <= #1 load_x; |
philpem@26 | 2499 | store_m <= #1 store_x; |
philpem@0 | 2500 | `ifdef CFG_FAST_UNCONDITIONAL_BRANCH |
philpem@26 | 2501 | branch_m <= #1 branch_x && !branch_taken_x; |
philpem@0 | 2502 | `else |
philpem@26 | 2503 | branch_m <= #1 branch_x; |
philpem@26 | 2504 | branch_predict_m <= #1 branch_predict_x; |
philpem@26 | 2505 | branch_predict_taken_m <= #1 branch_predict_taken_x; |
philpem@0 | 2506 | `endif |
philpem@0 | 2507 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 2508 | // Data bus errors are generated by the wishbone and are |
philpem@0 | 2509 | // made known to the processor only in next cycle (as a |
philpem@0 | 2510 | // non-debug exception). A break instruction can be seen |
philpem@0 | 2511 | // in same cycle (causing a debug exception). Handle non |
philpem@0 | 2512 | // -debug exception first! |
philpem@0 | 2513 | if (non_debug_exception_x == `TRUE) |
philpem@26 | 2514 | write_idx_m <= #1 `LM32_EA_REG; |
philpem@0 | 2515 | else if (debug_exception_x == `TRUE) |
philpem@26 | 2516 | write_idx_m <= #1 `LM32_BA_REG; |
philpem@0 | 2517 | else |
philpem@26 | 2518 | write_idx_m <= #1 write_idx_x; |
philpem@0 | 2519 | `else |
philpem@0 | 2520 | if (exception_x == `TRUE) |
philpem@26 | 2521 | write_idx_m <= #1 `LM32_EA_REG; |
philpem@0 | 2522 | else |
philpem@26 | 2523 | write_idx_m <= #1 write_idx_x; |
philpem@0 | 2524 | `endif |
philpem@26 | 2525 | condition_met_m <= #1 condition_met_x; |
philpem@0 | 2526 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 2527 | if (exception_x == `TRUE) |
philpem@0 | 2528 | if ((dc_re == `TRUE) |
philpem@26 | 2529 | `ifdef CFG_ALTERNATE_EBA |
philpem@26 | 2530 | || (at_debug == `TRUE) |
philpem@26 | 2531 | `endif |
philpem@0 | 2532 | || ((debug_exception_x == `TRUE) |
philpem@0 | 2533 | && (non_debug_exception_x == `FALSE))) |
philpem@26 | 2534 | branch_target_m <= #1 {deba, eid_x, {3{1'b0}}}; |
philpem@0 | 2535 | else |
philpem@26 | 2536 | branch_target_m <= #1 {eba, eid_x, {3{1'b0}}}; |
philpem@0 | 2537 | else |
philpem@26 | 2538 | branch_target_m <= #1 branch_target_x; |
philpem@0 | 2539 | `else |
philpem@26 | 2540 | branch_target_m <= #1 exception_x == `TRUE ? {eba, eid_x, {3{1'b0}}} : branch_target_x; |
philpem@0 | 2541 | `endif |
philpem@0 | 2542 | `ifdef CFG_TRACE_ENABLED |
philpem@26 | 2543 | eid_m <= #1 eid_x; |
philpem@0 | 2544 | `endif |
philpem@0 | 2545 | `ifdef CFG_DCACHE_ENABLED |
philpem@26 | 2546 | dflush_m <= #1 dflush_x; |
philpem@0 | 2547 | `endif |
philpem@26 | 2548 | eret_m <= #1 eret_q_x; |
philpem@0 | 2549 | `ifdef CFG_DEBUG_ENABLED |
philpem@26 | 2550 | bret_m <= #1 bret_q_x; |
philpem@0 | 2551 | `endif |
philpem@26 | 2552 | write_enable_m <= #1 exception_x == `TRUE ? `TRUE : write_enable_x; |
philpem@0 | 2553 | `ifdef CFG_DEBUG_ENABLED |
philpem@26 | 2554 | debug_exception_m <= #1 debug_exception_x; |
philpem@26 | 2555 | non_debug_exception_m <= #1 non_debug_exception_x; |
philpem@0 | 2556 | `endif |
philpem@0 | 2557 | end |
philpem@0 | 2558 | |
philpem@0 | 2559 | // State changing regs |
philpem@0 | 2560 | if (stall_m == `FALSE) |
philpem@0 | 2561 | begin |
philpem@0 | 2562 | if ((exception_x == `TRUE) && (q_x == `TRUE) && (stall_x == `FALSE)) |
philpem@26 | 2563 | exception_m <= #1 `TRUE; |
philpem@0 | 2564 | else |
philpem@26 | 2565 | exception_m <= #1 `FALSE; |
philpem@0 | 2566 | `ifdef CFG_BUS_ERRORS_ENABLED |
philpem@26 | 2567 | data_bus_error_exception_m <= #1 (data_bus_error_exception == `TRUE) |
philpem@0 | 2568 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 2569 | && (reset_exception == `FALSE) |
philpem@0 | 2570 | `endif |
philpem@0 | 2571 | ; |
philpem@0 | 2572 | `endif |
philpem@0 | 2573 | end |
philpem@0 | 2574 | |
philpem@0 | 2575 | // M/W stage registers |
philpem@0 | 2576 | `ifdef CFG_BUS_ERRORS_ENABLED |
philpem@26 | 2577 | operand_w <= #1 exception_m == `TRUE ? (data_bus_error_exception_m ? {memop_pc_w, 2'b00} : {pc_m, 2'b00}) : m_result; |
philpem@0 | 2578 | `else |
philpem@26 | 2579 | operand_w <= #1 exception_m == `TRUE ? {pc_m, 2'b00} : m_result; |
philpem@0 | 2580 | `endif |
philpem@26 | 2581 | w_result_sel_load_w <= #1 w_result_sel_load_m; |
philpem@0 | 2582 | `ifdef CFG_PL_MULTIPLY_ENABLED |
philpem@26 | 2583 | w_result_sel_mul_w <= #1 w_result_sel_mul_m; |
philpem@0 | 2584 | `endif |
philpem@26 | 2585 | write_idx_w <= #1 write_idx_m; |
philpem@0 | 2586 | `ifdef CFG_TRACE_ENABLED |
philpem@26 | 2587 | eid_w <= #1 eid_m; |
philpem@26 | 2588 | eret_w <= #1 eret_m; |
philpem@0 | 2589 | `ifdef CFG_DEBUG_ENABLED |
philpem@26 | 2590 | bret_w <= #1 bret_m; |
philpem@0 | 2591 | `endif |
philpem@0 | 2592 | `endif |
philpem@26 | 2593 | write_enable_w <= #1 write_enable_m; |
philpem@0 | 2594 | `ifdef CFG_DEBUG_ENABLED |
philpem@26 | 2595 | debug_exception_w <= #1 debug_exception_m; |
philpem@26 | 2596 | non_debug_exception_w <= #1 non_debug_exception_m; |
philpem@0 | 2597 | `else |
philpem@26 | 2598 | exception_w <= #1 exception_m; |
philpem@0 | 2599 | `endif |
philpem@0 | 2600 | `ifdef CFG_BUS_ERRORS_ENABLED |
philpem@0 | 2601 | if ( (stall_m == `FALSE) |
philpem@26 | 2602 | && (data_bus_error_exception == `FALSE) |
philpem@0 | 2603 | && ( (load_q_m == `TRUE) |
philpem@0 | 2604 | || (store_q_m == `TRUE) |
philpem@0 | 2605 | ) |
philpem@0 | 2606 | ) |
philpem@26 | 2607 | memop_pc_w <= #1 pc_m; |
philpem@0 | 2608 | `endif |
philpem@0 | 2609 | end |
philpem@0 | 2610 | end |
philpem@0 | 2611 | |
philpem@0 | 2612 | `ifdef CFG_EBR_POSEDGE_REGISTER_FILE |
philpem@0 | 2613 | // Buffer data read from register file, in case a stall occurs, and watch for |
philpem@0 | 2614 | // any writes to the modified registers |
philpem@0 | 2615 | always @(posedge clk_i `CFG_RESET_SENSITIVITY) |
philpem@0 | 2616 | begin |
philpem@0 | 2617 | if (rst_i == `TRUE) |
philpem@0 | 2618 | begin |
philpem@26 | 2619 | use_buf <= #1 `FALSE; |
philpem@26 | 2620 | reg_data_buf_0 <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2621 | reg_data_buf_1 <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@0 | 2622 | end |
philpem@0 | 2623 | else |
philpem@0 | 2624 | begin |
philpem@0 | 2625 | if (stall_d == `FALSE) |
philpem@26 | 2626 | use_buf <= #1 `FALSE; |
philpem@0 | 2627 | else if (use_buf == `FALSE) |
philpem@0 | 2628 | begin |
philpem@26 | 2629 | reg_data_buf_0 <= #1 reg_data_live_0; |
philpem@26 | 2630 | reg_data_buf_1 <= #1 reg_data_live_1; |
philpem@26 | 2631 | use_buf <= #1 `TRUE; |
philpem@0 | 2632 | end |
philpem@0 | 2633 | if (reg_write_enable_q_w == `TRUE) |
philpem@0 | 2634 | begin |
philpem@0 | 2635 | if (write_idx_w == read_idx_0_d) |
philpem@26 | 2636 | reg_data_buf_0 <= #1 w_result; |
philpem@0 | 2637 | if (write_idx_w == read_idx_1_d) |
philpem@26 | 2638 | reg_data_buf_1 <= #1 w_result; |
philpem@0 | 2639 | end |
philpem@0 | 2640 | end |
philpem@0 | 2641 | end |
philpem@0 | 2642 | `endif |
philpem@0 | 2643 | |
philpem@0 | 2644 | `ifdef LM32_EBR_REGISTER_FILE |
philpem@0 | 2645 | `else |
philpem@0 | 2646 | // Register file write port |
philpem@0 | 2647 | always @(posedge clk_i `CFG_RESET_SENSITIVITY) |
philpem@0 | 2648 | begin |
philpem@0 | 2649 | if (rst_i == `TRUE) begin |
philpem@26 | 2650 | registers[0] <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2651 | registers[1] <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2652 | registers[2] <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2653 | registers[3] <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2654 | registers[4] <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2655 | registers[5] <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2656 | registers[6] <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2657 | registers[7] <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2658 | registers[8] <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2659 | registers[9] <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2660 | registers[10] <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2661 | registers[11] <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2662 | registers[12] <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2663 | registers[13] <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2664 | registers[14] <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2665 | registers[15] <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2666 | registers[16] <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2667 | registers[17] <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2668 | registers[18] <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2669 | registers[19] <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2670 | registers[20] <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2671 | registers[21] <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2672 | registers[22] <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2673 | registers[23] <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2674 | registers[24] <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2675 | registers[25] <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2676 | registers[26] <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2677 | registers[27] <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2678 | registers[28] <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2679 | registers[29] <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2680 | registers[30] <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@26 | 2681 | registers[31] <= #1 {`LM32_WORD_WIDTH{1'b0}}; |
philpem@0 | 2682 | end |
philpem@0 | 2683 | else begin |
philpem@0 | 2684 | if (reg_write_enable_q_w == `TRUE) |
philpem@26 | 2685 | registers[write_idx_w] <= #1 w_result; |
philpem@0 | 2686 | end |
philpem@0 | 2687 | end |
philpem@0 | 2688 | `endif |
philpem@0 | 2689 | |
philpem@0 | 2690 | `ifdef CFG_TRACE_ENABLED |
philpem@0 | 2691 | // PC tracing logic |
philpem@0 | 2692 | always @(posedge clk_i `CFG_RESET_SENSITIVITY) |
philpem@0 | 2693 | begin |
philpem@0 | 2694 | if (rst_i == `TRUE) |
philpem@0 | 2695 | begin |
philpem@26 | 2696 | trace_pc_valid <= #1 `FALSE; |
philpem@26 | 2697 | trace_pc <= #1 {`LM32_PC_WIDTH{1'b0}}; |
philpem@26 | 2698 | trace_exception <= #1 `FALSE; |
philpem@26 | 2699 | trace_eid <= #1 `LM32_EID_RESET; |
philpem@26 | 2700 | trace_eret <= #1 `FALSE; |
philpem@0 | 2701 | `ifdef CFG_DEBUG_ENABLED |
philpem@26 | 2702 | trace_bret <= #1 `FALSE; |
philpem@0 | 2703 | `endif |
philpem@26 | 2704 | pc_c <= #1 `CFG_EBA_RESET/4; |
philpem@0 | 2705 | end |
philpem@0 | 2706 | else |
philpem@0 | 2707 | begin |
philpem@26 | 2708 | trace_pc_valid <= #1 `FALSE; |
philpem@0 | 2709 | // Has an exception occured |
philpem@0 | 2710 | `ifdef CFG_DEBUG_ENABLED |
philpem@0 | 2711 | if ((debug_exception_q_w == `TRUE) || (non_debug_exception_q_w == `TRUE)) |
philpem@0 | 2712 | `else |
philpem@0 | 2713 | if (exception_q_w == `TRUE) |
philpem@0 | 2714 | `endif |
philpem@0 | 2715 | begin |
philpem@26 | 2716 | trace_exception <= #1 `TRUE; |
philpem@26 | 2717 | trace_pc_valid <= #1 `TRUE; |
philpem@26 | 2718 | trace_pc <= #1 pc_w; |
philpem@26 | 2719 | trace_eid <= #1 eid_w; |
philpem@0 | 2720 | end |
philpem@0 | 2721 | else |
philpem@26 | 2722 | trace_exception <= #1 `FALSE; |
philpem@0 | 2723 | |
philpem@0 | 2724 | if ((valid_w == `TRUE) && (!kill_w)) |
philpem@0 | 2725 | begin |
philpem@0 | 2726 | // An instruction is commiting. Determine if it is non-sequential |
philpem@0 | 2727 | if (pc_c + 1'b1 != pc_w) |
philpem@0 | 2728 | begin |
philpem@0 | 2729 | // Non-sequential instruction |
philpem@26 | 2730 | trace_pc_valid <= #1 `TRUE; |
philpem@26 | 2731 | trace_pc <= #1 pc_w; |
philpem@0 | 2732 | end |
philpem@0 | 2733 | // Record PC so we can determine if next instruction is sequential or not |
philpem@26 | 2734 | pc_c <= #1 pc_w; |
philpem@0 | 2735 | // Indicate if it was an eret/bret instruction |
philpem@26 | 2736 | trace_eret <= #1 eret_w; |
philpem@0 | 2737 | `ifdef CFG_DEBUG_ENABLED |
philpem@26 | 2738 | trace_bret <= #1 bret_w; |
philpem@0 | 2739 | `endif |
philpem@0 | 2740 | end |
philpem@0 | 2741 | else |
philpem@0 | 2742 | begin |
philpem@26 | 2743 | trace_eret <= #1 `FALSE; |
philpem@0 | 2744 | `ifdef CFG_DEBUG_ENABLED |
philpem@26 | 2745 | trace_bret <= #1 `FALSE; |
philpem@0 | 2746 | `endif |
philpem@0 | 2747 | end |
philpem@0 | 2748 | end |
philpem@0 | 2749 | end |
philpem@0 | 2750 | `endif |
philpem@0 | 2751 | |
philpem@0 | 2752 | ///////////////////////////////////////////////////// |
philpem@0 | 2753 | // Behavioural Logic |
philpem@0 | 2754 | ///////////////////////////////////////////////////// |
philpem@0 | 2755 | |
philpem@0 | 2756 | // synthesis translate_off |
philpem@0 | 2757 | |
philpem@0 | 2758 | // Reset register 0. Only needed for simulation. |
philpem@0 | 2759 | initial |
philpem@0 | 2760 | begin |
philpem@0 | 2761 | `ifdef LM32_EBR_REGISTER_FILE |
philpem@0 | 2762 | reg_0.mem[0] = {`LM32_WORD_WIDTH{1'b0}}; |
philpem@0 | 2763 | reg_1.mem[0] = {`LM32_WORD_WIDTH{1'b0}}; |
philpem@0 | 2764 | `else |
philpem@0 | 2765 | registers[0] = {`LM32_WORD_WIDTH{1'b0}}; |
philpem@0 | 2766 | `endif |
philpem@0 | 2767 | end |
philpem@0 | 2768 | |
philpem@0 | 2769 | // synthesis translate_on |
philpem@0 | 2770 | |
philpem@0 | 2771 | endmodule |