Menu Close

uart 通讯协议中增加checksum

在uart 通讯中,为保证长距离通讯的可靠性,会在数据包通讯协议中, 增加checksum。主要是用于在接收端增加检测。在uart通讯中,对于字节传输是否正确,通常使用奇偶校验来验证数据的正确性。 在通讯中,使用CRC 或者checksum 来保证数据包的完整性。 原因是数据正确,不等于数据包完整性。本文中使用checksum来保证数据包传输正确性。checksum校验方法简单,算法逻辑比较小,在很多协议中都有相关的应用。缺点是不能有效的判断包长的错误。举例: data0 + data1 + data2 + checksum  和 data0 + data1 + data2 + 0/8’hff + 0/8’hff  + checksum

 

1.  Uart中增加checksum

  1. 上一篇文章的基础上,数据包格式增加了8bit的checksum,checksum 作为工程的可选项(parameter)。整个工程代码中,只有rx_app 模块内部有变动,端口信号都未变化,其余模块与fifo的版本保持不变。
  2. 产品定义:length比实际发送数据字节数长的数据包,丢弃处理;length比实际发送数据字节数端的数据包,截取有效字节,当作正确包处理。当有校验和时包长length大于等于4可当作正确包接收。
  3. checksum 算法为:

sum[15:0] = length + pkg_type + pkg_dev + data0 + data1 + data2 + …. datan

while (sum[15:8]) sum = sum[7:0] + sum[15:8]

sum = ~sum;

%title插图%num

  • 组织架构设计

 

%title插图%num

  • 模块功能概述
    1. 其他模块与之前的项目相同
    2. rx_app

与之前的版本比较:rx_app 模块内部分为主从状态机,主状态机主要负责读fifo,从状态机主要负责对读出的数据进行解析和校验。使得整个模块设计层次更清晰,错误查找更容易。

主状态机流程图:

%title插图%num

从状态机流程图:

%title插图%num

 

        1. 代码详解

端口信号解释:

sys_clk:时钟域模块传递进来的系统复位信号

rx_pkg_plus:rx_fifo传递的单脉冲信号,表示rx_fifo已经写入一个完整数据包

rx_fifo_dout:从rx_fifo读出的数据

rx_fifo_rd :读rx_fifo 使能,当rx_fifo写入一个完整包开始读

pkg_type:从设备地址,表示计算机准备对那个设备进行操作

pkg_op:读/写 控制字

pkg_data:计算机写入到fpga的数据

pkg_valid:传递给应用层的数据和命令有效信号

rst:时钟域模块传递进来的系统复位信号

状态机详解:

主状态机:

  • 初始化:rst信号对状态机初始化
  • 状态0:如果rx_fifo中已经写入一个完整的数据包,给读使能,同时给从状态开始指示信号,跳转到状态1
  • 状态1:无操作,等待一个时钟周期
  • 状态2:判断读出数据最高,为低表示fifo读空,跳转到状态3
  • 状态3:给从状态机数据读完标志,等待从状态捕获到此标志后返回一个chk_end信号跳转到状态4
  • 状态4:给出一个读完一个数据包标志rx_pkg_minus,判断从状态机校验结果,有错则此包丢弃,无错则给出数据有效指示跳转到状态5(等一个时钟确保0状态准确拿到 packets_count 的值)
  • 状态5:变量清0,跳转到状态0

从状态机:(需要注意从状态机与主状态机的衔接,保证fifo读出的每一笔数据不丢失)

初始化:主状态机发送的!rx_start信号 作为状态复位信号

  • 状态0: 根据parameter参数值判断是否需要checksum,如果需要checksum则跳转到状态1,否则跳转到状态12

//=============================1-8 处理带checksum的数据

  • 状态1:判断读出的数据最高位是否为高,为高表示数据有效,为高且长度字节的数据大于等于4,表示数据包长度正常,接收低8bit,对读出的低8bit进行校验和计算,跳转到状态2;如果读出为高但低8bit数据的值小于3,表示数据包长度有问题,则跳转到状态14(数据包错误处理状态);如果最高位为低,表示读出数据无效,数据包或者写入有问题,跳转到状态14。
  • 状态2-状态4:判断读出数据最高位是否为高,为高表示数据有效,接收低8bit有效数据,并对读出数据进行校验和计算。最高位为低表示数据无效,跳转到状态14。
  • 状态5:判断读出最高位是否为高,为高表示数据有效,再判断包长与实际接收数据计数对比,如果包长等于实际接收数据,表示实际发送的数据比包长值长,截取前面有效字节,调整到状态8对fifo中剩余字节进行校验和。最高bit为高但是包长值大于实际接收计数,表示数据未接收完毕,继续停留再状态5接收数据并做校验和。由于最后一笔数据是校验和,所以不能直接放入pkg_data,需要临时变量接收;如果发现读出的最高bit为低,表示fifo读空,且包长与实际接收计数相等,表示数据包正确,跳转到状态6,如果为低但是包长值比实际接收的长,说明实际写入FIFO 数据比包长值短,当作错误包处理,调整到状态20。
  • 状态6:判断checksum高8bit是否为0,不为0 表示有进位位,需要继续计算,直到无进位位则将校验和取反跳转到状态7
  • 状态7:如果校验和结果为0,表示数据接收正确,调整到状态21,否则给出校验和错误指示,跳转到状态20。
  • 状态8:判断读出数据最高bit是否为低,为低表示数据读完,调整到状态6。否则继续停留在8状态,对读出的数据进行校验和。

//===========================12-15(处理不带checksum 的数据)

  • 状态12:状态1:判断读出的数据最高位是否为高,为高表示数据有效,为高且长度字节的数据大于等于3,表示数据包长度正常,接收低8bit。跳转到状态13;如果读出为高但低8bit数据的值小于3,表示数据包长度有问题,则跳转到状态20(数据包错误处理状态);如果最高位为低,表示读出数据无效,数据包或者写入有问题,跳转到状态20。
  • 状态13-状态14:判断读出数据最高位是否为高,为高表示数据有效,接收低8bit有效数据,调整到状态15。最高位为低表示数据无效,跳转到状态20。
  • 状态15:判断读出最高位是否为高,为高表示数据有效,再判断包长与实际接收数据计    数对比,如果包长等于实际接收数据,表示实际发送的数据比包长值长,截取前面有效字节,调整到状态21。最高bit为高但是包长值大于实际接收计数,表示数据未接收完毕,继续停留在状态15接收数据;如果发现读出的最高bit为低,表示fifo读空,且包长与实际接收数据计数相等,表示数据包正确,跳转到状态21,如果为低但是包长值比实际接收的长,说明实际写入FIFO 数据比包长值短,当作错误处理,此包丢弃,调整到状态20.
  • 状态20:无操作,作为一个错误指示状态,直接跳转到状态21。
  • 状态21:变量清0,如果接收到主状态机的数据读取完成信号,反馈一个chk_end。停留在状态21,等待下一次主状态机对从状态机复位。

仿真下板调试详情

length比实际发送数据字节数长的数据包,丢弃处理;length比实际发送数据字节数短的数据包,截取有效字节,当作正确包处理。当有校验和时包长length大于等于3可当作正确包接收,包长不包括最后的checksum。从仿真以及下板12种情况结果看,设计与调试结果一致。

仿真测试数据:

040102F8;060001aabb92;050001aabb93(包长未包含校验和字节)

 

%title插图%num

下板测试数据:

无校验和:

  • 030102 (正确包),040001aa (正确包), 050001aabb (正确包);
  • 03010200 (包长比实际字节短–截取),
  • 050001aa33cc (包长比实际字节短–截取);
  • 040102 (包长比实际字节长–错误包),
  • 040001 (包长比实际字节长–错误包),
  • 050001aa (包长比实际字节长–错误包);
  • 030102 (正确包), 060001aabbcc (正确包);060001345678 (正确包);

 

有校验和:

  • 030102F9(包长低于4–无效);
  • 040001aa50(截取);
  • 0400011234B4  (包长比实际字节短,校验和正确);
  • 040001123495 (包长比实际字节短,校验和错误–无效);
  • 06000112E6(包长比实际字节长–无效);
  • 040102F8 (正确包),050001aa4F (正确包), 060001aabb92 (正确包);
  • 04010200F8 (截取),0501021234b1 (截取),0600015678cc5d (截取);
  • 050102F7 (错误包)050001aa44 (校验和错误), 060001aabb93 (校验和错误);

调试分类:

%title插图%num

 

Quartus 工程:

 

Posted in FPGA, FPGA 教材教案, Verilog, 教材与教案, 文章

1 Comment

  1. 12班-孔晓瑞

    老师,请问:
    1. 判断有校验和的数据和无校验和的数据是否有效的包长一个是大于等于4,一个是大于等于3,是因为多了一个校验不一样的么?如果后面还有其它数据,比如加个停止位,有效包长是否还要加1?

    2. 从状态机的状态4主要作用是什么?

发表回复

相关链接