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