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

Subversion Repositories v65c816

[/] [v65c816/] [trunk/] [alu_bin.vhd] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 Valerio63
library IEEE;
2
use IEEE.std_logic_1164.all;  -- defines std_logic types
3
use IEEE.STD_LOGIC_unsigned.all;
4
use IEEE.STD_LOGIC_arith.all;
5
 
6
-- 8/16 bit binary alu
7
-- Written by Valerio Venturi
8
entity alu_bin is
9
  port( alu_byp:  in STD_LOGIC;                      -- ALU bypass (no operation)  
10
            bcd:  in STD_LOGIC;                      -- BCD mode 
11
           size:  in STD_LOGIC;                      -- operations size: 1 = 8 bit, 0 = 16 bit
12
            cin:  in STD_LOGIC;                      -- carry/borrow in
13
            vin:  in STD_LOGIC;                      -- overflow in
14
            op1:  in STD_LOGIC_VECTOR(15 downto 0);  -- 16 bit operand #1
15
            op2:  in STD_LOGIC_VECTOR(15 downto 0);  -- 16 bit operand #2
16
             fc:  in STD_LOGIC_VECTOR(4 downto 0);   -- function code
17
             cf: out STD_LOGIC;                      -- carry/borrow out 
18
             zf: out STD_LOGIC;                      -- zero flag out
19
             nf: out STD_LOGIC;                      -- negative flag out
20
             vf: out STD_LOGIC;                      -- overflow flag out
21
          pc_cf: out STD_LOGIC;                      -- carry/borrow out for PC operation 
22
           dout: out STD_LOGIC_VECTOR(15 downto 0)   -- 16 bit result out
23
      );
24
end alu_bin;
25
 
26
architecture comb of alu_bin is
27
-- ALU function codes
28
constant NOP_A: STD_LOGIC_VECTOR(4 downto 0) := "00000";    -- no operation
29
constant SUM_A: STD_LOGIC_VECTOR(4 downto 0) := "00001";    -- sum with carry
30
constant SUB_A: STD_LOGIC_VECTOR(4 downto 0) := "00010";    -- subtract with borrow
31
constant AND_A: STD_LOGIC_VECTOR(4 downto 0) := "00011";    -- and
32
constant  OR_A: STD_LOGIC_VECTOR(4 downto 0) := "00100";    -- or
33
constant XOR_A: STD_LOGIC_VECTOR(4 downto 0) := "00101";    -- xor
34
constant INC_A: STD_LOGIC_VECTOR(4 downto 0) := "00110";    -- increment by 1
35
constant DEC_A: STD_LOGIC_VECTOR(4 downto 0) := "00111";    -- decrement by 1
36
constant SHL_A: STD_LOGIC_VECTOR(4 downto 0) := "01000";    -- shift left
37
constant SHR_A: STD_LOGIC_VECTOR(4 downto 0) := "01001";    -- shift right
38
constant ROL_A: STD_LOGIC_VECTOR(4 downto 0) := "01010";    -- rotation left
39
constant ROR_A: STD_LOGIC_VECTOR(4 downto 0) := "01011";    -- rotation right
40
constant SWC_A: STD_LOGIC_VECTOR(4 downto 0) := "01100";    -- sum without carry (used for indexing and branches)
41
constant SWC_N: STD_LOGIC_VECTOR(4 downto 0) := "01100";    -- subtract without borrow (used only by branches with negative offset)
42
constant BIT_A: STD_LOGIC_VECTOR(4 downto 0) := "01101";    -- bit test (used by BIT opcode)
43
constant DAA_A: STD_LOGIC_VECTOR(4 downto 0) := "01110";    -- decimal adjustement for BCD sum
44
constant DAS_A: STD_LOGIC_VECTOR(4 downto 0) := "01111";    -- decimal adjustement for BCD subtract
45
constant CMP_A: STD_LOGIC_VECTOR(4 downto 0) := "10000";    -- compare
46
constant TSB_A: STD_LOGIC_VECTOR(4 downto 0) := "10001";    -- test and set bit
47
constant TRB_A: STD_LOGIC_VECTOR(4 downto 0) := "10010";    -- test and reset bit
48
constant EXT_A: STD_LOGIC_VECTOR(4 downto 0) := "10011";    -- extend sign
49
constant NEG_A: STD_LOGIC_VECTOR(4 downto 0) := "10100";    -- negate
50
 
51
signal       c: STD_LOGIC;
52
signal    pc_c: STD_LOGIC;
53
signal     v_8: STD_LOGIC;
54
signal    v_16: STD_LOGIC;
55
signal   v_flg: STD_LOGIC;
56
signal  add_op: STD_LOGIC;
57
signal   bcd_c: STD_LOGIC;
58
signal   bcd_v: STD_LOGIC;
59
signal  n_size: STD_LOGIC;
60
signal bcd_sum: STD_LOGIC_VECTOR(15 downto 0);
61
signal  n8_op2: STD_LOGIC_VECTOR(7 downto 0);
62
signal n16_op2: STD_LOGIC_VECTOR(15 downto 0);
63
signal      y8: STD_LOGIC_VECTOR(8 downto 0);
64
signal     y16: STD_LOGIC_VECTOR(16 downto 0);
65
signal       y: STD_LOGIC_VECTOR(15 downto 0);
66
signal   i_op1: STD_LOGIC_VECTOR(7 downto 0);
67
signal   i_op2: STD_LOGIC_VECTOR(7 downto 0);
68
 
69
 
70
component AddSubBCD is
71
        port(
72
                    A: in std_logic_vector(15 downto 0);
73
                    B: in std_logic_vector(15 downto 0);
74
                   CI: in std_logic;
75
                  ADD: in std_logic;
76
                  BCD: in std_logic;
77
                  w16: in std_logic;
78
                    S: out std_logic_vector(15 downto 0);
79
                   CO: out std_logic;
80
                   VO: out std_logic
81
    );
82
end component;
83
 
84
 
85
begin
86
n_size <= not size;
87
u1:AddSubBCD port map(A=>op1,
88
                      B=>op2,
89
                                               CI=>cin,
90
                                                    ADD=>add_op,
91
                                                    BCD=>'1',
92
                      W16=>n_size,
93
                      S=>bcd_sum,
94
                                                    CO=>bcd_c,
95
                                                    vO=>bcd_v
96
                                              );
97
 
98
  i_op1 <= op1(7 downto 0);
99
  i_op2 <= op2(7 downto 0);
100
  n8_op2 <= (not i_op2);
101
  n16_op2 <= (not op2);
102
  process(size,bcd,alu_byp,fc,i_op1,i_op2,n8_op2,n16_op2,op1,op2,bcd_sum,cin,y16(7))
103
  begin
104
    if size = '1' then
105
            -- 8 bit
106
                 if alu_byp = '1' then
107
                        y8(y8'left) <= '0';
108
                        y8(y8'left-1 downto y8'right) <= i_op1;
109
         add_op <= '0';
110
                 else
111
                        case fc is
112
                          when SUM_A  =>
113
                add_op <= '1';
114
                               if bcd = '0' then
115
                                         y8 <= ('0' & i_op1) + ('0' & i_op2) + ("00000000" & cin);       -- ADC with carry in
116
                                         else
117
                                                   y8 <= '0' & bcd_sum(7 downto 0);
118
                end if;
119
                          when SUB_A  =>
120
                add_op <= '0';
121
                               if bcd = '0' then
122
                                         y8 <= ('0' & i_op1) + ('0' & n8_op2) + ("00000000" & cin);      -- SBC with borrow in
123
                                    else
124
                                                   y8 <= '0' & bcd_sum(7 downto 0);
125
                end if;
126
                          when BIT_A  => y8 <= ('0' & i_op1) and ('0' & i_op2);                          -- BIT test
127
                                         add_op <= '0';
128
                          when AND_A  => y8 <= ('0' & i_op1) and ('0' & i_op2);                          -- AND
129
                                         add_op <= '0';
130
                          when OR_A   => y8 <= ('0' & i_op1)  or ('0' & i_op2);                          -- OR
131
                                         add_op <= '0';
132
                          when XOR_A  => y8 <= ('0' & i_op1) xor ('0' & i_op2);                          -- XOR
133
                                         add_op <= '0';
134
                          when INC_A  => y8 <= i_op1 + "000000001";                                      -- INC
135
                                         add_op <= '0';
136
                          when DEC_A  => y8 <= i_op1 - "000000001";                                      -- DEC
137
                                         add_op <= '0';
138
                          when SHL_A  => y8(8 downto 1) <= i_op1; y8(0) <= '0';                          -- ASL
139
                                         add_op <= '0';
140
                          when SHR_A  => y8 <= "00" & i_op1(i_op1'left downto i_op1'right+1);            -- LSR
141
                                         add_op <= '0';
142
                          when ROL_A  => y8(8 downto 1) <= i_op1; y8(0) <= cin;                          -- ROL
143
                                         add_op <= '0';
144
                          when ROR_A  => y8 <= '0' & cin & i_op1(i_op1'left downto i_op1'right+1);       -- ROR
145
                                         add_op <= '0';
146
                          when SWC_A  => y8 <= ('0' & i_op1) + ('0' & i_op2);                            -- ADD without carry in
147
                                         add_op <= '0';
148
                          when DAA_A  => y8 <= '0' & bcd_sum(7 downto 0);                                -- ADD without carry in (used for DAA decimal adjustement)
149
                                         add_op <= '0';
150
                          when DAS_A  => y8 <= '0' & bcd_sum(7 downto 0);                                -- SUB without borrow in (used for DAS decimal adjustement)
151
                                         add_op <= '1';
152
                          when CMP_A  => y8 <= ('1' & i_op1) - ('0' & i_op2);                            -- SBC without borrow in (used for compare)
153
                                         add_op <= '0';
154
                          when TSB_A  => y8 <= ('0' & i_op1) or ('0' & i_op2);                           -- TSB
155
                                         add_op <= '0';
156
                          when TRB_A  => y8 <= ('0' & not i_op1) and ('0' & i_op2);                      -- TRB
157
                                         add_op <= '0';
158
                          when NEG_A  => y8 <= "000000000" - ('0' & i_op1);                              -- NEG
159
                                         add_op <= '0';
160
                          when EXT_A  => y8(y8'left) <= '0'; y8(y8'left-1 downto y8'right) <= i_op1;     -- NOP
161
                                         add_op <= '0';
162
                          when others => y8(y8'left) <= '0'; y8(y8'left-1 downto y8'right) <= i_op1;     -- NOP
163
                                         add_op <= '0';
164
                        end case;
165
                 end if;
166
                 y16 <= (others => '0');
167
         else
168
            -- 16 bit
169
                 if alu_byp = '1' then
170
                        y16(y16'left) <= '0';
171
                        y16(y16'left-1 downto y16'right) <= op1;
172
         add_op <= '0';
173
                 else
174
                        case fc is
175
                          when SUM_A  =>
176
                add_op <= '1';
177
                               if bcd = '0' then
178
                                         y16 <= ('0' & op1) + ('0' & op2) + ("0000000000000000" & cin);       -- ADC with carry in
179
                                         else
180
                                                   y16 <= '0' & bcd_sum;
181
                end if;
182
                          when SUB_A  =>
183
                add_op <= '0';
184
                               if bcd = '0' then
185
                                         y16 <= ('0' & op1) + ('0' & n16_op2) + ("0000000000000000" & cin);   -- SBC with borrow in
186
                                    else
187
                                                   y16 <= '0' & bcd_sum;
188
                end if;
189
                          when BIT_A  => y16 <= ('0' & op1) and ('0' & op2);                                  -- BIT test
190
                                         add_op <= '0';
191
                          when AND_A  => y16 <= ('0' & op1) and ('0' & op2);                                  -- AND
192
                                         add_op <= '0';
193
                          when OR_A   => y16 <= ('0' & op1)  or ('0' & op2);                                  -- OR
194
                                         add_op <= '0';
195
                          when XOR_A  => y16 <= ('0' & op1) xor ('0' & op2);                                  -- XOR
196
                                         add_op <= '0';
197
                          when INC_A  => y16 <= op1 + "00000000000000001";                                    -- INC
198
                                         add_op <= '0';
199
                          when DEC_A  => y16 <= op1 - "00000000000000001";                                    -- DEC
200
                                         add_op <= '0';
201
                          when SHL_A  => y16(16 downto 1) <= op1; y16(0) <= '0';                              -- ASL
202
                                         add_op <= '0';
203
                          when SHR_A  => y16 <= "00" & op1(op1'left downto op1'right+1);                      -- LSR
204
                                         add_op <= '0';
205
                          when ROL_A  => y16(16 downto 1) <= op1; y16(0) <= cin;                              -- ROL
206
                                         add_op <= '0';
207
                          when ROR_A  => y16 <= '0' & cin & op1(op1'left downto op1'right+1);                 -- ROR
208
                                         add_op <= '0';
209
                          when SWC_A  => y16 <= ('0' & op1) + ('0' & op2);                                    -- ADD without carry in
210
                                         add_op <= '0';
211
                          when DAA_A  => y16 <= '0' & bcd_sum;                                                -- ADD without carry in (used for DAA decimal adjustement)
212
                                         add_op <= '0';
213
                          when DAS_A  => y16 <= '0' & bcd_sum;                                                -- SUB without borrow in (used for DAS decimal adjustement)
214
                                         add_op <= '1';
215
                          when CMP_A  => y16 <= ('1' & op1) - ('0' & op2);                                    -- SBC without borrow in (used for compare)
216
                                         add_op <= '0';
217
                          when TSB_A  => y16 <= ('0' & op1) or ('0' & op2);                                   -- TSB
218
                                         add_op <= '0';
219
                          when TRB_A  => y16 <= ('0' & not op1) and ('0' & op2);                              -- TRB
220
                                         add_op <= '0';
221
                          when EXT_A  => if op1(7) = '1' then                                                 -- if negative
222
                                            y16(16 downto 8) <= "111111111";                                  -- extend sign to msb
223
                                                                          y16(7 downto 0) <= op1(7 downto 0);
224
                                              else
225
                                                      y16(16 downto 8) <= "000000000";
226
                                                                          y16(7 downto 0) <= op1(7 downto 0);
227
                          end if;
228
                                         add_op <= '0';
229
                          when NEG_A  => y16 <= "00000000000000000" - ('0' & op1);                            -- NEG
230
                                         add_op <= '0';
231
                          when others => y16(y16'left) <= '0'; y16(y16'left-1 downto y16'right) <= op1;       -- NOP
232
                                         add_op <= '0';
233
                        end case;
234
                 end if;
235
                 y8 <= (others => '0');
236
         end if;
237
  end process;
238
 
239
 
240
 
241
  -- flag "C" carry/borrow logic
242
  process(size,bcd,bcd_c,fc,op1,y8,y16,cin)
243
  begin
244
    if size = '1' then
245
                 case fc is
246
                        when SUM_A  =>
247
                                    if bcd = '0' then
248
                                       c    <= y8(y8'left);
249
                                                   else
250
                                                 c    <= bcd_c;
251
                                                   end if;
252
                                                                pc_c <= '0';
253
                        when SUB_A  =>
254
                                    if bcd = '0' then
255
                                       c    <= y8(y8'left);
256
                                                   else
257
                                                 c    <= bcd_c;
258
                                                   end if;
259
                                                                pc_c <= '0';
260
                        when SWC_A  => pc_c <= y8(y8'left);
261
                                                                c    <= cin;
262
                        when SHL_A  => c    <= y8(y8'left);
263
                                                                pc_c <= '0';
264
                        when SHR_A  => c    <= op1(op1'right);
265
                                                                pc_c <= '0';
266
                        when ROL_A  => c    <= y8(y8'left);
267
                                                                pc_c <= '0';
268
                        when ROR_A  => c    <= op1(op1'right);
269
                                                                pc_c <= '0';
270
                        when DAA_A  => c    <= y8(y8'left);
271
                                                                pc_c <= '0';
272
                        when DAS_A  => c    <= cin;
273
                                                                pc_c <= '0';
274
                        when BIT_A  => c    <= cin;
275
                                                                pc_c <= '0';
276
                        when CMP_A  => c    <= y8(y8'left);
277
                                                                pc_c <= '0';
278
                        when others => c    <= cin;
279
                                                                pc_c <= '0';
280
                 end case;
281
         else
282
                 case fc is
283
                        when SUM_A  =>
284
                                    if bcd = '0' then
285
                                       c    <= y16(y16'left);
286
                                                   else
287
                                                 c    <= bcd_c;
288
                                              end if;
289
                                                                pc_c <= '0';
290
                        when SUB_A  =>
291
                                    if bcd = '0' then
292
                                       c    <= y16(y16'left);
293
                                                   else
294
                                                 c    <= bcd_c;
295
                                              end if;
296
                                                                pc_c <= '0';
297
                        when SWC_A  => pc_c <= y16(8);
298
                                                                c    <= cin;
299
                        when SHL_A  => c    <= y16(y16'left);
300
                                                                pc_c <= '0';
301
                        when SHR_A  => c    <= op1(op1'right);
302
                                                                pc_c <= '0';
303
                        when ROL_A  => c    <= y16(y16'left);
304
                                                                pc_c <= '0';
305
                        when ROR_A  => c    <= op1(op1'right);
306
                                                                pc_c <= '0';
307
                        when DAA_A  => c    <= y16(y16'left);
308
                                                                pc_c <= '0';
309
                        when DAS_A  => c    <= cin;
310
                                                                pc_c <= '0';
311
                        when BIT_A  => c    <= cin;
312
                                                                pc_c <= '0';
313
                        when CMP_A  => c    <= y16(y16'left);
314
                                                                pc_c <= '0';
315
                        when others => c    <= cin;
316
                                                                pc_c <= '0';
317
                 end case;
318
         end if;
319
  end process;
320
 
321
  -- flag "V" overflow logic
322
  v_8  <= not (((op1(7) nor op2(7)) and y8(6)) nor ((op1(7) nand op2(7)) nor y8(6)));
323
  v_16 <= not (((op1(15) nor op2(15)) and y16(14)) nor ((op1(15) nand op2(15)) nor y16(14)));
324
  v_flg <= v_8 when size = '1' else v_16;
325
  process(size,fc,bcd,i_op2,op2,v_flg,bcd_v,vin)
326
  begin
327
    case fc is
328
      when SUM_A  =>
329
                                                        if bcd = '0' then
330
                                                                                        vf <= v_flg;
331
                                                        else
332
                                                                                        vf <= bcd_v;
333
                                                        end if;
334
      when SUB_A  =>
335
                                                        if bcd = '0' then
336
                                                                                        vf <= v_flg;
337
                                                        else
338
                                                                                        vf <= bcd_v;
339
                                                        end if;
340
      when BIT_A  =>
341
                     if size = '1' then
342
                                           vf <= op2(6);
343
                                                        else
344
                                                vf <= op2(14);
345
                                                        end if;
346
      when others =>             vf <= vin;
347
    end case;
348
  end process;
349
 
350
  -- flag "N" negative result logic
351
  process(size,fc,i_op2,y8,y16)
352
  begin
353
    if size = '1' then
354
                 case fc is
355
                        when BIT_A  => nf <= i_op2(i_op2'left);
356
                        when others => nf <= y8(y8'left-1);
357
                 end case;
358
         else
359
                 case fc is
360
                        when BIT_A  => nf <= i_op2(i_op2'left);
361
                        when others => nf <= y16(y16'left-1);
362
                 end case;
363
         end if;
364
  end process;
365
 
366
  -- flag "Z" zero result logic (always set with zero results)
367
  process(size,y8,y16)
368
  begin
369
    if size = '1' then
370
            if y8(y8'left-1 downto y8'right) = "00000000" then
371
          zf <= '1';
372
                 else
373
          zf <= '0';
374
            end if;
375
    else
376
            if y16(y16'left-1 downto y16'right) = "0000000000000000" then
377
          zf <= '1';
378
                 else
379
          zf <= '0';
380
            end if;
381
    end if;
382
  end process;
383
 
384
  y <= op1(15 downto 8) & y8(y8'left-1 downto y8'right) when size = '1' else y16(y16'left-1 downto y16'right);
385
 
386
 
387
  cf <= c;
388
  pc_cf <= pc_c;
389
  dout <= y;
390
end comb;

powered by: WebSVN 2.1.0

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