OpenCores
URL https://opencores.org/ocsvn/mips32r1/mips32r1/trunk

Subversion Repositories mips32r1

[/] [mips32r1/] [trunk/] [Hardware/] [XUPV5-LX110T_SoC/] [MIPS32-Pipelined-Hw/] [src/] [MIPS32/] [ALU.v] - Blame information for rev 10

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 ayersg
`timescale 1ns / 1ps
2
/*
3
 * File         : ALU.v
4
 * Project      : University of Utah, XUM Project MIPS32 core
5
 * Creator(s)   : Grant Ayers (ayers@cs.utah.edu)
6
 *
7
 * Modification History:
8
 *   Rev   Date         Initials  Description of Change
9
 *   1.0   7-Jun-2011   GEA       Initial design.
10
 *   2.0   26-Jul-2012  GEA       Many changes have been made.
11
 *
12
 * Standards/Formatting:
13
 *   Verilog 2001, 4 soft tab, wide column.
14
 *
15
 * Description:
16
 *   An Arithmetic Logic Unit for a MIPS32 processor. This module computes all
17
 *   arithmetic operations, including the following:
18
 *
19
 *   Add, Subtract, Multiply, And, Or, Nor, Xor, Shift, Count leading 1s/0s.
20
 */
21
module ALU(
22
    input  clock,
23
    input  reset,
24
    input  EX_Stall,
25
    input  EX_Flush,
26
    input  [31:0] A, B,
27
    input  [4:0]  Operation,
28
    input  signed [4:0] Shamt,
29
    output reg signed [31:0] Result,
30 10 ayersg
    output BZero,           // Used for Movc
31
    output reg EXC_Ov,
32
    output ALU_Stall        // Stalls due to long ALU operations
33 3 ayersg
    );
34
 
35
    `include "MIPS_Parameters.v"
36
 
37
    /***
38
     Performance Notes:
39
 
40
     The ALU is the longest delay path in the Execute stage, and one of the longest
41
     in the entire processor. This path varies based on the logic blocks that are
42
     chosen to implement various functions, but there is certainly room to improve
43
     the speed of arithmetic operations. The ALU could also be placed in a separate
44
     pipeline stage after the Execute forwarding has completed.
45
    ***/
46 10 ayersg
 
47
 
48
    /***
49
     Divider Logic:
50
 
51
     The hardware divider requires 32 cycles to complete. Because it writes its
52
     results to HILO and not to the pipeline, the pipeline can proceed without
53
     stalling. When a later instruction tries to access HILO, the pipeline will
54
     stall if the divide operation has not yet completed.
55
    ***/
56
 
57
 
58
    // Internal state registers
59
    reg  [63:0] HILO;
60
    reg  HILO_Access;                   // Behavioral; not DFFs
61
    reg  [5:0] CLO_Result, CLZ_Result;  // Behavioral; not DFFs
62
    reg  div_fsm;
63
 
64
    // Internal signals
65
    wire [31:0] HI, LO;
66
    wire HILO_Commit;
67
    wire signed [31:0] As, Bs;
68
    wire AddSub_Add;
69
    wire signed [31:0] AddSub_Result;
70
    wire signed [63:0] Mult_Result;
71
    wire [63:0] Multu_Result;
72
    wire [31:0] Quotient;
73
    wire [31:0] Remainder;
74
    wire Div_Stall;
75
    wire Div_Start, Divu_Start;
76
    wire DivOp;
77
    wire Div_Commit;
78 3 ayersg
 
79 10 ayersg
    // Assignments
80
    assign HI = HILO[63:32];
81
    assign LO = HILO[31:0];
82
    assign HILO_Commit = ~(EX_Stall | EX_Flush);
83
    assign As = A;
84
    assign Bs = B;
85
    assign AddSub_Add = ((Operation == AluOp_Add) | (Operation == AluOp_Addu));
86
    assign AddSub_Result = (AddSub_Add) ? (A + B) : (A - B);
87
    assign Mult_Result = As * Bs;
88
    assign Multu_Result = A * B;
89 3 ayersg
    assign BZero = (B == 32'h00000000);
90 10 ayersg
    assign DivOp = (Operation == AluOp_Div) || (Operation == AluOp_Divu);
91
    assign Div_Commit   = (div_fsm == 1'b1) && (Div_Stall == 1'b0);
92
    assign Div_Start    = (div_fsm == 1'b0) && (Operation == AluOp_Div)  && (HILO_Commit == 1'b1);
93
    assign Divu_Start   = (div_fsm == 1'b0) && (Operation == AluOp_Divu) && (HILO_Commit == 1'b1);
94
    assign ALU_Stall    = (div_fsm == 1'b1) && (HILO_Access == 1'b1);
95 3 ayersg
 
96
    always @(*) begin
97
        case (Operation)
98
            AluOp_Add   : Result <= AddSub_Result;
99
            AluOp_Addu  : Result <= AddSub_Result;
100
            AluOp_And   : Result <= A & B;
101
            AluOp_Clo   : Result <= {26'b0, CLO_Result};
102
            AluOp_Clz   : Result <= {26'b0, CLZ_Result};
103
            AluOp_Mfhi  : Result <= HI;
104
            AluOp_Mflo  : Result <= LO;
105
            AluOp_Mul   : Result <= Mult_Result[31:0];
106
            AluOp_Nor   : Result <= ~(A | B);
107
            AluOp_Or    : Result <= A | B;
108
            AluOp_Sll   : Result <= B << Shamt;
109
            AluOp_Sllc  : Result <= {B[15:0], 16'b0};
110
            AluOp_Sllv  : Result <= B << A[4:0];
111
            AluOp_Slt   : Result <= (As < Bs) ? 32'h00000001 : 32'h00000000;
112
            AluOp_Sltu  : Result <= (A < B)   ? 32'h00000001 : 32'h00000000;
113
            AluOp_Sra   : Result <= Bs >>> Shamt;
114
            AluOp_Srav  : Result <= Bs >>> As[4:0];
115
            AluOp_Srl   : Result <= B >> Shamt;
116
            AluOp_Srlv  : Result <= B >> A[4:0];
117
            AluOp_Sub   : Result <= AddSub_Result;
118
            AluOp_Subu  : Result <= AddSub_Result;
119
            AluOp_Xor   : Result <= A ^ B;
120
            default     : Result <= 32'bx;
121
        endcase
122
    end
123
 
124
 
125
    always @(posedge clock) begin
126
        if (reset) begin
127
            HILO <= 64'h00000000_00000000;
128 10 ayersg
        end
129
        else if (Div_Commit) begin
130
            HILO <= {Remainder, Quotient};
131 3 ayersg
        end
132
        else if (HILO_Commit) begin
133
            case (Operation)
134
                AluOp_Mult  : HILO <= Mult_Result;
135
                AluOp_Multu : HILO <= Multu_Result;
136
                AluOp_Madd  : HILO <= HILO + Mult_Result;
137
                AluOp_Maddu : HILO <= HILO + Multu_Result;
138
                AluOp_Msub  : HILO <= HILO - Mult_Result;
139
                AluOp_Msubu : HILO <= HILO - Multu_Result;
140
                AluOp_Mthi  : HILO <= {A, LO};
141
                AluOp_Mtlo  : HILO <= {HI, B};
142
                default     : HILO <= HILO;
143
            endcase
144
        end
145
        else begin
146
            HILO <= HILO;
147
        end
148 10 ayersg
    end
149
 
150
    // Detect accesses to HILO. RAW and WAW hazards are possible while a
151
    // divide operation is computing, so reads and writes to HILO must stall
152
    // while the divider is busy.
153
    // (This logic could be put into an earlier pipeline stage or into the
154
    // datapath bits to improve timing.)
155
    always @(Operation) begin
156
        case (Operation)
157
            AluOp_Div   : HILO_Access <= 1;
158
            AluOp_Divu  : HILO_Access <= 1;
159
            AluOp_Mfhi  : HILO_Access <= 1;
160
            AluOp_Mflo  : HILO_Access <= 1;
161
            AluOp_Mult  : HILO_Access <= 1;
162
            AluOp_Multu : HILO_Access <= 1;
163
            AluOp_Madd  : HILO_Access <= 1;
164
            AluOp_Maddu : HILO_Access <= 1;
165
            AluOp_Msub  : HILO_Access <= 1;
166
            AluOp_Msubu : HILO_Access <= 1;
167
            AluOp_Mthi  : HILO_Access <= 1;
168
            AluOp_Mtlo  : HILO_Access <= 1;
169
            default     : HILO_Access <= 0;
170
        endcase
171
    end
172
 
173
    // Divider FSM: The divide unit is either available or busy.
174
    always @(posedge clock) begin
175
        if (reset) begin
176
            div_fsm <= 2'd0;
177
        end
178
        else begin
179
            case (div_fsm)
180
                1'd0 : div_fsm <= (DivOp & HILO_Commit) ? 1'd1 : 1'd0;
181
                1'd1 : div_fsm <= (~Div_Stall) ? 1'd0 : 1'd1;
182
            endcase
183
        end
184 3 ayersg
    end
185
 
186
    // Detect overflow for signed operations. Note that MIPS32 has no overflow
187
    // detection for multiplication/division operations.
188
    always @(*) begin
189
        case (Operation)
190 2 ayersg
            AluOp_Add : EXC_Ov <= ((A[31] ~^ B[31]) & (A[31] ^ AddSub_Result[31]));
191 3 ayersg
            AluOp_Sub : EXC_Ov <= ((A[31]  ^ B[31]) & (A[31] ^ AddSub_Result[31]));
192
            default   : EXC_Ov <= 0;
193
        endcase
194
    end
195
 
196
    // Count Leading Ones
197
    always @(A) begin
198
        casex (A)
199
            32'b0xxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLO_Result <= 6'd0;
200
            32'b10xx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLO_Result <= 6'd1;
201
            32'b110x_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLO_Result <= 6'd2;
202
            32'b1110_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLO_Result <= 6'd3;
203
            32'b1111_0xxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLO_Result <= 6'd4;
204
            32'b1111_10xx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLO_Result <= 6'd5;
205
            32'b1111_110x_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLO_Result <= 6'd6;
206
            32'b1111_1110_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLO_Result <= 6'd7;
207
            32'b1111_1111_0xxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLO_Result <= 6'd8;
208
            32'b1111_1111_10xx_xxxx_xxxx_xxxx_xxxx_xxxx : CLO_Result <= 6'd9;
209
            32'b1111_1111_110x_xxxx_xxxx_xxxx_xxxx_xxxx : CLO_Result <= 6'd10;
210
            32'b1111_1111_1110_xxxx_xxxx_xxxx_xxxx_xxxx : CLO_Result <= 6'd11;
211
            32'b1111_1111_1111_0xxx_xxxx_xxxx_xxxx_xxxx : CLO_Result <= 6'd12;
212
            32'b1111_1111_1111_10xx_xxxx_xxxx_xxxx_xxxx : CLO_Result <= 6'd13;
213
            32'b1111_1111_1111_110x_xxxx_xxxx_xxxx_xxxx : CLO_Result <= 6'd14;
214
            32'b1111_1111_1111_1110_xxxx_xxxx_xxxx_xxxx : CLO_Result <= 6'd15;
215
            32'b1111_1111_1111_1111_0xxx_xxxx_xxxx_xxxx : CLO_Result <= 6'd16;
216
            32'b1111_1111_1111_1111_10xx_xxxx_xxxx_xxxx : CLO_Result <= 6'd17;
217
            32'b1111_1111_1111_1111_110x_xxxx_xxxx_xxxx : CLO_Result <= 6'd18;
218
            32'b1111_1111_1111_1111_1110_xxxx_xxxx_xxxx : CLO_Result <= 6'd19;
219
            32'b1111_1111_1111_1111_1111_0xxx_xxxx_xxxx : CLO_Result <= 6'd20;
220
            32'b1111_1111_1111_1111_1111_10xx_xxxx_xxxx : CLO_Result <= 6'd21;
221
            32'b1111_1111_1111_1111_1111_110x_xxxx_xxxx : CLO_Result <= 6'd22;
222
            32'b1111_1111_1111_1111_1111_1110_xxxx_xxxx : CLO_Result <= 6'd23;
223
            32'b1111_1111_1111_1111_1111_1111_0xxx_xxxx : CLO_Result <= 6'd24;
224
            32'b1111_1111_1111_1111_1111_1111_10xx_xxxx : CLO_Result <= 6'd25;
225
            32'b1111_1111_1111_1111_1111_1111_110x_xxxx : CLO_Result <= 6'd26;
226
            32'b1111_1111_1111_1111_1111_1111_1110_xxxx : CLO_Result <= 6'd27;
227
            32'b1111_1111_1111_1111_1111_1111_1111_0xxx : CLO_Result <= 6'd28;
228
            32'b1111_1111_1111_1111_1111_1111_1111_10xx : CLO_Result <= 6'd29;
229
            32'b1111_1111_1111_1111_1111_1111_1111_110x : CLO_Result <= 6'd30;
230
            32'b1111_1111_1111_1111_1111_1111_1111_1110 : CLO_Result <= 6'd31;
231
            32'b1111_1111_1111_1111_1111_1111_1111_1111 : CLO_Result <= 6'd32;
232
            default : CLO_Result <= 6'd0;
233
        endcase
234
    end
235
 
236
    // Count Leading Zeros
237
    always @(A) begin
238
        casex (A)
239
            32'b1xxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd0;
240
            32'b01xx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd1;
241
            32'b001x_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd2;
242
            32'b0001_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd3;
243
            32'b0000_1xxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd4;
244
            32'b0000_01xx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd5;
245
            32'b0000_001x_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd6;
246
            32'b0000_0001_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd7;
247
            32'b0000_0000_1xxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd8;
248
            32'b0000_0000_01xx_xxxx_xxxx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd9;
249
            32'b0000_0000_001x_xxxx_xxxx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd10;
250
            32'b0000_0000_0001_xxxx_xxxx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd11;
251
            32'b0000_0000_0000_1xxx_xxxx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd12;
252
            32'b0000_0000_0000_01xx_xxxx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd13;
253
            32'b0000_0000_0000_001x_xxxx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd14;
254
            32'b0000_0000_0000_0001_xxxx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd15;
255
            32'b0000_0000_0000_0000_1xxx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd16;
256
            32'b0000_0000_0000_0000_01xx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd17;
257
            32'b0000_0000_0000_0000_001x_xxxx_xxxx_xxxx : CLZ_Result <= 6'd18;
258
            32'b0000_0000_0000_0000_0001_xxxx_xxxx_xxxx : CLZ_Result <= 6'd19;
259
            32'b0000_0000_0000_0000_0000_1xxx_xxxx_xxxx : CLZ_Result <= 6'd20;
260
            32'b0000_0000_0000_0000_0000_01xx_xxxx_xxxx : CLZ_Result <= 6'd21;
261
            32'b0000_0000_0000_0000_0000_001x_xxxx_xxxx : CLZ_Result <= 6'd22;
262
            32'b0000_0000_0000_0000_0000_0001_xxxx_xxxx : CLZ_Result <= 6'd23;
263
            32'b0000_0000_0000_0000_0000_0000_1xxx_xxxx : CLZ_Result <= 6'd24;
264
            32'b0000_0000_0000_0000_0000_0000_01xx_xxxx : CLZ_Result <= 6'd25;
265
            32'b0000_0000_0000_0000_0000_0000_001x_xxxx : CLZ_Result <= 6'd26;
266
            32'b0000_0000_0000_0000_0000_0000_0001_xxxx : CLZ_Result <= 6'd27;
267
            32'b0000_0000_0000_0000_0000_0000_0000_1xxx : CLZ_Result <= 6'd28;
268
            32'b0000_0000_0000_0000_0000_0000_0000_01xx : CLZ_Result <= 6'd29;
269
            32'b0000_0000_0000_0000_0000_0000_0000_001x : CLZ_Result <= 6'd30;
270
            32'b0000_0000_0000_0000_0000_0000_0000_0001 : CLZ_Result <= 6'd31;
271
            32'b0000_0000_0000_0000_0000_0000_0000_0000 : CLZ_Result <= 6'd32;
272
            default : CLZ_Result <= 6'd0;
273
        endcase
274 10 ayersg
    end
275
 
276
    // Multicycle divide unit
277
    Divide Divider (
278
        .clock      (clock),
279
        .reset      (reset),
280
        .OP_div     (Div_Start),
281
        .OP_divu    (Divu_Start),
282
        .Dividend   (A),
283
        .Divisor    (B),
284
        .Quotient   (Quotient),
285
        .Remainder  (Remainder),
286
        .Stall      (Div_Stall)
287
    );
288 3 ayersg
 
289
endmodule
290
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.