串口接收原理与思路

 利用两个D触发器来作为边沿检测电路

  //两个D触发器的存储逻辑电路
reg [1:0]uart_rx_r;
    always@(posedge Clk)begin
        uart_rx_r[0]<=uart_rx;
        uart_rx_r[1]<=uart_rx_r[0];[1]是前一时刻的值
    end

    //检测上/下降沿
    wire pedge_uart_rx;//检测上升沿
    assign pedge_uart_rx=((uart_rx_r[1]==0)&&(uart_rx_r[0]==1));
    //等价于assign pedge_uart_rx=(uart_rx_r==2'b01)?1:0;
     wire nedge_uart_rx;//检测下降沿沿
    assign nedge_uart_rx=((uart_rx_r[1]==1)&&(uart_rx_r[0]==0));
    //等价于assign pedge_uart_rx=(uart_rx_r==2'b10)?1:0;

 分段采样

时间精度:设波特率为9600,则计数周期为1000000000/9600/16/20= 325,即计数325次产生一个BPS_CLK,除以16的原因是因为将一段数据分成了16段,以方便有舍取得进行采样。

若为115200,则计数周期为27。

module uart_byte_rx(
    Clk,
    Reset_n,
    Baud_Set,
    uart_rx,
    Data,
    Rx_Done
);
    input Clk;
    inout Reset_n;
    input [2:0]Baud_Set;
    input uart_rx;
    output reg [7:0]Data;
    output reg Rx_Done;
    
    reg [1:0]uart_rx_r;
    always@(posedge Clk)begin
        uart_rx_r[0]<=uart_rx;
        uart_rx_r[1]<=uart_rx_r[0];
    end
    wire pedge_uart_rx;//检测上升沿
    assign pedge_uart_rx=((uart_rx_r[1]==0)&&(uart_rx_r[0]==1));
    //等价于assign pedge_uart_rx=(uart_rx_r==2'b01)?1:0;
     wire nedge_uart_rx;//检测下降沿沿
    assign nedge_uart_rx=((uart_rx_r[1]==1)&&(uart_rx_r[0]==0));
    //等价于assign pedge_uart_rx=(uart_rx_r==2'b10)?1:0;
    
    //柑橘波特路计算计数周期
    reg [8:0] Bps_DR;
    always@(*)
        case(Baud_Set)
            0:Bps_DR=100000000/9600/16/20-1;
            1:Bps_DR=100000000/19200/16/20-1;
            2:Bps_DR=100000000/38400/16/20-1; 
            3:Bps_DR=100000000/57600/16/20-1;
            4:Bps_DR=100000000/115200/16/20-1;
            default:Bps_DR=100000000/9600/16/20-1;
       endcase
      wire bps_clk_16x;
      assign bps_clk_16x=(div_cnt==Bps_DR/2);//在每一段的中间时刻采样。
      
       reg RX_EN;//分频计数器
       always@(posedge Clk or negedge Reset_n)
      if(!Reset_n)
        RX_EN<=0;
      else if(nedge_uart_rx)
        RX_EN<=1;
      else if(Rx_Done||sta_bit>=4)
         RX_EN<=0;
      
      reg [8:0]div_cnt;//分频计数器
       always@(posedge Clk or negedge Reset_n)
      if(!Reset_n)
        div_cnt<=0;
       else if( RX_EN)begin
            if(div_cnt<=Bps_DR)
                div_cnt<=0;
             else
                div_cnt<=div_cnt+1'b1;
        end
       else 
            div_cnt<=0;
      
      //计数
      reg [7:0]bps_cnt;
      always@(posedge Clk or negedge Reset_n)
      if(!Reset_n)
            bps_cnt<=0;
       else if(RX_EN)begin
                if(bps_clk_16x)begin
        if(bps_cnt==160)
            bps_cnt<=0;
        else 
            bps_cnt<=bps_cnt+1'b1;
        end
        else
        bps_cnt<=bps_cnt;
      end
      else
        bps_cnt<=0;
        
        //计采样个数
        reg[2:0]r_data[7:0];//定义了一个二维寄存器,前面定义位宽,后面是个数,例r_data[0][1]
        reg[2:0]sta_bit;
        reg[2:0]sto_bit;
        
        //接收
        always@(posedge Clk or negedge Reset_n)
        if(!Reset_n)begin
            sta_bit<=0;
            sto_bit<=0;
            r_data[0]<=0;
            r_data[1]<=0;
            r_data[2]<=0;
            r_data[3]<=0;
            r_data[4]<=0;
            r_data[5]<=0;
            r_data[6]<=0;
            r_data[7]<=0;
         end
         else if(bps_clk_16x) begin
            case(bps_cnt)
                0:begin
                    sta_bit<=0;
                    sto_bit<=0;
                    r_data[0]<=0;
                    r_data[1]<=0;
                    r_data[2]<=0;
                    r_data[3]<=0;
                    r_data[4]<=0;
                    r_data[5]<=0;
                    r_data[6]<=0;
                    r_data[7]<=0;
               end
                5,6,7,8,9,10,11:sta_bit<=sta_bit+uart_rx;
                21,22,23,24,25,26,27:r_data[0]<=r_data[0]+uart_rx;
                37,38,39,40,41,42,43:r_data[1]<=r_data[1]+uart_rx;
                53,54,55,56,57,58,59:r_data[2]<=r_data[2]+uart_rx;
                69,70,71,72,73,74,75:r_data[3]<=r_data[3]+uart_rx;
                85,86,87,88,89,90,91:r_data[4]<=r_data[4]+uart_rx;
                101,102,103,104,105,106,107:r_data[5]<=r_data[5]+uart_rx;
                117,118,119,120,121,122,123:r_data[6]<=r_data[6]+uart_rx;
                133,134,135,136,137,138,139:r_data[7]<=r_data[7]+uart_rx; 
                149,150,151,152,153,154,155:sto_bit<=sto_bit+uart_rx; 
                default:;
            endcase 
          end         
       always@(posedge Clk or negedge Reset_n)
        if(!Reset_n)
               Data<=0;
         else if(bps_clk_16x&&(bps_cnt==159))begin
            Data[0]<=(r_data[0]>=4)?1'b1:1'b0;//Data[0]<=r_data[0][2];
            Data[1]<=(r_data[1]>=4)?1'b1:1'b0;
            Data[2]<=(r_data[2]>=4)?1'b1:1'b0;
            Data[3]<=(r_data[3]>=4)?1'b1:1'b0;
            Data[4]<=(r_data[4]>=4)?1'b1:1'b0;
            Data[5]<=(r_data[5]>=4)?1'b1:1'b0;
            Data[6]<=(r_data[6]>=4)?1'b1:1'b0;
            Data[7]<=(r_data[7]>=4)?1'b1:1'b0;
         end
       always@(posedge Clk or negedge Reset_n)
        if(!Reset_n)
            Rx_Done<=0;
        else if((div_cnt==Bps_DR/2)&&(bps_cnt==160))
            Rx_Done<=1;
        else
            Rx_Done<=0;
endmodule

//因为除法保留整数,所以存在误差。

testbench

`timescale 1ns/1ps
module uart_byte_rx_tb();
    reg Clk;
    reg  Reset_n;
    wire [2:0]Baud_Set;
    reg uart_rx;
    wire  [7:0]Data;
    wire  Rx_Done;
    
    assign Baud_Set=4;
    uart_byte_rx uart_byte_rx(
        Clk,
       Reset_n,
        Baud_Set,
        uart_rx,
        Data,
        Rx_Done
        );
        initial Clk=1;
        always#10 Clk=~Clk;
        
        initial begin
           Reset_n=0;
           uart_rx=1;
           #201;
           Reset_n=1;
           #200;
           uart_tx_byte(8'h5a);
           //@(posedge Rx_Done);
           #90000;
           uart_tx_byte(8'ha5);
          // @(posedge Rx_Done);
           #90000;
           uart_tx_byte(8'h86);
           //@(posedge Rx_Done);
           #90000;
           $stop;
           
        end
        
        task uart_tx_byte;
            input [7:0]tx_data;
            begin
                 uart_rx=1;
                 #20;
                 uart_rx=0;
                 #8680;//延时
                 uart_rx=tx_data[0];
                 #8680;
                 uart_rx=tx_data[1];
                  #8680;//延时
                 uart_rx=tx_data[2];
                 #8680;
                 uart_rx=tx_data[3];
                  #8680;//延时
                 uart_rx=tx_data[4];
                 #8680;
                 uart_rx=tx_data[5];
                  #8680;//延时
                 uart_rx=tx_data[6];
                 #8680;
                 uart_rx=tx_data[7];
                 #8680;
                 uart_rx=1;
                 #8680;
              end
           endtask
endmodule
                                

                    

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值