lm32_cpu.v

Mon, 05 Apr 2010 21:00:31 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Mon, 05 Apr 2010 21:00:31 +0100
changeset 6
a8e459b24c31
parent 0
cd0b58aa6f83
child 8
07be9df9fee8
permissions
-rw-r--r--

reduce size of caches to fit in DE1 FPGA

The default cache size makes the Icache and Dcache "just a bit" too big to
fit in the EP2C20 FPGA on the DE1 board. This commit reduces the Icache and
Dcache sizes to the defaults shown in the LatticeMico32 Processor Reference
Manual (pages 36 and 37).

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