lm32_mc_arithmetic.v

Mon, 05 Apr 2010 20:23:04 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Mon, 05 Apr 2010 20:23:04 +0100
changeset 4
99b7b037ce82
parent 0
cd0b58aa6f83
child 26
73de224304c1
permissions
-rw-r--r--

add better comment re Xilinx Xst cache issues

philpem@0 1 // =============================================================================
philpem@0 2 // COPYRIGHT NOTICE
philpem@0 3 // Copyright 2006 (c) Lattice Semiconductor Corporation
philpem@0 4 // ALL RIGHTS RESERVED
philpem@0 5 // This confidential and proprietary software may be used only as authorised by
philpem@0 6 // a licensing agreement from Lattice Semiconductor Corporation.
philpem@0 7 // The entire notice above must be reproduced on all authorized copies and
philpem@0 8 // copies may only be made to the extent permitted by a licensing agreement from
philpem@0 9 // Lattice Semiconductor Corporation.
philpem@0 10 //
philpem@0 11 // Lattice Semiconductor Corporation TEL : 1-800-Lattice (USA and Canada)
philpem@0 12 // 5555 NE Moore Court 408-826-6000 (other locations)
philpem@0 13 // Hillsboro, OR 97124 web : http://www.latticesemi.com/
philpem@0 14 // U.S.A email: techsupport@latticesemi.com
philpem@0 15 // =============================================================================/
philpem@0 16 // FILE DETAILS
philpem@0 17 // Project : LatticeMico32
philpem@0 18 // File : lm_mc_arithmetic.v
philpem@0 19 // Title : Multi-cycle arithmetic unit.
philpem@0 20 // Dependencies : lm32_include.v
philpem@0 21 // Version : 6.1.17
philpem@0 22 // : Initial Release
philpem@0 23 // Version : 7.0SP2, 3.0
philpem@0 24 // : No Change
philpem@0 25 // Version : 3.1
philpem@0 26 // : No Change
philpem@0 27 // =============================================================================
philpem@0 28
philpem@0 29 `include "lm32_include.v"
philpem@0 30
philpem@0 31 `define LM32_MC_STATE_RNG 2:0
philpem@0 32 `define LM32_MC_STATE_IDLE 3'b000
philpem@0 33 `define LM32_MC_STATE_MULTIPLY 3'b001
philpem@0 34 `define LM32_MC_STATE_MODULUS 3'b010
philpem@0 35 `define LM32_MC_STATE_DIVIDE 3'b011
philpem@0 36 `define LM32_MC_STATE_SHIFT_LEFT 3'b100
philpem@0 37 `define LM32_MC_STATE_SHIFT_RIGHT 3'b101
philpem@0 38
philpem@0 39 /////////////////////////////////////////////////////
philpem@0 40 // Module interface
philpem@0 41 /////////////////////////////////////////////////////
philpem@0 42
philpem@0 43 module lm32_mc_arithmetic (
philpem@0 44 // ----- Inputs -----
philpem@0 45 clk_i,
philpem@0 46 rst_i,
philpem@0 47 stall_d,
philpem@0 48 kill_x,
philpem@0 49 `ifdef CFG_MC_DIVIDE_ENABLED
philpem@0 50 divide_d,
philpem@0 51 modulus_d,
philpem@0 52 `endif
philpem@0 53 `ifdef CFG_MC_MULTIPLY_ENABLED
philpem@0 54 multiply_d,
philpem@0 55 `endif
philpem@0 56 `ifdef CFG_MC_BARREL_SHIFT_ENABLED
philpem@0 57 shift_left_d,
philpem@0 58 shift_right_d,
philpem@0 59 sign_extend_d,
philpem@0 60 `endif
philpem@0 61 operand_0_d,
philpem@0 62 operand_1_d,
philpem@0 63 // ----- Ouputs -----
philpem@0 64 result_x,
philpem@0 65 `ifdef CFG_MC_DIVIDE_ENABLED
philpem@0 66 divide_by_zero_x,
philpem@0 67 `endif
philpem@0 68 stall_request_x
philpem@0 69 );
philpem@0 70
philpem@0 71 /////////////////////////////////////////////////////
philpem@0 72 // Inputs
philpem@0 73 /////////////////////////////////////////////////////
philpem@0 74
philpem@0 75 input clk_i; // Clock
philpem@0 76 input rst_i; // Reset
philpem@0 77 input stall_d; // Stall instruction in D stage
philpem@0 78 input kill_x; // Kill instruction in X stage
philpem@0 79 `ifdef CFG_MC_DIVIDE_ENABLED
philpem@0 80 input divide_d; // Perform divide
philpem@0 81 input modulus_d; // Perform modulus
philpem@0 82 `endif
philpem@0 83 `ifdef CFG_MC_MULTIPLY_ENABLED
philpem@0 84 input multiply_d; // Perform multiply
philpem@0 85 `endif
philpem@0 86 `ifdef CFG_MC_BARREL_SHIFT_ENABLED
philpem@0 87 input shift_left_d; // Perform left shift
philpem@0 88 input shift_right_d; // Perform right shift
philpem@0 89 input sign_extend_d; // Whether to sign-extend (arithmetic) or zero-extend (logical)
philpem@0 90 `endif
philpem@0 91 input [`LM32_WORD_RNG] operand_0_d;
philpem@0 92 input [`LM32_WORD_RNG] operand_1_d;
philpem@0 93
philpem@0 94 /////////////////////////////////////////////////////
philpem@0 95 // Outputs
philpem@0 96 /////////////////////////////////////////////////////
philpem@0 97
philpem@0 98 output [`LM32_WORD_RNG] result_x; // Result of operation
philpem@0 99 reg [`LM32_WORD_RNG] result_x;
philpem@0 100 `ifdef CFG_MC_DIVIDE_ENABLED
philpem@0 101 output divide_by_zero_x; // A divide by zero was attempted
philpem@0 102 reg divide_by_zero_x;
philpem@0 103 `endif
philpem@0 104 output stall_request_x; // Request to stall pipeline from X stage back
philpem@0 105 wire stall_request_x;
philpem@0 106
philpem@0 107 /////////////////////////////////////////////////////
philpem@0 108 // Internal nets and registers
philpem@0 109 /////////////////////////////////////////////////////
philpem@0 110
philpem@0 111 reg [`LM32_WORD_RNG] p; // Temporary registers
philpem@0 112 reg [`LM32_WORD_RNG] a;
philpem@0 113 reg [`LM32_WORD_RNG] b;
philpem@0 114 `ifdef CFG_MC_DIVIDE_ENABLED
philpem@0 115 wire [32:0] t;
philpem@0 116 `endif
philpem@0 117
philpem@0 118 reg [`LM32_MC_STATE_RNG] state; // Current state of FSM
philpem@0 119 reg [5:0] cycles; // Number of cycles remaining in the operation
philpem@0 120
philpem@0 121 `ifdef CFG_MC_BARREL_SHIFT_ENABLED
philpem@0 122 reg sign_extend_x; // Whether to sign extend of zero extend right shifts
philpem@0 123 wire fill_value; // Value to fill with for right barrel-shifts
philpem@0 124 `endif
philpem@0 125
philpem@0 126 /////////////////////////////////////////////////////
philpem@0 127 // Combinational logic
philpem@0 128 /////////////////////////////////////////////////////
philpem@0 129
philpem@0 130 // Stall pipeline while any operation is being performed
philpem@0 131 assign stall_request_x = state != `LM32_MC_STATE_IDLE;
philpem@0 132
philpem@0 133 `ifdef CFG_MC_DIVIDE_ENABLED
philpem@0 134 // Subtraction
philpem@0 135 assign t = {p[`LM32_WORD_WIDTH-2:0], a[`LM32_WORD_WIDTH-1]} - b;
philpem@0 136 `endif
philpem@0 137
philpem@0 138 `ifdef CFG_MC_BARREL_SHIFT_ENABLED
philpem@0 139 // Determine fill value for right shift - Sign bit for arithmetic shift, or zero for logical shift
philpem@0 140 assign fill_value = (sign_extend_x == `TRUE) & b[`LM32_WORD_WIDTH-1];
philpem@0 141 `endif
philpem@0 142
philpem@0 143 /////////////////////////////////////////////////////
philpem@0 144 // Sequential logic
philpem@0 145 /////////////////////////////////////////////////////
philpem@0 146
philpem@0 147 // Perform right shift
philpem@0 148 always @(posedge clk_i `CFG_RESET_SENSITIVITY)
philpem@0 149 begin
philpem@0 150 if (rst_i == `TRUE)
philpem@0 151 begin
philpem@0 152 cycles <= {6{1'b0}};
philpem@0 153 p <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 154 a <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 155 b <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 156 `ifdef CFG_MC_BARREL_SHIFT_ENABLED
philpem@0 157 sign_extend_x <= 1'b0;
philpem@0 158 `endif
philpem@0 159 `ifdef CFG_MC_DIVIDE_ENABLED
philpem@0 160 divide_by_zero_x <= `FALSE;
philpem@0 161 `endif
philpem@0 162 result_x <= {`LM32_WORD_WIDTH{1'b0}};
philpem@0 163 state <= `LM32_MC_STATE_IDLE;
philpem@0 164 end
philpem@0 165 else
philpem@0 166 begin
philpem@0 167 `ifdef CFG_MC_DIVIDE_ENABLED
philpem@0 168 divide_by_zero_x <= `FALSE;
philpem@0 169 `endif
philpem@0 170 case (state)
philpem@0 171 `LM32_MC_STATE_IDLE:
philpem@0 172 begin
philpem@0 173 if (stall_d == `FALSE)
philpem@0 174 begin
philpem@0 175 cycles <= `LM32_WORD_WIDTH;
philpem@0 176 p <= 32'b0;
philpem@0 177 a <= operand_0_d;
philpem@0 178 b <= operand_1_d;
philpem@0 179 `ifdef CFG_MC_DIVIDE_ENABLED
philpem@0 180 if (divide_d == `TRUE)
philpem@0 181 state <= `LM32_MC_STATE_DIVIDE;
philpem@0 182 if (modulus_d == `TRUE)
philpem@0 183 state <= `LM32_MC_STATE_MODULUS;
philpem@0 184 `endif
philpem@0 185 `ifdef CFG_MC_MULTIPLY_ENABLED
philpem@0 186 if (multiply_d == `TRUE)
philpem@0 187 state <= `LM32_MC_STATE_MULTIPLY;
philpem@0 188 `endif
philpem@0 189 `ifdef CFG_MC_BARREL_SHIFT_ENABLED
philpem@0 190 if (shift_left_d == `TRUE)
philpem@0 191 begin
philpem@0 192 state <= `LM32_MC_STATE_SHIFT_LEFT;
philpem@0 193 sign_extend_x <= sign_extend_d;
philpem@0 194 cycles <= operand_1_d[4:0];
philpem@0 195 a <= operand_0_d;
philpem@0 196 b <= operand_0_d;
philpem@0 197 end
philpem@0 198 if (shift_right_d == `TRUE)
philpem@0 199 begin
philpem@0 200 state <= `LM32_MC_STATE_SHIFT_RIGHT;
philpem@0 201 sign_extend_x <= sign_extend_d;
philpem@0 202 cycles <= operand_1_d[4:0];
philpem@0 203 a <= operand_0_d;
philpem@0 204 b <= operand_0_d;
philpem@0 205 end
philpem@0 206 `endif
philpem@0 207 end
philpem@0 208 end
philpem@0 209 `ifdef CFG_MC_DIVIDE_ENABLED
philpem@0 210 `LM32_MC_STATE_DIVIDE:
philpem@0 211 begin
philpem@0 212 if (t[32] == 1'b0)
philpem@0 213 begin
philpem@0 214 p <= t[31:0];
philpem@0 215 a <= {a[`LM32_WORD_WIDTH-2:0], 1'b1};
philpem@0 216 end
philpem@0 217 else
philpem@0 218 begin
philpem@0 219 p <= {p[`LM32_WORD_WIDTH-2:0], a[`LM32_WORD_WIDTH-1]};
philpem@0 220 a <= {a[`LM32_WORD_WIDTH-2:0], 1'b0};
philpem@0 221 end
philpem@0 222 result_x <= a;
philpem@0 223 if ((cycles == `LM32_WORD_WIDTH'd0) || (kill_x == `TRUE))
philpem@0 224 begin
philpem@0 225 // Check for divide by zero
philpem@0 226 divide_by_zero_x <= b == {`LM32_WORD_WIDTH{1'b0}};
philpem@0 227 state <= `LM32_MC_STATE_IDLE;
philpem@0 228 end
philpem@0 229 cycles <= cycles - 1'b1;
philpem@0 230 end
philpem@0 231 `LM32_MC_STATE_MODULUS:
philpem@0 232 begin
philpem@0 233 if (t[32] == 1'b0)
philpem@0 234 begin
philpem@0 235 p <= t[31:0];
philpem@0 236 a <= {a[`LM32_WORD_WIDTH-2:0], 1'b1};
philpem@0 237 end
philpem@0 238 else
philpem@0 239 begin
philpem@0 240 p <= {p[`LM32_WORD_WIDTH-2:0], a[`LM32_WORD_WIDTH-1]};
philpem@0 241 a <= {a[`LM32_WORD_WIDTH-2:0], 1'b0};
philpem@0 242 end
philpem@0 243 result_x <= p;
philpem@0 244 if ((cycles == `LM32_WORD_WIDTH'd0) || (kill_x == `TRUE))
philpem@0 245 begin
philpem@0 246 // Check for divide by zero
philpem@0 247 divide_by_zero_x <= b == {`LM32_WORD_WIDTH{1'b0}};
philpem@0 248 state <= `LM32_MC_STATE_IDLE;
philpem@0 249 end
philpem@0 250 cycles <= cycles - 1'b1;
philpem@0 251 end
philpem@0 252 `endif
philpem@0 253 `ifdef CFG_MC_MULTIPLY_ENABLED
philpem@0 254 `LM32_MC_STATE_MULTIPLY:
philpem@0 255 begin
philpem@0 256 if (b[0] == 1'b1)
philpem@0 257 p <= p + a;
philpem@0 258 b <= {1'b0, b[`LM32_WORD_WIDTH-1:1]};
philpem@0 259 a <= {a[`LM32_WORD_WIDTH-2:0], 1'b0};
philpem@0 260 result_x <= p;
philpem@0 261 if ((cycles == `LM32_WORD_WIDTH'd0) || (kill_x == `TRUE))
philpem@0 262 state <= `LM32_MC_STATE_IDLE;
philpem@0 263 cycles <= cycles - 1'b1;
philpem@0 264 end
philpem@0 265 `endif
philpem@0 266 `ifdef CFG_MC_BARREL_SHIFT_ENABLED
philpem@0 267 `LM32_MC_STATE_SHIFT_LEFT:
philpem@0 268 begin
philpem@0 269 a <= {a[`LM32_WORD_WIDTH-2:0], 1'b0};
philpem@0 270 result_x <= a;
philpem@0 271 if ((cycles == `LM32_WORD_WIDTH'd0) || (kill_x == `TRUE))
philpem@0 272 state <= `LM32_MC_STATE_IDLE;
philpem@0 273 cycles <= cycles - 1'b1;
philpem@0 274 end
philpem@0 275 `LM32_MC_STATE_SHIFT_RIGHT:
philpem@0 276 begin
philpem@0 277 b <= {fill_value, b[`LM32_WORD_WIDTH-1:1]};
philpem@0 278 result_x <= b;
philpem@0 279 if ((cycles == `LM32_WORD_WIDTH'd0) || (kill_x == `TRUE))
philpem@0 280 state <= `LM32_MC_STATE_IDLE;
philpem@0 281 cycles <= cycles - 1'b1;
philpem@0 282 end
philpem@0 283 `endif
philpem@0 284 endcase
philpem@0 285 end
philpem@0 286 end
philpem@0 287
philpem@0 288 endmodule