• FPGA-结合协议时序实现UART收发器(五):串口顶层模块UART_TOP、例化PLL、UART_FIFO、uart_drive


    FPGA-结合协议时序实现UART收发器(五):串口顶层模块UART_TOP、例化PLL、UART_FIFO、uart_drive

    串口顶层模块UART_TOP、例化PLL、UART_FIFO、uart_drive,功能实现。



    一、功能实现

    对照代码,串口发送模块UART_TOP实现功能包括:

    • PLL锁相环,实现稳定系统输入时钟功能
    • UART_FIFO,数据先进先出,实现数据缓存功能,防止出现数据错乱
    • w_clk_rst = ~w_system_pll_locked;保证复位电平是先高位再地位
    • r_user_tx_ready,用户输出ready信号慢一拍,用于判断数据是否发送完毕,是否为结束状态
    • r_rden_lock,fifo使能锁控制
    • r_fifo_rden,fifo读使能情况
    • r_uart_tx_vaild比FIFO中的读使能r_fifo_rden慢一拍,为实现有效信号和数据能够匹配上,所以对有效信号进行打一拍来延迟一个周期,从而实现信号和数据匹配,正确获取数据

    一、UART_TOP代码

    `timescale 1ns / 1ps
    //
    // Company: 
    // Engineer: 
    // 
    // Create Date: 2023/09/09 13:13:15
    // Design Name: 
    // Module Name: UART_TOP
    // Project Name: 
    // Target Devices: 
    // Tool Versions: 
    // Description: 
    // 
    // Dependencies: 
    // 
    // Revision:
    // Revision 0.01 - File Created
    // Additional Comments:
    // 
    //不要直接用系统时钟!!!
    //要添加一个pll锁相环,进行滤波稳定时钟,方便后续处理
    //
    
    
    module UART_TOP(
    
    //模块输入输出
        input       i_clk       ,
        input       i_uart_rx   ,
    
        output      o_uart_tx   
        );
    
    
    wire                    w_clk_50Mhz;
    wire                    w_clk_rst;
    wire                    w_system_pll_locked;
    
    wire    [7:0]           w_user_tx_data;
    wire                    w_user_tx_ready;
    wire    [7:0]           w_user_rx_data;
    wire                    w_user_rx_vaild;
    wire                    w_user_clk;
    wire                    w_user_rst;
    wire                    w_fifo_empty;
    reg                     r_fifo_rden;
    reg                     r_uart_tx_vaild;
    reg                     r_rden_lock;//fifo使能锁
    reg                     r_user_tx_ready;
    
    
    //pll锁存器在时钟不稳定的时候是低电平,在稳定后是高电平,即先低电平后高电平
    //系统中习惯使用复位信号先高后低,即上电先高电平进行复位,然后再低电平,故需进行取反
    assign w_clk_rst = ~w_system_pll_locked;
    
    
    system_pll system_pll_u0
    (
        .clk_in1                        (i_clk),      // input clk_in1
        .clk_out1                       (w_clk_50Mhz),     // output clk_out1
        .locked                         (w_system_pll_locked)       // output locked
    );
    
    
    
    
    uart_drive#(
        //串口可调参数
        .P_SYSTEM_CLK                  (50_000_000),
        .P_UART_BUADRATE               (115200),
        .P_UART_DATA_WIDTH             (8),
        .P_UART_STOP_WIDTH             (1),
        .P_UART_CHECK                  (0)
    )
    uart_drive_u0( 
        //串口驱动输入输出
        .i_clk                         (w_clk_50Mhz),
        .i_rst                         (w_clk_rst),
        
        .i_uart_rx                     (i_uart_rx),
        .o_uart_tx                     (o_uart_tx),
    
        .i_user_tx_data                (w_user_tx_data),//用户输出数据,作为驱动的输入,即先输入到驱动处理再输出
        .i_user_tx_vaild               (r_uart_tx_vaild),//握手
        .o_user_tx_ready               (w_user_tx_ready),
    
        .o_user_rx_data                (w_user_rx_data),//用户输入数据,作为驱动的输出,即先经过驱动输出再输入到用户
        .o_user_rx_vaild               (w_user_rx_vaild),
    
        .o_user_clk                    (w_user_clk),
        .o_user_rst                    (w_user_rst)
    
    );
    
    
    
    UART_FIFO UART_FIFO_U0 (
      .clk          (w_user_clk),      // input wire clk
      .srst         (w_user_rst),    // input wire srst
      .din          (w_user_rx_data),      // input wire [7 : 0] din
      .wr_en        (w_user_rx_vaild),  // input wire wr_en
      .rd_en        (r_fifo_rden),  // input wire rd_en
      .dout         (w_user_tx_data),    // output wire [7 : 0] dout
      .full         (),    // output wire full
      .empty        (w_fifo_empty)  // output wire empty
    );
    
    
    //处理用户输出ready信号慢一拍
    //用于判断数据是否发送完毕,是否为结束状态
    always @(posedge w_user_clk or posedge w_user_rst)
    begin
        if(w_user_rst)
            r_user_tx_ready <= 'd0;
        else
            r_user_tx_ready <= w_user_tx_ready;
    
    end
    
    //处理fifo使能控制,使能锁r_rden_lock
    //防止fifo使能持续两个周期,导致读取两个数据,但握手只会读取一个数据,就会导致数据丢失,故需要使能锁控制来fifo只持续一个周期
    always @(posedge w_user_clk or posedge w_user_rst)
    begin
        if(w_user_rst)                                      //初始状态
            r_rden_lock <= 'd0;
        else if(w_user_tx_ready && !r_user_tx_ready)        //结束状态,当前为高电平1,前一拍为低电平,即上升沿判断为结束状态
            r_rden_lock <= 'd0;
        else if(~w_fifo_empty && w_user_tx_ready)           //变化状态,即fifo内有数据+ready好了
            r_rden_lock <= 'd1;
        else
            r_rden_lock <= r_rden_lock;
            
    end
    
    
    //处理fifo读使能情况,r_fifo_rden
    always @(posedge w_user_clk or posedge w_user_rst) 
    begin
        if(w_user_rst)
            r_fifo_rden <= 'd0;
        else if(~w_fifo_empty && w_user_tx_ready)
            r_fifo_rden <= 'd1;
        else
            r_fifo_rden <= 'd0;
    end
    
    
    //因为发送的数据是比FIFO中的读使能r_fifo_rden满一个周期
    //为实现有效信号和数据能够匹配上,所以对有效信号进行打一拍来延迟一个周期,从而实现信号和数据匹配,正确获取数据
    always @(posedge w_user_clk or posedge w_user_rst) 
    begin
        if(w_user_rst)
            r_uart_tx_vaild <= 'd0;
        else
            r_uart_tx_vaild <= r_fifo_rden;
    end
    
    endmodule
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159

    总结

    串口顶层模块UART_TOP、例化PLL、UART_FIFO、uart_drive,功能实现,数据缓存先进先出fifo实现,fifo使能控制等功能实现。

  • 相关阅读:
    误差反向传播法(激活函数层的实现)
    c++ pcl点云变换骨架枝干添加树叶源码实例
    rust打印闭包的插件实现
    Oracle 12c Docker镜像配置SSL
    【无标题】
    项目管理:敏捷开发之十大误区
    React SSR - 写个 Demo 一学就会
    大厂秋招真题【DP】米哈游20230924秋招T2-米小游与魔法少女-奇运
    四川竹哲电子商务有限公司培训服务引领你走向成功
    linux脚本,导出oracle(spool)指定数据到txt
  • 原文地址:https://blog.csdn.net/Bellwen/article/details/132838189