当前位置:   article > 正文

串口通信实现-串口发送(vivado&verilog版)

串口发送

串口系列知识分享:
(1)串口通信实现-串口发送
(2)串口通信发送多字节数据
(3)串口通信实现-串口接收
(4)UART 通信-使用VIO进行板级验证
(5)串口接收-控制LED闪烁
(6)使用串口发送实现ACX720开发板时钟显示
(7)串口发送+RAM+VGA传图


前言

此文介绍uart串口协议(串口发送)的verilog实现和testbench的编写,仿真环境为vivado 2018.3。


提示:以下是本篇文章正文内容,下面案例可供参考

一、串口通信协议(uart)

串口作为常用的三大低速总线(UART、SPI、IIC)之一,在设计众多通信接口和调试时占有重要地位。串口(UART)全称通用异步收发传输器(Universal Asynchronous Receiver/Transmitter),主要用于数据间的串行传递,是一种全双工传输模式。它在发送数据时将并行数据转换成串行数据来传输,在接收数据时将接收到的串行数据转换成并行数据。(具体应用可自行百度)

二、串口发送的时序图

UART 在发送或接收过程中的一帧数据由4部分组成,起始位、数据位、奇偶校验位和停止位,如上图所示。其中,起始位标志着一帧数据的开始,停止位标志着一帧数据的结束,数据位是一帧数据中的有效数据。

    起始位:起始位标志。低有效。

    数据位:一帧数据中的有效数据。注意,串口协议规定了数据位长度只能位 6 7 8 位。要想发多位数据,只能将其切分为多个过程发送。

    奇偶校验位:是用来验证数据的正确性。奇偶校验一般不使用,如果 使用,则既可以做奇校验(Odd)也可以做偶校验(Even)。其实就是发的时候如果奇校验位为1,表面数据中1的个数为奇数个,再看接受端的奇校验位是否依旧为1。如果是的话,校验成功。在一定概率上保证了传输的正确性。当然,只是概率上的传输正确。此次试验不同奇偶校验。

    停止位:停止位标志着一帧数据的结束,高有效。

    空闲时,传输 1 。

    波特率设置 : 由于是异步通信,所以没有一个统一的时钟,需要双方约定传输传输速率。常见的波特率有:300, 1200, 2400, 9600, 19200, 115200 等.即一秒发送多少位数据。

    所以我们需要实现下面的时序图。当使能信号到来时,发送起始位,数据位,停止位,一帧数据发送结束。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

1

三、uart_byte_tx模块

module uart_byte_tx(
    Clk,
    Reset_n,
    Data,
    Send_Go,    // 改成单脉冲启动信号  启动一个内部 send_en 信号
    Baud_set,
    uart_tx,
    Tx_done
);
    input Clk;
    input Reset_n;
    input [7:0]Data;
    input Send_Go;
    input [2:0]Baud_set;
    output reg uart_tx;
    output reg Tx_done;
    
    //Baud_set = 0   就让波特率 = 9600;
    //Baud_set = 1   就让波特率 = 19200
    //Baud_set = 2   就让波特率 = 38400;
    //Baud_set = 3   就让波特率 = 57600;   
    //Baud_set = 4   就让波特率 = 115200; 

    reg [17:0]bps_DR;
    always@(*)
        case(Baud_set)
            0:bps_DR = 1000000000/9600/20;
            1:bps_DR = 1000000000/19200/20;
            2:bps_DR = 1000000000/38400/20;
            3:bps_DR = 1000000000/57600/20;
            4:bps_DR = 1000000000/115200/20;
            default:bps_DR = 1000000000/9600/20;
         endcase

    reg Send_en;
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)       
        Send_en <= 0;
    else if(Send_Go)
        Send_en <= 1;
    else if(Tx_done)
        Send_en <= 0;
        
    reg [7:0]r_Data;
    always@(posedge Clk)     //进行数据寄存,防止当Send_Go脉冲出现时,Data数据发生偏差
    if(Send_Go)
        r_Data <= Data;
    else
        r_Data <= r_Data;     

    wire bps_clk;
    assign bps_clk = (div_cnt == 1);
    
    reg [17:0]div_cnt;
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        div_cnt <= 0;
    else if(Send_en)begin
        if(div_cnt == bps_DR - 1)
            div_cnt <= 0;
        else 
            div_cnt <= div_cnt + 1'b1;
    end
    else
        div_cnt <= 0;

    reg [3:0]bps_cnt;
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        bps_cnt <= 0;
    else if(Send_en)begin
        if(bps_clk)begin
            if(bps_cnt == 11)
                bps_cnt <= 0;
            else
                bps_cnt <= bps_cnt + 1'b1;
        end
    end
    else
        bps_cnt <= 0;
    
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n) begin
        uart_tx <= 1'b1;
    end
    else begin
        case(bps_cnt)
            1:uart_tx <= 0;
            2:uart_tx <= r_Data[0];
            3:uart_tx <= r_Data[1];
            4:uart_tx <= r_Data[2];
            5:uart_tx <= r_Data[3];
            6:uart_tx <= r_Data[4];
            7:uart_tx <= r_Data[5];
            8:uart_tx <= r_Data[6];
            9:uart_tx <= r_Data[7]; 
            10:uart_tx <= 1;
            11:begin uart_tx <= 1;end
            default:uart_tx <= 1;
        endcase
     end
     
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n) 
        Tx_done <= 0;
    else if((bps_clk == 1)  && (bps_cnt == 10))
        Tx_done <= 1;
    else
        Tx_done <= 0;

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

四、uart_tx_test模块

此模块用于对uart_byte_tx模块进行测试,将uart_byte_tx模块中的Data输入设为每次发送加1。即第一次发送8’d0,第二次发送8’d1,依次加1发送。

module uart_tx_test(
    Clk,
    Reset_n,
    uart_tx,
);
    input Clk;
    input Reset_n;
    output uart_tx;
    
    reg Send_Go;
    reg [7:0]Data;
    
    uart_byte_tx uart_byte_tx(
        .Clk(Clk),
        .Reset_n(Reset_n),
        .Data(Data),
        .Send_Go(Send_Go),
        .Baud_set(3'd4),
        .uart_tx(uart_tx),
        .Tx_done(Tx_done)
    );
    
    reg [24:0]counter;
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        counter <= 0;
    else if(counter == 4999999)        //每10ms发送一次数据
        counter <= 0;
    else
        counter <= counter + 1;
        
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)       
        Send_Go <= 0;
    else if(counter == 1)
        Send_Go <= 1;
    else
        Send_Go <= 0;

    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)        
        Data <= 0;
    else if(Tx_done)
        Data <= Data + 1'b1;   
    
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

五、TB文件

`timescale 1ns / 1ps

module uart_tx_test_tb();
    reg Clk;
    reg Reset_n;
    wire uart_tx;
    
     uart_tx_test uart_tx_test(
        .Clk(Clk),
        .Reset_n(Reset_n),
        .uart_tx(uart_tx)
    );
    
    initial Clk = 1;
    always#10 Clk = ~Clk;
    
    initial begin
        Reset_n = 0;
        #201;
        Reset_n = 1;
        #50000000;    
    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

六、仿真波形展示

2
【附件:】链接:https://pan.baidu.com/s/1KNI2lWvdekhcJ-VJukWNeg?pwd=78h6
提取码:78h6

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小蓝xlanll/article/detail/599686
推荐阅读
相关标签
  

闽ICP备14008679号