期待大家的一键三连,爱你们!!!
总目录:总目录(经验分享)
献上链接:
【高速接口-RapidIO】2、RapidIO串行物理层的包与控制符号
【高速接口-RapidIO】3、RapidIO串行物理层的包传输过程
【高速接口-RapidIO】4、Xilinx RapidIO核详解
【高速接口-RapidIO】5、Xilinx RapidIO核例子工程源码分析
【高速接口-RapidIO】6、Xilinx RapidIO核仿真与包时序分析
*
软件平台:
操作系统:Windows 8.1 64-bit
开发套件:Vivado2015.4.2
硬件平台:
评估板:ZYNQ-7 ZC706 Evaluation Board
1、新建工程,并在IP Catalog中找到Serial RapidIO Gen2
2、双击Serial RapidIO Gen2进入核的配置界面,所用参数全部保持默认,然后直接点击OK
3、在弹出的的对话框中直接点击Generate
4、在弹出的对话框中点击OK
5、等待srio_gen2_0核综合完毕,可能会花几分钟的时间
6、IP核综合完毕以后,单击srio_gen2_0,并点击鼠标右键,在弹出的菜单栏中单击Open IP Example Design…
7、在弹出的的对话框中选择例子工程的存放目录(这个目录可任意选择),然后单击OK
8、等一段时间以后例子工程就会自动打开
RapidIO核的例子工程的仿真顶层代码里面例化了两个实体,一个叫做srio_example_top_primary,另外一个叫做srio_example_top_mirror,如下图所示
其中每个例化实体都能被配置为发送支持的包类型,检测接收包失配以及上报链路的仿真细节。下表列出了例子工程中各个主要模块的功能简介
文件名 |
功能 |
srio_example_top.v |
例子工程的顶层模块 |
srio_request_gen.v |
生成请求事务的模块 |
instruction_list.vh |
这是一个Verilog头文件,里面定义了120个事务,它被包含在srio_request_gen.v模块中,srio_request_gen.v模块会把里面的所有事务依次发出去 |
srio_response_gen.v |
这个模块用来产生有响应事务的响应包 |
srio_condensed_gen.v |
当IP核的端口配置为Condensed I/O模式时,这个文件才会出现在例子工程中。它用来产生Condensed I/O模式的请求事务。 |
srio_quick_start.v |
这个模块与IP核的维护端口相连,用来发起维护事务。 |
maintenance_list.vh |
这是一个Verilog头文件,里面定义了一些维护事务,它被包含在srio_quick_start.v模块中,srio_quick_start.v模块会把里面的所有维护事务依次发出去用来配置相关寄存器 |
srio_report.v |
在仿真时,这个模块用来产生包接收和发送的时间戳,在硬件上运行的时候这个模块可以删除 |
srio_statistics.v |
这个模块用来收集核的统计信息并通过寄存器接口提交一些信息,提交的信息可以通过Vivado的调试特征以及用户设计来访问 |
srio_sim.v |
srio_sim.v是仿真顶层文件,它例化了两个核,分别是primary和mirror,并把它们连接到一起用于仿真。它也包含了上报测试是否成功的机制与超时(timeout)功能。 |
例子工程的顶层模块例化了所有核的所有组件和在硬件上执行所需要的例子代码,整个工程的结构如下图所示。
整个结构包括时钟模块,复位模块,配置结构以及产生RapidIO事务的激励模块。
srio_quick_start模块在顶层srio_example_top.v中例化,它与IP核的维护端口相连用来产成维护事务,维护事务在maintenance_list.vh中进行定义,用户可以根据需要编辑maintenance_list.vh文件来添加,修改和移除维护事务。
srio_request_gen.v模块也在顶层srio_example_top.v中例化,它用来产生I/O事务与消息事务。这个模块也存储了期望的响应并把接收的响应与期望值进行比较。
srio_response_gen.v模块也在顶层srio_example_top.v中例化,它用来为接收到的请求事务生成对应的响应事务。
通过上图可以看出,产生I/O事务一共有两种方式:第一种是通过例子工程中自带的srio_request_gen.v产生I/O事务;第二种是通过顶层模块中Initiator和Target的resquest/response接口自己编写代码产生I/O事务。同理,产生维护事务也有两种方式:第一种是通过例子工程中自带的srio_quick_start.v模块产生维护事务;第二种是通过顶层模块中的维护接口自己编写代码产生维护事务。I/O事务的端口类型是AXI4-Stream类型,维护事务的端口类型是AXI4-Lite类型。
默认情况下,由于例子工程的顶层srio_example_top.v模块中,VALIDATION_FEATURES与QUICK_STARTUP两个参数均被设置为1,如下图所示
所以,例子工程是采用自带的srio_request_gen.v和srio_quick_start.v分别产生I/O事务与维护事务,另外,推荐注释掉外部接口以节省管脚和改善时序。
如果要使用外部接口产生I/O事务,那么需要设置参数VALIDATION_FEATURES=0,并且取消顶层模块srio_example_top.v中外部接口(axis_ireq_*,axis_tresp_*, axis_iresp_*, axis_treq_*, axis_iotx_*, axis_iorx_*)的注释。如果要使用外部接口产生维护事务,那些需要设置参数QUICK_STARTUP=0,并且取消顶层模块srio_example_top.v中外部接口(axis_maintr_*)的注释。使用外部接口的工程结构如下图所示
I/O事务与维护事务
默认情况下,例子工程会使用srio_request_gen.v模块和srio_quick_start.v模块来产生I/O事务与维护事务。其中instruction_list.vh头文件定义了待发送的I/O事务,maintenance_list.vh头文件定义了待发送的维护事务。
当核被复位以后,maintenance_list.vh中的维护事务可以对核进行配置,维护事务可以在maintenance_list.vh进行添加、修改或移除。当没有处理器时,srio_quick_start.v模块可以用来管理公共的维护事务。当核复位以后,这是一种比较好的配置核的方法。
srio_request_gen.v模块和srio_response_gen.v模块可以用来产生I/O事务,srio_request_gen.v模块可以用来产生定义在instruction_list.vh中的I/O请求事务。instruction_list.vh中的I/O事务可以被添加、修改或移除,I/O事务的顺序是随机的,但是每次重新仿真时都是按照相同的顺序产生的。而且,只有IP核端口支持的事务才能被产生。srio_request_gen.v模块还可以追踪期望的响应并且比较接收的响应与期望值,这在仿真的时候可以很方便的确定事务的收发情况。
srio_response_gen.v模块用来产生接收到的请求所对应的目标响应I/O事务。如果写事务目标地址的第23位到16位为8’h12(address[23:16]=8’h12),那么数据负载会被存储在本地存储器。不需要响应的写事务会被丢弃,并且srio_response_gen.v模块不会响应SWRITE事务。如果读事务目标地址的第23位到16位为8’h12(address[23:16]=8’h12),那么数据将会从实际地址读出。对于那些地址不满足第23位到16位为8’h12(address[23:16]=8’h12)的事务,srio_response_gen.v模块将以地址递增的方式写入I/O事务携带的数据。响应会根据接收到的请求的顺序依次产生,所以不会有无序的事务产生。在所有的情况中,响应事务的优先级等于请求事务的优先级加1。
注意:每个srio_request_gen.v模块会消耗一个块RAM(Block RAM),每个srio_response_gen.v模块会消耗两个块RAM(Block RAM)。
配置结构
配置空间分布在RapidIO核的所有块中,配置结构的参考设计在例子设计的cfg_fabric模块中,用来管理每个块配置空间的访问情况。块(Block)的配置模块在配置总线(AXI4-Lite)上是作为从机存在的,cfg_fabric模块是作为主机存在的。维护事务的读写操作是从本地或者远程被发起,它是通过逻辑层的配置主端口接入配置模块,配置模块会把读写事务送入对应的块中,但如果地址不在各自配置寄存器的有效范围内,配置模块不会移交任何读写事务。往非法的空间写事务会被丢弃,读非法的空间将返回0。
时钟模块
例子设计的时钟模块与IP核的时钟模块是相同的。srio_clk模块有1个MMCM_ADV,1个IBUFDS和3个或4个BUFGs组成,在2x或4x模式,其中一个BUFGs将被转化为BUFGMUX。srio_clk模块会根据配置的不同产生合适的参考频率与用户时钟。
复位模块
srio_rst模块会把每个时钟域里面的异步复位信号转化为一个脉冲扩展的同步复位信号。当被用户设计调用的时候,srio_rst模块会用一个状态机强制对核重新初始化。
顶层模块srio_example_top.v源码的端口定义如下
顶层模块包含5个参数:SIM_VERBOSE,VALIDATION_FEATURES,QUICK_STARTUP,STATISTICS_GATHERING和C_LINK_WIDTH。
SIM_VERBOSE设为1时,可以利用srio_report.v模块生成不可综合的报告。为0时,此功能被屏蔽。
VALIDATION_FEATURES设为1时,选择例子工程中的srio_request_gen.v和srio_response_gen.v产生相应的请求事务与响应事务对IP核的功能进行测试。为0时,选择外部的用户接口由用户自己编写请求事务与响应事务的代码对IP进行测试。
QUICK_STARTUP设为1时,选择例子工程中的srio_quick_start.v产生相应的维护事务对IP核的配置空间进行访问。为0时,选择外部的维护接口由用户自己编写维护事务的代码对IP核的配置空间进行访问。
STATISTICS_GATHERING设为1时,可以利用srio_statistics.v模块搜集IP的性能细节,这个模块是可综合的,可以通过Chipscope或ILA进行访问。为0时,此功能被屏蔽。
顶层模块的差分时钟sys_clkp和sys_clkn就是IP核配置界面第一页的参考时钟,由于例子工程中采用的全部是默认参数,所以这里这个时钟为125MHz,这个时钟可以由FPGA外部的有源晶振或锁相环芯片输出。
sys_rst为IP核的复位信号,高电平有效。
差分信号srio_rxn0和srio_rxp0为串行接收数据信号,srio_txn0和srio_txp0为串行发送数据信号。
sim_train_en信号是一个用来减少仿真时间的控制信号,仿真时把这个信号置1可以加快仿真速度,但是代码在硬件上运行时这个信号必须赋值为0。
led0是led指示信号,可以把port_initialized和link_initialized两个信号接到led0中,这样在硬件上执行时可以方便观察链路状态。
顶层模块srio_example_top.v中的第466行到第590行例化了RapidIO核,部分源码如下图所示
第612行到631行是例化了srio_report.v模块用来收集ireq接口的统计信息。除此以外,还例化了3个srio_report.v模块用来收集iresp,treq,tresp接口的统计信息。下图是收集ireq统计信息的源代码。源码如下图所示
第637行到684行srio_request_gen.v模块用来生成请求事务。这个模块有7个参数,分别为SEND_SWRITE,SEND_NWRITER,SEND_NWRITE,SEND_NREAD,SEND_FTYPE9,SEND_DB和SEND_MSG。当他们设置为1时,srio_request_gen.v模块将会把instruction_list.vh模块中对应的事务发送给SRIO IP核。部分源码如下图所示
第779行到804行例化了srio_response_gen.v模块,这个模块用来产生响应事务。部分源码如下图所示
第890行到937行例化了srio_quick_start.v模块,这个模块产生维护事务来访问配置空间。部分源码如下图所示
第944行到988行例化了srio_statistics.v模块,这个模块用来收集统计信息,它是一个可综合的模块。部分源码如下图所示
模块srio_request_gen.v的作用是产生RapidIO请求事务,上篇文章《Xilinx RapidIO核详解》(链接:https://www.cnblogs.com/liujinggang/p/10072115.html)已经提到过,RapidIO核为了简化包的构建过程,设计了一种精简的包格式——HELLO格式来完成包的构建,然后按照HELLO格式的时序把数据发送给RapidIO核,RapidIO核会把HELLO格式的包转化为标准的RapidIO串行物理层的包。这样,用户在设计请求事务的Verilog代码时只需要对HELLO格式的包与时序有所了解,而不需要过多的关注RapidIO的协议与RapidIO包格式。这里重新复习一下HELLO格式的包结构与HELLO格式的时序。
HELLO格式的包结构如下图所示:
HELLO格式的时序图如下图所示:
事实上,整个srio_request_gen.v源代码的核心就是先构建HELLO格式的包,然后把包头(Header)和数据按照HELLO格式的时序传给RapidIO核就可以了。下面详细分析一下。
分析instruction_list.vh头文件
在分析srio_request_gen.v源代码之前先来分析一下instruction_list.vh头文件。因为srio_request_gen.v文件中包含了instruction_list.vh头文件,instruction_list.vh头文件中定义了srio_request_gen.v将要发送的所有事务。
instruction_list.vh头文件的第1行到第9行定义了事务的个数以及所有事务的总个数,每种事务的个数由一个控制变量进行选择,源码如下:
第11行到50行是37个SWRITE事务(流写事务),其中第1列的12位数据是由8-bit的保留位(SWRITE事务没有srcTID字段),1-bit的保留位,2-bit的prio和1-bit的CRF组成,第2列是FTYPE字段,第3列是保留字段(SWRITE事务没有TTYPE字段),第4列的36-bit数据是由最高2-bit的保留位和34-bit的address字段组成,第5列是8-bit保留字段(SWRITE事务没有size字段),不管这个字段的值为多少,目标设备都会把这个值当做0来处理。源代码如下图所示
第52行到72行是19个NWRITE_R事务(带响应的写事务),其中第1列的12位数据是由8-bit的srcTID,1-bit的保留位,2-bit的prio和1-bit的CRF组成,第2列是FTYPE字段,第3列是TTYPE字段,第4列的36-bit数据是由最高2-bit的保留位和34-bit的address字段组成,第5列是size字段,这个字段的值为实际的数据量减1。比如size=0,表示实际传输的数据量为1。源代码如下图所示
第74行到94行是19个NWRITE事务(写事务),其中第1列的12位数据是由8-bit的srcTID,1-bit的保留位,2-bit的prio和1-bit的CRF组成,第2列是FTYPE字段,第3列是TTYPE字段,第4列的36-bit数据是由最高2-bit的保留位和34-bit的address字段组成,第5列是size字段,这个字段的值为实际的数据量减1。比如size=0,表示实际传输的数据量为1。源代码如下图所示
第96行到123行是26个NREAD事务(读事务),其中第1列的12位数据是由8-bit的srcTID,1-bit的保留位,2-bit的prio和1-bit的CRF组成,第2列是FTYPE字段,第3列是TTYPE字段,第4列的36-bit数据是由最高2-bit的保留位和34-bit的address字段组成,第5列是size字段,这个字段的值为实际的数据量减1。比如size=0,表示实际传输的数据量为1。源代码如下图所示
第125行到128行是两个DOORBELL事务(门铃事务),其中第1列的12位数据是由8-bit的srcTID,1-bit的保留位,2-bit的prio和1-bit的CRF组成,第2列是FTYPE字段,第3列是保留字段(DOORBELL事务没有TTYPE字段),第4列的36-bit数据是由最高4-bit的保留位,8-bit的信息高8位,8-bit的信息低8位以及最后的16-bit保留位组成。第5列是8-bit保留字段(DOORBELL事务没有size字段)。源代码如下图所示
第130行到148行是17个MESSAGE事务(消息事务),其中第1列的12位数据是由4-bit的msglen,4-bit的msgseg,1-bit的保留位,2-bit的prio和1-bit的CRF组成,第2列是FTYPE字段,第3列是保留字段(MESSAGE事务没有TTYPE字段),第4列的36-bit数据是由最高26-bit的保留位,6-bit的mailbox字段,2-bit的保留位以及2-bit的ltr组成。第5列是8-bit的size字段。源代码如下图所示
第150行到152行是1个Data Streaming事务,这是Xilinx定义的第9类事务,由于这种事务用的不多,我自己也不太了解,所以这里就不进行分析了。源代码如下图所示
分析srio_request_gen.v源码
在分析完毕instruction_list.vh头文件以后接下来开始着手分析srio_request_gen.v源码。分析过程中始终要记住的一点是:srio_request_gen.v的核心功能就是组装HELLO包头并把包头和数据按照HELLO格式的时序发送出去。
srio_request_gen.v源码的第50行到92行是参数与接口的定义。它包含7个参数,分别为SEND_SWRITE、SEND_NWRITER、SEND_NWRITE、SEND_NREAD、SEND_DB、SEND_FTYPE9和SEND_MSG,它们的默认值被设置为0,但是在顶层模块中例化的时候,它们的值分别被设置为1、1、1、1、0、1、1。如下图所示
根据上面分析instruction_list.vh头文件可知,如果上面的7个参数为1的话,各个事务的个数应该由instruction_list.vh头文件中NUM_SWRITES、NUM_NWRITERS、NUM_NWRITES、NUM_NREADS、NUM_DBS、NUM_MSGS和NUM_FTYPE9决定。
接下来就是端口的定义,其中log_clk与log_rst均由IP输出,log_clk的频率与链路线速率和链路宽度有关,具体的对应关系在上篇文章中能找到。接下来就是设备ID,目的ID以及源ID的定义。然后定义了ireq与iresp,它们都采用了AXI4-Stream协议。link_initialized信号由IP核输出,当它为高时表明链路成功初始化。以user_*开头的几个变量可以方便用户自定义HELLO格式包头中的各个字段。
第96到110行定义了HELLO格式包头中的FTYPE字段与TTYPE字段的值,这两个字段的值与事务的类型有关,源码如下图所示
第120行定义了一个memory类型变量,综合的时候ram的类型为分布式ram,121行导入了instruction_list.vh头文件,126行定义的变量可以看做AXI4-Stream总线上数据有效的标志位,当这个信号为高时,AXI4-Stream总线上tdata上的数据为有效数据。源代码如下图所示
第178行到205行用来初始化事务列表,instruction[ii]存放的是instruction_list.vh头文件中定义的各个事务的相关字段值,源代码如下图所示
第208到第219行是一些简单的赋值操作。其中第208行的val_ireq_tkeep和val_ireq_tuser是根据HELLO格式的时序要求赋值的,HELLO格式的时序要求tkeep为8’hFF,tuser在第一个有效的时钟(log_clk)周期内由src_id与dest_id拼接而成。第213行和第217行的go变量用来选择HELLO格式包头各个字段由用户定义还是由instruction_list.vh定义。第219行的header_beat变量就是HELLO格式的包头,在第一个有效时钟(log_clk)周期,tdata上的数据必须为header_beat。源代码如下图所示
第266行到288行主要用来产生有效时钟计数器current_beat_cnt与有效时钟计数总数number_of_data_beats。当AXI4_Stream总线的tvalid和tready信号同时为高时,时钟为有效时钟,current_beat_cnt加1,当检测到tlast信号为高时表明最后一个数据已发送完毕,所以把current_beat_cnt清0。由于tdata的宽度为64-bit,也就是8个字节,所以有效时钟计数总数number_of_data_beats为current_size右移3位。源代码如下图所示
第294行到306行用来产生AXI4_Stream总线中tlast信号,tlast为高时表明发送的是最后一个数据,所以tlast信号相当于一帧数据的边界。
第307行到328行用来产生AXI4_Stream总线中的tdata信号,当有效时钟计数器current_beat_cnt为0时,tdata为包头header_beat,包头header_beat后面是待发送的数据data_beat,例子工程为了简单起见,发送的数据是累加数,每个累加数为8-bit,然后把每个累加数拼接8次作为待发送的数据,也就是说,待发送的数据为64’h0000000000000000,64’h0101010101010101,64’h0202020202020202,……..,后面以此类推。
第330行到345行主要用来产生AXI4_Stream总线中的tvalid信号,同时也产生了一些其他的标志信号。至此,整个AXI4_Stream总线中的所有信号的逻辑都编写完毕,并且整个逻辑都是完全符合HELLO格式的时序。代码的核心部分全部分析完毕。
第351行到第371行与数据的存储相关。每当current_beat_cnt的值为0时,request_address变量加1, request_address也被赋给了tid,也就是说request_address也是事务ID值,同时request_address也是instruction的索引值。源代码如下图所示
第382行到第406行例化了一个RAMB36SDP原语,RAMB36SDP是一个大小为36Kb的简单双口Block RAM(SDP=Simple Dual Port)。它的作用是把请求事务的tid,current_ftype和current_size写入RAM中存起来,对于有响应的事务,RapidIO会收到一个响应事务,收到响应事务事务以后可以把存放在RAMB36SDP中的数据读出来与响应事务中对应的字段进行对比从而对整个事务的交互过程的正确性进行一个初步判断。关于RAMB36SDP原语的详细解释请阅读下一小节。源代码如下图所示
第458行到482行就是把存储在RAM中请求事务的tid,current_ftype和current_size与响应事务对应的字段进行对比,在仿真时给出对应的提示信息。
至此,整个产生请求事务的代码全部分析完毕,其他未分析到的代码大家自己尝试分析。
RAMB36SDP是一个大小为36Kb的简单双口Block RAM(SDP=Simple Dual-Port),它其实是Virtex-5系列FPGA的一个原语,Vivado里面并没有RAMB36SDP的语法模板,ISE中才有它的语法模板,如下图所示
RAMB36SDP原语的完整代码如下所示
// RAMB36SDP : In order to incorporate this function into the design, // Verilog : the forllowing instance declaration needs to be placed // instance : in the body of the design code. The instance name // declaration : (RAMB36SDP_inst) and/or the port declarations within the // code : parenthesis may be changed to properly reference and // : connect this function to the design. All inputs // : and outputs must be connected.
// <-----Cut code below this line---->
// RAMB36SDP: 72x512 Simple Dual-Port BlockRAM w/ ECC
// Virtex-5
// Xilinx HDL Language Template, version 14.7
RAMB36SDP #(
.SIM_MODE(“SAFE”), // Simulation: “SAFE” vs. “FAST”, see “Synthesis and Simulation Design Guide” for details
.DO_REG(0), // Optional output register (0 or 1)
.EN_ECC_READ(“FALSE”), // Enable ECC decoder, “TRUE” or “FALSE”
.EN_ECC_WRITE(“FALSE”), // Enable ECC encoder, “TRUE” or “FALSE”
.INIT(72’h000000000000000000), // Initial values on output port
.SIM_COLLISION_CHECK(“ALL”), // Collision check enable “ALL”, “WARNING_ONLY”,
// “GENERATE_X_ONLY” or “NONE”
.SRVAL(72’h000000000000000000), // Set/Reset value for port output
// The forllowing INIT_xx declarations specify the initial contents of the RAM
.INIT_00(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_01(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_02(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_03(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_04(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_05(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_06(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_07(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_08(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_09(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_0A(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_0B(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_0C(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_0D(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_0E(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_0F(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_10(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_11(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_12(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_13(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_14(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_15(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_16(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_17(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_18(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_19(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_1A(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_1B(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_1C(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_1D(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_1E(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_1F(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_20(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_21(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_22(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_23(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_24(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_25(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_26(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_27(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_28(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_29(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_2A(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_2B(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_2C(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_2D(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_2E(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_2F(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_30(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_31(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_32(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_33(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_34(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_35(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_36(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_37(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_38(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_39(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_3A(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_3B(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_3C(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_3D(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_3E(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_3F(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_40(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_41(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_42(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_43(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_44(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_45(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_46(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_47(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_48(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_49(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_4A(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_4B(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_4C(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_4D(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_4E(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_4F(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_50(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_51(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_52(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_53(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_54(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_55(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_56(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_57(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_58(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_59(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_5A(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_5B(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_5C(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_5D(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_5E(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_5F(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_60(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_61(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_62(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_63(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_64(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_65(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_66(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_67(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_68(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_69(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_6A(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_6B(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_6C(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_6D(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_6E(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_6F(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_70(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_71(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_72(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_73(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_74(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_75(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_76(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_77(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_78(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_79(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_7A(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_7B(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_7C(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_7D(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_7E(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
.INIT_7F(256'h0000000000000000_0000000000000000_0000000000000000_0000000000000000),
// The next set of INITP_xx are for the parity bits
.INITP_00(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
.INITP_01(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
.INITP_02(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
.INITP_03(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
.INITP_04(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
.INITP_05(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
.INITP_06(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
.INITP_07(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
.INITP_08(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
.INITP_09(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
.INITP_0A(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
.INITP_0B(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
.INITP_0C(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
.INITP_0D(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
.INITP_0E(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00),
.INITP_0F(256'h00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00_00)
) RAMB36SDP_inst (
.DBITERR(DBITERR), // 1-bit double bit error status output
.SBITERR(SBITERR), // 1-bit single bit error status output
.DO(DO), // 64-bit data output
.DOP(DOP), // 8-bit parity data output
.ECCPARITY(ECCPARITY), // 8-bit generated error correction parity
.RDCLK(RDCLK), // 1-bit read port clock
.RDEN(RDEN), // 1-bit read port enable
.REGCE(REGCE), // 1-bit register enable input
.SSR(SSR), // 1-bit synchronous output set/reset input
.WRCLK(WRCLK), // 1-bit write port clock
.WREN(WREN), // 1-bit write port enable
.WRADDR(WRADDR), // 9-bit write port address input
.RDADDR(RDADDR), // 9-bit read port address input
.DI(DI), // 64-bit data input
.DIP(DIP), // 8-bit parity data input
.WE(WE) // 8-bit write enable input
);
// End of RAMB36SDP_inst instantiation
每个36Kb简单双口块RAM(Simple dual-port block RAM)都能被配置为512x64(32Kb)大小的RAM和一个内置的汉明纠错编码(Hamming Error Correction)块,由于要用到汉明纠错编码,所以数据位宽需要多用到8-bit,这样数据位宽就被扩展到72-bit,当数据位宽为72-bit,深度为512时,RAM的大小刚好为36Kb(512 * 72 / 1024 = 36),其中汉明纠错编码操作对用户是不可见的。每次写操作都会产生8-bit的保护位(原语中的ECCPARITY信号),这个8-bit的保护位在每次读操作的过程中可以用来纠正任何单比特的错误,或者检测(但不能纠正)任何双比特的错误。ECCPARITY输出信号没有可选的输出寄存器。原语中两个状态输出信号(SBITERR和DBITERR)的组合指示了三种可能的读操作结果:无错误(No Error),纠正了单比特错误(Signal Error Corrected)和检测到了双比特错误(Double Error Detected)。在读写操作的ECC(Error Correcting Code)模式均开启时(EN_ECC_READ = TRUE 并且 EN_ECC_WRITE = TRUE,EN_ECC_READ和EN_ECC_WRITE为原语的两个参数),读操作不能再存储器阵列中直接纠正错误,而只能把已经纠正完毕的数据输出给原语中的DO信号。ECC配置选项只有RAMB36SDP原语或FIFO36原语才支持。(此部分内容参考ug190的107页到155页)
Block RAM的ECC(Error Correcting Code)结构如下图所示
RAMB36SDP各个端口的定义如下表所示
端口名 |
方向 |
信号描述 |
DI[63:0] |
Input |
数据输入总线 |
DIP[7:0] |
Input |
数据输入奇偶校验总线 |
WRADDR[8:0] |
Input |
写地址总线 |
RDADDR[8:0] |
Input |
读地址总线 |
WREN |
Input |
写使能。当WREN=1时,数据将被写入存储器,当WREN=0,写操作不使能。 |
RDEN |
Input |
读使能。当RDEN=1时,数据将被从存储器读出,当RDEN=0,读操作不使能。 |
SSR |
Input |
同步设置/复位(Synchronous Set/Reset),这个信号用来复位输出寄存器的值为SRVAL,SRVAL是RAMB36SDP原语的一个参数。这个信号不会影响存储器存储单元的内容。 |
REGCE |
Input |
寄存器使能(Register Enable),端口输出寄存器使能信号。 |
WE[7:0] |
Input |
8位的字节写使能输入,由于输出数据总线为64-bit,一共为8个字节,所以字节写使能输入为8位,详细解释见表后的内容。 |
WRCLK |
Input |
写操作的时钟 |
RDCLK |
Input |
读操作的时钟 |
DO[63:0] |
Output |
数据输出总线 |
DOP[7:0] |
Output |
数据输出奇偶校验总线 |
SBITERR |
Output |
单比特错误(Signal Bit Error)状态 |
DBITERR |
Output |
双比特错误(Double Bit Error)状态 |
ECCPARITY |
Output |
ECC编码器输出数据总线 |
字节写使能(Byte-Writes):(此部分内容参考pg058的第50页到51页)
当字节写使能功能打开时,WE总线的宽度为输入数据总线DI中包含的字节个数。例如,输入数据总线DI为64位,包含8个字节,所以WE总线的宽度为8。其中WE总线的最高位对于输入数据总线DI的最高位的字节,WE总线的最低位对于输入数据总线DI的最低位的字节,在写操作过程中,只有WE总线中为1的位对应的字节才能被写入存储器中,为0的位保持原来的值不变。
假设输入数据总线的宽度为24位,它包含3个字节,所以WE的宽度为3,下图是一个字节写使能开启时往RAM的0地址写入数据的时序图(假设RAM的初始值全部为0)
由上图可知,当WEA(也就是上文的WE)为3’b011时,DINA数据24’hFF EE DD的后两个字节会写入存储器的0地址,而存储器0地址的最高字节保持00不变,所以第一次写操作完毕以后存储器0地址的数据为24’h00 EE DD;当WEA(也就是上文的WE)为3’b010时,DINA数据24’hCC BB AA的中间那个字节BB会写入存储器的0地址,而存储器0地址的最高字节和最低字节则保持前一次的00和DD值不变,所以第二次写操作完毕以后存储器0地址的数据为24’h00 BB DD。后面几次操作依次类推即可。
模块srio_response_gen.v的作用是产生RapidIO响应事务。RapidIO协议中只有NREAD、DOORBELL、MESSAGE以及NWRITE_R这几种事务有响应事务。
srio_response_gen.v源码的第51行到72行定义了模块的端口。log_clk和log_rst分别为逻辑层时钟与复位,tresp和treq为两个AXI4-Stream通道,tresp是响应事务传输通道,treq是请求事务传输通道。源码如下图所示
第77行到90行定义了HELLO格式包头中的FTYPE字段与TTYPE字段的值,这两个字段的值与事务的类型有关,源码如下图所示
第99行到100行定义了AXI4-Stream总线上有效数据的标志,当tvalid和tready同时为高时,tdata上的数据为有效数据。源代码如下图所示
第161行到163行按照HELLO格式的时序要求,把tkeep信号赋值为8’hFF,把tuser信号由src_id和dest_id拼接而成,并在第一个有效时钟发出去。源代码如下图所示
第193行到203行用来产生HELLO时序中的tready。源代码如下图所示
第205行到220行用来产生treq通道第一拍的标志信号,并把tdata中的数据按照HELLO格式的定义把对应的关键字段剥离出来,值得注意的是第218行优先级字段prio为tdata重对应的字段加1,原因是响应事务的优先级为请求事务的优先级加1,上篇博客也提到过这一点。这部分源代码如下图所示
第224行到第235行用来生成有响应事务的标志,其中RapidiO协议中只有NREAD、DOORBELL、MESSAGE和NWRITE_R这几种事务有对应的响应事务。这部分源代码如下图所示
第240行到274行与本地数据的存储有关。其中第240行到250行的逻辑用来产生数据存取使能位data_store_wen,本文第3.3节提到过,只有地址字段的第23位到第16位为8’h12时,写事务的数据才能被存放到本地存储器,原因就是第243行的判断语句加上了这个判断。第252行到260行的逻辑用来产生数据存储的写地址信号data_store_waddr。第262行到274行的逻辑用来产生数据存储的读地址信号data_store_raddr。源代码如下图所示
第276行到302行主要例化了一个RAMB36SDP用来存储写事务发送过来的数据。其中第276行用来产生数据存储的读使能标志。源代码如下图所示
第307行到第335行是把请求事务的包头(Header)信息存储在RAM中。其中第307行到308行把请求事务中HELLO格式定义的各个字段进行拼接作为RAM的输入,第325行到第335行用来产生RAM的读地址与写地址。
第337行例化了第二个Block RAM,它用来存储请求事务的HELLO格式信息。
第363行到第372行把从RAM中读出来的数据对应的字段剥离出来从而得到响应事务HELLO格式对应的字段。
第378行到第388行用来产生有效时钟的总数number_of_data_beats以及有效时钟计数器current_beat_cnt。这段逻辑与srio_request_gen.v中对应的逻辑完全一致。源代码如下图所示
第390行到400行用来产生tlast信号,发送最后一个数据时,tlast信号拉高。
第402行和第403行用来产生响应事务的包头(Header),第404行到414行用来产生响应事务的数据,其中响应事务的第一个有效时钟用来发送包头(Header),后面的有效时钟用来发送数据,这段逻辑也与srio_request_gen.v中对应的逻辑类似。源代码如下图所示
第459行到第469行用来产生AXI4-Stream中的tvalid信号,源代码如下
至此,整个响应事务的源代码分析完毕,其余未分析到的代码请自行分析。
模块srio_quick_start.v的作用是产生维护事务(Maintenance Transaction)访问本地设备和远程设备的配置空间。维护事务采用的接口协议为AXI4-Lite,它是一种轻量级的AXI4协议,有地址总线与数据总线,常用来实现单个寄存器的读写。在分析srio_quick_start.v源码之前首先分析一下maintenance_list.vh头文件。
分析maintenance_list.vh头文件
maintenance_list.vh头文件主要定义了维护事务相关的字段,其中第1列为2-bit的保留位,第2列为1-bit的远程/本地控制位,第3列为24-bit的地址,第4列为读/写控制位,第5列为32-bit的数据,第6列为4-bit的数据掩码(DATA MASK),部分源代码如下图所示
分析srio_quick_start.v源文件
srio_quick_start.v源文件的第68行到第101行是接口定义。log_clk和log_rst分别为逻辑层的时钟和复位。以maintr_*开头的信号为AXI4-Lite通道的信号,以user_*开头的信号是用户自定义的维护事务的相关字段,go变量用来在用户定义和maintenance_list.vh头文件定义的字段中进行选择
第105行到122行对maintenance_list.vh头文件中的参数进行了赋值,并引入了头文件,源代码如下图所示。
第192行到229行主要用来构建请求包,其本质就是产生AXI4-Lite的协议把数据发出去。部分源代码如下图所示
第233行到386行例化了一个RAMB36SDP原语,并用maintenance_list.vh头文件中定义的数据进行初始化。部分源代码如下图所示
第397行到416行主要负责响应侧的检测,通过maint_autocheck_error和maint_done指示检测状态。源代码如下图所示
至此,维护事务的代码分析完毕,它的代码逻辑相对来说比较简单。
另外,例子工程中还有两个模块srio_report.v和srio_statistics.v,它们只在仿真有用,在硬件上实现时最好删掉。这里不再作过多分析。只要理解了srio_request_gen.v与srio_response_gen.v,用RapidIO完成相关应用就足够了。
工程源码分析完毕以后,接下来就可以开始仿真了。例子工程中的代码一行都不要改,直接左键单击Run Simulation,在弹出的菜单中点击Run Behavioral Simulation,如下图所示
接着会出现下面的滚动框,在这个界面需要等待一会,如下图所示
上面的滚动框运行完毕以后就出现了波形界面,如下图所示
然后再点击下图中圈出的小图标把波形复位一下,如下图所示
复位波形以后在Tcl Console中输入指令:log_wave –r /* 。输入完毕以后按回车。这条指令的作用是记录所有中间变量的波形,这样后面要观察任何变量的波形只需要把它拖到波形界面中它的波形就会自动显示出来而不需要重新仿真,大大节约了时间。如下图所示
最后设置一个比较大的时间,我设置为10ms,然后点击它左边的按钮开始仿真,大约20分钟以后仿真会自动结束,如下图所示
仿真的过程中,在相应的时间点上,Tcl Console中会打印出包的收发情况
最后仿真结束以后,重新回到波形界面可以看到波形都正常产生了。这里最重要的两个信号就是link_initialized与port_initialized,当他们为高表示整个链路初始化完毕。至此,整个仿真过程全部结束,下篇文章会详细介绍每种事务的时序图以及需要注意的一些细节。
本节主要分析了一下请求事务与响应事务的Verilog源码,事实上,它们的源码就是按照pg007_srio_gen2.pdf把HELLO格式与HELLO时序描述出来而已。当然官方的这套源码为了尽可能保证测试到核的所有功能,写的比较混乱,但在实际项目中可以充分借鉴它的设计思想,然后根据你自己的需求对不需要的地方进行修改来达到你的目标。除此以外,HELLO格式的时序其通过一个状态机来实现可能更加简洁易懂。总而言之,这套代码具有很大的参考价值,但是要想把这个核玩透还是得自己多在项目中理解。
下篇文章将会教大家如何在Vivado抓出每种事务的时序来对各种RapidIO的交互过程有一个更加清晰的理解。
顶层模块srio_example_top_srio_gen2_0.v源码
1 // 2 // (c) Copyright 2010 - 2014 Xilinx, Inc. All rights reserved. 3 // 4 // 5 // This file contains confidential and proprietary information 6 // of Xilinx, Inc. and is protected under U.S. and 7 // international copyright and other intellectual property 8 // laws. 9 // 10 // DISCLAIMER 11 // This disclaimer is not a license and does not grant any 12 // rights to the materials distributed herewith. Except as 13 // otherwise provided in a valid license issued to you by 14 // Xilinx, and to the maximum extent permitted by applicable 15 // law: (1) THESE MATERIALS ARE MADE AVAILABLE "AS IS" AND 16 // WITH ALL FAULTS, AND XILINX HEREBY DISCLAIMS ALL WARRANTIES 17 // AND CONDITIONS, EXPRESS, IMPLIED, OR STATUTORY, INCLUDING 18 // BUT NOT LIMITED TO WARRANTIES OF MERCHANTABILITY, NON- 19 // INFRINGEMENT, OR FITNESS FOR ANY PARTICULAR PURPOSE; and 20 // (2) Xilinx shall not be liable (whether in contract or tort, 21 // including negligence, or under any other theory of 22 // liability) for any loss or damage of any kind or nature 23 // related to, arising under or in connection with these 24 // materials, including for any direct, or any indirect, 25 // special, incidental, or consequential loss or damage 26 // (including loss of data, profits, goodwill, or any type of 27 // loss or damage suffered as a result of any action brought 28 // by a third party) even if such damage or loss was 29 // reasonably foreseeable or Xilinx had been advised of the 30 // possibility of the same. 31 // 32 // CRITICAL APPLICATIONS 33 // Xilinx products are not designed or intended to be fail- 34 // safe, or for use in any application requiring fail-safe 35 // performance, such as life-support or safety devices or 36 // systems, Class III medical devices, nuclear facilities, 37 // applications related to the deployment of airbags, or any 38 // other applications that could lead to death, personal 39 // injury, or severe property or environmental damage 40 // (individually and collectively, "Critical 41 // Applications"). Customer assumes the sole risk and 42 // liability of any use of Xilinx products in Critical 43 // Applications, subject only to applicable laws and 44 // regulations governing limitations on product liability. 45 // 46 // THIS COPYRIGHT NOTICE AND DISCLAIMER MUST BE RETAINED AS 47 // PART OF THIS FILE AT ALL TIMES. 48 `timescale 1ps/1ps 49 (* DowngradeIPIdentifiedWarnings = "yes" *) 50 51 52 module srio_example_top_srio_gen2_0 #( 53 parameter SIM_VERBOSE = 1, // If set, generates unsynthesizable reporting 54 parameter VALIDATION_FEATURES = 1, // If set, uses internal instruction sequences for hw and sim test 55 parameter QUICK_STARTUP = 1, // If set, quick-launch configuration access is contained here 56 parameter STATISTICS_GATHERING = 1, // If set, I/O can be rerouted to the maint port [0,1] 57 parameter C_LINK_WIDTH = 1 58 ) 59 // port declarations ---------------- 60 ( 61 // Clocks and Resets 62 input sys_clkp, // MMCM reference clock 63 input sys_clkn, // MMCM reference clock 64 65 input sys_rst, // Global reset signal 66 67 // high-speed IO 68 input srio_rxn0, // Serial Receive Data 69 input srio_rxp0, // Serial Receive Data 70 71 72 73 output srio_txn0, // Serial Transmit Data 74 output srio_txp0, // Serial Transmit Data 75 76 77 78 input sim_train_en, // Set this only when simulating to reduce the size of counters 79 output [7:0] led0 80 81 ); 82 // ---------------------------------- 83 84 85 // wire declarations ---------------- 86 // 87 // ----------------------------------------------------------------------------- 88 // Note : Below portion of the wire declaration should be commented when 89 // used in non-shared mode AND the SRIO core 2nd instance is used to share 90 // common logic like clk, rst and GT Common with another instance of SRIO 91 // with Shared Logic (in DUT) option if the simulator throws errors. 92 // ----------------------------------------------------------------------------- 93 wire log_clk; 94 wire phy_clk; 95 wire gt_pcs_clk; 96 wire log_rst; 97 wire phy_rst; 98 wire clk_lock; // asserts from the MMCM 99 // 100 101 // signals into the DUT 102 103 104 wire ireq_tvalid; 105 wire ireq_tready; 106 wire ireq_tlast; 107 wire [63:0] ireq_tdata; 108 wire [7:0] ireq_tkeep; 109 wire [31:0] ireq_tuser; 110 111 wire iresp_tvalid; 112 wire iresp_tready; 113 wire iresp_tlast; 114 wire [63:0] iresp_tdata; 115 wire [7:0] iresp_tkeep; 116 wire [31:0] iresp_tuser; 117 118 wire treq_tvalid; 119 wire treq_tready; 120 wire treq_tlast; 121 wire [63:0] treq_tdata; 122 wire [7:0] treq_tkeep; 123 wire [31:0] treq_tuser; 124 125 wire tresp_tvalid; 126 wire tresp_tready; 127 wire tresp_tlast; 128 wire [63:0] tresp_tdata; 129 wire [7:0] tresp_tkeep; 130 wire [31:0] tresp_tuser; 131 132 wire maintr_rst = 1'b0; 133 134 wire maintr_awvalid; 135 wire maintr_awready; 136 wire [31:0] maintr_awaddr; 137 wire maintr_wvalid; 138 wire maintr_wready; 139 wire [31:0] maintr_wdata; 140 wire maintr_bvalid; 141 wire maintr_bready; 142 wire [1:0] maintr_bresp; 143 144 wire maintr_arvalid; 145 wire maintr_arready; 146 wire [31:0] maintr_araddr; 147 wire maintr_rvalid; 148 wire maintr_rready; 149 wire [31:0] maintr_rdata; 150 wire [1:0] maintr_rresp; 151 152 // signals from Validation modules 153 wire val_ireq_tvalid; 154 wire val_ireq_tready; 155 wire val_ireq_tlast; 156 wire [63:0] val_ireq_tdata; 157 wire [7:0] val_ireq_tkeep; 158 wire [31:0] val_ireq_tuser; 159 160 wire val_iresp_tvalid; 161 wire val_iresp_tready; 162 wire val_iresp_tlast; 163 wire [63:0] val_iresp_tdata; 164 wire [7:0] val_iresp_tkeep; 165 wire [31:0] val_iresp_tuser; 166 167 wire val_treq_tvalid; 168 wire val_treq_tready; 169 wire val_treq_tlast; 170 wire [63:0] val_treq_tdata; 171 wire [7:0] val_treq_tkeep; 172 wire [31:0] val_treq_tuser; 173 174 wire val_tresp_tvalid; 175 wire val_tresp_tready; 176 wire val_tresp_tlast; 177 wire [63:0] val_tresp_tdata; 178 wire [7:0] val_tresp_tkeep; 179 wire [31:0] val_tresp_tuser; 180 181 wire val_maintr_awvalid; 182 wire val_maintr_awready; 183 wire [31:0] val_maintr_awaddr; 184 wire val_maintr_wvalid; 185 wire val_maintr_wready; 186 wire [31:0] val_maintr_wdata; 187 wire val_maintr_bvalid; 188 wire val_maintr_bready; 189 wire [1:0] val_maintr_bresp; 190 191 wire val_maintr_arvalid; 192 wire val_maintr_arready; 193 wire [31:0] val_maintr_araddr; 194 wire val_maintr_rvalid; 195 wire val_maintr_rready; 196 wire [31:0] val_maintr_rdata; 197 wire [1:0] val_maintr_rresp; 198 199 200 //-- 201 //----------------------------------------------------------------------------// 202 203 204 //-- 205 206 // other core output signals that may be used by the user 207 wire [23:0] port_timeout; // Timeout value user can use to detect a lost packet 208 wire phy_rcvd_mce; // MCE control symbol received 209 (* mark_debug = "true" *) 210 wire phy_rcvd_link_reset; // Received 4 consecutive reset symbols 211 wire port_error; // In Port Error State 212 //(* mark_debug = "true" *)// this constraint is commented as it is failing due to new MLO flow 213 wire mode_1x; // Link is trained down to 1x mode 214 wire srio_host; // Endpoint is the system host 215 wire [223:0] phy_debug; // Useful debug signals 216 217 wire gtrx_disperr_or; // GT disparity error (reduce ORed) 218 219 wire gtrx_notintable_or; // GT not in table error (reduce ORed) 220 wire [15:0] deviceid; // Device ID 221 wire port_decode_error; // No valid output port for the RX transaction 222 (* mark_debug = "true" *) 223 wire idle_selected; // The IDLE sequence has been selected 224 (* mark_debug = "true" *) 225 wire idle2_selected; // The PHY is operating in IDLE2 mode 226 wire autocheck_error; // when set, packet didn't match expected 227 (* mark_debug = "true" *) 228 wire port_initialized; // Port is Initialized 229 (* mark_debug = "true" *) 230 wire link_initialized; // Link is Initialized 231 wire exercise_done; // sets when the generator(s) has completed 232 233 // other core output signals that may be used by the user 234 wire phy_mce = 1'b0; // Send MCE control symbol 235 wire phy_link_reset = 1'b0; // Send link reset control symbols 236 wire force_reinit = 1'b0; // Force reinitialization 237 238 239 // convert to ports when not using the pattern generator 240 241 242 wire axis_ireq_tvalid; 243 wire axis_ireq_tready; 244 wire axis_ireq_tlast; 245 wire [63:0] axis_ireq_tdata; 246 wire [7:0] axis_ireq_tkeep; 247 wire [31:0] axis_ireq_tuser; 248 249 wire axis_iresp_tvalid; 250 wire axis_iresp_tready; 251 wire axis_iresp_tlast; 252 wire [63:0] axis_iresp_tdata; 253 wire [7:0] axis_iresp_tkeep; 254 wire [31:0] axis_iresp_tuser; 255 256 wire axis_treq_tvalid; 257 wire axis_treq_tready; 258 wire axis_treq_tlast; 259 wire [63:0] axis_treq_tdata; 260 wire [7:0] axis_treq_tkeep; 261 wire [31:0] axis_treq_tuser; 262 263 wire axis_tresp_tvalid; 264 wire axis_tresp_tready; 265 wire axis_tresp_tlast; 266 wire [63:0] axis_tresp_tdata; 267 wire [7:0] axis_tresp_tkeep; 268 wire [31:0] axis_tresp_tuser; 269 270 wire axis_maintr_rst = 1'b0; 271 wire axis_maintr_awvalid = 1'b0; 272 wire axis_maintr_awready; 273 wire [31:0] axis_maintr_awaddr = 1'b0; 274 wire axis_maintr_wvalid = 1'b0; 275 wire axis_maintr_wready; 276 wire [31:0] axis_maintr_wdata = 1'b0; 277 wire [3:0] axis_maintr_wstrb = 1'b0; 278 wire axis_maintr_bvalid; 279 wire axis_maintr_bready = 1'b0; 280 wire [1:0] axis_maintr_bresp; 281 282 wire axis_maintr_arvalid = 1'b0; 283 wire axis_maintr_arready; 284 wire [31:0] axis_maintr_araddr = 1'b0; 285 wire axis_maintr_rvalid; 286 wire axis_maintr_rready = 1'b0; 287 wire [31:0] axis_maintr_rdata; 288 wire [1:0] axis_maintr_rresp; 289 290 wire ireq_autocheck_error; 291 wire ireq_request_done; 292 wire maint_autocheck_error; 293 wire maint_done; 294 295 // Vivado debug outputs for control of 296 (* mark_debug = "true" *) 297 wire peek_poke_go; 298 (* mark_debug = "true" *) 299 wire [23:0] user_addr; 300 (* mark_debug = "true" *) 301 wire [3:0] user_ftype; 302 (* mark_debug = "true" *) 303 wire [3:0] user_ttype; 304 (* mark_debug = "true" *) 305 wire [7:0] user_size; 306 (* mark_debug = "true" *) 307 wire [63:0] user_data; 308 (* mark_debug = "true" *) 309 wire [3:0] user_hop; 310 (* mark_debug = "true" *) 311 wire [15:0] dest_id; 312 (* mark_debug = "true" *) 313 wire [15:0] source_id; 314 (* mark_debug = "true" *) 315 wire id_override; 316 (* mark_debug = "true" *) 317 wire register_reset; 318 (* mark_debug = "true" *) 319 wire reset_all_registers; 320 (* mark_debug = "true" *) 321 wire [3:0] stats_address; 322 //(* mark_debug = "true" *) 323 // wire send_pna; 324 // (* mark_debug = "true" *) 325 // wire [2:0] sent_pna_cause_lsb; 326 // (* mark_debug = "true" *) 327 // wire in_recoverable_detect; 328 // (* mark_debug = "true" *) 329 // wire in_retry_detect; 330 // (* mark_debug = "true" *) 331 // wire out_recoverable_detect; 332 // (* mark_debug = "true" *) 333 // wire out_fatal_detect; 334 335 wire core_sent_pna; 336 337 wire core_received_pna; 338 339 wire core_sent_pr; 340 341 wire core_received_pr; 342 343 // Debug signals 344 wire go_req = peek_poke_go && user_ftype != 4'h8; 345 wire go_maint = peek_poke_go && user_ftype == 4'h8; 346 wire maint_inst = user_ttype == 4'h0; 347 reg [63:0] captured_data; 348 (* mark_debug = "true" *) 349 wire continuous_go; 350 reg continuous_go_q; 351 reg ireq_autocheck_error_q; 352 reg ireq_request_done_q; 353 reg reset_request_gen; 354 (* mark_debug = "true" *) 355 reg continuous_in_process; 356 reg reset_continuous_set; 357 (* mark_debug = "true" *) 358 reg stop_continuous_test; 359 reg [15:0] reset_continuous_srl; 360 wire [31:0] stats_data; 361 // }}} End wire declarations ------------ 362 363 364 // {{{ Drive LEDs to Development Board ------- 365 assign led0[0] = 1'b1; 366 assign led0[1] = 1'b1; 367 assign led0[2] = !mode_1x; 368 assign led0[3] = port_initialized; 369 assign led0[4] = link_initialized; 370 assign led0[5] = clk_lock; 371 assign led0[6] = sim_train_en ? autocheck_error : 1'b0; 372 assign led0[7] = sim_train_en ? exercise_done : 1'b0; 373 // }}} End LEDs to Development Board --------- 374 375 // assign send_pna = phy_debug[0]; 376 // assign sent_pna_cause_lsb = phy_debug[34:32]; 377 // assign in_recoverable_detect = phy_debug[40]; 378 // assign in_retry_detect = phy_debug[39]; 379 // assign out_recoverable_detect = phy_debug[38]; 380 // assign out_fatal_detect = phy_debug[37]; 381 // assign send_pna = phy_debug[0]; 382 assign core_sent_pna = phy_debug[160]; 383 assign core_received_pna = phy_debug[161]; 384 assign core_sent_pr = phy_debug[162]; 385 assign core_received_pr = phy_debug[163]; 386 387 388 389 390 assign continuous_go = 1'b0; 391 assign peek_poke_go = 1'b0; 392 assign user_addr = 24'b0; 393 assign user_ftype = 4'b0; 394 assign user_ttype = 4'b0; 395 assign user_size = 8'b0; 396 assign user_data = 64'b0; 397 assign user_hop = 4'b0; 398 assign dest_id = 16'b0; 399 assign source_id = 16'b0; 400 assign id_override = 1'b0; 401 assign register_reset = 1'b0; 402 assign reset_all_registers = 1'b0; 403 assign stats_address = 4'b0; 404 405 406 407 408 // feed back the last captured data to VIO 409 always @(posedge log_clk) begin 410 if (log_rst) begin 411 captured_data <= 64'h0; 412 // IO interface 413 end else if (iresp_tvalid && iresp_tready) begin 414 captured_data <= axis_iresp_tdata; 415 // maintenance interface 416 end else if (maintr_rvalid && maintr_rready) begin 417 captured_data <= axis_maintr_rdata; 418 end 419 end 420 421 // Continuous data flow 422 always @(posedge log_clk) begin 423 continuous_go_q <= continuous_go; 424 ireq_request_done_q <= ireq_request_done; 425 ireq_autocheck_error_q <= ireq_autocheck_error; 426 reset_request_gen <= sim_train_en ? log_rst : |reset_continuous_srl && continuous_in_process; 427 end 428 429 always @(posedge log_clk) begin 430 if (log_rst) begin 431 continuous_in_process <= 1'b0; 432 end else if (continuous_go && !continuous_go_q) begin 433 continuous_in_process <= 1'b1; 434 end else if (!continuous_go && continuous_go_q) begin 435 continuous_in_process <= 1'b0; 436 end 437 end 438 always @(posedge log_clk) begin 439 if (log_rst) begin 440 reset_continuous_set <= 1'b0; 441 stop_continuous_test <= 1'b0; 442 end else if (continuous_go && !continuous_go_q) begin 443 reset_continuous_set <= 1'b1; 444 stop_continuous_test <= 1'b0; 445 end else if (!ireq_autocheck_error_q && ireq_autocheck_error && continuous_in_process) begin 446 stop_continuous_test <= 1'b1; 447 end else if (!stop_continuous_test && !ireq_request_done_q && ireq_request_done && 448 continuous_in_process) begin 449 reset_continuous_set <= 1'b1; 450 end else begin 451 reset_continuous_set <= 1'b0; 452 end 453 end 454 always @(posedge log_clk) begin 455 if (log_rst) begin 456 reset_continuous_srl <= 16'h0; 457 end else if (reset_continuous_set) begin 458 reset_continuous_srl <= 16'hFFFF; 459 end else begin 460 reset_continuous_srl <= {reset_continuous_srl[14:0], 1'b0}; 461 end 462 end 463 464 // SRIO_DUT instantation ----------------- 465 // for production and shared logic in the core 466 srio_gen2_0 srio_gen2_0_inst 467 (//--------------------------------------------------------------- 468 .sys_clkp (sys_clkp ), 469 .sys_clkn (sys_clkn ), 470 .sys_rst (sys_rst ), 471 // all clocks as output in shared logic mode 472 .log_clk_out (log_clk ), 473 .phy_clk_out (phy_clk ), 474 .gt_clk_out (gt_clk ), 475 .gt_pcs_clk_out (gt_pcs_clk), 476 477 .drpclk_out (drpclk ), 478 479 .refclk_out (refclk ), 480 481 .clk_lock_out (clk_lock ), 482 // all resets as output in shared logic mode 483 .log_rst_out (log_rst ), 484 .phy_rst_out (phy_rst ), 485 .buf_rst_out (buf_rst ), 486 .cfg_rst_out (cfg_rst ), 487 .gt_pcs_rst_out (gt_pcs_rst), 488 489 //--------------------------------------------------------------- 490 491 .gt0_qpll_clk_out (gt0_qpll_clk_out ), 492 .gt0_qpll_out_refclk_out (gt0_qpll_out_refclk_out), 493 494 495 496 // //--------------------------------------------------------------- 497 .srio_rxn0 (srio_rxn0), 498 .srio_rxp0 (srio_rxp0), 499 500 .srio_txn0 (srio_txn0), 501 .srio_txp0 (srio_txp0), 502 503 .s_axis_ireq_tvalid (ireq_tvalid), 504 .s_axis_ireq_tready (ireq_tready), 505 .s_axis_ireq_tlast (ireq_tlast), 506 .s_axis_ireq_tdata (ireq_tdata), 507 .s_axis_ireq_tkeep (ireq_tkeep), 508 .s_axis_ireq_tuser (ireq_tuser), 509 510 .m_axis_iresp_tvalid (iresp_tvalid), 511 .m_axis_iresp_tready (iresp_tready), 512 .m_axis_iresp_tlast (iresp_tlast), 513 .m_axis_iresp_tdata (iresp_tdata), 514 .m_axis_iresp_tkeep (iresp_tkeep), 515 .m_axis_iresp_tuser (iresp_tuser), 516 517 .s_axis_tresp_tvalid (tresp_tvalid), 518 .s_axis_tresp_tready (tresp_tready), 519 .s_axis_tresp_tlast (tresp_tlast), 520 .s_axis_tresp_tdata (tresp_tdata), 521 .s_axis_tresp_tkeep (tresp_tkeep), 522 .s_axis_tresp_tuser (tresp_tuser), 523 524 .m_axis_treq_tvalid (treq_tvalid), 525 .m_axis_treq_tready (treq_tready), 526 .m_axis_treq_tlast (treq_tlast), 527 .m_axis_treq_tdata (treq_tdata), 528 .m_axis_treq_tkeep (treq_tkeep), 529 .m_axis_treq_tuser (treq_tuser), 530 531 .s_axi_maintr_rst (maintr_rst), 532 533 .s_axi_maintr_awvalid (maintr_awvalid), 534 .s_axi_maintr_awready (maintr_awready), 535 .s_axi_maintr_awaddr (maintr_awaddr), 536 .s_axi_maintr_wvalid (maintr_wvalid), 537 .s_axi_maintr_wready (maintr_wready), 538 .s_axi_maintr_wdata (maintr_wdata), 539 .s_axi_maintr_bvalid (maintr_bvalid), 540 .s_axi_maintr_bready (maintr_bready), 541 .s_axi_maintr_bresp (maintr_bresp), 542 543 .s_axi_maintr_arvalid (maintr_arvalid), 544 .s_axi_maintr_arready (maintr_arready), 545 .s_axi_maintr_araddr (maintr_araddr), 546 .s_axi_maintr_rvalid (maintr_rvalid), 547 .s_axi_maintr_rready (maintr_rready), 548 .s_axi_maintr_rdata (maintr_rdata), 549 .s_axi_maintr_rresp (maintr_rresp), 550 551 .sim_train_en (sim_train_en), 552 .phy_mce (phy_mce), 553 .phy_link_reset (phy_link_reset), 554 .force_reinit (force_reinit), 555 556 557 .phy_rcvd_mce (phy_rcvd_mce ), 558 .phy_rcvd_link_reset (phy_rcvd_link_reset), 559 .phy_debug (phy_debug ), 560 .gtrx_disperr_or (gtrx_disperr_or ), 561 .gtrx_notintable_or (gtrx_notintable_or ), 562 563 .port_error (port_error ), 564 .port_timeout (port_timeout ), 565 .srio_host (srio_host ), 566 .port_decode_error (port_decode_error ), 567 .deviceid (deviceid ), 568 .idle2_selected (idle2_selected ), 569 .phy_lcl_master_enable_out (), // these are side band output only signals 570 .buf_lcl_response_only_out (), 571 .buf_lcl_tx_flow_control_out (), 572 .buf_lcl_phy_buf_stat_out (), 573 .phy_lcl_phy_next_fm_out (), 574 .phy_lcl_phy_last_ack_out (), 575 .phy_lcl_phy_rewind_out (), 576 .phy_lcl_phy_rcvd_buf_stat_out (), 577 .phy_lcl_maint_only_out (), 578 //--- 579 580 581 582 583 584 //--- 585 .port_initialized (port_initialized ), 586 .link_initialized (link_initialized ), 587 .idle_selected (idle_selected ), 588 .mode_1x (mode_1x ) 589 ); 590 // End of SRIO_DUT instantiation --------- 591 592 593 // Initiator-driven side -------------------- 594 595 596 // {{{ IREQ Interface --------------------------- 597 // Select between internally-driven sequences or user sequences 598 assign ireq_tvalid = (VALIDATION_FEATURES) ? val_ireq_tvalid : axis_ireq_tvalid; 599 assign ireq_tlast = (VALIDATION_FEATURES) ? val_ireq_tlast : axis_ireq_tlast; 600 assign ireq_tdata = (VALIDATION_FEATURES) ? val_ireq_tdata : axis_ireq_tdata; 601 assign ireq_tkeep = (VALIDATION_FEATURES) ? val_ireq_tkeep : axis_ireq_tkeep; 602 assign ireq_tuser = (VALIDATION_FEATURES) ? val_ireq_tuser : axis_ireq_tuser; 603 604 assign axis_ireq_tready = (!VALIDATION_FEATURES) && ireq_tready; 605 assign val_ireq_tready = (VALIDATION_FEATURES) && ireq_tready; 606 607 608 609 610 // When enabled, report results. 611 // This is a simulation-only option and cannot be synthesized 612 generate if (SIM_VERBOSE) begin: ireq_reporting_gen 613 srio_report 614 #(.VERBOSITY (2), 615 .DIRECTION (1), 616 .NAME (0)) // Data is flowing into the core 617 srio_ireq_report_inst 618 ( 619 .log_clk (log_clk), 620 .log_rst (log_rst), 621 622 .tvalid (ireq_tvalid), 623 .tready (ireq_tready), 624 .tlast (ireq_tlast), 625 .tdata (ireq_tdata), 626 .tkeep (ireq_tkeep), 627 .tuser (ireq_tuser) 628 ); 629 end 630 endgenerate 631 // }}} End of IREQ Interface -------------------- 632 633 634 // {{{ Initiator Generator/Checker -------------- 635 636 // If internally-driven sequences are required 637 generate if (VALIDATION_FEATURES) begin: ireq_validation_gen 638 srio_request_gen_srio_gen2_0 639 #(.SEND_SWRITE (1), 640 .SEND_NWRITER (1), 641 .SEND_NWRITE (1), 642 .SEND_NREAD (1), 643 .SEND_FTYPE9 (0), 644 .SEND_DB (1), 645 .SEND_MSG (1)) 646 srio_request_gen_inst ( 647 .log_clk (log_clk), 648 .log_rst (reset_request_gen), 649 650 .deviceid (deviceid), 651 .dest_id (dest_id), 652 .source_id (source_id), 653 .id_override (id_override), 654 655 .val_ireq_tvalid (val_ireq_tvalid), 656 .val_ireq_tready (val_ireq_tready), 657 .val_ireq_tlast (val_ireq_tlast), 658 .val_ireq_tdata (val_ireq_tdata), 659 .val_ireq_tkeep (val_ireq_tkeep), 660 .val_ireq_tuser (val_ireq_tuser), 661 662 .val_iresp_tvalid (val_iresp_tvalid), 663 .val_iresp_tready (val_iresp_tready), 664 .val_iresp_tlast (val_iresp_tlast), 665 .val_iresp_tdata (val_iresp_tdata), 666 .val_iresp_tkeep (val_iresp_tkeep), 667 .val_iresp_tuser (val_iresp_tuser), 668 669 .link_initialized (link_initialized), 670 671 // use these ports to peek/poke IO transactions 672 .go (go_req), 673 .user_addr ({10'h000, user_addr}), 674 .user_ftype (user_ftype), 675 .user_ttype (user_ttype), 676 .user_size (user_size), 677 .user_data (user_data), 678 679 .request_autocheck_error (ireq_autocheck_error), 680 .request_done (ireq_request_done) 681 ); 682 end 683 endgenerate 684 // }}} End of Initiator Generator/Checker ------- 685 686 687 // {{{ IRESP Interface -------------------------- 688 // Select between internally-driven sequences or user sequences 689 690 assign iresp_tready = (VALIDATION_FEATURES) ? val_iresp_tready : axis_iresp_tready; 691 692 assign val_iresp_tvalid = (VALIDATION_FEATURES) && iresp_tvalid; 693 assign val_iresp_tlast = iresp_tlast; 694 assign val_iresp_tdata = iresp_tdata; 695 assign val_iresp_tkeep = iresp_tkeep; 696 assign val_iresp_tuser = iresp_tuser; 697 698 assign axis_iresp_tvalid = (!VALIDATION_FEATURES) && iresp_tvalid; 699 assign axis_iresp_tlast = iresp_tlast; 700 assign axis_iresp_tdata = iresp_tdata; 701 assign axis_iresp_tkeep = iresp_tkeep; 702 assign axis_iresp_tuser = iresp_tuser; 703 704 705 // When enabled, report results. 706 // This is a simulation-only option and cannot be synthesized 707 generate if (SIM_VERBOSE) begin: iresp_reporting_gen 708 srio_report 709 #(.VERBOSITY (2), 710 .DIRECTION (0), 711 .NAME (1)) // Data is flowing out of the core 712 srio_iresp_report_inst 713 ( 714 .log_clk (log_clk), 715 .log_rst (log_rst), 716 717 .tvalid (iresp_tvalid), 718 .tready (iresp_tready), 719 .tlast (iresp_tlast), 720 .tdata (iresp_tdata), 721 .tkeep (iresp_tkeep), 722 .tuser (iresp_tuser) 723 ); 724 end 725 endgenerate 726 // }}} End of IRESP Interface ------------------- 727 728 729 730 731 732 assign autocheck_error = ireq_autocheck_error || maint_autocheck_error; 733 assign exercise_done = ireq_request_done && maint_done; 734 735 // }}} End of Initiator-driven side ------------- 736 737 738 // {{{ Target-driven side ----------------------- 739 740 // {{{ TRESP Interface -------------------------- 741 // Select between internally-driven sequences or user sequences 742 assign tresp_tvalid = (VALIDATION_FEATURES) ? val_tresp_tvalid : axis_tresp_tvalid; 743 assign tresp_tlast = (VALIDATION_FEATURES) ? val_tresp_tlast : axis_tresp_tlast; 744 assign tresp_tdata = (VALIDATION_FEATURES) ? val_tresp_tdata : axis_tresp_tdata; 745 assign tresp_tkeep = (VALIDATION_FEATURES) ? val_tresp_tkeep : axis_tresp_tkeep; 746 assign tresp_tuser = (VALIDATION_FEATURES) ? val_tresp_tuser : axis_tresp_tuser; 747 748 assign axis_tresp_tready = (!VALIDATION_FEATURES) && tresp_tready; 749 assign val_tresp_tready = (VALIDATION_FEATURES) && tresp_tready; 750 751 752 // When enabled, report results. 753 // This is a simulation-only option and cannot be synthesized 754 generate if (SIM_VERBOSE) begin: tresp_reporting_gen 755 srio_report 756 #(.VERBOSITY (2), 757 .DIRECTION (1), 758 .NAME (8)) // Data is flowing into the core 759 srio_tresp_report_inst 760 ( 761 .log_clk (log_clk), 762 .log_rst (log_rst), 763 764 .tvalid (tresp_tvalid), 765 .tready (tresp_tready), 766 .tlast (tresp_tlast), 767 .tdata (tresp_tdata), 768 .tkeep (tresp_tkeep), 769 .tuser (tresp_tuser) 770 ); 771 end 772 endgenerate 773 // }}} End of TRESP Interface ------------------- 774 775 776 // {{{ Target Generator/Checker ----------------- 777 778 // If internally-driven sequences are required 779 generate if (VALIDATION_FEATURES) begin: tresp_validation_gen 780 srio_response_gen_srio_gen2_0 srio_response_gen_inst ( 781 .log_clk (log_clk), 782 .log_rst (log_rst), 783 784 .deviceid (deviceid), 785 .source_id (source_id), 786 .id_override (id_override), 787 788 .val_tresp_tvalid (val_tresp_tvalid), 789 .val_tresp_tready (val_tresp_tready), 790 .val_tresp_tlast (val_tresp_tlast), 791 .val_tresp_tdata (val_tresp_tdata), 792 .val_tresp_tkeep (val_tresp_tkeep), 793 .val_tresp_tuser (val_tresp_tuser), 794 795 .val_treq_tvalid (val_treq_tvalid), 796 .val_treq_tready (val_treq_tready), 797 .val_treq_tlast (val_treq_tlast), 798 .val_treq_tdata (val_treq_tdata), 799 .val_treq_tkeep (val_treq_tkeep), 800 .val_treq_tuser (val_treq_tuser) 801 ); 802 end 803 endgenerate 804 // }}} End of Target Generator/Checker ---------- 805 806 807 // {{{ TREQ Interface --------------------------- 808 // Select between internally-driven sequences or user sequences 809 810 assign treq_tready = (VALIDATION_FEATURES) ? val_treq_tready : axis_treq_tready; 811 812 assign val_treq_tvalid = (VALIDATION_FEATURES) && treq_tvalid; 813 assign val_treq_tlast = treq_tlast; 814 assign val_treq_tdata = treq_tdata; 815 assign val_treq_tkeep = treq_tkeep; 816 assign val_treq_tuser = treq_tuser; 817 818 assign axis_treq_tvalid = (!VALIDATION_FEATURES) && treq_tvalid; 819 assign axis_treq_tlast = treq_tlast; 820 assign axis_treq_tdata = treq_tdata; 821 assign axis_treq_tkeep = treq_tkeep; 822 assign axis_treq_tuser = treq_tuser; 823 824 825 // When enabled, report results. 826 // This is a simulation-only option and cannot be synthesized 827 generate if (SIM_VERBOSE) begin: treq_reporting_gen 828 srio_report 829 #(.VERBOSITY (2), 830 .DIRECTION (0), 831 .NAME (9)) // Data is flowing out of the core 832 srio_treq_report_inst 833 ( 834 .log_clk (log_clk), 835 .log_rst (log_rst), 836 837 .tvalid (treq_tvalid), 838 .tready (treq_tready), 839 .tlast (treq_tlast), 840 .tdata (treq_tdata), 841 .tkeep (treq_tkeep), 842 .tuser (treq_tuser) 843 ); 844 end 845 endgenerate 846 // }}} End of TREQ Interface -------------------- 847 848 849 850 851 852 // }}} End of Target-driven side ---------------- 853 854 // {{{ Maintenance Interface -------------------- 855 856 // Select between internally-driven sequences or user sequences 857 assign maintr_awvalid = (QUICK_STARTUP) ? val_maintr_awvalid : axis_maintr_awvalid; 858 assign maintr_awaddr = (QUICK_STARTUP) ? val_maintr_awaddr : axis_maintr_awaddr; 859 assign maintr_wvalid = (QUICK_STARTUP) ? val_maintr_wvalid : axis_maintr_wvalid; 860 assign maintr_wdata = (QUICK_STARTUP) ? val_maintr_wdata : axis_maintr_wdata; 861 assign maintr_bready = (QUICK_STARTUP) ? val_maintr_bready : axis_maintr_bready; 862 863 assign maintr_arvalid = (QUICK_STARTUP) ? val_maintr_arvalid : axis_maintr_arvalid; 864 assign maintr_araddr = (QUICK_STARTUP) ? val_maintr_araddr : axis_maintr_araddr; 865 assign maintr_rready = (QUICK_STARTUP) ? val_maintr_rready : axis_maintr_rready; 866 867 868 assign axis_maintr_awready = (!QUICK_STARTUP) && maintr_awready; 869 assign axis_maintr_wready = (!QUICK_STARTUP) && maintr_wready; 870 assign axis_maintr_bvalid = (!QUICK_STARTUP) && maintr_bvalid; 871 assign axis_maintr_bresp = maintr_bresp; 872 873 assign axis_maintr_arready = (!QUICK_STARTUP) && maintr_arready; 874 assign axis_maintr_rvalid = (!QUICK_STARTUP) && maintr_rvalid; 875 assign axis_maintr_rdata = maintr_rdata; 876 assign axis_maintr_rresp = maintr_rresp; 877 878 assign val_maintr_awready = (QUICK_STARTUP) && maintr_awready; 879 assign val_maintr_wready = (QUICK_STARTUP) && maintr_wready; 880 assign val_maintr_bvalid = (QUICK_STARTUP) && maintr_bvalid; 881 assign val_maintr_bresp = maintr_bresp; 882 883 assign val_maintr_arready = (QUICK_STARTUP) && maintr_arready; 884 assign val_maintr_rvalid = (QUICK_STARTUP) && maintr_rvalid; 885 assign val_maintr_rdata = maintr_rdata; 886 assign val_maintr_rresp = maintr_rresp; 887 888 889 // If internally-driven sequences are required 890 generate if (QUICK_STARTUP) begin: quick_maint_gen 891 srio_quick_start_srio_gen2_0 srio_quick_start_inst ( 892 .log_clk (log_clk), 893 .log_rst (log_rst), 894 895 .maintr_awvalid (val_maintr_awvalid), 896 .maintr_awready (val_maintr_awready), 897 .maintr_awaddr (val_maintr_awaddr), 898 .maintr_wvalid (val_maintr_wvalid), 899 .maintr_wready (val_maintr_wready), 900 .maintr_wdata (val_maintr_wdata), 901 .maintr_bvalid (val_maintr_bvalid), 902 .maintr_bready (val_maintr_bready), 903 .maintr_bresp (val_maintr_bresp), 904 905 .maintr_arvalid (val_maintr_arvalid), 906 .maintr_arready (val_maintr_arready), 907 .maintr_araddr (val_maintr_araddr), 908 .maintr_rvalid (val_maintr_rvalid), 909 .maintr_rready (val_maintr_rready), 910 .maintr_rdata (val_maintr_rdata), 911 .maintr_rresp (val_maintr_rresp), 912 913 // use these ports to peek/poke maintenance transactions 914 .go (go_maint), 915 .user_hop (user_hop), 916 .user_inst (maint_inst), 917 .user_addr (user_addr), 918 .user_data (user_data[31:0]), 919 920 .link_initialized (link_initialized), 921 .maint_done (maint_done), 922 .maint_autocheck_error (maint_autocheck_error) 923 ); 924 end else begin : no_quick_maint_gen 925 assign maintr_awaddr = 32'h0; 926 assign maintr_wvalid = 1'b0; 927 assign maintr_wdata = 32'h0; 928 assign maintr_bready = 1'b0; 929 assign maintr_arvalid = 1'b0; 930 assign maintr_araddr = 32'h0; 931 assign maintr_rready = 1'b0; 932 assign maint_done = 1'b1; 933 assign maint_autocheck_error = 1'b0; 934 end 935 endgenerate 936 937 // }}} End of Maintenance Interface ------------- 938 939 940 // {{{ Statistics Gatherer ---------------------- 941 942 // When enabled, statistics gatherer collects details about performance. 943 // This module is synthesizable and may be accessed through Chipscope 944 generate if (STATISTICS_GATHERING) begin: stats_gen 945 srio_statistics_srio_gen2_0 srio_statistics_inst ( 946 .log_clk (log_clk), 947 .phy_clk (phy_clk), 948 .gt_pcs_clk (gt_pcs_clk), 949 .log_rst (log_rst), 950 .phy_rst (phy_rst), 951 952 // outgoing port 1 953 .tvalid_o1 (ireq_tvalid), 954 .tready_o1 (ireq_tready), 955 .tlast_o1 (ireq_tlast), 956 .tdata_o1 (ireq_tdata), 957 958 // outgoing port 2 959 .tvalid_o2 (iresp_tvalid), 960 .tready_o2 (iresp_tready), 961 .tlast_o2 (iresp_tlast), 962 .tdata_o2 (iresp_tdata), 963 964 // incoming port 1 965 .tvalid_i1 (treq_tvalid), 966 .tready_i1 (treq_tready), 967 .tlast_i1 (treq_tlast), 968 .tdata_i1 (treq_tdata), 969 970 // incoming port 2 971 .tvalid_i2 (tresp_tvalid), 972 .tready_i2 (tresp_tready), 973 .tlast_i2 (tresp_tlast), 974 .tdata_i2 (tresp_tdata), 975 976 .link_initialized (link_initialized), 977 .phy_debug (phy_debug), 978 .gtrx_disperr_or (gtrx_disperr_or), 979 .gtrx_notintable_or (gtrx_notintable_or), 980 981 .register_reset (register_reset), 982 .reset_all_registers (reset_all_registers), 983 .stats_address (stats_ad