lm32_cpu.v

Sun, 04 Apr 2010 22:05:07 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Sun, 04 Apr 2010 22:05:07 +0100
changeset 3
b153470d41c5
parent 0
cd0b58aa6f83
child 8
07be9df9fee8
permissions
-rw-r--r--

remove more Lattice-specific fluff

Code now synthesizes properly on Altera Quartus 9.0 build 235

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