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

📄 uart.vhd

📁 這是Originl公司出的8051 VHDL source code.
💻 VHD
📖 第 1 页 / 共 2 页
字号:
-- EE301B Semester Project, Winter 1998-- 8051 UART (Universal Asynchronous Receiver/Transmitter) model-- Source : Intel 8051 Family Microprocessors Manual-- Author : Lingfeng Yuan, Prajakta Kurvey-- Revision history:-- 04/05-- Started writing the code for the UART-- 04/08-- implemented the transmission and reception of mode 0 and 1-- still a lot of errors and assumptions-- 04/09-- finished mode 2 and 3-- looks correct except for the assumptions-- 19/09-- changed the divide-by-16 counters-- 23/09-- changed the transmitter and receiver processes to be sentitive to a list-- eliminated all wait statements in them-- eliminated all bus contention problems-- package to define some typeslibrary ieee;use ieee.std_logic_1164.all;use ieee.std_logic_arith.all;package mc8051_UART_pkg is  subtype byte is unsigned (7 downto 0);  constant sbuf_addr : byte := "10011001";  constant scon_addr : byte := "10011000";  constant all_0 : byte := "00000000";  constant hi_imp : byte := "ZZZZZZZZ";-- the following type is used to break up the machine cycle-- into 6 states, with 2 pulses for each state-- copied from Mayer's program--  type machine_cycle_states is (init, s1p1, s1p2, s2p1, s2p2, s3p1, s3p2,--s4p1, s4p2, s5p1, s5p2, s6p1, s6p2);end mc8051_UART_pkg;-- main program for the UARTlibrary ieee;use ieee.std_logic_1164.all;use ieee.std_logic_arith.all;use work.mc8051_UART_pkg.all;use work.pack8051.all;-- these are the interface signals for our stand-alone UARTentity mc8051_UART is  port (        cycle_state : in machine_cycle_states;        p2clk : in std_logic;           -- phase 2 clock        addr_gb : in byte;              -- global address bus        data_gb : inout byte := hi_imp; -- global data bus        rd_gb : in std_logic;           -- global read signal, active high        wr_gb : in std_logic;           -- global write signal, active high        indirect_sel : in std_logic;    -- direct or indirect address mode        tf1 : in std_logic := '0';      -- tf1 is the timer 1 overflow flag        smod : in std_logic := '0';     -- smod is pcon.7        scon_out : out byte;                 -- serial port control SFR        sbuf_out : out byte;        rxd : inout std_logic := 'H';        txd : out std_logic := '1';        acknow : out std_logic := 'L');end entity;architecture behave of mc8051_UART issignal to_send, write_to_sbuf : std_logic := '0';-- serial control - should it be all_0 at default?signal scon     : unsigned(7 DOWNTO 0) := (OTHERS => '0');signal tb8_set, tb8_reset : std_logic := '0';signal rb8_set, rb8_reset : std_logic := '0';signal ti_set, ri_set : std_logic := '0';-- some aliases to decompose scon-- sm_r is reversed serial port mode  OR IS IT? -MRMalias sm_r : unsigned (2 downto 0) is scon(7 downto 5);alias ren : std_logic is scon(4);alias tb8 : std_logic is scon(3);alias rb8 : std_logic is scon(2);alias ti : std_logic is scon(1);alias ri : std_logic is scon(0);-- serial port bufferssignal sbuf_wr, sbuf_rd : byte := all_0;-- divide-by-16 counters and their reset signals (rising edge sensitive)-- tf1_16 is for timer 1 overflow signal-- p2clk_16 is for phase 2 clocksubtype cnt_type is natural range 0 to 16;signal tf1_16, rf1_16, p2clk_16 : cnt_type := 0;signal tf1_16_reset, rf1_16_reset, p2clk_16_reset : std_logic := '0';signal acknow_wr, acknow_rd : std_logic := 'L';signal txd_wr, txd_rd : std_logic := '1';beginsbuf_out <= sbuf_rd;scon_out <= scon;-- process to detect write_to_sbuf operation-- we still need to verify the timing of the execution of the instructionprocess beginwait until wr_gb = '1';if addr_gb = sbuf_addr and indirect_sel = '0' then      -- CPU writes to serial port  sbuf_wr <= data_gb;  to_send <= not to_send;  wait for 2 ns;  acknow_wr <= '1';  wait until to_x01(wr_gb) = '0';  acknow_wr <= 'L';end if;end process;-- process to detect write_to_scon operation-- we still need to verify the timing of the execution of the instructionPROCESS BEGINIF tb8_set = '1' THEN   scon(3) <= '1';END IF;IF tb8_reset = '1' THEN   scon(3) <= '0';END IF;IF rb8_set = '1' THEN   scon(2) <= '1';END IF;IF rb8_reset = '1' THEN   scon(2) <= '1';END IF;IF ti_set = '1' THEN   scon(1) <= '1';END IF;If ri_set = '1' THEN   scon(0) <= '1';END IF;IF wr_gb = '1' THEN  IF addr_gb = scon_addr and indirect_sel = '0' THEN    -- CPU writes to serial port     scon <= data_gb;     wait for 2 ns;     acknow_wr <= '1';     wait until to_x01(wr_gb) = '0';     acknow_wr <= 'L';  END IF;END IF;WAIT ON tb8_set, tb8_reset, rb8_set, rb8_reset, ti_set, ri_set, wr_gb;--WAIT ON ti_set, ri_set, wr_gb;END PROCESS;-- we assume that the write_to_sbuf pulse always occurs in s6p2-- process to align to_send with s6p2 and convert it to a pulseprocess begin  wait on to_send;  wait until cycle_state = s6p2;  write_to_sbuf <= '1';  -- wait for a cycle state  wait on cycle_state;  write_to_sbuf <= '0';end process;-- process to detect read_from_sbuf operation-- we still need to verify the timing of the execution of the instructionprocess beginwait until rd_gb = '1';if addr_gb = sbuf_addr and indirect_sel = '0' then      -- CPU reads from serial port  data_gb <= sbuf_rd;  acknow_rd <= '1';  wait until rd_gb = '0';  data_gb <= hi_imp;  acknow_rd <= 'L';end if;end process;-- process to detect read_from_scon operation-- we still need to verify the timing of the execution of the instructionprocess beginwait until rd_gb = '1';if addr_gb = scon_addr and indirect_sel = '0' then      -- CPU reads from serial control  data_gb <= scon;  acknow_rd <= '1';  wait until rd_gb = '0';  data_gb <= hi_imp;  acknow_rd <= 'L';end if;end process;-- process to resolve acknow_wr and acknow_rd to get acknowacknow <= acknow_wr or acknow_rd;-- transmitter process-- initiated by rising edge of write_to_sbuf generated when CPU writes to sbufprocess (sm_r(2 downto 1), write_to_sbuf, cycle_state, tf1_16, p2clk_16)variable i : integer := 0;              -- iteration countervariable sbuf_dup : byte := all_0;      -- internal buffer for sbufvariable to_send, no_start : bit := '0';begin-- if sm_r(2 downto 1) is changed, clear the current processif sm_r(2 downto 1)'event then to_send := '0'; end if;if rising_edge(write_to_sbuf) then      -- initiate transmission  to_send := '1';       -- this signal means transmission in progress  sbuf_dup := sbuf_wr;  -- fill internal buffer  i := 0;               -- clear iteration counter  no_start := '1';      -- still in the write_to_sbuf cycle, don't start  ti_set <= '0';        -- lower the ti_set signal to create an edge laterend if;if to_send = '1' then-- sm_r is reversed sm-- so mode 1 is "10", mode 2 is "01"   OR IS IT? -MRM  case sm_r(2 downto 1) is  when "00" =>    -- mode 0, 8-bit shift register, Fxtal1/12 (one bit every machine cycle)    -- shift clock is output through txd    -- shift clock is low during s3, s4, s5, high during s6, s1, s2    -- actual data is output through rxd    if cycle_state'event then      case cycle_state is        when s1p1 => if i = 0 then no_start := '0';     -- start iteration                     elsif i = 9 then                   -- time to stop                        rxd <= 'H';                        ti_set <= '1';                        to_send := '0';                     end if;        when s3p1 => if i /= 0 then txd_wr <= '0'; end if;        when s6p1 => if i /= 0 then txd_wr <= '1'; end if;        when s6p2 => if no_start = '0' then                        if i < 8 then rxd <= sbuf_dup(i); end if;                        i := i + 1;                     end if;        when others => null;      end case;    end if;  when "01" =>    -- mode 1, 8-bit UART, baud rate set by timer 1    -- assumes that shift happens at the rollovers    if tf1_16'event and tf1_16 = 0 then      case i is        when 0 => txd_wr <= '0';        -- start bit        when 9 => txd_wr <= '1';        -- 9th bit ('1')                  -- not sure when ti goes high, 9 or 10                  ti_set <= '1';        when 10 => null;                -- stop bit, keep high        when 11 => to_send := '0';      -- time to stop        when others => txd_wr <= sbuf_dup(i-1);         -- shift the byte out      end case;      i := i + 1;    end if;  when "10" =>    -- mode 2, 9-bit UART, Fxtal1/64 or Fxtal1/32    -- assumes that shift happens at the rollovers    if p2clk_16'event and p2clk_16 = 0 then      case i is        when 0 => txd_wr <= '0';        -- start bit        when 9 => txd_wr <= tb8;        -- 9th bit        when 10 => txd_wr <= '1';       -- stop bit                   ti_set <= '1';        when 11 => to_send := '0';      -- time to stop        when others => txd_wr <= sbuf_dup(i-1);         -- shift the byte out      end case;      i := i+1;    end if;  when "11" =>    -- mode 3, 9-bit UART, baud rate set by timer 1

⌨️ 快捷键说明

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