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

Subversion Repositories v6502

[/] [v6502/] [trunk/] [alu_bin.vhd] - Blame information for rev 6

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

Line No. Rev Author Line
1 4 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 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
            cin:  in STD_LOGIC;                      -- carry/borrow in
11
            vin:  in STD_LOGIC;                      -- overflow in
12
            op1:  in STD_LOGIC_VECTOR(7 downto 0);   -- 8 bit operand #1
13
            op2:  in STD_LOGIC_VECTOR(7 downto 0);   -- 8 bit operand #2
14
             fc:  in STD_LOGIC_VECTOR(5 downto 0);   -- function code (bit #0 serves as flag to signal an branch negative offset) 
15
             cf: out STD_LOGIC;                      -- carry/borrow out 
16
             zf: out STD_LOGIC;                      -- zero flag out
17
             nf: out STD_LOGIC;                      -- negative flag out
18
             vf: out STD_LOGIC;                      -- overflow flag out
19
          pc_cf: out STD_LOGIC;                      -- carry/borrow out for PC operation 
20
         bcd_ol: out STD_LOGIC;                      -- bcd lsb overflow  
21
         bcd_oh: out STD_LOGIC;                      -- bcd msb overflow  
22
           dout: out STD_LOGIC_VECTOR(7 downto 0)    -- 8 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(5 downto 0) := "000000";    -- no operation
29
constant SUM_A: STD_LOGIC_VECTOR(5 downto 0) := "000010";    -- sum with carry
30
constant SUB_A: STD_LOGIC_VECTOR(5 downto 0) := "000100";    -- subtract with borrow
31
constant AND_A: STD_LOGIC_VECTOR(5 downto 0) := "000110";    -- and
32
constant  OR_A: STD_LOGIC_VECTOR(5 downto 0) := "001000";    -- or
33
constant XOR_A: STD_LOGIC_VECTOR(5 downto 0) := "001010";    -- xor
34
constant INC_A: STD_LOGIC_VECTOR(5 downto 0) := "001100";    -- increment by 1
35
constant DEC_A: STD_LOGIC_VECTOR(5 downto 0) := "001110";    -- decrement by 1
36
constant SHL_A: STD_LOGIC_VECTOR(5 downto 0) := "010000";    -- shift left
37
constant SHR_A: STD_LOGIC_VECTOR(5 downto 0) := "010010";    -- shift right
38
constant ROL_A: STD_LOGIC_VECTOR(5 downto 0) := "010100";    -- rotation left
39
constant ROR_A: STD_LOGIC_VECTOR(5 downto 0) := "010110";    -- rotation right
40
constant SWC_A: STD_LOGIC_VECTOR(5 downto 0) := "011000";    -- sum without carry (used for indexing and branches)
41
constant SWC_N: STD_LOGIC_VECTOR(5 downto 0) := "011001";    -- subtract without borrow (used only by branches with negative offset)
42
constant BIT_A: STD_LOGIC_VECTOR(5 downto 0) := "011010";    -- bit test (used by BIT opcode)
43
constant DAA_A: STD_LOGIC_VECTOR(5 downto 0) := "011100";    -- decimal adjustement for BCD sum
44
constant DAS_A: STD_LOGIC_VECTOR(5 downto 0) := "011110";    -- decimal adjustement for BCD subtract
45
constant CMP_A: STD_LOGIC_VECTOR(5 downto 0) := "100000";    -- compare
46
constant TSB_A: STD_LOGIC_VECTOR(5 downto 0) := "100010";    -- test and set bit
47
constant TRB_A: STD_LOGIC_VECTOR(5 downto 0) := "100100";    -- test and reset bit
48
signal      op: STD_LOGIC_VECTOR(5 downto 0);
49
signal       c: STD_LOGIC;
50
signal    pc_c: STD_LOGIC;
51
signal   v_add: STD_LOGIC;
52
signal   v_sub: STD_LOGIC;
53
signal   bcd_l: STD_LOGIC;
54
signal   bcd_h: STD_LOGIC;
55
signal  bcd_lh: STD_LOGIC;
56
signal   n_op2: STD_LOGIC_VECTOR(7 downto 0);
57
signal       y: STD_LOGIC_VECTOR(8 downto 0);
58
 
59
begin
60
  process(fc)
61
  begin
62
    case fc is
63
      when SWC_A  => op             <= SWC_A;
64
      when SWC_N  => op             <= SWC_N;
65
      when others => op(5 downto 1) <= fc(5 downto 1);
66
                     op(0)          <= '0';
67
    end case;
68
  end process;
69
 
70
  n_op2 <= (not op2);
71
  process(alu_byp,op,op1,op2,n_op2,cin)
72
  begin
73
    if alu_byp = '1' then
74
      y(y'left) <= '0';
75
      y(y'left-1 downto y'right) <= op1;
76
    else
77
      case op is
78
        when SUM_A  => y <= ('0' & op1) + ('0' & op2) + ("00000000" & cin);     -- ADC with carry in
79
        when SUB_A  => y <= ('0' & op1) + ('0' & n_op2) + ("00000000" & cin);   -- SBC with borrow in
80
        when BIT_A  => y <= ('0' & op1) and ('0' & op2);                        -- BIT test
81
        when AND_A  => y <= ('0' & op1) and ('0' & op2);                        -- AND
82
        when OR_A   => y <= ('0' & op1)  or ('0' & op2);                        -- OR
83
        when XOR_A  => y <= ('0' & op1) xor ('0' & op2);                        -- XOR
84
        when INC_A  => y <= op1 + "000000001";                                  -- INC
85
        when DEC_A  => y <= op1 - "000000001";                                  -- DEC
86
        when SHL_A  => y(8 downto 1) <= op1; y(0) <= '0';                       -- ASL
87
        when SHR_A  => y <= "00" & op1(op1'left downto op1'right+1);            -- LSR
88
        when ROL_A  => y(8 downto 1) <= op1; y(0) <= cin;                       -- ROL
89
        when ROR_A  => y <= '0' & cin & op1(op1'left downto op1'right+1);       -- ROR
90
        when SWC_A  => y <= ('0' & op1) + ('0' & op2);                          -- ADD without carry in
91
        when SWC_N  => y <= ('0' & op1) - ('0' & (0 - op2));                    -- SUB two complement without borrow in
92
        when DAA_A  => y <= ('0' & op1) + ('0' & op2);                          -- ADD without carry in (used for DAA decimal adjustement)
93
        when DAS_A  => y <= ('0' & op1) - ('0' & op2);                          -- SUB without borrow in (used for DAS decimal adjustement)
94
        when CMP_A  => y <= ('1' & op1) - ('0' & op2);                          -- SBC without borrow in (used for compare)
95
        when TSB_A  => y <= ('0' & op1) or ('0' & op2);                         -- TSB
96
        when TRB_A  => y <= ('0' & not op1) and ('0' & op2);                    -- TRB
97
        when others => y(y'left) <= '0'; y(y'left-1 downto y'right) <= op1;     -- NOP
98
      end case;
99
    end if;
100
  end process;
101
 
102
 
103
  -- flag "C" carry/borrow logic
104
  process(op,op1,y,cin)
105
  begin
106
    case op is
107
      when SUM_A  => c    <= y(y'left);
108
                     pc_c <= '0';
109
      when SUB_A  => c    <= y(y'left);
110
                     pc_c <= '0';
111
      when SWC_A  => pc_c <= y(y'left);
112
                     c    <= cin;
113
      when SWC_N  => pc_c <= not y(y'left);
114
                     c    <= cin;
115
      when SHL_A  => c    <= y(y'left);
116
                     pc_c <= '0';
117
      when SHR_A  => c    <= op1(op1'right);
118
                     pc_c <= '0';
119
      when ROL_A  => c    <= y(y'left);
120
                     pc_c <= '0';
121
      when ROR_A  => c    <= op1(op1'right);
122
                     pc_c <= '0';
123
      when DAA_A  => c    <= y(y'left);
124
                     pc_c <= '0';
125
      when DAS_A  => c    <= cin;
126
                     pc_c <= '0';
127
      when BIT_A  => c    <= cin;
128
                     pc_c <= '0';
129
      when CMP_A  => c    <= y(y'left);
130
                     pc_c <= '0';
131
      when others => c    <= cin;
132
                     pc_c <= '0';
133
    end case;
134
  end process;
135
 
136
  -- flag "V" overflow logic
137
  v_add <= (y(7) xor op1(7)) and not (op1(7) xor op2(7));
138
  v_sub <= (y(7) xor op1(7)) and (op1(7) xor op2(7));
139
  process(op,op2,v_add,v_sub,vin)
140
  begin
141
    case op is
142
      when SUM_A  => vf <= v_add;
143
      when SUB_A  => vf <= v_sub;
144
      when BIT_A  => vf <= op2(op2'left-1);
145
      when others => vf <= vin;
146
    end case;
147
  end process;
148
 
149
  -- flag "N" negative result logic
150
  process(op,op2,y)
151
  begin
152
    case op is
153
      when BIT_A  => nf <= op2(op2'left);
154
      when others => nf <= y(y'left-1);
155
    end case;
156
  end process;
157
 
158
  -- flag "Z" zero result logic (always set with zero results)
159
  zf <= '1' when y(y'left-1 downto y'right) = "00000000" else '0';
160
 
161
  -- bcd adjustement detection
162
  process(y)
163
  begin
164
    case y(3 downto 0) is
165
      when "1010" => bcd_l <= '1';  -- 0xA
166
      when "1011" => bcd_l <= '1';  -- 0xB
167
      when "1100" => bcd_l <= '1';  -- 0xC
168
      when "1101" => bcd_l <= '1';  -- 0xD 
169
      when "1110" => bcd_l <= '1';  -- 0xE
170
      when "1111" => bcd_l <= '1';  -- 0xF
171
      when others => bcd_l <= '0';
172
    end case;
173
    case y(7 downto 4) is
174
      when "1010" => bcd_h <= '1';  -- 0xA
175
      when "1011" => bcd_h <= '1';  -- 0xB
176
      when "1100" => bcd_h <= '1';  -- 0xC
177
      when "1101" => bcd_h <= '1';  -- 0xD 
178
      when "1110" => bcd_h <= '1';  -- 0xE
179
      when "1111" => bcd_h <= '1';  -- 0xF
180
      when others => bcd_h <= '0';
181
    end case;
182
  end process;
183
  process(y)
184
  begin
185
    case y(7 downto 0) is
186
      when "10011010" => bcd_lh <= '1';  -- 0x9A
187
      when "10011011" => bcd_lh <= '1';  -- 0x9B
188
      when "10011100" => bcd_lh <= '1';  -- 0x9C
189
      when "10011101" => bcd_lh <= '1';  -- 0x9D 
190
      when "10011110" => bcd_lh <= '1';  -- 0x9E
191
      when "10011111" => bcd_lh <= '1';  -- 0x9F
192
      when others     => bcd_lh <= '0';
193
    end case;
194
  end process;
195
 
196
  bcd_ol <= bcd_l or bcd_lh;
197
  bcd_oh <= bcd_h or bcd_lh;
198
  cf <= c;
199
  pc_cf <= pc_c;
200
  dout <= y(y'left-1 downto y'right);
201
end comb;
202
 
203
 

powered by: WebSVN 2.1.0

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