串口UART 接收 Verilog实现

在实现串口时,吧每个bit分成14份,采样中间6个份,每一份采样一个点,就需要设置采样时钟。

本次实验设置波特率115200,系统时钟50Mhz,所以每个比特持续8680纳秒,系统时钟计数至434个周期时bit数加1,每个比特分成14份,即一份占用434/14=31个周期,在计数至31个周期中任取一个时刻采样就可以了,最后在所有bit都采样完成时进行判决,比如在第139份,判决6次采样0 1次数是否大于4。

以下为实验代码。

1:头文件

uart_rx模块:

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2024/03/12 16:07:50
// Design Name: 
// Module Name: uart_rx
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//
 
 
module uart_rx(
    uart_rx,
    clk,
    rst_n,
 
    Data_rx,
    Rx_done
    );
 
    input uart_rx;
    input clk;
    input rst_n;
 
    output reg [7:0]Data_rx;
    output reg Rx_done;
 
    
    localparam COUNT_115200=20'd433;    //对115200波特率计数
    localparam COUNT_14=5'd30;  //把一个比特位分割成14份,每一份间隔31个COUNT_115200
    reg [19:0] count_115200;
    reg [4:0]count_14;
 
    //对uart_rx两级打拍寄存用于信号同步
    reg uart_rx_sync1;
    reg uart_rx_sync2;
 
    //对同步后的信号uart_rx_sync2两级打拍寄存用于边缘判断
    reg uart_rx_reg1;
    reg uart_rx_reg2;
 
    //定义上升沿和下降沿标志信号
    wire posedge_uart_rx;
    wire negedge_uart_rx;
 
    //计数采样位置 当count_14每次加到26时,count_sample加一,算上起始位和停止位总共分为160份
    reg [7:0]count_sample;
 
    //存储6次采样结果 
    //reg [3:0]sample_bit;
    
    //计数采样次数里面1的个数,如果1大于4就取1   反之取0
    reg [3:0]number_start;
    reg [3:0]number_stop;
    reg [3:0]number_bit[7:0];
    
    //数据接收使能 在检测到下降沿时开始有效为1,Rx_done有效即接收完成时无效为0,其余时间为无效0
    reg Rx_en;
 
    //对接收到的数据bit数进行计数
    reg [3:0]bit_count;
    
    //先对接收信号存储
    //reg [7:0]Data;
 
 
    //定义采样时钟信号 在每个count_sample的只有一个时钟有效 从而每个采样点只采样一次
    reg sample_clk;
 
    always@(posedge clk or negedge rst_n)
    begin
      if(~rst_n)
        count_14<=5'd0;
      else if(Rx_en==1'b1)
      begin
       if(count_14==COUNT_14)
          count_14<=5'd0;
       else
          count_14<=count_14+1'b1;
      end
    end
 
    //约束采样时钟
    always@(posedge clk or negedge rst_n)
    begin
      if(~rst_n)
        sample_clk<=1'b0;
      else if(count_14==5'd10)
        sample_clk<=1'b1;
      else  
        sample_clk<=1'b0;
    end
 
    //将每个比特分成16份 从1计数到17 只采样6 7 8 9 10 11
    always@(posedge clk or negedge rst_n)
    begin
      if(~rst_n)
        count_sample<=8'd0;
      else if((count_sample==8'd139) && (count_14==COUNT_14))
        count_sample<=8'd0;
      else if((count_14==COUNT_14) && (Rx_en==1'b1))
        count_sample<=count_sample+1'b1; 
    end
/*
    //进行采样
    always@(posedge clk or negedge rst_n)
    begin
      if(~rst_n)
      begin
        sample_bit<=4'd0;
        number_1<=4'd0;
      end
      else
      else if((count_sample==5'd6) && (count_14==count_14))
      begin
        sample_bit[0]<=uart_rx_sync2;
          if(uart_rx_sync2==1'b1)
            number_1<=number_1+1'b1;    //对采样值里面1进行计数
      end
      else if((count_sample==5'd7) && (count_14==count_14))
      begin
        sample_bit[1]<=uart_rx_sync2;
         if(uart_rx_sync2==1'b1)
            number_1<=number_1+1'b1;
      end
      else if((count_sample==5'd8) && (count_14==count_14))
      begin
        sample_bit[2]<=uart_rx_sync2;
         if(uart_rx_sync2==1'b1)
            number_1<=number_1+1'b1;
      end
      else if((count_sample==5'd9) && (count_14==count_14))
      begin
        sample_bit[3]<=uart_rx_sync2;
         if(uart_rx_sync2==1'b1)
            number_1<=number_1+1'b1;
      end
      else if((count_sample==5'd10) && (count_14==count_14))
      begin
        sample_bit[4]<=uart_rx_sync2;
         if(uart_rx_sync2==1'b1)
            number_1<=number_1+1'b1;
      end
      else if((count_sample==5'd11) && (count_14==count_14))
      begin
        sample_bit[5]<=uart_rx_sync2;
         if(uart_rx_sync2==1'b1)
            number_1<=number_1+1'b1;
      end
    end
 
    always @(posedge clk)
    begin
        if(count_sample==5'd11)
          if(number_1>=3)
    end
*/
    
    //对信号进行寄存两拍
    always@(posedge clk or negedge rst_n)
    begin
      if(~rst_n)
        begin
          uart_rx_sync1<=1'b0;
          uart_rx_sync2<=1'b0;
        end
      else
        begin
          uart_rx_sync1<=uart_rx;
          uart_rx_sync2<=uart_rx_sync1;
        end
    end
    //进行波特率计数
    always@(posedge clk or negedge rst_n)
    begin
      if(~rst_n)
        count_115200<=20'd0;
      else if(Rx_en==1'b1)
      begin
        if(count_115200==COUNT_115200)
          count_115200<=20'd0;
        else  
          count_115200<=count_115200+1'b1;
      end
    end
    //对稳定后的信号进行上升沿和下降沿判断
    always@(posedge clk or negedge rst_n)
    begin
      if(~rst_n)
        begin
          uart_rx_reg1<=1'b0;
          uart_rx_reg2<=1'b0;
        end
      else
        begin
          uart_rx_reg1<=uart_rx_sync2;
          uart_rx_reg2<=uart_rx_reg1;
        end
    end
    assign posedge_uart_rx=uart_rx_reg1 & !uart_rx_reg2;
    assign negedge_uart_rx=!uart_rx_reg1 & uart_rx_reg2;
    //对Rx_done进行限制
    always@(posedge clk or negedge rst_n)
    begin
      if(~rst_n)
        Rx_done<=1'b0;
      else if(bit_count==4'd10)
        Rx_done<=1'b1;
      else  
        Rx_done<=1'b0;
    end
    //对Rx_en限制
    always@(posedge clk or negedge rst_n)
    begin
      if(~rst_n)
        Rx_en<=1'b0;
      else if(negedge_uart_rx==1'b1)
        Rx_en<=1'b1;
      else if(Rx_done==1'b1)
        Rx_en<=1'b0;
    end
 
    //对接收到的比特数进行计数
    always@(posedge clk or negedge rst_n)
    begin
      if(~rst_n)
        bit_count<=4'd0;
      else if(bit_count==4'd10)
        bit_count<=4'b0;
      else if((count_115200==COUNT_115200) && (Rx_en==1'b1))
        bit_count<=bit_count+1'b1;
    end
    /*
    always@(*)
    begin
      case(bit_count)
        4'd1: Data[0]=uart_rx_sync2;
        4'd2: Data[1]=uart_rx_sync2;
        4'd3: Data[2]=uart_rx_sync2;
        4'd4: Data[3]=uart_rx_sync2;
        4'd5: Data[4]=uart_rx_sync2;
        4'd6: Data[5]=uart_rx_sync2;
        4'd7: Data[6]=uart_rx_sync2;
        4'd8: Data[7]=uart_rx_sync2;
        
      endcase
    end
  */
    always @(posedge sample_clk or negedge rst_n) 
    begin
      if(~rst_n)
        begin
          number_start<=4'd0;
          number_stop<=4'd0;
          number_bit[0]<=4'd0;
          number_bit[1]<=4'd0;
          number_bit[2]<=4'd0;
          number_bit[3]<=4'd0;
          number_bit[4]<=4'd0;
          number_bit[5]<=4'd0;
          number_bit[6]<=4'd0;
          number_bit[7]<=4'd0;
        end
      else if(Rx_en==1'b1)
        begin
          case (count_sample)
            8'd0:
            begin
            number_start<=4'd0;
            number_stop<=4'd0;
            number_bit[0]<=4'd0;
            number_bit[1]<=4'd0;
            number_bit[2]<=4'd0;
            number_bit[3]<=4'd0;
            number_bit[4]<=4'd0;
            number_bit[5]<=4'd0;
            number_bit[6]<=4'd0;
            number_bit[7]<=4'd0;
            end
            8'd4,8'd5,8'd6,8'd7,8'd8,8'd9:number_start<=number_start+uart_rx_sync2;
            8'd18,8'd19,8'd20,8'd21,8'd22,8'd23:number_bit[0]<=number_bit[0]+uart_rx_sync2;
            8'd32,8'd33,8'd34,8'd35,8'd36,8'd37:number_bit[1]<=number_bit[1]+uart_rx_sync2;
            8'd46,8'd47,8'd48,8'd49,8'd50,8'd51:number_bit[2]<=number_bit[2]+uart_rx_sync2;
            8'd60,8'd61,8'd62,8'd63,8'd64,8'd65:number_bit[3]<=number_bit[3]+uart_rx_sync2;
            8'd74,8'd75,8'd76,8'd77,8'd78,8'd79:number_bit[4]<=number_bit[4]+uart_rx_sync2;
            8'd88,8'd89,8'd90,8'd91,8'd92,8'd93:number_bit[5]<=number_bit[5]+uart_rx_sync2;
            8'd102,8'd103,8'd104,8'd105,8'd106,8'd107:number_bit[6]<=number_bit[6]+uart_rx_sync2;
            8'd116,8'd117,8'd118,8'd119,8'd120,8'd121:number_bit[7]<=number_bit[7]+uart_rx_sync2;
            8'd130,8'd131,8'd132,8'd133,8'd134,8'd135:number_stop<=number_stop+uart_rx_sync2;
            default : 
            begin
            number_start<=number_start;
            number_stop<=number_stop;
            number_bit[0]<=number_bit[0];
            number_bit[1]<=number_bit[1];
            number_bit[2]<=number_bit[2];
            number_bit[3]<=number_bit[3];
            number_bit[4]<=number_bit[4];
            number_bit[5]<=number_bit[5];
            number_bit[6]<=number_bit[6];
            number_bit[7]<=number_bit[7];
            end
          endcase
        end  
    end
    always@(posedge clk or negedge rst_n)
    begin
      if(~rst_n)
        Data_rx<=8'd0;
      else if(count_sample==8'd139)
        begin
          if((number_start<=8'd2) &&(number_stop>=8'd4))
            begin
              Data_rx[0]<=(number_bit[0]>=8'd4) ? 1'b1 : 1'b0;
              Data_rx[1]<=(number_bit[1]>=8'd4) ? 1'b1 : 1'b0;
              Data_rx[2]<=(number_bit[2]>=8'd4) ? 1'b1 : 1'b0;
              Data_rx[3]<=(number_bit[3]>=8'd4) ? 1'b1 : 1'b0;
              Data_rx[4]<=(number_bit[4]>=8'd4) ? 1'b1 : 1'b0;
              Data_rx[5]<=(number_bit[5]>=8'd4) ? 1'b1 : 1'b0;
              Data_rx[6]<=(number_bit[6]>=8'd4) ? 1'b1 : 1'b0;
              Data_rx[7]<=(number_bit[7]>=8'd4) ? 1'b1 : 1'b0;
            end
        end
    end
endmodule

/*
//这个也能用
module uart_rx(
    Clk,
    Reset_n,
    uart_rx,
    Rx_Done,
    Rx_Data
);

    input Clk;
    input Reset_n;
    input uart_rx;
    output reg Rx_Done;
    output reg[7:0]Rx_Data;
    
    parameter CLOCK_FREQ = 50_000_000;
    parameter BAUD = 115200;
    parameter MCNT_BAUD = CLOCK_FREQ / BAUD - 1;
    
    reg [7:0]r_Rx_Data;
    
    reg [29:0]baud_div_cnt;
    reg en_baud_cnt;
    reg [3:0]bit_cnt;
    
    wire w_Rx_Done;
    wire nedge_uart_rx;
    
    reg r_uart_rx;
    
    reg dff0_uart_rx,dff1_uart_rx;
//波特率计数器逻辑
   always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        baud_div_cnt <= 0;
    else if(en_baud_cnt)begin
        if(baud_div_cnt == MCNT_BAUD)
            baud_div_cnt <= 0;
        else
            baud_div_cnt <= baud_div_cnt + 1'd1;
    end
    else
        baud_div_cnt <= 0;
  
        
//UART 信号边沿检测逻辑
    always@(posedge Clk)
        dff0_uart_rx <= uart_rx;
        
    always@(posedge Clk)
        dff1_uart_rx <= dff0_uart_rx;     
           
    always@(posedge Clk)
        r_uart_rx <= dff1_uart_rx;
        
    assign nedge_uart_rx = (dff1_uart_rx == 0) && (r_uart_rx == 1);
        
//波特率计数器使能逻辑
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        en_baud_cnt <= 0;
    else if(nedge_uart_rx)
        en_baud_cnt <= 1;
    else if((baud_div_cnt == MCNT_BAUD/2) && (bit_cnt == 0) && (dff1_uart_rx == 1))
        en_baud_cnt <= 0;
    else if((baud_div_cnt == MCNT_BAUD/2) && (bit_cnt == 9))
        en_baud_cnt <= 0;


//位计数器逻辑
    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)   
        bit_cnt <= 0;
    else if((bit_cnt == 9) && (baud_div_cnt == MCNT_BAUD/2))  
        bit_cnt <= 0;
    else if(baud_div_cnt == MCNT_BAUD)
        bit_cnt <= bit_cnt + 1'd1;

//位接收逻辑

    always@(posedge Clk or negedge Reset_n)
    if(!Reset_n)
        r_Rx_Data <= 8'd0;
    else if(baud_div_cnt == MCNT_BAUD/2)begin
        case(bit_cnt)
            1:r_Rx_Data[0] <= dff1_uart_rx;
            2:r_Rx_Data[1] <= dff1_uart_rx;
            3:r_Rx_Data[2] <= dff1_uart_rx;
            4:r_Rx_Data[3] <= dff1_uart_rx;
            5:r_Rx_Data[4] <= dff1_uart_rx;
            6:r_Rx_Data[5] <= dff1_uart_rx;
            7:r_Rx_Data[6] <= dff1_uart_rx;
            8:r_Rx_Data[7] <= dff1_uart_rx;
            default: r_Rx_Data <= r_Rx_Data;
        endcase     
    end

//接收完成标志信号
    assign w_Rx_Done = (baud_div_cnt == MCNT_BAUD/2) && (bit_cnt == 9);
    
     always@(posedge Clk)
        Rx_Done <= w_Rx_Done;

     always@(posedge Clk)
     if(w_Rx_Done)
        Rx_Data <= r_Rx_Data;
        
        
endmodule

*/



使用vivado的VIO IP核查看接收波形:

  • 9
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值