前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >串口通信控制器的Verilog HDL实现(四) 接收模块的Verilog HDL 实现

串口通信控制器的Verilog HDL实现(四) 接收模块的Verilog HDL 实现

作者头像
瓜大三哥
发布2018-02-24 17:31:03
1.1K0
发布2018-02-24 17:31:03
举报
文章被收录于专栏:瓜大三哥瓜大三哥

但凡涉及到双方通信的系统,接收机的复杂度往往都是高于发送机的,对于串口通信系统也如此。在接收系统中,起始状态和数据都需要依靠接收端检测得到,为了避免毛刺影响,能够得到正确的起始信号和有效数据,需要完成一个简单的最大似然判决,其方法如下:由于bclk信号的频率为9600Hz的16倍,则对于每个数据都会有16个样值,最终的采样比特值为出现次数超过8次的电平逻辑值。

整个接收模块的状态机包含3个状态:s_idle、s_sample以及s_stop,其状态转移图如图13-8所示。

s_idle状态为空闲状态,用于检测接收数据链路上的起始信号。系统复位后,接收模块就处于这一状态,一直检测rxd数据是否从1跳变为0,一个起始位代表着新的一帧数据。一旦检测到起始位,立刻进入s_sample状态,采集有效数据。在此状态下,rx_ready信号的值为1。

s_sample为数据采样状态,在此状态下,接收模块连续采样数据,并对每16个采样样值进行最大似然判决,判决得到相应的逻辑值,这一过程要重复8次,并依次完成串并转换,直到接收完8个数据比特后,直接进入s_stop状态。在这一状态下,rx_ready信号的值为0。

s_stop状态用于检测停止位,为了使得接收模块的使用范围更广,本程序在这一状态等待一定的时间后,直接跳转到s_idle状态,无论停止位是1、1.5还是2位,也不对其数值进行采样判断。这是因为没有添加校验位,根据串口的传输协议,8个有效数据后肯定是停止位,但停止位所占的时间却是要补偿的,对于不同位宽的停止位,需要修改计数器的模值。

代码语言:js
复制
module uart_rx(
bclk,reset,rxd,rx_ready,rx_dout
    );
 input bclk;
 input reset;
 input rxd;
 output rx_ready;
 output [7:0]rx_dout;
 parameter [3:0]Lframe=9;
 parameter [2:0]s_idle=3'b000;
 parameter [2:0]s_sample=3'b010;
 parameter [2:0]s_stop=3'b100;
 reg rx_ready;
 reg [7:0]rx_doutmp=0;
 reg [2:0]state=s_idle;
 reg [3:0]cnt=0;
 reg [3:0]dcnt=0;
 reg [3:0]num=0;
 assign rx_dout=rx_doutmp;
 always @(posedge bclk or posedge reset)
 begin
if(reset==1'b1)
begin
state<=s_idle;
cnt<=0;
dcnt<=0;
num<=0;
rx_doutmp<=0;
rx_ready<=0;
end
else
begin
case(state)
s_idle:
begin
rx_dout<=0;
rx_ready<=1;
dcnt<=0;
if(cnt==4'b1111)
begin
cnt<=0;
if(num>7)
begin
state<=s_sample;
num<=0;
end
else
begin
state<=s_idle;
num<=0;
end
end
else
begin
cnt<=cnt+1;
if(rxd==1'b0)
begin
num<=num+1;
end
else
begin
num<=num;
end
end
end
s_sample:
begin
rx_ready<=1'b0;
if(dcnt==Lframe)
begin
state<=s_stop;
end
else
begin
if(cnt==4'b1111)
begin
dcnt<=dcnt+1;
cnt<=0;
if(num>7)
begin
num<=0;
rx_doutmp[dcnt]<=1;
end
else
begin
num<=0;
rx_doutmp[dcnt]<=0;
end
end
else
begin
cnt<=cnt+1;
if(rxd==1'b1)
begin
num<=num+1;
end
else
begin
num<=num;
end
end
end
end
s_stop:
begin
rx_ready<=1'b1;
if(cnt==4'b1111)
begin
cnt<=0;
state<=s_idle;
end
else
begin
cnt<=cnt+1;
end
end
endcase
end
 end
endmodule
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2016-07-06,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 瓜大三哥 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档