11.串口接收原理与思路

11.串口接收原理与思路

1.原理

  • 基本原理:采样。

  • 技巧是:一位数据采多次,统计得到该电平出现的次数,次数多的就是该电平值。

  • 起始位检测:通过边沿检测电路。

  • 串口接收模块整体框图
    在这里插入图片描述
    在这里插入图片描述

2.思路

  1. 对边沿电平进行检测

  2. 波特率的设置,我们这里要把它分割成16份
    在这里插入图片描述

  3. 对(bps_cnt)16位操作 总共10位数据 那么要计数到160

  4. 接收16个格子中的中间的数据(r_date,sto_date,sta_date )

  5. 基本的分频器(div_cnt)来得到bps_clk = ( div_cnt == Bps_DR /2) 和 使能端口(RX_EN)

  6. 接收数据

  7. 处理rx_done

3.代码

`timescale 1ns / 1ps
module uart_byte_tx(
sys_clk , sys_rst , baud_set ,date_rx  ,    date   ,     rx_done   );  
    input sys_clk   ;
    input sys_rst   ;
    input [2:0] baud_set  ;
    input date_rx   ;
    output reg [7:0] date     ;
    output reg rx_done  ; 

// 1. 滤波     
//  reg date_rx_sync_1 ;
//  reg date_rx_sync_2 ;
//  wire date_rx_sync ; 
//  always@(posedge sys_clk or negedge sys_rst )
//      if(!sys_rst) 
//          begin 
//         date_rx_sync_1 <= 0  ;
//          date_rx_sync_2 <= 0; 
//          end
//      else  
//              begin 
//          date_rx_sync_1 <= date_rx ;
//          date_rx_sync_2 <= date_rx_sync_1 ;
//              end 
          
 // assign    date_rx_sync =  date_rx_sync_2 ;

// 2.波特率设置
reg [8:0] bps_DR ;
always@(*) begin 
    case(baud_set)      // 一份数据分成了16份
    1 : bps_DR <= 325 ; // 1_000_000_000 / 9600 /20 /16
    2 : bps_DR <= 163 ; // 1_000_000_000 / 19200 /20/16     
    3 : bps_DR <= 81 ; // 1_000_000_000 / 38400 /20 /16
    4 : bps_DR <= 54 ; // 1_000_000_000 / 57600 /20 /16    
    5 : bps_DR <= 27 ; // 1_000_000_000 / 115200 /20/16 
 default bps_DR <= 325 ;
 endcase
            end
// 3.边沿检测
 reg [1:0] check_date_rx;
 wire negedge_date_rx; //下降沿检测
 //wire posedge_date_rx;
 always@(posedge sys_clk or negedge sys_rst )
    if (!sys_rst)
        check_date_rx <= 2'b00 ;
    else
        begin 
        //check_date_rx[0] <= date_rx;
        //check_date_rx[1] <= check_date_rx[0] ;
        check_date_rx <= { check_date_rx[0]  , date_rx };
        end 
assign negedge_date_rx = ( check_date_rx == 2'b10 );        
//assign posedge_date_rx = ( check_date_rx == 2'b01 );  

// 4. 检测到有效下降沿 产生 有效的使能信号 RX_EN
reg  RX_EN ;
reg [2:0 ] sta_date ;
reg [2:0]  sto_date ; 
always@(posedge sys_clk or negedge sys_rst )
   if (!sys_rst)
        RX_EN <= 0 ;
   else if (negedge_date_rx) 
         RX_EN <= 1;
   else if ((rx_done) || ( sta_date[2] == 1))  //当数据发送完成 或者 起始位不满足低电平
         RX_EN <= 0 ;
   else 
        RX_EN <= RX_EN ;
        
// 5. bps_DR 分频  
reg [8:0] div_cnt     ;
always@(posedge sys_clk or negedge sys_rst )
   if (!sys_rst)
    div_cnt <= 0 ;
    else if (RX_EN) begin 
        if( (bps_DR -  1) <= div_cnt)
           div_cnt <= 0 ;
         else 
                div_cnt <= div_cnt + 1'b1 ;  
                        end
     else 
        div_cnt <= 0 ;
 // 6 . 对波特率进行计数
wire  bps_clk ;
reg [7:0 ] bps_cnt ;
assign bps_clk = (div_cnt == (bps_DR -  1) /2 ) ;
always@(posedge sys_clk or negedge sys_rst )
   if (!sys_rst)
        bps_cnt <= 0 ;
    else if (RX_EN) begin
        if(bps_clk)         begin  
        //每来一个bps_clk 进行加一
                if ( 8'd159  <= bps_cnt)
                    bps_cnt<= 0 ;
                else
                    bps_cnt <=  bps_cnt + 1'd1 ;
                            end
         else 
                bps_cnt <= bps_cnt ; 
                    end
     else 
            bps_cnt <= 0  ;
            
// 7.数据的接收
reg [2:0] r_date [7:0] ;
always@(posedge sys_clk or negedge sys_rst )
   if (!sys_rst)  begin
        sta_date<= 0  ;
        r_date[0] <= 0  ;
        r_date[1] <= 0  ; 
        r_date[2] <= 0  ; 
        r_date[3] <= 0  ; 
        r_date[4] <= 0  ; 
        r_date[5] <= 0  ; 
        r_date[6] <= 0  ; 
        r_date[7] <= 0  ;   
        sto_date<= 0 ;      end 
    else if (bps_clk) begin
      case(bps_cnt) 
        0 :     begin 
              sta_date  <= 0  ;
              r_date[0] <= 0  ;
              r_date[1] <= 0  ; 
              r_date[2] <= 0  ; 
              r_date[3] <= 0  ; 
              r_date[4] <= 0  ; 
              r_date[5] <= 0  ; 
              r_date[6] <= 0  ; 
              r_date[7] <= 0  ;   
              sto_date<= 0 ; end 
        5,6,7,8,9,10,11:              sta_date <= sta_date + date_rx;
        21,22,23,24,25,26,27 :        r_date[0]<= r_date[0]+date_rx;
        37,38,39,40,41,42,43 :        r_date[1]<= r_date[1]+date_rx;
        53,54,55,56,57,58,59:         r_date[2]<= r_date[2]+date_rx;
        69,70,71,72,73,74,75:         r_date[3]<= r_date[3]+date_rx; 
        85,86,87,88,89,90,91:         r_date[4]<= r_date[4]+date_rx;
        101,102,103,104,105,106,107 : r_date[5]<= r_date[5]+date_rx;
        117,118,119,120,121,122,123:  r_date[6]<= r_date[6]+date_rx;
        133,134,135,136,137,138,139:  r_date[7]<= r_date[7]+date_rx;
        149,150,151,152,153,154,155:  sto_date <= sto_date +date_rx; 
       
         endcase
                            end

always@(posedge sys_clk or negedge sys_rst )
   if (!sys_rst)
        date <= 0 ;
   else if ((159 <= bps_cnt) && (bps_clk))begin 
   date[0]<=r_date[0][2] ;
   date[1]<=r_date[1][2] ;
   date[2]<=r_date[2][2] ;
   date[3]<=r_date[3][2] ;
   date[4]<=r_date[4][2] ;
   date[5]<=r_date[5][2] ;
   date[6]<=r_date[6][2] ;
   date[7]<=r_date[7][2] ; end
//8.rx_done
always@(posedge sys_clk or negedge sys_rst )
   if (!sys_rst)
        rx_done <= 0 ;        
    else if ((159 <= bps_cnt) && ( bps_clk ) )
        rx_done <= 1 ;
    else
        rx_done <= 0 ;    
endmodule

4.激励文件代码

`timescale 1ns / 1ps
module uart_byte_tx_tb( );
    reg sys_clk   ;
    reg sys_rst   ;
    reg [2:0] baud_set  ;
    reg date_rx   ;
    wire [7:0] date     ;
    wire rx_done  ; 
    
uart_byte_tx uart_byte_tx(
.sys_clk  (sys_clk )       , 
.sys_rst  (sys_rst)       , 
.baud_set (baud_set)           ,
.date_rx  (date_rx)       ,    
.date     (date )   ,     
.rx_done  (rx_done) 
);

initial  sys_clk = 1 ;
always#10 sys_clk = !sys_clk ;

initial 
        begin
        sys_rst = 0 ;
        date_rx = 1 ;
        baud_set = 5 ;
        #201;
        sys_rst = 1 ;
        #200;
        uart_tx_byte(8'b1001_1010);
        #90000
        uart_tx_byte(8'b1000_1000);
        #90000
        uart_tx_byte(8'b1001_1011);
        #90000
        $stop;
        end 

task uart_tx_byte;
    input [7:0] rx_date;
    begin
       date_rx = 1;
       #20;
       date_rx = 0;
       #8680;
       date_rx = rx_date[0] ;
       #8680;
       date_rx = rx_date[1] ; 
       #8680;
       date_rx = rx_date[2] ;
       #8680;  
       date_rx = rx_date[3] ;
       #8680;
       date_rx = rx_date[4] ; 
       #8680;
       date_rx = rx_date[5] ;
       #8680;      
       date_rx = rx_date[6] ;
       #8680;
       date_rx = rx_date[7] ; 
       #8680;
        date_rx = 1 ;
       #8680; end
endtask

endmodule

5.仿真结果

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值