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

Subversion Repositories lxp32

[/] [lxp32/] [trunk/] [rtl/] [lxp32_alu.vhd] - Blame information for rev 2

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 ring0_mipt
---------------------------------------------------------------------
2
-- Arithmetic logic unit
3
--
4
-- Part of the LXP32 CPU
5
--
6
-- Copyright (c) 2016 by Alex I. Kuznetsov
7
--
8
-- Performs arithmetic and logic operations.
9
---------------------------------------------------------------------
10
 
11
library ieee;
12
use ieee.std_logic_1164.all;
13
use ieee.numeric_std.all;
14
 
15
entity lxp32_alu is
16
        generic(
17
                DIVIDER_EN: boolean;
18
                MUL_ARCH: string
19
        );
20
        port(
21
                clk_i: in std_logic;
22
                rst_i: in std_logic;
23
 
24
                valid_i: in std_logic;
25
 
26
                cmd_signed_i: in std_logic;
27
                cmd_addsub_i: in std_logic;
28
                cmd_mul_i: in std_logic;
29
                cmd_div_i: in std_logic;
30
                cmd_div_mod_i: in std_logic;
31
                cmd_cmp_i: in std_logic;
32
                cmd_negate_op2_i: in std_logic;
33
                cmd_and_i: in std_logic;
34
                cmd_or_i: in std_logic;
35
                cmd_xor_i: in std_logic;
36
                cmd_shift_i: in std_logic;
37
                cmd_shift_right_i: in std_logic;
38
 
39
                op1_i: in std_logic_vector(31 downto 0);
40
                op2_i: in std_logic_vector(31 downto 0);
41
 
42
                result_o: out std_logic_vector(31 downto 0);
43
 
44
                cmp_eq_o: out std_logic;
45
                cmp_ug_o: out std_logic;
46
                cmp_sg_o: out std_logic;
47
 
48
                we_o: out std_logic;
49
                busy_o: out std_logic
50
        );
51
end entity;
52
 
53
architecture rtl of lxp32_alu is
54
 
55
signal addend1: unsigned(31 downto 0);
56
signal addend2: unsigned(31 downto 0);
57
signal adder_result: unsigned(32 downto 0);
58
signal adder_we: std_logic;
59
 
60
signal cmp_eq: std_logic;
61
signal cmp_carry: std_logic;
62
signal cmp_s1: std_logic;
63
signal cmp_s2: std_logic;
64
 
65
signal and_result: std_logic_vector(31 downto 0);
66
signal and_we: std_logic;
67
signal or_result: std_logic_vector(31 downto 0);
68
signal or_we: std_logic;
69
signal xor_result: std_logic_vector(31 downto 0);
70
signal xor_we: std_logic;
71
 
72
signal mul_result: std_logic_vector(31 downto 0);
73
signal mul_ce: std_logic;
74
signal mul_we: std_logic;
75
 
76
signal div_quotient: std_logic_vector(31 downto 0);
77
signal div_remainder: std_logic_vector(31 downto 0);
78
signal div_ce: std_logic;
79
signal div_we: std_logic;
80
signal div_select_remainder: std_logic;
81
 
82
signal shift_result: std_logic_vector(31 downto 0);
83
signal shift_ce: std_logic;
84
signal shift_we: std_logic;
85
 
86
signal result_mux: std_logic_vector(31 downto 0);
87
signal result_we: std_logic;
88
 
89
signal busy: std_logic:='0';
90
 
91
begin
92
 
93
assert MUL_ARCH="dsp" or MUL_ARCH="seq" or MUL_ARCH="opt"
94
        report "Invalid MUL_ARCH generic value: dsp, opt or seq expected"
95
        severity failure;
96
 
97
-- Add/subtract
98
 
99
addend1<=unsigned(op1_i);
100
addend2<=unsigned(op2_i) when cmd_negate_op2_i='0' else not unsigned(op2_i);
101
adder_result<=("0"&addend1)+("0"&addend2)+(to_unsigned(0,adder_result'length-1)&cmd_negate_op2_i);
102
adder_we<=cmd_addsub_i and valid_i;
103
 
104
-- Comparator (needs cmd_negate_op2_i to work correctly)
105
 
106
process (clk_i) is
107
begin
108
        if rising_edge(clk_i) then
109
                if valid_i='1' and cmd_cmp_i='1' then
110
                        if op1_i=op2_i then
111
                                cmp_eq<='1';
112
                        else
113
                                cmp_eq<='0';
114
                        end if;
115
 
116
                        cmp_carry<=adder_result(adder_result'high);
117
                        cmp_s1<=op1_i(op1_i'high);
118
                        cmp_s2<=op2_i(op2_i'high);
119
                end if;
120
        end if;
121
end process;
122
 
123
cmp_eq_o<=cmp_eq;
124
cmp_ug_o<=cmp_carry and not cmp_eq;
125
cmp_sg_o<=((cmp_s1 and cmp_s2 and cmp_carry) or
126
        (not cmp_s1 and not cmp_s2 and cmp_carry) or
127
        (not cmp_s1 and cmp_s2)) and not cmp_eq;
128
 
129
-- Logical functions
130
 
131
and_result<=op1_i and op2_i;
132
and_we<=cmd_and_i and valid_i;
133
or_result<=op1_i or op2_i;
134
or_we<=cmd_or_i and valid_i;
135
xor_result<=op1_i xor op2_i;
136
xor_we<=cmd_xor_i and valid_i;
137
 
138
-- Multiplier
139
 
140
mul_ce<=cmd_mul_i and valid_i;
141
 
142
gen_mul_dsp: if MUL_ARCH="dsp" generate
143
        mul_inst: entity work.lxp32_mul_dsp(rtl)
144
                port map(
145
                        clk_i=>clk_i,
146
                        rst_i=>rst_i,
147
                        ce_i=>mul_ce,
148
                        op1_i=>op1_i,
149
                        op2_i=>op2_i,
150
                        ce_o=>mul_we,
151
                        result_o=>mul_result
152
                );
153
end generate;
154
 
155
gen_mul_opt: if MUL_ARCH="opt" generate
156
        mul_inst: entity work.lxp32_mul_opt(rtl)
157
                port map(
158
                        clk_i=>clk_i,
159
                        rst_i=>rst_i,
160
                        ce_i=>mul_ce,
161
                        op1_i=>op1_i,
162
                        op2_i=>op2_i,
163
                        ce_o=>mul_we,
164
                        result_o=>mul_result
165
                );
166
end generate;
167
 
168
gen_mul_seq: if MUL_ARCH="seq" generate
169
        mul_inst: entity work.lxp32_mul_seq(rtl)
170
                port map(
171
                        clk_i=>clk_i,
172
                        rst_i=>rst_i,
173
                        ce_i=>mul_ce,
174
                        op1_i=>op1_i,
175
                        op2_i=>op2_i,
176
                        ce_o=>mul_we,
177
                        result_o=>mul_result
178
                );
179
end generate;
180
 
181
-- Divider
182
 
183
div_ce<=cmd_div_i and valid_i;
184
 
185
gen_divider: if DIVIDER_EN generate
186
        divider_inst: entity work.lxp32_divider(rtl)
187
                port map(
188
                        clk_i=>clk_i,
189
                        rst_i=>rst_i,
190
                        ce_i=>div_ce,
191
                        op1_i=>op1_i,
192
                        op2_i=>op2_i,
193
                        signed_i=>cmd_signed_i,
194
                        ce_o=>div_we,
195
                        quotient_o=>div_quotient,
196
                        remainder_o=>div_remainder
197
                );
198
end generate;
199
 
200
gen_no_divider: if not DIVIDER_EN generate
201
        div_we<=div_ce;
202
        div_quotient<=(others=>'0');
203
        div_remainder<=(others=>'0');
204
end generate;
205
 
206
process (clk_i) is
207
begin
208
        if rising_edge(clk_i) then
209
                if div_ce='1' then
210
                        div_select_remainder<=cmd_div_mod_i;
211
                end if;
212
        end if;
213
end process;
214
 
215
-- Shifter
216
 
217
shift_ce<=cmd_shift_i and valid_i;
218
 
219
shifter_inst: entity work.lxp32_shifter(rtl)
220
        port map(
221
                clk_i=>clk_i,
222
                rst_i=>rst_i,
223
                ce_i=>shift_ce,
224
                d_i=>op1_i,
225
                s_i=>op2_i(4 downto 0),
226
                right_i=>cmd_shift_right_i,
227
                sig_i=>cmd_signed_i,
228
                ce_o=>shift_we,
229
                d_o=>shift_result
230
        );
231
 
232
-- Result multiplexer
233
 
234
result_mux_gen: for i in result_mux'range generate
235
        result_mux(i)<=(adder_result(i) and adder_we) or
236
                (and_result(i) and and_we) or
237
                (or_result(i) and or_we) or
238
                (xor_result(i) and xor_we) or
239
                (mul_result(i) and mul_we) or
240
                (div_quotient(i) and div_we and not div_select_remainder) or
241
                (div_remainder(i) and div_we and div_select_remainder) or
242
                (shift_result(i) and shift_we);
243
end generate;
244
 
245
result_o<=result_mux;
246
 
247
result_we<=adder_we or and_we or or_we or xor_we or mul_we or div_we or shift_we;
248
we_o<=result_we;
249
 
250
-- Pipeline control
251
 
252
process (clk_i) is
253
begin
254
        if rising_edge(clk_i) then
255
                if rst_i='1' then
256
                        busy<='0';
257
                else
258
                        if shift_ce='1' or mul_ce='1' or div_ce='1' then
259
                                busy<='1';
260
                        end if;
261
                        if result_we='1' then
262
                                busy<='0';
263
                        end if;
264
                end if;
265
        end if;
266
end process;
267
 
268
busy_o<=busy;
269
 
270
end architecture;

powered by: WebSVN 2.1.0

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