lm32_mc_arithmetic.v

Sat, 06 Aug 2011 01:26:56 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Sat, 06 Aug 2011 01:26:56 +0100
changeset 27
d6c693415d59
parent 26
73de224304c1
permissions
-rwxr-xr-x

remove synthesis delay entities to ease merge

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