目录

  • 引言
  • 硬件连接
  • FPGA端实现
  • DSP端实现
    • 初始化
    • 门铃中断
    • 中断服务函数

引言

  本文主要介绍在FPGA和DSP之间实现SRIO通信的过程。FPGA和DSP的型号分别为JFM7VX690T80-AS(XC7VX690T)和TMS320C6455。目前实现的是两者互相交替发送门铃事务,系统功能示意图如下图:

参考资料:
SPRAA89A - TMS320C6455 Design Guide and Comparisons to TMS320TC6416T
DS183 - Virtex‐7 T and XT FPGAs Data Sheet:DC and AC Switching Characteristics
ANTC206 - Differential Clock Translation
PG007 - Serial RapidIO Gen2 Endpoint v4.1 LogiCORE IP Product Guide
SPRU976E - TMS320C645x DSP Serial RapidIO (SRIO)

硬件连接

  链路之间的连接采用100nF电容耦合,主要是不同的器件需要的时钟类型可能不同,需要注意。TMS320C6455需要采用LVDS或者LVPECL逻辑电平标准的差分时钟。而当时我们整个系统里的另一个处理器需要的是HCSL类型的时钟,两者不能直接兼容,需要在电路上做一些处理。

  HCSL类型时钟转LVDS类型时钟,参考ANTC206,用的是下图中的电路。原理是另外引入3.3V,并用电阻分压,得到LVDS类型时钟的1.2V的共模电压,实际测试时发现,TMS320C6455的差分输入阻抗已经是100Ω,因此外面不需要再挂100Ω。

  FPGA的GTX和GTH对参考时钟输入的电气要求比较松,只需要是电容耦合,并且差分电压的峰峰值在350mV~2000mV之间即可。HCSL类型的差分时钟电压峰峰值为1400mV(单端700mV),因此满足输入条件。

FPGA端实现

  FPGA端实现SRIO主要参考PG007这个文档。SRIO的IP的配置可以很简单,主要就是把链路数量、链路的速率和参考时钟频率配置一下,记住它的Device ID即可。

  IP实例化的时候,信号非常多,但是比较有用的就是四个AXI4-Stream端口,ireq,iresp,treq和tresp。用来发送和接收事务包。其余的都是IP的输出信号,方便观察调试,查找问题。下面是SRIO实例化代码的一部分,sys_clk是外部输入的参考时钟,IP能够输出log_clk给用户实现自己的逻辑。

    .sys_clkp(sys_clkp),                            // input wire sys_clkp.sys_clkn(sys_clkn),                            // input wire sys_clkn.sys_rst(~sys_rst),                             // input wire sys_rst.log_clk_out(log_clk),                          // output wire log_clk_out.log_rst_out(log_rst),                          // output wire log_rst_out.clk_lock_out(clk_lock_out),                    // output wire clk_lock_out.mode_1x(mode_1x),                              // output wire mode_1x.port_error(port_error),                        // output wire port_error.gtrx_disperr_or(gtrx_disperr_or),              // output wire gtrx_disperr_or.gtrx_notintable_or(gtrx_notintable_or),        // output wire gtrx_notintable_or.deviceid(deviceid),                            // output wire [15 : 0] deviceid.port_decode_error(port_decode_error),          // output wire port_decode_error.link_initialized(link_initialized),            // output wire link_initialized.port_initialized(port_initialized),            // output wire port_initialized
  • link_initialized和port_initialized指示链路和端口是否初始化完成
  • deviceid就是我们在IP配置中设置的值,会用在事务包的发送和接收中。
  • mode_1x指示当前工作在1x模式
  • port_error,port_decode_error,gtrx_disperr_or,gtrx_notintable_or用来指示是否出现错误。具体错误信息可以查PG007。
 .sim_train_en(1'b0),                            // input wire sim_train_en.phy_mce(1'b0),                                 // input wire phy_mce.phy_link_reset(1'b0),                          // input wire phy_link_reset.force_reinit(1'b0),                            // input wire force_reinit

  另外有这四根线是输入,可以给常量。一开始我直接把仿真例程搬过来用的时候没有给sim_train_en置零,导致链路一直有问题。其余的输出信号都可以悬空,
  还有一个我遇到的问题是,当时没注意到这个sys_rst是高电平复位,我直接把接了外部复位按键的Pin接到了sys_rst上,而电路上做的是低电平复位,导致没有按键按下的时候IP一直处在复位状态。所以这里对外部输入的复位取反(~sys_rst)。
  FPGA的实现总体来说比较简单,就只要发送门铃后等待门铃,接收门铃的时候发送响应,再接着发送门铃就行。发送事务的过程都是通过AXI4-Steam的接口,基本不会有问题。
  只是在工程最后输出bitstream文件的时候出了问题,提示需要购买license,参考这篇文章即可解决。

DSP端实现

DSP端的软件流程图如下图所示。程序的编写和调试主要是参考SPRU976E。

初始化

  从SRIO的初始化开始,只要能建立链路连接,就成功了一大半。
  首先要弄清楚C6455的SRIO的工作模式。下面的表格里给出了它有两种工作模式。

  • 1x/4x:工作在1条或者4条链路的模式,其中1条链路的情况下,可以是lane0或者lane2。也就是0~3四条链路中只有0和2两条链路作为单条链路进行通信;
  • 1x/1x:只能工作在1x模式,就是四条链路都是独立的。

  然后具体到代码配置过程中,下面的1x/4p让我误以为是4个端口都工作在1x模式,而实际上这里的1x/4p就是前面的1x/4x模式。我们的需求是把四条链路都独立使用,因此需要按照1x/1x的方式进行配置。


  工作模式配置在PER_SET_CNTL寄存器中的BOOT_COMPLETE置一的时候就生效。就是当这一位置一时,C6455就开始对端口进行初始化。而后就不能再去修改工作模式了。CSL中自带的CSL_srioHwSetup函数上来就对BOOT_COMPLETE进行写入(写0或是写1取决于用户的配置)
  一般情况下,如果直接写“1”,那么它就直接工作在1x/4x模式了;如果直接写“0”,那就是不起作用,同时可以对其它的寄存器做修改,如果想让其它的配置生效,就需要再写一次“1”,如此两次先后调用CSL_srioHwSetup才能将它的工作模式正确配置为1x/1x模式。
  因此需要对这部分函数做修改,为此我将SRIO的配置分为两个阶段,一个是“预设置”,CSL_srioHwPresetup完成工作模式以及其他的一些配置;另一个CSL_srioFlowCtrlEnable是对BOOT_COMPLETE置一,并且在最后启动“流控制”(PCR寄存器中的PEREN需要最后置一)。

 CSL_srioHwPresetup(hSrio, &setup);CSL_srioDbIntrRoute(hSrio, &DbInfo, CSL_SRIO_INTR0);status = CSL_srioFlowCtrlEnable(hSrio, &setup);if (status != CSL_SOK) {printf("SRIO: ... Hardwrae setup, failed\n");return -1;}

  如何判断是否初始化完成?可以通过SPn_ERR_STAT寄存器中的第1位,PORT_OK来判断。只有当PORT_OK为1时,端口之间的链路才建立起来。在调试过程中我发现通过CCS的“Registers”窗口看到的值和真实值是有区别的。我通过读取SPn_ERR_STAT寄存器中的数据,并打印到控制台上才发现虽然窗口中显示的没有变化,端口似乎还是没有初始化,但是读取数据之后打印的结果却是表明链路已经建立连接了。

 for(i = 0; i<4; i++){rdata = hSrio->regs->PORT[i].SP_ERR_STAT;rdata = (rdata & 0x00000002) >> 1;if(i == 3) printf("port %d OK = %d\n", i, rdata);else printf("port %d OK = %d, ", i, rdata);}

  如何判断当前链路工作在什么模式?可以通过SPn_CTL寄存器中的最高两位来判断,如果为“00”则表示当前这个端口是单链路的模式;如果为“01”,则当前是四条链路构成一个端口,而且只对于SP0_CTL有效。这里同样也会有类似上面的一样的毛病。就是CCS的Registers页面看到的值和实际值不符,需要打印输出才能看到正确的实际就结果。

 for(i = 0; i<4; i++){rdata = hSrio->regs->PORT[i].SP_CTL;rdata = (rdata & 0xC0000000) >> 30;printf("port %d Port Width = %d\n", i, rdata);}

  一般只要配置没问题,这个链路就能建立起来。FPGA用ILA可以看到port_initialized和link_initialized都变高,DSP可以看到PORT_OK那一位置一就没问题了。

门铃中断

  因为中断经常要用到,所以关于中断的配置这一块一定要非常熟悉才行。一个IntcObj把12个处理器中断源(VectID4~15)之一和128个Event之一联系起来,hIntc指向是IntcObj的指针。context和record是管理整个中断系统的全局变量,其中记录了所有中断服务函数的数量和函数地址。
  初始化中断控制器,首先对context初始化赋值,调用CSL_intcInit即初始化了中断向量表,但这是中断服务函数都是空的。接着使能全局中断,使能不可屏蔽中断,以上操作在整个程序中只需执行一次。而后的CSL_intcOpen则是对单个中断源进行设置,如果系统中有多个中断源,则需要类似地执行多次。CSL_intcOpen初始化了IntcObj,将128个Event之一和12个CPU中断源之一联系在一起,本质上是修改了INTMUX寄存器。CSL_intcPlugEventHandler将中断服务函数和特定的中断联系在一起,最后再使能中断(实质上是将IER寄存器中的特定bit置一),即完成了中断的配置。

CSL_IntcObj IntcObj;
CSL_IntcHandle hIntc;
CSL_IntcContext context;
CSL_IntcEventHandlerRecord record[1];
void IntcConfig()
{CSL_IntcParam vectID;CSL_Status status;CSL_IntcEventHandlerRecord isr_doorbell;context.numEvtEntries = 1;context.eventhandlerRecord = record;/** contex include a record, isr invoked from this record*/CSL_intcInit(&context);/** global enable and nmi enable* interrupt will be enabled until enable the correspond bit in ier*/CSL_intcGlobalEnable(&state);CSL_intcGlobalNmiEnable();/** set intmux register bounding vectID and eventID* when interrupt occure, cpu check intmux to determin witch interrupt occured*/vectID = CSL_INTC_VECTID_10;hIntc = CSL_intcOpen(&IntcObj, CSL_INTC_EVENTID_RIOINT0, &vectID, &status);/** isr_doorbell is a temp variable* the value will copied to record*/isr_doorbell.handler = (CSL_IntcEventHandler)&Rio0InterruptHandler;isr_doorbell.arg = hSrio;/** plug interrupt handler into record*/CSL_intcPlugEventHandler(hIntc, &isr_doorbell);/** enable interrupt*/CSL_intcHwControl(hIntc, CSL_INTC_CMD_EVTCLEAR, NULL);CSL_intcHwControl(hIntc, CSL_INTC_CMD_EVTENABLE, NULL);
}

  一般的中断配置流程就像上面说的那样,但是SRIO实际上有很多中断源,但分给它的只有3个Event(3/128),分别是INTDST0、INTDST1、INTDST4。所以实际上从门铃中断到Event还有一次映射。

  这里需要配置SRIO的门铃的中断路由寄存器(ICRR),因为门铃共有64个中断源,这每个中断源都可以连接到以上三个Event之一,每次有中断发生时,用户可以通过查询的方式进一步确定发生中断的具体事件。为此,我专门写了CSL_srioDbIntrRoute函数,用于设置门铃的ICRR寄存器。而且由因为SRIO的寄存器只有在使能SRIO外设之后才能读写,所以这个函数需要在CSL_srioHwPresetup之后调用。

中断服务函数

void Rio0InterruptHandler(void *arg
)
{CSL_SrioPortData sdata;sdata.index = 0;sdata.data = 0x00000001;flag += 1;CSL_srioHwControl(hSrio, CSL_SRIO_CMD_DOORBELL_INTR_CLEAR, (void *)&sdata);CSL_srioIntrRateCtrl(hSrio,CSL_SRIO_INTR0,0x0000FFFF);CSL_intcHwControl(hIntc, CSL_INTC_CMD_EVTCLEAR, NULL);
}

  以上是一个简单的中断服务函数,主要就是令flag自增1。每次中断产生时,有三处地方产生了中断标志,SRIO的ICSR,中断控制器的EVTFLAG和CPU的IFR。其中CPU的IFR会在每次中断服务函数被调用时自动清除,而另外两处中断标志则需要由软件手动清除。以上代码中的CSL_srioHwControl和CSL_intcHwControl就是实现这么目的。
  另外SRIO还有一个中断速率控制寄存器,这个在每次中断发生后都需要向它写入一个数,即使不做中断速率控制也要写0。不然如果第二次中断标识产生了也进不了中断。调试的过程中发现,如果直接往中断速率控制寄存器中写0,程序就会反复进入这个中断服务函数。因此需要写一个较大的值,或者在中断服务函数外调用CSL_srioIntrRateCtrl。

DSP与FPGA的SRIO通信实现相关推荐

  1. DSP与FPGA间简单通信时序

    DSP与FPGA采用EMIF接口通信,即将FPGA作为DSP的外部SRAM,只需设置EMIF控制的存储器为SRAM类型即可,DSP通过EMIF接口读写SRAM的时序如下: 参考datasheet< ...

  2. FPGA+DSP SRIO通信(一)——DSP端参数设置(通道)

    FPGA+DSP SRIO通信(一)--DSP端参数设置(通道) 原创 2017年04月19日 18:56:45 标签: SRIO-C66x 1217 经过漫长的探索之后,博主发现关于TI的板子调试和 ...

  3. 多通路fpga 通信_多核DSP和FPGA之间的高速SRIO通信

    多核 DSP 和 FPGA 之间的高速 SRIO 通信 汪安民 1 ,韩道文 2 ,徐焱 3 [摘 要] 摘要:在高速采样系统中,大量数据需要实时传输到处理器.尤其是 系统中存在多个处理器协同工作,就 ...

  4. 【FPGA】SRIO IP核系统总览以及端口介绍(二)(I/O Port 含义介绍)

    上篇博文:[FPGA]SRIO IP核系统总览以及端口介绍(一)(User Interfaces 之 I/O Port)根据数据手册PG007,介绍到了逻辑层接口的IO口,今天想研究下,这些端口如何使 ...

  5. 基于FPGA的SRIO的相关介绍和实现

    SRIO的相关介绍和实现 1.SRIO简介 SRIO是面向嵌入式系统开发提出的高可靠.高性能.基于包交换的新一代高速互联技术,已于2004年被国际标准化组织(ISO)和国际电工协会(IEC)批准为IS ...

  6. 物理气相沉积半导体设备 PVD DSP/ARM+FPGA控制器设计

    磁控溅射技术属于PVD(物理气相沉积)技术的一种,是制备薄膜材料的重要方法之一.它是利用带电荷的粒子在电场中加速后具有一定动能的特点,将离子引向被溅射的物质制成的靶电极(阴极),并将靶材原子溅射出来使 ...

  7. 【FPGA】SRIO IP核系统介绍之事务类型(Transaction)

    RapidIO规范定义了几种事务类型. 每种事务类型执行不同的功能. IP核的事务支持是通过Vivado®集成设计环境(IDE)设置的. 表3-1列出了已定义的事务类型,并指示事务所属的LOG端口. ...

  8. 【FPGA】SRIO IP核的三层协议的作用?

    SRIO这种高速串口复杂就复杂在它的协议上,三层协议:逻辑层,传输层以及物理层. 数据手册会说这三层协议是干什么的呢?也就是分工([FPGA]SRIO IP核系统总览以及端口介绍(一)(User In ...

  9. ARM、DSP、FPGA的技术特点和区别

    首先,他们都是微处理器,都是嵌入式系统开发的核心,这也是他们与嵌入式的区别.单片机,也是微处理器,但不如他们集成的功能强大,要外扩设备.因此,确切的说,是微控制器. 在嵌入式开发领域,ARM是一款非常 ...

  10. ARM、8051、AVR、MSP430、Coldfire、DSP、FPGA七种体系比较区别

    本文来自米尔科技,原文地址:http://www.myir-tech.com/resource/502.asp,转载请注明出处. 我以为这样比没有意义,做嵌入式系统最大特征是"嵌入" ...

最新文章

  1. 20年第三次架构大调整,腾讯永远年轻!
  2. 王劲对外发声:确已离开景驰,不是因为百度诉讼
  3. java class 使用_Java反射机制(Class类的使用)
  4. 计算机网络平台实验,计算机网络实验
  5. 微信小程序实现web端锚点功能
  6. Trace SAP OData execution in CRM backend system
  7. .Net程序员学习Linux最简单的方法(转载)
  8. linux acl源码,acl框架库下载
  9. php urldecode 加号不显示_php|urldecode urlencode 的加号问题
  10. php curl 下载文件
  11. html静态页面作业 我的家乡网站设计——我的家乡-杭州(7页) HTML+CSS+JavaScript 大学生家乡网页作品 老家网页设计作业模板 学生网页制作源代码下载
  12. 【生信技能树】GEO数据库挖掘 P5
  13. hadoop 常用命令
  14. java 调用微信JsApi支付
  15. GoogleEarth-- 一日坐看天下八千里
  16. Intel 网卡使用
  17. 第五章、DOS基本命令与批处理(千峰网络安全300课时笔记)
  18. 济南商讯在线计算机,迅时IP话机 NRP2000W
  19. iOS 模拟微信内置浏览器CYWebViewController
  20. Scratch软件编程等级考试四级——20191221

热门文章

  1. 2020抖音无人直播技术:最新不封号无人直播的操作方法详细介绍
  2. PMF镜像中文件提取/diskgenius做的镜像文件
  3. android平板管理工具,安卓平板如何提升使用效率,这17款软件你应该知道
  4. troublemaker中文谐音_troublemaker歌词, trouble maker 音译中文歌词
  5. 原创度检测工具-免费原创度检测软件-在线伪原创免费工具
  6. 专利交底书怎么写 -
  7. 最最简单的使用DW编程软件
  8. java keytool证书cer,keytool 生成cer证书
  9. 架构系列---发号器(全局唯一ID生成器)系统设计方案和思路
  10. 大牛直播SDK: 如何实现简单粗暴靠谱的直播抓娃娃方案