查看: 1233|回复: 0

FPGA必须掌握的异步通信之UART

[复制链接]
  • TA的每日心情
    无聊
    2018-10-12 09:46
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]初来乍到

    发表于 2019-8-28 14:15:10 | 显示全部楼层 |阅读模式
    分享到:
    你知道FPGA是如何采样数据的吗?数据当与时钟一并到来,则叫同步。若不是与时钟一并到来的话,那就是异步。而UART一个就是异步接口

    在任何异步接口中,首先要知道的就要什么时候采样数据。如果采样的时间不对,那么就会看到错误的数据。为了收到正确的数据,发射器和接收器必须要设定相同的波特率。波特率是数据传输的频率,比如9600波特率就意味着为9600bit每秒。以下的VHDL代码用了一个类属来定义每位中有多少时钟周期。

    以下是VHDL的接收器与发射器代码。

    接收器

    • 图书馆;
    • 使用ieee.std_logic_1164.ALL;
    • 使用ieee.numeric_std.all;
    • TI TY UART_RX IS
    •   通用(
    •     g_CLKS_PER_BIT:整数:= 115
    •     );
    •   港口 (
    •     i_Clk:在std_logic中;
    •     i_RX_Serial:在std_logic中;
    •     o_RX_DV:out std_logic;
    •     o_RX_Byte:out std_logic_vector(7 downto 0)
    •     );
    • 结束UART_RX;
    • UART_RX的架构rtl是
    •   类型t_SM_Main是(s_Idle,s_RX_Start_Bit,s_RX_Data_Bits,
    •                      s_RX_Stop_Bit,s_Cleanup);
    •   signal r_SM_Main:t_SM_Main:= s_Idle;
    •   signal r_RX_Data_R:std_logic:='0';
    •   signal r_RX_Data:std_logic:='0';
    •   signal r_Clk_Count:整数范围0到g_CLKS_PER_BIT-1:= 0;
    •   signal r_Bit_Index:整数范围0到7:= 0; - 总共8位
    •   signal r_RX_Byte:std_logic_vector(7 downto 0):=(其他=>'0');
    •   signal r_RX_DV:std_logic:='0';
    • 开始
    •   p_SAMPLE:进程(i_Clk)
    •   开始
    •     如果 rising_edge(i_Clk)那么
    •       r_RX_Data_R <= i_RX_Serial;
    •       r_RX_Data <= r_RX_Data_R;
    •     万一;
    •   结束过程p_SAMPLE;
    •   - 控制RX状态机
    •   p_UART_RX:进程(i_Clk)
    •   开始
    •     如果rising_edge(i_Clk)那么
    •       case r_SM_Main是
    •         当s_Idle =>时
    •           r_RX_DV <='0';
    •           r_Clk_Count <= 0;
    •           r_Bit_Index <= 0;
    •           如果r_RX_Data ='0'则 - 检测到开始位
    •             r_SM_Main <= s_RX_Start_Bit;
    •           其他
    •             r_SM_Main <= s_Idle;
    •           万一;
    •         当s_RX_Start_Bit =>时
    •           如果r_Clk_Count =(g_CLKS_PER_BIT-1)/ 2则
    •             如果r_RX_Data ='0'那么
    •               r_Clk_Count <= 0; - 重置计数
    •               r_SM_Main <= s_RX_Data_Bits;
    •             其他
    •               r_SM_Main <= s_Idle;
    •             万一;
    •           其他
    •             r_Clk_Count <= r_Clk_Count + 1;
    •             r_SM_Main <= s_RX_Start_Bit;
    •           万一;
    •         当s_RX_Data_Bits =>时
    •           如果r_Clk_Count <g_CLKS_PER_BIT-1则
    •             r_Clk_Count <= r_Clk_Count + 1;
    •             r_SM_Main <= s_RX_Data_Bits;
    •           其他
    •             r_Clk_Count <= 0;
    •             r_RX_Byte(r_Bit_Index)<= r_RX_Data;
    •             如果r_Bit_Index <7则
    •               r_Bit_Index <= r_Bit_Index + 1;
    •               r_SM_Main <= s_RX_Data_Bits;
    •             其他
    •               r_Bit_Index <= 0;
    •               r_SM_Main <= s_RX_Stop_Bit;
    •             万一;
    •           万一;
    • - 停止位= 1
    •         当s_RX_Stop_Bit =>时
    •           如果r_Clk_Count <g_CLKS_PER_BIT-1则
    •             r_Clk_Count <= r_Clk_Count + 1;
    •             r_SM_Main <= s_RX_Stop_Bit;
    •           其他
    •             r_RX_DV <='1';
    •             r_Clk_Count <= 0;
    •             r_SM_Main <= s_Cleanup;
    •           万一;
    •         - 住1点钟
    •         当s_Cleanup =>时
    •           r_SM_Main <= s_Idle;
    •           r_RX_DV <='0';
    •         当别人=>
    •           r_SM_Main <= s_Idle;
    •       结束案例;
    •     万一;
    •   结束过程p_UART_RX;
    •   o_RX_DV <= r_RX_DV;
    •   o_RX_Byte <= r_RX_Byte;
    • 结束rtl;
    发送器
    • 图书馆;
    • 使用ieee.std_logic_1164.all;
    • 使用ieee.numeric_std.all;
    • 实体UART_TX是
    •   通用(
    •     g_CLKS_PER_BIT:整数:= 115
    •     );
    •   港口 (
    •     i_Clk:在std_logic中;
    •     i_TX_DV:在std_logic中;
    •     i_TX_Byte:在std_logic_vector中(7 downto 0);
    •     o_TX_Active:out std_logic;
    •     o_TX_Serial:out std_logic;
    •     o_TX_Done:输出std_logic
    •     );
    • 结束UART_TX;
    • UART_TX的架构RTL是
    •   类型t_SM_Main是(s_Idle,s_TX_Start_Bit,s_TX_Data_Bits,
    •                      s_TX_Stop_Bit,s_Cleanup);
    •   signal r_SM_Main:t_SM_Main:= s_Idle;
    •   signal r_Clk_Count:整数范围0到g_CLKS_PER_BIT-1:= 0;
    •   signal r_Bit_Index:整数范围0到7:= 0; - 总共8位
    •   signal r_TX_Data:std_logic_vector(7 downto 0):=(其他=>'0');
    •   signal r_TX_Done:std_logic:='0';
    • 开始
    •   p_UART_TX:进程(i_Clk)
    •   开始
    •     如果rising_edge(i_Clk)那么
    •       case r_SM_Main是
    •         当s_Idle =>时
    •           o_TX_Active <='0';
    •           o_TX_Serial <='1';
    •           r_TX_Done <='0';
    •           r_Clk_Count <= 0;
    •           r_Bit_Index <= 0;
    •           如果i_TX_DV ='1'那么
    •             r_TX_Data <= i_TX_Byte;
    •             r_SM_Main <= s_TX_Start_Bit;
    •           其他
    •             r_SM_Main <= s_Idle;
    •           万一;
    •         当s_TX_Start_Bit =>时
    •           o_TX_Active <='1';
    •           o_TX_Serial <='0';
    •           如果r_Clk_Count <g_CLKS_PER_BIT-1则
    •             r_Clk_Count <= r_Clk_Count + 1;
    •             r_SM_Main <= s_TX_Start_Bit;
    •           其他
    •             r_Clk_Count <= 0;
    •             r_SM_Main <= s_TX_Data_Bits;
    •           万一;
    •         当s_TX_Data_Bits =>时
    •           o_TX_Serial <= r_TX_Data(r_Bit_Index);
    •           如果r_Clk_Count <g_CLKS_PER_BIT-1则
    •             r_Clk_Count <= r_Clk_Count + 1;
    •             r_SM_Main <= s_TX_Data_Bits;
    •           其他
    •             r_Clk_Count <= 0;
    •             如果r_Bit_Index <7则
    •               r_Bit_Index <= r_Bit_Index + 1;
    •               r_SM_Main <= s_TX_Data_Bits;
    •             其他
    •               r_Bit_Index <= 0;
    •               r_SM_Main <= s_TX_Stop_Bit;
    •             万一;
    •           万一;
    •         当s_TX_Stop_Bit =>时
    •           o_TX_Serial <='1';
    •           如果r_Clk_Count <g_CLKS_PER_BIT-1则
    •             r_Clk_Count <= r_Clk_Count + 1;
    •             r_SM_Main <= s_TX_Stop_Bit;
    •           其他
    •             r_TX_Done <='1';
    •             r_Clk_Count <= 0;
    •             r_SM_Main <= s_Cleanup;
    •           万一;
    •         - 住1点钟
    •         当s_Cleanup =>时
    •           o_TX_Active <='0';
    •           r_TX_Done <='1';
    •           r_SM_Main <= s_Idle;
    •         当别人=>
    •           r_SM_Main <= s_Idle;
    •       结束案例;
    •     万一;
    •   结束进程p_UART_TX;
    •   o_TX_Done <= r_TX_Done;
    • 结束RTL;

    [color=rgb(51, 102, 153) !important]复制代码
    测试平台代码

    • 图书馆;
    • 使用ieee.std_logic_1164.ALL;
    • 使用ieee.numeric_std.all;
    • 实体uart_tb是
    • 结束uart_tb;
    • uart_tb的架构行为是
    •   组件uart_tx是
    •     通用(
    •       g_CLKS_PER_BIT:整数:= 115
    •       );
    •     港口 (
    •       i_clk:在std_logic中;
    •       i_tx_dv:在std_logic中;
    •       i_tx_byte:在std_logic_vector中(7 downto 0);
    •       o_tx_active:out std_logic;
    •       o_tx_serial:out std_logic;
    •       o_tx_done:out std_logic
    •       );
    •   结束组件uart_tx;
    •   组件uart_rx是
    •     通用(
    •       g_CLKS_PER_BIT:整数:= 115
    •       );
    •     港口 (
    •       i_clk:在std_logic中;
    •       i_rx_serial:在std_logic中;
    •       o_rx_dv:out std_logic;
    •       o_rx_byte:out std_logic_vector(7 downto 0)
    •       );
    •   结束组件uart_rx;
    •   - Test Bench使用了一个10 MHz的时钟

    [color=rgb(51, 102, 153) !important]复制代码


    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /2 下一条



    手机版|小黑屋|与非网

    GMT+8, 2024-4-18 12:17 , Processed in 0.121870 second(s), 17 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2020, Tencent Cloud.