【高速接口-RapidIO】5、Xilinx RapidIO核例子工程源码分析

期待大家的一键三连,爱你们!!!
总目录:总目录(经验分享)
献上链接:
【高速接口-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、等一段时间以后例子工程就会自动打开

 

三、例子工程详解

3.1 工程概述

       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)功能。

3.2 工程结构

       例子工程的顶层模块例化了所有核的所有组件和在硬件上执行所需要的例子代码,整个工程的结构如下图所示。

 

       整个结构包括时钟模块,复位模块,配置结构以及产生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_*)的注释。使用外部接口的工程结构如下图所示

 

3.3 工程分析

  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模块会用一个状态机强制对核重新初始化。

四、工程源码分析

3.1 顶层模块srio_example_top.v源码分析

       顶层模块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模块,这个模块用来收集统计信息,它是一个可综合的模块。部分源码如下图所示

 

3.2 模块srio_request_gen.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与响应事务对应的字段进行对比,在仿真时给出对应的提示信息。

 

       至此,整个产生请求事务的代码全部分析完毕,其他未分析到的代码大家自己尝试分析。

3.3 RAMB36SDP原语分析

       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。后面几次操作依次类推即可。

 

3.4 模块srio_response_gen.v源码分析

       模块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信号,源代码如下

 

       至此,整个响应事务的源代码分析完毕,其余未分析到的代码请自行分析。

3.5 模块srio_quick_start.v源码分析

       模块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

你可能感兴趣的:(rapidio,fpga)