-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathALU.vhd
More file actions
143 lines (110 loc) · 3.96 KB
/
ALU.vhd
File metadata and controls
143 lines (110 loc) · 3.96 KB
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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
library ieee;
use ieee.std_logic_1164.all;
--use ieee.std_logic_arith.all;
use ieee.numeric_std.all;
entity ALU is
generic(
DATA_WIDTH : integer := 16 --Default input and output width
);
port(
OPCODE: in unsigned(3 downto 0); --Specified the ALU which operation to perform
DATA0, DATA1: in signed((DATA_WIDTH - 1) downto 0);
RESET, CLK: in std_logic;
STATUS: out unsigned(3 downto 0);
DATA_OUT: out signed((DATA_WIDTH - 1) downto 0)); --Status information relating to the previously executed instruction
end ALU;
architecture behavior of ALU is
signal temp_opcode, temp_status : unsigned(3 downto 0);
signal temp_data_out : signed((DATA_WIDTH - 1) downto 0);
signal temp_data0_in, temp_data1_in : signed((DATA_WIDTH - 1) downto 0);
--Opertions performed by the ALU
constant ADDITION : unsigned(3 downto 0) := "0000";
constant SUBTRACTION : unsigned(3 downto 0) := "0001";
constant NEGATION : unsigned(3 downto 0) := "0010";
constant AND_OP : unsigned(3 downto 0) := "0011";
constant NAND_OP : unsigned(3 downto 0) := "0100";
constant OR_OP : unsigned(3 downto 0) := "0101";
constant NOR_OP : unsigned(3 downto 0) := "0110";
constant XOR_OP : unsigned(3 downto 0) := "0111";
constant XNOR_OP : unsigned(3 downto 0) := "1000";
constant ARITH_SHIFT_LEFT : unsigned(3 downto 0) := "1001";
constant ARITH_SHIFT_RIGHT : unsigned(3 downto 0) := "1010";
constant LOGICAL_SHIFT_LEFT : unsigned(3 downto 0) := "1011";
constant LOGICAL_SHIFT_RIGHT : unsigned(3 downto 0) := "1100";
begin
process (CLK)
begin
if (CLK'EVENT AND CLK = '1') then
--inputs to intermidiate signals at the rising edge of the clock to ensure that ALU gets the correct
--inputs and the correct operation code
temp_data0_in <= DATA0;
temp_data1_in <= DATA1;
temp_opcode <= OPCODE;
end if;
end process;
--intermidiate registers to outputs
STATUS <= temp_status;
DATA_OUT <= temp_data_out;
process(CLK, RESET, temp_opcode)
begin
if RESET = '1' then
--Default output and status values
temp_data_out <= to_signed(0,DATA_WIDTH);
temp_status <= to_unsigned(0,4);
elsif (CLK'EVENT AND CLK = '1') then
case temp_opcode is
when ADDITION =>
temp_data_out <= temp_data0_in + temp_data1_in;
temp_status <= ADDITION;
when SUBTRACTION =>
temp_data_out <= temp_data0_in - temp_data1_in;
temp_status <= SUBTRACTION;
when NEGATION =>
temp_data_out <= not temp_data0_in;
temp_status <= NEGATION;
when AND_OP =>
temp_data_out <= temp_data0_in and temp_data1_in;
temp_status <= AND_OP;
when NAND_OP =>
temp_data_out <= temp_data0_in nand temp_data1_in;
temp_status <= NAND_OP;
when OR_OP =>
temp_data_out <= temp_data0_in or temp_data1_in;
temp_status <= OR_OP;
when NOR_OP =>
temp_data_out <= temp_data0_in nor temp_data1_in;
temp_status <= NOR_OP;
when XOR_OP =>
temp_data_out <= temp_data0_in xor temp_data1_in;
temp_status <= XOR_OP;
when XNOR_OP =>
temp_data_out <= temp_data0_in xnor temp_data1_in;
temp_status <= XNOR_OP;
when ARITH_SHIFT_LEFT =>
temp_data_out <= shift_left(
temp_data0_in,
to_integer(unsigned(temp_data1_in)));
temp_status <= ARITH_SHIFT_LEFT;
when ARITH_SHIFT_RIGHT =>
temp_data_out <= shift_right(
temp_data0_in,
to_integer(unsigned(temp_data1_in)));
temp_status <= ARITH_SHIFT_RIGHT;
when LOGICAL_SHIFT_LEFT =>
temp_data_out <= signed(shift_left(
unsigned(temp_data0_in),
to_integer(unsigned(temp_data1_in))));
temp_status <= LOGICAL_SHIFT_LEFT;
when LOGICAL_SHIFT_RIGHT =>
temp_data_out <= signed(shift_right(
unsigned(temp_data0_in),
to_integer(unsigned(temp_data1_in))));
temp_status <= LOGICAL_SHIFT_RIGHT;
when OTHERS =>
--Default output and status values
temp_data_out <= to_signed(0,DATA_WIDTH);
temp_status <= to_unsigned(0,4);
end case;
end if;
end process;
end behavior;