2 -- Z80 compatible microprocessor core
6 -- Copyright (c) 2001-2002 Daniel Wallner (jesus@opencores.org)
10 -- Redistribution and use in source and synthezised forms, with or without
11 -- modification, are permitted provided that the following conditions are met:
13 -- Redistributions of source code must retain the above copyright notice,
14 -- this list of conditions and the following disclaimer.
16 -- Redistributions in synthesized form must reproduce the above copyright
17 -- notice, this list of conditions and the following disclaimer in the
18 -- documentation and/or other materials provided with the distribution.
20 -- Neither the name of the author nor the names of other contributors may
21 -- be used to endorse or promote products derived from this software without
22 -- specific prior written permission.
24 -- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
25 -- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
26 -- THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
27 -- PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE
28 -- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
29 -- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
30 -- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
31 -- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
32 -- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 -- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 -- POSSIBILITY OF SUCH DAMAGE.
36 -- Please report bugs to the author, but before you do so, please
37 -- make sure that this is not a derivative work and that
38 -- you have the latest version of this file.
40 -- The latest version of this file can be found at:
41 -- http://www.opencores.org/cvsweb.shtml/t80/
47 -- 0214 : Fixed mostly flags, only the block instructions now fail the zex regression test
49 -- 0238 : Fixed zero flag for 16 bit SBC and ADC
51 -- 0240 : Added GB operations
59 use IEEE.std_logic_1164.all;
60 use IEEE.numeric_std.all;
65 Flag_C : integer := 0;
66 Flag_N : integer := 1;
67 Flag_P : integer := 2;
68 Flag_X : integer := 3;
69 Flag_H : integer := 4;
70 Flag_Y : integer := 5;
71 Flag_Z : integer := 6;
75 Arith16 : in std_logic;
77 ALU_Op : in std_logic_vector(3 downto 0);
78 IR : in std_logic_vector(5 downto 0);
79 ISet : in std_logic_vector(1 downto 0);
80 BusA : in std_logic_vector(7 downto 0);
81 BusB : in std_logic_vector(7 downto 0);
82 F_In : in std_logic_vector(7 downto 0);
83 Q : out std_logic_vector(7 downto 0);
84 F_Out : out std_logic_vector(7 downto 0)
88 architecture rtl of T80_ALU is
90 procedure AddSub(A : std_logic_vector;
94 signal Res : out std_logic_vector;
95 signal Carry : out std_logic) is
96 variable B_i : unsigned(A'length - 1 downto 0);
97 variable Res_i : unsigned(A'length + 1 downto 0);
100 B_i := not unsigned(B);
104 Res_i := unsigned("0" & A & Carry_In) + unsigned("0" & B_i & "1");
105 Carry <= Res_i(A'length + 1);
106 Res <= std_logic_vector(Res_i(A'length downto 1));
109 -- AddSub variables (temporary signals)
110 signal UseCarry : std_logic;
111 signal Carry7_v : std_logic;
112 signal Overflow_v : std_logic;
113 signal HalfCarry_v : std_logic;
114 signal Carry_v : std_logic;
115 signal Q_v : std_logic_vector(7 downto 0);
117 signal BitMask : std_logic_vector(7 downto 0);
121 with IR(5 downto 3) select BitMask <= "00000001" when "000",
122 "00000010" when "001",
123 "00000100" when "010",
124 "00001000" when "011",
125 "00010000" when "100",
126 "00100000" when "101",
127 "01000000" when "110",
128 "10000000" when others;
130 UseCarry <= not ALU_Op(2) and ALU_Op(0);
131 AddSub(BusA(3 downto 0), BusB(3 downto 0), ALU_Op(1), ALU_Op(1) xor (UseCarry and F_In(Flag_C)), Q_v(3 downto 0), HalfCarry_v);
132 AddSub(BusA(6 downto 4), BusB(6 downto 4), ALU_Op(1), HalfCarry_v, Q_v(6 downto 4), Carry7_v);
133 AddSub(BusA(7 downto 7), BusB(7 downto 7), ALU_Op(1), Carry7_v, Q_v(7 downto 7), Carry_v);
134 OverFlow_v <= Carry_v xor Carry7_v;
136 process (Arith16, ALU_OP, F_In, BusA, BusB, IR, Q_v, Carry_v, HalfCarry_v, OverFlow_v, BitMask, ISet, Z16)
137 variable Q_t : std_logic_vector(7 downto 0);
138 variable DAA_Q : unsigned(8 downto 0);
142 DAA_Q := "---------";
144 when "0000" | "0001" | "0010" | "0011" | "0100" | "0101" | "0110" | "0111" =>
145 F_Out(Flag_N) <= '0';
146 F_Out(Flag_C) <= '0';
147 case ALU_OP(2 downto 0) is
148 when "000" | "001" => -- ADD, ADC
150 F_Out(Flag_C) <= Carry_v;
151 F_Out(Flag_H) <= HalfCarry_v;
152 F_Out(Flag_P) <= OverFlow_v;
153 when "010" | "011" | "111" => -- SUB, SBC, CP
155 F_Out(Flag_N) <= '1';
156 F_Out(Flag_C) <= not Carry_v;
157 F_Out(Flag_H) <= not HalfCarry_v;
158 F_Out(Flag_P) <= OverFlow_v;
160 Q_t(7 downto 0) := BusA and BusB;
161 F_Out(Flag_H) <= '1';
163 Q_t(7 downto 0) := BusA xor BusB;
164 F_Out(Flag_H) <= '0';
165 when others => -- OR "110"
166 Q_t(7 downto 0) := BusA or BusB;
167 F_Out(Flag_H) <= '0';
169 if ALU_Op(2 downto 0) = "111" then -- CP
170 F_Out(Flag_X) <= BusB(3);
171 F_Out(Flag_Y) <= BusB(5);
173 F_Out(Flag_X) <= Q_t(3);
174 F_Out(Flag_Y) <= Q_t(5);
176 if Q_t(7 downto 0) = "00000000" then
177 F_Out(Flag_Z) <= '1';
179 F_Out(Flag_Z) <= F_In(Flag_Z); -- 16 bit ADC,SBC
182 F_Out(Flag_Z) <= '0';
184 F_Out(Flag_S) <= Q_t(7);
185 case ALU_Op(2 downto 0) is
186 when "000" | "001" | "010" | "011" | "111" => -- ADD, ADC, SUB, SBC, CP
188 F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor
189 Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7));
191 if Arith16 = '1' then
192 F_Out(Flag_S) <= F_In(Flag_S);
193 F_Out(Flag_Z) <= F_In(Flag_Z);
194 F_Out(Flag_P) <= F_In(Flag_P);
198 F_Out(Flag_H) <= F_In(Flag_H);
199 F_Out(Flag_C) <= F_In(Flag_C);
200 DAA_Q(7 downto 0) := unsigned(BusA);
202 if F_In(Flag_N) = '0' then
205 if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then
206 if (DAA_Q(3 downto 0) > 9) then
207 F_Out(Flag_H) <= '1';
209 F_Out(Flag_H) <= '0';
213 -- new Ahigh > 9 or C = 1
214 if DAA_Q(8 downto 4) > 9 or F_In(Flag_C) = '1' then
215 DAA_Q := DAA_Q + 96; -- 0x60
219 if DAA_Q(3 downto 0) > 9 or F_In(Flag_H) = '1' then
220 if DAA_Q(3 downto 0) > 5 then
221 F_Out(Flag_H) <= '0';
223 DAA_Q(7 downto 0) := DAA_Q(7 downto 0) - 6;
225 if unsigned(BusA) > 153 or F_In(Flag_C) = '1' then
226 DAA_Q := DAA_Q - 352; -- 0x160
229 F_Out(Flag_X) <= DAA_Q(3);
230 F_Out(Flag_Y) <= DAA_Q(5);
231 F_Out(Flag_C) <= F_In(Flag_C) or DAA_Q(8);
232 Q_t := std_logic_vector(DAA_Q(7 downto 0));
233 if DAA_Q(7 downto 0) = "00000000" then
234 F_Out(Flag_Z) <= '1';
236 F_Out(Flag_Z) <= '0';
238 F_Out(Flag_S) <= DAA_Q(7);
239 F_Out(Flag_P) <= not (DAA_Q(0) xor DAA_Q(1) xor DAA_Q(2) xor DAA_Q(3) xor
240 DAA_Q(4) xor DAA_Q(5) xor DAA_Q(6) xor DAA_Q(7));
241 when "1101" | "1110" =>
243 Q_t(7 downto 4) := BusA(7 downto 4);
244 if ALU_Op(0) = '1' then
245 Q_t(3 downto 0) := BusB(7 downto 4);
247 Q_t(3 downto 0) := BusB(3 downto 0);
249 F_Out(Flag_H) <= '0';
250 F_Out(Flag_N) <= '0';
251 F_Out(Flag_X) <= Q_t(3);
252 F_Out(Flag_Y) <= Q_t(5);
253 if Q_t(7 downto 0) = "00000000" then
254 F_Out(Flag_Z) <= '1';
256 F_Out(Flag_Z) <= '0';
258 F_Out(Flag_S) <= Q_t(7);
259 F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor
260 Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7));
263 Q_t(7 downto 0) := BusB and BitMask;
264 F_Out(Flag_S) <= Q_t(7);
265 if Q_t(7 downto 0) = "00000000" then
266 F_Out(Flag_Z) <= '1';
267 F_Out(Flag_P) <= '1';
269 F_Out(Flag_Z) <= '0';
270 F_Out(Flag_P) <= '0';
272 F_Out(Flag_H) <= '1';
273 F_Out(Flag_N) <= '0';
274 F_Out(Flag_X) <= '0';
275 F_Out(Flag_Y) <= '0';
276 if IR(2 downto 0) /= "110" then
277 F_Out(Flag_X) <= BusB(3);
278 F_Out(Flag_Y) <= BusB(5);
282 Q_t(7 downto 0) := BusB or BitMask;
285 Q_t(7 downto 0) := BusB and not BitMask;
288 case IR(5 downto 3) is
290 Q_t(7 downto 1) := BusA(6 downto 0);
292 F_Out(Flag_C) <= BusA(7);
294 Q_t(7 downto 1) := BusA(6 downto 0);
295 Q_t(0) := F_In(Flag_C);
296 F_Out(Flag_C) <= BusA(7);
298 Q_t(6 downto 0) := BusA(7 downto 1);
300 F_Out(Flag_C) <= BusA(0);
302 Q_t(6 downto 0) := BusA(7 downto 1);
303 Q_t(7) := F_In(Flag_C);
304 F_Out(Flag_C) <= BusA(0);
306 Q_t(7 downto 1) := BusA(6 downto 0);
308 F_Out(Flag_C) <= BusA(7);
309 when "110" => -- SLL (Undocumented) / SWAP
311 Q_t(7 downto 4) := BusA(3 downto 0);
312 Q_t(3 downto 0) := BusA(7 downto 4);
313 F_Out(Flag_C) <= '0';
315 Q_t(7 downto 1) := BusA(6 downto 0);
317 F_Out(Flag_C) <= BusA(7);
320 Q_t(6 downto 0) := BusA(7 downto 1);
322 F_Out(Flag_C) <= BusA(0);
323 when others => -- SRL
324 Q_t(6 downto 0) := BusA(7 downto 1);
326 F_Out(Flag_C) <= BusA(0);
328 F_Out(Flag_H) <= '0';
329 F_Out(Flag_N) <= '0';
330 F_Out(Flag_X) <= Q_t(3);
331 F_Out(Flag_Y) <= Q_t(5);
332 F_Out(Flag_S) <= Q_t(7);
333 if Q_t(7 downto 0) = "00000000" then
334 F_Out(Flag_Z) <= '1';
336 F_Out(Flag_Z) <= '0';
338 F_Out(Flag_P) <= not (Q_t(0) xor Q_t(1) xor Q_t(2) xor Q_t(3) xor
339 Q_t(4) xor Q_t(5) xor Q_t(6) xor Q_t(7));
341 F_Out(Flag_P) <= F_In(Flag_P);
342 F_Out(Flag_S) <= F_In(Flag_S);
343 F_Out(Flag_Z) <= F_In(Flag_Z);