【Verilog硬件语言学习笔记4】FPGA串口通信

串口通信是系统设计中比较基部分,其原理其实也很通俗易懂。单次建立通信会传输8个bit,其时序也很简单,这里就不再赘述了。其对应的实例代码如下所示;

首先是接受部分(因为我的变量命名也很规范,通俗易懂,所以我不再详细介绍):

复制代码
`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2025/03/13 12:00:48
// Design Name: 
// Module Name: uart_rx
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//

module uart_rx(
    input                               clk                        ,
    input                               rst_n                      ,
    input                               uart_rxd                   ,

    output reg                          uart_rx_done               ,
    output reg         [   7: 0]        uart_rx_data                
    );

// parameter to define
    parameter                           CLK_FREQ                   = 50000000;
    parameter                           UART_BPS                   = 115200;
    localparam                          BAUD_CNT_MAX               = CLK_FREQ / UART_BPS;

// reg define
    reg                                 uart_rxd_d0                 ;
    reg                                 uart_rxd_d1                 ;
    reg                                 uart_rxd_d2                 ;
    reg                                 rx_flag                     ;
    reg                [   3: 0]        rx_cnt                      ;
    reg                [  15: 0]        baud_cnt                    ;
    reg                [   7: 0]        rx_data_t                   ;

// wire define
    wire                                start_en                    ;
// Main Code
// Because the sign fall from high to low, use this to catch the signal;
    assign                              start_en                    = uart_rxd_d2 & (~uart_rxd_d1) & (~rx_flag);

// aiming to asynchronous signal processing
always @(posedge clk or negedge rst_n)
begin
    if (!rst_n) begin
        uart_rxd_d0 <= 0;
        uart_rxd_d1 <= 0;
        uart_rxd_d2 <= 0;
    end
    else begin
        uart_rxd_d0 <= uart_rxd;
        uart_rxd_d1 <= uart_rxd_d0;
        uart_rxd_d2 <= uart_rxd_d1;
    end
end

// define the rx_flag
always @(posedge clk or negedge rst_n)
begin
    if (!rst_n)
        rx_flag <= 0;
    else if (start_en)
        rx_flag <= 1'b1;
    else if ((rx_cnt == 4'd9) && (baud_cnt == BAUD_CNT_MAX / 2 - 1'b1))
        rx_flag <= 0;
    else
        rx_flag <= rx_flag;
end

// Baud rate counter amplitude
always @(posedge clk or negedge rst_n)
begin
    if (!rst_n)
        baud_cnt <= 0;
    else if (rx_flag) begin
        if (baud_cnt <= BAUD_CNT_MAX - 1)
            baud_cnt <= baud_cnt + 1;
        else
            baud_cnt <= 0;
    end
    else
        baud_cnt <= 0;
end

// Accept data(rx_cnt) assignment
always @(posedge clk or negedge rst_n)
begin
    if (!rst_n)
        rx_cnt <= 0;
    else if (rx_flag) begin
        if (baud_cnt == BAUD_CNT_MAX-1) begin
            rx_cnt <= rx_cnt + 1;
        end
        else
            rx_cnt <= rx_cnt;
    end
    else
        rx_cnt <= 0;
end

// based on the rx_cnt to restore the rxd data
always @(posedge clk or negedge rst_n)
begin
    if (!rst_n)
        rx_data_t <= 0;
    else if (rx_flag) begin
        if (baud_cnt == BAUD_CNT_MAX / 2 - 1) begin
            case (rx_cnt)
                4'd1: rx_data_t[0] <= uart_rxd_d2;
                4'd2: rx_data_t[1] <= uart_rxd_d2;
                4'd3: rx_data_t[2] <= uart_rxd_d2;
                4'd4: rx_data_t[3] <= uart_rxd_d2;
                4'd5: rx_data_t[4] <= uart_rxd_d2;
                4'd6: rx_data_t[5] <= uart_rxd_d2;
                4'd7: rx_data_t[6] <= uart_rxd_d2;
                4'd8: rx_data_t[7] <= uart_rxd_d2;
                default: ;
            endcase
        end
        else
            rx_data_t <= rx_data_t;
    end
    else
        rx_data_t <= 0;
end

// assignment the data received
always @(posedge clk or negedge rst_n)
begin
    if (!rst_n) begin
        uart_rx_done <= 0;
        uart_rx_data <= 0;
    end
    else if (rx_cnt == 4'd9 && baud_cnt == BAUD_CNT_MAX / 2 - 1) begin
        uart_rx_done <= 1;
        uart_rx_data <= rx_data_t;
    end
    else begin
        uart_rx_done <= 0;
        uart_rx_data <= uart_rx_data;
    end
end

endmodule

然后是发送部分:

复制代码
`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2025/03/13 17:14:19
// Design Name: 
// Module Name: uart_tx
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module uart_tx(
    input                               clk                        ,
    input                               rst_n                      ,
    input                               uart_tx_en                 ,
    input              [   7: 0]        uart_tx_data               ,
    output reg                          uart_txd                   ,
    output reg                          uart_tx_busy                
    );

// parameter define
    parameter                           CLK_FREQ                   = 50000000;
    parameter                           UART_BPS                   = 115200;
    localparam                          BAUD_CNT_MAX               = CLK_FREQ/UART_BPS;

// reg define
    reg                [   7: 0]        tx_data_t                   ;
    reg                [   3: 0]        tx_cnt                      ;
    reg                [  15: 0]        baud_cnt                    ;

// Main Code
always @(posedge clk or negedge rst_n)
    begin
        if(!rst_n)     begin
            tx_data_t<=0;
            uart_tx_busy<=0;
        end
        else if(uart_tx_en)        begin
            tx_data_t<=uart_tx_data;
            uart_tx_busy<=1;
        end
        else if(tx_cnt==4'd9&&baud_cnt==BAUD_CNT_MAX-1) begin
            tx_data_t<=0;
            uart_tx_busy<=0;
        end
        else begin
            tx_data_t<=tx_data_t;
            uart_tx_busy<=uart_tx_busy;
        end
    end

// Baud counter
always @(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
            baud_cnt<=0;
        else if(uart_tx_en)
            baud_cnt<=0;
        else if(uart_tx_busy) begin
            if(baud_cnt<BAUD_CNT_MAX-1)
                baud_cnt<=baud_cnt+1;
            else
                baud_cnt<=0;
        end
        else
            baud_cnt<=0;
    end

// assign the tx_cnt
always @(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
            tx_cnt<=0;
        else if(uart_tx_busy) begin
            if(baud_cnt==BAUD_CNT_MAX-1)
                tx_cnt<=tx_cnt+1;
            else
                tx_cnt<=tx_cnt;
        end
        else
            tx_cnt<=0;
    end

always @(posedge clk or negedge rst_n)
    begin
        if(!rst_n)
            uart_txd<=1;
        else if(uart_tx_busy) begin
            case(tx_cnt)
                4'd0: uart_txd<=1'b0;
                4'd1: uart_txd<=tx_data_t[0];
                4'd2: uart_txd<=tx_data_t[1];
                4'd3: uart_txd<=tx_data_t[2];
                4'd4: uart_txd<=tx_data_t[3];
                4'd5: uart_txd<=tx_data_t[4];
                4'd6: uart_txd<=tx_data_t[5];
                4'd7: uart_txd<=tx_data_t[6];
                4'd8: uart_txd<=tx_data_t[7];
                4'd9: uart_txd<=1;
                default: uart_txd<=1;
            endcase
        end
        else
            uart_txd<=1'b1;
    end

endmodule

参考文献:

达芬奇之 FPGA 开发指南 V2.2 -正点原子 达芬奇开发板教程

相关推荐
不灭锦鲤5 分钟前
网络安全学习第59天
学习·安全·web安全
楼田莉子26 分钟前
同步/异步日志系统:日志落地模块\日志器模块\异步日志模块
linux·服务器·c++·学习·设计模式
旖-旎1 小时前
递归(汉诺塔问题)(1)
c++·学习·算法·leetcode·深度优先·递归
SUNNY_SHUN2 小时前
清华团队提出TFA-Net,用模板特征聚合破解工业异常检测中的“捷径学习“难题
人工智能·学习·视觉检测·github
SuperHeroWu72 小时前
【鸿蒙基础入门】概念理解和学习方法论说明
前端·学习·华为·开源·harmonyos·鸿蒙·移动端
speop2 小时前
TASK05 | Reasoning Kindom拟合的陷阱 —— 统计相关性不是推理
学习
сокол2 小时前
【网安-等保评测-基础记录】网络安全等级保护2.0 详解(定级、备案、测评、整改一站式指南)
网络·笔记·网络安全·云计算
深念Y2 小时前
感知机 ≈ 可学习的逻辑门?聊聊激活函数与二元分类的本质
人工智能·学习·分类·感知机·激活函数·逻辑门·二元分类
程序员大雄学编程2 小时前
学习资源总汇
学习
Shang180989357263 小时前
T31ZX 君正/INGENIC智能视频处理器T31ZX可提供软硬件资料T31Z采用先进的低功耗设计
嵌入式硬件·fpga开发·音视频·t31zx智能视频处理器