📄 uart.vhd
字号:
--**********************************************************************************************
-- UART Peripheral for the AVR Core
-- Version 0.4
-- Modified 18.12.2002
-- Designed by Ruslan Lepetenok
--**********************************************************************************************
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
use WORK.AVRuCPackage.all;
entity uart is port(
-- AVR Control
ireset : in std_logic;
cp2 : in std_logic;
adr : in std_logic_vector(5 downto 0);
dbus_in : in std_logic_vector(7 downto 0);
dbus_out : out std_logic_vector(7 downto 0);
iore : in std_logic;
iowe : in std_logic;
out_en : out std_logic;
--UART
rxd : in std_logic;
rx_en : out std_logic;
txd : out std_logic;
tx_en : out std_logic;
--IRQ
txcirq : out std_logic;
txc_irqack : in std_logic;
udreirq : out std_logic;
rxcirq : out std_logic);
end uart;
architecture rtl of uart is
signal UDR_Tx: std_logic_vector(7 downto 0) := (others => '0');
signal UDR_Rx: std_logic_vector(7 downto 0) := (others => '0');
signal UBRR : std_logic_vector(7 downto 0) := (others => '0');
-- USR Bits
signal USR : std_logic_vector(7 downto 0) := (5=>'1',others => '0');
signal USR_Wr_En : std_logic := '0';
alias RXC : std_logic is USR(7);
alias TXC : std_logic is USR(6);
alias UDRE : std_logic is USR(5);
alias FE : std_logic is USR(4);
alias DOR : std_logic is USR(3); -- OR in Atmel documents
-- UCR Bits
signal UCR : std_logic_vector(7 downto 0) := (others => '0');
signal UCR_Wr_En : std_logic := '0';
alias RXCIE : std_logic is UCR(7);
alias TXCIE : std_logic is UCR(6);
alias UDRIE : std_logic is UCR(5);
alias RXEN : std_logic is UCR(4);
alias TXEN : std_logic is UCR(3);
alias CHR9 : std_logic is UCR(2);
alias RXB8 : std_logic is UCR(1);
alias TXB8 : std_logic is UCR(0);
signal CHR9_Latched : std_logic := '0';
signal TXB8_Latched : std_logic := '0';
-- Common internal signals
signal UART_Clk_En : std_logic := '0';
-- Internal signals for transmitter
signal SR_Tx : std_logic_vector (7 downto 0):= (others => '0'); -- UART transmit shift register
signal SR_Tx_In : std_logic_vector (7 downto 0):= (others => '0');
signal Tx_In : std_logic :='0';
-- Transmitter state machine
signal nUART_Tr_St0 : std_logic :='0';
signal UART_Tr_St1 : std_logic :='0';
signal UART_Tr_St2 : std_logic :='0';
signal UART_Tr_St3 : std_logic :='0';
signal UART_Tr_St4 : std_logic :='0';
signal UART_Tr_St5 : std_logic :='0';
signal UART_Tr_St6 : std_logic :='0';
signal UART_Tr_St7 : std_logic :='0';
signal UART_Tr_St8 : std_logic :='0';
signal UART_Tr_St9 : std_logic :='0';
signal UART_Tr_St10 : std_logic :='0';
signal UART_Tr_St11 : std_logic :='0';
signal Flag_A : std_logic :='0';
signal Flag_B : std_logic :='0';
signal UDR_Wr_En : std_logic :='0';
signal UDR_Rd : std_logic :='0';
signal USR_Rd : std_logic :='0';
signal UCR_Rd : std_logic :='0';
signal UBRR_Rd : std_logic :='0';
-- Frequence divider signals
signal Div16_Cnt : std_logic_vector (3 downto 0) := (others => '0');
signal Div16_In : std_logic_vector (Div16_Cnt'range):= (others => '0'); -- Counter Input
signal Div16_Eq : std_logic :='0'; -- Combinatorial output of the comparator
-- Baud generator signals
signal UBRR_Wr_En : std_logic :='0';
signal Baud_Gen_Cnt: std_logic_vector (7 downto 0):= (others => '0'); -- Counter
signal Baud_Gen_In : std_logic_vector (Baud_Gen_Cnt'range):= (others => '0'); -- Counter Input
signal Baud_Gen_Eq : std_logic :='0'; -- Combinatorial output of the comparator
signal Baud_Gen_Out: std_logic :='0';
-- Receiver signals
signal nUART_RcDel_St0 : std_logic :='0';
signal UART_RcDel_St1 : std_logic :='0';
signal UART_RcDel_St2 : std_logic :='0';
signal UART_RcDel_St3 : std_logic :='0';
signal UART_RcDel_St4 : std_logic :='0';
signal UART_RcDel_St5 : std_logic :='0';
signal UART_RcDel_St6 : std_logic :='0';
signal UART_RcDel_St7 : std_logic :='0';
signal UART_RcDel_St8 : std_logic :='0';
signal UART_RcDel_St9 : std_logic :='0';
signal UART_RcDel_St10 : std_logic :='0';
signal UART_RcDel_St11 : std_logic :='0';
signal UART_RcDel_St12 : std_logic :='0';
signal UART_RcDel_St13 : std_logic :='0';
signal UART_RcDel_St14 : std_logic :='0';
signal UART_RcDel_St15 : std_logic :='0';
signal UART_RcDel_St16 : std_logic :='0';
signal nUART_Rc_St0 : std_logic :='0';
signal UART_Rc_St1 : std_logic :='0';
signal UART_Rc_St2 : std_logic :='0';
signal UART_Rc_St3 : std_logic :='0';
signal UART_Rc_St4 : std_logic :='0';
signal UART_Rc_St5 : std_logic :='0';
signal UART_Rc_St6 : std_logic :='0';
signal UART_Rc_St7 : std_logic :='0';
signal UART_Rc_St8 : std_logic :='0';
signal UART_Rc_St9 : std_logic :='0';
signal UART_Rc_St10 : std_logic :='0';
signal RXD_ResyncA : std_logic :='1';
signal RXD_ResyncB : std_logic :='1';
signal Detector_Out : std_logic :='0';
signal Detector_A : std_logic :='0';
signal Detector_B : std_logic :='0';
signal UART_Rc_SR : std_logic_vector(9 downto 0) := (others => '0');
signal UART_Rc_SR7_In : std_logic :='0';
signal UART_Rc_Delay : std_logic :='0';
begin
-- Baud generator (First divider)
Baud_Generator :process(cp2,ireset)
begin
if (ireset='0') then -- Reset
Baud_Gen_Cnt <= (others => '0');
Baud_Gen_Out <= '0';
elsif (cp2='1' and cp2'event) then -- Clock
Baud_Gen_Cnt <= Baud_Gen_In;
Baud_Gen_Out <= Baud_Gen_Eq;
end if;
end process;
Baud_Gen_Eq <= '1' when UBRR=Baud_Gen_Cnt else '0';
Baud_Gen_In <= Baud_Gen_Cnt+1 when Baud_Gen_Eq='0' else (others=>'0');
--Divide by 16 (Second divider)
Divide_By_16:process(cp2,ireset)
begin
if (ireset='0') then -- Reset
Div16_Cnt <= (others => '0');
-- UART_Clk_En <= '0';
elsif (cp2='1' and cp2'event) then -- Clock
if Baud_Gen_Out='1' then -- Clock enable
Div16_Cnt <= Div16_In;
-- UART_Clk_En <= Div16_Eq;
end if;
end if;
end process;
Div16_Eq <= '1' when Div16_Cnt="1111" else '0';
Div16_In <= Div16_Cnt+1 when Div16_Eq='0' else (others=>'0');
Global_Clock_Enable:process(cp2,ireset)
begin
if (ireset='0') then -- Reset
UART_Clk_En <= '0';
elsif (cp2='1' and cp2'event) then -- Clock
UART_Clk_En <= Div16_Eq and Baud_Gen_Out;
end if;
end process;
-- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-- UBRR
UBRR_Wr_En <= '1' when (adr=UBRR_Address and iowe='1') else '0'; -- UBRR write enable
UBRR_Load:process(cp2,ireset)
begin
if ireset='0' then -- Reset
UBRR <= ( others => '0');
elsif (cp2='1' and cp2'event) then -- Clock
if UBRR_Wr_En='1' then -- Clock enable
UBRR <= dbus_in;
end if;
end if;
end process;
UDR_Rd <= '1' when (adr=UDR_Address and iore='1') else '0'; -- UDR read enable
-- UDR for transmitter
UDR_Wr_En <= '1' when (adr=UDR_Address and iowe='1' and TXEN ='1') else '0'; -- UDR write enable
UDR_Tx_Load:process(cp2,ireset)
begin
if ireset='0' then -- Reset
UDR_Tx <= ( others => '0');
CHR9_Latched <= '0';
TXB8_Latched <= '0';
elsif (cp2='1' and cp2'event) then -- Clock
if (UDR_Wr_En and (Flag_A or nUART_Tr_St0))='1' then -- Clock enable
UDR_Tx <= dbus_in;
CHR9_Latched <= CHR9;
TXB8_Latched <= TXB8;
end if;
end if;
end process;
-- Load flags
Load_Flags:process(cp2,ireset)
begin
if ireset='0' then -- Reset
Flag_A <= '0';
Flag_B <= '0';
elsif (cp2='1' and cp2'event) then -- Clock
Flag_A <= (not Flag_A and UDR_Wr_En and not nUART_Tr_St0)or
(Flag_A and not (UART_Tr_St1 and UART_Clk_En));
Flag_B <= (not Flag_B and (UDR_Wr_En and (Flag_A or nUART_Tr_St0)))or
(Flag_B and not (UART_Clk_En and UART_Tr_St11));
end if;
end process;
Transmitter_Shifter:for i in 6 downto 0 generate
SR_Tx_In(i) <= (dbus_in(i) and not Flag_A and not nUART_Tr_St0 and UDR_Wr_En)or -- Direct load from data bus
(UDR_Tx(i) and UART_Tr_St11)or -- Load from UDR(TX)
(SR_Tx(i+1) and nUART_Tr_St0 and not UART_Tr_St11); -- Shift
end generate;
SR_Tx_In(7) <= (dbus_in(7) and not Flag_A and not nUART_Tr_St0 and UDR_Wr_En)or -- Direct load from data bus
(UDR_Tx(7) and UART_Tr_St11)or -- Load from UDR(TX)
(TXB8_Latched and (UART_Tr_St2 and CHR9_Latched))or -- Shift first
('1' and not((not Flag_A and not nUART_Tr_St0 and UDR_Wr_En)or UART_Tr_St11 or(UART_Tr_St2 and CHR9_Latched))); -- All other cases
TX_In <= ('0' and UART_Tr_St1)or -- Start bit
(SR_Tx(0) and (nUART_Tr_St0 and not UART_Tr_St1))or -- Shift
('1' and not nUART_Tr_St0); -- Idle
-- Transmitter shift register
SR_Tx_Load_Sift:process(cp2,ireset)
begin
if (ireset='0') then -- Reset
SR_Tx <= ( others => '0');
elsif (cp2='1' and cp2'event) then -- Clock
if ((not Flag_A and not nUART_Tr_St0 and UDR_Wr_En)or(UART_Tr_St11 and UART_Clk_En)or (nUART_Tr_St0 and UART_Clk_En and not UART_Tr_St1))='1' then -- Clock enable
SR_Tx <= SR_Tx_In;
end if;
end if;
end process;
-- Transmitter output register
Tx_Out:process(cp2,ireset)
begin
if (ireset='0') then -- Reset
txd <= '1';
elsif (cp2='1' and cp2'event) then -- Clock
if (UART_Clk_En and (nUART_Tr_St0 or Flag_A))='1' then -- Clock enable
txd <= TX_In;
end if;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -