4

国产CPLD(AGM1280)试用记录——做个SPI接口的任意波形DDS [原创www.cnblogs.com/heles...

 2 years ago
source link: https://www.cnblogs.com/helesheng/p/16692320.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

国产CPLD(AGM1280)试用记录——做个SPI接口的任意波形DDS [原创www.cnblogs.com/helesheng]

我之前用过的CPLD有Altera公司的MAX和MAX-II系列,主要有两个优点:1、程序存储在片上Flash,上电即行,保密性高。2、CPLD器件规模小,成本和功耗低,时序不收敛情况也不容易出现。缺点也很明显:1、没有片上RAM,无法对数据进行高速暂存和处理;2、没有PLL,使用一个以上的高频时钟非常不方便;3、没有小封装产品,MAX-II最小的EPM240也是LQFP100封装。近年来,随着Altera被Intel收购,对MAX-II的支持力度不断降低,当前EPM240的价格也达到了百元左右。

最近在B站关注到一种国产CPLD——AG1280Q48,几乎满足了我对CPLD的一切幻想:1、片上Flash,上电即行。2、有1280个LUT和触发器,资源足以媲美小型FPGA,而工作电流仅为几个mA——MAX-II的几分之一。3、成本低到数元。3、QFN48小封装,节约嵌入式系统空间,焊接又相对BGA封装简单。4、拥有和FPGA类似(包括PLL和片上RAM块)的资源,可用于完成以往CPLD无法完成的任务,如信号缓冲,高速通信等。

AG1280和STM32、GD32等低成本MCU联合使用时,能将只有专用解决方案才能完成的功能带给通用嵌入式系统。个人感觉,AG1280的最佳应用场景是在低成本应用领域和MCU协同工作, MCU+AG1280能部分替代Xilinx的Zynq方案。(注:AGM公司也有类似Zynq的ARM Cortex-M3 + FPGA方案,但我个人不看好这些方案,原因在于嵌入式工程师使用这些新MCU的开发环境和固件库的学习成本过高,没有学习动力。)

为验证这一设计思路,我自己动手做了一个MCU+AG1280+DAC的DDS(直接频率合成器)系统,跑通了STM32+AG1280的开发过程。其中AG1280除了完成DDS算法所需的地址累加、数据表格存储和查询之外,还实现了与STM32之间的同步串行数据接收和波形表格存入。现将开发全过程分享给各位网友,相信会对大家有一定的参考价值,也供大神批评指正。

有网友可能会较真质疑方案的意义:STM32有片上DAC,且还支持DMA,可以构成任意型号发生器,为什么还要用附加的可编程逻辑器件和DAC芯片?其原因在于STM32的DMA不支持存储器的地址递增值变化,因此不用中断无法实现DDS算法——而这也正好体现了AG1280在系统中的价值。

以下原创内容欢迎网友转载,但请注明出处: https://www.cnblogs.com/helesheng

一、硬件电路

MCU开发板很多,这里就不“重复发明轮子”了——直接用手头STM32开发板上的PMOD接口来和AG1280子板连接。系统硬件方案框图如下图所示。

(注1:PMOD接口是由Xilinx官方定义的一种用于其FPGA开发板的低速接口,现在很多FPGA和嵌入式处理器开发板上都有这种接口。PMOD仅使用12芯2.54mm间距的两排普通连接器,其中含有8个GPIO以及电源、地。

注2:有PMOD接口的单片机开发板可以自行搜索购买,我们教研室自己也开发过自编教材的配套Innovation-STM32开发板。)

 

1380455-20220915120935810-922680990.jpg

图1 系统硬件框图

用STM32开发板的PMOD连接一块自制的,具有一主一从两个PMOD接口的AG1280板子,该板子的另一个PMOD接口用于连接DAC板子。至于DAC我选用了常见的低成本同步串行芯片DAC7512。AG1280板子和DAC板子的电路图如下所示。

1380455-20220915121630101-1394774213.jpg

图2  两个PMOD接口的AG1280电路原理图

1380455-20220915121725191-955365471.jpg

图3  PMOD接口的DAC7512电路原理图

图2是AG1280基本电路,值得注意的有几点:

1、IO_GLOBE_S1(位于第9脚)、IO_GLOBE_S2(位于第13脚)、IO_GLOBE_S3(位于第15脚)、IO_GLOBE_S4(位于第19脚);IO_GLOBE_N1(位于第41脚) 、IO_GLOBE_N2(位于第44脚) 、IO_GLOBE_N3(位于第46脚)可以作为全局时钟输入管脚,可用于输入全局时钟。但若要使用PLL,则只能从13、15和19管脚输入

2、图2电路板载一个20MHz有源晶振,另外还可以通过PMOD接口从STM32的MCO时钟输出管脚获得时钟,它们被连接到具有PLL输入功能的管脚13、15上。

3、AG1280的GPIO分为North和South两组,可以使用不同IO电平,以实现不同电平逻辑的转换。另外AG1280还需要3.3V电源作为片上Flash电源,且该电源域North组的IO电源共用,因此North组也只能使用3.3V的IO电源电压。South组却可以任选电源电压

4、AG1280还需要1.2V内核电源电压,且该电源应略迟于Flash电源上电,以方便Flash加载程序。我的图2电路通过PMOD接口从STM32开发板获得3.3V电源,再用LDO芯片XC6206P122MR从3.3V向下稳压到1.2V内核电源,LDO后带有100uF电容,1.2V上电时间自然要落后于3.3V上电。

二、基于Supera和Quartus II的AG1280开发流程

AG1280的开发EDA软件Supera还不具备分析和综合电路的能力,但能实现其特有的PLL和片上RAM的IP核打包、综合后的布局布线、下载文件打包及下载等功能。我计划完成的DDS系统,完整的包含了PLL、片上RAM以及全部开发流程。

1、开发平台搭建

到百度网盘http://pan.baidu.com/s/1eQxc6XG 提取密码:q59e下载AGM公司EDA开发软件Supra(网盘上有多个版本的Supra,选择需要的一种即可)。Supra无需安装,下载后将其放置在不含中文的路径下,直接运行Bin目录下的Supra.exe即可。

目前版本的Supra还无法进行硬件描述语言及原理框图的开发和电路综合,用户只能在Supra下创建工程并完成AGM公司特有IP(包括PLL和RAM)的配置,再通过Supra创建Quartus-II工程文件,在转到Quartus-II下完成硬件描述语言和原理框图开发和电路综合,最后再回到Supra中完成器件内部的布局布线、下载文件的打包和器件烧写(具体流程在后续会详细介绍)。

综上,进行AG1280的开发一定需要安装一个顺手的Quartus-II。这里特别提醒网友注意,Supra只支持Quartus-II 13.0以上,且不支持Web与Lite版本,必须安装Full或Standard版本(本人掉到过坑里,因此特别提醒大家注意)。至于Quartus-II的安装方法,网上资料较多,这里不再赘述。

AG1280可以使用Intel的USB-Blaster进行下载和软件调试,但淘宝网上USB-Blaster版本较多,价格差异较大。据网传,有的版本USB-Blaster不支持AG1280的Flash下载,大家可自行注意避坑。

2、开发流程

1)新建Supra工程

运行 Supra,选择 File - Project - New Project。

1380455-20220915122104618-1221242626.png

图4 新建Supra工程

随后选择工程存放路径并填入工程名称,注意不要使用中文路径、国产路径,也不要在路径中使用空格。

2)配置AGM自有硬件IP

AGM公司自有的硬件及其相关电路的IP只能在Supra中配置。先配置PLL:选择Supra中Tools - CreateIP – Create Pll菜单,在弹出的下列界面中配置PLL。

1380455-20220915122147522-868965416.png

图5 配置PLL IP

分别配置模块名称、输入频率、PLL类型、反馈模式、输出时钟路数、输出频率后,单击Generate按钮产生IP和顶层封装HDL文件(模块名称.v和模块名称.ip)。

其中值得注意的是:AG1280有两种时钟源模式:片内RC振荡器模式和片外有源振荡器模式。可以在反馈模式(Feedback mode)选项中选择EXT_FEEDBACK,以选择外部有源振荡器模式;选择NO_REFERENCE,以选择片上RC振荡器模式。片上RC振荡器振荡频率不会太准确,供不需要精确定时的系统使用。若选择片上振荡器则应在输入频率(Input frequency)处输入8MHz,否则真实输出频率将与你输入的频率成比例变化

另外,Supra中AG1280的PLL配置中的PLL类型(PLL type),只能选择PLLX。而输出路数(PLL output count),相位移动(Phase shift)等配置参照字面意思理解即可。

继续配置AG1280的片上存储器RAM IP:选择Supra中Tools - CreateIP – Create memory菜单,在弹出的下列界面中配置片上BRAM。

1380455-20220915122225957-315780094.png

图6 配置片上存储器IP

根据我的DDS系统设计思路,AG1280实现的DDS控制器能从MCU接收波形数据,同时向DAC输出实时波形数据,因此,需要实现一个双口RAM。如图6所示,将存储器IP配置为2个端口,每个端口的数据宽度都是12bits(DAC7512的分辨率为12位),存储器深度为256(DDS算法要求波形表深度为2的整数次幂)。AG1280片上RAM较多,也可以选择更大的存储器深度,以获得更高信噪比。

另外,我还选择了复位后从Flash向双口RAM内部加载初始数据,因此指定了初始化数据文件(Select init file)。根据DAC7512对数据数据格式的要求,这些数据是0-4095之间的无符号数,你可以通过MATLAB或Python等工具计算产生。注意,Supra数据文件的格式与Quartus-II的MIF、HEX都不一样;Supra要求数据文件中,每个数据占一行,且采用ASCII码表示十六进制数。例如下面一样。

862
893
8C4
8F5
925
956
986
9B6

完成IP配置后,单击Generate按钮,Supra将自动生成可在Quartus-II中调用的IP文件和Verilog HDL文件。

3)在Quartus-II中完成功能模块开发

单击Supra菜单中Tools – Migrate,将工程移植为Quartus-II工程。在下图所示的配置窗口中输入工程名称、器件、需要使用的之前创建的IP等信息后,单击Next按钮。

注:最下面一个对话栏中,需要输入所有需要转换到Quartus-II工程的IP名称,如果有多余一个IP需要转换,可以在两个路径之间用半角逗号分隔开来,也可以点击Browse按钮后同时多选多个IP文件。

1380455-20220915122417313-1855102569.png

图7 移植为Quartus-II工程

Supra弹出如下界面,可转入Quartus-II进行开发和综合电路。

1380455-20220915122525871-73558155.png

图8 移植为Quartus-II工程

此时Supra已经在工程目录下建了与其工程同名的Quartus-II工程(xxxxx.qpf),以及顶层Verilog HDL文件,下一步需要在Quartus-II中打工程完成所有电路模块代码或原理图的开发。下图是我创建的DDS系统工程——DDS_SPI_dualRAM下的各个模块层次关系。

1380455-20220915122558402-1326063760.png

图9 Quartus-II工程

可以看到,在缺省情况下Quartus-II工程使用的器件是Cyclone IV系列的EP4CE75F29C8,我们不需要修改该工程使用的器件。但可以限定Quartus-II通过增量编译模式不编译Supra已经生成的IP:右键单击PLL IP和memory IP,并将其设置为Design Partition(该功能只有Prime和Standard版本的Quartus-II才有)。

1380455-20220915122641399-606848054.jpg

图10 设置IP为Design Partition

在Quartus-II中运行Supra生成的脚本文件af_quartus.tcl:选择Quartus-II的Tools菜单下的Tcl scripts,并在弹出的窗口中运行工程目录下的af_quartus.tcl文件。

1380455-20220915122715299-371084231.png

图11 Quartus-II运行Tcl脚本

Quartus-II将弹出Windows命令行窗口,等待综合工程中的所有模块,综合成功后Quartus-II的任务就完成了(这里可能需要几分钟)。

此时Supra已经自动生成了一个文件名与工程名相同,使用后缀asf的管教约束文件。该文件目前还是空的,可以其中添加约束器件管脚的脚本。asf文件的语法与Quartus-II的tcl脚本管脚约束语法相同,例如:

set_location_assignment -to cs_host1 PIN_43

set_instance_assignment -name WEAK_PULL_UP_RESISTOR ON -to cs_host1

上面的脚本将cs_host1约束到了AG1280的43脚,并将其配置成了弱上拉模式,以防止干扰拉低cs_host1,造成数据误传输

4)在Supra中完成AG1280的布局布线和程序下载烧写

根据图2的硬件电路编辑完asf文件,即可返回Supra的图8所示界面,单击Next按钮。(注:若你已经关闭了Supra也不要紧,再次打开Supra工程后,单击Migrate按钮重新进入图8所示界面即可)。在随后的界面中检查配置,并单击Finish按钮,Supra将完成布局布线。

若一切顺利,在Supra下部的Message窗口中间看到编译成功的提示信息,即可进入下载文件打包和USB Blaster下载配置文件阶段:选择Supra中的Tools – Program,连接电脑、USB Blaster以及AG1280板子的JTAG接口,在弹出的窗口中单击Query Device ID来查询Supra是否连接到AG1280。若正确连接了硬件,AG1280的ID应该是0x00120010。随后,可以在Program from file中选择需要下载的文件,单击Browse按钮选择所需的下载文件。其中xxxxx_sram.prg是直接烧写到AG1280的SRAM中;xxxxx_hybird.prg是烧写到Flash中,可以实现程序掉电不丢程序,上电即行。(文件名中的xxxxx是Supra工程的名称)。

1380455-20220915122828143-1764171503.png

图12 程序下载烧写界面

单击Program按钮,即可烧写刚才完成的程序。

三、在AG1280上实现基于DDS算法的任意波形发生器

1、DDS原理

DDS算法的功能特点是可以获得非常高的频率分辨率,以取得近乎连续的频率调节效果。下面简述一下DDS算法的核心思想,帮助读者理解AG1280上的硬件模块的原理和相互关系。一时无法理解的初学者,可以进一步阅读其他介绍DDS原理的书籍和帖子。

假设存储器中有个长度为N=2^n的波形数据表格,这些数据为1个周期的波形。若用频率fc从该表格中每间隔K个点取出一个放入DAC中变为模拟信号,则DAC输出模拟信号的频率将是:

fo = fc * K / N              (1)

从(1)式中可以看出输出模拟信号的频率fo和每次在数据表格中跳跃的地址数k成正比:k每增加1,输出频率fo就增加fc/N。为获得足够搞得频率分辨率,即使得fo输出的频率能够接近连续的调节,N的数值应该越大越好。一些ADI公司的商业DDS芯片,N甚至达到了2^40 ≈ 1T,这样大的表格显然是无法直接存储在AG1280中的。好在用1T个点来存储一个周期的信号其实并没有多大意义:在表格中相临的很多点大概率都是相同的内容。既然相邻点的数据都差不多,还不如不存储——在波形表格中每相临2^p个点,只存储第一个点的数值,如果用到后续2^p - 1个点,则都用第一个点的数值来代替。则AG1280所需的数据表格长度仅为2^(N-p) = 2^n(其中,设n = N-p),这样在AG1280中只需要长度N位的累加器和频率控制字,他们在时钟控制下不断相加新的表格地址(也是N位),但在读波形表时,只使用这个N位地址的高n位,低p位地址则直接舍弃。

我们的系统使用的DAC是DAC7512,其输出模拟信号的刷新率fc为100KSPS,精度为12bits,取N为16,n为8。即所需的存储器为256(2^8)个12位(具体配置参见图6所示),地址累加器和频率控制字为16位。获得的频率分辨率为100K / 2^16 ≈ 1.53Hz,理论上频率调节范围上限为:100K / 2 = 50KHz(奈奎斯特频率),频率下限为:100K / 2^16 ≈ 1.53Hz。

2、硬件总体设计

AG1280中的整个电路以双口RAM为核心,其左侧接口与MCU相连,用于接收MCU下发的波形数据和频率控制字K的数值;右侧接口和DAC7512相连,用于依次输出DDS算法输出的数据。

双口RAM左侧地址由一个每次加1的计数器产生,以遍历所有的村春单元;右侧地址由一个每次加K的加法器产生,以实现DDS算法的频率控制。由于双口RAM的深度256刚好是2的整数次幂,所以无需特意处理计数器和加法器的溢出问题,溢出后自然返回地址开头即可。

AG1280中还应实现两个SPI接口:一个SPI从机接口(通过左侧的PMOD接口)用于接收来自MCU的数据;另一个SPI主机接口(通过右侧的PMOD接口)用于向同步串行接口的DAC7512下发数据。

左侧与MCU的接口除了需要接收波形数据之外,还需要接收频率控制字K。我通过两个管脚分别输出两个低电平选通信号cs1和cs2来区分当前下发的数据是波形数据还是频率控制字。

3、硬件实现

3.1 双口RAM右侧与DAC接口的电路部分

1)DAC输出同步时钟生成电路

DAC7512需要使用100KSPS的刷新率,需要25MHz的主时钟分配产生输出同步时钟信号sap_syc_sig,该信号还将同步双口RAM右侧的读取和DDS地址累加器的不断叠加。

ContractedBlock.gifExpandedBlockStart.gif

同步时钟生成电路

2)与DAC7512通信的SPI主机电路

ContractedBlock.gifExpandedBlockStart.gif

DAC7512驱动电路

上面的代码,使用独立的计数器分别产生SCK和CS信号,避免了由于组合逻辑信号链过长可能造成的建立时间不收敛问题。另外输入数据data_in只有12位,其内容就是模拟信号大小。DAC7512的SPI通信中需要使用16位数据,其高四位被上面的模块自动补充为控制字4’b0000,需要使用其他控制模式的网友,可以根据DAC7512手册自行修改。

3)DDS地址累加器电路 

ContractedBlock.gifExpandedBlockStart.gif

DDS累加器代码

注意,根据DDS算法,16位的累加器每次增加的值也是16位的频率控制字delta_addr(相当于公式(1)中的K),但每次只输出累加器的高8位作为双口RAM右侧的地址。

3.2 双口RAM左侧与MCU接口的电路部分。

4)根据不同片选信号,将MCU的SPI信号分解为波形数据和频率控制字的数据多路器电路

ContractedBlock.gifExpandedBlockStart.gif

主机SPI信号多路器电路

上述信号可以根据MCU输出的两个不同的片选信号cs1和cs2将MCU输出的mosi、sck信号分解为连接波形数据双口RAM的mosi_ram、sck_ram,以及与频率控制字向量的mosi_DdsDelta和sck_DdsDelta。

5)SPI从机接收寄存器电路

ContractedBlock.gifExpandedBlockStart.gif

SPI数据接收移位寄存器

这个电路被例化为两个实例,分别用于接收波形数据或频率控制字。读者也可以只例化一个SPI从机移位寄存器,但这样做数据多路器就要放在移位寄存器并行化之后。这一点可以根据器件资源消耗情况灵活决定。

6)双口RAM左侧地址生成电路

ContractedBlock.gifExpandedBlockStart.gif

双口RAM存储地址生成电路

这个地址生成电路用于产生将接收到的波形数据依次存入双口RAM所需的地址,是一个简单的带异步复位信号的加1增计数器。

注意:1、该计数器的时钟应使用MCU产生的波形数据片选信号cs1,这样在每次一个地址单元的数据传输后,可以产生下一个单元的地址。2、该电路需要一个异步复位,以实现双方地址的同步,MCU可以在每次开始一个新的波形数据传输之前,输出该复位信号,以实现MCU和AG1280之间的地址同步。

7)LED闪烁电路

LED闪烁电路并不是必须的,加上该电路是为了监测系统时钟是否正常工作。读者可以根据实际情况自信选择,代码不再给出。

8)顶层例化文件

顶层例化文件用于连接上述各个模块电路

ContractedBlock.gifExpandedBlockStart.gif

顶层例化电路

4、MCU软件实现

MCU软件通过SPI口完成波形数据和频率控制字的下载。SPI应配置为时钟空闲时低电平(CPOL=0),第一个脉冲边沿读取数据(CPHA=0)的模式。此处不再给出MCU初始化代码,仅给出下载波形表格和频率控制字函数的代码。

ContractedBlock.gifExpandedBlockStart.gif

MCU主机配置函数代码

三、总结

1、实际测试

1)系统

下图是本文使用国产CPLD器件AG1280设计的DDS系统。实验系统看起来有点丑,请大家海涵。

1380455-20220915132121286-1346755194.jpg

图13 实际制作的DDS系统

2)功能实测

本文设计的DDS系统相比于ADI公司商业化的DDS芯片,最大的特点在于可以自己下载所需的波形,我测试了一个信号处理领域常用的小波基——墨西哥草帽小波基作。需要使用下面的MATLAB代码产生所需的数据。

ContractedBlock.gifExpandedBlockStart.gif

墨西哥草帽小波基--MATLAB

用STM32的SPI1口把上面MATLAB脚本产生的数据下发到AG1280中的DDS系统后得到频率/周期可以调节的墨西哥草帽函数周期波形,用示波器观察1.5KHz的波形如下图所示。

1380455-20220915132336403-2045679251.jpg

图14 用本DDS系统产生的频率可调墨西哥草帽小波基函数

可以看到不论是频率的准确性,还是波形的完整性均达到了设计预期。

3)AG1280占用资源、功耗和上电运行时间实测

本文设计的DDS系统占用AG1280资源如下:

1380455-20220915132417682-431441474.png

图15 AG1280资源占用情况

可以看到逻辑资源仅使用了10-20%,而存储器资源仅使用了10%左右(当然有可能随着DDS波形表格增长而变大)。可以想见AG1280的资源能够满足一般的MCU+FPGA的嵌入式系统需要。

另外,据实测本系统中的AG1280在25MHz工作频率,PLL打开的情况下,功耗约为5mA左右。

本次测试中唯一让我觉得意外的是AG1280的上电配置时间——可达100ms-300ms。仔细想来也可以理解:AG1280需要从其片上Flash中读取程序,在配置到内部的查找表中方能正常使用,肯定要比STM32一类直接在Flash中运行程序的器件要慢。但在使用中就需要如果与STM32等MCU配合,在MCU上电后延时一段时间再和AG1280通信

2、AG1280和Supra使用感慨

国产PLD器件一路走来不容易,虽然存在套用国外大厂EDA软件,支持文档不足,工具不够专业等等问题——但瑕不掩瑜,AG1280已经具有相当的可用性和市场竞争能力。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK