时序图
`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&®2)?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