lm32_cpu.v

Sun, 06 Mar 2011 19:48:34 +0000

author
Philip Pemberton <philpem@philpem.me.uk>
date
Sun, 06 Mar 2011 19:48:34 +0000
changeset 16
5fb37de64edc
parent 14
54dd95f89113
child 18
cc945f778cd7
permissions
-rwxr-xr-x

Add JTAG interface for Xilinx Spartan 6 (Michael Walle)

Original-Source: Milkymist mailing list posting, 2010-09-23
Original-Message-Id: <201009232334.04219.michael@walle.cc>
Original-Author: Michael Walle <michael walle.cc>

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@0 957 // ----- Outputs -------
philpem@0 958 // To pipeline
philpem@0 959 `ifdef CFG_DCACHE_ENABLED
philpem@0 960 .dcache_refill_request (dcache_refill_request),
philpem@0 961 .dcache_restart_request (dcache_restart_request),
philpem@0 962 .dcache_stall_request (dcache_stall_request),
philpem@0 963 .dcache_refilling (dcache_refilling),
philpem@0 964 `endif
philpem@0 965 `ifdef CFG_IROM_ENABLED
philpem@0 966 .irom_store_data_m (irom_store_data_m),
philpem@0 967 .irom_address_xm (irom_address_xm),
philpem@0 968 .irom_we_xm (irom_we_xm),
philpem@0 969 .irom_stall_request_x (irom_stall_request_x),
philpem@0 970 `endif
philpem@0 971 .load_data_w (load_data_w),
philpem@0 972 .stall_wb_load (stall_wb_load),
philpem@0 973 // To Wishbone
philpem@0 974 .d_dat_o (D_DAT_O),
philpem@0 975 .d_adr_o (D_ADR_O),
philpem@0 976 .d_cyc_o (D_CYC_O),
philpem@0 977 .d_sel_o (D_SEL_O),
philpem@0 978 .d_stb_o (D_STB_O),
philpem@0 979 .d_we_o (D_WE_O),
philpem@0 980 .d_cti_o (D_CTI_O),
philpem@0 981 .d_lock_o (D_LOCK_O),
philpem@0 982 .d_bte_o (D_BTE_O)
philpem@0 983 );
philpem@0 984
philpem@0 985 // Adder
philpem@0 986 lm32_adder adder (
philpem@0 987 // ----- Inputs -------
philpem@0 988 .adder_op_x (adder_op_x),
philpem@0 989 .adder_op_x_n (adder_op_x_n),
philpem@0 990 .operand_0_x (operand_0_x),
philpem@0 991 .operand_1_x (operand_1_x),
philpem@0 992 // ----- Outputs -------
philpem@0 993 .adder_result_x (adder_result_x),
philpem@0 994 .adder_carry_n_x (adder_carry_n_x),
philpem@0 995 .adder_overflow_x (adder_overflow_x)
philpem@0 996 );
philpem@0 997
philpem@0 998 // Logic operations
philpem@0 999 lm32_logic_op logic_op (
philpem@0 1000 // ----- Inputs -------
philpem@0 1001 .logic_op_x (logic_op_x),
philpem@0 1002 .operand_0_x (operand_0_x),
philpem@0 1003
philpem@0 1004 .operand_1_x (operand_1_x),
philpem@0 1005 // ----- Outputs -------
philpem@0 1006 .logic_result_x (logic_result_x)
philpem@0 1007 );
philpem@0 1008
philpem@0 1009 `ifdef CFG_PL_BARREL_SHIFT_ENABLED
philpem@0 1010 // Pipelined barrel-shifter
philpem@0 1011 lm32_shifter shifter (
philpem@0 1012 // ----- Inputs -------
philpem@0 1013 .clk_i (clk_i),
philpem@0 1014 .rst_i (rst_i),
philpem@0 1015 .stall_x (stall_x),
philpem@0 1016 .direction_x (direction_x),
philpem@0 1017 .sign_extend_x (sign_extend_x),
philpem@0 1018 .operand_0_x (operand_0_x),
philpem@0 1019 .operand_1_x (operand_1_x),
philpem@0 1020 // ----- Outputs -------
philpem@0 1021 .shifter_result_m (shifter_result_m)
philpem@0 1022 );
philpem@0 1023 `endif
philpem@0 1024
philpem@0 1025 `ifdef CFG_PL_MULTIPLY_ENABLED
philpem@0 1026 // Pipeline fixed-point multiplier
philpem@0 1027 lm32_multiplier multiplier (
philpem@0 1028 // ----- Inputs -------
philpem@0 1029 .clk_i (clk_i),
philpem@0 1030 .rst_i (rst_i),
philpem@0 1031 .stall_x (stall_x),
philpem@0 1032 .stall_m (stall_m),
philpem@0 1033 .operand_0 (d_result_0),
philpem@0 1034 .operand_1 (d_result_1),
philpem@0 1035 // ----- Outputs -------
philpem@0 1036 .result (multiplier_result_w)
philpem@0 1037 );
philpem@0 1038 `endif
philpem@0 1039
philpem@0 1040 `ifdef LM32_MC_ARITHMETIC_ENABLED
philpem@0 1041 // Multi-cycle arithmetic
philpem@0 1042 lm32_mc_arithmetic mc_arithmetic (
philpem@0 1043 // ----- Inputs -------
philpem@0 1044 .clk_i (clk_i),
philpem@0 1045 .rst_i (rst_i),
philpem@0 1046 .stall_d (stall_d),
philpem@0 1047 .kill_x (kill_x),
philpem@0 1048 `ifdef CFG_MC_DIVIDE_ENABLED
philpem@0 1049 .divide_d (divide_q_d),
philpem@0 1050 .modulus_d (modulus_q_d),
philpem@0 1051 `endif
philpem@0 1052 `ifdef CFG_MC_MULTIPLY_ENABLED
philpem@0 1053 .multiply_d (multiply_q_d),
philpem@0 1054 `endif
philpem@0 1055 `ifdef CFG_MC_BARREL_SHIFT_ENABLED
philpem@0 1056 .shift_left_d (shift_left_q_d),
philpem@0 1057 .shift_right_d (shift_right_q_d),
philpem@0 1058 .sign_extend_d (sign_extend_d),
philpem@0 1059 `endif
philpem@0 1060 .operand_0_d (d_result_0),
philpem@0 1061 .operand_1_d (d_result_1),
philpem@0 1062 // ----- Outputs -------
philpem@0 1063 .result_x (mc_result_x),
philpem@0 1064 `ifdef CFG_MC_DIVIDE_ENABLED
philpem@0 1065 .divide_by_zero_x (divide_by_zero_x),
philpem@0 1066 `endif
philpem@0 1067 .stall_request_x (mc_stall_request_x)
philpem@0 1068 );
philpem@0 1069 `endif
philpem@0 1070
philpem@0 1071 `ifdef CFG_INTERRUPTS_ENABLED
philpem@0 1072 // Interrupt unit
philpem@13 1073 lm32_interrupt interrupt_unit (
philpem@0 1074 // ----- Inputs -------
philpem@12 1075 .clk_i (clk_i),
philpem@0 1076 .rst_i (rst_i),
philpem@0 1077 // From external devices
philpem@12 1078 .interrupt (interrupt),
philpem@0 1079 // From pipeline
philpem@0 1080 .stall_x (stall_x),
philpem@0 1081 `ifdef CFG_DEBUG_ENABLED
philpem@12 1082 .non_debug_exception (non_debug_exception_q_w),
philpem@0 1083 .debug_exception (debug_exception_q_w),
philpem@0 1084 `else
philpem@12 1085 .exception (exception_q_w),
philpem@0 1086 `endif
philpem@0 1087 .eret_q_x (eret_q_x),
philpem@0 1088 `ifdef CFG_DEBUG_ENABLED
philpem@0 1089 .bret_q_x (bret_q_x),
philpem@0 1090 `endif
philpem@0 1091 .csr (csr_x),
philpem@0 1092 .csr_write_data (operand_1_x),
philpem@0 1093 .csr_write_enable (csr_write_enable_q_x),
philpem@0 1094 // ----- Outputs -------
philpem@0 1095 .interrupt_exception (interrupt_exception),
philpem@0 1096 // To pipeline
philpem@0 1097 .csr_read_data (interrupt_csr_read_data_x)
philpem@0 1098 );
philpem@0 1099 `endif
philpem@0 1100
philpem@0 1101 `ifdef CFG_JTAG_ENABLED
philpem@0 1102 // JTAG interface
philpem@0 1103 lm32_jtag jtag (
philpem@0 1104 // ----- Inputs -------
philpem@0 1105 .clk_i (clk_i),
philpem@0 1106 .rst_i (rst_i),
philpem@0 1107 // From JTAG
philpem@0 1108 .jtag_clk (jtag_clk),
philpem@0 1109 .jtag_update (jtag_update),
philpem@0 1110 .jtag_reg_q (jtag_reg_q),
philpem@0 1111 .jtag_reg_addr_q (jtag_reg_addr_q),
philpem@0 1112 // From pipeline
philpem@0 1113 `ifdef CFG_JTAG_UART_ENABLED
philpem@0 1114 .csr (csr_x),
philpem@0 1115 .csr_write_data (operand_1_x),
philpem@0 1116 .csr_write_enable (csr_write_enable_q_x),
philpem@0 1117 .stall_x (stall_x),
philpem@0 1118 `endif
philpem@0 1119 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 1120 .jtag_read_data (jtag_read_data),
philpem@0 1121 .jtag_access_complete (jtag_access_complete),
philpem@0 1122 `endif
philpem@0 1123 `ifdef CFG_DEBUG_ENABLED
philpem@0 1124 .exception_q_w (debug_exception_q_w || non_debug_exception_q_w),
philpem@0 1125 `endif
philpem@0 1126 // ----- Outputs -------
philpem@0 1127 // To pipeline
philpem@0 1128 `ifdef CFG_JTAG_UART_ENABLED
philpem@0 1129 .jtx_csr_read_data (jtx_csr_read_data),
philpem@0 1130 .jrx_csr_read_data (jrx_csr_read_data),
philpem@0 1131 `endif
philpem@0 1132 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 1133 .jtag_csr_write_enable (jtag_csr_write_enable),
philpem@0 1134 .jtag_csr_write_data (jtag_csr_write_data),
philpem@0 1135 .jtag_csr (jtag_csr),
philpem@0 1136 .jtag_read_enable (jtag_read_enable),
philpem@0 1137 .jtag_write_enable (jtag_write_enable),
philpem@0 1138 .jtag_write_data (jtag_write_data),
philpem@0 1139 .jtag_address (jtag_address),
philpem@0 1140 `endif
philpem@0 1141 `ifdef CFG_DEBUG_ENABLED
philpem@0 1142 .jtag_break (jtag_break),
philpem@0 1143 .jtag_reset (reset_exception),
philpem@0 1144 `endif
philpem@0 1145 // To JTAG
philpem@0 1146 .jtag_reg_d (jtag_reg_d),
philpem@0 1147 .jtag_reg_addr_d (jtag_reg_addr_d)
philpem@0 1148 );
philpem@0 1149 `endif
philpem@0 1150
philpem@0 1151 `ifdef CFG_DEBUG_ENABLED
philpem@0 1152 // Debug unit
philpem@0 1153 lm32_debug #(
philpem@0 1154 .breakpoints (breakpoints),
philpem@0 1155 .watchpoints (watchpoints)
philpem@0 1156 ) hw_debug (
philpem@0 1157 // ----- Inputs -------
philpem@0 1158 .clk_i (clk_i),
philpem@0 1159 .rst_i (rst_i),
philpem@0 1160 .pc_x (pc_x),
philpem@0 1161 .load_x (load_x),
philpem@0 1162 .store_x (store_x),
philpem@0 1163 .load_store_address_x (adder_result_x),
philpem@0 1164 .csr_write_enable_x (csr_write_enable_q_x),
philpem@0 1165 .csr_write_data (operand_1_x),
philpem@0 1166 .csr_x (csr_x),
philpem@0 1167 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 1168 .jtag_csr_write_enable (jtag_csr_write_enable),
philpem@0 1169 .jtag_csr_write_data (jtag_csr_write_data),
philpem@0 1170 .jtag_csr (jtag_csr),
philpem@0 1171 `endif
philpem@0 1172 `ifdef LM32_SINGLE_STEP_ENABLED
philpem@0 1173 .eret_q_x (eret_q_x),
philpem@0 1174 .bret_q_x (bret_q_x),
philpem@0 1175 .stall_x (stall_x),
philpem@0 1176 .exception_x (exception_x),
philpem@0 1177 .q_x (q_x),
philpem@0 1178 `ifdef CFG_DCACHE_ENABLED
philpem@0 1179 .dcache_refill_request (dcache_refill_request),
philpem@0 1180 `endif
philpem@0 1181 `endif
philpem@0 1182 // ----- Outputs -------
philpem@0 1183 `ifdef LM32_SINGLE_STEP_ENABLED
philpem@0 1184 .dc_ss (dc_ss),
philpem@0 1185 `endif
philpem@0 1186 .dc_re (dc_re),
philpem@0 1187 .bp_match (bp_match),
philpem@0 1188 .wp_match (wp_match)
philpem@0 1189 );
philpem@0 1190 `endif
philpem@0 1191
philpem@0 1192 // Register file
philpem@0 1193
philpem@0 1194 `ifdef CFG_EBR_POSEDGE_REGISTER_FILE
philpem@0 1195 /*----------------------------------------------------------------------
philpem@0 1196 Register File is implemented using EBRs. There can be three accesses to
philpem@0 1197 the register file in each cycle: two reads and one write. On-chip block
philpem@0 1198 RAM has two read/write ports. To accomodate three accesses, two on-chip
philpem@0 1199 block RAMs are used (each register file "write" is made to both block
philpem@0 1200 RAMs).
philpem@0 1201
philpem@0 1202 One limitation of the on-chip block RAMs is that one cannot perform a
philpem@0 1203 read and write to same location in a cycle (if this is done, then the
philpem@0 1204 data read out is indeterminate).
philpem@0 1205 ----------------------------------------------------------------------*/
philpem@0 1206 wire [31:0] regfile_data_0, regfile_data_1;
philpem@0 1207 reg [31:0] w_result_d;
philpem@0 1208 reg regfile_raw_0, regfile_raw_0_nxt;
philpem@0 1209 reg regfile_raw_1, regfile_raw_1_nxt;
philpem@0 1210
philpem@0 1211 /*----------------------------------------------------------------------
philpem@0 1212 Check if read and write is being performed to same register in current
philpem@0 1213 cycle? This is done by comparing the read and write IDXs.
philpem@0 1214 ----------------------------------------------------------------------*/
philpem@0 1215 always @(reg_write_enable_q_w or write_idx_w or instruction_f)
philpem@0 1216 begin
philpem@0 1217 if (reg_write_enable_q_w
philpem@0 1218 && (write_idx_w == instruction_f[25:21]))
philpem@0 1219 regfile_raw_0_nxt = 1'b1;
philpem@0 1220 else
philpem@0 1221 regfile_raw_0_nxt = 1'b0;
philpem@0 1222
philpem@0 1223 if (reg_write_enable_q_w
philpem@0 1224 && (write_idx_w == instruction_f[20:16]))
philpem@0 1225 regfile_raw_1_nxt = 1'b1;
philpem@0 1226 else
philpem@0 1227 regfile_raw_1_nxt = 1'b0;
philpem@0 1228 end
philpem@0 1229
philpem@0 1230 /*----------------------------------------------------------------------
philpem@0 1231 Select latched (delayed) write value or data from register file. If
philpem@0 1232 read in previous cycle was performed to register written to in same
philpem@0 1233 cycle, then latched (delayed) write value is selected.
philpem@0 1234 ----------------------------------------------------------------------*/
philpem@0 1235 always @(regfile_raw_0 or w_result_d or regfile_data_0)
philpem@0 1236 if (regfile_raw_0)
philpem@0 1237 reg_data_live_0 = w_result_d;
philpem@0 1238 else
philpem@0 1239 reg_data_live_0 = regfile_data_0;
philpem@0 1240
philpem@0 1241 /*----------------------------------------------------------------------
philpem@0 1242 Select latched (delayed) write value or data from register file. If
philpem@0 1243 read in previous cycle was performed to register written to in same
philpem@0 1244 cycle, then latched (delayed) write value is selected.
philpem@0 1245 ----------------------------------------------------------------------*/
philpem@0 1246 always @(regfile_raw_1 or w_result_d or regfile_data_1)
philpem@0 1247 if (regfile_raw_1)
philpem@0 1248 reg_data_live_1 = w_result_d;
philpem@0 1249 else
philpem@0 1250 reg_data_live_1 = regfile_data_1;
philpem@0 1251
philpem@0 1252 /*----------------------------------------------------------------------
philpem@0 1253 Latch value written to register file
philpem@0 1254 ----------------------------------------------------------------------*/
philpem@0 1255 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 1256 if (rst_i == `TRUE)
philpem@0 1257 begin
philpem@0 1258 regfile_raw_0 <= 1'b0;
philpem@0 1259 regfile_raw_1 <= 1'b0;
philpem@0 1260 w_result_d <= 32'b0;
philpem@0 1261 end
philpem@0 1262 else
philpem@0 1263 begin
philpem@0 1264 regfile_raw_0 <= regfile_raw_0_nxt;
philpem@0 1265 regfile_raw_1 <= regfile_raw_1_nxt;
philpem@0 1266 w_result_d <= w_result;
philpem@0 1267 end
philpem@0 1268
philpem@0 1269 /*----------------------------------------------------------------------
philpem@0 1270 Register file instantiation as Pseudo-Dual Port EBRs.
philpem@0 1271 ----------------------------------------------------------------------*/
philpem@0 1272 pmi_ram_dp
philpem@0 1273 #(
philpem@0 1274 // ----- Parameters -----
philpem@0 1275 .pmi_wr_addr_depth(1<<5),
philpem@0 1276 .pmi_wr_addr_width(5),
philpem@0 1277 .pmi_wr_data_width(32),
philpem@0 1278 .pmi_rd_addr_depth(1<<5),
philpem@0 1279 .pmi_rd_addr_width(5),
philpem@0 1280 .pmi_rd_data_width(32),
philpem@0 1281 .pmi_regmode("noreg"),
philpem@0 1282 .pmi_gsr("enable"),
philpem@0 1283 .pmi_resetmode("sync"),
philpem@0 1284 .pmi_init_file("none"),
philpem@0 1285 .pmi_init_file_format("binary"),
philpem@0 1286 .pmi_family(`LATTICE_FAMILY),
philpem@0 1287 .module_type("pmi_ram_dp")
philpem@0 1288 )
philpem@0 1289 reg_0
philpem@0 1290 (
philpem@0 1291 // ----- Inputs -----
philpem@0 1292 .Data(w_result),
philpem@0 1293 .WrAddress(write_idx_w),
philpem@0 1294 .RdAddress(instruction_f[25:21]),
philpem@0 1295 .WrClock(clk_i),
philpem@0 1296 .RdClock(clk_i),
philpem@0 1297 .WrClockEn(`TRUE),
philpem@0 1298 .RdClockEn(`TRUE),
philpem@0 1299 .WE(reg_write_enable_q_w),
philpem@0 1300 .Reset(rst_i),
philpem@0 1301 // ----- Outputs -----
philpem@0 1302 .Q(regfile_data_0)
philpem@0 1303 );
philpem@0 1304
philpem@0 1305 pmi_ram_dp
philpem@0 1306 #(
philpem@0 1307 // ----- Parameters -----
philpem@0 1308 .pmi_wr_addr_depth(1<<5),
philpem@0 1309 .pmi_wr_addr_width(5),
philpem@0 1310 .pmi_wr_data_width(32),
philpem@0 1311 .pmi_rd_addr_depth(1<<5),
philpem@0 1312 .pmi_rd_addr_width(5),
philpem@0 1313 .pmi_rd_data_width(32),
philpem@0 1314 .pmi_regmode("noreg"),
philpem@0 1315 .pmi_gsr("enable"),
philpem@0 1316 .pmi_resetmode("sync"),
philpem@0 1317 .pmi_init_file("none"),
philpem@0 1318 .pmi_init_file_format("binary"),
philpem@0 1319 .pmi_family(`LATTICE_FAMILY),
philpem@0 1320 .module_type("pmi_ram_dp")
philpem@0 1321 )
philpem@0 1322 reg_1
philpem@0 1323 (
philpem@0 1324 // ----- Inputs -----
philpem@0 1325 .Data(w_result),
philpem@0 1326 .WrAddress(write_idx_w),
philpem@0 1327 .RdAddress(instruction_f[20:16]),
philpem@0 1328 .WrClock(clk_i),
philpem@0 1329 .RdClock(clk_i),
philpem@0 1330 .WrClockEn(`TRUE),
philpem@0 1331 .RdClockEn(`TRUE),
philpem@0 1332 .WE(reg_write_enable_q_w),
philpem@0 1333 .Reset(rst_i),
philpem@0 1334 // ----- Outputs -----
philpem@0 1335 .Q(regfile_data_1)
philpem@0 1336 );
philpem@0 1337 `endif
philpem@0 1338
philpem@0 1339 `ifdef CFG_EBR_NEGEDGE_REGISTER_FILE
philpem@0 1340 pmi_ram_dp
philpem@0 1341 #(
philpem@0 1342 // ----- Parameters -----
philpem@0 1343 .pmi_wr_addr_depth(1<<5),
philpem@0 1344 .pmi_wr_addr_width(5),
philpem@0 1345 .pmi_wr_data_width(32),
philpem@0 1346 .pmi_rd_addr_depth(1<<5),
philpem@0 1347 .pmi_rd_addr_width(5),
philpem@0 1348 .pmi_rd_data_width(32),
philpem@0 1349 .pmi_regmode("noreg"),
philpem@0 1350 .pmi_gsr("enable"),
philpem@0 1351 .pmi_resetmode("sync"),
philpem@0 1352 .pmi_init_file("none"),
philpem@0 1353 .pmi_init_file_format("binary"),
philpem@0 1354 .pmi_family(`LATTICE_FAMILY),
philpem@0 1355 .module_type("pmi_ram_dp")
philpem@0 1356 )
philpem@0 1357 reg_0
philpem@0 1358 (
philpem@0 1359 // ----- Inputs -----
philpem@0 1360 .Data(w_result),
philpem@0 1361 .WrAddress(write_idx_w),
philpem@0 1362 .RdAddress(read_idx_0_d),
philpem@0 1363 .WrClock(clk_i),
philpem@0 1364 .RdClock(clk_n_i),
philpem@0 1365 .WrClockEn(`TRUE),
philpem@0 1366 .RdClockEn(stall_f == `FALSE),
philpem@0 1367 .WE(reg_write_enable_q_w),
philpem@0 1368 .Reset(rst_i),
philpem@0 1369 // ----- Outputs -----
philpem@0 1370 .Q(reg_data_0)
philpem@0 1371 );
philpem@0 1372
philpem@0 1373 pmi_ram_dp
philpem@0 1374 #(
philpem@0 1375 // ----- Parameters -----
philpem@0 1376 .pmi_wr_addr_depth(1<<5),
philpem@0 1377 .pmi_wr_addr_width(5),
philpem@0 1378 .pmi_wr_data_width(32),
philpem@0 1379 .pmi_rd_addr_depth(1<<5),
philpem@0 1380 .pmi_rd_addr_width(5),
philpem@0 1381 .pmi_rd_data_width(32),
philpem@0 1382 .pmi_regmode("noreg"),
philpem@0 1383 .pmi_gsr("enable"),
philpem@0 1384 .pmi_resetmode("sync"),
philpem@0 1385 .pmi_init_file("none"),
philpem@0 1386 .pmi_init_file_format("binary"),
philpem@0 1387 .pmi_family(`LATTICE_FAMILY),
philpem@0 1388 .module_type("pmi_ram_dp")
philpem@0 1389 )
philpem@0 1390 reg_1
philpem@0 1391 (
philpem@0 1392 // ----- Inputs -----
philpem@0 1393 .Data(w_result),
philpem@0 1394 .WrAddress(write_idx_w),
philpem@0 1395 .RdAddress(read_idx_1_d),
philpem@0 1396 .WrClock(clk_i),
philpem@0 1397 .RdClock(clk_n_i),
philpem@0 1398 .WrClockEn(`TRUE),
philpem@0 1399 .RdClockEn(stall_f == `FALSE),
philpem@0 1400 .WE(reg_write_enable_q_w),
philpem@0 1401 .Reset(rst_i),
philpem@0 1402 // ----- Outputs -----
philpem@0 1403 .Q(reg_data_1)
philpem@0 1404 );
philpem@0 1405 `endif
philpem@0 1406
philpem@0 1407
philpem@0 1408 /////////////////////////////////////////////////////
philpem@0 1409 // Combinational Logic
philpem@0 1410 /////////////////////////////////////////////////////
philpem@0 1411
philpem@0 1412 `ifdef CFG_EBR_POSEDGE_REGISTER_FILE
philpem@0 1413 // Select between buffered and live data from register file
philpem@0 1414 assign reg_data_0 = use_buf ? reg_data_buf_0 : reg_data_live_0;
philpem@0 1415 assign reg_data_1 = use_buf ? reg_data_buf_1 : reg_data_live_1;
philpem@0 1416 `endif
philpem@0 1417 `ifdef LM32_EBR_REGISTER_FILE
philpem@0 1418 `else
philpem@0 1419 // Register file read ports
philpem@0 1420 assign reg_data_0 = registers[read_idx_0_d];
philpem@0 1421 assign reg_data_1 = registers[read_idx_1_d];
philpem@0 1422 `endif
philpem@0 1423
philpem@0 1424 // Detect read-after-write hazzards
philpem@0 1425 assign raw_x_0 = (write_idx_x == read_idx_0_d) && (write_enable_q_x == `TRUE);
philpem@0 1426 assign raw_m_0 = (write_idx_m == read_idx_0_d) && (write_enable_q_m == `TRUE);
philpem@0 1427 assign raw_w_0 = (write_idx_w == read_idx_0_d) && (write_enable_q_w == `TRUE);
philpem@0 1428 assign raw_x_1 = (write_idx_x == read_idx_1_d) && (write_enable_q_x == `TRUE);
philpem@0 1429 assign raw_m_1 = (write_idx_m == read_idx_1_d) && (write_enable_q_m == `TRUE);
philpem@0 1430 assign raw_w_1 = (write_idx_w == read_idx_1_d) && (write_enable_q_w == `TRUE);
philpem@0 1431
philpem@0 1432 // Interlock detection - Raise an interlock for RAW hazzards
philpem@0 1433 always @(*)
philpem@0 1434 begin
philpem@0 1435 if ( ( (x_bypass_enable_x == `FALSE)
philpem@0 1436 && ( ((read_enable_0_d == `TRUE) && (raw_x_0 == `TRUE))
philpem@0 1437 || ((read_enable_1_d == `TRUE) && (raw_x_1 == `TRUE))
philpem@0 1438 )
philpem@0 1439 )
philpem@0 1440 || ( (m_bypass_enable_m == `FALSE)
philpem@0 1441 && ( ((read_enable_0_d == `TRUE) && (raw_m_0 == `TRUE))
philpem@0 1442 || ((read_enable_1_d == `TRUE) && (raw_m_1 == `TRUE))
philpem@0 1443 )
philpem@0 1444 )
philpem@0 1445 )
philpem@0 1446 interlock = `TRUE;
philpem@0 1447 else
philpem@0 1448 interlock = `FALSE;
philpem@0 1449 end
philpem@0 1450
philpem@0 1451 // Bypass for reg port 0
philpem@0 1452 always @(*)
philpem@0 1453 begin
philpem@0 1454 if (raw_x_0 == `TRUE)
philpem@0 1455 bypass_data_0 = x_result;
philpem@0 1456 else if (raw_m_0 == `TRUE)
philpem@0 1457 bypass_data_0 = m_result;
philpem@0 1458 else if (raw_w_0 == `TRUE)
philpem@0 1459 bypass_data_0 = w_result;
philpem@0 1460 else
philpem@0 1461 bypass_data_0 = reg_data_0;
philpem@0 1462 end
philpem@0 1463
philpem@0 1464 // Bypass for reg port 1
philpem@0 1465 always @(*)
philpem@0 1466 begin
philpem@0 1467 if (raw_x_1 == `TRUE)
philpem@0 1468 bypass_data_1 = x_result;
philpem@0 1469 else if (raw_m_1 == `TRUE)
philpem@0 1470 bypass_data_1 = m_result;
philpem@0 1471 else if (raw_w_1 == `TRUE)
philpem@0 1472 bypass_data_1 = w_result;
philpem@0 1473 else
philpem@0 1474 bypass_data_1 = reg_data_1;
philpem@0 1475 end
philpem@0 1476
philpem@0 1477 /*----------------------------------------------------------------------
philpem@0 1478 Branch prediction is performed in D stage of pipeline. Only PC-relative
philpem@0 1479 branches are predicted: forward-pointing conditional branches are not-
philpem@0 1480 taken, while backward-pointing conditional branches are taken.
philpem@0 1481 Unconditional branches are always predicted taken!
philpem@0 1482 ----------------------------------------------------------------------*/
philpem@0 1483 assign branch_predict_d = bi_unconditional | bi_conditional;
philpem@0 1484 assign branch_predict_taken_d = bi_unconditional ? 1'b1 : (bi_conditional ? instruction_d[15] : 1'b0);
philpem@0 1485
philpem@0 1486 // Compute branch target address: Branch PC PLUS Offset
philpem@0 1487 assign branch_target_d = pc_d + branch_offset_d;
philpem@0 1488
philpem@0 1489 // Compute fetch address. Address of instruction sequentially after the
philpem@0 1490 // branch if branch is not taken. Target address of branch is branch is
philpem@0 1491 // taken
philpem@0 1492 assign branch_predict_address_d = branch_predict_taken_d ? branch_target_d : pc_f;
philpem@0 1493
philpem@0 1494 // D stage result selection
philpem@0 1495 always @(*)
philpem@0 1496 begin
philpem@0 1497 d_result_0 = d_result_sel_0_d[0] ? {pc_f, 2'b00} : bypass_data_0;
philpem@0 1498 case (d_result_sel_1_d)
philpem@0 1499 `LM32_D_RESULT_SEL_1_ZERO: d_result_1 = {`LM32_WORD_WIDTH{1'b0}};
philpem@0 1500 `LM32_D_RESULT_SEL_1_REG_1: d_result_1 = bypass_data_1;
philpem@0 1501 `LM32_D_RESULT_SEL_1_IMMEDIATE: d_result_1 = immediate_d;
philpem@0 1502 default: d_result_1 = {`LM32_WORD_WIDTH{1'bx}};
philpem@0 1503 endcase
philpem@0 1504 end
philpem@0 1505
philpem@0 1506 `ifdef CFG_USER_ENABLED
philpem@0 1507 // Operands for user-defined instructions
philpem@0 1508 assign user_operand_0 = operand_0_x;
philpem@0 1509 assign user_operand_1 = operand_1_x;
philpem@0 1510 `endif
philpem@0 1511
philpem@0 1512 `ifdef CFG_SIGN_EXTEND_ENABLED
philpem@0 1513 // Sign-extension
philpem@0 1514 assign sextb_result_x = {{24{operand_0_x[7]}}, operand_0_x[7:0]};
philpem@0 1515 assign sexth_result_x = {{16{operand_0_x[15]}}, operand_0_x[15:0]};
philpem@0 1516 assign sext_result_x = size_x == `LM32_SIZE_BYTE ? sextb_result_x : sexth_result_x;
philpem@0 1517 `endif
philpem@0 1518
philpem@0 1519 `ifdef LM32_NO_BARREL_SHIFT
philpem@0 1520 // Only single bit shift operations are supported when barrel-shifter isn't implemented
philpem@0 1521 assign shifter_result_x = {operand_0_x[`LM32_WORD_WIDTH-1] & sign_extend_x, operand_0_x[`LM32_WORD_WIDTH-1:1]};
philpem@0 1522 `endif
philpem@0 1523
philpem@0 1524 // Condition evaluation
philpem@0 1525 assign cmp_zero = operand_0_x == operand_1_x;
philpem@0 1526 assign cmp_negative = adder_result_x[`LM32_WORD_WIDTH-1];
philpem@0 1527 assign cmp_overflow = adder_overflow_x;
philpem@0 1528 assign cmp_carry_n = adder_carry_n_x;
philpem@0 1529 always @(*)
philpem@0 1530 begin
philpem@0 1531 case (condition_x)
philpem@0 1532 `LM32_CONDITION_U1: condition_met_x = `TRUE;
philpem@0 1533 `LM32_CONDITION_U2: condition_met_x = `TRUE;
philpem@0 1534 `LM32_CONDITION_E: condition_met_x = cmp_zero;
philpem@0 1535 `LM32_CONDITION_NE: condition_met_x = !cmp_zero;
philpem@0 1536 `LM32_CONDITION_G: condition_met_x = !cmp_zero && (cmp_negative == cmp_overflow);
philpem@0 1537 `LM32_CONDITION_GU: condition_met_x = cmp_carry_n && !cmp_zero;
philpem@0 1538 `LM32_CONDITION_GE: condition_met_x = cmp_negative == cmp_overflow;
philpem@0 1539 `LM32_CONDITION_GEU: condition_met_x = cmp_carry_n;
philpem@0 1540 default: condition_met_x = 1'bx;
philpem@0 1541 endcase
philpem@0 1542 end
philpem@0 1543
philpem@0 1544 // X stage result selection
philpem@0 1545 always @(*)
philpem@0 1546 begin
philpem@0 1547 x_result = x_result_sel_add_x ? adder_result_x
philpem@0 1548 : x_result_sel_csr_x ? csr_read_data_x
philpem@0 1549 `ifdef CFG_SIGN_EXTEND_ENABLED
philpem@0 1550 : x_result_sel_sext_x ? sext_result_x
philpem@0 1551 `endif
philpem@0 1552 `ifdef CFG_USER_ENABLED
philpem@0 1553 : x_result_sel_user_x ? user_result
philpem@0 1554 `endif
philpem@0 1555 `ifdef LM32_NO_BARREL_SHIFT
philpem@0 1556 : x_result_sel_shift_x ? shifter_result_x
philpem@0 1557 `endif
philpem@0 1558 `ifdef LM32_MC_ARITHMETIC_ENABLED
philpem@0 1559 : x_result_sel_mc_arith_x ? mc_result_x
philpem@0 1560 `endif
philpem@0 1561 : logic_result_x;
philpem@0 1562 end
philpem@0 1563
philpem@0 1564 // M stage result selection
philpem@0 1565 always @(*)
philpem@0 1566 begin
philpem@0 1567 m_result = m_result_sel_compare_m ? {{`LM32_WORD_WIDTH-1{1'b0}}, condition_met_m}
philpem@0 1568 `ifdef CFG_PL_BARREL_SHIFT_ENABLED
philpem@0 1569 : m_result_sel_shift_m ? shifter_result_m
philpem@0 1570 `endif
philpem@0 1571 : operand_m;
philpem@0 1572 end
philpem@0 1573
philpem@0 1574 // W stage result selection
philpem@0 1575 always @(*)
philpem@0 1576 begin
philpem@0 1577 w_result = w_result_sel_load_w ? load_data_w
philpem@0 1578 `ifdef CFG_PL_MULTIPLY_ENABLED
philpem@0 1579 : w_result_sel_mul_w ? multiplier_result_w
philpem@0 1580 `endif
philpem@0 1581 : operand_w;
philpem@0 1582 end
philpem@0 1583
philpem@0 1584 `ifdef CFG_FAST_UNCONDITIONAL_BRANCH
philpem@0 1585 // Indicate when a branch should be taken in X stage
philpem@0 1586 assign branch_taken_x = (stall_x == `FALSE)
philpem@0 1587 && ( (branch_x == `TRUE)
philpem@0 1588 && ((condition_x == `LM32_CONDITION_U1) || (condition_x == `LM32_CONDITION_U2))
philpem@0 1589 && (valid_x == `TRUE)
philpem@0 1590 && (branch_predict_x == `FALSE)
philpem@0 1591 );
philpem@0 1592 `endif
philpem@0 1593
philpem@0 1594 // Indicate when a branch should be taken in M stage (exceptions are a type of branch)
philpem@0 1595 assign branch_taken_m = (stall_m == `FALSE)
philpem@0 1596 && ( ( (branch_m == `TRUE)
philpem@0 1597 && (valid_m == `TRUE)
philpem@0 1598 && ( ( (condition_met_m == `TRUE)
philpem@0 1599 && (branch_predict_taken_m == `FALSE)
philpem@0 1600 )
philpem@0 1601 || ( (condition_met_m == `FALSE)
philpem@0 1602 && (branch_predict_m == `TRUE)
philpem@0 1603 && (branch_predict_taken_m == `TRUE)
philpem@0 1604 )
philpem@0 1605 )
philpem@0 1606 )
philpem@0 1607 || (exception_m == `TRUE)
philpem@0 1608 );
philpem@0 1609
philpem@0 1610 // Indicate when a branch in M stage is mispredicted as being taken
philpem@0 1611 assign branch_mispredict_taken_m = (condition_met_m == `FALSE)
philpem@0 1612 && (branch_predict_m == `TRUE)
philpem@0 1613 && (branch_predict_taken_m == `TRUE);
philpem@0 1614
philpem@0 1615 // Indicate when a branch in M stage will cause flush in X stage
philpem@0 1616 assign branch_flushX_m = (stall_m == `FALSE)
philpem@0 1617 && ( ( (branch_m == `TRUE)
philpem@0 1618 && (valid_m == `TRUE)
philpem@0 1619 && ( (condition_met_m == `TRUE)
philpem@0 1620 || ( (condition_met_m == `FALSE)
philpem@0 1621 && (branch_predict_m == `TRUE)
philpem@0 1622 && (branch_predict_taken_m == `TRUE)
philpem@0 1623 )
philpem@0 1624 )
philpem@0 1625 )
philpem@0 1626 || (exception_m == `TRUE)
philpem@0 1627 );
philpem@0 1628
philpem@0 1629 // Generate signal that will kill instructions in each pipeline stage when necessary
philpem@0 1630 assign kill_f = ( (valid_d == `TRUE)
philpem@0 1631 && (branch_predict_taken_d == `TRUE)
philpem@0 1632 )
philpem@0 1633 || (branch_taken_m == `TRUE)
philpem@0 1634 `ifdef CFG_FAST_UNCONDITIONAL_BRANCH
philpem@0 1635 || (branch_taken_x == `TRUE)
philpem@0 1636 `endif
philpem@0 1637 `ifdef CFG_ICACHE_ENABLED
philpem@0 1638 || (icache_refill_request == `TRUE)
philpem@0 1639 `endif
philpem@0 1640 `ifdef CFG_DCACHE_ENABLED
philpem@0 1641 || (dcache_refill_request == `TRUE)
philpem@0 1642 `endif
philpem@0 1643 ;
philpem@0 1644 assign kill_d = (branch_taken_m == `TRUE)
philpem@0 1645 `ifdef CFG_FAST_UNCONDITIONAL_BRANCH
philpem@0 1646 || (branch_taken_x == `TRUE)
philpem@0 1647 `endif
philpem@0 1648 `ifdef CFG_ICACHE_ENABLED
philpem@0 1649 || (icache_refill_request == `TRUE)
philpem@0 1650 `endif
philpem@0 1651 `ifdef CFG_DCACHE_ENABLED
philpem@0 1652 || (dcache_refill_request == `TRUE)
philpem@0 1653 `endif
philpem@0 1654 ;
philpem@0 1655 assign kill_x = (branch_flushX_m == `TRUE)
philpem@0 1656 `ifdef CFG_DCACHE_ENABLED
philpem@0 1657 || (dcache_refill_request == `TRUE)
philpem@0 1658 `endif
philpem@0 1659 ;
philpem@0 1660 assign kill_m = `FALSE
philpem@0 1661 `ifdef CFG_DCACHE_ENABLED
philpem@0 1662 || (dcache_refill_request == `TRUE)
philpem@0 1663 `endif
philpem@0 1664 ;
philpem@0 1665 assign kill_w = `FALSE
philpem@0 1666 `ifdef CFG_DCACHE_ENABLED
philpem@0 1667 || (dcache_refill_request == `TRUE)
philpem@0 1668 `endif
philpem@0 1669 ;
philpem@0 1670
philpem@0 1671 // Exceptions
philpem@0 1672
philpem@0 1673 `ifdef CFG_DEBUG_ENABLED
philpem@0 1674 assign breakpoint_exception = ( ( (break_x == `TRUE)
philpem@0 1675 || (bp_match == `TRUE)
philpem@0 1676 )
philpem@0 1677 && (valid_x == `TRUE)
philpem@0 1678 )
philpem@0 1679 `ifdef CFG_JTAG_ENABLED
philpem@0 1680 || (jtag_break == `TRUE)
philpem@0 1681 `endif
philpem@0 1682 ;
philpem@0 1683 `endif
philpem@0 1684
philpem@0 1685 `ifdef CFG_DEBUG_ENABLED
philpem@0 1686 assign watchpoint_exception = wp_match == `TRUE;
philpem@0 1687 `endif
philpem@0 1688
philpem@0 1689 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 1690 assign instruction_bus_error_exception = ( (bus_error_x == `TRUE)
philpem@0 1691 && (valid_x == `TRUE)
philpem@0 1692 );
philpem@0 1693 assign data_bus_error_exception = data_bus_error_seen == `TRUE;
philpem@0 1694 `endif
philpem@0 1695
philpem@0 1696 `ifdef CFG_MC_DIVIDE_ENABLED
philpem@0 1697 assign divide_by_zero_exception = divide_by_zero_x == `TRUE;
philpem@0 1698 `endif
philpem@0 1699
philpem@0 1700 assign system_call_exception = ( (scall_x == `TRUE)
philpem@0 1701 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 1702 && (valid_x == `TRUE)
philpem@0 1703 `endif
philpem@0 1704 );
philpem@0 1705
philpem@0 1706 `ifdef CFG_DEBUG_ENABLED
philpem@0 1707 assign debug_exception_x = (breakpoint_exception == `TRUE)
philpem@0 1708 || (watchpoint_exception == `TRUE)
philpem@0 1709 ;
philpem@0 1710
philpem@0 1711 assign non_debug_exception_x = (system_call_exception == `TRUE)
philpem@0 1712 `ifdef CFG_JTAG_ENABLED
philpem@0 1713 || (reset_exception == `TRUE)
philpem@0 1714 `endif
philpem@0 1715 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 1716 || (instruction_bus_error_exception == `TRUE)
philpem@0 1717 || (data_bus_error_exception == `TRUE)
philpem@0 1718 `endif
philpem@0 1719 `ifdef CFG_MC_DIVIDE_ENABLED
philpem@0 1720 || (divide_by_zero_exception == `TRUE)
philpem@0 1721 `endif
philpem@0 1722 `ifdef CFG_INTERRUPTS_ENABLED
philpem@0 1723 || ( (interrupt_exception == `TRUE)
philpem@0 1724 `ifdef LM32_SINGLE_STEP_ENABLED
philpem@0 1725 && (dc_ss == `FALSE)
philpem@0 1726 `endif
philpem@0 1727 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 1728 && (store_q_m == `FALSE)
philpem@0 1729 && (D_CYC_O == `FALSE)
philpem@0 1730 `endif
philpem@0 1731 )
philpem@0 1732 `endif
philpem@0 1733 ;
philpem@0 1734
philpem@0 1735 assign exception_x = (debug_exception_x == `TRUE) || (non_debug_exception_x == `TRUE);
philpem@0 1736 `else
philpem@0 1737 assign exception_x = (system_call_exception == `TRUE)
philpem@0 1738 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 1739 || (instruction_bus_error_exception == `TRUE)
philpem@0 1740 || (data_bus_error_exception == `TRUE)
philpem@0 1741 `endif
philpem@0 1742 `ifdef CFG_MC_DIVIDE_ENABLED
philpem@0 1743 || (divide_by_zero_exception == `TRUE)
philpem@0 1744 `endif
philpem@0 1745 `ifdef CFG_INTERRUPTS_ENABLED
philpem@0 1746 || ( (interrupt_exception == `TRUE)
philpem@0 1747 `ifdef LM32_SINGLE_STEP_ENABLED
philpem@0 1748 && (dc_ss == `FALSE)
philpem@0 1749 `endif
philpem@0 1750 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 1751 && (store_q_m == `FALSE)
philpem@0 1752 && (D_CYC_O == `FALSE)
philpem@0 1753 `endif
philpem@0 1754 )
philpem@0 1755 `endif
philpem@0 1756 ;
philpem@0 1757 `endif
philpem@0 1758
philpem@0 1759 // Exception ID
philpem@0 1760 always @(*)
philpem@0 1761 begin
philpem@0 1762 `ifdef CFG_DEBUG_ENABLED
philpem@0 1763 `ifdef CFG_JTAG_ENABLED
philpem@0 1764 if (reset_exception == `TRUE)
philpem@0 1765 eid_x = `LM32_EID_RESET;
philpem@0 1766 else
philpem@0 1767 `endif
philpem@0 1768 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 1769 if (data_bus_error_exception == `TRUE)
philpem@0 1770 eid_x = `LM32_EID_DATA_BUS_ERROR;
philpem@0 1771 else
philpem@0 1772 `endif
philpem@0 1773 if (breakpoint_exception == `TRUE)
philpem@0 1774 eid_x = `LM32_EID_BREAKPOINT;
philpem@0 1775 else
philpem@0 1776 `endif
philpem@0 1777 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 1778 if (data_bus_error_exception == `TRUE)
philpem@0 1779 eid_x = `LM32_EID_DATA_BUS_ERROR;
philpem@0 1780 else
philpem@0 1781 if (instruction_bus_error_exception == `TRUE)
philpem@0 1782 eid_x = `LM32_EID_INST_BUS_ERROR;
philpem@0 1783 else
philpem@0 1784 `endif
philpem@0 1785 `ifdef CFG_DEBUG_ENABLED
philpem@0 1786 if (watchpoint_exception == `TRUE)
philpem@0 1787 eid_x = `LM32_EID_WATCHPOINT;
philpem@0 1788 else
philpem@0 1789 `endif
philpem@0 1790 `ifdef CFG_MC_DIVIDE_ENABLED
philpem@0 1791 if (divide_by_zero_exception == `TRUE)
philpem@0 1792 eid_x = `LM32_EID_DIVIDE_BY_ZERO;
philpem@0 1793 else
philpem@0 1794 `endif
philpem@0 1795 `ifdef CFG_INTERRUPTS_ENABLED
philpem@0 1796 if ( (interrupt_exception == `TRUE)
philpem@0 1797 `ifdef LM32_SINGLE_STEP_ENABLED
philpem@0 1798 && (dc_ss == `FALSE)
philpem@0 1799 `endif
philpem@0 1800 )
philpem@0 1801 eid_x = `LM32_EID_INTERRUPT;
philpem@0 1802 else
philpem@0 1803 `endif
philpem@0 1804 eid_x = `LM32_EID_SCALL;
philpem@0 1805 end
philpem@0 1806
philpem@0 1807 // Stall generation
philpem@0 1808
philpem@0 1809 assign stall_a = (stall_f == `TRUE);
philpem@0 1810
philpem@0 1811 assign stall_f = (stall_d == `TRUE);
philpem@0 1812
philpem@0 1813 assign stall_d = (stall_x == `TRUE)
philpem@0 1814 || ( (interlock == `TRUE)
philpem@0 1815 && (kill_d == `FALSE)
philpem@0 1816 )
philpem@0 1817 || ( ( (eret_d == `TRUE)
philpem@0 1818 || (scall_d == `TRUE)
philpem@14 1819 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 1820 || (bus_error_d == `TRUE)
philpem@14 1821 `endif
philpem@0 1822 )
philpem@0 1823 && ( (load_q_x == `TRUE)
philpem@0 1824 || (load_q_m == `TRUE)
philpem@0 1825 || (store_q_x == `TRUE)
philpem@0 1826 || (store_q_m == `TRUE)
philpem@0 1827 || (D_CYC_O == `TRUE)
philpem@0 1828 )
philpem@0 1829 && (kill_d == `FALSE)
philpem@0 1830 )
philpem@0 1831 `ifdef CFG_DEBUG_ENABLED
philpem@0 1832 || ( ( (break_d == `TRUE)
philpem@0 1833 || (bret_d == `TRUE)
philpem@0 1834 )
philpem@0 1835 && ( (load_q_x == `TRUE)
philpem@0 1836 || (store_q_x == `TRUE)
philpem@0 1837 || (load_q_m == `TRUE)
philpem@0 1838 || (store_q_m == `TRUE)
philpem@0 1839 || (D_CYC_O == `TRUE)
philpem@0 1840 )
philpem@0 1841 && (kill_d == `FALSE)
philpem@0 1842 )
philpem@0 1843 `endif
philpem@0 1844 || ( (csr_write_enable_d == `TRUE)
philpem@0 1845 && (load_q_x == `TRUE)
philpem@0 1846 )
philpem@0 1847 ;
philpem@0 1848
philpem@0 1849 assign stall_x = (stall_m == `TRUE)
philpem@0 1850 `ifdef LM32_MC_ARITHMETIC_ENABLED
philpem@0 1851 || ( (mc_stall_request_x == `TRUE)
philpem@0 1852 && (kill_x == `FALSE)
philpem@0 1853 )
philpem@0 1854 `endif
philpem@0 1855 `ifdef CFG_IROM_ENABLED
philpem@0 1856 // Stall load/store instruction in D stage if there is an ongoing store
philpem@0 1857 // operation to instruction ROM in M stage
philpem@0 1858 || ( (irom_stall_request_x == `TRUE)
philpem@0 1859 && ( (load_d == `TRUE)
philpem@0 1860 || (store_d == `TRUE)
philpem@0 1861 )
philpem@0 1862 )
philpem@0 1863 `endif
philpem@0 1864 ;
philpem@0 1865
philpem@0 1866 assign stall_m = (stall_wb_load == `TRUE)
philpem@0 1867 `ifdef CFG_SIZE_OVER_SPEED
philpem@0 1868 || (D_CYC_O == `TRUE)
philpem@0 1869 `else
philpem@0 1870 || ( (D_CYC_O == `TRUE)
philpem@0 1871 && ( (store_m == `TRUE)
philpem@0 1872 /*
philpem@0 1873 Bug: Following loop does not allow interrupts to be services since
philpem@0 1874 either D_CYC_O or store_m is always high during entire duration of
philpem@0 1875 loop.
philpem@0 1876 L1: addi r1, r1, 1
philpem@0 1877 sw (r2,0), r1
philpem@0 1878 bi L1
philpem@0 1879
philpem@0 1880 Introduce a single-cycle stall when a wishbone cycle is in progress
philpem@0 1881 and a new store instruction is in Execute stage and a interrupt
philpem@0 1882 exception has occured. This stall will ensure that D_CYC_O and
philpem@0 1883 store_m will both be low for one cycle.
philpem@0 1884 */
philpem@0 1885 || ((store_x == `TRUE) && (interrupt_exception == `TRUE))
philpem@0 1886 || (load_m == `TRUE)
philpem@0 1887 || (load_x == `TRUE)
philpem@0 1888 )
philpem@0 1889 )
philpem@0 1890 `endif
philpem@0 1891 `ifdef CFG_DCACHE_ENABLED
philpem@0 1892 || (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 1893 `endif
philpem@0 1894 `ifdef CFG_ICACHE_ENABLED
philpem@0 1895 || (icache_stall_request == `TRUE) // Pipeline needs to be stalled otherwise branches may be lost
philpem@0 1896 || ((I_CYC_O == `TRUE) && ((branch_m == `TRUE) || (exception_m == `TRUE)))
philpem@0 1897 `else
philpem@0 1898 `ifdef CFG_IWB_ENABLED
philpem@0 1899 || (I_CYC_O == `TRUE)
philpem@0 1900 `endif
philpem@0 1901 `endif
philpem@0 1902 `ifdef CFG_USER_ENABLED
philpem@0 1903 || ( (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 1904 && (user_complete == `FALSE)
philpem@0 1905 )
philpem@0 1906 `endif
philpem@0 1907 ;
philpem@0 1908
philpem@0 1909 // Qualify state changing control signals
philpem@0 1910 `ifdef LM32_MC_ARITHMETIC_ENABLED
philpem@0 1911 assign q_d = (valid_d == `TRUE) && (kill_d == `FALSE);
philpem@0 1912 `endif
philpem@0 1913 `ifdef CFG_MC_BARREL_SHIFT_ENABLED
philpem@0 1914 assign shift_left_q_d = (shift_left_d == `TRUE) && (q_d == `TRUE);
philpem@0 1915 assign shift_right_q_d = (shift_right_d == `TRUE) && (q_d == `TRUE);
philpem@0 1916 `endif
philpem@0 1917 `ifdef CFG_MC_MULTIPLY_ENABLED
philpem@0 1918 assign multiply_q_d = (multiply_d == `TRUE) && (q_d == `TRUE);
philpem@0 1919 `endif
philpem@0 1920 `ifdef CFG_MC_DIVIDE_ENABLED
philpem@0 1921 assign divide_q_d = (divide_d == `TRUE) && (q_d == `TRUE);
philpem@0 1922 assign modulus_q_d = (modulus_d == `TRUE) && (q_d == `TRUE);
philpem@0 1923 `endif
philpem@0 1924 assign q_x = (valid_x == `TRUE) && (kill_x == `FALSE);
philpem@0 1925 assign csr_write_enable_q_x = (csr_write_enable_x == `TRUE) && (q_x == `TRUE);
philpem@0 1926 assign eret_q_x = (eret_x == `TRUE) && (q_x == `TRUE);
philpem@0 1927 `ifdef CFG_DEBUG_ENABLED
philpem@0 1928 assign bret_q_x = (bret_x == `TRUE) && (q_x == `TRUE);
philpem@0 1929 `endif
philpem@0 1930 assign load_q_x = (load_x == `TRUE)
philpem@0 1931 && (q_x == `TRUE)
philpem@0 1932 `ifdef CFG_DEBUG_ENABLED
philpem@0 1933 && (bp_match == `FALSE)
philpem@0 1934 `endif
philpem@0 1935 ;
philpem@0 1936 assign store_q_x = (store_x == `TRUE)
philpem@0 1937 && (q_x == `TRUE)
philpem@0 1938 `ifdef CFG_DEBUG_ENABLED
philpem@0 1939 && (bp_match == `FALSE)
philpem@0 1940 `endif
philpem@0 1941 ;
philpem@0 1942 `ifdef CFG_USER_ENABLED
philpem@0 1943 assign user_valid = (x_result_sel_user_x == `TRUE) && (q_x == `TRUE);
philpem@0 1944 `endif
philpem@0 1945 assign q_m = (valid_m == `TRUE) && (kill_m == `FALSE) && (exception_m == `FALSE);
philpem@0 1946 assign load_q_m = (load_m == `TRUE) && (q_m == `TRUE);
philpem@0 1947 assign store_q_m = (store_m == `TRUE) && (q_m == `TRUE);
philpem@0 1948 `ifdef CFG_DEBUG_ENABLED
philpem@0 1949 assign debug_exception_q_w = ((debug_exception_w == `TRUE) && (valid_w == `TRUE));
philpem@0 1950 assign non_debug_exception_q_w = ((non_debug_exception_w == `TRUE) && (valid_w == `TRUE));
philpem@0 1951 `else
philpem@0 1952 assign exception_q_w = ((exception_w == `TRUE) && (valid_w == `TRUE));
philpem@0 1953 `endif
philpem@0 1954 // 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 1955 assign write_enable_q_x = (write_enable_x == `TRUE) && (valid_x == `TRUE) && (branch_flushX_m == `FALSE);
philpem@0 1956 assign write_enable_q_m = (write_enable_m == `TRUE) && (valid_m == `TRUE);
philpem@0 1957 assign write_enable_q_w = (write_enable_w == `TRUE) && (valid_w == `TRUE);
philpem@0 1958 // The enable that actually does write the registers needs to be qualified with kill
philpem@0 1959 assign reg_write_enable_q_w = (write_enable_w == `TRUE) && (kill_w == `FALSE) && (valid_w == `TRUE);
philpem@0 1960
philpem@0 1961 // Configuration (CFG) CSR
philpem@0 1962 assign cfg = {
philpem@0 1963 `LM32_REVISION,
philpem@0 1964 watchpoints[3:0],
philpem@0 1965 breakpoints[3:0],
philpem@0 1966 interrupts[5:0],
philpem@0 1967 `ifdef CFG_JTAG_UART_ENABLED
philpem@0 1968 `TRUE,
philpem@0 1969 `else
philpem@0 1970 `FALSE,
philpem@0 1971 `endif
philpem@0 1972 `ifdef CFG_ROM_DEBUG_ENABLED
philpem@0 1973 `TRUE,
philpem@0 1974 `else
philpem@0 1975 `FALSE,
philpem@0 1976 `endif
philpem@0 1977 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 1978 `TRUE,
philpem@0 1979 `else
philpem@0 1980 `FALSE,
philpem@0 1981 `endif
philpem@0 1982 `ifdef CFG_DEBUG_ENABLED
philpem@0 1983 `TRUE,
philpem@0 1984 `else
philpem@0 1985 `FALSE,
philpem@0 1986 `endif
philpem@0 1987 `ifdef CFG_ICACHE_ENABLED
philpem@0 1988 `TRUE,
philpem@0 1989 `else
philpem@0 1990 `FALSE,
philpem@0 1991 `endif
philpem@0 1992 `ifdef CFG_DCACHE_ENABLED
philpem@0 1993 `TRUE,
philpem@0 1994 `else
philpem@0 1995 `FALSE,
philpem@0 1996 `endif
philpem@0 1997 `ifdef CFG_CYCLE_COUNTER_ENABLED
philpem@0 1998 `TRUE,
philpem@0 1999 `else
philpem@0 2000 `FALSE,
philpem@0 2001 `endif
philpem@0 2002 `ifdef CFG_USER_ENABLED
philpem@0 2003 `TRUE,
philpem@0 2004 `else
philpem@0 2005 `FALSE,
philpem@0 2006 `endif
philpem@0 2007 `ifdef CFG_SIGN_EXTEND_ENABLED
philpem@0 2008 `TRUE,
philpem@0 2009 `else
philpem@0 2010 `FALSE,
philpem@0 2011 `endif
philpem@0 2012 `ifdef LM32_BARREL_SHIFT_ENABLED
philpem@0 2013 `TRUE,
philpem@0 2014 `else
philpem@0 2015 `FALSE,
philpem@0 2016 `endif
philpem@0 2017 `ifdef CFG_MC_DIVIDE_ENABLED
philpem@0 2018 `TRUE,
philpem@0 2019 `else
philpem@0 2020 `FALSE,
philpem@0 2021 `endif
philpem@0 2022 `ifdef LM32_MULTIPLY_ENABLED
philpem@0 2023 `TRUE
philpem@0 2024 `else
philpem@0 2025 `FALSE
philpem@0 2026 `endif
philpem@0 2027 };
philpem@0 2028
philpem@0 2029 assign cfg2 = {
philpem@0 2030 30'b0,
philpem@0 2031 `ifdef CFG_IROM_ENABLED
philpem@0 2032 `TRUE,
philpem@0 2033 `else
philpem@0 2034 `FALSE,
philpem@0 2035 `endif
philpem@0 2036 `ifdef CFG_DRAM_ENABLED
philpem@0 2037 `TRUE
philpem@0 2038 `else
philpem@0 2039 `FALSE
philpem@0 2040 `endif
philpem@0 2041 };
philpem@0 2042
philpem@0 2043 // Cache flush
philpem@0 2044 `ifdef CFG_ICACHE_ENABLED
philpem@0 2045 assign iflush = (csr_write_enable_d == `TRUE)
philpem@0 2046 && (csr_d == `LM32_CSR_ICC)
philpem@0 2047 && (stall_d == `FALSE)
philpem@0 2048 && (kill_d == `FALSE)
philpem@0 2049 && (valid_d == `TRUE);
philpem@0 2050 `endif
philpem@0 2051 `ifdef CFG_DCACHE_ENABLED
philpem@0 2052 assign dflush_x = (csr_write_enable_q_x == `TRUE)
philpem@0 2053 && (csr_x == `LM32_CSR_DCC);
philpem@0 2054 `endif
philpem@0 2055
philpem@0 2056 // Extract CSR index
philpem@0 2057 assign csr_d = read_idx_0_d[`LM32_CSR_RNG];
philpem@0 2058
philpem@0 2059 // CSR reads
philpem@0 2060 always @(*)
philpem@0 2061 begin
philpem@0 2062 case (csr_x)
philpem@0 2063 `ifdef CFG_INTERRUPTS_ENABLED
philpem@0 2064 `LM32_CSR_IE,
philpem@0 2065 `LM32_CSR_IM,
philpem@0 2066 `LM32_CSR_IP: csr_read_data_x = interrupt_csr_read_data_x;
philpem@0 2067 `endif
philpem@0 2068 `ifdef CFG_CYCLE_COUNTER_ENABLED
philpem@0 2069 `LM32_CSR_CC: csr_read_data_x = cc;
philpem@0 2070 `endif
philpem@0 2071 `LM32_CSR_CFG: csr_read_data_x = cfg;
philpem@0 2072 `LM32_CSR_EBA: csr_read_data_x = {eba, 8'h00};
philpem@0 2073 `ifdef CFG_DEBUG_ENABLED
philpem@0 2074 `LM32_CSR_DEBA: csr_read_data_x = {deba, 8'h00};
philpem@0 2075 `endif
philpem@0 2076 `ifdef CFG_JTAG_UART_ENABLED
philpem@0 2077 `LM32_CSR_JTX: csr_read_data_x = jtx_csr_read_data;
philpem@0 2078 `LM32_CSR_JRX: csr_read_data_x = jrx_csr_read_data;
philpem@0 2079 `endif
philpem@0 2080 `LM32_CSR_CFG2: csr_read_data_x = cfg2;
philpem@0 2081
philpem@0 2082 default: csr_read_data_x = {`LM32_WORD_WIDTH{1'bx}};
philpem@0 2083 endcase
philpem@0 2084 end
philpem@0 2085
philpem@0 2086 /////////////////////////////////////////////////////
philpem@0 2087 // Sequential Logic
philpem@0 2088 /////////////////////////////////////////////////////
philpem@0 2089
philpem@0 2090 // Exception Base Address (EBA) CSR
philpem@0 2091 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 2092 begin
philpem@0 2093 if (rst_i == `TRUE)
philpem@0 2094 eba <= eba_reset[`LM32_PC_WIDTH+2-1:8];
philpem@0 2095 else
philpem@0 2096 begin
philpem@0 2097 if ((csr_write_enable_q_x == `TRUE) && (csr_x == `LM32_CSR_EBA) && (stall_x == `FALSE))
philpem@0 2098 eba <= operand_1_x[`LM32_PC_WIDTH+2-1:8];
philpem@0 2099 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 2100 if ((jtag_csr_write_enable == `TRUE) && (jtag_csr == `LM32_CSR_EBA))
philpem@0 2101 eba <= jtag_csr_write_data[`LM32_PC_WIDTH+2-1:8];
philpem@0 2102 `endif
philpem@0 2103 end
philpem@0 2104 end
philpem@0 2105
philpem@0 2106 `ifdef CFG_DEBUG_ENABLED
philpem@0 2107 // Debug Exception Base Address (DEBA) CSR
philpem@0 2108 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 2109 begin
philpem@0 2110 if (rst_i == `TRUE)
philpem@0 2111 deba <= deba_reset[`LM32_PC_WIDTH+2-1:8];
philpem@0 2112 else
philpem@0 2113 begin
philpem@0 2114 if ((csr_write_enable_q_x == `TRUE) && (csr_x == `LM32_CSR_DEBA) && (stall_x == `FALSE))
philpem@0 2115 deba <= operand_1_x[`LM32_PC_WIDTH+2-1:8];
philpem@0 2116 `ifdef CFG_HW_DEBUG_ENABLED
philpem@0 2117 if ((jtag_csr_write_enable == `TRUE) && (jtag_csr == `LM32_CSR_DEBA))
philpem@0 2118 deba <= jtag_csr_write_data[`LM32_PC_WIDTH+2-1:8];
philpem@0 2119 `endif
philpem@0 2120 end
philpem@0 2121 end
philpem@0 2122 `endif
philpem@0 2123
philpem@0 2124 // Cycle Counter (CC) CSR
philpem@0 2125 `ifdef CFG_CYCLE_COUNTER_ENABLED
philpem@0 2126 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 2127 begin
philpem@0 2128 if (rst_i == `TRUE)
philpem@0 2129 cc <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2130 else
philpem@0 2131 cc <= cc + 1'b1;
philpem@0 2132 end
philpem@0 2133 `endif
philpem@0 2134
philpem@0 2135 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 2136 // Watch for data bus errors
philpem@0 2137 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 2138 begin
philpem@0 2139 if (rst_i == `TRUE)
philpem@0 2140 data_bus_error_seen <= `FALSE;
philpem@0 2141 else
philpem@0 2142 begin
philpem@0 2143 // Set flag when bus error is detected
philpem@0 2144 if ((D_ERR_I == `TRUE) && (D_CYC_O == `TRUE))
philpem@0 2145 data_bus_error_seen <= `TRUE;
philpem@0 2146 // Clear flag when exception is taken
philpem@0 2147 if ((exception_m == `TRUE) && (kill_m == `FALSE))
philpem@0 2148 data_bus_error_seen <= `FALSE;
philpem@0 2149 end
philpem@0 2150 end
philpem@0 2151 `endif
philpem@0 2152
philpem@0 2153 // Valid bits to indicate whether an instruction in a partcular pipeline stage is valid or not
philpem@0 2154
philpem@0 2155 `ifdef CFG_ICACHE_ENABLED
philpem@0 2156 `ifdef CFG_DCACHE_ENABLED
philpem@0 2157 always @(*)
philpem@0 2158 begin
philpem@0 2159 if ( (icache_refill_request == `TRUE)
philpem@0 2160 || (dcache_refill_request == `TRUE)
philpem@0 2161 )
philpem@0 2162 valid_a = `FALSE;
philpem@0 2163 else if ( (icache_restart_request == `TRUE)
philpem@0 2164 || (dcache_restart_request == `TRUE)
philpem@0 2165 )
philpem@0 2166 valid_a = `TRUE;
philpem@0 2167 else
philpem@0 2168 valid_a = !icache_refilling && !dcache_refilling;
philpem@0 2169 end
philpem@0 2170 `else
philpem@0 2171 always @(*)
philpem@0 2172 begin
philpem@0 2173 if (icache_refill_request == `TRUE)
philpem@0 2174 valid_a = `FALSE;
philpem@0 2175 else if (icache_restart_request == `TRUE)
philpem@0 2176 valid_a = `TRUE;
philpem@0 2177 else
philpem@0 2178 valid_a = !icache_refilling;
philpem@0 2179 end
philpem@0 2180 `endif
philpem@0 2181 `else
philpem@0 2182 `ifdef CFG_DCACHE_ENABLED
philpem@0 2183 always @(*)
philpem@0 2184 begin
philpem@0 2185 if (dcache_refill_request == `TRUE)
philpem@0 2186 valid_a = `FALSE;
philpem@0 2187 else if (dcache_restart_request == `TRUE)
philpem@0 2188 valid_a = `TRUE;
philpem@0 2189 else
philpem@0 2190 valid_a = !dcache_refilling;
philpem@0 2191 end
philpem@0 2192 `endif
philpem@0 2193 `endif
philpem@0 2194
philpem@0 2195 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 2196 begin
philpem@0 2197 if (rst_i == `TRUE)
philpem@0 2198 begin
philpem@0 2199 valid_f <= `FALSE;
philpem@0 2200 valid_d <= `FALSE;
philpem@0 2201 valid_x <= `FALSE;
philpem@0 2202 valid_m <= `FALSE;
philpem@0 2203 valid_w <= `FALSE;
philpem@0 2204 end
philpem@0 2205 else
philpem@0 2206 begin
philpem@0 2207 if ((kill_f == `TRUE) || (stall_a == `FALSE))
philpem@0 2208 `ifdef LM32_CACHE_ENABLED
philpem@0 2209 valid_f <= valid_a;
philpem@0 2210 `else
philpem@0 2211 valid_f <= `TRUE;
philpem@0 2212 `endif
philpem@0 2213 else if (stall_f == `FALSE)
philpem@0 2214 valid_f <= `FALSE;
philpem@0 2215
philpem@0 2216 if (kill_d == `TRUE)
philpem@0 2217 valid_d <= `FALSE;
philpem@0 2218 else if (stall_f == `FALSE)
philpem@0 2219 valid_d <= valid_f & !kill_f;
philpem@0 2220 else if (stall_d == `FALSE)
philpem@0 2221 valid_d <= `FALSE;
philpem@0 2222
philpem@0 2223 if (stall_d == `FALSE)
philpem@0 2224 valid_x <= valid_d & !kill_d;
philpem@0 2225 else if (kill_x == `TRUE)
philpem@0 2226 valid_x <= `FALSE;
philpem@0 2227 else if (stall_x == `FALSE)
philpem@0 2228 valid_x <= `FALSE;
philpem@0 2229
philpem@0 2230 if (kill_m == `TRUE)
philpem@0 2231 valid_m <= `FALSE;
philpem@0 2232 else if (stall_x == `FALSE)
philpem@0 2233 valid_m <= valid_x & !kill_x;
philpem@0 2234 else if (stall_m == `FALSE)
philpem@0 2235 valid_m <= `FALSE;
philpem@0 2236
philpem@0 2237 if (stall_m == `FALSE)
philpem@0 2238 valid_w <= valid_m & !kill_m;
philpem@0 2239 else
philpem@0 2240 valid_w <= `FALSE;
philpem@0 2241 end
philpem@0 2242 end
philpem@0 2243
philpem@0 2244 // Microcode pipeline registers
philpem@0 2245 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 2246 begin
philpem@0 2247 if (rst_i == `TRUE)
philpem@0 2248 begin
philpem@0 2249 `ifdef CFG_USER_ENABLED
philpem@0 2250 user_opcode <= {`LM32_USER_OPCODE_WIDTH{1'b0}};
philpem@0 2251 `endif
philpem@0 2252 operand_0_x <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2253 operand_1_x <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2254 store_operand_x <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2255 branch_target_x <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2256 x_result_sel_csr_x <= `FALSE;
philpem@0 2257 `ifdef LM32_MC_ARITHMETIC_ENABLED
philpem@0 2258 x_result_sel_mc_arith_x <= `FALSE;
philpem@0 2259 `endif
philpem@0 2260 `ifdef LM32_NO_BARREL_SHIFT
philpem@0 2261 x_result_sel_shift_x <= `FALSE;
philpem@0 2262 `endif
philpem@0 2263 `ifdef CFG_SIGN_EXTEND_ENABLED
philpem@0 2264 x_result_sel_sext_x <= `FALSE;
philpem@8 2265 `endif
philpem@8 2266 x_result_sel_logic_x <= `FALSE;
philpem@0 2267 `ifdef CFG_USER_ENABLED
philpem@0 2268 x_result_sel_user_x <= `FALSE;
philpem@0 2269 `endif
philpem@0 2270 x_result_sel_add_x <= `FALSE;
philpem@0 2271 m_result_sel_compare_x <= `FALSE;
philpem@0 2272 `ifdef CFG_PL_BARREL_SHIFT_ENABLED
philpem@0 2273 m_result_sel_shift_x <= `FALSE;
philpem@0 2274 `endif
philpem@0 2275 w_result_sel_load_x <= `FALSE;
philpem@0 2276 `ifdef CFG_PL_MULTIPLY_ENABLED
philpem@0 2277 w_result_sel_mul_x <= `FALSE;
philpem@0 2278 `endif
philpem@0 2279 x_bypass_enable_x <= `FALSE;
philpem@0 2280 m_bypass_enable_x <= `FALSE;
philpem@0 2281 write_enable_x <= `FALSE;
philpem@0 2282 write_idx_x <= {`LM32_REG_IDX_WIDTH{1'b0}};
philpem@0 2283 csr_x <= {`LM32_CSR_WIDTH{1'b0}};
philpem@0 2284 load_x <= `FALSE;
philpem@0 2285 store_x <= `FALSE;
philpem@0 2286 size_x <= {`LM32_SIZE_WIDTH{1'b0}};
philpem@0 2287 sign_extend_x <= `FALSE;
philpem@0 2288 adder_op_x <= `FALSE;
philpem@0 2289 adder_op_x_n <= `FALSE;
philpem@0 2290 logic_op_x <= 4'h0;
philpem@0 2291 `ifdef CFG_PL_BARREL_SHIFT_ENABLED
philpem@0 2292 direction_x <= `FALSE;
philpem@0 2293 `endif
philpem@0 2294 `ifdef CFG_ROTATE_ENABLED
philpem@0 2295 rotate_x <= `FALSE;
philpem@0 2296
philpem@0 2297 `endif
philpem@0 2298 branch_x <= `FALSE;
philpem@0 2299 branch_predict_x <= `FALSE;
philpem@0 2300 branch_predict_taken_x <= `FALSE;
philpem@0 2301 condition_x <= `LM32_CONDITION_U1;
philpem@0 2302 `ifdef CFG_DEBUG_ENABLED
philpem@0 2303 break_x <= `FALSE;
philpem@0 2304 `endif
philpem@0 2305 scall_x <= `FALSE;
philpem@0 2306 eret_x <= `FALSE;
philpem@0 2307 `ifdef CFG_DEBUG_ENABLED
philpem@0 2308 bret_x <= `FALSE;
philpem@0 2309 `endif
philpem@0 2310 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 2311 bus_error_x <= `FALSE;
philpem@0 2312 data_bus_error_exception_m <= `FALSE;
philpem@0 2313 `endif
philpem@0 2314 csr_write_enable_x <= `FALSE;
philpem@0 2315 operand_m <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2316 branch_target_m <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2317 m_result_sel_compare_m <= `FALSE;
philpem@0 2318 `ifdef CFG_PL_BARREL_SHIFT_ENABLED
philpem@0 2319 m_result_sel_shift_m <= `FALSE;
philpem@0 2320 `endif
philpem@0 2321 w_result_sel_load_m <= `FALSE;
philpem@0 2322 `ifdef CFG_PL_MULTIPLY_ENABLED
philpem@0 2323 w_result_sel_mul_m <= `FALSE;
philpem@0 2324 `endif
philpem@0 2325 m_bypass_enable_m <= `FALSE;
philpem@0 2326 branch_m <= `FALSE;
philpem@0 2327 branch_predict_m <= `FALSE;
philpem@0 2328 branch_predict_taken_m <= `FALSE;
philpem@0 2329 exception_m <= `FALSE;
philpem@0 2330 load_m <= `FALSE;
philpem@0 2331 store_m <= `FALSE;
philpem@0 2332 write_enable_m <= `FALSE;
philpem@0 2333 write_idx_m <= {`LM32_REG_IDX_WIDTH{1'b0}};
philpem@0 2334 condition_met_m <= `FALSE;
philpem@0 2335 `ifdef CFG_DCACHE_ENABLED
philpem@0 2336 dflush_m <= `FALSE;
philpem@0 2337 `endif
philpem@0 2338 `ifdef CFG_DEBUG_ENABLED
philpem@0 2339 debug_exception_m <= `FALSE;
philpem@0 2340 non_debug_exception_m <= `FALSE;
philpem@0 2341 `endif
philpem@0 2342 operand_w <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2343 w_result_sel_load_w <= `FALSE;
philpem@0 2344 `ifdef CFG_PL_MULTIPLY_ENABLED
philpem@0 2345 w_result_sel_mul_w <= `FALSE;
philpem@0 2346 `endif
philpem@0 2347 write_idx_w <= {`LM32_REG_IDX_WIDTH{1'b0}};
philpem@0 2348 write_enable_w <= `FALSE;
philpem@0 2349 `ifdef CFG_DEBUG_ENABLED
philpem@0 2350 debug_exception_w <= `FALSE;
philpem@0 2351 non_debug_exception_w <= `FALSE;
philpem@0 2352 `else
philpem@0 2353 exception_w <= `FALSE;
philpem@0 2354 `endif
philpem@0 2355 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 2356 memop_pc_w <= {`LM32_PC_WIDTH{1'b0}};
philpem@0 2357 `endif
philpem@0 2358 end
philpem@0 2359 else
philpem@0 2360 begin
philpem@0 2361 // D/X stage registers
philpem@0 2362
philpem@0 2363 if (stall_x == `FALSE)
philpem@0 2364 begin
philpem@0 2365 `ifdef CFG_USER_ENABLED
philpem@0 2366 user_opcode <= user_opcode_d;
philpem@0 2367 `endif
philpem@0 2368 operand_0_x <= d_result_0;
philpem@0 2369 operand_1_x <= d_result_1;
philpem@0 2370 store_operand_x <= bypass_data_1;
philpem@0 2371 branch_target_x <= branch_reg_d == `TRUE ? bypass_data_0[`LM32_PC_RNG] : branch_target_d;
philpem@0 2372 x_result_sel_csr_x <= x_result_sel_csr_d;
philpem@0 2373 `ifdef LM32_MC_ARITHMETIC_ENABLED
philpem@0 2374 x_result_sel_mc_arith_x <= x_result_sel_mc_arith_d;
philpem@0 2375 `endif
philpem@0 2376 `ifdef LM32_NO_BARREL_SHIFT
philpem@0 2377 x_result_sel_shift_x <= x_result_sel_shift_d;
philpem@0 2378 `endif
philpem@0 2379 `ifdef CFG_SIGN_EXTEND_ENABLED
philpem@0 2380 x_result_sel_sext_x <= x_result_sel_sext_d;
philpem@0 2381 `endif
philpem@8 2382 x_result_sel_logic_x <= x_result_sel_logic_d;
philpem@0 2383 `ifdef CFG_USER_ENABLED
philpem@0 2384 x_result_sel_user_x <= x_result_sel_user_d;
philpem@0 2385 `endif
philpem@0 2386 x_result_sel_add_x <= x_result_sel_add_d;
philpem@0 2387 m_result_sel_compare_x <= m_result_sel_compare_d;
philpem@0 2388 `ifdef CFG_PL_BARREL_SHIFT_ENABLED
philpem@0 2389 m_result_sel_shift_x <= m_result_sel_shift_d;
philpem@0 2390 `endif
philpem@0 2391 w_result_sel_load_x <= w_result_sel_load_d;
philpem@0 2392 `ifdef CFG_PL_MULTIPLY_ENABLED
philpem@0 2393 w_result_sel_mul_x <= w_result_sel_mul_d;
philpem@0 2394 `endif
philpem@0 2395 x_bypass_enable_x <= x_bypass_enable_d;
philpem@0 2396 m_bypass_enable_x <= m_bypass_enable_d;
philpem@0 2397 load_x <= load_d;
philpem@0 2398 store_x <= store_d;
philpem@0 2399 branch_x <= branch_d;
philpem@0 2400 branch_predict_x <= branch_predict_d;
philpem@0 2401 branch_predict_taken_x <= branch_predict_taken_d;
philpem@0 2402 write_idx_x <= write_idx_d;
philpem@0 2403 csr_x <= csr_d;
philpem@0 2404 size_x <= size_d;
philpem@0 2405 sign_extend_x <= sign_extend_d;
philpem@0 2406 adder_op_x <= adder_op_d;
philpem@0 2407 adder_op_x_n <= ~adder_op_d;
philpem@0 2408 logic_op_x <= logic_op_d;
philpem@0 2409 `ifdef CFG_PL_BARREL_SHIFT_ENABLED
philpem@0 2410 direction_x <= direction_d;
philpem@0 2411 `endif
philpem@0 2412 `ifdef CFG_ROTATE_ENABLED
philpem@0 2413 rotate_x <= rotate_d;
philpem@0 2414 `endif
philpem@0 2415 condition_x <= condition_d;
philpem@0 2416 csr_write_enable_x <= csr_write_enable_d;
philpem@0 2417 `ifdef CFG_DEBUG_ENABLED
philpem@0 2418 break_x <= break_d;
philpem@0 2419 `endif
philpem@0 2420 scall_x <= scall_d;
philpem@0 2421 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 2422 bus_error_x <= bus_error_d;
philpem@0 2423 `endif
philpem@0 2424 eret_x <= eret_d;
philpem@0 2425 `ifdef CFG_DEBUG_ENABLED
philpem@0 2426 bret_x <= bret_d;
philpem@0 2427 `endif
philpem@0 2428 write_enable_x <= write_enable_d;
philpem@0 2429 end
philpem@0 2430
philpem@0 2431 // X/M stage registers
philpem@0 2432
philpem@0 2433 if (stall_m == `FALSE)
philpem@0 2434 begin
philpem@0 2435 operand_m <= x_result;
philpem@0 2436 m_result_sel_compare_m <= m_result_sel_compare_x;
philpem@0 2437 `ifdef CFG_PL_BARREL_SHIFT_ENABLED
philpem@0 2438 m_result_sel_shift_m <= m_result_sel_shift_x;
philpem@0 2439 `endif
philpem@0 2440 if (exception_x == `TRUE)
philpem@0 2441 begin
philpem@0 2442 w_result_sel_load_m <= `FALSE;
philpem@0 2443 `ifdef CFG_PL_MULTIPLY_ENABLED
philpem@0 2444 w_result_sel_mul_m <= `FALSE;
philpem@0 2445 `endif
philpem@0 2446 end
philpem@0 2447 else
philpem@0 2448 begin
philpem@0 2449 w_result_sel_load_m <= w_result_sel_load_x;
philpem@0 2450 `ifdef CFG_PL_MULTIPLY_ENABLED
philpem@0 2451 w_result_sel_mul_m <= w_result_sel_mul_x;
philpem@0 2452 `endif
philpem@0 2453 end
philpem@0 2454 m_bypass_enable_m <= m_bypass_enable_x;
philpem@0 2455 `ifdef CFG_PL_BARREL_SHIFT_ENABLED
philpem@0 2456 `endif
philpem@0 2457 load_m <= load_x;
philpem@0 2458 store_m <= store_x;
philpem@0 2459 `ifdef CFG_FAST_UNCONDITIONAL_BRANCH
philpem@0 2460 branch_m <= branch_x && !branch_taken_x;
philpem@0 2461 `else
philpem@0 2462 branch_m <= branch_x;
philpem@0 2463 branch_predict_m <= branch_predict_x;
philpem@0 2464 branch_predict_taken_m <= branch_predict_taken_x;
philpem@0 2465 `endif
philpem@0 2466 `ifdef CFG_DEBUG_ENABLED
philpem@0 2467 // Data bus errors are generated by the wishbone and are
philpem@0 2468 // made known to the processor only in next cycle (as a
philpem@0 2469 // non-debug exception). A break instruction can be seen
philpem@0 2470 // in same cycle (causing a debug exception). Handle non
philpem@0 2471 // -debug exception first!
philpem@0 2472 if (non_debug_exception_x == `TRUE)
philpem@0 2473 write_idx_m <= `LM32_EA_REG;
philpem@0 2474 else if (debug_exception_x == `TRUE)
philpem@0 2475 write_idx_m <= `LM32_BA_REG;
philpem@0 2476 else
philpem@0 2477 write_idx_m <= write_idx_x;
philpem@0 2478 `else
philpem@0 2479 if (exception_x == `TRUE)
philpem@0 2480 write_idx_m <= `LM32_EA_REG;
philpem@0 2481 else
philpem@0 2482 write_idx_m <= write_idx_x;
philpem@0 2483 `endif
philpem@0 2484 condition_met_m <= condition_met_x;
philpem@0 2485 `ifdef CFG_DEBUG_ENABLED
philpem@0 2486 if (exception_x == `TRUE)
philpem@0 2487 if ((dc_re == `TRUE)
philpem@0 2488 || ((debug_exception_x == `TRUE)
philpem@0 2489 && (non_debug_exception_x == `FALSE)))
philpem@0 2490 branch_target_m <= {deba, eid_x, {3{1'b0}}};
philpem@0 2491 else
philpem@0 2492 branch_target_m <= {eba, eid_x, {3{1'b0}}};
philpem@0 2493 else
philpem@0 2494 branch_target_m <= branch_target_x;
philpem@0 2495 `else
philpem@0 2496 branch_target_m <= exception_x == `TRUE ? {eba, eid_x, {3{1'b0}}} : branch_target_x;
philpem@0 2497 `endif
philpem@0 2498 `ifdef CFG_TRACE_ENABLED
philpem@0 2499 eid_m <= eid_x;
philpem@0 2500 `endif
philpem@0 2501 `ifdef CFG_DCACHE_ENABLED
philpem@0 2502 dflush_m <= dflush_x;
philpem@0 2503 `endif
philpem@0 2504 eret_m <= eret_q_x;
philpem@0 2505 `ifdef CFG_DEBUG_ENABLED
philpem@0 2506 bret_m <= bret_q_x;
philpem@0 2507 `endif
philpem@0 2508 write_enable_m <= exception_x == `TRUE ? `TRUE : write_enable_x;
philpem@0 2509 `ifdef CFG_DEBUG_ENABLED
philpem@0 2510 debug_exception_m <= debug_exception_x;
philpem@0 2511 non_debug_exception_m <= non_debug_exception_x;
philpem@0 2512 `endif
philpem@0 2513 end
philpem@0 2514
philpem@0 2515 // State changing regs
philpem@0 2516 if (stall_m == `FALSE)
philpem@0 2517 begin
philpem@0 2518 if ((exception_x == `TRUE) && (q_x == `TRUE) && (stall_x == `FALSE))
philpem@0 2519 exception_m <= `TRUE;
philpem@0 2520 else
philpem@0 2521 exception_m <= `FALSE;
philpem@0 2522 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 2523 data_bus_error_exception_m <= (data_bus_error_exception == `TRUE)
philpem@0 2524 `ifdef CFG_DEBUG_ENABLED
philpem@0 2525 && (reset_exception == `FALSE)
philpem@0 2526 `endif
philpem@0 2527 ;
philpem@0 2528 `endif
philpem@0 2529 end
philpem@0 2530
philpem@0 2531 // M/W stage registers
philpem@0 2532 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 2533 operand_w <= exception_m == `TRUE ? (data_bus_error_exception_m ? {memop_pc_w, 2'b00} : {pc_m, 2'b00}) : m_result;
philpem@0 2534 `else
philpem@0 2535 operand_w <= exception_m == `TRUE ? {pc_m, 2'b00} : m_result;
philpem@0 2536 `endif
philpem@0 2537 w_result_sel_load_w <= w_result_sel_load_m;
philpem@0 2538 `ifdef CFG_PL_MULTIPLY_ENABLED
philpem@0 2539 w_result_sel_mul_w <= w_result_sel_mul_m;
philpem@0 2540 `endif
philpem@0 2541 write_idx_w <= write_idx_m;
philpem@0 2542 `ifdef CFG_TRACE_ENABLED
philpem@0 2543 eid_w <= eid_m;
philpem@0 2544 eret_w <= eret_m;
philpem@0 2545 `ifdef CFG_DEBUG_ENABLED
philpem@0 2546 bret_w <= bret_m;
philpem@0 2547 `endif
philpem@0 2548 `endif
philpem@0 2549 write_enable_w <= write_enable_m;
philpem@0 2550 `ifdef CFG_DEBUG_ENABLED
philpem@0 2551 debug_exception_w <= debug_exception_m;
philpem@0 2552 non_debug_exception_w <= non_debug_exception_m;
philpem@0 2553 `else
philpem@0 2554 exception_w <= exception_m;
philpem@0 2555 `endif
philpem@0 2556 `ifdef CFG_BUS_ERRORS_ENABLED
philpem@0 2557 if ( (stall_m == `FALSE)
philpem@0 2558 && ( (load_q_m == `TRUE)
philpem@0 2559 || (store_q_m == `TRUE)
philpem@0 2560 )
philpem@0 2561 )
philpem@0 2562 memop_pc_w <= pc_m;
philpem@0 2563 `endif
philpem@0 2564 end
philpem@0 2565 end
philpem@0 2566
philpem@0 2567 `ifdef CFG_EBR_POSEDGE_REGISTER_FILE
philpem@0 2568 // Buffer data read from register file, in case a stall occurs, and watch for
philpem@0 2569 // any writes to the modified registers
philpem@0 2570 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 2571 begin
philpem@0 2572 if (rst_i == `TRUE)
philpem@0 2573 begin
philpem@0 2574 use_buf <= `FALSE;
philpem@0 2575 reg_data_buf_0 <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2576 reg_data_buf_1 <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2577 end
philpem@0 2578 else
philpem@0 2579 begin
philpem@0 2580 if (stall_d == `FALSE)
philpem@0 2581 use_buf <= `FALSE;
philpem@0 2582 else if (use_buf == `FALSE)
philpem@0 2583 begin
philpem@0 2584 reg_data_buf_0 <= reg_data_live_0;
philpem@0 2585 reg_data_buf_1 <= reg_data_live_1;
philpem@0 2586 use_buf <= `TRUE;
philpem@0 2587 end
philpem@0 2588 if (reg_write_enable_q_w == `TRUE)
philpem@0 2589 begin
philpem@0 2590 if (write_idx_w == read_idx_0_d)
philpem@0 2591 reg_data_buf_0 <= w_result;
philpem@0 2592 if (write_idx_w == read_idx_1_d)
philpem@0 2593 reg_data_buf_1 <= w_result;
philpem@0 2594 end
philpem@0 2595 end
philpem@0 2596 end
philpem@0 2597 `endif
philpem@0 2598
philpem@0 2599 `ifdef LM32_EBR_REGISTER_FILE
philpem@0 2600 `else
philpem@0 2601 // Register file write port
philpem@0 2602 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 2603 begin
philpem@0 2604 if (rst_i == `TRUE) begin
philpem@0 2605 registers[0] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2606 registers[1] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2607 registers[2] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2608 registers[3] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2609 registers[4] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2610 registers[5] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2611 registers[6] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2612 registers[7] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2613 registers[8] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2614 registers[9] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2615 registers[10] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2616 registers[11] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2617 registers[12] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2618 registers[13] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2619 registers[14] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2620 registers[15] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2621 registers[16] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2622 registers[17] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2623 registers[18] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2624 registers[19] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2625 registers[20] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2626 registers[21] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2627 registers[22] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2628 registers[23] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2629 registers[24] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2630 registers[25] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2631 registers[26] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2632 registers[27] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2633 registers[28] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2634 registers[29] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2635 registers[30] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2636 registers[31] <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2637 end
philpem@0 2638 else begin
philpem@0 2639 if (reg_write_enable_q_w == `TRUE)
philpem@0 2640 registers[write_idx_w] <= w_result;
philpem@0 2641 end
philpem@0 2642 end
philpem@0 2643 `endif
philpem@0 2644
philpem@0 2645 `ifdef CFG_TRACE_ENABLED
philpem@0 2646 // PC tracing logic
philpem@0 2647 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 2648 begin
philpem@0 2649 if (rst_i == `TRUE)
philpem@0 2650 begin
philpem@0 2651 trace_pc_valid <= `FALSE;
philpem@0 2652 trace_pc <= {`LM32_PC_WIDTH{1'b0}};
philpem@0 2653 trace_exception <= `FALSE;
philpem@0 2654 trace_eid <= `LM32_EID_RESET;
philpem@0 2655 trace_eret <= `FALSE;
philpem@0 2656 `ifdef CFG_DEBUG_ENABLED
philpem@0 2657 trace_bret <= `FALSE;
philpem@0 2658 `endif
philpem@0 2659 pc_c <= `CFG_EBA_RESET/4;
philpem@0 2660 end
philpem@0 2661 else
philpem@0 2662 begin
philpem@0 2663 trace_pc_valid <= `FALSE;
philpem@0 2664 // Has an exception occured
philpem@0 2665 `ifdef CFG_DEBUG_ENABLED
philpem@0 2666 if ((debug_exception_q_w == `TRUE) || (non_debug_exception_q_w == `TRUE))
philpem@0 2667 `else
philpem@0 2668 if (exception_q_w == `TRUE)
philpem@0 2669 `endif
philpem@0 2670 begin
philpem@0 2671 trace_exception <= `TRUE;
philpem@0 2672 trace_pc_valid <= `TRUE;
philpem@0 2673 trace_pc <= pc_w;
philpem@0 2674 trace_eid <= eid_w;
philpem@0 2675 end
philpem@0 2676 else
philpem@0 2677 trace_exception <= `FALSE;
philpem@0 2678
philpem@0 2679 if ((valid_w == `TRUE) && (!kill_w))
philpem@0 2680 begin
philpem@0 2681 // An instruction is commiting. Determine if it is non-sequential
philpem@0 2682 if (pc_c + 1'b1 != pc_w)
philpem@0 2683 begin
philpem@0 2684 // Non-sequential instruction
philpem@0 2685 trace_pc_valid <= `TRUE;
philpem@0 2686 trace_pc <= pc_w;
philpem@0 2687 end
philpem@0 2688 // Record PC so we can determine if next instruction is sequential or not
philpem@0 2689 pc_c <= pc_w;
philpem@0 2690 // Indicate if it was an eret/bret instruction
philpem@0 2691 trace_eret <= eret_w;
philpem@0 2692 `ifdef CFG_DEBUG_ENABLED
philpem@0 2693 trace_bret <= bret_w;
philpem@0 2694 `endif
philpem@0 2695 end
philpem@0 2696 else
philpem@0 2697 begin
philpem@0 2698 trace_eret <= `FALSE;
philpem@0 2699 `ifdef CFG_DEBUG_ENABLED
philpem@0 2700 trace_bret <= `FALSE;
philpem@0 2701 `endif
philpem@0 2702 end
philpem@0 2703 end
philpem@0 2704 end
philpem@0 2705 `endif
philpem@0 2706
philpem@0 2707 /////////////////////////////////////////////////////
philpem@0 2708 // Behavioural Logic
philpem@0 2709 /////////////////////////////////////////////////////
philpem@0 2710
philpem@0 2711 // synthesis translate_off
philpem@0 2712
philpem@0 2713 // Reset register 0. Only needed for simulation.
philpem@0 2714 initial
philpem@0 2715 begin
philpem@0 2716 `ifdef LM32_EBR_REGISTER_FILE
philpem@0 2717 reg_0.mem[0] = {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2718 reg_1.mem[0] = {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2719 `else
philpem@0 2720 registers[0] = {`LM32_WORD_WIDTH{1'b0}};
philpem@0 2721 `endif
philpem@0 2722 end
philpem@0 2723
philpem@0 2724 // synthesis translate_on
philpem@0 2725
philpem@0 2726 endmodule