?? cpu01.vhd
字號:
--===========================================================================--
--
-- S Y N T H E Z I A B L E CPU01 C O R E
--
-- www.OpenCores.Org - December 2002
-- This core adheres to the GNU public license
--
-- File name : cpu01.vhd
--
-- Purpose : Implements a 6801 compatible CPU core
--
-- Dependencies : ieee.Std_Logic_1164
-- ieee.std_logic_unsigned
--
-- Author : John E. Kent
--
--===========================================================================----
--
-- Revision History:
--
-- Date: Revision Author
-- 22 Sep 2002 0.1 John Kent
--
-- 30 Oct 2002 0.2 John Kent
-- made NMI edge triggered
--
-- 30 Oct 2002 0.3 John Kent
-- more corrections to NMI
-- added wai_wait_state to prevent stack overflow on wai.
--
-- 1 Nov 2002 0.4 John Kent
-- removed WAI states and integrated WAI with the interrupt service routine
-- replace Data out (do) and Data in (di) register with a single Memory Data (md) reg.
-- Added Multiply instruction states.
-- run ALU and CC out of CPU module for timing measurements.
--
-- 3 Nov 2002 0.5 John Kent
-- Memory Data Register was not loaded on Store instructions
-- SEV and CLV were not defined in the ALU
-- Overflow Flag on NEG was incorrect
--
-- 16th Feb 2003 0.6 John Kent
-- Rearranged the execution cycle for dual operand instructions
-- so that occurs during the following fetch cycle.
-- This allows the reduction of one clock cycle from dual operand
-- instruction. Note that this also necessitated re-arranging the
-- program counter so that it is no longer incremented in the ALU.
-- The effective address has also been re-arranged to include a
-- separate added. The STD (store accd) now sets the condition codes.
--
-- 28th Jun 2003 0.7 John Kent
-- Added Hold and Halt signals. Hold is used to steal cycles from the
-- CPU or add wait states. Halt puts the CPU in the inactive state
-- and is only honoured in the fetch cycle. Both signals are active high.
--
-- 24 Aug 2003 1.0 John Kent
-- Converted 6800 core to 6801 by removing alu_cpx
-- Also added 4 extra interrupt inputs
--
-- 16 January 2004 1.1 John Kent (by Michael Hasenfratz)
-- Failure to clear carry bit during CLR instructions
-- Corrected CLR instructions to set alu_ctrl to alu_clr instead of alu_ld8.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity cpu01 is
port (
clk: in std_logic;
rst: in std_logic;
rw: out std_logic;
vma: out std_logic;
address: out std_logic_vector(15 downto 0);
data_in: in std_logic_vector(7 downto 0);
data_out: out std_logic_vector(7 downto 0);
hold: in std_logic;
halt: in std_logic;
irq: in std_logic;
nmi: in std_logic;
irq_icf: in std_logic;
irq_ocf: in std_logic;
irq_tof: in std_logic;
irq_sci: in std_logic;
test_alu: out std_logic_vector(15 downto 0);
test_cc: out std_logic_vector(7 downto 0)
);
end;
architecture CPU_ARCH of cpu01 is
constant SBIT : integer := 7;
constant XBIT : integer := 6;
constant HBIT : integer := 5;
constant IBIT : integer := 4;
constant NBIT : integer := 3;
constant ZBIT : integer := 2;
constant VBIT : integer := 1;
constant CBIT : integer := 0;
type state_type is (reset_state, fetch_state, decode_state,
extended_state, indexed_state, read8_state, read16_state, immediate16_state,
write8_state, write16_state,
execute_state, halt_state, error_state,
mul_state, mulea_state, muld_state,
mul0_state, mul1_state, mul2_state, mul3_state,
mul4_state, mul5_state, mul6_state, mul7_state,
jmp_state, jsr_state, jsr1_state,
branch_state, bsr_state, bsr1_state,
rts_hi_state, rts_lo_state,
int_pcl_state, int_pch_state,
int_ixl_state, int_ixh_state,
int_cc_state, int_acca_state, int_accb_state,
int_wai_state, int_mask_state,
rti_state, rti_cc_state, rti_acca_state, rti_accb_state,
rti_ixl_state, rti_ixh_state,
rti_pcl_state, rti_pch_state,
pula_state, psha_state, pulb_state, pshb_state,
pulx_lo_state, pulx_hi_state, pshx_lo_state, pshx_hi_state,
vect_lo_state, vect_hi_state );
type addr_type is (idle_ad, fetch_ad, read_ad, write_ad, push_ad, pull_ad, int_hi_ad, int_lo_ad );
type dout_type is (md_lo_dout, md_hi_dout, acca_dout, accb_dout, ix_lo_dout, ix_hi_dout, cc_dout, pc_lo_dout, pc_hi_dout );
type op_type is (reset_op, fetch_op, latch_op );
type acca_type is (reset_acca, load_acca, load_hi_acca, pull_acca, latch_acca );
type accb_type is (reset_accb, load_accb, pull_accb, latch_accb );
type cc_type is (reset_cc, load_cc, pull_cc, latch_cc );
type ix_type is (reset_ix, load_ix, pull_lo_ix, pull_hi_ix, latch_ix );
type sp_type is (reset_sp, latch_sp, load_sp );
type pc_type is (reset_pc, latch_pc, load_ea_pc, add_ea_pc, pull_lo_pc, pull_hi_pc, inc_pc );
type md_type is (reset_md, latch_md, load_md, fetch_first_md, fetch_next_md, shiftl_md );
type ea_type is (reset_ea, latch_ea, add_ix_ea, load_accb_ea, inc_ea, fetch_first_ea, fetch_next_ea );
type iv_type is (reset_iv, latch_iv, swi_iv, nmi_iv, irq_iv, icf_iv, ocf_iv, tof_iv, sci_iv );
type nmi_type is (reset_nmi, set_nmi, latch_nmi );
type left_type is (acca_left, accb_left, accd_left, md_left, ix_left, sp_left );
type right_type is (md_right, zero_right, plus_one_right, accb_right );
type alu_type is (alu_add8, alu_sub8, alu_add16, alu_sub16, alu_adc, alu_sbc,
alu_and, alu_ora, alu_eor,
alu_tst, alu_inc, alu_dec, alu_clr, alu_neg, alu_com,
alu_inx, alu_dex,
alu_lsr16, alu_lsl16,
alu_ror8, alu_rol8,
alu_asr8, alu_asl8, alu_lsr8,
alu_sei, alu_cli, alu_sec, alu_clc, alu_sev, alu_clv, alu_tpa, alu_tap,
alu_ld8, alu_st8, alu_ld16, alu_st16, alu_nop, alu_daa );
signal op_code: std_logic_vector(7 downto 0);
signal acca: std_logic_vector(7 downto 0);
signal accb: std_logic_vector(7 downto 0);
signal cc: std_logic_vector(7 downto 0);
signal cc_out: std_logic_vector(7 downto 0);
signal xreg: std_logic_vector(15 downto 0);
signal sp: std_logic_vector(15 downto 0);
signal ea: std_logic_vector(15 downto 0);
signal pc: std_logic_vector(15 downto 0);
signal md: std_logic_vector(15 downto 0);
signal left: std_logic_vector(15 downto 0);
signal right: std_logic_vector(15 downto 0);
signal out_alu: std_logic_vector(15 downto 0);
signal iv: std_logic_vector(2 downto 0);
signal nmi_req: std_logic;
signal nmi_ack: std_logic;
signal state: state_type;
signal next_state: state_type;
signal pc_ctrl: pc_type;
signal ea_ctrl: ea_type;
signal op_ctrl: op_type;
signal md_ctrl: md_type;
signal acca_ctrl: acca_type;
signal accb_ctrl: accb_type;
signal ix_ctrl: ix_type;
signal cc_ctrl: cc_type;
signal sp_ctrl: sp_type;
signal iv_ctrl: iv_type;
signal left_ctrl: left_type;
signal right_ctrl: right_type;
signal alu_ctrl: alu_type;
signal addr_ctrl: addr_type;
signal dout_ctrl: dout_type;
signal nmi_ctrl: nmi_type;
begin
----------------------------------
--
-- Address bus multiplexer
--
----------------------------------
addr_mux: process( clk, addr_ctrl, pc, ea, 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 push_ad =>
address <= sp;
vma <= '1';
rw <= '0';
when pull_ad =>
address <= sp;
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( clk, dout_ctrl, md, acca, accb, xreg, pc, cc )
begin
case dout_ctrl is
when md_hi_dout => -- alu output
data_out <= md(15 downto 8);
when md_lo_dout =>
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 cc_dout => -- condition codes
data_out <= cc;
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;
----------------------------------
--
-- Program Counter Control
--
----------------------------------
pc_mux: process( clk, pc_ctrl, pc, out_alu, data_in, ea, hold )
variable tempof : std_logic_vector(15 downto 0);
variable temppc : std_logic_vector(15 downto 0);
begin
case pc_ctrl is
when add_ea_pc =>
if ea(7) = '0' then
tempof := "00000000" & ea(7 downto 0);
else
tempof := "11111111" & ea(7 downto 0);
end if;
when inc_pc =>
tempof := "0000000000000001";
when others =>
tempof := "0000000000000000";
end case;
case pc_ctrl is
when reset_pc =>
temppc := "1111111111111110";
when load_ea_pc =>
temppc := ea;
when pull_lo_pc =>
temppc(7 downto 0) := data_in;
temppc(15 downto 8) := pc(15 downto 8);
when pull_hi_pc =>
temppc(7 downto 0) := pc(7 downto 0);
temppc(15 downto 8) := data_in;
when others =>
temppc := pc;
end case;
if clk'event and clk = '0' then
if hold = '1' then
pc <= pc;
else
pc <= temppc + tempof;
end if;
end if;
end process;
----------------------------------
--
-- Effective Address Control
--
----------------------------------
ea_mux: process( clk, ea_ctrl, ea, out_alu, data_in, accb, xreg, hold )
variable tempind : std_logic_vector(15 downto 0);
variable tempea : std_logic_vector(15 downto 0);
begin
case ea_ctrl is
when add_ix_ea =>
tempind := "00000000" & ea(7 downto 0);
when inc_ea =>
tempind := "0000000000000001";
when others =>
tempind := "0000000000000000";
end case;
case ea_ctrl is
when reset_ea =>
tempea := "0000000000000000";
when load_accb_ea =>
tempea := "00000000" & accb(7 downto 0);
when add_ix_ea =>
tempea := xreg;
when fetch_first_ea =>
tempea(7 downto 0) := data_in;
tempea(15 downto 8) := "00000000";
when fetch_next_ea =>
tempea(7 downto 0) := data_in;
tempea(15 downto 8) := ea(7 downto 0);
when others =>
tempea := ea;
end case;
if clk'event and clk = '0' then
if hold = '1' then
ea <= ea;
else
ea <= tempea + tempind;
end if;
end if;
end process;
--------------------------------
--
-- Accumulator A
--
--------------------------------
acca_mux : process( clk, acca_ctrl, out_alu, acca, data_in, hold )
begin
if clk'event and clk = '0' then
if hold = '1' then
acca <= acca;
else
case acca_ctrl is
when reset_acca =>
acca <= "00000000";
when load_acca =>
acca <= out_alu(7 downto 0);
when load_hi_acca =>
acca <= out_alu(15 downto 8);
when pull_acca =>
acca <= data_in;
when others =>
-- when latch_acca =>
acca <= acca;
end case;
end if;
end if;
end process;
--------------------------------
--
-- Accumulator B
--
--------------------------------
accb_mux : process( clk, accb_ctrl, out_alu, accb, data_in, hold )
begin
if clk'event and clk = '0' then
if hold = '1' then
accb <= accb;
else
case accb_ctrl is
when reset_accb =>
accb <= "00000000";
when load_accb =>
accb <= out_alu(7 downto 0);
when pull_accb =>
accb <= data_in;
when others =>
-- when latch_accb =>
accb <= accb;
end case;
end if;
end if;
end process;
--------------------------------
--
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -