-
Notifications
You must be signed in to change notification settings - Fork 3
/
alu.vhd
116 lines (94 loc) · 2.86 KB
/
alu.vhd
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
use IEEE.numeric_std.all;
use work.types.all;
use work.util.all;
entity alu is
port (
clk : in std_logic;
rst : in std_logic;
alu_in : in alu_in_type;
alu_out : out alu_out_type);
end entity;
architecture behavioral of alu is
type reg_type is record
res : std_logic_vector(31 downto 0);
end record;
constant rzero : reg_type := (
res => (others => '0'));
signal r, rin : reg_type := rzero;
begin
comb : process(r, alu_in) is
variable v : reg_type;
variable a : std_logic_vector(31 downto 0);
variable b : std_logic_vector(31 downto 0);
begin
v := r;
a := alu_in.data_a;
b := std_logic_vector(signed(alu_in.data_b) + signed(alu_in.data_l));
case alu_in.optag is
when ALU_ADD =>
v.res := a + b;
when ALU_SUB =>
v.res := a - b;
when ALU_SHL =>
v.res := std_logic_vector(shift_left(unsigned(a), conv_integer(b(4 downto 0))));
when ALU_SHR =>
v.res := std_logic_vector(shift_right(unsigned(a), conv_integer(b(4 downto 0))));
when ALU_SAR =>
v.res := std_logic_vector(shift_right(signed(a), conv_integer(b(4 downto 0))));
when ALU_AND =>
v.res := a and b;
when ALU_OR =>
v.res := a or b;
when ALU_XOR =>
v.res := a xor b;
when ALU_ADDA =>
v.res := a + (b(29 downto 0) & "00");
when ALU_CMPULT =>
v.res := repeat('0', 31) & to_std_logic(a < b);
when ALU_CMPULE =>
v.res := repeat('0', 31) & to_std_logic(a <= b);
when ALU_CMPNE =>
v.res := repeat('0', 31) & to_std_logic(a /= b);
when ALU_CMPEQ =>
v.res := repeat('0', 31) & to_std_logic(a = b);
when ALU_CMPLT =>
v.res := repeat('0', 31) & to_std_logic(signed(a) < signed(b));
when ALU_CMPLE =>
v.res := repeat('0', 31) & to_std_logic(signed(a) <= signed(b));
when ALU_FCMPNE =>
v.res := repeat('0', 31) & to_std_logic(a /= b);
when ALU_FCMPEQ =>
v.res := repeat('0', 31) & to_std_logic(a = b);
when ALU_FCMPLT =>
if a(31) = '1' or b(31) = '1' then
v.res := repeat('0', 31) & to_std_logic(a >= b);
else
v.res := repeat('0', 31) & to_std_logic(a < b);
end if;
when ALU_FCMPLE =>
if a(31) = '1' or b(31) = '1' then
v.res := repeat('0', 31) & to_std_logic(a > b);
else
v.res := repeat('0', 31) & to_std_logic(a <= b);
end if;
when others =>
v.res := (others => '0');
end case;
if alu_in.stall = '1' then
v := r;
end if;
rin <= v;
alu_out.res <= r.res;
end process;
regs : process(clk, rst) is
begin
if rst = '1' then
r <= rzero;
elsif rising_edge(clk) then
r <= rin;
end if;
end process;
end architecture;