LabVIEW FPGA中的流水式程序设计以及使用C#调用LabVIEW生成的程序集实现与FPGA交互



主要软件: Driver Software>>NI-RIO
主要软件版本: 4.0
主要软件修正版本: N/A
次要软件: Driver Software>>NI-HSDIO
硬件: Modular Instruments>>FlexRIO>>PXIe-7965R

问题: 客户要求通过FlexRIO-7965R和适配器模块6583进行多路脉冲信号之间相位差的测量,6583适配器模块的数字IO为32通道同步采集。客户要求FPGA的工作时钟频率为200MHz,计算24路信号与参考信号之间的相位差延时。在FPGA中,通过模块IO可以直接读取U32的32通道数字波形数据,但问题是,如何在一个时钟周期之内完成通道信号的拆分,同时在一个时钟周期之内完成通道之间的相位差的计算?同时,客户要求使用LabVIEW编程后,上层采用C#对相位差的结果进行调用,并且要求实现一些基本的交互功能。

解答:
FPGA编程与一般软件编程不同,最终的代码将转化为实际的硬件逻辑电路;特别是对于同步信号处理而言,FPGA的代码风格直接决定了最终同步信号处理可以达到的时钟上限。
要达到较高的时钟频率(200MHz甚至更高),必须尽可能的缩短FPGA中的关键路径。而最好的方法就是使用寄存器分割关键路径并使用流水式的程序处理架构。利用FPGA内部的寄存器等资源,以代码面积换取处理速率,实现FPGA中关键路径的拆分和隔离,从而提高FPGA对于数字信号处理的吞吐量。
 
流水线编程简介:
在FPGA的编程中,同步逻辑以寄存器的方式存储和传递数据。在每一个时钟的上升沿,寄存器输出当前值并将寄存器存储值更新为输入值,如图1所示。

图1 流水式寄存器传输
与非FPGA代码不同,如图所示程序中的寄存器的输出只在每一个时钟上升沿(单周期定时循环)更新,即每次循环,每个寄存器同步更新为寄存器的输入值。
 
流水线编程的好处:
         利用流水线式的机构编程,可以将一个时钟周期之内处理不完的任务分割到多个周期完成,这种方法的副作用是带来一定的处理延时,但是对于连续不断的数据处理,采用这种方法不仅不会造成数据处理效率降低,反而会因为缩短了FPGA中的关键路径而提高时钟上限,从而提高数据处理的吞吐率。
图2所示的3数乘法,由于逻辑代码实现乘法延时比较大,如果将两次乘法操作都放在一个时钟周期内完成,势必需要提高时钟周期,才能保证乘法完成。这样导致无法达到较高的时钟上限。而采用图3所示的流水式的3数乘法,那么只需要每个时钟周期只能完成一个乘法操作即可,时钟上限取决于单个乘法的逻辑延时。这样方法将上限时钟提高了一倍。

图2 单周期定时循环3数除法
图3 单周期流水线式3数除法
 
针对具体问题:
 
开发环境及软件模块
软件:
LabVIEW 2011 SP1
VS 2008或者VS 2010
NI-RIO 4.0
LabVIEW FPGA 11.0.1
 
硬件:
HSDIO 6545
FlexRIO 7965R
Adapter 6583
 
流水式通道拆分:
Adapter 6583进行U32的数据采集,首先通过“数字到布尔数组”的转化,然后通过数组索引的方式获取某一通道的数字信号。其中索引X对应通道X,通道拆分如图4所示:

图4 拆分通道
问题是,如果在一个时钟周期之内进行32路信号的索引,将无法保证FPGA以较高的时钟频率执行该操作,因为每一路通道拆分的延时不同,32路信号在一个时钟之内采用逻辑的方式拆分则容易导致总延时超过时钟周期,代码编译无法通过。
采用流水式的通道拆分,每个时钟周期拆分仅拆分一个通道:
图5 多级流水式通道拆分
通过多级寄存器缓存,实现了每一个通道仅拆分出一个数字通道,从而缩短关键路径,提高代码的吞吐率。对于25路信号的拆分,采用了25级寄存器缓存数据,每一级寄存器拆分得到通道数据再另外利用寄存器缓存,其中,拆分后的通道数据需要的缓存寄存器个数等于25-X(X为之前缓存的级数)。通过流水式的编程方式,保证了通道数据同步到达后级模块。
 
流水式相位差计算:
A、计数
使用边沿复位的计数器:脉冲上升沿计数器复位。通过计数值之差,确定两个脉冲之间的超前或者延时关系。

图6流水式计数器
可以看到,通过反馈节点构造的寄存器将计数器分割为3块逻辑代码区,虽然造成了3个时钟的计数延时,但是提高了计数的吞吐量。
B、相位差(Clocks)

图7 32位的减法,使用寄存器隔离逻辑代码。
 
实验结果
1、通过HSDIO产生测试数据:HSDIO以200MHz采样率输出16路Matching Ones信号:每一路每隔16个周期输出一次高电平“1”,因此脉冲宽度为1/200MHz,相连通道间延迟为一个HSDIO采样周期

图8 16通道测试信号
2、FPGA计算结果:

图9 相位差计算结果
结果分析:由于每一路为周期信号,因此计算其余15路数字信号与第一路数字信号之间的相位差存在超前(负值,如第一路和第二路之间的计数差为-15)或者延时(正值)两种计数值,这里只显示了各个通道相对第一个通道的延时量。FPGA的工作频率为200MHZ,可见,FPGA计算得到了如图所示的正确延时值。注:通道4显示结果不正确,是因为HSDIO在高频产生数字信号并传输到Adapter模块,信号中可能存在毛刺或者抖动,而造成漏检的现象。

2、 LabVIEW生成.net程序集
项目组织架构:

LabVIEW主程序框图(NI 6538 Continuous Acq-Internal Clock (Host).vi):
LabVIEW生成dll和exe大家已经都比较熟悉了,现在越来越多的用户采用C#进行编程,而C#编程主要是基于程序集的,而LabVIEW有很方便的生成程序集的方法。
1) 新建->.net互操作程序集
2) 修改程序生成规范名称、目标文件名、程序集空间名等

3) 配置源文件和设定函数
选择VI到导出VI,然后定义原型,适当删除不需要的参数。这里添加了commitstop.vi、主程序NI 6538 Continuous Acq-Internal Clock (Host).vi、readchannel.vi以及state.vi;生成互操作程序集时也会相应生成对应的函数。

         选中导出的VI,可以为VI定义函数原型;其中,主VI名称太长,重新定义函数原型的名称为start,其余保留默认函数原型及名称。

4) 生成程序集后会出现三个文件
当然使用LabVIEW生成的dll也可以被C#调用,但是调用的方法比较复杂,dll也需要放在system32的文件夹下。
Commitstop.vi和state.vi都是功能全局变量,它们的功能是实现了对主线程的交互操作。由于每个VI只对应一个函数,所以需要多个功能全局变量来实现更为复杂的功能供C#调用。
3、 C#语言调用互操作程序集
在C#中调用互操作集是非常简单实用的。注意不要使用.net 4.0,LabVIEW2012开始支持.net 4.0
1)       添加Test.dll到References中
2)       声明使用生成的互操作集命名空间(例如:Test)
using Test;
3)       设置资源名称,将start函数封装
        public string resourcename = "RIO2";
        public void Start()
        {
            Test.Fpga.start(resourcename);
        }  
4)       将start()作为后台线程先运行,这样可以方便用户在后台线程上进行交互操作
            //////-------------thread encoding--------------//////////////////
            Startprimary p = new Startprimary();
            Thread bbackgroundthread = new Thread(new ThreadStart(p.Start));
            bbackgroundthread.IsBackground = true;
            bbackgroundthread.Start();
            /////////----------------------------------------////////////////
5)       查看IOModule和Voltage是否设置好,可以开始采集。
            Test.Fpga.state(out IOModuleIOEnabled, out SetVoltageDone, LVEnum_2.read);
6)       开始采集信号,可以发现LabVIEW中的枚举变量在C#中有自己的定义格式,不需要额外定义。
            Test.Fpga.commitstop(LVEnum_1.commit, 0, 1);
7)       读取i通道的延迟([0,23])
            Test.Fpga.readchannel(out Delay[i], LVEnum_3.read, i);
8)       停止信号采集
            Test.Fpga.commitstop(LVEnum_1.stop, 1, 1);
 
C#控制台程序运行结果:
使用MAX生成16路Matching Ones:15路待测信号和1路基准信号(HSDIO为100M采样率输出数字脉宽),测量结果如下:


相关链接: http://www.ni.com/white-paper/7062/zhs

附件:
FPGA项目文件&C#项目文件PhaseDifference.rar




报告日期: 08/14/2012
最近更新: 08/29/2012
文档编号: 60D2UMPR