📄 cpu09.vhd
字号:
-- $Id: cpu09.vhd,v 1.4 2006/07/16 17:44:23 dilbert57 Exp $
--===========================================================================----
--
-- S Y N T H E Z I A B L E CPU09 - 6809 compatible CPU Core
--
-- www.OpenCores.Org - September 2003
-- This core adheres to the GNU public license
--
-- File name : cpu09.vhd
--
-- Purpose : 6809 CPU core
--
-- Dependencies : ieee.Std_Logic_1164
-- ieee.std_logic_unsigned
--
-- Uses : None
--
-- Author : John E. Kent
-- dilbert57@opencores.org
--
--===========================================================================----
--
-- Revision History:
--===========================================================================--
--
-- Version 0.1 - 26 June 2003 - John Kent
-- Added extra level in state stack
-- fixed some calls to the extended addressing state
--
-- Version 0.2 - 5 Sept 2003 - John Kent
-- Fixed 16 bit indexed offset (was doing read rather than fetch)
-- Added/Fixed STY and STS instructions.
-- ORCC_STATE ANDed CC state rather than ORed it - Now fixed
-- CMPX Loaded ACCA and ACCB - Now fixed
--
-- Version 1.0 - 6 Sep 2003 - John Kent
-- Initial release to Open Cores
-- reversed clock edge
--
-- Version 1.1 - 29 November 2003 John kent
-- ACCA and ACCB indexed offsets are 2's complement.
-- ALU Right Mux now sign extends ACCA & ACCB offsets
-- Absolute Indirect addressing performed a read on the
-- second byte of the address rather than a fetch
-- so it formed an incorrect address. Now fixed.
--
-- Version 1.2 - 29 November 2003 John Kent
-- LEAX and LEAY affect the Z bit only
-- LEAS and LEAU do not affect any condition codes
-- added an extra ALU control for LEA.
--
-- Version 1.3 - 12 December 2003 John Kent
-- CWAI did not work, was missed a PUSH_ST on calling
-- the ANDCC_STATE. Thanks go to Ghassan Kraidy for
-- finding this fault.
--
-- Version 1.4 - 12 December 2003 John Kent
-- Missing cc_ctrl assignment in otherwise case of
-- lea_state resulted in cc_ctrl being latched in
-- that state.
-- The otherwise statement should never be reached,
-- and has been fixed simply to resolve synthesis warnings.
--
-- Version 1.5 - 17 january 2004 John kent
-- The clear instruction used "alu_ld8" to control the ALU
-- rather than "alu_clr". This mean the Carry was not being
-- cleared correctly.
--
-- Version 1.6 - 24 January 2004 John Kent
-- Fixed problems in PSHU instruction
--
-- Version 1.7 - 25 January 2004 John Kent
-- removed redundant "alu_inx" and "alu_dex'
-- Removed "test_alu" and "test_cc"
-- STD instruction did not set condition codes
-- JMP direct was not decoded properly
-- CLR direct performed an unwanted read cycle
-- Bogus "latch_md" in Page2 indexed addressing
--
-- Version 1.8 - 27 January 2004 John Kent
-- CWAI in decode1_state should increment the PC.
-- ABX is supposed to be an unsigned addition.
-- Added extra ALU function
-- ASR8 slightly changed in the ALU.
--
-- Version 1.9 - 20 August 2005
-- LSR8 is now handled in ASR8 and ROR8 case in the ALU,
-- rather than LSR16. There was a problem with single
-- operand instructions using the MD register which is
-- sign extended on the first 8 bit fetch.
--
-- Version 1.10 - 13 September 2005
-- TFR & EXG instructions did not work for the Condition Code Register
-- An extra case has been added to the ALU for the alu_tfr control
-- to assign the left ALU input (alu_left) to the condition code
-- outputs (cc_out).
--
-- Version 1.11 - 16 September 2005
-- JSR ,X should not predecrement S before calculating the jump address.
-- The reason is that JSR [0,S] needs S to point to the top of the stack
-- to fetch a valid vector address. The solution is to have the addressing
-- mode microcode called before decrementing S and then decrementing S in
-- JSR_STATE. JSR_STATE in turn calls PUSH_RETURN_LO_STATE rather than
-- PUSH_RETURN_HI_STATE so that both the High & Low halves of the PC are
-- pushed on the stack. This adds one extra bus cycle, but resolves the
-- addressing conflict. I've also removed the pre-decement S in
-- JSR EXTENDED as it also calls JSR_STATE.
--
-- Version 1.12 - 6th June 2006
-- 6809 Programming reference manual says V is not affected by ASR, LSR and ROR
-- This is different to the 6800. CLR should reset the V bit.
--
-- Version 1.13 - 7th July 2006
-- Disable NMI on reset until S Stack pointer has been loaded.
-- Added nmi_enable signal in sp_reg process and nmi_handler process.
--
-- Version 1.4 - 11th July 2006
-- 1. Added new state to RTI called rti_entire_state.
-- This state tests the CC register after it has been loaded
-- from the stack. Previously the current CC was tested which
-- was incorrect. The Entire Flag should be set before the
-- interrupt stacks the CC.
-- 2. On bogus Interrupts, int_cc_state went to rti_state,
-- which was an enumerated state, but not defined anywhere.
-- rti_state has been changed to rti_cc_state so that bogus interrupt
-- will perform an RTI after entering that state.
-- 3. Sync should generate an interrupt if the interrupt masks
-- are cleared. If the interrupt masks are set, then an interrupt
-- will cause the the PC to advance to the next instruction.
-- Note that I don't wait for an interrupt to be asserted for
-- three clock cycles.
-- 4. Added new ALU control state "alu_mul". "alu_mul" is used in
-- the Multiply instruction replacing "alu_add16". This is similar
-- to "alu_add16" except it sets the Carry bit to B7 of the result
-- in ACCB, sets the Zero bit if the 16 bit result is zero, but
-- does not affect The Half carry (H), Negative (N) or Overflow (V)
-- flags. The logic was re-arranged so that it adds md or zero so
-- that the Carry condition code is set on zero multiplicands.
-- 5. DAA (Decimal Adjust Accumulator) should set the Negative (N)
-- and Zero Flags. It will also affect the Overflow (V) flag although
-- the operation is undefined. It's anyones guess what DAA does to V.
--
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity cpu09 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);
halt: in std_logic;
hold: in std_logic;
irq: in std_logic;
firq: in std_logic;
nmi: in std_logic
);
end;
architecture CPU_ARCH of cpu09 is
constant EBIT : integer := 7;
constant FBIT : 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;
--
-- Interrupt vector modifiers
--
constant RST_VEC : std_logic_vector(2 downto 0) := "111";
constant NMI_VEC : std_logic_vector(2 downto 0) := "110";
constant SWI_VEC : std_logic_vector(2 downto 0) := "101";
constant IRQ_VEC : std_logic_vector(2 downto 0) := "100";
constant FIRQ_VEC : std_logic_vector(2 downto 0) := "011";
constant SWI2_VEC : std_logic_vector(2 downto 0) := "010";
constant SWI3_VEC : std_logic_vector(2 downto 0) := "001";
constant RESV_VEC : std_logic_vector(2 downto 0) := "000";
type state_type is (-- Start off in Reset
reset_state,
-- Fetch Interrupt Vectors (including reset)
vect_lo_state, vect_hi_state,
-- Fetch Instruction Cycle
fetch_state,
-- Decode Instruction Cycles
decode1_state, decode2_state, decode3_state,
-- Calculate Effective Address
imm16_state,
indexed_state, index8_state, index16_state, index16_2_state,
pcrel8_state, pcrel16_state, pcrel16_2_state,
indexaddr_state, indexaddr2_state,
postincr1_state, postincr2_state,
indirect_state, indirect2_state, indirect3_state,
extended_state,
-- single ops
single_op_read_state,
single_op_exec_state,
single_op_write_state,
-- Dual op states
dual_op_read8_state, dual_op_read16_state, dual_op_read16_2_state,
dual_op_write8_state, dual_op_write16_state,
--
sync_state, halt_state, error_state,
--
andcc_state, orcc_state,
tfr_state, exg_state, exg1_state,
lea_state,
-- Multiplication
mul_state, mulea_state, muld_state,
mul0_state, mul1_state, mul2_state, mul3_state,
mul4_state, mul5_state, mul6_state, mul7_state,
-- Branches
lbranch_state, sbranch_state,
-- Jumps, Subroutine Calls and Returns
jsr_state, jmp_state,
push_return_hi_state, push_return_lo_state,
pull_return_hi_state, pull_return_lo_state,
-- Interrupt cycles
int_decr_state,
int_entire_state,
int_pcl_state, int_pch_state,
int_upl_state, int_uph_state,
int_iyl_state, int_iyh_state,
int_ixl_state, int_ixh_state,
int_cc_state,
int_acca_state, int_accb_state,
int_dp_state,
int_cwai_state, int_mask_state,
-- Return From Interrupt
rti_cc_state, rti_entire_state,
rti_acca_state, rti_accb_state,
rti_dp_state,
rti_ixl_state, rti_ixh_state,
rti_iyl_state, rti_iyh_state,
rti_upl_state, rti_uph_state,
rti_pcl_state, rti_pch_state,
-- Push Registers using SP
pshs_state,
pshs_pcl_state, pshs_pch_state,
pshs_upl_state, pshs_uph_state,
pshs_iyl_state, pshs_iyh_state,
pshs_ixl_state, pshs_ixh_state,
pshs_dp_state,
pshs_acca_state, pshs_accb_state,
pshs_cc_state,
-- Pull Registers using SP
puls_state,
puls_cc_state,
puls_acca_state, puls_accb_state,
puls_dp_state,
puls_ixl_state, puls_ixh_state,
puls_iyl_state, puls_iyh_state,
puls_upl_state, puls_uph_state,
puls_pcl_state, puls_pch_state,
-- Push Registers using UP
pshu_state,
pshu_pcl_state, pshu_pch_state,
pshu_spl_state, pshu_sph_state,
pshu_iyl_state, pshu_iyh_state,
pshu_ixl_state, pshu_ixh_state,
pshu_dp_state,
pshu_acca_state, pshu_accb_state,
pshu_cc_state,
-- Pull Registers using UP
pulu_state,
pulu_cc_state,
pulu_acca_state, pulu_accb_state,
pulu_dp_state,
pulu_ixl_state, pulu_ixh_state,
pulu_iyl_state, pulu_iyh_state,
pulu_spl_state, pulu_sph_state,
pulu_pcl_state, pulu_pch_state );
type stack_type is array(2 downto 0) of state_type;
type st_type is (idle_st, push_st, pull_st );
type addr_type is (idle_ad, fetch_ad, read_ad, write_ad, pushu_ad, pullu_ad, pushs_ad, pulls_ad, int_hi_ad, int_lo_ad );
type dout_type is (cc_dout, acca_dout, accb_dout, dp_dout,
ix_lo_dout, ix_hi_dout, iy_lo_dout, iy_hi_dout,
up_lo_dout, up_hi_dout, sp_lo_dout, sp_hi_dout,
pc_lo_dout, pc_hi_dout, md_lo_dout, md_hi_dout );
type op_type is (reset_op, fetch_op, latch_op );
type pre_type is (reset_pre, fetch_pre, latch_pre );
type cc_type is (reset_cc, load_cc, pull_cc, latch_cc );
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 dp_type is (reset_dp, load_dp, pull_dp, latch_dp );
type ix_type is (reset_ix, load_ix, pull_lo_ix, pull_hi_ix, latch_ix );
type iy_type is (reset_iy, load_iy, pull_lo_iy, pull_hi_iy, latch_iy );
type sp_type is (reset_sp, latch_sp, load_sp, pull_hi_sp, pull_lo_sp );
type up_type is (reset_up, latch_up, load_up, pull_hi_up, pull_lo_up );
type pc_type is (reset_pc, latch_pc, load_pc, pull_lo_pc, pull_hi_pc, incr_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, load_ea, fetch_first_ea, fetch_next_ea );
type iv_type is (reset_iv, latch_iv, nmi_iv, irq_iv, firq_iv, swi_iv, swi2_iv, swi3_iv, resv_iv);
type nmi_type is (reset_nmi, set_nmi, latch_nmi );
type left_type is (cc_left, acca_left, accb_left, dp_left,
ix_left, iy_left, up_left, sp_left,
accd_left, md_left, pc_left, ea_left );
type right_type is (ea_right, zero_right, one_right, two_right,
acca_right, accb_right, accd_right,
md_right, md_sign5_right, md_sign8_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_lsr16, alu_lsl16,
alu_ror8, alu_rol8, alu_mul,
alu_asr8, alu_asl8, alu_lsr8,
alu_andcc, alu_orcc, alu_sex, alu_tfr, alu_abx,
alu_seif, alu_sei, alu_see, alu_cle,
alu_ld8, alu_st8, alu_ld16, alu_st16, alu_lea, alu_nop, alu_daa );
signal op_code: std_logic_vector(7 downto 0);
signal pre_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 dp: std_logic_vector(7 downto 0);
signal xreg: std_logic_vector(15 downto 0);
signal yreg: std_logic_vector(15 downto 0);
signal sp: std_logic_vector(15 downto 0);
signal up: 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 nmi_enable: std_logic;
signal state: state_type;
signal next_state: state_type;
signal saved_state: state_type;
signal return_state: state_type;
signal state_stack: stack_type;
signal st_ctrl: st_type;
signal pc_ctrl: pc_type;
signal ea_ctrl: ea_type;
signal op_ctrl: op_type;
signal pre_ctrl: pre_type;
signal md_ctrl: md_type;
signal acca_ctrl: acca_type;
signal accb_ctrl: accb_type;
signal ix_ctrl: ix_type;
signal iy_ctrl: iy_type;
signal cc_ctrl: cc_type;
signal dp_ctrl: dp_type;
signal sp_ctrl: sp_type;
signal up_ctrl: up_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
----------------------------------
--
-- State machine stack
--
----------------------------------
state_stack_proc: process( clk, st_ctrl, state_stack, return_state, hold )
begin
if clk'event and clk = '0' then
if hold= '1' then
state_stack(0) <= state_stack(0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -