lm32_cpu.v

Sun, 06 Mar 2011 21:17:31 +0000

author
Philip Pemberton <philpem@philpem.me.uk>
date
Sun, 06 Mar 2011 21:17:31 +0000
changeset 23
252df75c8f67
parent 18
cc945f778cd7
parent 22
35dc7ba83714
permissions
-rw-r--r--

[MERGE] Merge changes from LatticeMico32 v3.6

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