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

Subversion Repositories c16

[/] [c16/] [trunk/] [vhdl/] [alu8.vhd] - Blame information for rev 2

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

Line No. Rev Author Line
1 2 jsauermann
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.STD_LOGIC_ARITH.ALL;
4
use IEEE.STD_LOGIC_UNSIGNED.ALL;
5
 
6
--  Uncomment the following lines to use the declarations that are
7
--  provided for instantiating Xilinx primitive components.
8
--library UNISIM;
9
--use UNISIM.VComponents.all;
10
 
11
use work.cpu_pack.ALL;
12
 
13
entity alu8 is
14
        PORT(   CLK_I : in   std_logic;
15
                        T2    : in   std_logic;
16
                        CLR   : in   std_logic;
17
                        CE    : in   std_logic;
18
 
19
                        ALU_OP : in  std_logic_vector( 4 downto 0);
20
                        XX     : in  std_logic_vector(15 downto 0);
21
                        YY     : in  std_logic_vector(15 downto 0);
22
 
23
                        ZZ     : out std_logic_vector(15 downto 0)
24
                );
25
end alu8;
26
 
27
architecture Behavioral of alu8 is
28
 
29
 
30
        function sh_mask(Y    : unsigned(3 downto 0);
31
                                         YMAX : unsigned(3 downto 0);
32
                         LR   : std_logic;
33
                         FILL : std_logic;
34
                                         X    : std_logic) return std_logic is
35
 
36
        begin
37
                if (YMAX >= Y) then                                                                     -- Y small
38
                        if (LR = '1') then              return  X;                      -- LSL
39
                        else                                    return  FILL;           -- LSR
40
                        end if;
41
                else                                                                                            -- Y big
42
                        if (LR = '1') then              return  FILL;           -- LSL
43
                        else                                    return  X;                      -- ASR/LSR
44
                        end if;
45
                end if;
46
        end;
47
 
48
        function b8(A : std_logic) return std_logic_vector is
49
        begin
50
                return A & A & A & A & A & A & A & A;
51
        end;
52
 
53
        function b16(A : std_logic) return std_logic_vector is
54
        begin
55
                return b8(A) & b8(A);
56
        end;
57
 
58
        function aoxn(A : std_logic_vector(3 downto 0)) return std_logic is
59
        begin
60
                case A is
61
                        -- and
62
                        when "0000" =>  return '0';
63
                        when "0001" =>  return '0';
64
                        when "0010" =>  return '0';
65
                        when "0011" =>  return '1';
66
                        -- or
67
                        when "0100" =>  return '0';
68
                        when "0101" =>  return '1';
69
                        when "0110" =>  return '1';
70
                        when "0111" =>  return '1';
71
                        -- xor
72
                        when "1000" =>  return '1';
73
                        when "1001" =>  return '0';
74
                        when "1010" =>  return '0';
75
                        when "1011" =>  return '1';
76
                        -- not Y
77
                        when "1100" =>  return '1';
78
                        when "1101" =>  return '0';
79
                        when "1110" =>  return '1';
80
                        when others =>  return '0';
81
                end case;
82
        end;
83
 
84
        signal MD_OR     : std_logic_vector(15 downto 0);                -- Multiplicator/Divisor
85
        signal PROD_REM  : std_logic_vector(31 downto 0);
86
        signal MD_OP     : std_logic;                                           -- operation D/M, S/U
87
        signal QP_NEG    : std_logic;                                           -- product / quotient negative
88
        signal RM_NEG    : std_logic;                                           -- remainder negative
89
 
90
begin
91
 
92
        alumux: process(ALU_OP, MD_OP, XX, YY, QP_NEG, RM_NEG, PROD_REM)
93
 
94
                variable MASKED_X : std_logic_vector(15 downto 0);
95
                variable SCNT     : unsigned(3 downto 0);
96
                variable SFILL    : std_logic;
97
                variable ROL1     : std_logic_vector(15 downto 0);
98
                variable ROL2     : std_logic_vector(15 downto 0);
99
                variable ROL4     : std_logic_vector(15 downto 0);
100
                variable ROL8     : std_logic_vector(15 downto 0);
101
                variable X_GE_Y   : std_logic;  -- signed   X >=  Y
102
                variable X_HS_Y   : std_logic;  -- unsigned X >=  Y
103
                variable X_HSGE_Y : std_logic;  -- any      X >=  Y
104
                variable X_EQ_Y   : std_logic;  -- signed   X ==  Y
105
                variable X_CMP_Y  : std_logic;
106
 
107
        begin
108
                MASKED_X := XX and b16(ALU_OP(0));
109
                SFILL    := ALU_OP(0) and XX(15);
110
 
111
                if (ALU_OP(1) = '1') then       -- LSL
112
                        SCNT := UNSIGNED(YY(3 downto 0));
113
                else                                            -- LSR / ASR
114
                        SCNT := "0000" - UNSIGNED(YY(3 downto 0));
115
                end if;
116
 
117
                if (SCNT(0) = '0') then   ROL1 := XX;
118
                else                                    ROL1 := XX(14 downto 0) & XX(15);
119
                end if;
120
 
121
                if (SCNT(1) = '0') then  ROL2 := ROL1;
122
                else                                    ROL2 := ROL1(13 downto 0) & ROL1(15 downto 14);
123
                end if;
124
 
125
                if (SCNT(2) = '0') then  ROL4 := ROL2;
126
                else                                    ROL4 := ROL2(11 downto 0) & ROL2(15 downto 12);
127
                end if;
128
 
129
                if (SCNT(3) = '0') then  ROL8 := ROL4;
130
                else                                    ROL8 := ROL4(7 downto 0) & ROL4(15 downto 8);
131
                end if;
132
 
133
                if (XX = YY) then               X_EQ_Y := '1';
134
                else                                    X_EQ_Y := '0';
135
                end if;
136
 
137
                if (UNSIGNED(XX) >= UNSIGNED(YY)) then          X_HSGE_Y := '1';
138
                else                                                                            X_HSGE_Y := '0';
139
                end if;
140
 
141
                if (XX(15) /= YY(15)) then              -- different sign/high bit
142
                        X_HS_Y := XX(15);               -- X ia bigger iff high bit set
143
                        X_GE_Y := YY(15);               -- X is bigger iff Y negative
144
                else                                                    -- same sign/high bit: GE == HS
145
                        X_HS_Y := X_HSGE_Y;
146
                        X_GE_Y := X_HSGE_Y;
147
                end if;
148
 
149
                case ALU_OP is
150
                        when    ALU_X_HS_Y      =>      X_CMP_Y :=      X_HS_Y;
151
                        when    ALU_X_LO_Y      =>      X_CMP_Y := not  X_HS_Y;
152
                        when    ALU_X_HI_Y      =>      X_CMP_Y :=      X_HS_Y and not X_EQ_Y;
153
                        when    ALU_X_LS_Y      =>      X_CMP_Y := not (X_HS_Y and not X_EQ_Y);
154
                        when    ALU_X_GE_Y      =>      X_CMP_Y :=      X_GE_Y;
155
                        when    ALU_X_LT_Y      =>      X_CMP_Y := not  X_GE_Y;
156
                        when    ALU_X_GT_Y      =>      X_CMP_Y :=      X_GE_Y and not X_EQ_Y;
157
                        when    ALU_X_LE_Y      =>      X_CMP_Y := not (X_GE_Y and not X_EQ_Y);
158
                        when    ALU_X_EQ_Y      =>      X_CMP_Y :=      X_EQ_Y;
159
                        when    others          =>      X_CMP_Y := not  X_EQ_Y;
160
                end case;
161
 
162
                ZZ <= X"0000";
163
 
164
                case ALU_OP is
165
                        when    ALU_X_HS_Y | ALU_X_LO_Y | ALU_X_HI_Y | ALU_X_LS_Y |
166
                                        ALU_X_GE_Y | ALU_X_LT_Y | ALU_X_GT_Y | ALU_X_LE_Y |
167
                                        ALU_X_EQ_Y | ALU_X_NE_Y =>
168
                                ZZ  <= b16(X_CMP_Y);
169
 
170
                        when    ALU_NEG_Y |     ALU_X_SUB_Y =>
171
                                ZZ  <= MASKED_X - YY;
172
 
173
                        when    ALU_MOVE_Y | ALU_X_ADD_Y =>
174
                                ZZ  <= MASKED_X + YY;
175
 
176
                        when    ALU_X_AND_Y | ALU_X_OR_Y  | ALU_X_XOR_Y | ALU_NOT_Y =>
177
                                for i in 0 to 15 loop
178
                                        ZZ(i) <= aoxn(ALU_OP(1 downto 0) & XX(i) & YY(i));
179
                                end loop;
180
 
181
                        when    ALU_X_LSR_Y | ALU_X_ASR_Y | ALU_X_LSL_Y =>
182
                                for i in 0 to 15 loop
183
                                        ZZ(i) <= sh_mask(SCNT, CONV_UNSIGNED(i, 4),
184
                                                                         ALU_OP(1), SFILL, ROL8(i));
185
                                end loop;
186
 
187
                        when    ALU_X_MIX_Y =>
188
                                        ZZ(15 downto 8) <= YY(7 downto 0);
189
                                        ZZ( 7 downto 0) <= XX(7 downto 0);
190
 
191
                        when    ALU_MUL_IU | ALU_MUL_IS |
192
                                        ALU_DIV_IU | ALU_DIV_IS | ALU_MD_STP => -- mult/div ini/step
193
                                        ZZ <= PROD_REM(15 downto 0);
194
 
195
                        when    ALU_MD_FIN =>   -- mult/div
196
                                if (QP_NEG = '0') then   ZZ <= PROD_REM(15 downto 0);
197
                                else                                    ZZ <= X"0000" - PROD_REM(15 downto 0);
198
                                end if;
199
 
200
                        when    others =>       -- modulo
201
                                if (RM_NEG = '0') then   ZZ <= PROD_REM(31 downto 16);
202
                                else                                    ZZ <= X"0000" - PROD_REM(31 downto 16);
203
                                end if;
204
                end case;
205
        end process;
206
 
207
        muldiv: process(CLK_I)
208
 
209
                variable POS_YY : std_logic_vector(15 downto 0);
210
                variable POS_XX : std_logic_vector(15 downto 0);
211
                variable DIFF   : std_logic_vector(16 downto 0);
212
                variable SUM    : std_logic_vector(16 downto 0);
213
 
214
        begin
215
                if (rising_edge(CLK_I)) then
216
                        if (T2 = '1') then
217
                                if (CLR = '1') then
218
                                        PROD_REM <= X"00000000";        -- product/remainder
219
                                        MD_OR    <= X"0000";            -- multiplicator/divisor
220
                                        MD_OP    <= '0';                 -- mult(0)/div(1)
221
                                        QP_NEG   <= '0';                 -- quotient/product negative
222
                                        RM_NEG   <= '0';                 -- remainder negative
223
                                elsif (CE = '1') then
224
                                        SUM  := ('0' & PROD_REM(31 downto 16)) + ('0' & MD_OR);
225
                                        DIFF := ('0' & PROD_REM(30 downto 15)) - ('0' & MD_OR);
226
 
227
                                        if (XX(15) = '0') then   POS_XX := XX;
228
                                        else                                    POS_XX := X"0000" - XX;
229
                                        end if;
230
 
231
                                        if (YY(15) = '0') then   POS_YY := YY;
232
                                        else                                    POS_YY := X"0000" - YY;
233
                                        end if;
234
 
235
                                        case  ALU_OP is
236
                                                when    ALU_MUL_IU | ALU_MUL_IS | ALU_DIV_IU | ALU_DIV_IS =>
237
                                                        MD_OP    <= ALU_OP(1);          -- div / mult
238
                                                        MD_OR    <= POS_YY;             -- multiplicator/divisor
239
                                                        QP_NEG   <= ALU_OP(0) and (XX(15) xor YY(15));
240
                                                        RM_NEG   <= ALU_OP(0) and  XX(15);
241
                                                        PROD_REM <= X"0000" & POS_XX;
242
 
243
                                                when    ALU_MD_STP =>
244
                                                        if (MD_OP = '0') then            -- multiplication step
245
 
246
                                                                PROD_REM(15 downto 0) <= PROD_REM(16 downto 1);
247
                                                                if (PROD_REM(0) = '0') then
248
                                                                                PROD_REM(31 downto 15) <=
249
                                                                                '0' & PROD_REM(31 downto 16);
250
                                                                else
251
                                                                        PROD_REM(31 downto 15) <= SUM;
252
                                                                end if;
253
                                                        else                                            -- division step
254
                                                                if (DIFF(16) = '1') then        -- carry: small remainder
255
                                                                        PROD_REM(31 downto 16) <= PROD_REM(30 downto 15);
256
                                                                else
257
                                                                        PROD_REM(31 downto 16) <= DIFF(15 downto 0);
258
                                                                end if;
259
 
260
                                                                PROD_REM(15 downto 1) <= PROD_REM(14 downto 0);
261
                                                                PROD_REM(0) <= not DIFF(16);
262
                                                        end if;
263
 
264
                                                when    others =>
265
                                        end case;
266
                                end if;
267
                        end if;
268
                end if;
269
        end process;
270
 
271
end Behavioral;

powered by: WebSVN 2.1.0

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