1 ----------------------------
2 ---- 6502 ALU implementation
3 ----------------------------
5 use ieee.std_logic_1164.all;
6 use ieee.std_logic_unsigned.all;
7 use ieee.std_logic_arith.conv_std_logic_vector;
10 generic ( dsize : integer := 8
12 port ( clk : in std_logic;
13 pcl_inc_n : in std_logic;
14 pch_inc_n : in std_logic;
15 sph_oe_n : in std_logic;
16 sp_push_n : in std_logic;
17 sp_pop_n : in std_logic;
18 abs_xy_n : in std_logic;
19 pg_next_n : in std_logic;
21 zp_xy_n : in std_logic;
22 rel_calc_n : in std_logic;
23 arith_en_n : in std_logic;
24 instruction : in std_logic_vector (dsize - 1 downto 0);
25 int_d_bus : inout std_logic_vector (dsize - 1 downto 0);
26 acc_out : in std_logic_vector (dsize - 1 downto 0);
27 index_bus : in std_logic_vector (dsize - 1 downto 0);
28 bal : in std_logic_vector (dsize - 1 downto 0);
29 bah : in std_logic_vector (dsize - 1 downto 0);
30 addr_back : out std_logic_vector (dsize - 1 downto 0);
31 acc_in : out std_logic_vector (dsize - 1 downto 0);
32 abl : out std_logic_vector (dsize - 1 downto 0);
33 abh : out std_logic_vector (dsize - 1 downto 0);
34 pcl_inc_carry : out std_logic;
35 ea_carry : out std_logic;
36 carry_in : in std_logic;
37 negative : out std_logic;
39 carry_out : out std_logic;
40 overflow : out std_logic
44 architecture rtl of alu is
55 d : in std_logic_vector (dsize - 1 downto 0);
56 q : out std_logic_vector (dsize - 1 downto 0)
60 component address_calculator
61 generic ( dsize : integer := 8
64 sel : in std_logic_vector (1 downto 0);
65 addr1 : in std_logic_vector (dsize - 1 downto 0);
66 addr2 : in std_logic_vector (dsize - 1 downto 0);
67 addr_out : out std_logic_vector (dsize - 1 downto 0);
68 carry_in : in std_logic;
69 carry_out : out std_logic
74 generic ( dsize : integer := 8
77 sel : in std_logic_vector (3 downto 0);
78 d1 : in std_logic_vector (dsize - 1 downto 0);
79 d2 : in std_logic_vector (dsize - 1 downto 0);
80 d_out : out std_logic_vector (dsize - 1 downto 0);
81 carry_in : in std_logic;
82 negative : out std_logic;
84 carry_out : out std_logic;
85 overflow : out std_logic
90 --------- signals for address calucuration ----------
91 signal al_buf_we : std_logic;
92 signal ah_buf_we : std_logic;
94 signal al_reg_in : std_logic_vector (dsize - 1 downto 0);
95 signal ah_reg_in : std_logic_vector (dsize - 1 downto 0);
96 signal al_reg : std_logic_vector (dsize - 1 downto 0);
97 signal ah_reg : std_logic_vector (dsize - 1 downto 0);
100 signal a_sel : std_logic_vector (1 downto 0);
101 signal addr1 : std_logic_vector (dsize - 1 downto 0);
102 signal addr2 : std_logic_vector (dsize - 1 downto 0);
103 signal addr_out : std_logic_vector (dsize - 1 downto 0);
105 signal addr_c_in : std_logic;
106 signal addr_c : std_logic;
108 ----------- signals for arithmatic ----------
109 signal sel : std_logic_vector (3 downto 0);
110 signal d1 : std_logic_vector (dsize - 1 downto 0);
111 signal d2 : std_logic_vector (dsize - 1 downto 0);
112 signal d_out : std_logic_vector (dsize - 1 downto 0);
114 signal n : std_logic;
115 signal z : std_logic;
116 signal c_in : std_logic;
117 signal c : std_logic;
118 signal v : std_logic;
120 signal arith_reg_in : std_logic_vector (dsize - 1 downto 0);
121 signal arith_reg : std_logic_vector (dsize - 1 downto 0);
122 signal arith_buf_we : std_logic;
126 ----------------------------------------
127 -- address calucurator instances ----
128 ----------------------------------------
129 al_buf : d_flip_flop generic map (dsize)
130 port map(clk, '1', '1', al_buf_we, al_reg_in, al_reg);
131 ah_buf : d_flip_flop generic map (dsize)
132 port map(clk, '1', '1', ah_buf_we, ah_reg_in, ah_reg);
134 addr_calc_inst : address_calculator generic map (dsize)
135 port map (a_sel, addr1, addr2, addr_out, addr_c_in, addr_c);
138 ----------------------------------------
139 -- arithmatic operation instances ----
140 ----------------------------------------
141 arith_buf : d_flip_flop generic map (dsize)
142 port map(clk, '1', '1', arith_buf_we, arith_reg_in, arith_reg);
144 alu_inst : alu_core generic map (dsize)
145 port map (sel, d1, d2, d_out, c_in, n, z, c, v);
148 -------------------------------
149 ---- address calucuration -----
150 -------------------------------
151 alu_p : process (clk,
152 ---for address calucuration
153 pcl_inc_n, pch_inc_n, sph_oe_n, sp_push_n, sp_pop_n,
154 abs_xy_n, pg_next_n, zp_n, zp_xy_n, rel_calc_n,
155 int_d_bus, index_bus, bal, bal, addr_c_in, addr_out, addr_c,
157 --for arithmatic operation.
159 instruction, int_d_bus, acc_out, index_bus,
160 carry_in, d_out, n, z, c, v)
163 constant ADDR_ADC : std_logic_vector (1 downto 0) := "00";
164 constant ADDR_INC : std_logic_vector (1 downto 0) := "01";
165 constant ADDR_DEC : std_logic_vector (1 downto 0) := "10";
166 constant ADDR_SIGNED_ADD : std_logic_vector (1 downto 0) := "11";
168 constant ALU_AND : std_logic_vector (3 downto 0) := "0000";
169 constant ALU_EOR : std_logic_vector (3 downto 0) := "0001";
170 constant ALU_OR : std_logic_vector (3 downto 0) := "0010";
171 constant ALU_BIT : std_logic_vector (3 downto 0) := "0011";
172 constant ALU_ADC : std_logic_vector (3 downto 0) := "0100";
173 constant ALU_SBC : std_logic_vector (3 downto 0) := "0101";
174 constant ALU_CMP : std_logic_vector (3 downto 0) := "0110";
175 constant ALU_SL : std_logic_vector (3 downto 0) := "0111";
176 constant ALU_SR : std_logic_vector (3 downto 0) := "1000";
177 constant ALU_RL : std_logic_vector (3 downto 0) := "1001";
178 constant ALU_RR : std_logic_vector (3 downto 0) := "1010";
179 constant ALU_INC : std_logic_vector (3 downto 0) := "1011";
180 constant ALU_DEC : std_logic_vector (3 downto 0) := "1100";
182 procedure output_d_bus is
184 arith_reg_in <= d_out;
188 int_d_bus <= arith_reg_in;
192 procedure d_print(msg : string) is
194 use ieee.std_logic_textio.all;
195 variable out_l : line;
198 writeline(output, out_l);
203 if (pcl_inc_n = '0') then
206 addr_back <= addr_out;
207 pcl_inc_carry <= addr_c;
209 --keep the value in the cycle
212 if (instruction = "01001100") then
213 ---exceptional case: only jmp instruction
224 int_d_bus <= (others => 'Z');
225 elsif (pch_inc_n = '0') then
228 addr_back <= addr_out;
229 pcl_inc_carry <= '0';
231 --inc pch cycle is not fetch cycle.
232 --it is special cycle.
236 int_d_bus <= (others => 'Z');
237 elsif (sph_oe_n = '0') then
240 int_d_bus <= (others => 'Z');
242 if (sp_push_n /= '0' and sp_pop_n /= '0') then
244 elsif (sp_pop_n = '0') then
248 addr_back <= addr_out;
261 addr_back <= addr_out;
271 elsif (zp_n = '0') then
274 int_d_bus <= (others => 'Z');
276 elsif (abs_xy_n = '0') then
277 if (pg_next_n = '0') then
284 ---al is in the al_reg.
293 ---keep al for page crossed case
295 al_reg_in <= addr_out;
300 elsif (rel_calc_n = '0') then
301 if (pg_next_n = '1') then
302 if (int_d_bus(7) = '1') then
303 ---backward relative branch
306 ---forward relative branch
311 ---rel val is on the d_bus.
312 addr_back <= addr_out;
315 --keep the value in the cycle
317 ah_reg_in <= addr_out;
322 a_sel <= ADDR_SIGNED_ADD;
325 ---rel val is on the d_bus.
327 addr_back <= addr_out;
330 --keep the value in the cycle
332 al_reg_in <= addr_out;
340 int_d_bus <= (others => 'Z');
345 int_d_bus <= (others => 'Z');
354 ----addr_back is always bal for jsr instruction....
355 -----TODO must check later if it's ok.
357 pcl_inc_carry <= '0';
358 end if; --if (pcl_inc_n = '0') then
360 -------------------------------
361 ---- arithmatic operations-----
362 -------------------------------
363 if (arith_en_n = '0') then
367 if instruction = conv_std_logic_vector(16#ca#, dsize) then
377 elsif instruction = conv_std_logic_vector(16#88#, dsize) then
387 elsif instruction = conv_std_logic_vector(16#e8#, dsize) then
397 elsif instruction = conv_std_logic_vector(16#c8#, dsize) then
400 --instruction is aaabbbcc format.
401 elsif instruction (1 downto 0) = "01" then
402 if instruction (7 downto 5) = "000" then
404 elsif instruction (7 downto 5) = "001" then
406 elsif instruction (7 downto 5) = "010" then
408 elsif instruction (7 downto 5) = "011" then
410 elsif instruction (7 downto 5) = "110" then
420 elsif instruction (7 downto 5) = "111" then
423 elsif instruction (1 downto 0) = "10" then
424 if instruction (7 downto 5) = "000" then
426 elsif instruction (7 downto 5) = "001" then
428 elsif instruction (7 downto 5) = "010" then
430 elsif instruction (7 downto 5) = "011" then
432 elsif instruction (7 downto 5) = "110" then
434 elsif instruction (7 downto 5) = "111" then
437 elsif instruction (1 downto 0) = "00" then
438 if instruction (7 downto 5) = "001" then
440 elsif instruction (7 downto 5) = "110" then
442 elsif instruction (7 downto 5) = "111" then
451 end if; --if instruction (7 downto 5) = "001" then
452 end if; --if instruction = conv_std_logic_vector(16#ca#, dsize)
455 end if; -- if (arith_en_n = '0') then
460 -----------------------------------------
461 ---------- Address calculator------------
462 -----------------------------------------
465 use ieee.std_logic_1164.all;
466 use ieee.std_logic_unsigned.all;
468 entity address_calculator is
469 generic ( dsize : integer := 8
472 sel : in std_logic_vector (1 downto 0);
473 addr1 : in std_logic_vector (dsize - 1 downto 0);
474 addr2 : in std_logic_vector (dsize - 1 downto 0);
475 addr_out : out std_logic_vector (dsize - 1 downto 0);
476 carry_in : in std_logic;
477 carry_out : out std_logic
479 end address_calculator;
481 architecture rtl of address_calculator is
483 constant ADDR_ADC : std_logic_vector (1 downto 0) := "00";
484 constant ADDR_INC : std_logic_vector (1 downto 0) := "01";
485 constant ADDR_DEC : std_logic_vector (1 downto 0) := "10";
486 constant ADDR_SIGNED_ADD : std_logic_vector (1 downto 0) := "11";
490 alu_p : process (sel, addr1, addr2, carry_in)
491 variable res : std_logic_vector (dsize downto 0);
494 if sel = ADDR_ADC then
495 res := ('0' & addr1) + ('0' & addr2) + carry_in;
496 addr_out <= res(dsize - 1 downto 0);
497 carry_out <= res(dsize);
499 elsif sel = ADDR_SIGNED_ADD then
500 res := ('0' & addr1) + ('0' & addr2);
501 addr_out <= res(dsize - 1 downto 0);
502 if ((addr1(dsize - 1) = addr1(dsize - 1))
503 and (addr1(dsize - 1) /= res(dsize - 1))) then
509 elsif sel = ADDR_INC then
510 res := ('0' & addr1) + "000000001";
511 addr_out <= res(dsize - 1 downto 0);
512 carry_out <= res(dsize);
513 elsif sel = ADDR_DEC then
514 res := ('0' & addr1) - "000000001";
515 addr_out <= res(dsize - 1 downto 0);
516 carry_out <= res(dsize);
523 -----------------------------------------
524 ------------- ALU Core -----------------
525 -----------------------------------------
528 use ieee.std_logic_1164.all;
529 use ieee.std_logic_unsigned.all;
534 generic ( dsize : integer := 8
537 sel : in std_logic_vector (3 downto 0);
538 d1 : in std_logic_vector (dsize - 1 downto 0);
539 d2 : in std_logic_vector (dsize - 1 downto 0);
540 d_out : out std_logic_vector (dsize - 1 downto 0);
541 carry_in : in std_logic;
542 negative : out std_logic;
543 zero : out std_logic;
544 carry_out : out std_logic;
545 overflow : out std_logic
549 architecture rtl of alu_core is
551 procedure d_print(msg : string) is
553 use ieee.std_logic_textio.all;
554 variable out_l : line;
557 writeline(output, out_l);
560 constant ALU_AND : std_logic_vector (3 downto 0) := "0000";
561 constant ALU_EOR : std_logic_vector (3 downto 0) := "0001";
562 constant ALU_OR : std_logic_vector (3 downto 0) := "0010";
563 constant ALU_BIT : std_logic_vector (3 downto 0) := "0011";
564 constant ALU_ADC : std_logic_vector (3 downto 0) := "0100";
565 constant ALU_SBC : std_logic_vector (3 downto 0) := "0101";
566 constant ALU_CMP : std_logic_vector (3 downto 0) := "0110";
567 constant ALU_SL : std_logic_vector (3 downto 0) := "0111";
568 constant ALU_SR : std_logic_vector (3 downto 0) := "1000";
569 constant ALU_RL : std_logic_vector (3 downto 0) := "1001";
570 constant ALU_RR : std_logic_vector (3 downto 0) := "1010";
571 constant ALU_INC : std_logic_vector (3 downto 0) := "1011";
572 constant ALU_DEC : std_logic_vector (3 downto 0) := "1100";
576 alu_p : process (sel, d1, d2, carry_in)
577 variable res : std_logic_vector (dsize downto 0);
579 procedure set_n (data : in std_logic_vector (dsize - 1 downto 0)) is
581 if (data(7) = '1') then
588 procedure set_z (data : in std_logic_vector (dsize - 1 downto 0)) is
590 if (data = "00000000") then
598 if sel = ALU_AND then
600 elsif sel = ALU_EOR then
602 elsif sel = ALU_OR then
604 elsif sel = ALU_BIT then
606 elsif sel = ALU_ADC then
607 res := ('0' & d1) + ('0' & d2) + carry_in;
608 d_out <= res(dsize - 1 downto 0);
609 carry_out <= res(dsize);
610 if ((d1(dsize - 1) = d1(dsize - 1))
611 and (d1(dsize - 1) /= res(dsize - 1))) then
617 elsif sel = ALU_SBC then
619 elsif sel = ALU_CMP then
620 res := ('0' & d1) - ('0' & d2);
626 elsif sel = ALU_SL then
628 elsif sel = ALU_SR then
630 elsif sel = ALU_RL then
632 elsif sel = ALU_RR then
634 elsif sel = ALU_INC then
635 res := ('0' & d1) + "000000001";
636 d_out <= res(dsize - 1 downto 0);
637 carry_out <= res(dsize);
638 elsif sel = ALU_DEC then
639 res := ('0' & d1) - "000000001";
640 d_out <= res(dsize - 1 downto 0);
641 carry_out <= res(dsize);
643 set_n(res(dsize - 1 downto 0));
644 set_z(res(dsize - 1 downto 0));