- 苏萦
-
UART通信
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity UART is --通用异步串行收发器实体
Port ( UART_clk : in STD_LOGIC; --收发器时钟输入,50MHz
UART_rst : in std_logic;
UART_TX_buf : in STD_LOGIC_VECTOR(7 downto 0);
UART_TX_TI : out std_logic;
UART_TX_EN : in std_logic;
UART_TXD : out std_logic;
UART_baudrate : out STD_LOGIC); --收发器波特率输出19200的14倍频(测试完成后可以取消)
end UART;
architecture Behavioral of UART is
signal baudrate_counter :std_logic_vector(6 downto 0):="0000000"; --波特率发生器分频计数器
signal baudrate_out :std_logic:="0"; --波特率发生器波特率信号
signal TX_clk : std_logic:="0";
signal tx_clk_counter : std_logic_vector(3 downto 0) :="0000";
type TX_STATE is (TX_idle,TX_transfer);
signal TX_current_state,TX_next_state : Tx_state;
signal TX_buf_shift : std_logic_vector(9 downto 0):= "0111111111";
signal TX_counter :std_logic_vector(3 downto 0):="0000";
signal TX_start : std_logic:="0";
signal TXD_buf: std_logic:="0";
signal TX_TI : std_logic:="1";
begin
baudrate: process (UART_clk) --波特率发生器进程
begin
if rising_edge(UART_clk) then --对输入时钟进行分频获得所需波特率的14倍频
if (baudrate_counter >= "1011100") then
baudrate_counter <= "0000000";
baudrate_out <= not baudrate_out;
else
baudrate_counter <= baudrate_counter + "1";
baudrate_out <= baudrate_out;
end if;
end if;
end process;
UART_baudrate <= baudrate_out; --将波特率信号传给输出接口
sync_proc_tx: process(baudrate_out,UART_rst) --同步进程,状态机转换
begin
if (UART_rst = "1") then
tx_current_state <= tx_idle;
elsif (falling_edge(baudrate_out)) then
tx_current_state <= TX_next_state;
end if;
end process;
comb_proc_tx: process(baudrate_out,UART_rst) --组合逻辑,状态机转换、输出
begin
if (UART_rst = "1") then
TX_next_state <= TX_idle;
TX_counter <= "0000";
TXD_buf <= "1";
TX_start <= "0";
TX_TI <= "1";
TX_clk_counter <= "0000";
TX_buf_shift <= "1111111111";
elsif (rising_edge(baudrate_out)) then
case TX_current_state is
when TX_idle =>
if (UART_TX_EN = "1" and TX_TI = "1") then --如果满足发送起始条件
TX_next_state <= TX_transfer; --转换下一状态到发送
TX_counter <= "1010"; --发送bit计数器置数,发送10个bit,8bit数据加上开始结束位
TXD_buf <= "1"; --发送寄存器发送‘1"
TX_start <= "1"; --发送过程标志
TX_TI <= "0"; --发送进行中标志,表示发送器不可用
TX_clk_counter <= "1101"; --分频计数器置数
TX_buf_shift <= "1" & UART_TX_buf & "0"; --寄存器保存数据与开始结束位
else
TX_next_state <= TX_idle;
TX_counter <= "0000";
TXD_buf <= "1";
TX_start <= "0";
TX_TI <= "1";
TX_clk_counter <= "0000";
TX_buf_shift <= "1111111111";
end if;
when TX_transfer =>
if (TX_start = "1" and TX_TI = "0" and TX_counter /= "0000") then --进入正常发送状态
if (TX_clk_counter >= "1101") then --如果分频完成
TX_next_state <= TX_transfer; --没有发送完成,继续进入发送状态
TX_counter <= TX_counter - "1"; --发送bit计数器自减
TXD_buf <= TX_buf_shift(0); --发送数据
TX_start <= "1"; --发送过程标志继续允许
TX_TI <= "0"; --发送器不允许使用
TX_clk_counter <= "0000"; --分频计数器清灵,继续下一次
TX_buf_shift <= "1" & TX_buf_shift(9 downto 1); --数据移位
else
TX_next_state <= TX_transfer;
TX_counter <= TX_counter;
TXD_buf <= TXD_buf;
TX_start <= "1";
TX_TI <= "0";
TX_clk_counter <= TX_clk_counter + "1";
TX_buf_shift <= TX_buf_shift;
end if;
else
TX_next_state <= TX_idle;
TX_counter <= "0000";
TXD_buf <= "1";
TX_start <= "0";
TX_TI <= "1";
TX_clk_counter <= "0000";
TX_buf_shift <= "1111111111";
end if;
when others =>
TX_next_state <= TX_idle;
TX_counter <= "0000";
TXD_buf <= "1";
TX_start <= "0";
TX_TI <= "1";
TX_clk_counter <= "0000";
TX_buf_shift <= "1111111111";
end case;
end if;
end process;
UART_TXD <= TXD_buf;
UART_TX_TI <= TX_TI;
end Behavioral;
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity transmitter is
port(cs,clk,rx:in std_logic;
indata:in std_logic_vector(7 downto 0);
txd,ti:out std_logic);
end transmitter;
architecture tr1 of transmitter is
signal sig_count:std_logic_vector(3 downto 0);
signal sig_ti,sig_ti1,sig_txd,sig_buffer:std_logic;
signal sig_data:std_logic_vector(7 downto 0);
signal sig_txddata:std_logic_vector(9 downto 0);
begin
process(cs,clk,rx)
begin
if(clk"event and clk="1")then
if(cs="0")then
if(sig_buffer="0")then
if(rx="0")then
for i in 8 downto 1 loop
sig_txddata(i)<=indata(i-1);
end loop;
sig_txddata(9)<="0"; --加起始位
sig_data<=indata;
sig_buffer<="1";
end if;
else
for i in 9 downto 1 loop
sig_txddata(i)<=sig_txddata(i-1);
end loop;
sig_txd<=sig_txddata(9);
sig_txddata(0)<="1"; --加停止位
if(sig_count="1000")then
sig_count<="0000";
elsif(sig_count="0000"and sig_ti="1")then
sig_buffer<="0";
sig_ti<="0";
else
sig_count<=sig_count+"1";
sig_ti<="1";
end if;
end if;
end if;
end if;
end process;
process
begin
if(sig_ti="0")then
txd<="1";
else txd<=sig_txd;
end if;
end process;
ti<=not sig_ti;
end tr1;