📄 uart.vhd
字号:
library IEEE;
use IEEE.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
entity UART is
port(
rst : in std_logic;--复位
clk1 : in std_logic;--发送模块工作时钟
clk16 : in std_logic;--接收模块工作时钟
rd : in std_logic;--MCU读UART
wr : in std_logic;--MCU写UART
cs : in std_logic;--UART片选
ad : in std_logic;--当前帧为地址帧还是数据帧 1--地址;0--数据
rxd : in std_logic;--串行接收
txd : out std_logic;--串行发送
ri : out std_logic;--为1表示接收到一帧
ti : out std_logic;--为1表示已经发送完一帧
err : out std_logic;--为一表示接收到一个错误帧
data : inout std_logic_vector(7 downto 0)--数据总线
);
end UART;
architecture behav of UART is
constant s0 :std_logic_vector(2 downto 0):= "001"; --就绪
constant s1 :std_logic_vector(2 downto 0):= "011"; --发送
constant s2 :std_logic_vector(2 downto 0):= "111"; --发送完成
constant s3 :std_logic_vector(2 downto 0):= "110"; --接收正确
constant s4 :std_logic_vector(2 downto 0):= "100"; --接收错误
constant address : std_logic_vector(7 downto 0):="00000001";--本片地址
constant close_all: std_logic_vector(7 downto 0):="11111111";--使所有从机的sm2置1
signal sst,ssr: std_logic_vector(2 downto 0);
signal txdcnt,rxdcnt,cnt: std_logic_vector(3 downto 0);
signal rbuf,tbuf: std_logic_vector(7 downto 0);
signal r_shift,t_shift: std_logic_vector(11 downto 0);
signal receive: std_logic;
signal over: std_logic_vector(1 downto 0);
signal sm2: std_logic :='1';
begin
process(rst,clk1) --状态转换
begin
if cs='0' then
if rst = '0' then
sst<=s0;
ssr<=s0;
elsif clk1'event and clk1 = '1' then
case sst is
when s0 =>
if wr='0' then
sst<=s1;
end if;
when s1 =>
if txdcnt=12 then
sst<=s2;
end if;
when s2 =>
sst<=s0;
when others =>
sst <= s0;
end case;
case ssr is
when s0 =>
if over="01" then
ssr<=s3;
elsif over="10" then
ssr<=s4;
end if;
when s3 =>
if rd='0' then
ssr<=s0;
elsif over="10" then
ssr<=s4;
end if;
when s4 =>
if rd='0' then
ssr<=s0;
end if;
when others =>
ssr<=s0;
end case;
end if;
end if;
end process;
process(rst,clk1)--串行发送
begin
if cs ='0' then
if rst = '0' then
txd<='1';
elsif clk1'event and clk1 = '1' then
if wr='0' then
t_shift(0)<='0';
t_shift(8 downto 1)<=tbuf;
t_shift(9)<=tbuf(0)xor tbuf(1)xor tbuf(2)xor tbuf(3)xor tbuf(4)xor tbuf(5)xor tbuf(6)xor tbuf(7);
t_shift(10)<=ad;
t_shift(11)<='1';
end if;
if sst = s1 then
txd <= t_shift(0);
t_shift(0)<=t_shift(1);
t_shift(1)<=t_shift(2);
t_shift(2)<=t_shift(3);
t_shift(3)<=t_shift(4);
t_shift(4)<=t_shift(5);
t_shift(5)<=t_shift(6);
t_shift(6)<=t_shift(7);
t_shift(7)<=t_shift(8);
t_shift(8)<=t_shift(9);
t_shift(9)<=t_shift(10);
t_shift(10)<=t_shift(11);
else txd<='1';
end if;
end if;
end if;
end process;
process(rst,clk1) --txd counter
begin
if cs ='0' then
if rst= '0' then
txdcnt<=(others =>'0');
elsif clk1'event and clk1='1' then
if sst=s1 then
if txdcnt=12 then
txdcnt<=(others=>'0');
else txdcnt<=txdcnt+1;
end if;
end if;
end if;
end if;
end process;
----------------------------------------------------------------
----------------------------------------------------------------
process(rst,clk16)
variable tem7,tem8 :std_logic;
begin
if cs ='0' then
if rst='0' then
tem7:='0';
tem8:='0';
r_shift<=(others=>'0');
elsif clk16'event and clk16='1' then
if cnt=7 then
tem7 :=rxd;
elsif cnt=8 then
tem8 :=rxd;
elsif cnt=9 then
r_shift(0)<=r_shift(1);
r_shift(1)<=r_shift(2);
r_shift(2)<=r_shift(3);
r_shift(3)<=r_shift(4);
r_shift(4)<=r_shift(5);
r_shift(5)<=r_shift(6);
r_shift(6)<=r_shift(7);
r_shift(7)<=r_shift(8);
r_shift(8)<=r_shift(9);
r_shift(9)<=r_shift(10);
r_shift(10)<=r_shift(11);
r_shift(11)<=(tem7 and tem8)or(tem7 and rxd)or(tem8 and rxd);
end if;
end if;
end if;
end process;
process(rst,clk16)--add cnt
begin
if cs ='0' then
if rst='0' then
cnt<=(others=>'0');
receive<='0';
over<="00";
sm2<='1';
elsif clk16'event and clk16='1' then
if rd='0' then--当读信号有效时over 复位。
over<="00";
end if;
if receive='0' then
if rxd='0' then
cnt<=cnt+1;
if cnt=8 then
receive<='1';
end if;
end if;
else cnt<=cnt+1;
if rxdcnt=12 then
receive<='0';
cnt<="0000";
if r_shift(10)='1' then--如果是广播帧
if (r_shift(8 downto 1) = close_all) then--如果是置位sm2信号
sm2<='1';
end if;
if sm2='1' and (r_shift(8 downto 1) = address) then--如果地址匹配
sm2<='0';
end if;
elsif sm2='0' then--如果是单机通信,则直接接收
if (r_shift(1)xor r_shift(2)xor r_shift(3)xor r_shift(4)xor r_shift(5)xor r_shift(6)xor r_shift(7)xor r_shift(8)xor r_shift(9))= '0' then
rbuf <= r_shift(8 downto 1);
over<="01"; --正常结束
else over<="10";--奇偶校验错
end if;
if r_shift(11)='0' or ssr/=s0 then--祯格式错或者发生覆盖
over<="10";
end if;
end if;
end if;
end if;
end if;
end if;
end process;
process(rst,clk16)--接收移位寄存器-->接收缓冲器
begin
if cs ='0' then
if rst='0' then
rxdcnt<=(others=>'0');
elsif clk16'event and clk16='1' then
if receive='0' then
rxdcnt<=(others=>'0');
elsif cnt=15 then
rxdcnt<=rxdcnt+1;
end if;
end if;
end if;
end process;
data <= rbuf when rd = '0' else "ZZZZZZZZ";
tbuf <= data when wr = '0' ;
ti<='1' when sst=s2 else '0';
ri<='1' when ssr/=s0 else '0';
err<='1' when ssr=s4 else '0';
end behav;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -