串口UART发送协议

根据小梅哥教程和网上资料编写。

1.串口通信原理:

通用异步收发传输器(Universal Asynchronous Receiver/Transmitter,UART)是一种异步收发传输器,其在数据发送时将并行数据转换成串行数据来传输,在数据接收时将接收到的串行数据转换成并行数据,可以实现全双工传输和接收。它包括了 RS232、RS449、RS423、RS422和RS485等接口标准规范和总线标准规范。

数据帧格式:起始位(1‘b0)+ 数据位(8bit) + 1位校验位 + 停止位(1’b1)

大多资料记在笔记本里,这里记一下实现代码。

设计功能:波特率为9600,8位数据位,无校验位,无流控功能,每1s发送一次当前8位拨码开关的值,每次发送完成后将LED的状态翻转。

2.uart_tx:

module UART_tx(
    input clk , 
    input reset_n , 
    input [7:0]data ,   //数据
    input Send_Go ,    //发送使能
    output reg uart_tx ,   //输出寄存器,并行数据->串行数据发送出去
    output reg Tx_Done  );    //发送完成信号
    //默认使用波特率BAUD 9600  时钟频率 CLK_FREQ  50MHz
    parameter start_bit = 0 ;
    parameter stop_bit  = 1 ;
    parameter BAUD = 9600;
    parameter CLK_FREQ = 50_000_000;
    parameter bps_c = CLK_FREQ / BAUD ;    
    
        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_flag==9)&&(counter_bps == bps_c - 1)) 

                        //else if (Tx_Done) tx_flag <= 0 ;
            Send_en <= 0 ;
        
      // bps
      reg [30:0] counter_bps ;        
      always@(posedge clk or negedge reset_n)
        if(! reset_n) 
            counter_bps <= 0 ;
        else if (Send_en)
            if(counter_bps == bps_c - 1)
                counter_bps <= 0 ;
            else
                counter_bps <= counter_bps + 1'b1 ;
        else
            counter_bps <= 0 ;
            
      // 发送状态
      reg [3:0] tx_flag;
      always@(posedge clk or negedge reset_n)
        if(! reset_n) 
            tx_flag <= 0 ;
        else if (!Send_en) tx_flag <= 0 ;
        else if ((tx_flag==9)&&(counter_bps == bps_c - 1))

                //else if (Tx_Done) tx_flag <= 0 ;
             tx_flag <= 0 ;
        else
             if(counter_bps == bps_c - 1)
                tx_flag <= tx_flag + 1'b1 ;


      // Send_Go改变发送信号         
        reg [7:0]r_data;
        always@(posedge clk)
        if(Send_Go )
         r_data <= data;
        else
         r_data <= r_data;          

         
    //  tx_flag          
       always@(*)
       if(!Send_en) uart_tx <= 1'b1;
       else
        begin 
            case(tx_flag)
            4'b0000 : uart_tx <= start_bit;
            4'b0001 : uart_tx <= r_data[0];
            4'b0010 : uart_tx <= r_data[1];
            4'b0011 : uart_tx <= r_data[2];
            4'b0100 : uart_tx <= r_data[3];
            4'b0101 : uart_tx <= r_data[4];
            4'b0110 : uart_tx <= r_data[5];
            4'b0111 : uart_tx <= r_data[6];
            4'b1000 : uart_tx <= r_data[7];
            4'b1001 : uart_tx <= stop_bit;
            default : uart_tx  <= uart_tx;
            endcase
            
        end      
        
        
        always@(posedge clk or negedge reset_n)        
        Tx_Done <= (tx_flag==9)&&(counter_bps == bps_c - 1);
     
endmodule

3.uart_tx_tb:测试:

`timescale 1ns / 1ns
module UART_tx_tb();
    reg clk ,reset_n , Send_Go ;
    reg [7:0]data;
    wire uart_tx , Tx_Done;
    UART_tx  uart_tx_inst(
        .clk(clk) , 
        .reset_n(reset_n) ,
        .data(data) ,
        .Send_Go(Send_Go),
        .uart_tx(uart_tx) ,
        .Tx_Done(Tx_Done)  );
    initial begin clk = 0 ;
    forever
    #10 clk = ~clk ;
    end
    
    initial
    begin
        Send_Go = 0;
        data = 8'b0110_0000;
        reset_n = 0 ;
        #20001;
        reset_n = 1 ;       
        Send_Go = 1 ; #40;
        Send_Go = 0 ; #400000;
        data = 8'b0101_1111;
        Send_Go = 0 ; #500000;
        
        data = 8'b1101_0101;#500000;
        Send_Go = 1 ;#40;
        Send_Go = 0 ;#1200000 ;
        $stop;
    end
    
endmodule

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值