lm32_mc_arithmetic.v

Mon, 05 Apr 2010 21:00:31 +0100

author
Philip Pemberton <philpem@philpem.me.uk>
date
Mon, 05 Apr 2010 21:00:31 +0100
changeset 6
a8e459b24c31
parent 0
cd0b58aa6f83
child 26
73de224304c1
permissions
-rw-r--r--

reduce size of caches to fit in DE1 FPGA

The default cache size makes the Icache and Dcache "just a bit" too big to
fit in the EP2C20 FPGA on the DE1 board. This commit reduces the Icache and
Dcache sizes to the defaults shown in the LatticeMico32 Processor Reference
Manual (pages 36 and 37).

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