写这篇文章的时候一直在想哪些东西要讲哪些不要讲,怎么用一条线去把这些东西串起来。刚开始学的时候其实就是想修改这个程序,让它满足自己的需求。那就得知道这个程序的总体流程,哪个地方负责什么功能,具体是靠哪些信号线进行操作的,改了这部分会不会影响其他的部分等问题。
所以我写的时候也是按这个思路来写的,先介绍整个程序的结构,然后再把一些很可能要使用的信号重点讲一下。
程序讲解
配置好IP核以后(可以参考XILINX的IP核GTX的配置),打开例程
得到例程,包括仿真程序(若是直接在这个例程上修改IP核的配置,可能会导致错误,因为生成的例程会把之前IP没有配置的信号线隐藏)
下面我们来介绍一下这个例程
程序的总体框架如下:
XILINX已经为我们搭建好了一个完整测试系统,IP核的时钟,复位等,数据发送给IP核的并行口,串行口输出数据回到串行接收口,并行输出的数据以后和原始数据对比。
Support模块:
IP核是包含support里面的
GT核的时钟和复位都是比较复杂的,这几个程序正是帮我们解决这部分的问题,如果没有特殊的需求的话,建议不要对此进行改动。
support模块可以算是这个核的“最小工作系统”了。信号线是真的多,从77行到170都是信号线,一开始学的时候直接给吓到了。
但其实这里面的大部分线是用不到的,不去管它们也不会有什么影响。比如这里输出的gt0_rxcharisk_out的作用是告诉你接收到k码了,如果你不需要用它进一步开发的话不用管它就好了。正因为这个原因,所以外层的程序exdes很多信号线输出了。
frame_gen(信号发送模块)
先来看看它的端口:
module gtwizard_0_GT_FRAME_GEN #
(
// parameter to set the number of words in the BRAM
parameter WORDS_IN_BRAM = 512
)
(
// User Interface
output reg [79:0] TX_DATA_OUT,
output reg [7:0] TXCTRL_OUT,
// System Interface
input wire USER_CLK,
input wire SYSTEM_RESET
);
TX_DATA_OUT是发送给IP核数据,它有80位是为了考虑数据拓展的需求,我给IP核设置数据宽度为16位,实际上它也只把16位数据给了IP核,但IP核的数据宽度是可以设置更大的。
TXCTRL_OUT是控制符,表示现在输入的数据还是对齐码。
USER_CLK是IP核给到外部的时钟
可以看到用的是txusrclk2,也就是IP核希望我们以这个时钟的速率给IP核输入并行数据。
SYSTEM_RESET:也是IP核给的复位信号,这个信号一来就说明IP核的发送端已经准备好了,你快点把数据传过来吧。
可以看到它连接的是TX(发送端)的复位状态机输出 。
Check(数据检验模块)
这部分程序用来检查接收到的数据和刚开始发送的数据是不是一致的,发生不一致的时候ERROR_COUNT_OUT会+1。我没有检验接收数据的需求,所以这部分程序没有使用,也就不多讲了。不过看一下它的编程逻辑,代码还是很有帮助的。如果你需要对接收到的数据再进行下一步处理可以好好看看这部分的程序。
Exdes:
这是整个例程的顶层程序,它负责把support,gen,check等模块连接起来,然后把时钟信号引进来(复位是在support里面的reset做的),把差分输入输出端口引出去。如果你需要对IP核进行进一步的开发可以直接在这里编程,但现在它做的事情很少,所以给外部接口的信号线非常简单
module gtwizard_0_exdes #
(
parameter EXAMPLE_CONFIG_INDEPENDENT_LANES = 1,//configuration for frame gen and check
parameter EXAMPLE_LANE_WITH_START_CHAR = 0, // specifies lane with unique start frame char
parameter EXAMPLE_WORDS_IN_BRAM = 512, // specifies amount of data in BRAM
parameter EXAMPLE_SIM_GTRESET_SPEEDUP = "TRUE", // simulation setting for GT SecureIP model
parameter EXAMPLE_USE_CHIPSCOPE = 0, // Set to 1 to use Chipscope to drive resets
parameter STABLE_CLOCK_PERIOD = 10
)
(
input wire Q0_CLK1_GTREFCLK_PAD_N_IN,
input wire Q0_CLK1_GTREFCLK_PAD_P_IN,
input wire DRP_CLK_IN_P,
input wire DRP_CLK_IN_N,
output wire TRACK_DATA_OUT,
input wire RXN_IN,
input wire RXP_IN,
output wire TXN_OUT,
output wire TXP_OUT
);
差分时钟Q0_CLK1_GTREFCLK_PAD_N_IN和Q0_CLK1_GTREFCLK_PAD_P_IN它们的数值和IP核配置界面里面的参考时钟一致。
差分时钟DRP_CLK_IN_P和DRP_CLK_IN_N在第三页的配置中
使用差分时钟是因为它更稳定,它后面也是转换为了单端时钟输入给IP核了,如果你的时钟足够稳定,就不用进行这个操作了。
RXN_IN, RXP_IN, TXN_OUT, TXP_OUT分别是串行的差分输入和输出信号,后面的仿真模块中把它们直接连起来了。
TRACK_DATA_OUT是一个指示信号,拉高的时候证明当前接收信号有效。
最后再说说仿真模块,它其实就是给了exdes相应的时钟信号,然后把差分输入和输出端口连接起来了。
Run Simulation仿真
数据发送端:
在gt0_txresetdone_out拉高,也就是TX复位成功后,可以看到差分输出端口已经在发送数据了,此时发送的是0000对应的8B/10B编码。过了若干个周期后,发送程序的system_reset_r2拉低,开始改变传输数据。
数据接收端:
接收端也是在gt0_rxresetdone_out拉高之后开始正常识别数据,在识别到K码信号对齐,也就是rxbyteusaligned_out拉高后信号对齐了,可以看到gt0_rxdata_out上显示了02bc,bc就是我们设置的K码。
怎么改发送的数据内容
最简单的是打开数据来源的gt_rom_init_tx.dat文件,16进制的数据。
改速率的话可以调整frame_gen里的计数器。
或者你也可以直接重新写一个发送程序,使用和它一样的时钟和复位信号就是了。
写在最后
刚开始学这个IP核的时候,跟着手册看GT的内部结构,令人头大,后来如果只需要简单跑起来,了解配置的意义和会修改例程就行了,希望这篇文章对大家去修改使用例程有所帮助
大家有什么问题欢迎和我一起讨论~