OSDN Git Service

8ea09d895c7ab48ffa43cb473f91e5210dd3e002
[motonesfpga/motonesfpga.git] / simulation / cpu / alu.vhd
1 -----------------------------------------
2 ------------- ALU Core -----------------
3 -----------------------------------------
4
5 library ieee;
6 use ieee.std_logic_1164.all;
7 use ieee.std_logic_unsigned.all;
8
9 ----d1 = acc
10 ----d2 = memory
11 entity alu_core is 
12     generic (   dsize : integer := 8
13             );
14     port ( 
15             sel         : in std_logic_vector (3 downto 0);
16             d1          : in std_logic_vector (dsize - 1 downto 0);
17             d2          : in std_logic_vector (dsize - 1 downto 0);
18             d_out       : out std_logic_vector (dsize - 1 downto 0);
19             carry_in    : in std_logic;
20             negative    : out std_logic;
21             zero        : out std_logic;
22             carry_out   : out std_logic;
23             overflow    : out std_logic
24     );
25 end alu_core;
26
27 architecture rtl of alu_core is
28
29 procedure d_print(msg : string) is
30 use std.textio.all;
31 use ieee.std_logic_textio.all;
32 variable out_l : line;
33 begin
34     write(out_l, msg);
35     writeline(output, out_l);
36 end  procedure;
37
38 constant ALU_AND    : std_logic_vector (3 downto 0) := "0000";
39 constant ALU_EOR    : std_logic_vector (3 downto 0) := "0001";
40 constant ALU_OR     : std_logic_vector (3 downto 0) := "0010";
41 constant ALU_BIT    : std_logic_vector (3 downto 0) := "0011";
42 constant ALU_ADC    : std_logic_vector (3 downto 0) := "0100";
43 constant ALU_SBC    : std_logic_vector (3 downto 0) := "0101";
44 constant ALU_CMP    : std_logic_vector (3 downto 0) := "0110";
45 constant ALU_SL     : std_logic_vector (3 downto 0) := "0111";
46 constant ALU_SR     : std_logic_vector (3 downto 0) := "1000";
47 constant ALU_RL     : std_logic_vector (3 downto 0) := "1001";
48 constant ALU_RR     : std_logic_vector (3 downto 0) := "1010";
49 constant ALU_INC    : std_logic_vector (3 downto 0) := "1011";
50 constant ALU_DEC    : std_logic_vector (3 downto 0) := "1100";
51
52 begin
53
54     alu_p : process (sel, d1, d2, carry_in)
55     variable res : std_logic_vector (dsize downto 0);
56
57 procedure set_n (data : in std_logic_vector (dsize - 1 downto 0)) is
58 begin
59     if (data(7) = '1') then
60         negative <= '1';
61     else
62         negative <= '0';
63     end if;
64 end procedure;
65
66 procedure set_z (data : in std_logic_vector (dsize - 1 downto 0)) is
67 begin
68     if  (data(7) or data(6) or data(5) or data(4) or 
69         data(3) or data(2) or data(1) or data(0)) = '0' then
70         zero <= '1';
71     else
72         zero <= '0';
73     end if;
74 end procedure;
75
76     begin
77     if sel = ALU_AND then
78         res := d1 and d2;
79     elsif sel = ALU_EOR then
80         res := d1 xor d2;
81     elsif sel = ALU_OR then
82         res := d1 or d2;
83     elsif sel = ALU_BIT then
84         ----
85     elsif sel = ALU_ADC then
86         res := ('0' & d1) + ('0' & d2) + carry_in;
87         d_out <= res(dsize - 1 downto 0);
88         carry_out <= res(dsize);
89         if ((d1(dsize - 1) = d1(dsize - 1)) 
90                             and (d1(dsize - 1) /= res(dsize - 1))) then
91             overflow <= '1';
92         else
93             overflow <= '0';
94         end if;
95
96     elsif sel = ALU_SBC then
97         ----
98     elsif sel = ALU_CMP then
99         res := d1 - d2;
100     elsif sel = ALU_SL then
101         ----
102     elsif sel = ALU_SR then
103         ----
104     elsif sel = ALU_RL then
105         ----
106     elsif sel = ALU_RR then
107         ----
108     elsif sel = ALU_INC then
109         res := ('0' & d1) + "000000001";
110         d_out <= res(dsize - 1 downto 0);
111         carry_out <= res(dsize);
112     elsif sel = ALU_DEC then
113         res := ('0' & d1) - "000000001";
114         d_out <= res(dsize - 1 downto 0);
115         carry_out <= res(dsize);
116     end if;
117     set_n(res(dsize - 1 downto 0));
118     set_z(res(dsize - 1 downto 0));
119
120     end process;
121
122 end rtl;
123
124
125 ----------------------------
126 ---- 6502 ALU implementation
127 ----------------------------
128 library ieee;
129 use ieee.std_logic_1164.all;
130 use ieee.std_logic_unsigned.all;
131
132 entity alu is 
133     generic (   dsize : integer := 8
134             );
135     port (  clk             : in std_logic;
136             pcl_inc_n       : in std_logic;
137             pch_inc_n       : in std_logic;
138             sph_oe_n        : in std_logic;
139             sp_push_n       : in std_logic;
140             sp_pop_n        : in std_logic;
141             abs_xy_n        : in std_logic;
142             abs_pg_next_n   : in std_logic;
143             zp_n            : in std_logic;
144             zp_xy_n         : in std_logic;
145             arith_en_n      : in std_logic;
146             instruction     : in std_logic_vector (dsize - 1 downto 0);
147             int_d_bus       : inout std_logic_vector (dsize - 1 downto 0);
148             acc_out         : in std_logic_vector (dsize - 1 downto 0);
149             index_bus       : in std_logic_vector (dsize - 1 downto 0);
150             bal             : in std_logic_vector (dsize - 1 downto 0);
151             bah             : in std_logic_vector (dsize - 1 downto 0);
152             alu_res         : out std_logic_vector (dsize - 1 downto 0);
153             abl             : out std_logic_vector (dsize - 1 downto 0);
154             abh             : out std_logic_vector (dsize - 1 downto 0);
155             pcl_inc_carry   : out std_logic;
156             ea_carry        : out std_logic;
157             carry_in        : in std_logic;
158             negative        : out std_logic;
159             zero            : out std_logic;
160             carry_out       : out std_logic;
161             overflow        : out std_logic
162     );
163 end alu;
164
165 architecture rtl of alu is
166
167 component d_flip_flop
168     generic (
169             dsize : integer := 8
170             );
171     port (  
172             clk     : in std_logic;
173             res_n   : in std_logic;
174             set_n   : in std_logic;
175             we_n    : in std_logic;
176             d       : in std_logic_vector (dsize - 1 downto 0);
177             q       : out std_logic_vector (dsize - 1 downto 0)
178         );
179 end component;
180
181 component alu_core
182     generic (   dsize : integer := 8
183             );
184     port ( 
185             sel         : in std_logic_vector (3 downto 0);
186             d1          : in std_logic_vector (dsize - 1 downto 0);
187             d2          : in std_logic_vector (dsize - 1 downto 0);
188             d_out       : out std_logic_vector (dsize - 1 downto 0);
189             carry_in    : in std_logic;
190             negative    : out std_logic;
191             zero        : out std_logic;
192             carry_out   : out std_logic;
193             overflow    : out std_logic
194     );
195 end component;
196
197 constant ALU_AND    : std_logic_vector (3 downto 0) := "0000";
198 constant ALU_EOR    : std_logic_vector (3 downto 0) := "0001";
199 constant ALU_OR     : std_logic_vector (3 downto 0) := "0010";
200 constant ALU_BIT    : std_logic_vector (3 downto 0) := "0011";
201 constant ALU_ADC    : std_logic_vector (3 downto 0) := "0100";
202 constant ALU_SBC    : std_logic_vector (3 downto 0) := "0101";
203 constant ALU_CMP    : std_logic_vector (3 downto 0) := "0110";
204 constant ALU_SL     : std_logic_vector (3 downto 0) := "0111";
205 constant ALU_SR     : std_logic_vector (3 downto 0) := "1000";
206 constant ALU_RL     : std_logic_vector (3 downto 0) := "1001";
207 constant ALU_RR     : std_logic_vector (3 downto 0) := "1010";
208 constant ALU_INC    : std_logic_vector (3 downto 0) := "1011";
209 constant ALU_DEC    : std_logic_vector (3 downto 0) := "1100";
210
211 procedure d_print(msg : string) is
212 use std.textio.all;
213 use ieee.std_logic_textio.all;
214 variable out_l : line;
215 begin
216     write(out_l, msg);
217     writeline(output, out_l);
218 end  procedure;
219
220 signal sel : std_logic_vector (3 downto 0);
221 signal d1 : std_logic_vector (dsize - 1 downto 0);
222 signal d2 : std_logic_vector (dsize - 1 downto 0);
223 signal d_out : std_logic_vector (dsize - 1 downto 0);
224
225 signal al_reg_in : std_logic_vector (dsize - 1 downto 0);
226 signal ah_reg_in : std_logic_vector (dsize - 1 downto 0);
227 signal al_reg : std_logic_vector (dsize - 1 downto 0);
228 signal ah_reg : std_logic_vector (dsize - 1 downto 0);
229
230 signal n : std_logic;
231 signal z : std_logic;
232 signal c_in : std_logic;
233 signal c : std_logic;
234 signal v : std_logic;
235
236 signal al_buf_we : std_logic;
237 signal ah_buf_we : std_logic;
238
239 begin
240
241     al_buf : d_flip_flop generic map (dsize) 
242             port map(clk, '1', '1', al_buf_we, al_reg_in, al_reg);
243     ah_buf : d_flip_flop generic map (dsize) 
244             port map(clk, '1', '1', ah_buf_we, ah_reg_in, ah_reg);
245
246     alu_inst : alu_core generic map (dsize)
247             port map (sel, d1, d2, d_out, c_in, n, z, c, v);
248
249     alu_p : process (clk, pcl_inc_n, pch_inc_n, sph_oe_n, sp_push_n, sp_pop_n,
250                     abs_xy_n, abs_pg_next_n, zp_n, zp_xy_n, arith_en_n,
251                     instruction, 
252                     int_d_bus, acc_out, index_bus, bal, bal, carry_in, d_out, 
253                     n, z, c, v)
254     begin
255     if (pcl_inc_n = '0') then
256         sel <= ALU_INC;
257         d1 <= bal;
258         alu_res <= d_out;
259         pcl_inc_carry <= c;
260
261         --keep the value in the cycle
262         al_buf_we <= '0';
263         al_reg_in <= bal;
264         if (clk = '0') then
265             abl <= bal;
266         else
267             abl <= al_reg;
268         end if;
269         abh <= bah;
270
271     elsif (pch_inc_n = '0') then
272         sel <= ALU_INC;
273         d1 <= bah;
274         alu_res <= d_out;
275         pcl_inc_carry <= '0';
276
277         --inc pch cycle is not fetch cycle.
278         --it is special cycle.
279         abl <= bal;
280         abh <= bah;
281
282     elsif (sph_oe_n = '0') then
283         --stack operation...
284         abh <= "00000001";
285
286         if (sp_push_n /= '0' and sp_pop_n /= '0') then
287             abl <= bal;
288         elsif (sp_pop_n = '0') then
289             sel <= ALU_INC;
290             d1 <= bal;
291             alu_res <= d_out;
292
293             al_buf_we <= '0';
294             al_reg_in <= bal;
295             if (clk = '0') then
296                 abl <= bal;
297             else
298                 abl <= al_reg;
299             end if;
300         else
301             ---case push
302             sel <= ALU_DEC;
303             d1 <= bal;
304             alu_res <= d_out;
305
306             if (clk = '0') then
307                 abl <= bal;
308             else
309                 abl <= al_reg;
310             end if;
311         end if;
312     elsif (abs_xy_n = '0') then
313         if (abs_pg_next_n = '0') then
314             sel <= ALU_INC;
315             d1 <= bah;
316             ea_carry <= '0';
317
318             al_buf_we <= '1';
319             abh <= d_out;
320             ---al is in the al_reg.
321             abl <= al_reg;
322         else
323             sel <= ALU_ADC;
324             d1 <= bal;
325             d2 <= index_bus;
326             c_in <= '0';
327             ea_carry <= c;
328
329             ---keep al for page crossed case
330             al_buf_we <= '0';
331             al_reg_in <= d_out;
332             abh <= bah;
333             abl <= d_out;
334         end if;
335
336     elsif (arith_en_n = '0') then
337             --instruction is aaabbbcc format.
338             if instruction (1 downto 0) = "01" then
339                 if instruction (7 downto 5) = "000" then
340                     d_print("ora");
341                 elsif instruction (7 downto 5) = "001" then
342                     d_print("and");
343                 elsif instruction (7 downto 5) = "010" then
344                     d_print("eor");
345                 elsif instruction (7 downto 5) = "011" then
346                     d_print("adc");
347                 elsif instruction (7 downto 5) = "110" then
348                     d_print("cmp");
349                     --cmpare A - M.
350                     sel <= ALU_CMP;
351                     d1 <= acc_out;
352                     d2 <= int_d_bus;
353                     alu_res <= d_out;
354
355                 elsif instruction (7 downto 5) = "111" then
356                     d_print("sbc");
357                 end if;
358             elsif instruction (1 downto 0) = "10" then
359                 if instruction (7 downto 5) = "000" then
360                     d_print("asl");
361                 elsif instruction (7 downto 5) = "001" then
362                     d_print("rol");
363                 elsif instruction (7 downto 5) = "010" then
364                     d_print("lsr");
365                 elsif instruction (7 downto 5) = "011" then
366                     d_print("ror");
367                 elsif instruction (7 downto 5) = "110" then
368                     d_print("dec");
369                 elsif instruction (7 downto 5) = "111" then
370                     d_print("inc");
371                 end if;
372             elsif instruction (1 downto 0) = "00" then
373                 if instruction (7 downto 5) = "001" then
374                     d_print("bit");
375                 elsif instruction (7 downto 5) = "110" then
376                     d_print("cpy");
377                 elsif instruction (7 downto 5) = "111" then
378                     d_print("cpx");
379                 end if; --if instruction (7 downto 5) = "001" then
380             end if; --if instruction (1 downto 0) = "01"
381     else
382         int_d_bus <= (others => 'Z');
383         negative <= 'Z';
384         zero <= 'Z';
385         carry_out <= 'Z';
386         overflow <= 'Z';
387
388         abl <= bal;
389         abh <= bah;
390
391         ----alu_res is always bal for jsr instruction....
392         -----TODO must check later if it's ok.
393         alu_res <= bal;
394         pcl_inc_carry <= '0';
395     end if; --if (pcl_inc_n = '0') then
396     end process;
397
398 end rtl;
399
400
401 ----------------------------------------
402 ---- 6502 effective address calucurator
403 ----------------------------------------
404 library ieee;
405 use ieee.std_logic_1164.all;
406 use ieee.std_logic_unsigned.all;
407
408 entity effective_adder is 
409     generic (   dsize : integer := 8
410             );
411     port (  
412             ea_calc_n       : in std_logic;
413             zp_n            : in std_logic;
414             pg_next_n       : in std_logic;
415             base_l          : in std_logic_vector (dsize - 1 downto 0);
416             base_h          : in std_logic_vector (dsize - 1 downto 0);
417             index           : in std_logic_vector (dsize - 1 downto 0);
418             ah_bus          : out std_logic_vector (dsize - 1 downto 0);
419             al_bus          : out std_logic_vector (dsize - 1 downto 0);
420             carry           : out std_logic
421     );
422 end effective_adder;
423
424 architecture rtl of effective_adder is
425
426 signal adc_work : std_logic_vector (dsize downto 0);
427
428 begin
429     adc_work <= ('0' & base_l) + ('0' & index);
430     carry <= adc_work(dsize) when ea_calc_n = '0' else
431             'Z';
432     --if not calc effective adder, pass through input.
433     al_bus <= adc_work(dsize - 1 downto 0) when ea_calc_n = '0' else
434             base_l;
435
436     ah_bus <= "00000000" when zp_n = '0' else
437             base_h + '1' when ea_calc_n = '0' and pg_next_n = '0' else
438             base_h;
439
440 end rtl;
441
442