FPGA always语句块实现rx串口

ffa9e4cf853145b6b5edca4fdb42d4c8.jpg

 时序图

`timescale 1ns / 1ps
//rx端口 :always语句块的写法
//1、rx是用来接收数据的(涉及数据传输--->防止亚稳态-->打拍:打一拍)
//2、需要根据数据帧结构来进行数据接收
    //2-1、需要只知道处理一个bit的时间--->需要一个bit计时器-->cnt_clk(传输一个Bit需要的时钟周期:时间/波特率)
    //2-2、需要一个bit位计数器(用来对bit位进行计数,方便看具体传输到哪个位置,便于取出一帧数据中的有效数据位部分)bit计时器推动bit计数器自加
    //2-3、抓取有效数据(需要一个寄存器--->寄存有效数据)
//3、规定一个工作时间--->en     起始位开始(采集下降沿)上班                    停止位结束(cnt_bit==9)下班

module rx(
             input                    sysclk           ,
             input                    rst_n            ,
             input                    rx               ,//一根数据线-->传输(串行输入,数据一个bit一个bit的输入进来)数据的

             output        [7:0]     rx_data ,  //并行输出的有效数据位     
             output                  rx_done   /Ç信号(握手信号)--->作用是意味着一帧数据传输完成   rx_done==1--->别的模块可以正常使用rx_data

    );
    
             reg            reg1;//第一拍-->缓存输入进来rx数据线上的数据:防止亚稳态
             reg            reg2;//第二拍-->将第一拍的数据缓存到第二拍:采集下降沿
             reg   [31:0]    cnt_clk;//传输一个bit需要的时钟周期
             reg   [9:0]    cnt_bit;//bit位计数器-->能够表示具体传输到哪一个Bit位了
             wire           flag;//采集下降沿的信号  flag==1 有效信号
             reg             en;//规定数据传输的工作时间   en拉高-->数据在进行传输   en拉低--->数据不传输
             reg   [7:0]    data_reg;//有效数据位寄存器-->在整个帧结构中抓取有效数据位
           parameter delay = clk/BPS;//传输一个bit需要的周期数      -->   5208:传输一个bit需要5208个周期(每个周期是20ns)
           parameter BPS = 9600;//声明波特率(自己选择
           parameter clk = 50_000_000;
           // bit计时器模块
           always@(posedge sysclk)
              if(!rst_n)
                cnt_clk<=0;
             else if(en==1)begin//en拉高表示工作时间(传输数据)
          if(cnt_clk==delay-1)//传输一位bit的时钟周期
                   cnt_clk<=0;
                else
                      cnt_clk<=cnt_clk+1;
              end        
            else//en没有拉高 不工作
            cnt_clk<=0;
           
           //bit计数器模块
           always@(posedge sysclk)
              if(!rst_n)
                cnt_bit<=0;
            else if(en==1)begin
         if(cnt_clk==delay-1) //传输一个bit到了 计数器开始自加                
              cnt_bit<=cnt_bit+1;
           else
                 cnt_bit<=cnt_bit;
            end
            else
            cnt_bit<=0;
            
            
            
            //reg寄存数据模块
             always@(posedge sysclk)
              if(!rst_n)begin
                 reg1<=1;//因为采集下降沿,数据又是从空闲到起始位(如果是多帧数据,上一个数据结束总是停止位高电平,下一帧数据开始总是起始位低电平)
                 reg2<=1;//因为采集下降沿,数据又是从空闲到起始位(如果是多帧数据,上一个数据结束总是停止位高电平,下一帧数据开始总是起始位低电平)

           end
             else begin
                reg1<=rx;//开始工作开始传输数据 数据先寄存到reg1  然后到reg2
                reg2<=reg1;
           end
           
           ///下降沿采集成功标志信号  

           assign  flag = (~reg1&&reg2)?1:0;
           
                    
           
           //工作时间模块
             always@(posedge sysclk)
              if(!rst_n)
               en<=0;
               else if(flag==1)//下降沿采集到了就拉高
                  en<=1;
          else if(cnt_bit==9&&cnt_clk==delay/2-1)//停止位结束
                  en<=0;
            else
                  en<=en;  
                  
                  
              //data_reg有效数据位传输模块
        always@(posedge sysclk)
              if(!rst_n)
               data_reg<=0;   
          else if(en==1&&cnt_bit>0&&cnt_bit<9&&cnt_clk==delay/2-1)//数据位中间时刻采样--->避免数据交接点的亚稳态现象引起的数据错乱现象        
               data_reg[cnt_bit-1]<=reg2; //数据通过二拍一位一位的传入到数据寄存器当中
            else if(en==1)
              data_reg<=data_reg;      
            else
              data_reg<=0;      
                  
      assign  rx_data = (cnt_bit==9&&cnt_clk==delay/2-1)?data_reg:rx_data;    
      assign  rx_done = (cnt_bit==9&&cnt_clk==delay/2-1)?1:0;   
           
           
endmodule

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值