当前位置: 首页 > article >正文

【FPGA】UART串口通信

文章目录

  • 一、通信方式
      • 1.串行通信
      • 2.并行通信
  • 二、UART串口通信
      • 1.模块设计与时序图
      • 2.代码实现
  • 三、测试结果
      • 1.仿真结果
      • 2.上板验证

一、通信方式

1.串行通信

串行通信是指利用一条传输线将数据一位位地顺序传送。(也就是说串行通信传输的数据是1比特1比特的传送的)
在这里插入图片描述常见串行通信接口
在这里插入图片描述
串行通信优点是传输距离远、占用资源少。
串行通信缺点是发送速度慢。

2.并行通信

并行是指多比特数据同时通过并行线进行传送,这样数据传送速度大大提高。

但并行传送的线路长度受到限制,因为长度增加,干扰就会增加,数据也就容易出错。
在这里插入图片描述
并行通信优点是发送速度快。
并行通信缺点是传输距离短、资源占用多。

二、UART串口通信

UART是一种异步全双工通信方式
在这里插入图片描述

1.模块设计与时序图

在这里插入图片描述

uart_tx模块时序图
在这里插入图片描述

uart_rx模块时序图
在这里插入图片描述

2.代码实现

uart.v(顶层模块)

module  uart
(
    input   clk     ,
    input   rst_n   ,

    input   u_rx    ,
    output  u_tx       
);

wire    [7:0]   data    ;
wire            start   ;

uart_rx uart_rx(
    .clk        (clk)   ,
    .rst_n      (rst_n) ,

    .data       (data)  ,
    .start      (start) ,
    .u_rx       (u_rx)
);

uart_tx uart_tx(
    .clk        (clk)   ,
    .rst_n      (rst_n) ,
    
    .data       (data)  ,
    .start      (start) ,
    .u_tx       (u_tx)  
);

endmodule

uart_tx

module uart_tx
#(
    parameter BAUD_MAX  = 5208,
    parameter BAUD_FLAG = 1
)
(
    input           clk         ,
    input           rst_n       ,

    input   [7:0]   data        ,
    input           start       ,

    output  reg     u_tx             
);

reg     [14:0]      baud_cnt    ;
reg     [4:0]       bit_cnt     ;

reg                 data_state  ;
reg                 bit_flag    ;
reg                 done        ;

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        data_state <= 1'b0 ;
    else if(start)
        data_state <= 1'b1 ;
    else if(done)
        data_state <= 1'b0 ;
    else
        data_state <= data_state ; 
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        baud_cnt <= 1'b0 ;
    else if(data_state)begin
        if(baud_cnt == BAUD_MAX - 1)
            baud_cnt <= 1'b0 ;
        else
            baud_cnt <= baud_cnt + 1'b1 ;
    end
    else
        baud_cnt <= 1'b0 ;
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        bit_flag <= 1'b0 ;
    else if(baud_cnt == BAUD_FLAG)
        bit_flag <= 1'b1 ;
    else
        bit_flag <= 1'b0 ;
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        bit_cnt <= 1'b0 ;
    else if(bit_flag)begin
        if(bit_cnt == 9)
            bit_cnt <= 1'b0 ;
        else
            bit_cnt <= bit_cnt + 1'b1 ;
    end
    else
        bit_cnt <= bit_cnt ;
end

always @(posedge clk or negedge rst_n) begin  
    if(!rst_n)
        u_tx <= 1'b1 ;  
    else if(bit_flag)begin
        case(bit_cnt)
            0 : u_tx <= 1'b0    ;
            1 : u_tx <= data[0] ;
            2 : u_tx <= data[1] ;
            3 : u_tx <= data[2] ;
            4 : u_tx <= data[3] ;
            5 : u_tx <= data[4] ;
            6 : u_tx <= data[5] ;
            7 : u_tx <= data[6] ;
            8 : u_tx <= data[7] ;
            9 : u_tx <= 1'b1    ;
            default : u_tx <= 1'b1 ;
        endcase
    end
    else
        u_tx <= u_tx ;
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        done <= 1'b0 ;
    else if(bit_cnt == 9 && bit_flag)
        done <= 1'b1 ;
    else
        done <= 1'b0 ;
end

endmodule

uart_rx

module uart_rx
#(
    parameter BAUD_MAX  = 5208,
    parameter BAUD_FLAG = 2604 
)
(
    input   clk     ,
    input   rst_n   ,

    input   u_rx    ,

    output reg        start ,
    output reg  [7:0] data
);

reg                 u_rx0       ;
reg                 u_rx1       ;
reg                 u_rx2       ;

reg     [14:0]      baud_cnt    ;
reg     [4:0]       bit_cnt     ;

reg                 data_state  ;
reg                 bit_flag    ;
reg                 done        ;

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        u_rx0 <= 1'b1 ;
        u_rx1 <= 1'b1 ;
        u_rx2 <= 1'b1 ;
    end
    else begin
        u_rx0 <= u_rx  ;
        u_rx1 <= u_rx0 ;
        u_rx2 <= u_rx1 ;
    end
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        data_state <= 1'b0 ;
    else if((!u_rx1) && (u_rx2))
        data_state <= 1'b1 ;
    else if(done)
        data_state <= 1'b0 ;
    else
        data_state <= data_state ;
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        baud_cnt <= 1'b0 ;
    else if(data_state)begin
        if(baud_cnt == BAUD_MAX - 1)
            baud_cnt <= 1'b0 ;
        else
            baud_cnt <= baud_cnt + 1'b1 ;
    end
    else
        baud_cnt <= 1'b0 ;
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        bit_flag <= 1'b0 ;
    else if(baud_cnt == BAUD_FLAG)
        bit_flag <= 1'b1 ;
    else
        bit_flag <= 1'b0 ;
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        bit_cnt <= 1'b0 ;
    else if(bit_flag)begin
        if(bit_cnt == 9)
            bit_cnt <= 1'b0 ;
        else
            bit_cnt <= bit_cnt + 1'b1 ;
    end
    else
        bit_cnt <= bit_cnt ;
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        data <= 8'b00000000 ;
    else if(bit_flag)begin     
        case(bit_cnt)
            0 : data    <= data  ;
            1 : data[0] <= u_rx2 ;
            2 : data[1] <= u_rx2 ;
            3 : data[2] <= u_rx2 ;
            4 : data[3] <= u_rx2 ;
            5 : data[4] <= u_rx2 ;
            6 : data[5] <= u_rx2 ;
            7 : data[6] <= u_rx2 ;
            8 : data[7] <= u_rx2 ;
            9 : data    <= data  ;
            default : data <= data ;
        endcase
    end
    else
        data <= data ;
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        done <= 1'b0 ;
    else if(bit_cnt == 9 && bit_flag)
        done <= 1'b1 ;
    else
        done <= 1'b0 ;
end

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)
        start <= 1'b0 ;
    else
        start <= done ;
end

endmodule

uart_tb

`timescale 1ps/1ps

module uart_tb();

reg             clk     ;
reg             rst_n   ;

reg             u_rx    ;
wire            u_tx    ;

uart    u_uart
(
    .clk        (clk)   ,
    .rst_n      (rst_n) ,

    .u_rx       (u_rx)  ,
    .u_tx       (u_tx)  
);

initial begin
    clk = 1;
    forever
    #10
    clk=~clk;
end

initial begin
    rst_n = 1;
    #10;
    rst_n = 0;
    #20;
    rst_n = 1;
end

parameter TIMEPERIOD = 20;

initial begin
		u_rx = 1'b1;
		#200
		//发送起始位
		u_rx = 1'd0;
		#(5027*TIMEPERIOD);
		//发送数据0
		u_rx = 1'd1;
        #(5027*TIMEPERIOD);
		//发送数据1
		u_rx = 1'd0;
		#(5027*TIMEPERIOD);
		//发送数据2
		u_rx = 1'd0;
		#(5027*TIMEPERIOD);
		//发送数据3
		u_rx = 1'd0;
		#(5027*TIMEPERIOD);
		//发送数据4
		u_rx = 1'd0;
		#(5027*TIMEPERIOD);
		//发送数据5
		u_rx = 1'd1;
        #(5027*TIMEPERIOD);
		//发送数据6
		u_rx = 1'd0;
		#(5027*TIMEPERIOD);
		//发送数据7
		u_rx = 1'd0;
		#(5027*TIMEPERIOD);
		//发送结束位
		u_rx = 1'd1;
		#(100000*TIMEPERIOD);
		$stop ;
end

endmodule

三、测试结果

1.仿真结果

在这里插入图片描述

2.上板验证

在这里插入图片描述


http://www.kler.cn/a/414437.html

相关文章:

  • linux内核读写硬盘文件 kernel_writekernel_read
  • 学习ASP.NET Core的身份认证(基于Session的身份认证1)
  • 如何在Python中进行数学建模?
  • 什么是SeaTunnel
  • css:项目
  • 【适配】屏幕拖拽-滑动手感在不同分辨率下的机型适配
  • 深度学习视频编解码开源项目介绍【持续更新】
  • 新版Android Studio 一些配置细节
  • Algorithms and Data Structures in C++ by Mohammed Yasir Eramangadan
  • linux安全管理-防火墙配置
  • UNity将脚本中的文本提示显示在编辑器中
  • #渗透测试#红蓝攻防#HW#漏洞挖掘#漏洞复现01-笑脸漏洞(vsftpd)
  • 启动SpringBoot
  • Docker网络模式:桥接(Bridge)模式与主机模式(Host)实操对比(一)
  • docker网络配置
  • git打标签的作用?
  • ELK(Elasticsearch + logstash + kibana + Filebeat + Kafka + Zookeeper)日志分析系统
  • 【05】Selenium+Python 两种文件上传方式(AutoIt)
  • 计算机网络八股整理(二)
  • http账号密码认证Http Basic Auth
  • Kafka日志索引详解以及生产常见问题分析与总结
  • 微信小程序下拉刷新与上拉触底的全面教程
  • 刷题分享11_28
  • MySQL乐观锁
  • SpringCloud之Config:从基础到高级应用
  • verilog实现开方运算/基于迭代法的平方根计算算法/FPGA实现开根号算法