Vivado 串口通信(UART)------串口发送

Vivado 摸鱼记录 Day_9  (∪。∪)。。。zzz

review

         day_8 串口发送原理 Vivado 串口通信(UART)原理A ------串口发送实验-CSDN博客

         day_8 实现了一个简单的串口程序

1. 今日摸鱼任务 (∪。∪)。。。zzz

        1. 实现 uart_tx(input clk , input reset_n , input [7:0]data , input Send_Go ,
                               output reg uart_tx , output reg Tx_Done )

        2. 使用uart_tx 实现day_8任务

2. uart_tx

        分析:Send_Go为一个短暂时间信号,如按键按下、人路过等

                   对比day_8:

                显然需要在接收到Send_Go 后设置使能信号Send_en控制信号发送

2.1 design sources

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

2.2 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_t_1(.clk(clk) , .reset_n(reset_n) , .data(data) ,.Send_Go(Send_Go),
               .uart_tx(uart_tx) , .Tx_Done(Tx_Done)  );
    initial clk = 1 ;
    always #10 clk = ~clk ;
    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

2.2.1 Tx_Done 与 (tx_flag==9)&&(counter_bps == bps_c - 1)

else if (Tx_Done) 

        由上面两个图可以看出,tx_flag出现了一个时钟周期的状态a

        虽然对uart_tx无影响  default : uart_tx  <= uart_tx; 但还是修改一下:

else if (tx_flag==9)&&(counter_bps == bps_c - 1))

2.2.2 data 与 r_data

无r_data        uart_tx <= data[*];
 由上图可以看出:直接输出data,在data变化且正在输出时,会使输出数据错误
      // Send_Go改变发送信号         
        reg [7:0]r_data;
        always@(posedge clk)
        if(Send_Go)
         r_data <= data;
        else
         r_data <= r_data;        

由上面两图可以看出,使用r_data Send_Go 信号后对data锁存,可以保证每次发送的是当时时刻的数据。

3. uart_tx_test 实现今日摸鱼任务(∪。∪)。。。zzz

3.1 design sources

module uart_tx_test(input clk , 
                    input reset_n , 
                    input [7:0]data ,
                    output uart_tx , 
                    output reg LED);

   
    reg Send_Go ;   
    wire Tx_Done;
    UART_tx #(.BAUD(115200))
     uart_tx_test_(.clk(clk) , .reset_n(reset_n) , .data(data) ,.Send_Go(Send_Go),
               .uart_tx(uart_tx) , .Tx_Done(Tx_Done)  );


    // 1s
    parameter counter_second = 50000000; 
    reg [30:0] counter ; 
    always@(posedge clk or negedge reset_n)
    if(! reset_n) 
        counter <= 0 ;
    else if(counter == counter_second - 1)    
        counter <= 0 ;
    else 
        counter <= counter + 1'b1 ;


    // tx  Send_Go
    always@(posedge clk or negedge reset_n)
    if(! reset_n) 
        Send_Go <= 1 ;
    else if(counter == counter_second - 1)    
        Send_Go <= 1 ;
    else 
        Send_Go <= 0 ;


    // led
    always@(posedge clk or negedge reset_n)
    if(! reset_n) 
        LED <= 0 ;
    else if(Tx_Done)    
        LED <= 1 ;
    else 
        LED <= 0 ;


endmodule

wire Tx_Done;    Tx_Done 是 UART_tx 的输出
UART_tx #(.BAUD(115200))   本次实验要求波特率为115200

3.2 uart_tx_text_tb

`timescale 1ns / 1ns

module uart_tx_text_tb();
    
    reg clk ,reset_n ;
    reg [7:0]data;
    wire uart_tx , LED ;
    uart_tx_test#(.counter_second(8000)) 
                text_tb(.clk(clk) , .reset_n(reset_n) , .data(data) ,
                        .uart_tx(uart_tx) , .LED(LED));           
    initial clk = 1 ;
    always #10 clk = ~clk ;
    initial
    begin
       data = 8'b0101_1111;
        reset_n = 0 ;
        #20001;
        reset_n = 1 ;       
        #80000 ;        
        data = 8'b1101_0111;#60;        
        #200000 ;
        data = 8'b1101_0000;#60;
        #200000 ;
        $stop;
    end
    
endmodule

uart_tx_test#(.counter_second(8000))    本次波特率115200 , 为测试方便,减少周期时间

        看着貌似没有问题,不过上板测试发现LED闪时间太短啦!

// led
    always@(posedge clk or negedge reset_n)
    if(! reset_n) 
        LED <= 0 ;
    else if(Tx_Done)    
        LED <= 1 ;
    else if(Send_Go)  
        LED <= 0 ;      

//不过感觉变成了一直亮

         (主要原因是波特率115200 )86.8us观察也太难为人了有点(∪。∪)。。。zzz

//好啦,摸鱼结束哩(∪。∪)。。。zzz

  • 13
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值