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

Subversion Repositories lxp32

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

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_xor_i: in std_logic;
35
                cmd_shift_i: in std_logic;
36
                cmd_shift_right_i: in std_logic;
37
 
38
                op1_i: in std_logic_vector(31 downto 0);
39
                op2_i: in std_logic_vector(31 downto 0);
40
 
41
                result_o: out std_logic_vector(31 downto 0);
42
 
43
                cmp_eq_o: out std_logic;
44
                cmp_ug_o: out std_logic;
45
                cmp_sg_o: out std_logic;
46
 
47
                we_o: out std_logic;
48
                busy_o: out std_logic
49
        );
50
end entity;
51
 
52
architecture rtl of lxp32_alu is
53
 
54
signal addend1: unsigned(31 downto 0);
55
signal addend2: unsigned(31 downto 0);
56
signal adder_result: unsigned(32 downto 0);
57
signal adder_we: std_logic;
58
 
59
signal cmp_eq: std_logic;
60
signal cmp_carry: std_logic;
61
signal cmp_s1: std_logic;
62
signal cmp_s2: std_logic;
63
 
64 6 ring0_mipt
signal logic_result: std_logic_vector(31 downto 0);
65
signal logic_we: std_logic;
66 2 ring0_mipt
 
67
signal mul_result: std_logic_vector(31 downto 0);
68
signal mul_ce: std_logic;
69
signal mul_we: std_logic;
70
 
71 6 ring0_mipt
signal div_result: std_logic_vector(31 downto 0);
72 2 ring0_mipt
signal div_ce: std_logic;
73
signal div_we: std_logic;
74
 
75
signal shift_result: std_logic_vector(31 downto 0);
76
signal shift_ce: std_logic;
77
signal shift_we: std_logic;
78
 
79
signal result_mux: std_logic_vector(31 downto 0);
80
signal result_we: std_logic;
81
 
82
signal busy: std_logic:='0';
83
 
84
begin
85
 
86
assert MUL_ARCH="dsp" or MUL_ARCH="seq" or MUL_ARCH="opt"
87
        report "Invalid MUL_ARCH generic value: dsp, opt or seq expected"
88
        severity failure;
89
 
90
-- Add/subtract
91
 
92
addend1<=unsigned(op1_i);
93 6 ring0_mipt
 
94
addend2_gen: for i in addend2'range generate
95
        addend2(i)<=op2_i(i) xor cmd_negate_op2_i;
96
end generate;
97
 
98 2 ring0_mipt
adder_result<=("0"&addend1)+("0"&addend2)+(to_unsigned(0,adder_result'length-1)&cmd_negate_op2_i);
99
adder_we<=cmd_addsub_i and valid_i;
100
 
101
-- Comparator (needs cmd_negate_op2_i to work correctly)
102
 
103
process (clk_i) is
104
begin
105
        if rising_edge(clk_i) then
106
                if valid_i='1' and cmd_cmp_i='1' then
107
                        if op1_i=op2_i then
108
                                cmp_eq<='1';
109
                        else
110
                                cmp_eq<='0';
111
                        end if;
112
 
113
                        cmp_carry<=adder_result(adder_result'high);
114
                        cmp_s1<=op1_i(op1_i'high);
115
                        cmp_s2<=op2_i(op2_i'high);
116
                end if;
117
        end if;
118
end process;
119
 
120
cmp_eq_o<=cmp_eq;
121
cmp_ug_o<=cmp_carry and not cmp_eq;
122
cmp_sg_o<=((cmp_s1 and cmp_s2 and cmp_carry) or
123
        (not cmp_s1 and not cmp_s2 and cmp_carry) or
124
        (not cmp_s1 and cmp_s2)) and not cmp_eq;
125
 
126 6 ring0_mipt
-- Bitwise operations (and, or, xor)
127
-- Note: (a or b) = (a and b) or (a xor b)
128 2 ring0_mipt
 
129 6 ring0_mipt
logic_result_gen: for i in logic_result'range generate
130
        logic_result(i)<=((op1_i(i) and op2_i(i)) and cmd_and_i) or
131
                ((op1_i(i) xor op2_i(i)) and cmd_xor_i);
132
end generate;
133 2 ring0_mipt
 
134 6 ring0_mipt
logic_we<=(cmd_and_i or cmd_xor_i) and valid_i;
135
 
136 2 ring0_mipt
-- Multiplier
137
 
138
mul_ce<=cmd_mul_i and valid_i;
139
 
140
gen_mul_dsp: if MUL_ARCH="dsp" generate
141
        mul_inst: entity work.lxp32_mul_dsp(rtl)
142
                port map(
143
                        clk_i=>clk_i,
144
                        rst_i=>rst_i,
145
                        ce_i=>mul_ce,
146
                        op1_i=>op1_i,
147
                        op2_i=>op2_i,
148
                        ce_o=>mul_we,
149
                        result_o=>mul_result
150
                );
151
end generate;
152
 
153
gen_mul_opt: if MUL_ARCH="opt" generate
154
        mul_inst: entity work.lxp32_mul_opt(rtl)
155
                port map(
156
                        clk_i=>clk_i,
157
                        rst_i=>rst_i,
158
                        ce_i=>mul_ce,
159
                        op1_i=>op1_i,
160
                        op2_i=>op2_i,
161
                        ce_o=>mul_we,
162
                        result_o=>mul_result
163
                );
164
end generate;
165
 
166
gen_mul_seq: if MUL_ARCH="seq" generate
167
        mul_inst: entity work.lxp32_mul_seq(rtl)
168
                port map(
169
                        clk_i=>clk_i,
170
                        rst_i=>rst_i,
171
                        ce_i=>mul_ce,
172
                        op1_i=>op1_i,
173
                        op2_i=>op2_i,
174
                        ce_o=>mul_we,
175
                        result_o=>mul_result
176
                );
177
end generate;
178
 
179
-- Divider
180
 
181
div_ce<=cmd_div_i and valid_i;
182
 
183
gen_divider: if DIVIDER_EN generate
184
        divider_inst: entity work.lxp32_divider(rtl)
185
                port map(
186
                        clk_i=>clk_i,
187
                        rst_i=>rst_i,
188
                        ce_i=>div_ce,
189
                        op1_i=>op1_i,
190
                        op2_i=>op2_i,
191
                        signed_i=>cmd_signed_i,
192 6 ring0_mipt
                        rem_i=>cmd_div_mod_i,
193 2 ring0_mipt
                        ce_o=>div_we,
194 6 ring0_mipt
                        result_o=>div_result
195 2 ring0_mipt
                );
196
end generate;
197
 
198
gen_no_divider: if not DIVIDER_EN generate
199
        div_we<=div_ce;
200 6 ring0_mipt
        div_result<=(others=>'0');
201 2 ring0_mipt
end generate;
202
 
203
-- Shifter
204
 
205
shift_ce<=cmd_shift_i and valid_i;
206
 
207
shifter_inst: entity work.lxp32_shifter(rtl)
208
        port map(
209
                clk_i=>clk_i,
210
                rst_i=>rst_i,
211
                ce_i=>shift_ce,
212
                d_i=>op1_i,
213
                s_i=>op2_i(4 downto 0),
214
                right_i=>cmd_shift_right_i,
215
                sig_i=>cmd_signed_i,
216
                ce_o=>shift_we,
217
                d_o=>shift_result
218
        );
219
 
220
-- Result multiplexer
221
 
222
result_mux_gen: for i in result_mux'range generate
223
        result_mux(i)<=(adder_result(i) and adder_we) or
224 6 ring0_mipt
                (logic_result(i) and logic_we) or
225 2 ring0_mipt
                (mul_result(i) and mul_we) or
226 6 ring0_mipt
                (div_result(i) and div_we) or
227 2 ring0_mipt
                (shift_result(i) and shift_we);
228
end generate;
229
 
230
result_o<=result_mux;
231
 
232 6 ring0_mipt
result_we<=adder_we or logic_we or mul_we or div_we or shift_we;
233 2 ring0_mipt
we_o<=result_we;
234
 
235
-- Pipeline control
236
 
237
process (clk_i) is
238
begin
239
        if rising_edge(clk_i) then
240 6 ring0_mipt
                if rst_i='1' or result_we='1' then
241 2 ring0_mipt
                        busy<='0';
242 6 ring0_mipt
                elsif shift_ce='1' or mul_ce='1' or div_ce='1' then
243
                        busy<='1';
244 2 ring0_mipt
                end if;
245
        end if;
246
end process;
247
 
248
busy_o<=busy;
249
 
250
end architecture;

powered by: WebSVN 2.1.0

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