Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

lm32: use submodule

  • Loading branch information...
commit 43343b131f4cc1e7ea910a89f67c8633daa2bd2c 1 parent 0caac22
@sbourdeauducq sbourdeauducq authored
View
3  .gitmodules
@@ -0,0 +1,3 @@
+[submodule "verilog/lm32/submodule"]
+ path = verilog/lm32/submodule
+ url = git://github.com/milkymist/lm32.git
View
5 build.py
@@ -49,13 +49,14 @@ def main():
# add Verilog sources
for d in ["generic", "m1crg", "s6ddrphy", "minimac3"]:
plat.add_source_dir(os.path.join("verilog", d))
- plat.add_sources(os.path.join("verilog", "lm32"),
+ plat.add_sources(os.path.join("verilog", "lm32", "submodule", "rtl"),
"lm32_cpu.v", "lm32_instruction_unit.v", "lm32_decoder.v",
"lm32_load_store_unit.v", "lm32_adder.v", "lm32_addsub.v", "lm32_logic_op.v",
- "lm32_shifter.v", "lm32_multiplier_spartan6.v", "lm32_mc_arithmetic.v",
+ "lm32_shifter.v", "lm32_multiplier.v", "lm32_mc_arithmetic.v",
"lm32_interrupt.v", "lm32_ram.v", "lm32_dp_ram.v", "lm32_icache.v",
"lm32_dcache.v", "lm32_top.v", "lm32_debug.v", "lm32_jtag.v", "jtag_cores.v",
"jtag_tap_spartan6.v")
+ plat.add_sources(os.path.join("verilog", "lm32"), "lm32_config.v")
plat.build_cmdline(soc.get_fragment(), clock_domains=soc.crg.get_clock_domains())
View
86 verilog/lm32/jtag_cores.v
@@ -1,86 +0,0 @@
-/*
- * Milkymist SoC
- * Copyright (c) 2010 Michael Walle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-module jtag_cores (
- input [7:0] reg_d,
- input [2:0] reg_addr_d,
- output reg_update,
- output [7:0] reg_q,
- output [2:0] reg_addr_q,
- output jtck,
- output jrstn
-);
-
-wire tck;
-wire tdi;
-wire tdo;
-wire shift;
-wire update;
-wire reset;
-
-jtag_tap jtag_tap (
- .tck(tck),
- .tdi(tdi),
- .tdo(tdo),
- .shift(shift),
- .update(update),
- .reset(reset)
-);
-
-reg [10:0] jtag_shift;
-reg [10:0] jtag_latched;
-
-always @(posedge tck or posedge reset)
-begin
- if(reset)
- jtag_shift <= 11'b0;
- else begin
- if(shift)
- jtag_shift <= {tdi, jtag_shift[10:1]};
- else
- jtag_shift <= {reg_d, reg_addr_d};
- end
-end
-
-assign tdo = jtag_shift[0];
-
-always @(posedge reg_update or posedge reset)
-begin
- if(reset)
- jtag_latched <= 11'b0;
- else
- jtag_latched <= jtag_shift;
-end
-
-assign reg_update = update;
-assign reg_q = jtag_latched[10:3];
-assign reg_addr_q = jtag_latched[2:0];
-assign jtck = tck;
-assign jrstn = ~reset;
-
-endmodule
View
60 verilog/lm32/jtag_tap_spartan6.v
@@ -1,60 +0,0 @@
-/*
- * Milkymist SoC
- * Copyright (c) 2010 Michael Walle
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-module jtag_tap(
- output tck,
- output tdi,
- input tdo,
- output shift,
- output update,
- output reset
-);
-
-wire g_shift;
-wire g_update;
-
-assign shift = g_shift & sel;
-assign update = g_update & sel;
-
-BSCAN_SPARTAN6 #(
- .JTAG_CHAIN(1)
-) bscan (
- .CAPTURE(),
- .DRCK(tck),
- .RESET(reset),
- .RUNTEST(),
- .SEL(sel),
- .SHIFT(g_shift),
- .TCK(),
- .TDI(tdi),
- .TMS(),
- .UPDATE(g_update),
- .TDO(tdo)
-);
-
-endmodule
View
136 verilog/lm32/lm32_adder.v
@@ -1,136 +0,0 @@
-// ==================================================================
-// >>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
-// ------------------------------------------------------------------
-// Copyright (c) 2006-2011 by Lattice Semiconductor Corporation
-// ALL RIGHTS RESERVED
-// ------------------------------------------------------------------
-//
-// IMPORTANT: THIS FILE IS AUTO-GENERATED BY THE LATTICEMICO SYSTEM.
-//
-// Permission:
-//
-// Lattice Semiconductor grants permission to use this code
-// pursuant to the terms of the Lattice Semiconductor Corporation
-// Open Source License Agreement.
-//
-// Disclaimer:
-//
-// Lattice Semiconductor provides no warranty regarding the use or
-// functionality of this code. It is the user's responsibility to
-// verify the user's design for consistency and functionality through
-// the use of formal verification methods.
-//
-// --------------------------------------------------------------------
-//
-// Lattice Semiconductor Corporation
-// 5555 NE Moore Court
-// Hillsboro, OR 97214
-// U.S.A
-//
-// TEL: 1-800-Lattice (USA and Canada)
-// 503-286-8001 (other locations)
-//
-// web: http://www.latticesemi.com/
-// email: techsupport@latticesemi.com
-//
-// --------------------------------------------------------------------
-// FILE DETAILS
-// Project : LatticeMico32
-// File : lm32_adder.v
-// Title : Integer adder / subtractor with comparison flag generation
-// Dependencies : lm32_include.v
-// Version : 6.1.17
-// : Initial Release
-// Version : 7.0SP2, 3.0
-// : No Change
-// Version : 3.1
-// : No Change
-// =============================================================================
-
-`include "lm32_include.v"
-
-/////////////////////////////////////////////////////
-// Module interface
-/////////////////////////////////////////////////////
-
-module lm32_adder (
- // ----- Inputs -------
- adder_op_x,
- adder_op_x_n,
- operand_0_x,
- operand_1_x,
- // ----- Outputs -------
- adder_result_x,
- adder_carry_n_x,
- adder_overflow_x
- );
-
-/////////////////////////////////////////////////////
-// Inputs
-/////////////////////////////////////////////////////
-
-input adder_op_x; // Operating to perform, 0 for addition, 1 for subtraction
-input adder_op_x_n; // Inverted version of adder_op_x
-input [`LM32_WORD_RNG] operand_0_x; // Operand to add, or subtract from
-input [`LM32_WORD_RNG] operand_1_x; // Opearnd to add, or subtract by
-
-/////////////////////////////////////////////////////
-// Outputs
-/////////////////////////////////////////////////////
-
-output [`LM32_WORD_RNG] adder_result_x; // Result of addition or subtraction
-wire [`LM32_WORD_RNG] adder_result_x;
-output adder_carry_n_x; // Inverted carry
-wire adder_carry_n_x;
-output adder_overflow_x; // Indicates if overflow occured, only valid for subtractions
-reg adder_overflow_x;
-
-/////////////////////////////////////////////////////
-// Internal nets and registers
-/////////////////////////////////////////////////////
-
-wire a_sign; // Sign (i.e. positive or negative) of operand 0
-wire b_sign; // Sign of operand 1
-wire result_sign; // Sign of result
-
-/////////////////////////////////////////////////////
-// Instantiations
-/////////////////////////////////////////////////////
-
-lm32_addsub addsub (
- // ----- Inputs -----
- .DataA (operand_0_x),
- .DataB (operand_1_x),
- .Cin (adder_op_x),
- .Add_Sub (adder_op_x_n),
- // ----- Ouputs -----
- .Result (adder_result_x),
- .Cout (adder_carry_n_x)
- );
-
-/////////////////////////////////////////////////////
-// Combinational Logic
-/////////////////////////////////////////////////////
-
-// Extract signs of operands and result
-
-assign a_sign = operand_0_x[`LM32_WORD_WIDTH-1];
-assign b_sign = operand_1_x[`LM32_WORD_WIDTH-1];
-assign result_sign = adder_result_x[`LM32_WORD_WIDTH-1];
-
-// Determine whether an overflow occured when performing a subtraction
-
-always @(*)
-begin
- // +ve - -ve = -ve -> overflow
- // -ve - +ve = +ve -> overflow
- if ( (!a_sign & b_sign & result_sign)
- || (a_sign & !b_sign & !result_sign)
- )
- adder_overflow_x = `TRUE;
- else
- adder_overflow_x = `FALSE;
-end
-
-endmodule
-
View
95 verilog/lm32/lm32_addsub.v
@@ -1,95 +0,0 @@
-// ==================================================================
-// >>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
-// ------------------------------------------------------------------
-// Copyright (c) 2006-2011 by Lattice Semiconductor Corporation
-// ALL RIGHTS RESERVED
-// ------------------------------------------------------------------
-//
-// IMPORTANT: THIS FILE IS AUTO-GENERATED BY THE LATTICEMICO SYSTEM.
-//
-// Permission:
-//
-// Lattice Semiconductor grants permission to use this code
-// pursuant to the terms of the Lattice Semiconductor Corporation
-// Open Source License Agreement.
-//
-// Disclaimer:
-//
-// Lattice Semiconductor provides no warranty regarding the use or
-// functionality of this code. It is the user's responsibility to
-// verify the user's design for consistency and functionality through
-// the use of formal verification methods.
-//
-// --------------------------------------------------------------------
-//
-// Lattice Semiconductor Corporation
-// 5555 NE Moore Court
-// Hillsboro, OR 97214
-// U.S.A
-//
-// TEL: 1-800-Lattice (USA and Canada)
-// 503-286-8001 (other locations)
-//
-// web: http://www.latticesemi.com/
-// email: techsupport@latticesemi.com
-//
-// --------------------------------------------------------------------
-// FILE DETAILS
-// Project : LatticeMico32
-// File : lm32_addsub.v
-// Title : PMI adder/subtractor.
-// Version : 6.1.17
-// : Initial Release
-// Version : 7.0SP2, 3.0
-// : No Change
-// Version : 3.1
-// : No Change
-// =============================================================================
-
-`include "lm32_include.v"
-
-/////////////////////////////////////////////////////
-// Module interface
-/////////////////////////////////////////////////////
-
-module lm32_addsub (
- // ----- Inputs -------
- DataA,
- DataB,
- Cin,
- Add_Sub,
- // ----- Outputs -------
- Result,
- Cout
- );
-
-/////////////////////////////////////////////////////
-// Inputs
-/////////////////////////////////////////////////////
-
-input [31:0] DataA;
-input [31:0] DataB;
-input Cin;
-input Add_Sub;
-
-/////////////////////////////////////////////////////
-// Outputs
-/////////////////////////////////////////////////////
-
-output [31:0] Result;
-wire [31:0] Result;
-output Cout;
-wire Cout;
-
-/////////////////////////////////////////////////////
-// Instantiations
-/////////////////////////////////////////////////////
-
-// Modified for Milkymist: removed non-portable instantiated block
- wire [32:0] tmp_addResult = DataA + DataB + Cin;
- wire [32:0] tmp_subResult = DataA - DataB - !Cin;
-
- assign Result = (Add_Sub == 1) ? tmp_addResult[31:0] : tmp_subResult[31:0];
- assign Cout = (Add_Sub == 1) ? tmp_addResult[32] : !tmp_subResult[32];
-
-endmodule
View
167 verilog/lm32/lm32_config.v
@@ -2,39 +2,186 @@
`else
`define LM32_CONFIG_V
+//
+// EXCEPTION VECTORS BASE ADDRESS
+//
+
+// Base address for exception vectors
`define CFG_EBA_RESET 32'h00860000
+
+// Base address for the debug exception vectors. If the DC_RE flag is
+// set or the at_debug signal is asserted (see CFG_ALTERNATE_EBA) this
+// will also be used for normal exception vectors.
`define CFG_DEBA_RESET 32'h10000000
-`define CFG_PL_MULTIPLY_ENABLED
-`define CFG_PL_BARREL_SHIFT_ENABLED
+// Enable exception vector remapping by external signal
+//`define CFG_ALTERNATE_EBA
+
+
+//
+// ALU OPTIONS
+//
+
+// Enable sign-extension instructions
`define CFG_SIGN_EXTEND_ENABLED
+
+// Shifter
+// You may either enable the piplined or the multi-cycle barrel
+// shifter. The multi-cycle shifter will stall the pipeline until
+// the result is available after 32 cycles.
+// If both options are disabled, only "right shift by one bit" is
+// available.
+//`define CFG_MC_BARREL_SHIFT_ENABLED
+`define CFG_PL_BARREL_SHIFT_ENABLED
+
+// Multiplier
+// The multiplier is available either in a multi-cycle version or
+// in a pipelined one. The multi-cycle multiplier stalls the pipe
+// for 32 cycles. If both options are disabled, multiply operations
+// are not supported.
+//`define CFG_MC_MULTIPLY_ENABLED
+`define CFG_PL_MULTIPLY_ENABLED
+
+// Enable the multi-cycle divider. Stalls the pipe until the result
+// is ready after 32 cycles. If disabled, the divide operation is not
+// supported.
`define CFG_MC_DIVIDE_ENABLED
-`define CFG_EBR_POSEDGE_REGISTER_FILE
+
+//
+// INTERRUPTS
+//
+
+// Enable support for 32 hardware interrupts
+`define CFG_INTERRUPTS_ENABLED
+
+// Enable level-sensitive interrupts. The interrupt line status is
+// reflected in the IP register, which is then read-only.
+`define CFG_LEVEL_SENSITIVE_INTERRUPTS
+
+
+//
+// USER INSTRUCTION
+//
+
+// Enable support for the user opcode.
+//`define CFG_USER_ENABLED
+
+
+//
+// MEMORY MANAGEMENT UNIT
+//
+
+// Enable instruction and data translation lookaside buffers and
+// restricted user mode.
+//`define CFG_MMU_ENABLED
+
+
+//
+// CACHE
+//
+
+// Instruction cache
`define CFG_ICACHE_ENABLED
`define CFG_ICACHE_ASSOCIATIVITY 1
`define CFG_ICACHE_SETS 256
`define CFG_ICACHE_BYTES_PER_LINE 16
-`define CFG_ICACHE_BASE_ADDRESS 32'h0
+`define CFG_ICACHE_BASE_ADDRESS 32'h00000000
`define CFG_ICACHE_LIMIT 32'h7fffffff
+// Data cache
`define CFG_DCACHE_ENABLED
`define CFG_DCACHE_ASSOCIATIVITY 1
`define CFG_DCACHE_SETS 256
`define CFG_DCACHE_BYTES_PER_LINE 16
-`define CFG_DCACHE_BASE_ADDRESS 32'h0
+`define CFG_DCACHE_BASE_ADDRESS 32'h00000000
`define CFG_DCACHE_LIMIT 32'h7fffffff
-// Enable Debugging
+
+//
+// DEBUG OPTION
+//
+
+// Globally enable debugging
+//`define CFG_DEBUG_ENABLED
+
+// Enable the hardware JTAG debugging interface.
+// Note: to use this, there must be a special JTAG module for your
+// device. At the moment, there is only support for the
+// Spartan-6.
//`define CFG_JTAG_ENABLED
+
+// JTAG UART is a communication channel which uses JTAG to transmit
+// and receive bytes to and from the host computer.
//`define CFG_JTAG_UART_ENABLED
-//`define CFG_DEBUG_ENABLED
+
+// Enable reading and writing to the memory and writing CSRs using
+// the JTAG interface.
//`define CFG_HW_DEBUG_ENABLED
+
+// Number of hardware watchpoints, max. 4
+//`define CFG_WATCHPOINTS 32'h4
+
+// Enable hardware breakpoints
//`define CFG_ROM_DEBUG_ENABLED
+
+// Number of hardware breakpoints, max. 4
//`define CFG_BREAKPOINTS 32'h4
-//`define CFG_WATCHPOINTS 32'h4
+
+// Put the processor into debug mode by an external signal. That is,
+// raise a breakpoint exception. This is useful if you have a debug
+// monitor and a serial line and you want to trap into the monitor on a
+// BREAK symbol on the serial line.
//`define CFG_EXTERNAL_BREAK_ENABLED
-//`define CFG_GDBSTUB_ENABLED
+
+
+//
+// REGISTER FILE
+//
+
+// The following option explicitly infers block RAM for the register
+// file. There is extra logic to avoid parallel writes and reads.
+// Normally, if your synthesizer is smart enough, this should not be
+// necessary because it will automatically infer block RAM for you.
+//`define CFG_EBR_POSEDGE_REGISTER_FILE
+
+// Explicitly infers block RAM, too. But it uses two different clocks,
+// one being shifted by 180deg, for the read and write port. Therefore,
+// no additional logic to avoid the parallel write/reads.
+//`define CFG_EBR_NEGEDGE_REGISTER_FILE
+
+
+//
+// MISCELLANEOUS
+//
+
+// Exceptions on wishbone bus errors
+//`define CFG_BUS_ERRORS_ENABLED
+
+// Enable the cycle counter
+`define CFG_CYCLE_COUNTER_ENABLED
+
+// Embedded instruction ROM using on-chip block RAM
+//`define CFG_IROM_ENABLED
+//`define CFG_IROM_INIT_FILE "NONE"
+//`define CFG_IROM_BASE_ADDRESS 32'h10000000
+//`define CFG_IROM_LIMIT 32'h10000fff
+
+// Embedded data RAM using on-chip block RAM
+//`define CFG_DRAM_ENABLED
+//`define CFG_DRAM_INIT_FILE "NONE"
+//`define CFG_DRAM_BASE_ADDRESS 32'h20000000
+//`define CFG_DRAM_LIMIT 32'h20000fff
+
+// Trace unit
+//`define CFG_TRACE_ENABLED
+
+// Resolve unconditional branches already in the X stage (UNTESTED!)
+//`define CFG_FAST_UNCONDITIONAL_BRANCH
+
+// log2 function
+// If your simulator/synthesizer does not support the $clog2 system
+// function you can use a constant function instead.
function integer clog2;
input integer value;
@@ -47,4 +194,6 @@ endfunction
`define CLOG2 clog2
+//`define CLOG2 $clog2
+
`endif
View
2,767 verilog/lm32/lm32_cpu.v
@@ -1,2767 +0,0 @@
-// ==================================================================
-// >>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<
-// ------------------------------------------------------------------
-// Copyright (c) 2006-2011 by Lattice Semiconductor Corporation
-// ALL RIGHTS RESERVED
-// ------------------------------------------------------------------
-//
-// IMPORTANT: THIS FILE IS AUTO-GENERATED BY THE LATTICEMICO SYSTEM.
-//
-// Permission:
-//
-// Lattice Semiconductor grants permission to use this code
-// pursuant to the terms of the Lattice Semiconductor Corporation
-// Open Source License Agreement.
-//
-// Disclaimer:
-//
-// Lattice Semiconductor provides no warranty regarding the use or
-// functionality of this code. It is the user's responsibility to
-// verify the user's design for consistency and functionality through
-// the use of formal verification methods.
-//
-// --------------------------------------------------------------------
-//
-// Lattice Semiconductor Corporation
-// 5555 NE Moore Court
-// Hillsboro, OR 97214
-// U.S.A
-//
-// TEL: 1-800-Lattice (USA and Canada)
-// 503-286-8001 (other locations)
-//
-// web: http://www.latticesemi.com/
-// email: techsupport@latticesemi.com
-//
-// --------------------------------------------------------------------
-// FILE DETAILS
-// Project : LatticeMico32
-// File : lm32_cpu.v
-// Title : Top-level of CPU.
-// Dependencies : lm32_include.v
-//
-// Version 3.8
-// 1. Feature: Support for dynamically switching EBA to DEBA via a GPIO.
-// 2. Bug: EA now reports instruction that caused the data abort, rather than
-// next instruction.
-//
-// Version 3.4
-// 1. Bug Fix: In a tight infinite loop (add, sw, bi) incoming interrupts were
-// never serviced.
-//
-// Version 3.3
-// 1. Feature: Support for memory that is tightly coupled to processor core, and
-// has a single-cycle access latency (same as caches). Instruction port has
-// access to a dedicated physically-mapped memory. Data port has access to
-// a dedicated physically-mapped memory. In order to be able to manipulate
-// values in both these memories via the debugger, these memories also
-// interface with the data port of LM32.
-// 2. Feature: Extended Configuration Register
-// 3. Bug Fix: Removed port names that conflict with keywords reserved in System-
-// Verilog.
-//
-// Version 3.2
-// 1. Bug Fix: Single-stepping a load/store to invalid address causes debugger to
-// hang. At the same time CPU fails to register data bus error exception. Bug
-// is caused because (a) data bus error exception occurs after load/store has
-// passed X stage and next sequential instruction (e.g., brk) is already in X
-// stage, and (b) data bus error exception had lower priority than, say, brk
-// exception.
-// 2. Bug Fix: If a brk (or scall/eret/bret) sequentially follows a load/store to
-// invalid location, CPU will fail to register data bus error exception. The
-// solution is to stall scall/eret/bret/brk instructions in D pipeline stage
-// until load/store has completed.
-// 3. Feature: Enable precise identification of load/store that causes seg fault.
-// 4. SYNC resets used for register file when implemented in EBRs.
-//
-// Version 3.1
-// 1. Feature: LM32 Register File can now be mapped in to on-chip block RAM (EBR)
-// instead of distributed memory by enabling the option in LM32 GUI.
-// 2. Feature: LM32 also adds a static branch predictor to improve branch
-// performance. All immediate-based forward-pointing branches are predicted
-// not-taken. All immediate-based backward-pointing branches are predicted taken.
-//
-// Version 7.0SP2, 3.0
-// No Change
-//
-// Version 6.1.17
-// Initial Release
-// =============================================================================
-
-`include "lm32_include.v"
-
-/////////////////////////////////////////////////////
-// Module interface
-/////////////////////////////////////////////////////
-
-module lm32_cpu (
- // ----- Inputs -------
- clk_i,
-`ifdef CFG_EBR_NEGEDGE_REGISTER_FILE
- clk_n_i,
-`endif
- rst_i,
-`ifdef CFG_DEBUG_ENABLED
- `ifdef CFG_ALTERNATE_EBA
- at_debug,
- `endif
-`endif
- // From external devices
-`ifdef CFG_INTERRUPTS_ENABLED
- interrupt,
-`endif
- // From user logic
-`ifdef CFG_USER_ENABLED
- user_result,
- user_complete,
-`endif
-`ifdef CFG_JTAG_ENABLED
- // From JTAG
- jtag_clk,
- jtag_update,
- jtag_reg_q,
- jtag_reg_addr_q,
-`endif
-`ifdef CFG_EXTERNAL_BREAK_ENABLED
- ext_break,
-`endif
-`ifdef CFG_IWB_ENABLED
- // Instruction Wishbone master
- I_DAT_I,
- I_ACK_I,
- I_ERR_I,
- I_RTY_I,
-`endif
- // Data Wishbone master
- D_DAT_I,
- D_ACK_I,
- D_ERR_I,
- D_RTY_I,
- // ----- Outputs -------
-`ifdef CFG_TRACE_ENABLED
- trace_pc,
- trace_pc_valid,
- trace_exception,
- trace_eid,
- trace_eret,
-`ifdef CFG_DEBUG_ENABLED
- trace_bret,
-`endif
-`endif
-`ifdef CFG_JTAG_ENABLED
- jtag_reg_d,
- jtag_reg_addr_d,
-`endif
-`ifdef CFG_USER_ENABLED
- user_valid,
- user_opcode,
- user_operand_0,
- user_operand_1,
-`endif
-`ifdef CFG_IWB_ENABLED
- // Instruction Wishbone master
- I_DAT_O,
- I_ADR_O,
- I_CYC_O,
- I_SEL_O,
- I_STB_O,
- I_WE_O,
- I_CTI_O,
- I_LOCK_O,
- I_BTE_O,
-`endif
- // Data Wishbone master
- D_DAT_O,
- D_ADR_O,
- D_CYC_O,
- D_SEL_O,
- D_STB_O,
- D_WE_O,
- D_CTI_O,
- D_LOCK_O,
- D_BTE_O
- );
-
-/////////////////////////////////////////////////////
-// Parameters
-/////////////////////////////////////////////////////
-
-parameter eba_reset = `CFG_EBA_RESET; // Reset value for EBA CSR
-`ifdef CFG_DEBUG_ENABLED
-parameter deba_reset = `CFG_DEBA_RESET; // Reset value for DEBA CSR
-`endif
-
-`ifdef CFG_ICACHE_ENABLED
-parameter icache_associativity = `CFG_ICACHE_ASSOCIATIVITY; // Associativity of the cache (Number of ways)
-parameter icache_sets = `CFG_ICACHE_SETS; // Number of sets
-parameter icache_bytes_per_line = `CFG_ICACHE_BYTES_PER_LINE; // Number of bytes per cache line
-parameter icache_base_address = `CFG_ICACHE_BASE_ADDRESS; // Base address of cachable memory
-parameter icache_limit = `CFG_ICACHE_LIMIT; // Limit (highest address) of cachable memory
-`else
-parameter icache_associativity = 1;
-parameter icache_sets = 512;
-parameter icache_bytes_per_line = 16;
-parameter icache_base_address = 0;
-parameter icache_limit = 0;
-`endif
-
-`ifdef CFG_DCACHE_ENABLED
-parameter dcache_associativity = `CFG_DCACHE_ASSOCIATIVITY; // Associativity of the cache (Number of ways)
-parameter dcache_sets = `CFG_DCACHE_SETS; // Number of sets
-parameter dcache_bytes_per_line = `CFG_DCACHE_BYTES_PER_LINE; // Number of bytes per cache line
-parameter dcache_base_address = `CFG_DCACHE_BASE_ADDRESS; // Base address of cachable memory
-parameter dcache_limit = `CFG_DCACHE_LIMIT; // Limit (highest address) of cachable memory
-`else
-parameter dcache_associativity = 1;
-parameter dcache_sets = 512;
-parameter dcache_bytes_per_line = 16;
-parameter dcache_base_address = 0;
-parameter dcache_limit = 0;
-`endif
-
-`ifdef CFG_DEBUG_ENABLED
-parameter watchpoints = `CFG_WATCHPOINTS; // Number of h/w watchpoint CSRs
-`else
-parameter watchpoints = 0;
-`endif
-`ifdef CFG_ROM_DEBUG_ENABLED
-parameter breakpoints = `CFG_BREAKPOINTS; // Number of h/w breakpoint CSRs
-`else
-parameter breakpoints = 0;
-`endif
-
-`ifdef CFG_INTERRUPTS_ENABLED
-parameter interrupts = `CFG_INTERRUPTS; // Number of interrupts
-`else
-parameter interrupts = 0;
-`endif
-
-/////////////////////////////////////////////////////
-// Inputs
-/////////////////////////////////////////////////////
-
-input clk_i; // Clock
-`ifdef CFG_EBR_NEGEDGE_REGISTER_FILE
-input clk_n_i; // Inverted clock
-`endif
-input rst_i; // Reset
-
-`ifdef CFG_DEBUG_ENABLED
- `ifdef CFG_ALTERNATE_EBA
- input at_debug; // GPIO input that maps EBA to DEBA
- `endif
-`endif
-
-`ifdef CFG_INTERRUPTS_ENABLED
-input [`LM32_INTERRUPT_RNG] interrupt; // Interrupt pins
-`endif
-
-`ifdef CFG_USER_ENABLED
-input [`LM32_WORD_RNG] user_result; // User-defined instruction result
-input user_complete; // User-defined instruction execution is complete
-`endif
-
-`ifdef CFG_JTAG_ENABLED
-input jtag_clk; // JTAG clock
-input jtag_update; // JTAG state machine is in data register update state
-input [`LM32_BYTE_RNG] jtag_reg_q;
-input [2:0] jtag_reg_addr_q;
-`endif
-
-`ifdef CFG_IWB_ENABLED
-input [`LM32_WORD_RNG] I_DAT_I; // Instruction Wishbone interface read data
-input I_ACK_I; // Instruction Wishbone interface acknowledgement
-input I_ERR_I; // Instruction Wishbone interface error
-input I_RTY_I; // Instruction Wishbone interface retry
-`endif
-
-input [`LM32_WORD_RNG] D_DAT_I; // Data Wishbone interface read data
-input D_ACK_I; // Data Wishbone interface acknowledgement
-input D_ERR_I; // Data Wishbone interface error
-input D_RTY_I; // Data Wishbone interface retry
-
-`ifdef CFG_EXTERNAL_BREAK_ENABLED
-input ext_break;
-`endif
-
-/////////////////////////////////////////////////////
-// Outputs
-/////////////////////////////////////////////////////
-
-`ifdef CFG_TRACE_ENABLED
-output [`LM32_PC_RNG] trace_pc; // PC to trace
-reg [`LM32_PC_RNG] trace_pc;
-output trace_pc_valid; // Indicates that a new trace PC is valid
-reg trace_pc_valid;
-output trace_exception; // Indicates an exception has occured
-reg trace_exception;
-output [`LM32_EID_RNG] trace_eid; // Indicates what type of exception has occured
-reg [`LM32_EID_RNG] trace_eid;
-output trace_eret; // Indicates an eret instruction has been executed
-reg trace_eret;
-`ifdef CFG_DEBUG_ENABLED
-output trace_bret; // Indicates a bret instruction has been executed
-reg trace_bret;
-`endif
-`endif
-
-`ifdef CFG_JTAG_ENABLED
-output [`LM32_BYTE_RNG] jtag_reg_d;
-wire [`LM32_BYTE_RNG] jtag_reg_d;
-output [2:0] jtag_reg_addr_d;
-wire [2:0] jtag_reg_addr_d;
-`endif
-
-`ifdef CFG_USER_ENABLED
-output user_valid; // Indicates if user_opcode is valid
-wire user_valid;
-output [`LM32_USER_OPCODE_RNG] user_opcode; // User-defined instruction opcode
-reg [`LM32_USER_OPCODE_RNG] user_opcode;
-output [`LM32_WORD_RNG] user_operand_0; // First operand for user-defined instruction
-wire [`LM32_WORD_RNG] user_operand_0;
-output [`LM32_WORD_RNG] user_operand_1; // Second operand for user-defined instruction
-wire [`LM32_WORD_RNG] user_operand_1;
-`endif
-
-`ifdef CFG_IWB_ENABLED
-output [`LM32_WORD_RNG] I_DAT_O; // Instruction Wishbone interface write data
-wire [`LM32_WORD_RNG] I_DAT_O;
-output [`LM32_WORD_RNG] I_ADR_O; // Instruction Wishbone interface address
-wire [`LM32_WORD_RNG] I_ADR_O;
-output I_CYC_O; // Instruction Wishbone interface cycle
-wire I_CYC_O;
-output [`LM32_BYTE_SELECT_RNG] I_SEL_O; // Instruction Wishbone interface byte select
-wire [`LM32_BYTE_SELECT_RNG] I_SEL_O;
-output I_STB_O; // Instruction Wishbone interface strobe
-wire I_STB_O;
-output I_WE_O; // Instruction Wishbone interface write enable
-wire I_WE_O;
-output [`LM32_CTYPE_RNG] I_CTI_O; // Instruction Wishbone interface cycle type
-wire [`LM32_CTYPE_RNG] I_CTI_O;
-output I_LOCK_O; // Instruction Wishbone interface lock bus
-wire I_LOCK_O;
-output [`LM32_BTYPE_RNG] I_BTE_O; // Instruction Wishbone interface burst type
-wire [`LM32_BTYPE_RNG] I_BTE_O;
-`endif
-
-output [`LM32_WORD_RNG] D_DAT_O; // Data Wishbone interface write data
-wire [`LM32_WORD_RNG] D_DAT_O;
-output [`LM32_WORD_RNG] D_ADR_O; // Data Wishbone interface address
-wire [`LM32_WORD_RNG] D_ADR_O;
-output D_CYC_O; // Data Wishbone interface cycle
-wire D_CYC_O;
-output [`LM32_BYTE_SELECT_RNG] D_SEL_O; // Data Wishbone interface byte select
-wire [`LM32_BYTE_SELECT_RNG] D_SEL_O;
-output D_STB_O; // Data Wishbone interface strobe
-wire D_STB_O;
-output D_WE_O; // Data Wishbone interface write enable
-wire D_WE_O;
-output [`LM32_CTYPE_RNG] D_CTI_O; // Data Wishbone interface cycle type
-wire [`LM32_CTYPE_RNG] D_CTI_O;
-output D_LOCK_O; // Date Wishbone interface lock bus
-wire D_LOCK_O;
-output [`LM32_BTYPE_RNG] D_BTE_O; // Data Wishbone interface burst type
-wire [`LM32_BTYPE_RNG] D_BTE_O;
-
-/////////////////////////////////////////////////////
-// Internal nets and registers
-/////////////////////////////////////////////////////
-
-// Pipeline registers
-
-`ifdef LM32_CACHE_ENABLED
-reg valid_a; // Instruction in A stage is valid
-`endif
-reg valid_f; // Instruction in F stage is valid
-reg valid_d; // Instruction in D stage is valid
-reg valid_x; // Instruction in X stage is valid
-reg valid_m; // Instruction in M stage is valid
-reg valid_w; // Instruction in W stage is valid
-
-wire q_x;
-wire [`LM32_WORD_RNG] immediate_d; // Immediate operand
-wire load_d; // Indicates a load instruction
-reg load_x;
-reg load_m;
-wire load_q_x;
-wire store_q_x;
-wire store_d; // Indicates a store instruction
-reg store_x;
-reg store_m;
-wire [`LM32_SIZE_RNG] size_d; // Size of load/store (byte, hword, word)
-reg [`LM32_SIZE_RNG] size_x;
-wire branch_d; // Indicates a branch instruction
-wire branch_predict_d; // Indicates a branch is predicted
-wire branch_predict_taken_d; // Indicates a branch is predicted taken
-wire [`LM32_PC_RNG] branch_predict_address_d; // Address to which predicted branch jumps
-wire [`LM32_PC_RNG] branch_target_d;
-wire bi_unconditional;
-wire bi_conditional;
-reg branch_x;
-reg branch_predict_x;
-reg branch_predict_taken_x;
-reg branch_m;
-reg branch_predict_m;
-reg branch_predict_taken_m;
-wire branch_mispredict_taken_m; // Indicates a branch was mispredicted as taken
-wire branch_flushX_m; // Indicates that instruction in X stage must be squashed
-wire branch_reg_d; // Branch to register or immediate
-wire [`LM32_PC_RNG] branch_offset_d; // Branch offset for immediate branches
-reg [`LM32_PC_RNG] branch_target_x; // Address to branch to
-reg [`LM32_PC_RNG] branch_target_m;
-wire [`LM32_D_RESULT_SEL_0_RNG] d_result_sel_0_d; // Which result should be selected in D stage for operand 0
-wire [`LM32_D_RESULT_SEL_1_RNG] d_result_sel_1_d; // Which result should be selected in D stage for operand 1
-
-wire x_result_sel_csr_d; // Select X stage result from CSRs
-reg x_result_sel_csr_x;
-`ifdef LM32_MC_ARITHMETIC_ENABLED
-wire x_result_sel_mc_arith_d; // Select X stage result from multi-cycle arithmetic unit
-reg x_result_sel_mc_arith_x;
-`endif
-`ifdef LM32_NO_BARREL_SHIFT
-wire x_result_sel_shift_d; // Select X stage result from shifter
-reg x_result_sel_shift_x;
-`endif
-`ifdef CFG_SIGN_EXTEND_ENABLED
-wire x_result_sel_sext_d; // Select X stage result from sign-extend logic
-reg x_result_sel_sext_x;
-`endif
-wire x_result_sel_logic_d; // Select X stage result from logic op unit
-reg x_result_sel_logic_x;
-`ifdef CFG_USER_ENABLED
-wire x_result_sel_user_d; // Select X stage result from user-defined logic
-reg x_result_sel_user_x;
-`endif
-wire x_result_sel_add_d; // Select X stage result from adder
-reg x_result_sel_add_x;
-wire m_result_sel_compare_d; // Select M stage result from comparison logic
-reg m_result_sel_compare_x;
-reg m_result_sel_compare_m;
-`ifdef CFG_PL_BARREL_SHIFT_ENABLED
-wire m_result_sel_shift_d; // Select M stage result from shifter
-reg m_result_sel_shift_x;
-reg m_result_sel_shift_m;
-`endif
-wire w_result_sel_load_d; // Select W stage result from load/store unit
-reg w_result_sel_load_x;
-reg w_result_sel_load_m;
-reg w_result_sel_load_w;
-`ifdef CFG_PL_MULTIPLY_ENABLED
-wire w_result_sel_mul_d; // Select W stage result from multiplier
-reg w_result_sel_mul_x;
-reg w_result_sel_mul_m;
-reg w_result_sel_mul_w;
-`endif
-wire x_bypass_enable_d; // Whether result is bypassable in X stage
-reg x_bypass_enable_x;
-wire m_bypass_enable_d; // Whether result is bypassable in M stage
-reg m_bypass_enable_x;
-reg m_bypass_enable_m;
-wire sign_extend_d; // Whether to sign-extend or zero-extend
-reg sign_extend_x;
-wire write_enable_d; // Register file write enable
-reg write_enable_x;
-wire write_enable_q_x;
-reg write_enable_m;
-wire write_enable_q_m;
-reg write_enable_w;
-wire write_enable_q_w;
-wire read_enable_0_d; // Register file read enable 0
-wire [`LM32_REG_IDX_RNG] read_idx_0_d; // Register file read index 0
-wire read_enable_1_d; // Register file read enable 1
-wire [`LM32_REG_IDX_RNG] read_idx_1_d; // Register file read index 1
-wire [`LM32_REG_IDX_RNG] write_idx_d; // Register file write index
-reg [`LM32_REG_IDX_RNG] write_idx_x;
-reg [`LM32_REG_IDX_RNG] write_idx_m;
-reg [`LM32_REG_IDX_RNG] write_idx_w;
-wire [`LM32_CSR_RNG] csr_d; // CSR read/write index
-reg [`LM32_CSR_RNG] csr_x;
-wire [`LM32_CONDITION_RNG] condition_d; // Branch condition
-reg [`LM32_CONDITION_RNG] condition_x;
-`ifdef CFG_DEBUG_ENABLED
-wire break_d; // Indicates a break instruction
-reg break_x;
-`endif
-wire scall_d; // Indicates a scall instruction
-reg scall_x;
-wire eret_d; // Indicates an eret instruction
-reg eret_x;
-wire eret_q_x;
-reg eret_m;
-`ifdef CFG_TRACE_ENABLED
-reg eret_w;
-`endif
-`ifdef CFG_DEBUG_ENABLED
-wire bret_d; // Indicates a bret instruction
-reg bret_x;
-wire bret_q_x;
-reg bret_m;
-`ifdef CFG_TRACE_ENABLED
-reg bret_w;
-`endif
-`endif
-wire csr_write_enable_d; // CSR write enable
-reg csr_write_enable_x;
-wire csr_write_enable_q_x;
-`ifdef CFG_USER_ENABLED
-wire [`LM32_USER_OPCODE_RNG] user_opcode_d; // User-defined instruction opcode
-`endif
-
-`ifdef CFG_BUS_ERRORS_ENABLED
-wire bus_error_d; // Indicates an bus error occured while fetching the instruction in this pipeline stage
-reg bus_error_x;
-reg data_bus_error_exception_m;
-reg [`LM32_PC_RNG] memop_pc_w;
-`endif
-
-reg [`LM32_WORD_RNG] d_result_0; // Result of instruction in D stage (operand 0)
-reg [`LM32_WORD_RNG] d_result_1; // Result of instruction in D stage (operand 1)
-reg [`LM32_WORD_RNG] x_result; // Result of instruction in X stage
-reg [`LM32_WORD_RNG] m_result; // Result of instruction in M stage
-reg [`LM32_WORD_RNG] w_result; // Result of instruction in W stage
-
-reg [`LM32_WORD_RNG] operand_0_x; // Operand 0 for X stage instruction
-reg [`LM32_WORD_RNG] operand_1_x; // Operand 1 for X stage instruction
-reg [`LM32_WORD_RNG] store_operand_x; // Data read from register to store
-reg [`LM32_WORD_RNG] operand_m; // Operand for M stage instruction
-reg [`LM32_WORD_RNG] operand_w; // Operand for W stage instruction
-
-// To/from register file
-`ifdef CFG_EBR_POSEDGE_REGISTER_FILE
-reg [`LM32_WORD_RNG] reg_data_live_0;
-reg [`LM32_WORD_RNG] reg_data_live_1;
-reg use_buf; // Whether to use reg_data_live or reg_data_buf
-reg [`LM32_WORD_RNG] reg_data_buf_0;
-reg [`LM32_WORD_RNG] reg_data_buf_1;
-`endif
-`ifdef LM32_EBR_REGISTER_FILE
-`else
-reg [`LM32_WORD_RNG] registers[0:(1<<`LM32_REG_IDX_WIDTH)-1]; // Register file
-`endif
-wire [`LM32_WORD_RNG] reg_data_0; // Register file read port 0 data
-wire [`LM32_WORD_RNG] reg_data_1; // Register file read port 1 data
-reg [`LM32_WORD_RNG] bypass_data_0; // Register value 0 after bypassing
-reg [`LM32_WORD_RNG] bypass_data_1; // Register value 1 after bypassing
-wire reg_write_enable_q_w;
-
-reg interlock; // Indicates pipeline should be stalled because of a read-after-write hazzard
-
-wire stall_a; // Stall instruction in A pipeline stage
-wire stall_f; // Stall instruction in F pipeline stage
-wire stall_d; // Stall instruction in D pipeline stage
-wire stall_x; // Stall instruction in X pipeline stage
-wire stall_m; // Stall instruction in M pipeline stage
-
-// To/from adder
-wire adder_op_d; // Whether to add or subtract
-reg adder_op_x;
-reg adder_op_x_n; // Inverted version of adder_op_x
-wire [`LM32_WORD_RNG] adder_result_x; // Result from adder
-wire adder_overflow_x; // Whether a signed overflow occured
-wire adder_carry_n_x; // Whether a carry was generated
-
-// To/from logical operations unit
-wire [`LM32_LOGIC_OP_RNG] logic_op_d; // Which operation to perform
-reg [`LM32_LOGIC_OP_RNG] logic_op_x;
-wire [`LM32_WORD_RNG] logic_result_x; // Result of logical operation
-
-`ifdef CFG_SIGN_EXTEND_ENABLED
-// From sign-extension unit
-wire [`LM32_WORD_RNG] sextb_result_x; // Result of byte sign-extension
-wire [`LM32_WORD_RNG] sexth_result_x; // Result of half-word sign-extenstion
-wire [`LM32_WORD_RNG] sext_result_x; // Result of sign-extension specified by instruction
-`endif
-
-// To/from shifter
-`ifdef CFG_PL_BARREL_SHIFT_ENABLED
-`ifdef CFG_ROTATE_ENABLED
-wire rotate_d; // Whether we should rotate or shift
-reg rotate_x;
-`endif
-wire direction_d; // Which direction to shift in
-reg direction_x;
-wire [`LM32_WORD_RNG] shifter_result_m; // Result of shifter
-`endif
-`ifdef CFG_MC_BARREL_SHIFT_ENABLED
-wire shift_left_d; // Indicates whether to perform a left shift or not
-wire shift_left_q_d;
-wire shift_right_d; // Indicates whether to perform a right shift or not
-wire shift_right_q_d;
-`endif
-`ifdef LM32_NO_BARREL_SHIFT
-wire [`LM32_WORD_RNG] shifter_result_x; // Result of single-bit right shifter
-`endif
-
-// To/from multiplier
-`ifdef LM32_MULTIPLY_ENABLED
-wire [`LM32_WORD_RNG] multiplier_result_w; // Result from multiplier
-`endif
-`ifdef CFG_MC_MULTIPLY_ENABLED
-wire multiply_d; // Indicates whether to perform a multiply or not
-wire multiply_q_d;
-`endif
-
-// To/from divider
-`ifdef CFG_MC_DIVIDE_ENABLED
-wire divide_d; // Indicates whether to perform a divider or not
-wire divide_q_d;
-wire modulus_d;
-wire modulus_q_d;
-wire divide_by_zero_x; // Indicates an attempt was made to divide by zero
-`endif
-
-// To from multi-cycle arithmetic unit
-`ifdef LM32_MC_ARITHMETIC_ENABLED
-wire mc_stall_request_x; // Multi-cycle arithmetic unit stall request
-wire [`LM32_WORD_RNG] mc_result_x;
-`endif
-
-// From CSRs
-`ifdef CFG_INTERRUPTS_ENABLED
-wire [`LM32_WORD_RNG] interrupt_csr_read_data_x;// Data read from interrupt CSRs
-`endif
-wire [`LM32_WORD_RNG] cfg; // Configuration CSR
-wire [`LM32_WORD_RNG] cfg2; // Extended Configuration CSR
-`ifdef CFG_CYCLE_COUNTER_ENABLED
-reg [`LM32_WORD_RNG] cc; // Cycle counter CSR
-`endif
-reg [`LM32_WORD_RNG] csr_read_data_x; // Data read from CSRs
-
-// To/from instruction unit
-wire [`LM32_PC_RNG] pc_f; // PC of instruction in F stage
-wire [`LM32_PC_RNG] pc_d; // PC of instruction in D stage
-wire [`LM32_PC_RNG] pc_x; // PC of instruction in X stage
-wire [`LM32_PC_RNG] pc_m; // PC of instruction in M stage
-wire [`LM32_PC_RNG] pc_w; // PC of instruction in W stage
-`ifdef CFG_TRACE_ENABLED
-reg [`LM32_PC_RNG] pc_c; // PC of last commited instruction
-`endif
-`ifdef CFG_EBR_POSEDGE_REGISTER_FILE
-wire [`LM32_INSTRUCTION_RNG] instruction_f; // Instruction in F stage
-`endif
-//pragma attribute instruction_d preserve_signal true
-//pragma attribute instruction_d preserve_driver true
-wire [`LM32_INSTRUCTION_RNG] instruction_d; // Instruction in D stage
-`ifdef CFG_ICACHE_ENABLED
-wire iflush; // Flush instruction cache
-wire icache_stall_request; // Stall pipeline because instruction cache is busy
-wire icache_restart_request; // Restart instruction that caused an instruction cache miss
-wire icache_refill_request; // Request to refill instruction cache
-wire icache_refilling; // Indicates the instruction cache is being refilled
-`endif
-`ifdef CFG_IROM_ENABLED
-wire [`LM32_WORD_RNG] irom_store_data_m; // Store data to instruction ROM
-wire [`LM32_WORD_RNG] irom_address_xm; // Address to instruction ROM from load-store unit
-wire [`LM32_WORD_RNG] irom_data_m; // Load data from instruction ROM
-wire irom_we_xm; // Indicates data needs to be written to instruction ROM
-wire irom_stall_request_x; // Indicates D stage needs to be stalled on a store to instruction ROM
-`endif
-
-// To/from load/store unit
-`ifdef CFG_DCACHE_ENABLED
-wire dflush_x; // Flush data cache
-reg dflush_m;
-wire dcache_stall_request; // Stall pipeline because data cache is busy
-wire dcache_restart_request; // Restart instruction that caused a data cache miss
-wire dcache_refill_request; // Request to refill data cache
-wire dcache_refilling; // Indicates the data cache is being refilled
-`endif
-wire [`LM32_WORD_RNG] load_data_w; // Result of a load instruction
-wire stall_wb_load; // Stall pipeline because of a load via the data Wishbone interface
-
-// To/from JTAG interface
-`ifdef CFG_JTAG_ENABLED
-`ifdef CFG_JTAG_UART_ENABLED
-wire [`LM32_WORD_RNG] jtx_csr_read_data; // Read data for JTX CSR
-wire [`LM32_WORD_RNG] jrx_csr_read_data; // Read data for JRX CSR
-`endif
-`ifdef CFG_HW_DEBUG_ENABLED
-wire jtag_csr_write_enable; // Debugger CSR write enable
-wire [`LM32_WORD_RNG] jtag_csr_write_data; // Data to write to specified CSR
-wire [`LM32_CSR_RNG] jtag_csr; // Which CSR to write
-wire jtag_read_enable;
-wire [`LM32_BYTE_RNG] jtag_read_data;
-wire jtag_write_enable;
-wire [`LM32_BYTE_RNG] jtag_write_data;
-wire [`LM32_WORD_RNG] jtag_address;
-wire jtag_access_complete;
-`endif
-`ifdef CFG_DEBUG_ENABLED
-wire jtag_break; // Request from debugger to raise a breakpoint
-`endif
-`endif
-
-// Hazzard detection
-wire raw_x_0; // RAW hazzard between instruction in X stage and read port 0
-wire raw_x_1; // RAW hazzard between instruction in X stage and read port 1
-wire raw_m_0; // RAW hazzard between instruction in M stage and read port 0
-wire raw_m_1; // RAW hazzard between instruction in M stage and read port 1
-wire raw_w_0; // RAW hazzard between instruction in W stage and read port 0
-wire raw_w_1; // RAW hazzard between instruction in W stage and read port 1
-
-// Control flow
-wire cmp_zero; // Result of comparison is zero
-wire cmp_negative; // Result of comparison is negative
-wire cmp_overflow; // Comparison produced an overflow
-wire cmp_carry_n; // Comparison produced a carry, inverted
-reg condition_met_x; // Condition of branch instruction is met
-reg condition_met_m;
-`ifdef CFG_FAST_UNCONDITIONAL_BRANCH
-wire branch_taken_x; // Branch is taken in X stage
-`endif
-wire branch_taken_m; // Branch is taken in M stage
-
-wire kill_f; // Kill instruction in F stage
-wire kill_d; // Kill instruction in D stage
-wire kill_x; // Kill instruction in X stage
-wire kill_m; // Kill instruction in M stage
-wire kill_w; // Kill instruction in W stage
-
-reg [`LM32_PC_WIDTH+2-1:8] eba; // Exception Base Address (EBA) CSR
-`ifdef CFG_DEBUG_ENABLED
-reg [`LM32_PC_WIDTH+2-1:8] deba; // Debug Exception Base Address (DEBA) CSR
-`endif
-reg [`LM32_EID_RNG] eid_x; // Exception ID in X stage
-`ifdef CFG_TRACE_ENABLED
-reg [`LM32_EID_RNG] eid_m; // Exception ID in M stage
-reg [`LM32_EID_RNG] eid_w; // Exception ID in W stage
-`endif
-
-`ifdef CFG_DEBUG_ENABLED
-`ifdef LM32_SINGLE_STEP_ENABLED
-wire dc_ss; // Is single-step enabled
-`endif
-wire dc_re; // Remap all exceptions
-wire exception_x; // An exception occured in the X stage
-reg exception_m; // An instruction that caused an exception is in the M stage
-wire debug_exception_x; // Indicates if a debug exception has occured
-reg debug_exception_m;
-reg debug_exception_w;
-wire debug_exception_q_w;
-wire non_debug_exception_x; // Indicates if a non debug exception has occured
-reg non_debug_exception_m;
-reg non_debug_exception_w;
-wire non_debug_exception_q_w;
-`else
-wire exception_x; // Indicates if a debug exception has occured
-reg exception_m;
-reg exception_w;
-wire exception_q_w;
-`endif
-
-`ifdef CFG_DEBUG_ENABLED
-wire reset_exception; // Indicates if a reset exception has occured
-`endif
-`ifdef CFG_INTERRUPTS_ENABLED
-wire interrupt_exception; // Indicates if an interrupt exception has occured
-`endif
-`ifdef CFG_DEBUG_ENABLED
-wire breakpoint_exception; // Indicates if a breakpoint exception has occured
-wire watchpoint_exception; // Indicates if a watchpoint exception has occured
-`endif
-`ifdef CFG_BUS_ERRORS_ENABLED
-wire instruction_bus_error_exception; // Indicates if an instruction bus error exception has occured
-wire data_bus_error_exception; // Indicates if a data bus error exception has occured
-`endif
-`ifdef CFG_MC_DIVIDE_ENABLED
-wire divide_by_zero_exception; // Indicates if a divide by zero exception has occured
-`endif
-wire system_call_exception; // Indicates if a system call exception has occured
-
-`ifdef CFG_BUS_ERRORS_ENABLED
-reg data_bus_error_seen; // Indicates if a data bus error was seen
-`endif
-
-`ifdef CFG_EXTERNAL_BREAK_ENABLED
-reg ext_break_r;
-`endif
-
-/////////////////////////////////////////////////////
-// Functions
-/////////////////////////////////////////////////////
-
-/////////////////////////////////////////////////////
-// Instantiations
-/////////////////////////////////////////////////////
-
-// Instruction unit
-lm32_instruction_unit #(
- .associativity (icache_associativity),
- .sets (icache_sets),
- .bytes_per_line (icache_bytes_per_line),
- .base_address (icache_base_address),
- .limit (icache_limit)
- ) instruction_unit (
- // ----- Inputs -------
- .clk_i (clk_i),
- .rst_i (rst_i),
-`ifdef CFG_DEBUG_ENABLED
- `ifdef CFG_ALTERNATE_EBA
- .at_debug (at_debug),
- `endif
-`endif
- // From pipeline
- .stall_a (stall_a),
- .stall_f (stall_f),
- .stall_d (stall_d),
- .stall_x (stall_x),
- .stall_m (stall_m),
- .valid_f (valid_f),
- .valid_d (valid_d),
- .kill_f (kill_f),
- .branch_predict_taken_d (branch_predict_taken_d),
- .branch_predict_address_d (branch_predict_address_d),
-`ifdef CFG_FAST_UNCONDITIONAL_BRANCH
- .branch_taken_x (branch_taken_x),
- .branch_target_x (branch_target_x),
-`endif
- .exception_m (exception_m),
- .branch_taken_m (branch_taken_m),
- .branch_mispredict_taken_m (branch_mispredict_taken_m),
- .branch_target_m (branch_target_m),
-`ifdef CFG_ICACHE_ENABLED
- .iflush (iflush),
-`endif
-`ifdef CFG_IROM_ENABLED
- .irom_store_data_m (irom_store_data_m),
- .irom_address_xm (irom_address_xm),
- .irom_we_xm (irom_we_xm),
-`endif
-`ifdef CFG_DCACHE_ENABLED
- .dcache_restart_request (dcache_restart_request),
- .dcache_refill_request (dcache_refill_request),
- .dcache_refilling (dcache_refilling),
-`endif
-`ifdef CFG_IWB_ENABLED
- // From Wishbone
- .i_dat_i (I_DAT_I),
- .i_ack_i (I_ACK_I),
- .i_err_i (I_ERR_I),
-`endif
-`ifdef CFG_HW_DEBUG_ENABLED
- .jtag_read_enable (jtag_read_enable),
- .jtag_write_enable (jtag_write_enable),
- .jtag_write_data (jtag_write_data),
- .jtag_address (jtag_address),
-`endif
- // ----- Outputs -------
- // To pipeline
- .pc_f (pc_f),
- .pc_d (pc_d),
- .pc_x (pc_x),
- .pc_m (pc_m),
- .pc_w (pc_w),
-`ifdef CFG_ICACHE_ENABLED
- .icache_stall_request (icache_stall_request),
- .icache_restart_request (icache_restart_request),
- .icache_refill_request (icache_refill_request),
- .icache_refilling (icache_refilling),
-`endif
-`ifdef CFG_IROM_ENABLED
- .irom_data_m (irom_data_m),
-`endif
-`ifdef CFG_IWB_ENABLED
- // To Wishbone
- .i_dat_o (I_DAT_O),
- .i_adr_o (I_ADR_O),
- .i_cyc_o (I_CYC_O),
- .i_sel_o (I_SEL_O),
- .i_stb_o (I_STB_O),
- .i_we_o (I_WE_O),
- .i_cti_o (I_CTI_O),
- .i_lock_o (I_LOCK_O),
- .i_bte_o (I_BTE_O),
-`endif
-`ifdef CFG_HW_DEBUG_ENABLED
- .jtag_read_data (jtag_read_data),
- .jtag_access_complete (jtag_access_complete),
-`endif
-`ifdef CFG_BUS_ERRORS_ENABLED
- .bus_error_d (bus_error_d),
-`endif
-`ifdef CFG_EBR_POSEDGE_REGISTER_FILE
- .instruction_f (instruction_f),
-`endif
- .instruction_d (instruction_d)
- );
-
-// Instruction decoder
-lm32_decoder decoder (
- // ----- Inputs -------
- .instruction (instruction_d),
- // ----- Outputs -------
- .d_result_sel_0 (d_result_sel_0_d),
- .d_result_sel_1 (d_result_sel_1_d),
- .x_result_sel_csr (x_result_sel_csr_d),
-`ifdef LM32_MC_ARITHMETIC_ENABLED
- .x_result_sel_mc_arith (x_result_sel_mc_arith_d),
-`endif
-`ifdef LM32_NO_BARREL_SHIFT
- .x_result_sel_shift (x_result_sel_shift_d),
-`endif
-`ifdef CFG_SIGN_EXTEND_ENABLED
- .x_result_sel_sext (x_result_sel_sext_d),
-`endif
- .x_result_sel_logic (x_result_sel_logic_d),
-`ifdef CFG_USER_ENABLED
- .x_result_sel_user (x_result_sel_user_d),
-`endif
- .x_result_sel_add (x_result_sel_add_d),
- .m_result_sel_compare (m_result_sel_compare_d),
-`ifdef CFG_PL_BARREL_SHIFT_ENABLED
- .m_result_sel_shift (m_result_sel_shift_d),
-`endif
- .w_result_sel_load (w_result_sel_load_d),
-`ifdef CFG_PL_MULTIPLY_ENABLED
- .w_result_sel_mul (w_result_sel_mul_d),
-`endif
- .x_bypass_enable (x_bypass_enable_d),
- .m_bypass_enable (m_bypass_enable_d),
- .read_enable_0 (read_enable_0_d),
- .read_idx_0 (read_idx_0_d),
- .read_enable_1 (read_enable_1_d),
- .read_idx_1 (read_idx_1_d),
- .write_enable (write_enable_d),
- .write_idx (write_idx_d),
- .immediate (immediate_d),
- .branch_offset (branch_offset_d),
- .load (load_d),
- .store (store_d),
- .size (size_d),
- .sign_extend (sign_extend_d),
- .adder_op (adder_op_d),
- .logic_op (logic_op_d),
-`ifdef CFG_PL_BARREL_SHIFT_ENABLED
- .direction (direction_d),
-`endif
-`ifdef CFG_MC_BARREL_SHIFT_ENABLED
- .shift_left (shift_left_d),
- .shift_right (shift_right_d),
-`endif
-`ifdef CFG_MC_MULTIPLY_ENABLED
- .multiply (multiply_d),
-`endif
-`ifdef CFG_MC_DIVIDE_ENABLED
- .divide (divide_d),
- .modulus (modulus_d),
-`endif
- .branch (branch_d),
- .bi_unconditional (bi_unconditional),
- .bi_conditional (bi_conditional),
- .branch_reg (branch_reg_d),
- .condition (condition_d),
-`ifdef CFG_DEBUG_ENABLED
- .break_opcode (break_d),
-`endif
- .scall (scall_d),
- .eret (eret_d),
-`ifdef CFG_DEBUG_ENABLED
- .bret (bret_d),
-`endif
-`ifdef CFG_USER_ENABLED
- .user_opcode (user_opcode_d),
-`endif
- .csr_write_enable (csr_write_enable_d)
- );
-
-// Load/store unit
-lm32_load_store_unit #(
- .associativity (dcache_associativity),
- .sets (dcache_sets),
- .bytes_per_line (dcache_bytes_per_line),
- .base_address (dcache_base_address),
- .limit (dcache_limit)
- ) load_store_unit (
- // ----- Inputs -------
- .clk_i (clk_i),
- .rst_i (rst_i),
- // From pipeline
- .stall_a (stall_a),
- .stall_x (stall_x),
- .stall_m (stall_m),
- .kill_x (kill_x),
- .kill_m (kill_m),
- .exception_m (exception_m),
- .store_operand_x (store_operand_x),
- .load_store_address_x (adder_result_x),
- .load_store_address_m (operand_m),
- .load_store_address_w (operand_w[1:0]),
- .load_x (load_x),
- .store_x (store_x),
- .load_q_x (load_q_x),
- .store_q_x (store_q_x),
- .load_q_m (load_q_m),
- .store_q_m (store_q_m),
- .sign_extend_x (sign_extend_x),
- .size_x (size_x),
-`ifdef CFG_DCACHE_ENABLED
- .dflush (dflush_m),
-`endif
-`ifdef CFG_IROM_ENABLED
- .irom_data_m (irom_data_m),
-`endif
- // From Wishbone
- .d_dat_i (D_DAT_I),
- .d_ack_i (D_ACK_I),
- .d_err_i (D_ERR_I),
- .d_rty_i (D_RTY_I),
- // ----- Outputs -------
- // To pipeline
-`ifdef CFG_DCACHE_ENABLED
- .dcache_refill_request (dcache_refill_request),
- .dcache_restart_request (dcache_restart_request),
- .dcache_stall_request (dcache_stall_request),
- .dcache_refilling (dcache_refilling),
-`endif
-`ifdef CFG_IROM_ENABLED
- .irom_store_data_m (irom_store_data_m),
- .irom_address_xm (irom_address_xm),
- .irom_we_xm (irom_we_xm),
- .irom_stall_request_x (irom_stall_request_x),
-`endif
- .load_data_w (load_data_w),
- .stall_wb_load (stall_wb_load),
- // To Wishbone
- .d_dat_o (D_DAT_O),
- .d_adr_o (D_ADR_O),
- .d_cyc_o (D_CYC_O),
- .d_sel_o (D_SEL_O),
- .d_stb_o (D_STB_O),
- .d_we_o (D_WE_O),
- .d_cti_o (D_CTI_O),
- .d_lock_o (D_LOCK_O),
- .d_bte_o (D_BTE_O)
- );
-
-// Adder
-lm32_adder adder (
- // ----- Inputs -------
- .adder_op_x (adder_op_x),
- .adder_op_x_n (adder_op_x_n),
- .operand_0_x (operand_0_x),
- .operand_1_x (operand_1_x),
- // ----- Outputs -------
- .adder_result_x (adder_result_x),
- .adder_carry_n_x (adder_carry_n_x),
- .adder_overflow_x (adder_overflow_x)
- );
-
-// Logic operations
-lm32_logic_op logic_op (
- // ----- Inputs -------
- .logic_op_x (logic_op_x),
- .operand_0_x (operand_0_x),
-
- .operand_1_x (operand_1_x),
- // ----- Outputs -------
- .logic_result_x (logic_result_x)
- );
-
-`ifdef CFG_PL_BARREL_SHIFT_ENABLED
-// Pipelined barrel-shifter
-lm32_shifter shifter (
- // ----- Inputs -------
- .clk_i (clk_i),
- .rst_i (rst_i),
- .stall_x (stall_x),
- .direction_x (direction_x),
- .sign_extend_x (sign_extend_x),
- .operand_0_x (operand_0_x),
- .operand_1_x (operand_1_x),
- // ----- Outputs -------
- .shifter_result_m (shifter_result_m)
- );
-`endif
-
-`ifdef CFG_PL_MULTIPLY_ENABLED
-// Pipeline fixed-point multiplier
-lm32_multiplier multiplier (
- // ----- Inputs -------
- .clk_i (clk_i),
- .rst_i (rst_i),
- .stall_x (stall_x),
- .stall_m (stall_m),
- .operand_0 (d_result_0),
- .operand_1 (d_result_1),
- // ----- Outputs -------
- .result (multiplier_result_w)
- );
-`endif
-
-`ifdef LM32_MC_ARITHMETIC_ENABLED
-// Multi-cycle arithmetic
-lm32_mc_arithmetic mc_arithmetic (
- // ----- Inputs -------
- .clk_i (clk_i),
- .rst_i (rst_i),
- .stall_d (stall_d),
- .kill_x (kill_x),
-`ifdef CFG_MC_DIVIDE_ENABLED
- .divide_d (divide_q_d),
- .modulus_d (modulus_q_d),
-`endif
-`ifdef CFG_MC_MULTIPLY_ENABLED
- .multiply_d (multiply_q_d),
-`endif
-`ifdef CFG_MC_BARREL_SHIFT_ENABLED
- .shift_left_d (shift_left_q_d),
- .shift_right_d (shift_right_q_d),
- .sign_extend_d (sign_extend_d),
-`endif
- .operand_0_d (d_result_0),
- .operand_1_d (d_result_1),
- // ----- Outputs -------
- .result_x (mc_result_x),
-`ifdef CFG_MC_DIVIDE_ENABLED
- .divide_by_zero_x (divide_by_zero_x),
-`endif
- .stall_request_x (mc_stall_request_x)
- );
-`endif
-
-`ifdef CFG_INTERRUPTS_ENABLED
-// Interrupt unit
-lm32_interrupt interrupt_unit (
- // ----- Inputs -------
- .clk_i (clk_i),
- .rst_i (rst_i),
- // From external devices
- .interrupt (interrupt),
- // From pipeline
- .stall_x (stall_x),
-`ifdef CFG_DEBUG_ENABLED
- .non_debug_exception (non_debug_exception_q_w),
- .debug_exception (debug_exception_q_w),
-`else
- .exception (exception_q_w),
-`endif
- .eret_q_x (eret_q_x),
-`ifdef CFG_DEBUG_ENABLED
- .bret_q_x (bret_q_x),
-`endif
- .csr (csr_x),
- .csr_write_data (operand_1_x),
- .csr_write_enable (csr_write_enable_q_x),
- // ----- Outputs -------
- .interrupt_exception (interrupt_exception),
- // To pipeline
- .csr_read_data (interrupt_csr_read_data_x)
- );
-`endif
-
-`ifdef CFG_JTAG_ENABLED
-// JTAG interface
-lm32_jtag jtag (
- // ----- Inputs -------
- .clk_i (clk_i),
- .rst_i (rst_i),
- // From JTAG
- .jtag_clk (jtag_clk),
- .jtag_update (jtag_update),
- .jtag_reg_q (jtag_reg_q),
- .jtag_reg_addr_q (jtag_reg_addr_q),
- // From pipeline
-`ifdef CFG_JTAG_UART_ENABLED
- .csr (csr_x),
- .csr_write_data (operand_1_x),
- .csr_write_enable (csr_write_enable_q_x),
- .stall_x (stall_x),
-`endif
-`ifdef CFG_HW_DEBUG_ENABLED
- .jtag_read_data (jtag_read_data),
- .jtag_access_complete (jtag_access_complete),
-`endif
-`ifdef CFG_DEBUG_ENABLED
- .exception_q_w (debug_exception_q_w || non_debug_exception_q_w),
-`endif
- // ----- Outputs -------
- // To pipeline
-`ifdef CFG_JTAG_UART_ENABLED
- .jtx_csr_read_data (jtx_csr_read_data),
- .jrx_csr_read_data (jrx_csr_read_data),
-`endif
-`ifdef CFG_HW_DEBUG_ENABLED
- .jtag_csr_write_enable (jtag_csr_write_enable),
- .jtag_csr_write_data (jtag_csr_write_data),
- .jtag_csr (jtag_csr),
- .jtag_read_enable (jtag_read_enable),
- .jtag_write_enable (jtag_write_enable),
- .jtag_write_data (jtag_write_data),
- .jtag_address (jtag_address),
-`endif
-`ifdef CFG_DEBUG_ENABLED
- .jtag_break (jtag_break),
- .jtag_reset (reset_exception),
-`endif
- // To JTAG
- .jtag_reg_d (jtag_reg_d),
- .jtag_reg_addr_d (jtag_reg_addr_d)
- );
-`endif
-
-`ifdef CFG_DEBUG_ENABLED
-// Debug unit
-lm32_debug #(
- .breakpoints (breakpoints),
- .watchpoints (watchpoints)
- ) hw_debug (
- // ----- Inputs -------
- .clk_i (clk_i),
- .rst_i (rst_i),
- .pc_x (pc_x),
- .load_x (load_x),
- .store_x (store_x),
- .load_store_address_x (adder_result_x),
- .csr_write_enable_x (csr_write_enable_q_x),
- .csr_write_data (operand_1_x),
- .csr_x (csr_x),
-`ifdef CFG_HW_DEBUG_ENABLED
- .jtag_csr_write_enable (jtag_csr_write_enable),
- .jtag_csr_write_data (jtag_csr_write_data),
- .jtag_csr (jtag_csr),
-`endif
-`ifdef LM32_SINGLE_STEP_ENABLED
- .eret_q_x (eret_q_x),
- .bret_q_x (bret_q_x),
- .stall_x (stall_x),
- .exception_x (exception_x),
- .q_x (q_x),
-`ifdef CFG_DCACHE_ENABLED
- .dcache_refill_request (dcache_refill_request),
-`endif
-`endif
- // ----- Outputs -------
-`ifdef LM32_SINGLE_STEP_ENABLED
- .dc_ss (dc_ss),
-`endif
- .dc_re (dc_re),
- .bp_match (bp_match),
- .wp_match (wp_match)
- );
-`endif
-
-// Register file
-
-`ifdef CFG_EBR_POSEDGE_REGISTER_FILE
- /*----------------------------------------------------------------------
- Register File is implemented using EBRs. There can be three accesses to
- the register file in each cycle: two reads and one write. On-chip block
- RAM has two read/write ports. To accomodate three accesses, two on-chip
- block RAMs are used (each register file "write" is made to both block
- RAMs).
-
- One limitation of the on-chip block RAMs is that one cannot perform a
- read and write to same location in a cycle (if this is done, then the
- data read out is indeterminate).
- ----------------------------------------------------------------------*/
- wire [31:0] regfile_data_0, regfile_data_1;
- reg [31:0] w_result_d;
- reg regfile_raw_0, regfile_raw_0_nxt;
- reg regfile_raw_1, regfile_raw_1_nxt;
-
- /*----------------------------------------------------------------------
- Check if read and write is being performed to same register in current
- cycle? This is done by comparing the read and write IDXs.
- ----------------------------------------------------------------------*/
- always @(reg_write_enable_q_w or write_idx_w or instruction_f)
- begin
- if (reg_write_enable_q_w
- && (write_idx_w == instruction_f[25:21]))
- regfile_raw_0_nxt = 1'b1;
- else
- regfile_raw_0_nxt = 1'b0;
-
- if (reg_write_enable_q_w
- && (write_idx_w == instruction_f[20:16]))
- regfile_raw_1_nxt = 1'b1;
- else
- regfile_raw_1_nxt = 1'b0;
- end
-
- /*----------------------------------------------------------------------
- Select latched (delayed) write value or data from register file. If
- read in previous cycle was performed to register written to in same
- cycle, then latched (delayed) write value is selected.
- ----------------------------------------------------------------------*/
- always @(regfile_raw_0 or w_result_d or regfile_data_0)
- if (regfile_raw_0)
- reg_data_live_0 = w_result_d;
- else
- reg_data_live_0 = regfile_data_0;
-
- /*----------------------------------------------------------------------
- Select latched (delayed) write value or data from register file. If
- read in previous cycle was performed to register written to in same
- cycle, then latched (delayed) write value is selected.
- ----------------------------------------------------------------------*/
- always @(regfile_raw_1 or w_result_d or regfile_data_1)
- if (regfile_raw_1)
- reg_data_live_1 = w_result_d;
- else
- reg_data_live_1 = regfile_data_1;
-
- /*----------------------------------------------------------------------
- Latch value written to register file
- ----------------------------------------------------------------------*/
- always @(posedge clk_i `CFG_RESET_SENSITIVITY)
- if (rst_i == `TRUE)
- begin
- regfile_raw_0 <= 1'b0;
- regfile_raw_1 <= 1'b0;
- w_result_d <= 32'b0;
- end
- else
- begin
- regfile_raw_0 <= regfile_raw_0_nxt;
- regfile_raw_1 <= regfile_raw_1_nxt;
- w_result_d <= w_result;
- end
-
- /*----------------------------------------------------------------------
- Register file instantiation as Pseudo-Dual Port EBRs.
- ----------------------------------------------------------------------*/
- // Modified by GSI: removed non-portable RAM instantiation
- lm32_dp_ram
- #(
- // ----- Parameters -----
- .addr_width(5),
- .data_width(32)
- )
- reg_0
- (
- // ----- Inputs -----
- .clk_i (clk_i),
- .rst_i (rst_i),
- .we_i (reg_write_enable_q_w),
- .wdata_i (w_result),
- .waddr_i (write_idx_w),
- .raddr_i (instruction_f[25:21]),
- // ----- Outputs -----
- .rdata_o (regfile_data_0)
- );
-
- lm32_dp_ram
- #(
- .addr_width(5),
- .data_width(32)
- )
- reg_1
- (
- // ----- Inputs -----
- .clk_i (clk_i),
- .rst_i (rst_i),
- .we_i (reg_write_enable_q_w),
- .wdata_i (w_result),
- .waddr_i (write_idx_w),
- .raddr_i (instruction_f[20:16]),
- // ----- Outputs -----
- .rdata_o (regfile_data_1)
- );
-`endif
-
-`ifdef CFG_EBR_NEGEDGE_REGISTER_FILE
- pmi_ram_dp
- #(
- // ----- Parameters -----
- .pmi_wr_addr_depth(1<<5),
- .pmi_wr_addr_width(5),
- .pmi_wr_data_width(32),
- .pmi_rd_addr_depth(1<<5),
- .pmi_rd_addr_width(5),
- .pmi_rd_data_width(32),
- .pmi_regmode("noreg"),
- .pmi_gsr("enable"),
- .pmi_resetmode("sync"),
- .pmi_init_file("none"),
- .pmi_init_file_format("binary"),
- .pmi_family(`LATTICE_FAMILY),
- .module_type("pmi_ram_dp")
- )
- reg_0
- (
- // ----- Inputs -----
- .Data(w_result),
- .WrAddress(write_idx_w),
- .RdAddress(read_idx_0_d),
- .WrClock(clk_i),
- .RdClock(clk_n_i),
- .WrClockEn(`TRUE),
- .RdClockEn(stall_f == `FALSE),
- .WE(reg_write_enable_q_w),
- .Reset(rst_i),
- // ----- Outputs -----
- .Q(reg_data_0)
- );
-
- pmi_ram_dp
- #(
- // ----- Parameters -----
- .pmi_wr_addr_depth(1<<5),
- .pmi_wr_addr_width(5),
- .pmi_wr_data_width(32),
- .pmi_rd_addr_depth(1<<5),
- .pmi_rd_addr_width(5),
- .pmi_rd_data_width(32),
- .pmi_regmode("noreg"),
- .pmi_gsr("enable"),
- .pmi_resetmode("sync"),
- .pmi_init_file("none"),
- .pmi_init_file_format("binary"),
- .pmi_family(`LATTICE_FAMILY),
- .module_type("pmi_ram_dp")
- )
- reg_1
- (
- // ----- Inputs -----
- .Data(w_result),
- .WrAddress(write_idx_w),
- .RdAddress(read_idx_1_d),
- .WrClock(clk_i),
- .RdClock(clk_n_i),
- .WrClockEn(`TRUE),
- .RdClockEn(stall_f == `FALSE),
- .WE(reg_write_enable_q_w),
- .Reset(rst_i),
- // ----- Outputs -----
- .Q(reg_data_1)
- );
-`endif
-
-
-/////////////////////////////////////////////////////
-// Combinational Logic
-/////////////////////////////////////////////////////
-
-`ifdef CFG_EBR_POSEDGE_REGISTER_FILE
-// Select between buffered and live data from register file
-assign reg_data_0 = use_buf ? reg_data_buf_0 : reg_data_live_0;
-assign reg_data_1 = use_buf ? reg_data_buf_1 : reg_data_live_1;
-`endif
-`ifdef LM32_EBR_REGISTER_FILE
-`else
-// Register file read ports
-assign reg_data_0 = registers[read_idx_0_d];
-assign reg_data_1 = registers[read_idx_1_d];
-`endif
-
-// Detect read-after-write hazzards
-assign raw_x_0 = (write_idx_x == read_idx_0_d) && (write_enable_q_x == `TRUE);
-assign raw_m_0 = (write_idx_m == read_idx_0_d) && (write_enable_q_m == `TRUE);
-assign raw_w_0 = (write_idx_w == read_idx_0_d) && (write_enable_q_w == `TRUE);
-assign raw_x_1 = (write_idx_x == read_idx_1_d) && (write_enable_q_x == `TRUE);
-assign raw_m_1 = (write_idx_m == read_idx_1_d) && (write_enable_q_m == `TRUE);
-assign raw_w_1 = (write_idx_w == read_idx_1_d) && (write_enable_q_w == `TRUE);
-
-// Interlock detection - Raise an interlock for RAW hazzards
-always @(*)
-begin
- if ( ( (x_bypass_enable_x == `FALSE)
- && ( ((read_enable_0_d == `TRUE) && (raw_x_0 == `TRUE))
- || ((read_enable_1_d == `TRUE) && (raw_x_1 == `TRUE))
- )
- )
- || ( (m_bypass_enable_m == `FALSE)
- && ( ((read_enable_0_d == `TRUE) && (raw_m_0 == `TRUE))
- || ((read_enable_1_d == `TRUE) && (raw_m_1 == `TRUE))
- )
- )
- )
- interlock = `TRUE;
- else
- interlock = `FALSE;
-end
-
-// Bypass for reg port 0
-always @(*)
-begin
- if (raw_x_0 == `TRUE)
- bypass_data_0 = x_result;
- else if (raw_m_0 == `TRUE)
- bypass_data_0 = m_result;
- else if (raw_w_0 == `TRUE)
- bypass_data_0 = w_result;
- else
- bypass_data_0 = reg_data_0;
-end
-
-// Bypass for reg port 1
-always @(*)
-begin
- if (raw_x_1 == `TRUE)
- bypass_data_1 = x_result;
- else if (raw_m_1 == `TRUE)
- bypass_data_1 = m_result;
- else if (raw_w_1 == `TRUE)
- bypass_data_1 = w_result;
- else
- bypass_data_1 = reg_data_1;
-end
-
- /*----------------------------------------------------------------------
- Branch prediction is performed in D stage of pipeline. Only PC-relative
- branches are predicted: forward-pointing conditional branches are not-
- taken, while backward-pointing conditional branches are taken.
- Unconditional branches are always predicted taken!
- ----------------------------------------------------------------------*/
- assign branch_predict_d = bi_unconditional | bi_conditional;
- assign branch_predict_taken_d = bi_unconditional ? 1'b1 : (bi_conditional ? instruction_d[15] : 1'b0);
-
- // Compute branch target address: Branch PC PLUS Offset
- assign branch_target_d = pc_d + branch_offset_d;
-
- // Compute fetch address. Address of instruction sequentially after the
- // branch if branch is not taken. Target address of branch is branch is
- // taken
- assign branch_predict_address_d = branch_predict_taken_d ? branch_target_d : pc_f;
-
-// D stage result selection
-always @(*)
-begin
- d_result_0 = d_result_sel_0_d[0] ? {pc_f, 2'b00} : bypass_data_0;
- case (d_result_sel_1_d)
- `LM32_D_RESULT_SEL_1_ZERO: d_result_1 = {`LM32_WORD_WIDTH{1'b0}};
- `LM32_D_RESULT_SEL_1_REG_1: d_result_1 = bypass_data_1;
- `LM32_D_RESULT_SEL_1_IMMEDIATE: d_result_1 = immediate_d;
- default: d_result_1 = {`LM32_WORD_WIDTH{1'bx}};
- endcase
-end
-
-`ifdef CFG_USER_ENABLED
-// Operands for user-defined instructions
-assign user_operand_0 = operand_0_x;
-assign user_operand_1 = operand_1_x;
-`endif
-
-`ifdef CFG_SIGN_EXTEND_ENABLED
-// Sign-extension
-assign sextb_result_x = {{24{operand_0_x[7]}}, operand_0_x[7:0]};
-assign sexth_result_x = {{16{operand_0_x[15]}}, operand_0_x[15:0]};
-assign sext_result_x = size_x == `LM32_SIZE_BYTE ? sextb_result_x : sexth_result_x;
-`endif
-
-`ifdef LM32_NO_BARREL_SHIFT
-// Only single bit shift operations are supported when barrel-shifter isn't implemented
-assign shifter_result_x = {operand_0_x[`LM32_WORD_WIDTH-1] & sign_extend_x, operand_0_x[`LM32_WORD_WIDTH-1:1]};
-`endif
-
-// Condition evaluation
-assign cmp_zero = operand_0_x == operand_1_x;
-assign cmp_negative = adder_result_x[`LM32_WORD_WIDTH-1];
-assign cmp_overflow = adder_overflow_x;
-assign cmp_carry_n = adder_carry_n_x;
-always @(*)
-begin
- case (condition_x)
- `LM32_CONDITION_U1: condition_met_x = `TRUE;
- `LM32_CONDITION_U2: condition_met_x = `TRUE;
- `LM32_CONDITION_E: condition_met_x = cmp_zero;
- `LM32_CONDITION_NE: condition_met_x = !cmp_zero;
- `LM32_CONDITION_G: condition_met_x = !cmp_zero && (cmp_negative == cmp_overflow);
- `LM32_CONDITION_GU: condition_met_x = cmp_carry_n && !cmp_zero;
- `LM32_CONDITION_GE: condition_met_x = cmp_negative == cmp_overflow;
- `LM32_CONDITION_GEU: condition_met_x = cmp_carry_n;
- default: condition_met_x = 1'bx;
- endcase
-end
-
-// X stage result selection
-always @(*)
-begin
- x_result = x_result_sel_add_x ? adder_result_x
- : x_result_sel_csr_x ? csr_read_data_x
-`ifdef CFG_SIGN_EXTEND_ENABLED
- : x_result_sel_sext_x ? sext_result_x
-`endif
-`ifdef CFG_USER_ENABLED
- : x_result_sel_user_x ? user_result
-`endif
-`ifdef LM32_NO_BARREL_SHIFT
- : x_result_sel_shift_x ? shifter_result_x
-`endif
-`ifdef LM32_MC_ARITHMETIC_ENABLED
- : x_result_sel_mc_arith_x ? mc_result_x
-`endif
- : logic_result_x;
-end
-
-// M stage result selection
-always @(*)
-begin
- m_result = m_result_sel_compare_m ? {{`LM32_WORD_WIDTH-1{1'b0}}, condition_met_m}
-`ifdef CFG_PL_BARREL_SHIFT_ENABLED
- : m_result_sel_shift_m ? shifter_result_m
-`endif
- : operand_m;
-end
-
-// W stage result selection
-always @(*)
-begin
- w_result = w_result_sel_load_w ? load_data_w
-`ifdef CFG_PL_MULTIPLY_ENABLED
- : w_result_sel_mul_w ? multiplier_result_w
-`endif
- : operand_w;
-end
-
-`ifdef CFG_FAST_UNCONDITIONAL_BRANCH
-// Indicate when a branch should be taken in X stage
-assign branch_taken_x = (stall_x == `FALSE)
- && ( (branch_x == `TRUE)
- && ((condition_x == `LM32_CONDITION_U1) || (condition_x == `LM32_CONDITION_U2))
- && (valid_x == `TRUE)
- && (branch_predict_x == `FALSE)
- );
-`endif
-
-// Indicate when a branch should be taken in M stage (exceptions are a type of branch)
-assign branch_taken_m = (stall_m == `FALSE)
- && ( ( (branch_m == `TRUE)
- && (valid_m == `TRUE)
- && ( ( (condition_met_m == `TRUE)
- && (branch_predict_taken_m == `FALSE)
- )
- || ( (condition_met_m == `FALSE)
- && (branch_predict_m == `TRUE)
- && (branch_predict_taken_m == `TRUE)
- )
- )
- )
- || (exception_m == `TRUE)
- );
-
-// Indicate when a branch in M stage is mispredicted as being taken
-assign branch_mispredict_taken_m = (condition_met_m == `FALSE)
- && (branch_predict_m == `TRUE)
- && (branch_predict_taken_m == `TRUE);
-
-// Indicate when a branch in M stage will cause flush in X stage
-assign branch_flushX_m = (stall_m == `FALSE)
- && ( ( (branch_m == `TRUE)
- && (valid_m == `TRUE)
- && ( (condition_met_m == `TRUE)
- || ( (condition_met_m == `FALSE)
- && (branch_predict_m == `TRUE)
- && (branch_predict_taken_m == `TRUE)
- )
- )
- )
- || (exception_m == `TRUE)
- );
-
-// Generate signal that will kill instructions in each pipeline stage when necessary
-assign kill_f = ( (valid_d == `TRUE)
- && (branch_predict_taken_d == `TRUE)
- )
- || (branch_taken_m == `TRUE)
-`ifdef CFG_FAST_UNCONDITIONAL_BRANCH
- || (branch_taken_x == `TRUE)
-`endif
-`ifdef CFG_ICACHE_ENABLED
- || (icache_refill_request == `TRUE)
-`endif
-`ifdef CFG_DCACHE_ENABLED
- || (dcache_refill_request == `TRUE)
-`endif
- ;
-assign kill_d = (branch_taken_m == `TRUE)
-`ifdef CFG_FAST_UNCONDITIONAL_BRANCH
- || (branch_taken_x == `TRUE)
-`endif
-`ifdef CFG_ICACHE_ENABLED
- || (icache_refill_request == `TRUE)
-`endif
-`ifdef CFG_DCACHE_ENABLED
- || (dcache_refill_request == `TRUE)
-`endif
- ;
-assign kill_x = (branch_flushX_m == `TRUE)
-`ifdef CFG_DCACHE_ENABLED
- || (dcache_refill_request == `TRUE)
-`endif
- ;
-assign kill_m = `FALSE
-`ifdef CFG_DCACHE_ENABLED
- || (dcache_refill_request == `TRUE)
-`endif
- ;
-assign kill_w = `FALSE
-`ifdef CFG_DCACHE_ENABLED
- || (dcache_refill_request == `TRUE)
-`endif
- ;
-
-// Exceptions
-
-`ifdef CFG_DEBUG_ENABLED
-assign breakpoint_exception = ( ( (break_x == `TRUE)
- || (bp_match == `TRUE)
- )
- && (valid_x == `TRUE)
- )
-`ifdef CFG_JTAG_ENABLED
- || (jtag_break == `TRUE)
-`endif
-`ifdef CFG_EXTERNAL_BREAK_ENABLED
- || (ext_break_r == `TRUE)
-`endif
- ;
-`endif
-
-`ifdef CFG_DEBUG_ENABLED
-assign watchpoint_exception = wp_match == `TRUE;
-`endif
-
-`ifdef CFG_BUS_ERRORS_ENABLED
-assign instruction_bus_error_exception = ( (bus_error_x == `TRUE)
- && (valid_x == `TRUE)
- );
-assign data_bus_error_exception = data_bus_error_seen == `TRUE;
-`endif
-
-`ifdef CFG_MC_DIVIDE_ENABLED
-assign divide_by_zero_exception = divide_by_zero_x == `TRUE;
-`endif
-
-assign system_call_exception = ( (scall_x == `TRUE)
-`ifdef CFG_BUS_ERRORS_ENABLED
- && (valid_x == `TRUE)
-`endif
- );
-
-`ifdef CFG_DEBUG_ENABLED
-assign debug_exception_x = (breakpoint_exception == `TRUE)
- || (watchpoint_exception == `TRUE)
- ;
-
-assign non_debug_exception_x = (system_call_exception == `TRUE)
-`ifdef CFG_JTAG_ENABLED
- || (reset_exception == `TRUE)
-`endif
-`ifdef CFG_BUS_ERRORS_ENABLED
- || (instruction_bus_error_exception == `TRUE)
- || (data_bus_error_exception == `TRUE)
-`endif
-`ifdef CFG_MC_DIVIDE_ENABLED
- || (divide_by_zero_exception == `TRUE)
-`endif
-`ifdef CFG_INTERRUPTS_ENABLED
- || ( (interrupt_exception == `TRUE)
-`ifdef LM32_SINGLE_STEP_ENABLED
- && (dc_ss == `FALSE)
-`endif
-`ifdef CFG_BUS_ERRORS_ENABLED
- && (store_q_m == `FALSE)
- && (D_CYC_O == `FALSE)
-`endif
- )
-`endif
- ;
-
-assign exception_x = (debug_exception_x == `TRUE) || (non_debug_exception_x == `TRUE);
-`else
-assign exception_x = (system_call_exception == `TRUE)
-`ifdef CFG_BUS_ERRORS_ENABLED
- || (instruction_bus_error_exception == `TRUE)
- || (data_bus_error_exception == `TRUE)
-`endif
-`ifdef CFG_MC_DIVIDE_ENABLED
- || (divide_by_zero_exception == `TRUE)
-`endif
-`ifdef CFG_INTERRUPTS_ENABLED
- || ( (interrupt_exception == `TRUE)
-`ifdef LM32_SINGLE_STEP_ENABLED
- && (dc_ss == `FALSE)
-`endif
-`ifdef CFG_BUS_ERRORS_ENABLED
- && (store_q_m == `FALSE)
- && (D_CYC_O == `FALSE)
-`endif
- )
-`endif
- ;
-`endif
-
-// Exception ID
-always @(*)
-begin
-`ifdef CFG_DEBUG_ENABLED
-`ifdef CFG_JTAG_ENABLED
- if (reset_exception == `TRUE)
- eid_x = `LM32_EID_RESET;
- else
-`endif
-`ifdef CFG_BUS_ERRORS_ENABLED
- if (data_bus_error_exception == `TRUE)
- eid_x = `LM32_EID_DATA_BUS_ERROR;
- else
-`endif
- if (breakpoint_exception == `TRUE)
- eid_x = `LM32_EID_BREAKPOINT;
- else
-`endif
-`ifdef CFG_BUS_ERRORS_ENABLED
- if (data_bus_error_exception == `TRUE)
- eid_x = `LM32_EID_DATA_BUS_ERROR;
- else
- if (instruction_bus_error_exception == `TRUE)
- eid_x = `LM32_EID_INST_BUS_ERROR;
- else
-`endif
-`ifdef CFG_DEBUG_ENABLED
- if (watchpoint_exception == `TRUE)
- eid_x = `LM32_EID_WATCHPOINT;
- else
-`endif
-`ifdef CFG_MC_DIVIDE_ENABLED
- if (divide_by_zero_exception == `TRUE)
- eid_x = `LM32_EID_DIVIDE_BY_ZERO;
- else
-`endif
-`ifdef CFG_INTERRUPTS_ENABLED
- if ( (interrupt_exception == `TRUE)
-`ifdef LM32_SINGLE_STEP_ENABLED
- && (dc_ss == `FALSE)
-`endif
- )
- eid_x = `LM32_EID_INTERRUPT;
- else
-`endif
- eid_x = `LM32_EID_SCALL;
-end
-
-// Stall generation
-
-assign stall_a = (stall_f == `TRUE);
-
-assign stall_f = (stall_d == `TRUE);
-
-assign stall_d = (stall_x == `TRUE)
- || ( (interlock == `TRUE)
- && (kill_d == `FALSE)
- )
- || ( ( (eret_d == `TRUE)
- || (scall_d == `TRUE)
-`ifdef CFG_BUS_ERRORS_ENABLED
- || (bus_error_d == `TRUE)
-`endif
- )
- && ( (load_q_x == `TRUE)
- || (load_q_m == `TRUE)
- || (store_q_x == `TRUE)
- || (store_q_m == `TRUE)
- || (D_CYC_O == `TRUE)
- )
- && (kill_d == `FALSE)
- )
-`ifdef CFG_DEBUG_ENABLED
- || ( ( (break_d == `TRUE)
- || (bret_d == `TRUE)
- )
- && ( (load_q_x == `TRUE)
- || (store_q_x == `TRUE)
- || (load_q_m == `TRUE)
- || (store_q_m == `TRUE)
- || (D_CYC_O == `TRUE)
- )
- && (kill_d == `FALSE)
- )
-`endif
- || ( (csr_write_enable_d == `TRUE)
- && (load_q_x == `TRUE)
- )
- ;
-
-assign stall_x = (stall_m == `TRUE)
-`ifdef LM32_MC_ARITHMETIC_ENABLED
- || ( (mc_stall_request_x == `TRUE)
- && (kill_x == `FALSE)
- )
-`endif
-`ifdef CFG_IROM_ENABLED
- // Stall load/store instruction in D stage if there is an ongoing store
- // operation to instruction ROM in M stage
- || ( (irom_stall_request_x == `TRUE)
- && ( (load_d == `TRUE)
- || (store_d == `TRUE)
- )
- )
-`endif
- ;
-
-assign stall_m = (stall_wb_load == `TRUE)
-`ifdef CFG_SIZE_OVER_SPEED
- || (D_CYC_O == `TRUE)
-`else
- || ( (D_CYC_O == `TRUE)
- && ( (store_m == `TRUE)
- /*
- Bug: Following loop does not allow interrupts to be services since
- either D_CYC_O or store_m is always high during entire duration of
- loop.
- L1: addi r1, r1, 1
- sw (r2,0), r1
- bi L1
-
- Introduce a single-cycle stall when a wishbone cycle is in progress
- and a new store instruction is in Execute stage and a interrupt
- exception has occured. This stall will ensure that D_CYC_O and
- store_m will both be low for one cycle.
- */
-`ifdef CFG_INTERRUPTS_ENABLED
- || ((store_x == `TRUE) && (interrupt_exception == `TRUE))
-`endif
- || (load_m == `TRUE)
- || (load_x == `TRUE)
- )
- )
-`endif
-`ifdef CFG_DCACHE_ENABLED
- || (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
-`endif
-`ifdef CFG_ICACHE_ENABLED