📄 cpu01.vhd
字号:
--
case alu_ctrl is
when alu_sei =>
cc_out(IBIT) <= '1'; -- set interrupt mask
when alu_cli =>
cc_out(IBIT) <= '0'; -- clear interrupt mask
when alu_tap =>
cc_out(IBIT) <= left(IBIT);
when others =>
cc_out(IBIT) <= cc(IBIT); -- interrupt mask
end case;
--
-- Half Carry flag
--
case alu_ctrl is
when alu_add8 | alu_adc =>
cc_out(HBIT) <= (left(3) and right(3)) or
(right(3) and not out_alu(3)) or
(left(3) and not out_alu(3));
when alu_tap =>
cc_out(HBIT) <= left(HBIT);
when others =>
cc_out(HBIT) <= cc(HBIT);
end case;
--
-- Overflow flag
--
case alu_ctrl is
when alu_add8 | alu_adc =>
cc_out(VBIT) <= (left(7) and right(7) and (not out_alu(7))) or
((not left(7)) and (not right(7)) and out_alu(7));
when alu_sub8 | alu_sbc =>
cc_out(VBIT) <= (left(7) and (not right(7)) and (not out_alu(7))) or
((not left(7)) and right(7) and out_alu(7));
when alu_add16 =>
cc_out(VBIT) <= (left(15) and right(15) and (not out_alu(15))) or
((not left(15)) and (not right(15)) and out_alu(15));
when alu_sub16 =>
cc_out(VBIT) <= (left(15) and (not right(15)) and (not out_alu(15))) or
((not left(15)) and right(15) and out_alu(15));
when alu_inc =>
cc_out(VBIT) <= ((not left(7)) and left(6) and left(5) and left(4) and
left(3) and left(2) and left(1) and left(0));
when alu_dec | alu_neg =>
cc_out(VBIT) <= (left(7) and (not left(6)) and (not left(5)) and (not left(4)) and
(not left(3)) and (not left(2)) and (not left(1)) and (not left(0)));
when alu_asr8 =>
cc_out(VBIT) <= left(0) xor left(7);
when alu_lsr8 | alu_lsr16 =>
cc_out(VBIT) <= left(0);
when alu_ror8 =>
cc_out(VBIT) <= left(0) xor cc(CBIT);
when alu_lsl16 =>
cc_out(VBIT) <= left(15) xor left(14);
when alu_rol8 | alu_asl8 =>
cc_out(VBIT) <= left(7) xor left(6);
when alu_tap =>
cc_out(VBIT) <= left(VBIT);
when alu_and | alu_ora | alu_eor | alu_com |
alu_st8 | alu_st16 | alu_ld8 | alu_ld16 |
alu_clv =>
cc_out(VBIT) <= '0';
when alu_sev =>
cc_out(VBIT) <= '1';
when others =>
cc_out(VBIT) <= cc(VBIT);
end case;
case alu_ctrl is
when alu_tap =>
cc_out(XBIT) <= cc(XBIT) and left(XBIT);
cc_out(SBIT) <= left(SBIT);
when others =>
cc_out(XBIT) <= cc(XBIT) and left(XBIT);
cc_out(SBIT) <= cc(SBIT);
end case;
test_alu <= out_alu;
test_cc <= cc_out;
end process;
------------------------------------
--
-- Detect Edge of NMI interrupt
--
------------------------------------
nmi_handler : process( clk, rst, nmi, nmi_ack )
begin
if clk'event and clk = '0' then
if hold = '1' then
nmi_req <= nmi_req;
else
if rst='1' then
nmi_req <= '0';
else
if (nmi='1') and (nmi_ack='0') then
nmi_req <= '1';
else
if (nmi='0') and (nmi_ack='1') then
nmi_req <= '0';
else
nmi_req <= nmi_req;
end if;
end if;
end if;
end if;
end if;
end process;
------------------------------------
--
-- Nmi mux
--
------------------------------------
nmi_mux: process( clk, nmi_ctrl, nmi_ack, hold )
begin
if clk'event and clk = '0' then
if hold = '1' then
nmi_ack <= nmi_ack;
else
case nmi_ctrl is
when set_nmi =>
nmi_ack <= '1';
when reset_nmi =>
nmi_ack <= '0';
when others =>
-- when latch_nmi =>
nmi_ack <= nmi_ack;
end case;
end if;
end if;
end process;
------------------------------------
--
-- state sequencer
--
------------------------------------
process( state, op_code, cc, ea,
irq, irq_icf, irq_ocf, irq_tof, irq_sci,
nmi_req, nmi_ack, hold, halt )
begin
case state is
when reset_state => -- released from reset
-- reset the registers
op_ctrl <= reset_op;
acca_ctrl <= reset_acca;
accb_ctrl <= reset_accb;
ix_ctrl <= reset_ix;
sp_ctrl <= reset_sp;
pc_ctrl <= reset_pc;
ea_ctrl <= reset_ea;
md_ctrl <= reset_md;
iv_ctrl <= reset_iv;
nmi_ctrl <= reset_nmi;
-- idle the ALU
left_ctrl <= acca_left;
right_ctrl <= zero_right;
alu_ctrl <= alu_nop;
cc_ctrl <= reset_cc;
-- idle the bus
dout_ctrl <= md_lo_dout;
addr_ctrl <= idle_ad;
next_state <= vect_hi_state;
--
-- Jump via interrupt vector
-- iv holds interrupt type
-- fetch PC hi from vector location
--
when vect_hi_state =>
-- default the registers
op_ctrl <= latch_op;
nmi_ctrl <= latch_nmi;
acca_ctrl <= latch_acca;
accb_ctrl <= latch_accb;
ix_ctrl <= latch_ix;
sp_ctrl <= latch_sp;
md_ctrl <= latch_md;
ea_ctrl <= latch_ea;
iv_ctrl <= latch_iv;
-- idle the ALU
left_ctrl <= acca_left;
right_ctrl <= zero_right;
alu_ctrl <= alu_nop;
cc_ctrl <= latch_cc;
-- fetch pc low interrupt vector
pc_ctrl <= pull_hi_pc;
addr_ctrl <= int_hi_ad;
dout_ctrl <= pc_hi_dout;
next_state <= vect_lo_state;
--
-- jump via interrupt vector
-- iv holds vector type
-- fetch PC lo from vector location
--
when vect_lo_state =>
-- default the registers
op_ctrl <= latch_op;
nmi_ctrl <= latch_nmi;
acca_ctrl <= latch_acca;
accb_ctrl <= latch_accb;
ix_ctrl <= latch_ix;
sp_ctrl <= latch_sp;
md_ctrl <= latch_md;
ea_ctrl <= latch_ea;
iv_ctrl <= latch_iv;
-- idle the ALU
left_ctrl <= acca_left;
right_ctrl <= zero_right;
alu_ctrl <= alu_nop;
cc_ctrl <= latch_cc;
-- fetch the vector low byte
pc_ctrl <= pull_lo_pc;
addr_ctrl <= int_lo_ad;
dout_ctrl <= pc_lo_dout;
next_state <= fetch_state;
--
-- Here to fetch an instruction
-- PC points to opcode
-- Should service interrupt requests at this point
-- either from the timer
-- or from the external input.
--
when fetch_state =>
case op_code(7 downto 4) is
when "0000" |
"0001" |
"0010" | -- branch conditional
"0011" |
"0100" | -- acca single op
"0101" | -- accb single op
"0110" | -- indexed single op
"0111" => -- extended single op
-- idle ALU
left_ctrl <= acca_left;
right_ctrl <= zero_right;
alu_ctrl <= alu_nop;
cc_ctrl <= latch_cc;
acca_ctrl <= latch_acca;
accb_ctrl <= latch_accb;
ix_ctrl <= latch_ix;
sp_ctrl <= latch_sp;
when "1000" | -- acca immediate
"1001" | -- acca direct
"1010" | -- acca indexed
"1011" => -- acca extended
case op_code(3 downto 0) is
when "0000" => -- suba
left_ctrl <= acca_left;
right_ctrl <= md_right;
alu_ctrl <= alu_sub8;
cc_ctrl <= load_cc;
acca_ctrl <= load_acca;
accb_ctrl <= latch_accb;
ix_ctrl <= latch_ix;
sp_ctrl <= latch_sp;
when "0001" => -- cmpa
left_ctrl <= acca_left;
right_ctrl <= md_right;
alu_ctrl <= alu_sub8;
cc_ctrl <= load_cc;
acca_ctrl <= latch_acca;
accb_ctrl <= latch_accb;
ix_ctrl <= latch_ix;
sp_ctrl <= latch_sp;
when "0010" => -- sbca
left_ctrl <= acca_left;
right_ctrl <= md_right;
alu_ctrl <= alu_sbc;
cc_ctrl <= load_cc;
acca_ctrl <= load_acca;
accb_ctrl <= latch_accb;
ix_ctrl <= latch_ix;
sp_ctrl <= latch_sp;
when "0011" => -- subd
left_ctrl <= accd_left;
right_ctrl <= md_right;
alu_ctrl <= alu_sub16;
cc_ctrl <= load_cc;
acca_ctrl <= load_hi_acca;
accb_ctrl <= load_accb;
ix_ctrl <= latch_ix;
sp_ctrl <= latch_sp;
when "0100" => -- anda
left_ctrl <= acca_left;
right_ctrl <= md_right;
alu_ctrl <= alu_and;
cc_ctrl <= load_cc;
acca_ctrl <= load_acca;
accb_ctrl <= latch_accb;
ix_ctrl <= latch_ix;
sp_ctrl <= latch_sp;
when "0101" => -- bita
left_ctrl <= acca_left;
right_ctrl <= md_right;
alu_ctrl <= alu_and;
cc_ctrl <= load_cc;
acca_ctrl <= latch_acca;
accb_ctrl <= latch_accb;
ix_ctrl <= latch_ix;
sp_ctrl <= latch_sp;
when "0110" => -- ldaa
left_ctrl <= acca_left;
right_ctrl <= md_right;
alu_ctrl <= alu_ld8;
cc_ctrl <= load_cc;
acca_ctrl <= load_acca;
accb_ctrl <= latch_accb;
ix_ctrl <= latch_ix;
sp_ctrl <= latch_sp;
when "0111" => -- staa
left_ctrl <= acca_left;
right_ctrl <= md_right;
alu_ctrl <= alu_st8;
cc_ctrl <= load_cc;
acca_ctrl <= latch_acca;
accb_ctrl <= latch_accb;
ix_ctrl <= latch_ix;
sp_ctrl <= latch_sp;
when "1000" => -- eora
left_ctrl <= acca_left;
right_ctrl <= md_right;
alu_ctrl <= alu_eor;
cc_ctrl <= load_cc;
acca_ctrl <= load_acca;
accb_ctrl <= latch_accb;
ix_ctrl <= latch_ix;
sp_ctrl <= latch_sp;
when "1001" => -- adca
left_ctrl <= acca_left;
right_ctrl <= md_right;
alu_ctrl <= alu_adc;
cc_ctrl <= load_cc;
acca_ctrl <= load_acca;
accb_ctrl <= latch_accb;
ix_ctrl <= latch_ix;
sp_ctrl <= latch_sp;
when "1010" => -- oraa
left_ctrl <= acca_left;
right_ctrl <= md_right;
alu_ctrl <= alu_ora;
cc_ctrl <= load_cc;
acca_ctrl <= load_acca;
accb_ctrl <= latch_accb;
ix_ctrl <= latch_ix;
sp_ctrl <= latch_sp;
when "1011" => -- adda
left_ctrl <= acca_left;
right_ctrl <= md_right;
alu_ctrl <= alu_add8;
cc_ctrl <= load_cc;
acca_ctrl <= load_acca;
accb_ctrl <= latch_accb;
ix_ctrl <= latch_ix;
sp_ctrl <= latch_sp;
when "1100" => -- cpx
left_ctrl <= ix_left;
right_ctrl <= md_right;
alu_ctrl <= alu_sub16;
cc_ctrl <= load_cc;
acca_ctrl <= latch_acca;
accb_ctrl <= latch_accb;
ix_ctrl <= latch_ix;
sp_ctrl <= latch_sp;
when "1101" => -- bsr / jsr
left_ctrl <= acca_left;
right_ctrl <= md_right;
alu_ctrl <= alu_nop;
cc_ctrl <= latch_cc;
acca_ctrl <= latch_acca;
accb_ctrl <= latch_accb;
ix_ctrl <= latch_ix;
sp_ctrl <= latch_sp;
when "1110" => -- lds
left_ctrl <= sp_left;
right_ctrl <= md_right;
alu_ctrl <= alu_ld16;
cc_ctrl <= load_cc;
acca_ctrl <= latch_acca;
accb_ctrl <= latch_accb;
ix_ctrl <= latch_ix;
sp_ctrl <= load_sp;
when "1111" => -- sts
left_ctrl <= sp_left;
right_ctrl <= md_right;
alu_ctrl <= alu_st16;
cc_ctrl <= load_cc;
acca_ctrl <= latch_acca;
accb_ctrl <= latch_accb;
ix_ctrl <= latch_ix;
sp_ctrl <= latch_sp;
when others =>
left_ctrl <= acca_left;
right_ctrl <= md_right;
alu_ctrl <= alu_nop;
cc_ctrl <= latch_cc;
acca_ctrl <= latch_acca;
accb_ctrl <= latch_accb;
ix_ctrl <= latch_ix;
sp_ctrl <= latch_sp;
end case;
when "1100" | -- accb immediate
"1101" | -- accb direct
"1110" | -- accb indexed
"1111" => -- accb extended
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -