当前位置: 首页 > news >正文

多字节串口收发IP设计(四)串口接收模块设计及联合仿真(含源码)

串口接收模块的设计比较简单,按照串口的接收时序按位将数据接收即可。

本模块比较特殊的是增加了奇偶校验的计算,并判断校验是否正确。

模块接口

信号名

位宽

说明

I_clk

1

模块时钟

I_rst

1

模块复位,高电平有效

I_uart_baud_cnt

16

波特率计数器,计数单bit时钟数

I_uart_check

2

校验位设置:0-无校验,1-奇校验,2-偶校验

O_user_rx_data

8

用户接收的数据

O_user_rx_valid

1

用户接收数据有效,高电平有效

O_user_rx_error

1

奇偶校验错误标志,高电平有效

I_uart_rx

1

串行数据接收

串口接收时序

源代码

`timescale 1ns / 1psmodule UART_rx#(parameter       C_DATA_WIDTH  =  8           , //数据位宽parameter       C_STOP_WIDTH  =  1             //停止位位宽  
)(input   wire                            i_clk               ,input   wire                            i_rst               ,input   wire                            i_uart_rx           ,input   wire    [15:0]                  i_uart_baud_cnt     ,input   wire    [ 1:0]                  i_uart_check        , //0-no,1-odd,2-evenoutput  reg     [C_DATA_WIDTH - 1 : 0]  o_user_rx_data      ,output  reg                             o_user_rx_valid     ,output  reg                             o_user_rx_error 
);
////////////////////////////////////////////////////////////////////
//parameter define 
localparam      C_DATA_LEN = 2 + C_DATA_WIDTH + C_STOP_WIDTH ; //start+data+check+stop//reg define
reg     [ 5:0]                  r_uart_rx                       ;               
reg     [15:0]                  r_cnt_baud                      ;
reg     [15:0]                  r_cnt_bit                       ;
reg                             r_rx_check                      ;
reg                             r_run                           ;//wire define
wire                            w_rx_en                         ;
wire                            w_bit_en                        ;
wire                            w_start_flag                    ;////////////////////////////////////////////////////////////////////assign w_rx_en = (r_cnt_baud == (i_uart_baud_cnt >> 1) - 1 );
assign w_bit_en = (r_cnt_baud == i_uart_baud_cnt - 1 );
assign w_start_flag = ~(r_uart_rx[4] | r_uart_rx[3] | r_uart_rx[2] | r_uart_rx[1] | r_uart_rx[0]) ;////////////////////////////////////////////////////////////////////
always @(posedge i_clk )beginif(i_rst)r_uart_rx <= 6'b111111;elser_uart_rx <= {r_uart_rx[4:0],i_uart_rx}; 
endalways @(posedge i_clk) beginif (i_rst)r_run <= 0 ;else if (o_user_rx_valid)r_run <= 0 ;else if (w_start_flag && !r_run)r_run <= 1 ;
end always @(posedge i_clk) beginif (i_rst)r_cnt_baud <= 0 ;else if (r_run && r_cnt_baud < i_uart_baud_cnt - 1)r_cnt_baud <= r_cnt_baud + 1 ;else r_cnt_baud <= 0 ;
endalways @(posedge i_clk )beginif(i_rst)r_cnt_bit <= 'd0;else if(r_run && r_cnt_bit == C_DATA_LEN - 3 && i_uart_check == 0 && w_bit_en)r_cnt_bit <= 'd0;else if(r_run && r_cnt_bit == C_DATA_LEN - 2 && i_uart_check > 0 && w_bit_en)r_cnt_bit <= 'd0;else if(r_run && w_bit_en)r_cnt_bit <= r_cnt_bit + 1;
endalways @(posedge i_clk )beginif(i_rst)o_user_rx_data <= 'd0;else if(r_run && r_cnt_bit >= 1 && r_cnt_bit <= C_DATA_WIDTH && w_rx_en)o_user_rx_data <= {r_uart_rx[5],o_user_rx_data[C_DATA_WIDTH-1:1]};//LSB first
endalways @(posedge i_clk )beginif(i_rst)o_user_rx_valid <= 'd0;else if(r_run && r_cnt_bit == C_DATA_WIDTH && i_uart_check == 0 && w_bit_en)o_user_rx_valid <= 1'd1;else if(r_run && r_cnt_bit == C_DATA_WIDTH + 1 && w_bit_en)o_user_rx_valid <= 1'd1; else if(r_run && r_cnt_bit == C_DATA_WIDTH + 1 && w_bit_en)o_user_rx_valid <= 1'd1;elseo_user_rx_valid <= 'd0;
endalways @(posedge i_clk )beginif(i_rst)o_user_rx_error <= 'd0;else if(r_run && r_cnt_bit == C_DATA_WIDTH && i_uart_check == 0 && w_bit_en)o_user_rx_error <= 1'd0;else if(r_run && r_cnt_bit == C_DATA_WIDTH + 1 && i_uart_check == 1 && r_uart_rx[5] == r_rx_check && w_bit_en)o_user_rx_error <= 1'd1; else if(r_run && r_cnt_bit == C_DATA_WIDTH + 1 && i_uart_check == 2 && r_uart_rx[5] == ~r_rx_check && w_bit_en)o_user_rx_error <= 1'd1;elseo_user_rx_error <= 'd0;
endalways @(posedge i_clk )beginif(i_rst)r_rx_check <= 'd0;else if(r_run && r_cnt_bit >= 1 && r_cnt_bit <= C_DATA_WIDTH && w_rx_en)r_rx_check <= r_rx_check ^ r_uart_rx[5];else if (!r_run)r_rx_check <= 'd0;
endendmodule

仿真代码

`timescale 1ns / 1psmodule tb_UART( );
reg                            i_clk               ;
reg                            i_rst               ;
reg    [31:0]                  i_uart_baud_cnt     ;
reg    [ 1:0]                  i_uart_check        ; //0-no,1-odd,2-even
reg    [ 7:0]                  i_user_tx_data      ;
reg                            i_user_tx_valid     ;
wire                           o_user_tx_ready     ;
wire                           o_uart_tx           ;
wire   [ 7:0]                  w_usr_rx_data       ;
wire                           w_usr_rx_valid      ;
wire                           o_user_rx_error     ;wire w_active = i_user_tx_valid & o_user_tx_ready ;initial begini_clk = 0 ;i_rst = 1 ;i_uart_check = 0 ;i_uart_baud_cnt = 8 ;#100;@(posedge i_clk) i_rst = 0 ;
endalways #5 i_clk = ~i_clk ;always @(posedge i_clk) beginif (i_rst)i_user_tx_data <= 8'h55 ;else if (w_active)i_user_tx_data <= i_user_tx_data + 1 ; 
endalways @(posedge i_clk) beginif (i_rst)i_user_tx_valid <= 0 ;else if (w_active)i_user_tx_valid <= 0 ; else if (o_user_tx_ready)i_user_tx_valid <= 1 ; 
endUART_tx u_UART_tx(.i_clk           (i_clk           ),.i_rst           (i_rst           ),.i_uart_baud_cnt (i_uart_baud_cnt ),.i_uart_check    (i_uart_check    ),.i_user_tx_data  (i_user_tx_data  ),.i_user_tx_valid (i_user_tx_valid ),.o_user_tx_ready (o_user_tx_ready ),.o_uart_tx       (o_uart_tx       )
);UART_rx#(.C_DATA_WIDTH  (8           ), //数据位宽.C_STOP_WIDTH  (1           ) //停止位位宽
)UART_rx_u
(.i_clk              (i_clk          ),.i_rst              (i_rst          ),.i_uart_rx          (o_uart_tx      ),.i_uart_baud_cnt    (i_uart_baud_cnt),.i_uart_check       (i_uart_check   ),.o_user_rx_data     (w_usr_rx_data  ),.o_user_rx_valid    (w_usr_rx_valid ),.o_user_rx_error    (o_user_rx_error));endmodule

与串口发送模块联合仿真结果

无校验

将i_uart_check信号赋值为0,表示无校验,则数据的长度为:起始位+数据位+停止位=10。

通过仿真结果可以看出,接收时序符合串口发送格式。

R_cnt_bit为0时对应起始位,为1~8时对应数据位。

数据接收完成后,输出接收到的数据和有效信号。

奇校验

将i_uart_check信号赋值为1,表示奇校验,则数据的长度为:起始位+数据位+校验位+停止位=11。

接收数据为8’h55时,其二进制为01010101,数据位有4个1,是偶数,则校验位就为1,r_cnt_bit为9时对应校验位,符合预期。

接收到的校验位与计算的校验位一致,无校验错误。

接收数据为8’h57时,其二进制为01010111,数据位有5个1,是奇数,则校验位就为0,r_cnt_bit为9时对应校验位,符合预期。

接收到的校验位与计算的校验位一致,无校验错误。

偶校验

将i_uart_check信号赋值为2,表示偶校验,则数据的长度为:起始位+数据位+校验位+停止位=11。

接收数据为8’h55时,其二进制为01010101,数据位有4个1,是偶数,则校验位就为0,r_cnt_bit为9时对应校验位,符合预期。

接收到的校验位与计算的校验位一致,无校验错误。

接收数据为8’h57时,其二进制为01010111,数据位有5个1,是奇数,则校验位就为1,r_cnt_bit为9时对应校验位,符合预期。

接收到的校验位与计算的校验位一致,无校验错误。

发送奇校验,接收偶校验

将串口发送模块设置为奇校验,串口接收模块设置为偶校验,验证奇偶校验判断的正确性。

通过仿真结果可以看出,校验全部错误,符合预期。

串口收发的基础模块已开发完成,并完成了仿真测试。

由于没有找到一个较好的可以进行奇偶校验位检验的上位机软件,所以暂时不对串口收发模块进行上板测试。

如果有小伙伴进行上板测试发现了问题,欢迎在此评论,大家一起进步。

http://www.dtcms.com/a/469829.html

相关文章:

  • 封装相关学习
  • 成都网站优化方案wordpress cms主题教程
  • 网络原理基础
  • aws s3设置跨域,s3配置预签名,aws 配置文件上传
  • 18芯城网站开发案例国内简约网站设计
  • 网站开发用什么字体一般域名的作用
  • 『 QT 』Hello World控件实现指南
  • 【CF】Day148——Codeforces Round 1057 (Div. 2) CD (非退化凸多边形的分类讨论 | 破环成链动态规划)
  • 网站建设教程金旭亮wordpress自动加p标签
  • 使用C#代码将ODT转换为PDF文件
  • 【网络编程】详解 IP 协议:报头字段、路由器功能、网段划分和分片传输
  • 大模型微调 SFTTrainer 数据处理与训练器配置解析(116)
  • gtest简单应用
  • 访答知识库,企业知识库,访答浏览器,Al编辑器,RAG,Pdf转word。个人知识库,访答RAG,云知识库,私有知识库……
  • 通过企业画册宣传_网络网站建设_新闻媒体合作等方式_企业营销网站制作
  • BERT相关知识自测
  • 【完整源码+数据集+部署教程】 真菌孢子图像分割系统源码&数据集分享 [yolov8-seg-convnextv2等50+全套改进创新点发刊_一键训练
  • 遵义市网站制作如何申请域名网站注册
  • GitHub 热榜项目 - 日榜(2025-10-11)
  • MySQL数据库之DBA命令
  • 4.打造个人Z-Library镜像
  • CoRL-2025 | 物体相对控制赋能具身导航!ObjectReact:学习用于视觉导航的物体相对控制
  • 长春seo网站优化做企业网站接单
  • word超链接网站怎么做网站建设网页设计网站模板
  • spring boot 整合 activiti 教程
  • 免费网站电视剧下载不支持下载的视频怎么保存下来
  • 接口自动化测试流程、工具与实践
  • 【C++继承】深入浅出C++继承机制
  • Mysql杂志(三十一)——Join连接算法与子查询、排序优化
  • HashMap - 底层原理