1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/lm32_mc_arithmetic.v Sun Apr 04 20:40:03 2010 +0100 1.3 @@ -0,0 +1,288 @@ 1.4 +// ============================================================================= 1.5 +// COPYRIGHT NOTICE 1.6 +// Copyright 2006 (c) Lattice Semiconductor Corporation 1.7 +// ALL RIGHTS RESERVED 1.8 +// This confidential and proprietary software may be used only as authorised by 1.9 +// a licensing agreement from Lattice Semiconductor Corporation. 1.10 +// The entire notice above must be reproduced on all authorized copies and 1.11 +// copies may only be made to the extent permitted by a licensing agreement from 1.12 +// Lattice Semiconductor Corporation. 1.13 +// 1.14 +// Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada) 1.15 +// 5555 NE Moore Court 408-826-6000 (other locations) 1.16 +// Hillsboro, OR 97124 web : http://www.latticesemi.com/ 1.17 +// U.S.A email: techsupport@latticesemi.com 1.18 +// =============================================================================/ 1.19 +// FILE DETAILS 1.20 +// Project : LatticeMico32 1.21 +// File : lm_mc_arithmetic.v 1.22 +// Title : Multi-cycle arithmetic unit. 1.23 +// Dependencies : lm32_include.v 1.24 +// Version : 6.1.17 1.25 +// : Initial Release 1.26 +// Version : 7.0SP2, 3.0 1.27 +// : No Change 1.28 +// Version : 3.1 1.29 +// : No Change 1.30 +// ============================================================================= 1.31 + 1.32 +`include "lm32_include.v" 1.33 + 1.34 +`define LM32_MC_STATE_RNG 2:0 1.35 +`define LM32_MC_STATE_IDLE 3'b000 1.36 +`define LM32_MC_STATE_MULTIPLY 3'b001 1.37 +`define LM32_MC_STATE_MODULUS 3'b010 1.38 +`define LM32_MC_STATE_DIVIDE 3'b011 1.39 +`define LM32_MC_STATE_SHIFT_LEFT 3'b100 1.40 +`define LM32_MC_STATE_SHIFT_RIGHT 3'b101 1.41 + 1.42 +///////////////////////////////////////////////////// 1.43 +// Module interface 1.44 +///////////////////////////////////////////////////// 1.45 + 1.46 +module lm32_mc_arithmetic ( 1.47 + // ----- Inputs ----- 1.48 + clk_i, 1.49 + rst_i, 1.50 + stall_d, 1.51 + kill_x, 1.52 +`ifdef CFG_MC_DIVIDE_ENABLED 1.53 + divide_d, 1.54 + modulus_d, 1.55 +`endif 1.56 +`ifdef CFG_MC_MULTIPLY_ENABLED 1.57 + multiply_d, 1.58 +`endif 1.59 +`ifdef CFG_MC_BARREL_SHIFT_ENABLED 1.60 + shift_left_d, 1.61 + shift_right_d, 1.62 + sign_extend_d, 1.63 +`endif 1.64 + operand_0_d, 1.65 + operand_1_d, 1.66 + // ----- Ouputs ----- 1.67 + result_x, 1.68 +`ifdef CFG_MC_DIVIDE_ENABLED 1.69 + divide_by_zero_x, 1.70 +`endif 1.71 + stall_request_x 1.72 + ); 1.73 + 1.74 +///////////////////////////////////////////////////// 1.75 +// Inputs 1.76 +///////////////////////////////////////////////////// 1.77 + 1.78 +input clk_i; // Clock 1.79 +input rst_i; // Reset 1.80 +input stall_d; // Stall instruction in D stage 1.81 +input kill_x; // Kill instruction in X stage 1.82 +`ifdef CFG_MC_DIVIDE_ENABLED 1.83 +input divide_d; // Perform divide 1.84 +input modulus_d; // Perform modulus 1.85 +`endif 1.86 +`ifdef CFG_MC_MULTIPLY_ENABLED 1.87 +input multiply_d; // Perform multiply 1.88 +`endif 1.89 +`ifdef CFG_MC_BARREL_SHIFT_ENABLED 1.90 +input shift_left_d; // Perform left shift 1.91 +input shift_right_d; // Perform right shift 1.92 +input sign_extend_d; // Whether to sign-extend (arithmetic) or zero-extend (logical) 1.93 +`endif 1.94 +input [`LM32_WORD_RNG] operand_0_d; 1.95 +input [`LM32_WORD_RNG] operand_1_d; 1.96 + 1.97 +///////////////////////////////////////////////////// 1.98 +// Outputs 1.99 +///////////////////////////////////////////////////// 1.100 + 1.101 +output [`LM32_WORD_RNG] result_x; // Result of operation 1.102 +reg [`LM32_WORD_RNG] result_x; 1.103 +`ifdef CFG_MC_DIVIDE_ENABLED 1.104 +output divide_by_zero_x; // A divide by zero was attempted 1.105 +reg divide_by_zero_x; 1.106 +`endif 1.107 +output stall_request_x; // Request to stall pipeline from X stage back 1.108 +wire stall_request_x; 1.109 + 1.110 +///////////////////////////////////////////////////// 1.111 +// Internal nets and registers 1.112 +///////////////////////////////////////////////////// 1.113 + 1.114 +reg [`LM32_WORD_RNG] p; // Temporary registers 1.115 +reg [`LM32_WORD_RNG] a; 1.116 +reg [`LM32_WORD_RNG] b; 1.117 +`ifdef CFG_MC_DIVIDE_ENABLED 1.118 +wire [32:0] t; 1.119 +`endif 1.120 + 1.121 +reg [`LM32_MC_STATE_RNG] state; // Current state of FSM 1.122 +reg [5:0] cycles; // Number of cycles remaining in the operation 1.123 + 1.124 +`ifdef CFG_MC_BARREL_SHIFT_ENABLED 1.125 +reg sign_extend_x; // Whether to sign extend of zero extend right shifts 1.126 +wire fill_value; // Value to fill with for right barrel-shifts 1.127 +`endif 1.128 + 1.129 +///////////////////////////////////////////////////// 1.130 +// Combinational logic 1.131 +///////////////////////////////////////////////////// 1.132 + 1.133 +// Stall pipeline while any operation is being performed 1.134 +assign stall_request_x = state != `LM32_MC_STATE_IDLE; 1.135 + 1.136 +`ifdef CFG_MC_DIVIDE_ENABLED 1.137 +// Subtraction 1.138 +assign t = {p[`LM32_WORD_WIDTH-2:0], a[`LM32_WORD_WIDTH-1]} - b; 1.139 +`endif 1.140 + 1.141 +`ifdef CFG_MC_BARREL_SHIFT_ENABLED 1.142 +// Determine fill value for right shift - Sign bit for arithmetic shift, or zero for logical shift 1.143 +assign fill_value = (sign_extend_x == `TRUE) & b[`LM32_WORD_WIDTH-1]; 1.144 +`endif 1.145 + 1.146 +///////////////////////////////////////////////////// 1.147 +// Sequential logic 1.148 +///////////////////////////////////////////////////// 1.149 + 1.150 +// Perform right shift 1.151 +always @(posedge clk_i `CFG_RESET_SENSITIVITY) 1.152 +begin 1.153 + if (rst_i == `TRUE) 1.154 + begin 1.155 + cycles <= {6{1'b0}}; 1.156 + p <= {`LM32_WORD_WIDTH{1'b0}}; 1.157 + a <= {`LM32_WORD_WIDTH{1'b0}}; 1.158 + b <= {`LM32_WORD_WIDTH{1'b0}}; 1.159 +`ifdef CFG_MC_BARREL_SHIFT_ENABLED 1.160 + sign_extend_x <= 1'b0; 1.161 +`endif 1.162 +`ifdef CFG_MC_DIVIDE_ENABLED 1.163 + divide_by_zero_x <= `FALSE; 1.164 +`endif 1.165 + result_x <= {`LM32_WORD_WIDTH{1'b0}}; 1.166 + state <= `LM32_MC_STATE_IDLE; 1.167 + end 1.168 + else 1.169 + begin 1.170 +`ifdef CFG_MC_DIVIDE_ENABLED 1.171 + divide_by_zero_x <= `FALSE; 1.172 +`endif 1.173 + case (state) 1.174 + `LM32_MC_STATE_IDLE: 1.175 + begin 1.176 + if (stall_d == `FALSE) 1.177 + begin 1.178 + cycles <= `LM32_WORD_WIDTH; 1.179 + p <= 32'b0; 1.180 + a <= operand_0_d; 1.181 + b <= operand_1_d; 1.182 +`ifdef CFG_MC_DIVIDE_ENABLED 1.183 + if (divide_d == `TRUE) 1.184 + state <= `LM32_MC_STATE_DIVIDE; 1.185 + if (modulus_d == `TRUE) 1.186 + state <= `LM32_MC_STATE_MODULUS; 1.187 +`endif 1.188 +`ifdef CFG_MC_MULTIPLY_ENABLED 1.189 + if (multiply_d == `TRUE) 1.190 + state <= `LM32_MC_STATE_MULTIPLY; 1.191 +`endif 1.192 +`ifdef CFG_MC_BARREL_SHIFT_ENABLED 1.193 + if (shift_left_d == `TRUE) 1.194 + begin 1.195 + state <= `LM32_MC_STATE_SHIFT_LEFT; 1.196 + sign_extend_x <= sign_extend_d; 1.197 + cycles <= operand_1_d[4:0]; 1.198 + a <= operand_0_d; 1.199 + b <= operand_0_d; 1.200 + end 1.201 + if (shift_right_d == `TRUE) 1.202 + begin 1.203 + state <= `LM32_MC_STATE_SHIFT_RIGHT; 1.204 + sign_extend_x <= sign_extend_d; 1.205 + cycles <= operand_1_d[4:0]; 1.206 + a <= operand_0_d; 1.207 + b <= operand_0_d; 1.208 + end 1.209 +`endif 1.210 + end 1.211 + end 1.212 +`ifdef CFG_MC_DIVIDE_ENABLED 1.213 + `LM32_MC_STATE_DIVIDE: 1.214 + begin 1.215 + if (t[32] == 1'b0) 1.216 + begin 1.217 + p <= t[31:0]; 1.218 + a <= {a[`LM32_WORD_WIDTH-2:0], 1'b1}; 1.219 + end 1.220 + else 1.221 + begin 1.222 + p <= {p[`LM32_WORD_WIDTH-2:0], a[`LM32_WORD_WIDTH-1]}; 1.223 + a <= {a[`LM32_WORD_WIDTH-2:0], 1'b0}; 1.224 + end 1.225 + result_x <= a; 1.226 + if ((cycles == `LM32_WORD_WIDTH'd0) || (kill_x == `TRUE)) 1.227 + begin 1.228 + // Check for divide by zero 1.229 + divide_by_zero_x <= b == {`LM32_WORD_WIDTH{1'b0}}; 1.230 + state <= `LM32_MC_STATE_IDLE; 1.231 + end 1.232 + cycles <= cycles - 1'b1; 1.233 + end 1.234 + `LM32_MC_STATE_MODULUS: 1.235 + begin 1.236 + if (t[32] == 1'b0) 1.237 + begin 1.238 + p <= t[31:0]; 1.239 + a <= {a[`LM32_WORD_WIDTH-2:0], 1'b1}; 1.240 + end 1.241 + else 1.242 + begin 1.243 + p <= {p[`LM32_WORD_WIDTH-2:0], a[`LM32_WORD_WIDTH-1]}; 1.244 + a <= {a[`LM32_WORD_WIDTH-2:0], 1'b0}; 1.245 + end 1.246 + result_x <= p; 1.247 + if ((cycles == `LM32_WORD_WIDTH'd0) || (kill_x == `TRUE)) 1.248 + begin 1.249 + // Check for divide by zero 1.250 + divide_by_zero_x <= b == {`LM32_WORD_WIDTH{1'b0}}; 1.251 + state <= `LM32_MC_STATE_IDLE; 1.252 + end 1.253 + cycles <= cycles - 1'b1; 1.254 + end 1.255 +`endif 1.256 +`ifdef CFG_MC_MULTIPLY_ENABLED 1.257 + `LM32_MC_STATE_MULTIPLY: 1.258 + begin 1.259 + if (b[0] == 1'b1) 1.260 + p <= p + a; 1.261 + b <= {1'b0, b[`LM32_WORD_WIDTH-1:1]}; 1.262 + a <= {a[`LM32_WORD_WIDTH-2:0], 1'b0}; 1.263 + result_x <= p; 1.264 + if ((cycles == `LM32_WORD_WIDTH'd0) || (kill_x == `TRUE)) 1.265 + state <= `LM32_MC_STATE_IDLE; 1.266 + cycles <= cycles - 1'b1; 1.267 + end 1.268 +`endif 1.269 +`ifdef CFG_MC_BARREL_SHIFT_ENABLED 1.270 + `LM32_MC_STATE_SHIFT_LEFT: 1.271 + begin 1.272 + a <= {a[`LM32_WORD_WIDTH-2:0], 1'b0}; 1.273 + result_x <= a; 1.274 + if ((cycles == `LM32_WORD_WIDTH'd0) || (kill_x == `TRUE)) 1.275 + state <= `LM32_MC_STATE_IDLE; 1.276 + cycles <= cycles - 1'b1; 1.277 + end 1.278 + `LM32_MC_STATE_SHIFT_RIGHT: 1.279 + begin 1.280 + b <= {fill_value, b[`LM32_WORD_WIDTH-1:1]}; 1.281 + result_x <= b; 1.282 + if ((cycles == `LM32_WORD_WIDTH'd0) || (kill_x == `TRUE)) 1.283 + state <= `LM32_MC_STATE_IDLE; 1.284 + cycles <= cycles - 1'b1; 1.285 + end 1.286 +`endif 1.287 + endcase 1.288 + end 1.289 +end 1.290 + 1.291 +endmodule