📄 cpu09.vhd
字号:
end case;
end if;
end if;
end process;
----------------------------------
--
-- op code register
--
----------------------------------
op_reg: process( clk, op_ctrl, hold, op_code, data_in )
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 <= "00010010";
when fetch_op =>
op_code <= data_in;
when others =>
-- when latch_op =>
op_code <= op_code;
end case;
end if;
end if;
end process;
----------------------------------
--
-- pre byte op code register
--
----------------------------------
pre_reg: process( clk, pre_ctrl, hold, pre_code, data_in )
begin
if clk'event and clk = '0' then
if hold= '1' then
pre_code <= pre_code;
else
case pre_ctrl is
when reset_pre =>
pre_code <= "00000000";
when fetch_pre =>
pre_code <= data_in;
when others =>
-- when latch_pre =>
pre_code <= pre_code;
end case;
end if;
end if;
end process;
--------------------------------
--
-- state machine
--
--------------------------------
change_state: process( clk, rst, state, hold, next_state )
begin
if clk'event and clk = '0' then
if rst = '1' then
state <= reset_state;
else
if hold = '1' then
state <= state;
else
state <= next_state;
end if;
end if;
end if;
end process;
-- output
------------------------------------
--
-- Nmi register
--
------------------------------------
nmi_reg: process( clk, nmi_ctrl, hold, nmi_ack )
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;
------------------------------------
--
-- Detect Edge of NMI interrupt
--
------------------------------------
nmi_handler : process( clk, rst, nmi, nmi_ack, nmi_req, nmi_enable )
begin
if clk'event and clk='0' then
if rst='1' then
nmi_req <= '0';
else
if (nmi='1') and (nmi_ack='0') and (nmi_enable='1') 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 process;
----------------------------------
--
-- Address output multiplexer
--
----------------------------------
addr_mux: process( addr_ctrl, pc, ea, up, sp, iv )
begin
case addr_ctrl is
when idle_ad =>
address <= "1111111111111111";
vma <= '0';
rw <= '1';
when fetch_ad =>
address <= pc;
vma <= '1';
rw <= '1';
when read_ad =>
address <= ea;
vma <= '1';
rw <= '1';
when write_ad =>
address <= ea;
vma <= '1';
rw <= '0';
when pushs_ad =>
address <= sp;
vma <= '1';
rw <= '0';
when pulls_ad =>
address <= sp;
vma <= '1';
rw <= '1';
when pushu_ad =>
address <= up;
vma <= '1';
rw <= '0';
when pullu_ad =>
address <= up;
vma <= '1';
rw <= '1';
when int_hi_ad =>
address <= "111111111111" & iv & "0";
vma <= '1';
rw <= '1';
when int_lo_ad =>
address <= "111111111111" & iv & "1";
vma <= '1';
rw <= '1';
when others =>
address <= "1111111111111111";
vma <= '0';
rw <= '1';
end case;
end process;
--------------------------------
--
-- Data Bus output
--
--------------------------------
dout_mux : process( dout_ctrl, md, acca, accb, dp, xreg, yreg, sp, up, pc, cc )
begin
case dout_ctrl is
when md_hi_dout => -- alu output
data_out <= md(15 downto 8);
when md_lo_dout => -- alu output
data_out <= md(7 downto 0);
when acca_dout => -- accumulator a
data_out <= acca;
when accb_dout => -- accumulator b
data_out <= accb;
when ix_lo_dout => -- index reg
data_out <= xreg(7 downto 0);
when ix_hi_dout => -- index reg
data_out <= xreg(15 downto 8);
when iy_lo_dout => -- index reg
data_out <= yreg(7 downto 0);
when iy_hi_dout => -- index reg
data_out <= yreg(15 downto 8);
when sp_lo_dout => -- s stack pointer
data_out <= sp(7 downto 0);
when sp_hi_dout => -- s stack pointer
data_out <= sp(15 downto 8);
when up_lo_dout => -- u stack pointer
data_out <= up(7 downto 0);
when up_hi_dout => -- u stack pointer
data_out <= up(15 downto 8);
when cc_dout => -- condition code register
data_out <= cc;
when dp_dout => -- direct page register
data_out <= dp;
when pc_lo_dout => -- low order pc
data_out <= pc(7 downto 0);
when pc_hi_dout => -- high order pc
data_out <= pc(15 downto 8);
when others =>
data_out <= "00000000";
end case;
end process;
----------------------------------
--
-- Left Mux
--
----------------------------------
left_mux: process( left_ctrl, acca, accb, cc, dp, xreg, yreg, up, sp, pc, ea, md )
begin
case left_ctrl is
when cc_left =>
left(15 downto 8) <= "00000000";
left(7 downto 0) <= cc;
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 dp_left =>
left(15 downto 8) <= "00000000";
left(7 downto 0) <= dp;
when accd_left =>
left(15 downto 8) <= acca;
left(7 downto 0) <= accb;
when md_left =>
left <= md;
when ix_left =>
left <= xreg;
when iy_left =>
left <= yreg;
when sp_left =>
left <= sp;
when up_left =>
left <= up;
when pc_left =>
left <= pc;
when others =>
-- when ea_left =>
left <= ea;
end case;
end process;
----------------------------------
--
-- Right Mux
--
----------------------------------
right_mux: process( right_ctrl, md, acca, accb, ea )
begin
case right_ctrl is
when ea_right =>
right <= ea;
when zero_right =>
right <= "0000000000000000";
when one_right =>
right <= "0000000000000001";
when two_right =>
right <= "0000000000000010";
when acca_right =>
if acca(7) = '0' then
right <= "00000000" & acca(7 downto 0);
else
right <= "11111111" & acca(7 downto 0);
end if;
when accb_right =>
if accb(7) = '0' then
right <= "00000000" & accb(7 downto 0);
else
right <= "11111111" & accb(7 downto 0);
end if;
when accd_right =>
right <= acca & accb;
when md_sign5_right =>
if md(4) = '0' then
right <= "00000000000" & md(4 downto 0);
else
right <= "11111111111" & md(4 downto 0);
end if;
when md_sign8_right =>
if md(7) = '0' then
right <= "00000000" & md(7 downto 0);
else
right <= "11111111" & md(7 downto 0);
end if;
when others =>
-- when md_right =>
right <= md;
end case;
end process;
----------------------------------
--
-- Arithmetic Logic Unit
--
----------------------------------
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 alu_asr8 =>
carry_in := left(7);
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 i
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -