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