Vivado 串口通信(UART)原理B ------串口接收仿真

Vivado 摸鱼记录 Day_10    ๑乛v乛๑

review

         day_9 实现了串口发送模块与使用 Vivado 串口通信(UART)------串口发送-CSDN博客

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

         串口发送:并 ---> 串

         串口接收:串 ---> 并

1. 串口接收原理

        小梅哥视频链接 13A_UART串口接收逻辑设计要点分析_哔哩哔哩_bilibili

Q1:  如何从串行数据准确的接收每一位数据?  取计数中点

Q2:  如何检测起始位的下降沿 ?  下降沿检测电路

Q3:  波特率分频计数器使能逻辑    对于毛刺信号的处理

Q4:  判断当前信号是第几位?    使用位计数器

2. 今日摸鱼任务    ๑乛v乛๑    完成串口接收仿真

3. uart_rx

3.1 design sources

module uart_rx_1(input clk ,
                 input reset_n ,
                 input uart_rx ,
                 output reg [7:0]rx_data,
                 output reg rx_done    );

        // bps 
            
       // neg_rx_go   

        避免亚稳态的影响,采用如下电路
          关于亚稳态亚稳态浅浅学习 ( ੭ ˙ᗜ˙ )੭-CSDN博客


      // rx_en 
  
     // rx_flag
     
     // [7:0]rx_data   
     
    // rx_done
     
endmodule

module uart_rx_1(input clk ,
                 input reset_n ,
                 input uart_rx ,
                 output reg [7:0]rx_data,
                 output reg rx_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 rx_en ;   
    reg[3:0] rx_flag;
        // bps 
        reg [30:0] counter_bps ;        
      always@(posedge clk or negedge reset_n)
        if(! reset_n) 
            counter_bps <= 0 ;
        else if (rx_en)
            if(counter_bps == bps_c - 1)
                counter_bps <= 0 ;
            else
                counter_bps <= counter_bps + 1'b1 ;
        else
            counter_bps <= 0 ;


        reg dff_rx_0 , dff_rx_1 ;
        reg r_uart_rx; 
        wire neg_rx_go ;
        always@(posedge clk )    
            dff_rx_0 <= uart_rx ;
        always@(posedge clk )    
            dff_rx_1 <= dff_rx_0 ;
        always@(posedge clk )    
            r_uart_rx <= dff_rx_1 ;
            
        assign neg_rx_go = (dff_rx_1 == 0)&&(r_uart_rx == 1);
        
      // rx_en 
        always@(posedge clk or negedge reset_n)
        if(! reset_n) 
            rx_en <= 0 ;
        else if(neg_rx_go) 
            rx_en <= 1 ;
        else if((rx_flag==9)&&(counter_bps == bps_c - 1))
            rx_en <= 0 ;
        else if((rx_flag==0)&&(counter_bps == bps_c/2 )&&(dff_rx_1==1))   //处理毛刺信号
            rx_en <= 0 ;
               
     // rx_flag
        always@(posedge clk or negedge reset_n)
        if(!reset_n) rx_flag <= 4'b0000 ;   //调试发现rx_flag一直为0,结果问题出在没写!
        else if(counter_bps == bps_c - 1)
        begin
            if(rx_flag == 9)
                rx_flag <= 0 ;
            else
                rx_flag <= rx_flag + 1'b1 ;
        end    

                                ​​​​​​​        //注意这里后边有修改
     // [7:0]rx_data   
     always@(posedge clk )
       if(!rx_en) rx_data <= rx_data;
       else if(counter_bps == bps_c / 2)      //取计数中点
        begin 
            case(rx_flag)
            1 : rx_data[0] <= dff_rx_1;
            2 : rx_data[1] <= dff_rx_1;
            3 : rx_data[2] <= dff_rx_1;
            4 : rx_data[3] <= dff_rx_1;
            5 : rx_data[4] <= dff_rx_1;
            6 : rx_data[5] <= dff_rx_1;
            7 : rx_data[6] <= dff_rx_1;
            8 : rx_data[7] <= dff_rx_1;
            default : rx_data <= rx_data;
            endcase
        end    
 


    // rx_done
     always@(posedge clk)
            rx_done <= (rx_flag==9)&&(counter_bps == bps_c - 1);
        
endmodule

3.2 uart_rx_text_tb

`timescale 1ns / 1ns
module uart_rx_tb();
    reg clk , reset_n ;
    reg uart_rx;
    wire [7:0]rx_data;
    wire rx_done;
    uart_rx_1 uart_rx_tb_( .clk(clk) ,
               .reset_n(reset_n) ,
               .uart_rx(uart_rx) ,
               .rx_data(rx_data),
               .rx_done(rx_done)    );
    
    initial clk = 1 ;
    always #10 clk = ~clk ;
    initial
    begin
        
        reset_n = 0 ;
        uart_rx = 1 ;
        #201;
        reset_n = 1 ;  #2000;     
        //   0F   0000_1111
        uart_rx = 0 ; #(5208*20);
        uart_rx = 0 ; #(5208*20);
        uart_rx = 0 ; #(5208*20);
        uart_rx = 0 ; #(5208*20);
        uart_rx = 0 ; #(5208*20);
        uart_rx = 1 ; #(5208*20);
        uart_rx = 1 ; #(5208*20);
        uart_rx = 1 ; #(5208*20);
        uart_rx = 1 ; #(5208*20);
        uart_rx = 1 ; #(5208*20);
        #200000;
     //   55   0101_0101
        uart_rx = 0 ; #(5208*20);
        uart_rx = 1 ; #(5208*20);
        uart_rx = 0 ; #(5208*20);
        uart_rx = 1 ; #(5208*20);
        uart_rx = 0 ; #(5208*20);
        uart_rx = 1 ; #(5208*20);
        uart_rx = 0 ; #(5208*20);
        uart_rx = 1 ; #(5208*20);
        uart_rx = 0 ; #(5208*20);
        uart_rx = 1 ; #(5208*20);
        #200000;
        
        $stop;
    end
    
    
endmodule
 

                红框部分表示输出rx_data会在传送过程中有变化,同串口发送,设置锁存data

3.3 设置 r_rx_data 后 design sources

module uart_rx_1(input clk ,
                 input reset_n ,
                 input uart_rx ,
                 output reg [7:0]rx_data,
                 output reg rx_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 rx_en ;   
    reg[3:0] rx_flag;
        // bps 
        reg [30:0] counter_bps ;        
      always@(posedge clk or negedge reset_n)
        if(! reset_n) 
            counter_bps <= 0 ;
        else if (rx_en)
            if(counter_bps == bps_c - 1)
                counter_bps <= 0 ;
            else
                counter_bps <= counter_bps + 1'b1 ;
        else
            counter_bps <= 0 ;
        reg dff_rx_0 , dff_rx_1 ;
        reg r_uart_rx; 
        wire neg_rx_go ;
        always@(posedge clk )    
            dff_rx_0 <= uart_rx ;
        always@(posedge clk )    
            dff_rx_1 <= dff_rx_0 ;
        always@(posedge clk )    
            r_uart_rx <= dff_rx_1 ;
            
        assign neg_rx_go = (dff_rx_1 == 0)&&(r_uart_rx == 1);
        
      // rx_en 
        always@(posedge clk or negedge reset_n)
        if(! reset_n) 
            rx_en <= 0 ;
        else if(neg_rx_go) 
            rx_en <= 1 ;
        else if((rx_flag==9)&&(counter_bps == bps_c - 1))
            rx_en <= 0 ;
        else if((rx_flag==0)&&(counter_bps == bps_c/2 )&&(dff_rx_1==1)) 
            rx_en <= 0 ;
               
     // rx_flag
        always@(posedge clk or negedge reset_n)
        if(!reset_n) rx_flag <= 4'b0000 ;
        else if(counter_bps == bps_c - 1)
        begin
            if(rx_flag == 9)
                rx_flag <= 0 ;
            else
                rx_flag <= rx_flag + 1'b1 ;
        end    


     // [7:0]r_rx_data   
     reg [7:0] r_rx_data;
     always@(posedge clk )
       if(!rx_en) r_rx_data <= r_rx_data;
       else if(counter_bps == bps_c / 2)
        begin 
            case(rx_flag)
            1 : r_rx_data[0] <= dff_rx_1;
            2 : r_rx_data[1] <= dff_rx_1;
            3 : r_rx_data[2] <= dff_rx_1;
            4 : r_rx_data[3] <= dff_rx_1;
            5 : r_rx_data[4] <= dff_rx_1;
            6 : r_rx_data[5] <= dff_rx_1;
            7 : r_rx_data[6] <= dff_rx_1;
            8 : r_rx_data[7] <= dff_rx_1;
            default : r_rx_data <= r_rx_data;
            endcase
        end      


    // rx_done
     always@(posedge clk)
            rx_done <= (rx_flag==9)&&(counter_bps == bps_c - 1);
    // rx_data ;
       always@(posedge clk)
           if(rx_done) rx_data <= r_rx_data;  
endmodule

//嘎嘎嘎~~~~~

//好啦,摸鱼结束哩  ๑乛v乛๑

//下一次完成摸鱼任务白白~

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值