📄 mc8051.vhd
字号:
------------------------------------------------
-- Model : 8051 Behavioral Model,
-- Top Level Block
--
-- File : mc8051.vhd (MicroController 8051)
--
-- Author : Michael Mayer (mrmayer@computer.org),
-- Dr. Hardy J. Pottinger, advisor
-- Department of Electrical Engineering
-- University of Missouri - Rolla
--
-- Requires : pack8051.vhd (Package containing
-- needed procedures, types, etc.)
-- uart.vhd (UART peripheral)
-- (written by Lingfeng Yuan, Prajakta Kurvey)
-- see also LIBRARY and USE clauses below
--
-- Thanks to : Kyle Mitchel for much help
--
-- Inspired from : Sundar Subbarayan
-- UC Riverside CS 122a (lab 3)
-- Professor: Dr.Frank Vahid
-- 17th January 1996
--
-- Date Started : September 15, 1997
--
-- Features : Entire command set
-- Support for Intel Hex format
-- Internal program memory (4Kb)
-- Internal data memory (256 Bytes) - 8052
-- Supports external prog mem up to 64 Kb
-- Supports external data mem up to 64 Kb
-- using MOVX instr. with 16 bit data ptr.
-- Supports I/O through 4 ports when not using
-- above features
-- Interrupts w/ Priority
-- Choice of level / edge sensitive interrupts
-- Timer 1 in mode 2 only
-- Serial tx / rx in mode 1
--
-- Limitations : Reset Port does not function
-- LIMITED PERIPHERALS:
-- No timer 0
-- Limited timer 1 (only mode 2)
-- can't read from timer value TL0
-- Limited UART
--
-- REV DATE Description
-- ----- -------- ---------------------------------------
-- 1.0 01/17/97 Work from Sundar Subbarayan and
-- Dr. Frank Vahid
--
-- 2.0 11/04/97 Initial implementation of command
-- interpreter for Hex Code set.
--
-- 2.1 11/12/97 Changed memory to separate lo and hi mem
-- and made all access through functions /
-- procedures / aliases to allow for
-- distinction between indirect and direct
-- accessing of upper 128 bytes of data mem
-- (for 8052 compatibility).
--
-- 2.2 11/21/97 Made program memory access only through
-- the process get_pmem and its two
-- signals: pmem_s1_byte and pmem_s4_byte
-- Added state machine sensitive to xtal which
-- governs the machine cycles, port & mem
-- reads, etc. Built support for external
-- program memory read in process get_pmem.
--
-- 2.3 12/12/97 Corrected bug in get_pmem - resync to pc
-- Moved load_program procedure to pack8051
-- Converted IF..ELSEIF structure to CASE for
-- decoding of opcodes. Completed any missing
-- commands and verified that all 256 were available
--
-- 3.0 12/13/97 Changed port 3 to a single std_logic_vector
-- Differentiated between commands that read the
-- port and those that read the latch.
-- Added output drivers for port3
--
-- 3.1 12/14/97 Modified procedures in main for accessing
-- data bytes. All use get_byte_dmem
-- and set_byte_dmem for any data access, unless
-- they access it through aliases (e.g. acc <= val)
--
-- 3.1.1 01/26/98 Added condition of ea_n to the program rom load
--
-- 3.1.2 02/22/98 Corrected handle_sub's advancing of the pc
-- Corrected JNC to IF cy='0' instead of '1'
--
-- 3.1.3 02/24/98 Corrected MOVX's control of Ports 2 & 3.
--
-- 3.2 07/??/98 Corrections from Kyle Mitchell for
-- 0 or L, 1 or H and for initial boot-up
--
-- 4.0 08/30/98 Added serial UART, timer 1 in mode 2, and
-- the serial interrupt
--
-- 4.1 09/02/98 Added more interrupts.
--
-- 4.2 10/06/98 Corrected MOVX's control of ALE and PSEN_n
-- Fixed PC increment on several instructions
--
-- 4.3 10/08/98 Added level / edge sensitive interrupt support
-- Added priority to interrupts (IP)
--
-- 4.4 10/23/98 Fixed interrupt ea
-- ------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_arith.ALL;
-- Uses type unsigned, the "+" and "-" operators, and the functions
-- conv_integer and conv_unsigned, amongst others
USE std.textio.ALL;
USE work.pack8051.ALL;
ENTITY mc8051 IS
GENERIC (
program_filename : string := "code.hex"
);
PORT (
P0 : INOUT std_logic_vector(7 DOWNTO 0); -- used for data i/o
P1 : INOUT std_logic_vector(7 DOWNTO 0); -- low-order address byte
P2 : INOUT std_logic_vector(7 DOWNTO 0); -- high-order address byte
P3 : INOUT std_logic_vector(7 DOWNTO 0);
-- These are the other uses for port 3 pins
-- rxd : INOUT std_logic; --port 3.0, serial port receiver data
-- txd : INOUT std_logic; --port 3.1, serial port transmitter
-- int0_n : INOUT std_logic; --port 3.2, interrupt 0 input
-- int1_n : INOUT std_logic; --port 3.3, interrupt 1 input
-- t0 : INOUT std_logic; --port 3.4, input to counter 0
-- t1 : INOUT std_logic; --port 3.5, input to counter 1
-- wr_n : INOUT std_logic; --port 3.6, write control, latches port 0 to external
-- rd_n : INOUT std_logic; --port 3.7, read control, enables external to port 0
rst : IN std_logic; -- low to high causes reset - IGNORED!
xtal1 : IN std_logic; -- clock input 1.2 to 12 MHz
xtal2 : OUT std_logic; -- output from oscillator (for crystal) - IGNORED!
ale : OUT std_logic; -- provides Address Latch Enable output,
psen_n : OUT std_logic; -- program store enable
ea_n : IN std_logic -- when low, access external prog. mem
);
END ENTITY mc8051;
ARCHITECTURE behav OF mc8051 IS
-- The following variables hold the program and data memory.
-- Note that the upper 128 byte block of the data memory can
-- only be accessed via indirect addressing. Direct addressing
-- will instead reach the special function registers, etc.
-- The aliases below are mapped to specific points in the data so that
-- they can be accessed more easily. All data writes MUST be done
-- through the set_dmem process.
SIGNAL lo_dmem : data_lomem_T; -- the lower data memory
SIGNAL direct_hi_dmem : data_himem_T; -- the SFR memory space
SIGNAL indirect_hi_dmem : data_himem_T; -- the data memory
SIGNAL pc : wVec; -- program counter
SIGNAL pmem_s1_byte, pmem_s4_byte : bVec; -- next pmem data if needed
ALIAS acc : bvec IS direct_hi_dmem(16#E0#); -- accumulator
ALIAS b : bvec IS direct_hi_dmem(16#F0#); -- used for mult / div
ALIAS psw : bvec IS direct_hi_dmem(16#D0#); -- program status word
ALIAS cy : std_logic IS psw(7); -- carry flag
ALIAS ac : std_logic IS psw(6); -- auxiliary carry flag
ALIAS f0 : std_logic IS psw(5); -- flag 0
ALIAS rs : unsigned(1 DOWNTO 0) IS psw(4 DOWNTO 3); -- register bank selector
ALIAS ov : std_logic IS psw(2); -- overflow flag
ALIAS p : std_logic IS psw(0); -- parity - not implemented
ALIAS sp : bvec IS direct_hi_dmem(16#81#); -- stack pointer
ALIAS dpl : bvec IS direct_hi_dmem(16#82#); -- data pointer low
ALIAS dph : bvec IS direct_hi_dmem(16#83#); -- data pointer high
ALIAS p0_latch : bvec IS direct_hi_dmem(16#80#); -- port 0 in memory
ALIAS p1_latch : bvec IS direct_hi_dmem(16#90#); -- port 1 in memory
ALIAS p2_latch : bvec IS direct_hi_dmem(16#A0#); -- port 2 in memory
ALIAS p3_latch : bvec IS direct_hi_dmem(16#B0#); -- port 3 in memory
ALIAS scon : bvec IS direct_hi_dmem(16#98#); -- serial control reg.
ALIAS sm : unsigned(2 DOWNTO 0) IS scon(7 DOWNTO 5); -- serial mode
-- NOT IMPLEMENTED, but would decode as follows:
-- 00 shift reg (FOSC / 12 Baud)
-- 01 8-Bit UART (Variable Baus)
-- 10 9-Bit UART (Fosc / 64 or Fosc / 32 Baus)
-- 11 9-Bit UART (Variable Baud)
-- sm2 enables multiprocessor communication feature
ALIAS ren : std_logic IS scon(4); -- Reception Enable (active high)
ALIAS tb8 : std_logic IS scon(3); -- Transmit Bit 8 (ninth bit)
ALIAS rb8 : std_logic IS scon(2); -- Received Bit 8 (ninth bit)
ALIAS ti : std_logic IS scon(1); -- transmit interrupt
ALIAS ri : std_logic IS scon(0); -- receive interrup
ALIAS sbuf : bvec IS direct_hi_dmem(16#99#); -- serial data buffer
ALIAS tcon : bvec IS direct_hi_dmem(16#88#); -- timer control reg.
ALIAS timer1_on : std_logic IS tcon(6);
ALIAS it0 : std_logic IS tcon(0); -- ext. int. 0 type
ALIAS it1 : std_logic IS tcon(2); -- ext. int. 1 type
ALIAS ie : bvec IS direct_hi_dmem(16#A8#); -- interrupt enable
ALIAS ea : std_logic IS ie(7); -- disable all interrupts
ALIAS en_serial : std_logic IS ie(4); -- es bit
ALIAS en_t1 : std_logic IS ie(3);
ALIAS en_x1 : std_logic IS ie(2);
ALIAS en_t0 : std_logic IS ie(1);
ALIAS en_x0 : std_logic IS ie(0);
ALIAS ip : bvec IS direct_hi_dmem(16#B8#); -- interrupt priority
-- cycle_state is a signal containing the current state of the
-- machine cycle (s1 through s6), with 2 pulses for each state (p1 and p2).
SIGNAL cycle_state : machine_cycle_states;
SIGNAL TCLCL : TIME := 0 ns; -- time for a period of XTAL1
SIGNAL reset_pmem : std_logic;
-- port_req is used by the external data memory access (in process main)
-- to halt the output of the external program memory process.
SIGNAL port_req : std_logic := '0';
-- These two signals carry addr / data for ports 0 and 2
SIGNAL p0_addr, p2_addr : bvec;
-- When the following ctrl signals are low, then the port will
-- output the value associated with the latch, otherwise it is
-- the value of data / addr or special function.
SIGNAL p0_ctrl, p2_ctrl : std_logic;
SIGNAL p3_ctrl : bvec;
-- When Port 0 is written to for data / addr purposes, the latch is reset
-- to all ones. Process main is in charge of all writes to the memory.
-- The following signal is used by get_pmem to indicate the reset:
SIGNAL p0_reset : std_logic;
-- Handshaking signal controlled by main to acknowledge above reset
SIGNAL p0_reset_ack : std_logic;
-- Denotes bad data read at s1p1 which could be an opcode
SIGNAL bad_data : std_logic;
-- Two signals that are used to resolve ale (from get_pmem and main)
SIGNAL ale_pm, ale_dm : std_logic;
-- Internal signals for port3 special functions
SIGNAL wr_n_internal, rd_n_internal,
rxd_internal, txd_internal,
int0_n_internal, int1_n_internal,
t0_internal, t1_internal : std_logic := '1';
-- the sbuf reg. maintained by the serial driver
SIGNAL sbuf_dup : bvec;
SIGNAL p2clk : std_logic; -- used by uart, high for any s?p2
SIGNAL addr_gb, data_gb : bvec;
SIGNAL wr_gb, rd_gb : std_logic := '0';
SIGNAL acknow : std_logic;
SIGNAL scon_out : bvec;
ALIAS trans_int : std_logic IS scon_out(1);
ALIAS recv_int : std_logic IS scon_out(0);
SIGNAL timer1H : unsigned(7 DOWNTO 0);
SIGNAL timer1_int : std_logic := '0';
SIGNAL timer0_int : std_logic := '0';
SIGNAL interrupt_ack : std_logic := '0';
-- acknowledges one of the external interrupts - used for
-- edge sensitive mode to reset the signal and wait for a
-- new edge (edge sensitive based on IT0 and IT1 bits in TCON)
SIGNAL current_priority : std_logic_vector(1 DOWNTO 0) := "00";
-- the current priority of the processor - used to determine
-- if a 'higher' priority interrupt is indeed higher
-- "00" lowest priority - any interrupt accepted
-- "01" low priority - only high priority interrupts accepted
-- "11" high priority - no interrupts accepted
-- note, IE is also used to mask interrupts
SIGNAL previous_priority : std_logic_vector(1 DOWNTO 0) := "00";
------------------------------------------------------------------------
BEGIN -- architecture
--===============================================================
-- Concurrent Signal Assignments
--===============================================================
-- Strobe ale high whenever program or data memory requires it.
ale <= '1' WHEN ale_pm = '1' OR ale_dm = '1' ELSE '0';
-- Put a weak low on control lines, so that a 1 write will pull high
p0_ctrl <= 'L'; p2_ctrl <= 'L';
p3_ctrl <= "LLLLLLLL";
-- assign a high impedance version of the latch (either L or H)
-- on any falling edge
P0 <= std_logic_vector(to_high_imped(p0_latch))
WHEN cycle_state=s1p1 AND falling_edge(xtal1) ELSE UNAFFECTED;
P1 <= std_logic_vector(to_high_imped(p1_latch))
WHEN cycle_state=s1p1 AND falling_edge(xtal1) ELSE UNAFFECTED;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -