⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mc8051.vhd

📁 8051 vhdl source code
💻 VHD
📖 第 1 页 / 共 5 页
字号:
    -- 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 TF1_t1, TF0_t0: std_ulogic := '0';    SIGNAL TF1, TF0, TF1_main, TF0_main, TF1_t0m3: std_ulogic := '0';        SIGNAL t0_in, t1_in: std_logic := '1';        SIGNAL TH1, TL1, TH0, TL0 : bvec := "00000000";    SIGNAL TH1_main, TL1_main, TH0_main, TL0_main: bvec := "00000000";    SIGNAL TH1_t1, TL1_t1, TH0_t0, TL0_t0: bvec := "00000000";    SIGNAL TH0_t0m3: bvec := "00000000";        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";	-- resolve2 resolves two signals into one	-- Used for SFRs written to by processes other than main	PROCEDURE resolve2 (signal first, second: in bvec; 	   -- This transaction stuff is a hack to make the procedure fire	                    signal first_trans, second_trans: in bit;	                    signal output: out bvec) IS	BEGIN	   if second'active then	      output <= second;	   end if;	   if first'active then	      output <= first;	   end if;	END PROCEDURE resolve2;	PROCEDURE resolve2 (signal first, second: in std_ulogic;	   -- This transaction stuff is a hack to make the procedure fire	                    signal first_trans, second_trans: in bit;	                    signal output: out std_ulogic) IS	BEGIN	   if second'active then	      output <= second;	   end if;	   if first'active then	      output <= first;	   end if;	END PROCEDURE resolve2;------------------------------------------------------------------------BEGIN -- architecture    --===============================================================    --    Concurrent Signal Assignments    --===============================================================     -- Strobe ale high whenever program or data memory requires it.    ale <= 'Z' WHEN rst = '1' ELSE           '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';    -- assign a high impedance version of the latch (either L or H)    -- on any falling edge    -- when the ctrl is asserted (by get_pmem or main) then    -- force the addr/data value out the port    P0    <= (OTHERS => 'Z')             WHEN rst = '1' ELSE               std_logic_vector(p0_addr)  WHEN p0_ctrl = '1' ELSE               std_logic_vector(to_high_imped(p0_latch))               WHEN cycle_state=s1p1 AND falling_edge(xtal1) ELSE UNAFFECTED;    P1    <= (OTHERS => 'Z') WHEN rst = '1' ELSE               std_logic_vector(to_high_imped(p1_latch))               WHEN cycle_state=s1p1 AND falling_edge(xtal1) ELSE UNAFFECTED;    P2    <= (OTHERS => 'Z')             WHEN rst = '1' ELSE               std_logic_vector(p2_addr)  WHEN p2_ctrl = '1' ELSE              std_logic_vector(to_high_imped(p2_latch))               WHEN cycle_state=s1p1 AND falling_edge(xtal1) ELSE UNAFFECTED;    P3    <= (OTHERS => 'Z') WHEN rst = '1' ELSE               std_logic_vector(to_high_imped(p3_resolved));    -- Update the latch output at s1p1    p3_latch <= direct_hi_dmem(16#B0#)                WHEN cycle_state=s1p1 AND falling_edge(xtal1) ELSE UNAFFECTED;    -- Handle P3 special functions    p3_resolved(7) <= rd_n_internal WHEN p3_latch(7) = '1' ELSE p3_latch(7);    p3_resolved(6) <= wr_n_internal WHEN p3_latch(6) = '1' ELSE p3_latch(6);    p3_resolved(5 downto 2) <= p3_latch(5 downto 2);    p3_resolved(1) <= txd_internal WHEN p3_latch(1) = '1' ELSE p3_latch(1);    p3_resolved(0) <= p3_latch(0);    rxd_internal <= P3(0);    -- whenever there is a falling edge on the interrupt pin, it will    -- be sent to the interrupt processor (which may acknowledge or mask)    -- for a level sensitive interrupt (it? = 0) the rising edge of the pin    -- will clear out this internal signal.  For an edge sensitive interrupt    -- (it? = 1) the acknowledge from the interrupt processor will clear    int0_n_internal <= '0' WHEN falling_edge(P3(2)) ELSE                       '0' WHEN P3(2) = '0' and it0 = '0' ELSE                       '1' WHEN rising_edge(P3(2)) AND it0 = '0' ELSE                       '1' WHEN interrupt_ack = '1' AND it0 = '1' ELSE                       int0_n_internal;    int1_n_internal <= '0' WHEN falling_edge(P3(3)) ELSE                       '0' WHEN P3(3) = '0' and it1 = '0' ELSE                       '1' WHEN rising_edge(P3(3)) AND it1 = '0' ELSE                       '1' WHEN interrupt_ack = '1' AND it1 = '1' ELSE                       int1_n_internal;    t0_internal <= P3(4);    t1_internal <= P3(5);     --===============================================================    --    Process Statements    --===============================================================    ------------------------------------------------------------------------    -- The oscillator process will follow the XTAL clock signal and    -- advance the current state.  The states are s1p1, s1p2, s2p1, s2p2,    -- up to s6p1 and s6p2.    ------------------------------------------------------------------------    oscillator : PROCESS (XTAL1) IS        VARIABLE last_falling_edge_time : TIME    := 0 ns;        VARIABLE startup_count          : INTEGER := 0;    BEGIN        IF falling_edge(XTAL1) THEN            IF startup_count < 3 THEN                cycle_state <= init;                startup_count := startup_count + 1;                last_falling_edge_time := NOW;            ELSE                cycle_state <= inc(cycle_state);  -- increment the current state,                -- and loop back from s6p2 to s1p1                TCLCL <= NOW - last_falling_edge_time;                last_falling_edge_time := NOW;            END IF;        END IF;    END PROCESS oscillator;     ------------------------------------------------------------------------    -- The process get_pmem is responsible for reading all of the program    -- memory (whetere internal or external) and feeding the read bytes to    -- the process main through the signals pmem_s1_byte and pmem_s4_byte.    -- If there has been a transaction on pc, this process will set    -- its internal addr to the value of pc at state s4p1.  Then, if needed,    -- it will output this addr at s5p1 and then read in the appropriate data    -- at s1p1.  Then it increments its internal addr and will read the next    -- byte at s4p1.  It will continue to increment the internal addr until    -- there is another transaction on pc.    -------------------------------------------------------------------------    get_pmem : PROCESS(cycle_state, pc'TRANSACTION) IS        VARIABLE addr        : INTEGER := 0;        VARIABLE pmem        : program_mem_T;     -- the program memory        VARIABLE prog_loaded : BOOLEAN := FALSE;  -- true after pmem is updated        VARIABLE resync      : BOOLEAN := FALSE;  -- set true when pc changes        VARIABLE port_to_01  : bit_vector(7 DOWNTO 0);     BEGIN        -- Put lines at HiZ if the processor is in reset state        IF rst = '1' THEN            psen_n <= 'Z';            ale_pm <= 'Z';            p0_ctrl <= 'Z';            p2_ctrl <= 'Z';            p0_addr <= "ZZZZZZZZ";            p2_addr <= "ZZZZZZZZ";        ELSIF NOT prog_loaded THEN            IF (ea_n = '1' or ea_n = 'H') THEN                load_program(program_filename,pmem);            END IF;            -- Set default values for control lines            psen_n <= '1';            p0_ctrl <= 'Z';            p2_ctrl <= 'Z';            p0_reset <= '0';            prog_loaded := TRUE;        ELSE            -- If process main has acknowledged a reset, then            -- clear the p0 reset line.            IF p0_reset_ack <= '1' THEN                p0_reset <= '0';            END IF;            -- If there has been a transaction on pc, and it is            -- not the initial start-up state, then flag the            -- resync variable            IF pc'ACTIVE THEN                resync := TRUE;            END IF;            -- If the process main is trying to read a data byte            -- from external mem, yield to it by putting ctrl's            -- to high impedance            IF port_req = '1' THEN                p0_ctrl <= 'Z';                p2_ctrl <= 'Z';                p0_addr <= "ZZZZZZZZ";                p2_addr <= "ZZZZZZZZ";                ale_pm <= '0';                psen_n <= '1';            ELSIF reset_pmem = '1' THEN                resync := TRUE;                addr := 0;            ELSIF cycle_state'ACTIVE THEN                CASE cycle_state IS                WHEN init =>                    NULL;                WHEN s1p1 =>                -- read in the current byte from pmem                    IF ( addr > 16#0FFF#) OR (ea_n = '0') OR (ea_n = 'L') THEN                        IF Is_X(P0) THEN                           pmem_s1_byte <= unsigned'("00000000");                            bad_data <= '1';                        ELSE                           port_to_01 := to_bitVector(P0);                           pmem_s1_byte <= unsigned(to_stdlogicvector(port_to_01));                           bad_data <= '0';                        END IF;                    ELSE -- fetch from internal memory                        pmem_s1_byte <= pmem(addr);                    END IF;                WHEN s4p1 =>                -- read in the current byte from pmem                    IF ( addr >= 16#0FFF#) OR (ea_n = '0') OR (ea_n = 'L') THEN                        port_to_01 := to_bitVector(P0);                        pmem_s4_byte <= unsigned(to_stdlogicvector(port_to_01));                    ELSE -- fetch from internal memory                        pmem_s4_byte <= pmem(addr);                    END IF;                WHEN s1p2 | s4p2 =>                    IF resync THEN                        addr := conv_integer(pc);                        resync := FALSE;                    ELSE                        addr := addr + 1;                    END IF;                    -- strobe ale if next addr is external                    -- rewrite p0_latch to all 1's                    IF ( addr >= 16#0FFF#) OR (ea_n = '0') OR (ea_n = 'L') THEN                        ale_pm <= '1';                        psen_n <= '1';                        p0_reset <= '1';                    END IF;                WHEN s2p1 | s5p1 =>                -- drive port 0 and port 2 if addr is external                    IF ( addr >= 16#0FFF#) OR (ea_n = '0') OR (ea_n = 'L') THEN                        p0_addr <= conv_unsigned(addr MOD 256, 8);                        p2_addr <= conv_unsigned(addr / 256, 8);                        p0_ctrl <= '1';                        p2_ctrl <= '1';                    ELSE                        p0_ctrl <= 'Z';                        p2_ctrl <= 'Z';                    END IF;                WHEN s2p2 | s5p2 =>  -- drive ale to zero                    IF ( addr >= 16#0FFF#) OR (ea_n = '0') OR (ea_n = 'L') THEN                        ale_pm <= '0';                    END IF;                WHEN s3p1 | s6p1 => -- drive psen low                    IF ( addr >= 16#0FFF#) OR (ea_n = '0') OR (ea_n = 'L') THEN                        psen_n <= '0';                        p0_addr <= "ZZZZZZZZ";                    END IF;                WHEN s3p2  | s6p2 =>                    NULL;                END CASE;            END IF;        END IF; 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -