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 |
|
|
|