lm32_mc_arithmetic.v

changeset 0
cd0b58aa6f83
child 26
73de224304c1
     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