当前位置:文档之家› FPGA实现串口通信

FPGA实现串口通信

FPGA实现串口通信UART接收。

因为只有数据线,没有时钟,这种叫异步通信。

首先双方必须约定好通信用的时钟频率,但是双方用的时钟必定有误差,而且不知道每个bit的起始时间。

这两点是造成你有时候收到对的,有时候收到错的原因。

所以必须要用高倍的时钟来采样,一般用8倍、16倍。

仅仅简单实现的话,用8倍举例,如果另一块板子(或PC)发过来的是数据,发送一个bit用的时钟频率是115200Hz的话,那么自己板子上要先产生一个115200x 8 = 921600Hz 的内部时钟。

用这个时钟对收到的串行数据进行采样,理论上讲,每个bit可以得到7-8个采样点。

如果FPGA晶振是50000000Hz(50MHz),则54.25分频得到921600Hz。

分频模块library IEEE;use IEEE.STD_LOGIC_1164.ALL;use IEEE.STD_LOGIC_arith.ALL;use IEEE.STD_LOGIC_UNSIGNED.ALL;entity Clk_DIV isport (clk : in std_logic;CLK_O : out std_logic );end Clk_DIV;architecture Clk_DIV_arch of Clk_DIV issignal clk1,clk2 : std_logic;signal s1,s2 : integer range 0 to 53;beginprocess(clk)beginif rising_edge(clk) thenif s1 < 53 thens1<= s1+1;elses1<=0;end if;if s1 < 28 thenclk1 <= '1';elseclk1 <= '0';end if;end if;end process;process(clk)beginif falling_edge(clk) thenif s2 < 53 thens2<= s2+1;elses2<=0;end if;if s2 < 28 thenclk2 <= '1';elseclk2 <= '0';end if;end if;end process;CLK_O <=clk1 or clk2;end Clk_DIV_arch;接下来第一步就是找起始bit,如果连采3次(或4次)都是0的话,说明找到起始bit 了,并且当前采样点大概在这个bit的中间了。

那么从现在开始,每过8个时钟,就能采到下一个bit的中间位置。

然后把这8个采到的bit组成一个byte就行了。

这样,才能得到稳定而正确的数据。

最后,过8个时钟,再采一下,确保后面跟着的bit是高,表示结束。

如果不是,说明有错发生了,没关系,重新搜索起始bit就好了。

接收模块library IEEE;use IEEE.std_logic_1164.all;use IEEE.std_logic_arith.all;use IEEE.std_logic_unsigned.all;entity UART_RX isport (reset_n : in std_logic;clk : in std_logic;RD_x : in std_logic; RD_x,接收数据线dout : out std_logic_vector(7 downto 0); 模块接收到得1字节数据 dav : out std_logic 传输成功应答);end UART_RX;architecture UART_RX_arch of UART_RX istype UART_RX_STATE_TYPE is (WAIT_START, DATA, STOP);signal curState : UART_RX_STATE_TYPE; 接收状态机状态signal bits : std_logic_vector(7 downto 0); 接收数据暂存signal smpCnt : integer range 0 to 7; 8次采样计数signal bitCnt : integer range 0 to 15; 接收位数计数beginprocess(reset_n, clk)beginif reset_n = '0' thencurState <= WAIT_START;bits <= (others => '0');smpCnt <= 0;bitCnt <= 0;elsif rising_edge(clk) thencase curState iswhen WAIT_START =>if RD_x = '0' thenif smpCnt = 3 thencurState <= DATA; 3次采样低电平证明起始位,下一个状态接收数据 smpCnt <= 0;elsecurState <= WAIT_START;smpCnt <= smpCnt + 1;end if;elsecurState <= WAIT_START;smpCnt <= 0;end if;bits <= (others => '0');bitCnt <= 0;when DATA =>if smpCnt = 7 then 如果采样八次,则保存一位数据if bitCnt = 7 then 如果已经接收八位则下一个状态停止接收 curState <= STOP;elsecurState <= DATA;end if;smpCnt <= 0;bits <= RD_x & bits(7 downto 1); 完成接收bitCnt <= bitCnt + 1;elsecurState <= DATA;smpCnt <= smpCnt + 1;bits <= bits;bitCnt <= bitCnt;end if;when STOP =>if smpCnt = 7 thencurState <= WAIT_START;smpCnt <= 0;elsecurState <= STOP;smpCnt <= smpCnt + 1;end if;bits <= bits;bitCnt <= 0;when others =>curState <= WAIT_START;bits <= (others => '0');smpCnt <= 0;bitCnt <= 0;end case;end if;end process;dout <= bits;process(reset_n, clk)beginif reset_n = '0' thendav <= '0';elsif rising_edge(clk) thenif curState = STOP and smpCnt = 7 and RD_x = '1' thendav <= '1'; 应答接收成功 elsedav <= '0';end if;end if;end process;end UART_RX_arch;发送程序library IEEE;use IEEE.std_logic_1164.all;use IEEE.std_logic_arith.all;use IEEE.std_logic_unsigned.all;entity UART_TX isport (EN : in std_logic;clk : in std_logic;TD_x : out std_logic;Data_in : in std_logic_vector(7 downto 0));end UART_TX;architecture UART_TX_arch of UART_TX istype UART_TX_STATE_TYPE is (WAIT_START, DATA, STOP);signal curState : UART_TX_STATE_TYPE;signal bits : std_logic_vector(7 downto 0);signal D_bit : std_logic;signal bitCnt : integer range 0 to 7;signal i : integer range 0 to 7;beginprocess(EN, clk)beginif rising_edge(clk) then i <= i+1;if i=7 theni <= 0;case curState iswhen WAIT_START =>if EN='0' thencurState <=WAIT_START;D_bit <='1';elsecurState <=DATA;bitCnt <= 0;bits <=Data_in;D_bit <='0';end if;when DATA =>if bitCnt = 7 thencurState <= STOP;D_bit <= bits(0);elsecurState <= DATA;bitCnt <= bitCnt + 1;D_bit <= bits(7);bits (7 downto 1)<= bits(6 downto 0); end if;when STOP =>if EN='1' thencurState <=WAIT_START;D_bit <='1';elsecurState <=STOP;bits <=Data_in;D_bit <='1';end if;when others =>null;end case;end if;end if;TD_x <=D_bit;end process;end UART_TX_arch;。

相关主题