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

Subversion Repositories arm4u

[/] [arm4u/] [trunk/] [hdl/] [barrelshift.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 Bregalad
-- This file is part of ARM4U CPU
2
-- 
3
-- This is a creation of the Laboratory of Processor Architecture
4
-- of Ecole Polytechnique Fédérale de Lausanne ( http://lap.epfl.ch )
5
--
6
-- barrelshift.vhd  --  Describes the barrel shifter inside the execute pipeline stage
7
--
8
-- Written By -  Jonathan Masur and Xavier Jimenez (2013)
9
--
10
-- This program is free software; you can redistribute it and/or modify it
11
-- under the terms of the GNU General Public License as published by the
12
-- Free Software Foundation; either version 2, or (at your option) any
13
-- later version.
14
--
15
-- This program is distributed in the hope that it will be useful,
16
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
17
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
-- GNU General Public License for more details.
19
--
20
-- In other words, you are welcome to use, share and improve this program.
21
-- You are forbidden to forbid anyone else to use, share and improve
22
-- what you give them.   Help stamp out software-hoarding!
23
 
24
library ieee;
25
use ieee.std_logic_1164.all;
26
use ieee.numeric_std.all;
27
use work.arm_types.all;
28
 
29
entity barrelshift is
30
        port(
31
                c : in std_logic;
32
                exe_barrelshift_operand : in std_logic;
33
                exe_barrelshift_type : in std_logic_vector(1 downto 0);
34
                exe_literal_shift_amnt : in std_logic_vector(4 downto 0);
35
                exe_literal_data : in std_logic_vector(23 downto 0);
36
                exe_opb_is_literal : in std_logic;
37
                op_b_data : in unsigned(31 downto 0);
38
                op_c_data : in unsigned(31 downto 0);
39
                barrelshift_c : out std_logic;
40
                barrelshift_out : out unsigned(31 downto 0)
41
        );
42
end;
43
 
44
-- Note : This architecture synthetizes poorly
45
architecture rtl of barrelshift is
46
begin
47
        -- barrel shifter
48
        barrelshift : process(exe_barrelshift_operand, exe_barrelshift_type, op_b_data, op_c_data, exe_opb_is_literal, exe_literal_shift_amnt, exe_literal_data, c) is
49
        variable shift_positions : integer range 0 to 31;
50
        variable shift_in : unsigned(31 downto 0);
51
        begin
52
                        -- shift by register (opc)
53
                if exe_barrelshift_operand = '1'
54
                then
55
                        shift_positions := to_integer(op_c_data(4 downto 0));
56
                else
57
                        -- shift by literal value
58
                        shift_positions := to_integer(unsigned(exe_literal_shift_amnt));
59
                end if;
60
 
61
                if exe_opb_is_literal = '1'
62
                then
63
                        -- sign extend literal value
64
                        shift_in := (31 downto 24 => exe_literal_data(23)) & unsigned(exe_literal_data);
65
                else
66
                        shift_in := op_b_data;
67
                end if;
68
 
69
                case exe_barrelshift_type is
70
                -- LSR
71
                when "01" =>
72
                        -- shift by register > 32 -> overflows, all bits are out
73
                        if exe_barrelshift_operand = '1' and op_c_data(7 downto 0) > x"20"
74
                        then
75
                                barrelshift_out <= (others => '0');
76
                                barrelshift_c <= '0';
77
 
78
                        -- shift by register or literal, 32 positions
79
                        elsif (exe_barrelshift_operand = '1' and op_c_data(7 downto 0) = x"20")
80
                           or (exe_barrelshift_operand = '0' and exe_literal_shift_amnt = "00000")
81
                        then
82
                                barrelshift_out <= (others => '0');
83
                                barrelshift_c <= shift_in(31);
84
 
85
 
86
                        -- shift by register = 0, opb passes through and C is unaffected
87
                        elsif exe_barrelshift_operand = '1' and op_c_data(7 downto 0) = x"00"
88
                        then
89
                                barrelshift_out <= shift_in;
90
                                barrelshift_c <= c;
91
 
92
                        -- shift by literal or register, range 1..31
93
                        else
94
                                barrelshift_out <= shift_in srl shift_positions;
95
                                barrelshift_c <= shift_in(shift_positions - 1);
96
                        end if;
97
 
98
                -- ASR
99
                when "10" =>
100
                        -- shift by register or literal >= 32 -> overflows, all bits are the sign bit
101
                        -- shift by register or literal, 32 positions
102
                        if (exe_barrelshift_operand = '1' and op_c_data(7 downto 0) >= x"20")
103
                        or (exe_barrelshift_operand = '0' and exe_literal_shift_amnt = "00000")
104
                        then
105
                                barrelshift_out <= (others => shift_in(31));
106
                                barrelshift_c <= shift_in(31);
107
 
108
                        -- shift by register = 0, opb passes through and C is unaffected
109
                        elsif exe_barrelshift_operand = '1' and op_c_data(7 downto 0) = x"00"
110
                        then
111
                                barrelshift_out <= shift_in;
112
                                barrelshift_c <= c;
113
 
114
                        -- shift by literal or register, range 1..31
115
                        else
116
                                barrelshift_out <= unsigned(shift_right(signed(shift_in), shift_positions));
117
                                barrelshift_c <= shift_in(shift_positions - 1);
118
                        end if;
119
 
120
                -- ROR / RRX
121
                when "11" =>
122
                        -- RRX - 33 bit rotation with carry
123
                        if exe_barrelshift_operand = '0' and exe_literal_shift_amnt = "00000"
124
                        then
125
                                barrelshift_out <= c & shift_in(31 downto 1);
126
                                barrelshift_c <= shift_in(0);
127
 
128
                        -- ROR by register = 0, opb passes through and C is unaffected
129
                        elsif exe_barrelshift_operand = '1' and op_c_data(7 downto 0) = x"00"
130
                        then
131
                                barrelshift_out <= shift_in;
132
                                barrelshift_c <= c;
133
 
134
                        -- ROR by register = 32, 64, etc.... opb passes through but C is affected
135
                        elsif exe_barrelshift_operand = '1' and op_c_data(4 downto 0) = "00000"
136
                        then
137
                                barrelshift_out <= shift_in;
138
                                barrelshift_c <= shift_in(31);
139
 
140
                        -- ROR by literal or register, range 1..31 (if ROR by register, 33 => 1, 34 => 2, etc....)
141
                        else
142
                                barrelshift_out <= shift_in ror shift_positions;
143
                                barrelshift_c <= shift_in(shift_positions - 1);
144
                        end if;
145
 
146
                -- LSL
147
                when others =>  -- "00"
148
                        -- shift by register > 32 -> overflows, all bits are out
149
                        if exe_barrelshift_operand = '1' and op_c_data(7 downto 0) > x"20"
150
                        then
151
                                barrelshift_out <= (others => '0');
152
                                barrelshift_c <= '0';
153
 
154
                        -- shift by register = 32 positions
155
                        elsif exe_barrelshift_operand = '1' and op_c_data(7 downto 0) = x"20"
156
                        then
157
                                barrelshift_out <= (others => '0');
158
                                barrelshift_c <= shift_in(0);
159
 
160
                        -- shift by register = 0 or literal = 0, opb passes through and C is unaffected
161
                        elsif shift_positions = 0
162
                        then
163
                                barrelshift_out <= shift_in;
164
                                barrelshift_c <= c;
165
 
166
                        -- shift by literal or register, range 1..31
167
                        else
168
                                barrelshift_out <= shift_in sll shift_positions;
169
                                barrelshift_c <= shift_in(32 - shift_positions);
170
                        end if;
171
                end case;
172
        end process;
173
end;
174
 
175
-- optimized architecture expliciting all stages of the barrel shifter
176
-- (individual shifters by power of 2 bits in series)
177
-- synthetizes in something way better
178
architecture optimized of barrelshift is
179
        signal shift_in : unsigned(31 downto 0);
180
        signal shift_amnt : unsigned(4 downto 0);
181
        signal stage1_dout, stage2_dout, stage3_dout, stage4_dout, stage5_dout : unsigned(31 downto 0);
182
        signal stage1_cout, stage2_cout, stage3_cout, stage4_cout, stage5_cout : std_logic;
183
begin
184
        -- Barrelshifter made manually with 5 individual shift stages in series
185
 
186
        -- shift by 1 position
187
        stage1 : process(shift_in, c, shift_amnt, exe_barrelshift_type) is
188
        begin
189
                if shift_amnt(0) = '1'
190
                then
191
                        case exe_barrelshift_type is
192
                        when "00" =>            -- LSL #1
193
                                stage1_dout <= shift_in(30 downto 0) & '0';
194
                                stage1_cout <= shift_in(31);
195
                        when "01" =>            -- LSR #1
196
                                stage1_dout <= '0' & shift_in(31 downto 1);
197
                                stage1_cout <= shift_in(0);
198
                        when "10" =>            -- ASR #1
199
                                stage1_dout <= shift_in(31) & shift_in(31 downto 1);
200
                                stage1_cout <= shift_in(0);
201
                        when others =>          -- ROR #1
202
                                stage1_dout <= shift_in(0) & shift_in(31 downto 1);
203
                                stage1_cout <= shift_in(0);
204
                        end case;
205
                else
206
                        stage1_dout <= shift_in;
207
                        stage1_cout <= c;
208
                end if;
209
        end process;
210
 
211
        -- shift by 2 positions
212
        stage2 : process(stage1_dout, stage1_cout, shift_amnt, exe_barrelshift_type) is
213
        begin
214
                if shift_amnt(1) = '1'
215
                then
216
                        case exe_barrelshift_type is
217
                        when "00" =>            -- LSL #2
218
                                stage2_dout <= stage1_dout(29 downto 0) & "00";
219
                                stage2_cout <= stage1_dout(30);
220
                        when "01" =>            -- LSR #2
221
                                stage2_dout <= "00" & stage1_dout(31 downto 2);
222
                                stage2_cout <= stage1_dout(1);
223
                        when "10" =>            -- ASR #2
224
                                stage2_dout <= (1 downto 0 => stage1_dout(31)) & stage1_dout(31 downto 2);
225
                                stage2_cout <= stage1_dout(1);
226
                        when others =>          -- ROR #2
227
                                stage2_dout <= stage1_dout(1 downto 0) & stage1_dout(31 downto 2);
228
                                stage2_cout <= stage1_dout(1);
229
                        end case;
230
                else
231
                        stage2_dout <= stage1_dout;
232
                        stage2_cout <= stage1_cout;
233
                end if;
234
        end process;
235
 
236
        -- shift by 4 positions
237
        stage3 : process(stage2_dout, stage2_cout, shift_amnt, exe_barrelshift_type) is
238
        begin
239
                if shift_amnt(2) = '1'
240
                then
241
                        case exe_barrelshift_type is
242
                        when "00" =>            -- LSL #4
243
                                stage3_dout <= stage2_dout(27 downto 0) & "0000";
244
                                stage3_cout <= stage2_dout(28);
245
                        when "01" =>            -- LSR #4
246
                                stage3_dout <= "0000" & stage2_dout(31 downto 4);
247
                                stage3_cout <= stage2_dout(3);
248
                        when "10" =>            -- ASR #4
249
                                stage3_dout <= (3 downto 0 => stage2_dout(31)) & stage2_dout(31 downto 4);
250
                                stage3_cout <= stage2_dout(3);
251
                        when others =>          -- ROR #4
252
                                stage3_dout <= stage2_dout(3 downto 0) & stage2_dout(31 downto 4);
253
                                stage3_cout <= stage2_dout(3);
254
                        end case;
255
                else
256
                        stage3_dout <= stage2_dout;
257
                        stage3_cout <= stage2_cout;
258
                end if;
259
        end process;
260
 
261
        -- shift by 8 positions
262
        stage4 : process(stage3_dout, stage3_cout, shift_amnt, exe_barrelshift_type) is
263
        begin
264
                if shift_amnt(3) = '1'
265
                then
266
                        case exe_barrelshift_type is
267
                        when "00" =>            -- LSL #8
268
                                stage4_dout <= stage3_dout(23 downto 0) & (7 downto 0 => '0');
269
                                stage4_cout <= stage3_dout(24);
270
                        when "01" =>            -- LSR #8
271
                                stage4_dout <= (7 downto 0 => '0') & stage3_dout(31 downto 8);
272
                                stage4_cout <= stage3_dout(7);
273
                        when "10" =>            -- ASR #8
274
                                stage4_dout <= (7 downto 0 => stage3_dout(31)) & stage3_dout(31 downto 8);
275
                                stage4_cout <= stage3_dout(7);
276
                        when others =>          -- ROR #8
277
                                stage4_dout <= stage3_dout(7 downto 0) & stage3_dout(31 downto 8);
278
                                stage4_cout <= stage3_dout(7);
279
                        end case;
280
                else
281
                        stage4_dout <= stage3_dout;
282
                        stage4_cout <= stage3_cout;
283
                end if;
284
        end process;
285
 
286
        -- shift by 16 positions
287
        stage5 : process(stage4_dout, stage4_cout, shift_amnt, exe_barrelshift_type) is
288
        begin
289
                if shift_amnt(4) = '1'
290
                then
291
                        case exe_barrelshift_type is
292
                        when "00" =>            -- LSL #16
293
                                stage5_dout <= stage4_dout(15 downto 0) & (15 downto 0 => '0');
294
                                stage5_cout <= stage4_dout(15);
295
                        when "01" =>            -- LSR #16
296
                                stage5_dout <= (15 downto 0 => '0') & stage4_dout(31 downto 16);
297
                                stage5_cout <= stage4_dout(15);
298
                        when "10" =>            -- ASR #16
299
                                stage5_dout <= (15 downto 0 => stage4_dout(31)) & stage4_dout(31 downto 16);
300
                                stage5_cout <= stage4_dout(15);
301
                        when others =>          -- ROR #16
302
                                stage5_dout <= stage4_dout(15 downto 0) & stage4_dout(31 downto 16);
303
                                stage5_cout <= stage4_dout(15);
304
                        end case;
305
                else
306
                        stage5_dout <= stage4_dout;
307
                        stage5_cout <= stage4_cout;
308
                end if;
309
        end process;
310
 
311
        -- Barelshifter control logic
312
        barrelshift : process(exe_barrelshift_operand, exe_barrelshift_type, op_b_data, op_c_data, exe_opb_is_literal,
313
                                                  exe_literal_shift_amnt, exe_literal_data, c, shift_in, stage5_dout, stage5_cout) is
314
        begin
315
                        -- shift by register (opc)
316
                if exe_barrelshift_operand = '1'
317
                then
318
                        shift_amnt <= op_c_data(4 downto 0);
319
                else
320
                        -- shift by literal value
321
                        shift_amnt <= unsigned(exe_literal_shift_amnt);
322
                end if;
323
 
324
                if exe_opb_is_literal = '1'
325
                then
326
                        -- sign extend literal value
327
                        shift_in <= (31 downto 24 => exe_literal_data(23)) & unsigned(exe_literal_data);
328
                else
329
                        shift_in <= op_b_data;
330
                end if;
331
 
332
                case exe_barrelshift_type is
333
                -- LSL
334
                when "00" =>
335
                        -- shift by register > 32 -> overflows, all bits are out
336
                        if exe_barrelshift_operand = '1' and op_c_data(7 downto 0) > x"20"
337
                        then
338
                                barrelshift_out <= (others => '0');
339
                                barrelshift_c <= '0';
340
 
341
                        -- shift by register = 32 positions
342
                        elsif exe_barrelshift_operand = '1' and op_c_data(7 downto 0) = x"20"
343
                        then
344
                                barrelshift_out <= (others => '0');
345
                                barrelshift_c <= shift_in(0);
346
 
347
                        -- shift by literal or register, range 0..31
348
                        else
349
                                barrelshift_out <= stage5_dout;
350
                                barrelshift_c <= stage5_cout;
351
                        end if;
352
 
353
                -- LSR
354
                when "01" =>
355
                        -- shift by register > 32 -> overflows, all bits are out
356
                        if exe_barrelshift_operand = '1' and op_c_data(7 downto 0) > x"20"
357
                        then
358
                                barrelshift_out <= (others => '0');
359
                                barrelshift_c <= '0';
360
 
361
                        -- shift by register or literal = 0, 32 positions
362
                        elsif (exe_barrelshift_operand = '1' and op_c_data(7 downto 0) = x"20")
363
                           or (exe_barrelshift_operand = '0' and exe_literal_shift_amnt = "00000")
364
                        then
365
                                barrelshift_out <= (others => '0');
366
                                barrelshift_c <= shift_in(31);
367
 
368
                        -- shift by literal or register, range 0..31
369
                        else
370
                                barrelshift_out <= stage5_dout;
371
                                barrelshift_c <= stage5_cout;
372
                        end if;
373
 
374
                -- ASR
375
                when "10" =>
376
                        -- shift by register >= 32 or literal = 0, 32 positions -> overflows, all bits are the sign bit
377
                        if (exe_barrelshift_operand = '1' and op_c_data(7 downto 0) >= x"20")
378
                        or (exe_barrelshift_operand = '0' and exe_literal_shift_amnt = "00000")
379
                        then
380
                                barrelshift_out <= (others => shift_in(31));
381
                                barrelshift_c <= shift_in(31);
382
 
383
                        -- shift by literal or register, range 0..31
384
                        else
385
                                barrelshift_out <= stage5_dout;
386
                                barrelshift_c <= stage5_cout;
387
                        end if;
388
 
389
                -- ROR / RRX
390
                when others =>          -- "11"
391
                        -- RRX - 33 bit rotation with carry
392
                        if exe_barrelshift_operand = '0' and exe_literal_shift_amnt = "00000"
393
                        then
394
                                barrelshift_out <= c & op_b_data(31 downto 1);
395
                                barrelshift_c <= shift_in(0);
396
 
397
                        -- ROR by register = 32, 64, etc.... opb passes through but C is affected
398
                        elsif exe_barrelshift_operand = '1' and op_c_data(4 downto 0) = "00000"
399
                        then
400
                                barrelshift_out <= stage5_dout;
401
                                barrelshift_c <= shift_in(31);
402
 
403
                        -- ROR by literal or register, range 0..31 (if ROR by register, 33 => 1, 34 => 2, etc....)
404
                        else
405
                                barrelshift_out <= stage5_dout;
406
                                barrelshift_c <= stage5_cout;
407
                        end if;
408
                end case;
409
        end process;
410
 
411
end;

powered by: WebSVN 2.1.0

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