📄 cpu01.vhd
字号:
-- X Index register
--
--------------------------------
ix_mux : process( clk, ix_ctrl, out_alu, xreg, data_in, hold )
begin
if clk'event and clk = '0' then
if hold = '1' then
xreg <= xreg;
else
case ix_ctrl is
when reset_ix =>
xreg <= "0000000000000000";
when load_ix =>
xreg <= out_alu(15 downto 0);
when pull_hi_ix =>
xreg(15 downto 8) <= data_in;
when pull_lo_ix =>
xreg(7 downto 0) <= data_in;
when others =>
-- when latch_ix =>
xreg <= xreg;
end case;
end if;
end if;
end process;
--------------------------------
--
-- stack pointer
--
--------------------------------
sp_mux : process( clk, sp_ctrl, out_alu, hold )
begin
if clk'event and clk = '0' then
if hold = '1' then
sp <= sp;
else
case sp_ctrl is
when reset_sp =>
sp <= "0000000000000000";
when load_sp =>
sp <= out_alu(15 downto 0);
when others =>
-- when latch_sp =>
sp <= sp;
end case;
end if;
end if;
end process;
--------------------------------
--
-- Memory Data
--
--------------------------------
md_mux : process( clk, md_ctrl, out_alu, data_in, md, hold )
begin
if clk'event and clk = '0' then
if hold = '1' then
md <= md;
else
case md_ctrl is
when reset_md =>
md <= "0000000000000000";
when load_md =>
md <= out_alu(15 downto 0);
when fetch_first_md =>
md(15 downto 8) <= "00000000";
md(7 downto 0) <= data_in;
when fetch_next_md =>
md(15 downto 8) <= md(7 downto 0);
md(7 downto 0) <= data_in;
when shiftl_md =>
md(15 downto 1) <= md(14 downto 0);
md(0) <= '0';
when others =>
-- when latch_md =>
md <= md;
end case;
end if;
end if;
end process;
----------------------------------
--
-- Condition Codes
--
----------------------------------
cc_mux: process( clk, cc_ctrl, cc_out, cc, data_in, hold )
begin
if clk'event and clk = '0' then
if hold = '1' then
cc <= cc;
else
case cc_ctrl is
when reset_cc =>
cc <= "11000000";
when load_cc =>
cc <= cc_out;
when pull_cc =>
cc <= data_in;
when others =>
-- when latch_cc =>
cc <= cc;
end case;
end if;
end if;
end process;
----------------------------------
--
-- interrupt vector
--
----------------------------------
iv_mux: process( clk, iv_ctrl, hold )
begin
if clk'event and clk = '0' then
if hold = '1' then
iv <= iv;
else
case iv_ctrl is
when reset_iv =>
iv <= "111";
when nmi_iv =>
iv <= "110";
when swi_iv =>
iv <= "101";
when irq_iv =>
iv <= "100";
when icf_iv =>
iv <= "011";
when ocf_iv =>
iv <= "010";
when tof_iv =>
iv <= "001";
when sci_iv =>
iv <= "000";
when others =>
iv <= iv;
end case;
end if;
end if;
end process;
----------------------------------
--
-- op code fetch
--
----------------------------------
op_fetch: process( clk, data_in, op_ctrl, op_code, hold )
begin
if clk'event and clk = '0' then
if hold = '1' then
op_code <= op_code;
else
case op_ctrl is
when reset_op =>
op_code <= "00000001"; -- nop
when fetch_op =>
op_code <= data_in;
when others =>
-- when latch_op =>
op_code <= op_code;
end case;
end if;
end if;
end process;
----------------------------------
--
-- Left Mux
--
----------------------------------
left_mux: process( left_ctrl, acca, accb, xreg, sp, pc, ea, md )
begin
case left_ctrl is
when acca_left =>
left(15 downto 8) <= "00000000";
left(7 downto 0) <= acca;
when accb_left =>
left(15 downto 8) <= "00000000";
left(7 downto 0) <= accb;
when accd_left =>
left(15 downto 8) <= acca;
left(7 downto 0) <= accb;
when ix_left =>
left <= xreg;
when sp_left =>
left <= sp;
when others =>
-- when md_left =>
left <= md;
end case;
end process;
----------------------------------
--
-- Right Mux
--
----------------------------------
right_mux: process( right_ctrl, data_in, md, accb, ea )
begin
case right_ctrl is
when zero_right =>
right <= "0000000000000000";
when plus_one_right =>
right <= "0000000000000001";
when accb_right =>
right <= "00000000" & accb;
when others =>
-- when md_right =>
right <= md;
end case;
end process;
----------------------------------
--
-- Arithmetic Logic Unit
--
----------------------------------
mux_alu: process( alu_ctrl, cc, left, right, out_alu, cc_out )
variable valid_lo, valid_hi : boolean;
variable carry_in : std_logic;
variable daa_reg : std_logic_vector(7 downto 0);
begin
case alu_ctrl is
when alu_adc | alu_sbc |
alu_rol8 | alu_ror8 =>
carry_in := cc(CBIT);
when others =>
carry_in := '0';
end case;
valid_lo := left(3 downto 0) <= 9;
valid_hi := left(7 downto 4) <= 9;
if (cc(CBIT) = '0') then
if( cc(HBIT) = '1' ) then
if valid_hi then
daa_reg := "00000110";
else
daa_reg := "01100110";
end if;
else
if valid_lo then
if valid_hi then
daa_reg := "00000000";
else
daa_reg := "01100000";
end if;
else
if( left(7 downto 4) <= 8 ) then
daa_reg := "00000110";
else
daa_reg := "01100110";
end if;
end if;
end if;
else
if ( cc(HBIT) = '1' )then
daa_reg := "01100110";
else
if valid_lo then
daa_reg := "01100000";
else
daa_reg := "01100110";
end if;
end if;
end if;
case alu_ctrl is
when alu_add8 | alu_inc |
alu_add16 | alu_inx |
alu_adc =>
out_alu <= left + right + ("000000000000000" & carry_in);
when alu_sub8 | alu_dec |
alu_sub16 | alu_dex |
alu_sbc =>
out_alu <= left - right - ("000000000000000" & carry_in);
when alu_and =>
out_alu <= left and right; -- and/bit
when alu_ora =>
out_alu <= left or right; -- or
when alu_eor =>
out_alu <= left xor right; -- eor/xor
when alu_lsl16 | alu_asl8 | alu_rol8 =>
out_alu <= left(14 downto 0) & carry_in; -- rol8/asl8/lsl16
when alu_lsr16 | alu_lsr8 =>
out_alu <= carry_in & left(15 downto 1); -- lsr
when alu_ror8 =>
out_alu <= "00000000" & carry_in & left(7 downto 1); -- ror
when alu_asr8 =>
out_alu <= "00000000" & left(7) & left(7 downto 1); -- asr
when alu_neg =>
out_alu <= right - left; -- neg (right=0)
when alu_com =>
out_alu <= not left;
when alu_clr | alu_ld8 | alu_ld16 =>
out_alu <= right; -- clr, ld
when alu_st8 | alu_st16 =>
out_alu <= left;
when alu_daa =>
out_alu <= left + ("00000000" & daa_reg);
when alu_tpa =>
out_alu <= "00000000" & cc;
when others =>
out_alu <= left; -- nop
end case;
--
-- carry bit
--
case alu_ctrl is
when alu_add8 | alu_adc =>
cc_out(CBIT) <= (left(7) and right(7)) or
(left(7) and not out_alu(7)) or
(right(7) and not out_alu(7));
when alu_sub8 | alu_sbc =>
cc_out(CBIT) <= ((not left(7)) and right(7)) or
((not left(7)) and out_alu(7)) or
(right(7) and out_alu(7));
when alu_add16 =>
cc_out(CBIT) <= (left(15) and right(15)) or
(left(15) and not out_alu(15)) or
(right(15) and not out_alu(15));
when alu_sub16 =>
cc_out(CBIT) <= ((not left(15)) and right(15)) or
((not left(15)) and out_alu(15)) or
(right(15) and out_alu(15));
when alu_ror8 | alu_lsr16 | alu_lsr8 | alu_asr8 =>
cc_out(CBIT) <= left(0);
when alu_rol8 | alu_asl8 =>
cc_out(CBIT) <= left(7);
when alu_lsl16 =>
cc_out(CBIT) <= left(15);
when alu_com =>
cc_out(CBIT) <= '1';
when alu_neg | alu_clr =>
cc_out(CBIT) <= out_alu(7) or out_alu(6) or out_alu(5) or out_alu(4) or
out_alu(3) or out_alu(2) or out_alu(1) or out_alu(0);
when alu_daa =>
if ( daa_reg(7 downto 4) = "0110" ) then
cc_out(CBIT) <= '1';
else
cc_out(CBIT) <= '0';
end if;
when alu_sec =>
cc_out(CBIT) <= '1';
when alu_clc =>
cc_out(CBIT) <= '0';
when alu_tap =>
cc_out(CBIT) <= left(CBIT);
when others =>
cc_out(CBIT) <= cc(CBIT);
end case;
--
-- Zero flag
--
case alu_ctrl is
when alu_add8 | alu_sub8 |
alu_adc | alu_sbc |
alu_and | alu_ora | alu_eor |
alu_inc | alu_dec |
alu_neg | alu_com | alu_clr |
alu_rol8 | alu_ror8 | alu_asr8 | alu_asl8 | alu_lsr8 |
alu_ld8 | alu_st8 =>
cc_out(ZBIT) <= not( out_alu(7) or out_alu(6) or out_alu(5) or out_alu(4) or
out_alu(3) or out_alu(2) or out_alu(1) or out_alu(0) );
when alu_add16 | alu_sub16 |
alu_lsl16 | alu_lsr16 |
alu_inx | alu_dex |
alu_ld16 | alu_st16 =>
cc_out(ZBIT) <= not( out_alu(15) or out_alu(14) or out_alu(13) or out_alu(12) or
out_alu(11) or out_alu(10) or out_alu(9) or out_alu(8) or
out_alu(7) or out_alu(6) or out_alu(5) or out_alu(4) or
out_alu(3) or out_alu(2) or out_alu(1) or out_alu(0) );
when alu_tap =>
cc_out(ZBIT) <= left(ZBIT);
when others =>
cc_out(ZBIT) <= cc(ZBIT);
end case;
--
-- negative flag
--
case alu_ctrl is
when alu_add8 | alu_sub8 |
alu_adc | alu_sbc |
alu_and | alu_ora | alu_eor |
alu_rol8 | alu_ror8 | alu_asr8 | alu_asl8 | alu_lsr8 |
alu_inc | alu_dec | alu_neg | alu_com | alu_clr |
alu_ld8 | alu_st8 =>
cc_out(NBIT) <= out_alu(7);
when alu_add16 | alu_sub16 |
alu_lsl16 | alu_lsr16 |
alu_ld16 | alu_st16 =>
cc_out(NBIT) <= out_alu(15);
when alu_tap =>
cc_out(NBIT) <= left(NBIT);
when others =>
cc_out(NBIT) <= cc(NBIT);
end case;
--
-- Interrupt mask flag
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -