forked from Fernsicles/RV32-verilog
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMALU.sv
100 lines (95 loc) · 2.45 KB
/
MALU.sv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
module MALU(
input [2:0] i_op,
input [31:0] i_x,
input [31:0] i_y,
output logic [31:0] o_res
);
wire [63:0] x = fx(i_op, i_x, i_y);
wire [63:0] y = fy(i_op, i_x, i_y);
wire [63:0] prod = x * y;
wire [31:0] quotient = x[31:0] / y[31:0];
wire [31:0] remainder = x[31:0] % y[31:0];
assign o_res = res(i_op, i_x, i_y, prod, quotient, remainder);
function [63:0] fx(
input [2:0] i_op,
input [31:0] i_x,
input [31:0] i_y
);
case(i_op)
3'b010: begin
fx = $signed({{32{i_x[31]}}, i_x});
end
3'b011,
3'b101,
3'b111: begin
fx = $unsigned({32'b0, i_x});
end
default: begin
fx = $signed({{32{i_x[31]}}, i_x});
end
endcase
endfunction
function [63:0] fy(
input [2:0] i_op,
input [31:0] i_x,
input [31:0] i_y
);
case(i_op)
3'b010: begin
fy = $unsigned({32'b0, i_y});
end
3'b011,
3'b101,
3'b111: begin
fy = $unsigned({32'b0, i_y});
end
default: begin
fy = $signed({{32{i_x[31]}}, i_y});
end
endcase
endfunction
function [31:0] res(
input [2:0] i_op,
input [31:0] i_x,
input [31:0] i_y,
input [63:0] prod,
input [31:0] quotient,
input [31:0] remainder
);
case(i_op)
3'b000: res = prod[31:0]; // MUL
3'b001, // MULH
3'b010, // MULHSU
3'b011: res = prod[63:32]; // MULHU
3'b100: begin // DIV
if(i_y == 32'b0)
res = -32'h1;
else if(i_x == 32'h80000000 && i_y == -32'b1)
res = -32'b1 << 31;
else
res = quotient;
end
3'b101: begin // DIVU
if(i_y == 32'b0)
res = -32'h1;
else
res = quotient;
end
3'b110: begin // REM
if(i_y == 32'b0)
res = i_x;
else if(i_x == 32'h80000000 && i_y == -32'b1)
res = 32'b0;
else
res = remainder;
end
3'b111: begin // REMU
if(i_y == 32'b0)
res = i_x;
else
res = remainder;
end
default: res = 32'b0;
endcase
endfunction
endmodule