所谓ADC通路,就是AD9361接收端数据经由FMC到达ZEDBOARD上XC7Z020芯片的PL引脚后,最后直到DDR3,内部通过的数据路径。如下图:
我这里简单说一下图中各个模块:
1,AXI_9361,这是跟9361接口的最前沿,无论接收和发送端,都是经由了这个模块。内部有时钟的处理,双边缘采集的处理,双边缘发送的实现。这个由于实现细节太多,需要专门分析。
2,wfifo模块,这个不是一个通用的fifo模块,而是ADI专门写的一个专用用来实现跨时钟域转换的模块。输入端是数据,en,valid,输出端也是这三类数据。看来主要目的无非就是时钟数据域传递。另外也有一个反馈闭环的脚。
是adc_dmac的控制端发出overflow信号告知wfifo模块的ovf脚,我这边已经发生溢出了,就不要再传输数据了。这里面隐含了一个很强的技巧。如果adc_dmac真的发生发生溢出了,告知wfifo有用吗?肯定没用的!那么adc_dmac那端可以在即将数据满的时候提起几个周期通过拉高overflow信号告知wfifo,我这边已经数据满了,不要再传了。wfifo需要n周期做出反应,儿后面pack的延迟是m个周期,所以那边adc_dmac必须保留至少(n+m)个空位。这样的好处在于,不需要每一级别都设置反馈握手信号,中间的pack编写逻辑就简单了很多,控制思路也就清晰了很多。
3,pack模块,显而易见的是这里将4路16位数据拼接64位的数据。我们可能想到操作,直接一个拼接符号不就完事了。不是那么简单,问题就在于en脚和valid脚。这思路数据通过en控制是否有效,也就决定了拼接方式不是简单{ a,b,c,d}的拼接方式。另外valid信号输入部分应该是告知有数据来了【用没用】,而en输入信号应该是表示此组数据参与拼接【有没有用】。看到pack端口上还有一个sync我觉得可能就是64位对其。比如之前发送了3个16位数据,要将这些发送出去就可以发送一个sync信号。当然输出端的adc_valid实际就是数据的ready信号,应该对应axi的ready但是不同之处是不需要回应。
接下来就简单看看这三个模块。
1,wfifo这个模块分析代码发现就是简单调用了一个双时钟ram,以及延迟了几级的信号用来实现时钟区域穿越。这里是一个简单的定制的双时钟fifo,看到了两级时钟延迟,由于不需要空慢信号的指示,也没有用gray码。
2,pack这个模块主要是实现数据的重新打包,输入四个16位都en,那简单,直接并列排开就行{a,b,c,d}。如果输入数据只有三个是en的,那需要重组一下数据成{0,a,b,d}的样子。 而那个valid我们还是认为有效的意思,就是说数据ready可以对下一级进行write。(分析了pack这个模块我们回头分析一下unpack这个模块会发现思路能更加清晰了一些)。
至于上述截图位什么是8路数据,这个模块是可以配置的,最多配置8路。我们这里可以看到配置的规则。
3,adc_dmac这个实例调用了axi_dmac模块。这个模块让我脑洞打开,居然是adi自己写的dmc控制器,利用了axi的时序和握手特征生生自己用手工代码撸出了一个dmac控制器。其发送部分(dac)和接收部分(adc)分别用了这样一个模块。
这个代码有点多,但是好像也很有规律。从模块名称看就是多个fifo,数据请求,分割长度(同时变换地址),还有就是axi_lite控制接口等。这个代码有点多,这个柿子不太软,不太好捏,我也要好好学习研究下再说。