HDLC 发送的FPGA设计

摘要

关于HDLC 发送的设计思路和源码使用方法。

HDLC协议格式

帧头标志 地址 控制 信息 校验 帧尾标志
4个7E 自定义 自定义 自定义 16位CRC 4个7E

注意:HDLC 帧头和帧尾只规定至少1个7E,实际用几个属于内部协议。

模块架构

文件依赖

文件依赖结构图
注:(蓝字部分是需要使用的设计文件,黑字部分为xilinx ip,只需要指定参数并调用xilinx ip core)。

模块依赖

模块结构图

模块端口

hdlctra.v

端口类型 名称 描述 备注
输入 clk 数据时钟
rst_n 复位信号,低有效
trastart_flag 发送开始信号,持续一段时间
db 数据个数
ramd cpu并行数据
输出 datat 满足hdlc格式数据
inr 发送完成标志

insert0.v

端口类型 名称 描述 备注
输入 clk 数据时钟
rst_n 复位信号,低有效
trastart_flag 发送开始信号,持续一段时间
db 数据个数
ramd cpu并行数据
inr 发送完成标志
输出 ram_outd 当数据需要插零时,多保持1个时钟

flag_i0.v

端口类型 名称 描述 备注
输入 clk 数据时钟
rst_n 复位信号,低有效
insert0_flag 插零标记
insert0_flag_valid 插零标记是否有效
inr 发送完成标志
输出 insert0_flag_d5 插零后的数据

iverilog仿真结果

hdlctra.v
hdlctra iverilog仿真波形
这里发送了4个字节的数据,即16进制的FF、55、FF、AA。
datat数据为

  • 01111110(重复4次,即帧头4个7E)
  • 11111(0)111(0xFF,低位在前,且连续5个1插入1个0)
  • 10101010(0x55)
  • 111110111(0xFF)
  • 01010101(0xAA)
  • 1000,1000,0001,0000(16位CRC)
  • 01111110(重复4次,即帧尾4个7E)

insert0.v
insert0 iverilog仿真波形
insert0.v的设计目标是:如果数据需要插零,则多持续一个时钟周期。输出有14个时钟的延迟。
例如:0xFF对应的输入ramd持续8个时钟周期,对应的输出ram_outd持续9个时钟周期。

flag_i0.v
flag_i0 iverilog仿真波形
flag_i0.v的设计目标是:将insert0_flag进行插零延迟,有1处后面插零。输出有5个时钟的延迟。
例如:001000100
变成 001(0)0001(0)00

源码使用

所有的代码均共享在Github。verilog设计文件在zhangxin6/iverilog_testbench,xilinx ip core文件在zhangxin6/manage_ip
如果你会使用Github,推荐使用命令行中的Git下载

1
2
git clone git@github.com:zhangxin6/iverilog_testbench.git
git clone git@github.com:zhangxin6/manage_ip.git

反之,你可以通过上面的链接,通过Download ZIP下载。
insert0 iverilog仿真波形
这里提供hdlctra_testbench.v及iverilog仿真的hdlctra_testbench.bat供参考。双击hdlctra_testbench.bat即可实现仿真!

hdlctra_testbench.bat

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@echo off
set testbench=hdlctra_testbench

set iverilog_path=c:/iverilog/bin;
set gtkwave_path=c:/iverilog/gtkwave/bin;
set path=%iverilog_path%%gtkwave_path%%path%

set dir=..
set ip_dir=../../manage_ip
set batdir=.

set s1=%dir%/hdlctra_testbench.v
set s2=%dir%/hdlctra.v
set s3=%dir%/insert0.v
set s4=%dir%/flag_i0.v

set ip1="%ip_dir%/flag_insert0_ram/sim/flag_insert0_ram.v"
set ip2="%ip_dir%/flag_insert0_ram/simulation/blk_mem_gen_v8_4.v"
set ip3="%ip_dir%/insert0_ram/sim/insert0_ram.v"

set vivado_dir=C:/Xilinx/Vivado/2018.2/data/verilog/src
set vivado_lib="-y%vivado_dir%" "-y%vivado_dir%/retarget" "-y%vivado_dir%/unifast" "-y%vivado_dir%/unimacro" "-y%vivado_dir%/unisims" "-y%vivado_dir%/xeclib"

iverilog -g2012 -o "%batdir%/%testbench%.vvp" %vivado_lib% %s1% %s2% %s3% %s4% %ip1% %ip2% %ip3% %vivado_dir%/glbl.v

vvp "%batdir%/%testbench%.vvp"

set gtkw_file="%batdir%/%testbench%.gtkw"
if exist %gtkw_file% (gtkwave %gtkw_file%) else (gtkwave "%batdir%/%testbench%.vcd")

pause

里面绝对路径iverilog_path,gtkwave_path,vivado_dir需要根据软件实际安装位置进行调整。
各个文件的相对路径如有修改,则hdlctra_testbench.bat需要做相应修改。
zhang可以替换成不含中文的路径,其他建议按照下图处理。
文件路径

设计思路

hdlctra.v(顶层)

  • 调用insert0实现:需要插零时,数据多保持一个时钟
  • 用状态机实现,帧头、内容、CRC、帧尾的状态切换,及输出控制

HDLC发送状态机

insert0.v

  • 调用flag_i0实现需要插零时,读使能延迟一个时钟

  • 调用insert0_ram实现读写数据间的转换

flag_i0.v

这个模块是插零设计的关键。

  • 采用跳地址方式,配合RAM清零操作实现数据比原始多0
  • 考虑到来两帧通信数据间隔可能较短,而RAM清零需要时间,采用空间换时间方法,通过奇、偶两个RAM乒乓操作,实现时序合理布局。

值得注意的是,这里只提供精要的设计思路。如果需要了解更多细节,应该结合源码阅读并进行iverilog仿真。

设计思路不应该是代码含义复述(这违反了DRY原则),而是精粹的设计思路概述。

软件依赖

  • 仿真必需
  • 推荐
    • Notepad++(查看源码)或Sublime text
    • VHDL
      • 如果你更熟悉VHDL而不是Verilog,可以使用XHDL软件进行转换,你可以支持正版或淘宝购买
    • 操作系统
      • Windows 没有任何问题
      • 理论上Linux也是支持的,但iverlog的设置会有不同(参考iverilog官方文档),文件路径也和Windows不一样,需要探索

更多

  • HDLC接收的FPGA设计(coming soon…)
  • 远程FPGA及DSP HDLC硬件级实验服务(long after…)

最后

如果你有任何问题,有以下3种方式给我反馈:

  • 在下面评论
  • 去相应的github repo提issue
  • 发邮件给我,zhangxin_mail163@163.com

Just feel free to raise a question and have some fun with using this code 😄

Author: Zhang Xin
Link: https://zhangxin6.github.io/2019/01/11/hdlctra(HDLC发送)/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.