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

Subversion Repositories mips32r1

[/] [mips32r1/] [trunk/] [Hardware/] [MIPS32_Standalone/] [ALU.v] - Blame information for rev 9

Go to most recent revision | 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
    output BZero,  // Used for Movc
31
    output reg EXC_Ov
32
    );
33
 
34
    `include "MIPS_Parameters.v"
35
 
36
    /***
37
     Performance Notes:
38
 
39
     The ALU is the longest delay path in the Execute stage, and one of the longest
40
     in the entire processor. This path varies based on the logic blocks that are
41
     chosen to implement various functions, but there is certainly room to improve
42
     the speed of arithmetic operations. The ALU could also be placed in a separate
43
     pipeline stage after the Execute forwarding has completed.
44
    ***/
45
 
46
    wire signed [31:0] As = A;
47
    wire signed [31:0] Bs = B;
48
 
49
    reg  [63:0] HILO;
50
    wire [31:0] HI = HILO[63:32];
51
    wire [31:0] LO = HILO[31:0];
52
    wire HILO_Commit = ~(EX_Stall | EX_Flush);
53
 
54
    wire AddSub_Add = ((Operation == AluOp_Add) | (Operation == AluOp_Addu));
55
    wire signed [31:0] AddSub_Result = (AddSub_Add) ? (A + B) : (A - B);
56
 
57
    wire signed [63:0] Mult_Result = As * Bs;
58
    wire [63:0] Multu_Result = A * B;
59
 
60
    reg  [5:0] CLO_Result, CLZ_Result;
61
 
62
    assign BZero = (B == 32'h00000000);
63
 
64
    always @(*) begin
65
        case (Operation)
66
            AluOp_Add   : Result <= AddSub_Result;
67
            AluOp_Addu  : Result <= AddSub_Result;
68
            AluOp_And   : Result <= A & B;
69
            AluOp_Clo   : Result <= {26'b0, CLO_Result};
70
            AluOp_Clz   : Result <= {26'b0, CLZ_Result};
71
            AluOp_Div   : Result <= 32'hdeafbeef;   // XXX implement division
72
            AluOp_Divu  : Result <= 32'hdeadbeef;   // XXX implement division
73
            AluOp_Mfhi  : Result <= HI;
74
            AluOp_Mflo  : Result <= LO;
75
            AluOp_Mul   : Result <= Mult_Result[31:0];
76
            AluOp_Nor   : Result <= ~(A | B);
77
            AluOp_Or    : Result <= A | B;
78
            AluOp_Sll   : Result <= B << Shamt;
79
            AluOp_Sllc  : Result <= {B[15:0], 16'b0};
80
            AluOp_Sllv  : Result <= B << A[4:0];
81
            AluOp_Slt   : Result <= (As < Bs) ? 32'h00000001 : 32'h00000000;
82
            AluOp_Sltu  : Result <= (A < B)   ? 32'h00000001 : 32'h00000000;
83
            AluOp_Sra   : Result <= Bs >>> Shamt;
84
            AluOp_Srav  : Result <= Bs >>> As[4:0];
85
            AluOp_Srl   : Result <= B >> Shamt;
86
            AluOp_Srlv  : Result <= B >> A[4:0];
87
            AluOp_Sub   : Result <= AddSub_Result;
88
            AluOp_Subu  : Result <= AddSub_Result;
89
            AluOp_Xor   : Result <= A ^ B;
90
            default     : Result <= 32'bx;
91
        endcase
92
    end
93
 
94
 
95
    always @(posedge clock) begin
96
        if (reset) begin
97
            HILO <= 64'h00000000_00000000;
98
        end
99
        else if (HILO_Commit) begin
100
            case (Operation)
101
                AluOp_Mult  : HILO <= Mult_Result;
102
                AluOp_Multu : HILO <= Multu_Result;
103
                AluOp_Madd  : HILO <= HILO + Mult_Result;
104
                AluOp_Maddu : HILO <= HILO + Multu_Result;
105
                AluOp_Msub  : HILO <= HILO - Mult_Result;
106
                AluOp_Msubu : HILO <= HILO - Multu_Result;
107
                AluOp_Mthi  : HILO <= {A, LO};
108
                AluOp_Mtlo  : HILO <= {HI, B};
109
                default     : HILO <= HILO;
110
            endcase
111
        end
112
        else begin
113
            HILO <= HILO;
114
        end
115
    end
116
 
117
    // Detect overflow for signed operations. Note that MIPS32 has no overflow
118
    // detection for multiplication/division operations.
119
    always @(*) begin
120
        case (Operation)
121 2 ayersg
            AluOp_Add : EXC_Ov <= ((A[31] ~^ B[31]) & (A[31] ^ AddSub_Result[31]));
122 3 ayersg
            AluOp_Sub : EXC_Ov <= ((A[31]  ^ B[31]) & (A[31] ^ AddSub_Result[31]));
123
            default   : EXC_Ov <= 0;
124
        endcase
125
    end
126
 
127
 
128
    // Count Leading Ones
129
    always @(A) begin
130
        casex (A)
131
            32'b0xxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLO_Result <= 6'd0;
132
            32'b10xx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLO_Result <= 6'd1;
133
            32'b110x_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLO_Result <= 6'd2;
134
            32'b1110_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLO_Result <= 6'd3;
135
            32'b1111_0xxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLO_Result <= 6'd4;
136
            32'b1111_10xx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLO_Result <= 6'd5;
137
            32'b1111_110x_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLO_Result <= 6'd6;
138
            32'b1111_1110_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLO_Result <= 6'd7;
139
            32'b1111_1111_0xxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLO_Result <= 6'd8;
140
            32'b1111_1111_10xx_xxxx_xxxx_xxxx_xxxx_xxxx : CLO_Result <= 6'd9;
141
            32'b1111_1111_110x_xxxx_xxxx_xxxx_xxxx_xxxx : CLO_Result <= 6'd10;
142
            32'b1111_1111_1110_xxxx_xxxx_xxxx_xxxx_xxxx : CLO_Result <= 6'd11;
143
            32'b1111_1111_1111_0xxx_xxxx_xxxx_xxxx_xxxx : CLO_Result <= 6'd12;
144
            32'b1111_1111_1111_10xx_xxxx_xxxx_xxxx_xxxx : CLO_Result <= 6'd13;
145
            32'b1111_1111_1111_110x_xxxx_xxxx_xxxx_xxxx : CLO_Result <= 6'd14;
146
            32'b1111_1111_1111_1110_xxxx_xxxx_xxxx_xxxx : CLO_Result <= 6'd15;
147
            32'b1111_1111_1111_1111_0xxx_xxxx_xxxx_xxxx : CLO_Result <= 6'd16;
148
            32'b1111_1111_1111_1111_10xx_xxxx_xxxx_xxxx : CLO_Result <= 6'd17;
149
            32'b1111_1111_1111_1111_110x_xxxx_xxxx_xxxx : CLO_Result <= 6'd18;
150
            32'b1111_1111_1111_1111_1110_xxxx_xxxx_xxxx : CLO_Result <= 6'd19;
151
            32'b1111_1111_1111_1111_1111_0xxx_xxxx_xxxx : CLO_Result <= 6'd20;
152
            32'b1111_1111_1111_1111_1111_10xx_xxxx_xxxx : CLO_Result <= 6'd21;
153
            32'b1111_1111_1111_1111_1111_110x_xxxx_xxxx : CLO_Result <= 6'd22;
154
            32'b1111_1111_1111_1111_1111_1110_xxxx_xxxx : CLO_Result <= 6'd23;
155
            32'b1111_1111_1111_1111_1111_1111_0xxx_xxxx : CLO_Result <= 6'd24;
156
            32'b1111_1111_1111_1111_1111_1111_10xx_xxxx : CLO_Result <= 6'd25;
157
            32'b1111_1111_1111_1111_1111_1111_110x_xxxx : CLO_Result <= 6'd26;
158
            32'b1111_1111_1111_1111_1111_1111_1110_xxxx : CLO_Result <= 6'd27;
159
            32'b1111_1111_1111_1111_1111_1111_1111_0xxx : CLO_Result <= 6'd28;
160
            32'b1111_1111_1111_1111_1111_1111_1111_10xx : CLO_Result <= 6'd29;
161
            32'b1111_1111_1111_1111_1111_1111_1111_110x : CLO_Result <= 6'd30;
162
            32'b1111_1111_1111_1111_1111_1111_1111_1110 : CLO_Result <= 6'd31;
163
            32'b1111_1111_1111_1111_1111_1111_1111_1111 : CLO_Result <= 6'd32;
164
            default : CLO_Result <= 6'd0;
165
        endcase
166
    end
167
 
168
    // Count Leading Zeros
169
    always @(A) begin
170
        casex (A)
171
            32'b1xxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd0;
172
            32'b01xx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd1;
173
            32'b001x_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd2;
174
            32'b0001_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd3;
175
            32'b0000_1xxx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd4;
176
            32'b0000_01xx_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd5;
177
            32'b0000_001x_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd6;
178
            32'b0000_0001_xxxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd7;
179
            32'b0000_0000_1xxx_xxxx_xxxx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd8;
180
            32'b0000_0000_01xx_xxxx_xxxx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd9;
181
            32'b0000_0000_001x_xxxx_xxxx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd10;
182
            32'b0000_0000_0001_xxxx_xxxx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd11;
183
            32'b0000_0000_0000_1xxx_xxxx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd12;
184
            32'b0000_0000_0000_01xx_xxxx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd13;
185
            32'b0000_0000_0000_001x_xxxx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd14;
186
            32'b0000_0000_0000_0001_xxxx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd15;
187
            32'b0000_0000_0000_0000_1xxx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd16;
188
            32'b0000_0000_0000_0000_01xx_xxxx_xxxx_xxxx : CLZ_Result <= 6'd17;
189
            32'b0000_0000_0000_0000_001x_xxxx_xxxx_xxxx : CLZ_Result <= 6'd18;
190
            32'b0000_0000_0000_0000_0001_xxxx_xxxx_xxxx : CLZ_Result <= 6'd19;
191
            32'b0000_0000_0000_0000_0000_1xxx_xxxx_xxxx : CLZ_Result <= 6'd20;
192
            32'b0000_0000_0000_0000_0000_01xx_xxxx_xxxx : CLZ_Result <= 6'd21;
193
            32'b0000_0000_0000_0000_0000_001x_xxxx_xxxx : CLZ_Result <= 6'd22;
194
            32'b0000_0000_0000_0000_0000_0001_xxxx_xxxx : CLZ_Result <= 6'd23;
195
            32'b0000_0000_0000_0000_0000_0000_1xxx_xxxx : CLZ_Result <= 6'd24;
196
            32'b0000_0000_0000_0000_0000_0000_01xx_xxxx : CLZ_Result <= 6'd25;
197
            32'b0000_0000_0000_0000_0000_0000_001x_xxxx : CLZ_Result <= 6'd26;
198
            32'b0000_0000_0000_0000_0000_0000_0001_xxxx : CLZ_Result <= 6'd27;
199
            32'b0000_0000_0000_0000_0000_0000_0000_1xxx : CLZ_Result <= 6'd28;
200
            32'b0000_0000_0000_0000_0000_0000_0000_01xx : CLZ_Result <= 6'd29;
201
            32'b0000_0000_0000_0000_0000_0000_0000_001x : CLZ_Result <= 6'd30;
202
            32'b0000_0000_0000_0000_0000_0000_0000_0001 : CLZ_Result <= 6'd31;
203
            32'b0000_0000_0000_0000_0000_0000_0000_0000 : CLZ_Result <= 6'd32;
204
            default : CLZ_Result <= 6'd0;
205
        endcase
206
    end
207
endmodule
208
 

powered by: WebSVN 2.1.0

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