lm32_cpu.v

Sat, 06 Aug 2011 01:26:56 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Sat, 06 Aug 2011 01:26:56 +0100
changeset 27
d6c693415d59
parent 26
73de224304c1
permissions
-rwxr-xr-x

remove synthesis delay entities to ease merge

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@27 1301 regfile_raw_0 <= 1'b0;
philpem@27 1302 regfile_raw_1 <= 1'b0;
philpem@27 1303 w_result_d <= 32'b0;
philpem@0 1304 end
philpem@0 1305 else
philpem@0 1306 begin
philpem@27 1307 regfile_raw_0 <= regfile_raw_0_nxt;
philpem@27 1308 regfile_raw_1 <= regfile_raw_1_nxt;
philpem@27 1309 w_result_d <= 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@27 2135 eba <= 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@27 2139 eba <= 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@27 2142 eba <= 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@27 2152 deba <= 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@27 2156 deba <= 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@27 2159 deba <= 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@27 2170 cc <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2171 else
philpem@27 2172 cc <= 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@27 2181 data_bus_error_seen <= `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@27 2186 data_bus_error_seen <= `TRUE;
philpem@0 2187 // Clear flag when exception is taken
philpem@0 2188 if ((exception_m == `TRUE) && (kill_m == `FALSE))
philpem@27 2189 data_bus_error_seen <= `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@27 2240 valid_f <= `FALSE;
philpem@27 2241 valid_d <= `FALSE;
philpem@27 2242 valid_x <= `FALSE;
philpem@27 2243 valid_m <= `FALSE;
philpem@27 2244 valid_w <= `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@27 2250 valid_f <= valid_a;
philpem@0 2251 `else
philpem@27 2252 valid_f <= `TRUE;
philpem@0 2253 `endif
philpem@0 2254 else if (stall_f == `FALSE)
philpem@27 2255 valid_f <= `FALSE;
philpem@0 2256
philpem@0 2257 if (kill_d == `TRUE)
philpem@27 2258 valid_d <= `FALSE;
philpem@0 2259 else if (stall_f == `FALSE)
philpem@27 2260 valid_d <= valid_f & !kill_f;
philpem@0 2261 else if (stall_d == `FALSE)
philpem@27 2262 valid_d <= `FALSE;
philpem@0 2263
philpem@0 2264 if (stall_d == `FALSE)
philpem@27 2265 valid_x <= valid_d & !kill_d;
philpem@0 2266 else if (kill_x == `TRUE)
philpem@27 2267 valid_x <= `FALSE;
philpem@0 2268 else if (stall_x == `FALSE)
philpem@27 2269 valid_x <= `FALSE;
philpem@0 2270
philpem@0 2271 if (kill_m == `TRUE)
philpem@27 2272 valid_m <= `FALSE;
philpem@0 2273 else if (stall_x == `FALSE)
philpem@27 2274 valid_m <= valid_x & !kill_x;
philpem@0 2275 else if (stall_m == `FALSE)
philpem@27 2276 valid_m <= `FALSE;
philpem@0 2277
philpem@0 2278 if (stall_m == `FALSE)
philpem@27 2279 valid_w <= valid_m & !kill_m;
philpem@0 2280 else
philpem@27 2281 valid_w <= `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@27 2291 user_opcode <= {`LM32_USER_OPCODE_WIDTH{1'b0}};
philpem@0 2292 `endif
philpem@27 2293 operand_0_x <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2294 operand_1_x <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2295 store_operand_x <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2296 branch_target_x <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2297 x_result_sel_csr_x <= `FALSE;
philpem@0 2298 `ifdef LM32_MC_ARITHMETIC_ENABLED
philpem@27 2299 x_result_sel_mc_arith_x <= `FALSE;
philpem@0 2300 `endif
philpem@0 2301 `ifdef LM32_NO_BARREL_SHIFT
philpem@27 2302 x_result_sel_shift_x <= `FALSE;
philpem@0 2303 `endif
philpem@0 2304 `ifdef CFG_SIGN_EXTEND_ENABLED
philpem@27 2305 x_result_sel_sext_x <= `FALSE;
philpem@8 2306 `endif
philpem@27 2307 x_result_sel_logic_x <= `FALSE;
philpem@0 2308 `ifdef CFG_USER_ENABLED
philpem@27 2309 x_result_sel_user_x <= `FALSE;
philpem@0 2310 `endif
philpem@27 2311 x_result_sel_add_x <= `FALSE;
philpem@27 2312 m_result_sel_compare_x <= `FALSE;
philpem@0 2313 `ifdef CFG_PL_BARREL_SHIFT_ENABLED
philpem@27 2314 m_result_sel_shift_x <= `FALSE;
philpem@0 2315 `endif
philpem@27 2316 w_result_sel_load_x <= `FALSE;
philpem@0 2317 `ifdef CFG_PL_MULTIPLY_ENABLED
philpem@27 2318 w_result_sel_mul_x <= `FALSE;
philpem@0 2319 `endif
philpem@27 2320 x_bypass_enable_x <= `FALSE;
philpem@27 2321 m_bypass_enable_x <= `FALSE;
philpem@27 2322 write_enable_x <= `FALSE;
philpem@27 2323 write_idx_x <= {`LM32_REG_IDX_WIDTH{1'b0}};
philpem@27 2324 csr_x <= {`LM32_CSR_WIDTH{1'b0}};
philpem@27 2325 load_x <= `FALSE;
philpem@27 2326 store_x <= `FALSE;
philpem@27 2327 size_x <= {`LM32_SIZE_WIDTH{1'b0}};
philpem@27 2328 sign_extend_x <= `FALSE;
philpem@27 2329 adder_op_x <= `FALSE;
philpem@27 2330 adder_op_x_n <= `FALSE;
philpem@27 2331 logic_op_x <= 4'h0;
philpem@0 2332 `ifdef CFG_PL_BARREL_SHIFT_ENABLED
philpem@27 2333 direction_x <= `FALSE;
philpem@0 2334 `endif
philpem@0 2335 `ifdef CFG_ROTATE_ENABLED
philpem@27 2336 rotate_x <= `FALSE;
philpem@0 2337
philpem@0 2338 `endif
philpem@27 2339 branch_x <= `FALSE;
philpem@27 2340 branch_predict_x <= `FALSE;
philpem@27 2341 branch_predict_taken_x <= `FALSE;
philpem@27 2342 condition_x <= `LM32_CONDITION_U1;
philpem@0 2343 `ifdef CFG_DEBUG_ENABLED
philpem@27 2344 break_x <= `FALSE;
philpem@0 2345 `endif
philpem@27 2346 scall_x <= `FALSE;
philpem@27 2347 eret_x <= `FALSE;
philpem@0 2348 `ifdef CFG_DEBUG_ENABLED
philpem@27 2349 bret_x <= `FALSE;
philpem@0 2350 `endif
philpem@0 2351 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@27 2352 bus_error_x <= `FALSE;
philpem@27 2353 data_bus_error_exception_m <= `FALSE;
philpem@0 2354 `endif
philpem@27 2355 csr_write_enable_x <= `FALSE;
philpem@27 2356 operand_m <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2357 branch_target_m <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2358 m_result_sel_compare_m <= `FALSE;
philpem@0 2359 `ifdef CFG_PL_BARREL_SHIFT_ENABLED
philpem@27 2360 m_result_sel_shift_m <= `FALSE;
philpem@0 2361 `endif
philpem@27 2362 w_result_sel_load_m <= `FALSE;
philpem@0 2363 `ifdef CFG_PL_MULTIPLY_ENABLED
philpem@27 2364 w_result_sel_mul_m <= `FALSE;
philpem@0 2365 `endif
philpem@27 2366 m_bypass_enable_m <= `FALSE;
philpem@27 2367 branch_m <= `FALSE;
philpem@27 2368 branch_predict_m <= `FALSE;
philpem@27 2369 branch_predict_taken_m <= `FALSE;
philpem@27 2370 exception_m <= `FALSE;
philpem@27 2371 load_m <= `FALSE;
philpem@27 2372 store_m <= `FALSE;
philpem@27 2373 write_enable_m <= `FALSE;
philpem@27 2374 write_idx_m <= {`LM32_REG_IDX_WIDTH{1'b0}};
philpem@27 2375 condition_met_m <= `FALSE;
philpem@0 2376 `ifdef CFG_DCACHE_ENABLED
philpem@27 2377 dflush_m <= `FALSE;
philpem@0 2378 `endif
philpem@0 2379 `ifdef CFG_DEBUG_ENABLED
philpem@27 2380 debug_exception_m <= `FALSE;
philpem@27 2381 non_debug_exception_m <= `FALSE;
philpem@0 2382 `endif
philpem@27 2383 operand_w <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2384 w_result_sel_load_w <= `FALSE;
philpem@0 2385 `ifdef CFG_PL_MULTIPLY_ENABLED
philpem@27 2386 w_result_sel_mul_w <= `FALSE;
philpem@0 2387 `endif
philpem@27 2388 write_idx_w <= {`LM32_REG_IDX_WIDTH{1'b0}};
philpem@27 2389 write_enable_w <= `FALSE;
philpem@0 2390 `ifdef CFG_DEBUG_ENABLED
philpem@27 2391 debug_exception_w <= `FALSE;
philpem@27 2392 non_debug_exception_w <= `FALSE;
philpem@0 2393 `else
philpem@27 2394 exception_w <= `FALSE;
philpem@0 2395 `endif
philpem@0 2396 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@27 2397 memop_pc_w <= {`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@27 2407 user_opcode <= user_opcode_d;
philpem@0 2408 `endif
philpem@27 2409 operand_0_x <= d_result_0;
philpem@27 2410 operand_1_x <= d_result_1;
philpem@27 2411 store_operand_x <= bypass_data_1;
philpem@27 2412 branch_target_x <= branch_reg_d == `TRUE ? bypass_data_0[`LM32_PC_RNG] : branch_target_d;
philpem@27 2413 x_result_sel_csr_x <= x_result_sel_csr_d;
philpem@0 2414 `ifdef LM32_MC_ARITHMETIC_ENABLED
philpem@27 2415 x_result_sel_mc_arith_x <= x_result_sel_mc_arith_d;
philpem@0 2416 `endif
philpem@0 2417 `ifdef LM32_NO_BARREL_SHIFT
philpem@27 2418 x_result_sel_shift_x <= x_result_sel_shift_d;
philpem@0 2419 `endif
philpem@0 2420 `ifdef CFG_SIGN_EXTEND_ENABLED
philpem@27 2421 x_result_sel_sext_x <= x_result_sel_sext_d;
philpem@0 2422 `endif
philpem@27 2423 x_result_sel_logic_x <= x_result_sel_logic_d;
philpem@0 2424 `ifdef CFG_USER_ENABLED
philpem@27 2425 x_result_sel_user_x <= x_result_sel_user_d;
philpem@0 2426 `endif
philpem@27 2427 x_result_sel_add_x <= x_result_sel_add_d;
philpem@27 2428 m_result_sel_compare_x <= m_result_sel_compare_d;
philpem@0 2429 `ifdef CFG_PL_BARREL_SHIFT_ENABLED
philpem@27 2430 m_result_sel_shift_x <= m_result_sel_shift_d;
philpem@0 2431 `endif
philpem@27 2432 w_result_sel_load_x <= w_result_sel_load_d;
philpem@0 2433 `ifdef CFG_PL_MULTIPLY_ENABLED
philpem@27 2434 w_result_sel_mul_x <= w_result_sel_mul_d;
philpem@0 2435 `endif
philpem@27 2436 x_bypass_enable_x <= x_bypass_enable_d;
philpem@27 2437 m_bypass_enable_x <= m_bypass_enable_d;
philpem@27 2438 load_x <= load_d;
philpem@27 2439 store_x <= store_d;
philpem@27 2440 branch_x <= branch_d;
philpem@27 2441 branch_predict_x <= branch_predict_d;
philpem@27 2442 branch_predict_taken_x <= branch_predict_taken_d;
philpem@27 2443 write_idx_x <= write_idx_d;
philpem@27 2444 csr_x <= csr_d;
philpem@27 2445 size_x <= size_d;
philpem@27 2446 sign_extend_x <= sign_extend_d;
philpem@27 2447 adder_op_x <= adder_op_d;
philpem@27 2448 adder_op_x_n <= ~adder_op_d;
philpem@27 2449 logic_op_x <= logic_op_d;
philpem@0 2450 `ifdef CFG_PL_BARREL_SHIFT_ENABLED
philpem@27 2451 direction_x <= direction_d;
philpem@0 2452 `endif
philpem@0 2453 `ifdef CFG_ROTATE_ENABLED
philpem@27 2454 rotate_x <= rotate_d;
philpem@0 2455 `endif
philpem@27 2456 condition_x <= condition_d;
philpem@27 2457 csr_write_enable_x <= csr_write_enable_d;
philpem@0 2458 `ifdef CFG_DEBUG_ENABLED
philpem@27 2459 break_x <= break_d;
philpem@0 2460 `endif
philpem@27 2461 scall_x <= scall_d;
philpem@0 2462 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@27 2463 bus_error_x <= bus_error_d;
philpem@0 2464 `endif
philpem@27 2465 eret_x <= eret_d;
philpem@0 2466 `ifdef CFG_DEBUG_ENABLED
philpem@27 2467 bret_x <= bret_d;
philpem@0 2468 `endif
philpem@27 2469 write_enable_x <= 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@27 2476 operand_m <= x_result;
philpem@27 2477 m_result_sel_compare_m <= m_result_sel_compare_x;
philpem@0 2478 `ifdef CFG_PL_BARREL_SHIFT_ENABLED
philpem@27 2479 m_result_sel_shift_m <= m_result_sel_shift_x;
philpem@0 2480 `endif
philpem@0 2481 if (exception_x == `TRUE)
philpem@0 2482 begin
philpem@27 2483 w_result_sel_load_m <= `FALSE;
philpem@0 2484 `ifdef CFG_PL_MULTIPLY_ENABLED
philpem@27 2485 w_result_sel_mul_m <= `FALSE;
philpem@0 2486 `endif
philpem@0 2487 end
philpem@0 2488 else
philpem@0 2489 begin
philpem@27 2490 w_result_sel_load_m <= w_result_sel_load_x;
philpem@0 2491 `ifdef CFG_PL_MULTIPLY_ENABLED
philpem@27 2492 w_result_sel_mul_m <= w_result_sel_mul_x;
philpem@0 2493 `endif
philpem@0 2494 end
philpem@27 2495 m_bypass_enable_m <= m_bypass_enable_x;
philpem@0 2496 `ifdef CFG_PL_BARREL_SHIFT_ENABLED
philpem@0 2497 `endif
philpem@27 2498 load_m <= load_x;
philpem@27 2499 store_m <= store_x;
philpem@0 2500 `ifdef CFG_FAST_UNCONDITIONAL_BRANCH
philpem@27 2501 branch_m <= branch_x && !branch_taken_x;
philpem@0 2502 `else
philpem@27 2503 branch_m <= branch_x;
philpem@27 2504 branch_predict_m <= branch_predict_x;
philpem@27 2505 branch_predict_taken_m <= 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@27 2514 write_idx_m <= `LM32_EA_REG;
philpem@0 2515 else if (debug_exception_x == `TRUE)
philpem@27 2516 write_idx_m <= `LM32_BA_REG;
philpem@0 2517 else
philpem@27 2518 write_idx_m <= write_idx_x;
philpem@0 2519 `else
philpem@0 2520 if (exception_x == `TRUE)
philpem@27 2521 write_idx_m <= `LM32_EA_REG;
philpem@0 2522 else
philpem@27 2523 write_idx_m <= write_idx_x;
philpem@0 2524 `endif
philpem@27 2525 condition_met_m <= 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@27 2534 branch_target_m <= {deba, eid_x, {3{1'b0}}};
philpem@0 2535 else
philpem@27 2536 branch_target_m <= {eba, eid_x, {3{1'b0}}};
philpem@0 2537 else
philpem@27 2538 branch_target_m <= branch_target_x;
philpem@0 2539 `else
philpem@27 2540 branch_target_m <= exception_x == `TRUE ? {eba, eid_x, {3{1'b0}}} : branch_target_x;
philpem@0 2541 `endif
philpem@0 2542 `ifdef CFG_TRACE_ENABLED
philpem@27 2543 eid_m <= eid_x;
philpem@0 2544 `endif
philpem@0 2545 `ifdef CFG_DCACHE_ENABLED
philpem@27 2546 dflush_m <= dflush_x;
philpem@0 2547 `endif
philpem@27 2548 eret_m <= eret_q_x;
philpem@0 2549 `ifdef CFG_DEBUG_ENABLED
philpem@27 2550 bret_m <= bret_q_x;
philpem@0 2551 `endif
philpem@27 2552 write_enable_m <= exception_x == `TRUE ? `TRUE : write_enable_x;
philpem@0 2553 `ifdef CFG_DEBUG_ENABLED
philpem@27 2554 debug_exception_m <= debug_exception_x;
philpem@27 2555 non_debug_exception_m <= 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@27 2563 exception_m <= `TRUE;
philpem@0 2564 else
philpem@27 2565 exception_m <= `FALSE;
philpem@0 2566 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@27 2567 data_bus_error_exception_m <= (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@27 2577 operand_w <= exception_m == `TRUE ? (data_bus_error_exception_m ? {memop_pc_w, 2'b00} : {pc_m, 2'b00}) : m_result;
philpem@0 2578 `else
philpem@27 2579 operand_w <= exception_m == `TRUE ? {pc_m, 2'b00} : m_result;
philpem@0 2580 `endif
philpem@27 2581 w_result_sel_load_w <= w_result_sel_load_m;
philpem@0 2582 `ifdef CFG_PL_MULTIPLY_ENABLED
philpem@27 2583 w_result_sel_mul_w <= w_result_sel_mul_m;
philpem@0 2584 `endif
philpem@27 2585 write_idx_w <= write_idx_m;
philpem@0 2586 `ifdef CFG_TRACE_ENABLED
philpem@27 2587 eid_w <= eid_m;
philpem@27 2588 eret_w <= eret_m;
philpem@0 2589 `ifdef CFG_DEBUG_ENABLED
philpem@27 2590 bret_w <= bret_m;
philpem@0 2591 `endif
philpem@0 2592 `endif
philpem@27 2593 write_enable_w <= write_enable_m;
philpem@0 2594 `ifdef CFG_DEBUG_ENABLED
philpem@27 2595 debug_exception_w <= debug_exception_m;
philpem@27 2596 non_debug_exception_w <= non_debug_exception_m;
philpem@0 2597 `else
philpem@27 2598 exception_w <= 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@27 2607 memop_pc_w <= 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@27 2619 use_buf <= `FALSE;
philpem@27 2620 reg_data_buf_0 <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2621 reg_data_buf_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@27 2626 use_buf <= `FALSE;
philpem@0 2627 else if (use_buf == `FALSE)
philpem@0 2628 begin
philpem@27 2629 reg_data_buf_0 <= reg_data_live_0;
philpem@27 2630 reg_data_buf_1 <= reg_data_live_1;
philpem@27 2631 use_buf <= `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@27 2636 reg_data_buf_0 <= w_result;
philpem@0 2637 if (write_idx_w == read_idx_1_d)
philpem@27 2638 reg_data_buf_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@27 2650 registers[0] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2651 registers[1] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2652 registers[2] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2653 registers[3] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2654 registers[4] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2655 registers[5] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2656 registers[6] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2657 registers[7] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2658 registers[8] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2659 registers[9] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2660 registers[10] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2661 registers[11] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2662 registers[12] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2663 registers[13] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2664 registers[14] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2665 registers[15] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2666 registers[16] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2667 registers[17] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2668 registers[18] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2669 registers[19] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2670 registers[20] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2671 registers[21] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2672 registers[22] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2673 registers[23] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2674 registers[24] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2675 registers[25] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2676 registers[26] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2677 registers[27] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2678 registers[28] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2679 registers[29] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2680 registers[30] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@27 2681 registers[31] <= {`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@27 2685 registers[write_idx_w] <= 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@27 2696 trace_pc_valid <= `FALSE;
philpem@27 2697 trace_pc <= {`LM32_PC_WIDTH{1'b0}};
philpem@27 2698 trace_exception <= `FALSE;
philpem@27 2699 trace_eid <= `LM32_EID_RESET;
philpem@27 2700 trace_eret <= `FALSE;
philpem@0 2701 `ifdef CFG_DEBUG_ENABLED
philpem@27 2702 trace_bret <= `FALSE;
philpem@0 2703 `endif
philpem@27 2704 pc_c <= `CFG_EBA_RESET/4;
philpem@0 2705 end
philpem@0 2706 else
philpem@0 2707 begin
philpem@27 2708 trace_pc_valid <= `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@27 2716 trace_exception <= `TRUE;
philpem@27 2717 trace_pc_valid <= `TRUE;
philpem@27 2718 trace_pc <= pc_w;
philpem@27 2719 trace_eid <= eid_w;
philpem@0 2720 end
philpem@0 2721 else
philpem@27 2722 trace_exception <= `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@27 2730 trace_pc_valid <= `TRUE;
philpem@27 2731 trace_pc <= pc_w;
philpem@0 2732 end
philpem@0 2733 // Record PC so we can determine if next instruction is sequential or not
philpem@27 2734 pc_c <= pc_w;
philpem@0 2735 // Indicate if it was an eret/bret instruction
philpem@27 2736 trace_eret <= eret_w;
philpem@0 2737 `ifdef CFG_DEBUG_ENABLED
philpem@27 2738 trace_bret <= bret_w;
philpem@0 2739 `endif
philpem@0 2740 end
philpem@0 2741 else
philpem@0 2742 begin
philpem@27 2743 trace_eret <= `FALSE;
philpem@0 2744 `ifdef CFG_DEBUG_ENABLED
philpem@27 2745 trace_bret <= `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