磕磕碰碰 发表于 2022-3-29 16:42:43

【实验指导手册】AC620_AD9226_sdram_uart工程贴

# [基于FPGA的Ad9226数据采集系统设计与验证]

|工程源码                  |针对AC620||----01_设计实例 |--------AC620_AD9226_sdram_uart.zip|
| ---------------------------- | ------------- | --------------------------------------------------------- |
|相关视频课程            |             |暂无相关视频课程                                       |
|本实验对各开发板支持情况|
|开发板型号                |AC620|

本节导读

本节介绍了基于FPGA的Ad9226数据采集系统设计与验证方法。本案例基于芯路恒AC620_V2开发板(Cyclone IV E FPGA),结合两片 ADI 公司的单芯片、12 位、65 MSPS 模数转换器(ADC)AD9226芯片,实现了利用串口对AD9226数据采样转换控制并输出。

## 文档所涉及文件说明

本次实验配套的文件压缩包名为AC620_AD9226_sdram_uart,解压后可得到配套的工程文件,采样数据和调试工具等,具体如下图 1:

!(data/attachment/forum/202203/29/151211qbgjbuudimxtziim.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "1.png")

图 1 文件说明

1、AC620_AD9226_sdram_uart:基于AC620_V2开发板(Cyclone IV E FPGA)QUARTUS II 13.0平台AD9226数据采集系统源工程

2、ADCdata_to_wave_v2_2.m:基于MATLAB的采样结果数据处理函数

3、sscom5.13.1: 串口调试工具

**背景介绍**

在计算机广泛应用的今天,数据采集系统在许多领域都有着十分重要的应用。

数据采集是计算机与外部物理世界连接的桥梁,通过数据采集工作,自然界的许多模拟量信息能够借助计算机进行保存,分析,还原等操作。技术实践中,我们只需要制订上位机(PC)与移动数据采集器的通信协议,就可以实现两者之间阻塞式通信交互过程。

数据采集系统往往由传感器、模拟多路开关、放大器,采样保持器、AD转换器、计算机及外设等组成。在农业、工业、日常生活和航空航天等领域,尤其是在对信息实时性能要求较高或者恶劣的自然环境中,数据采集有其应用的必要性。比如说:在工业生产和科学技术研究的各行业中,常常有利用PC或工控机配合末端传感器对诸如液位、温度、压力、频率等参数进行实时监控和记录的需求。再比如说:在航天航空领域,卫星数据采集系统利用航天遥测、遥控、遥监等技术,对航天器远地点进行各种监测,并根据需求进行自动采集,经过卫星传输到数据中心处理后,送给用户使用。

现在常用的数据转换方式是通过数据采集板卡进行,常用的有如A/D卡以及422、485等总线板卡,我们今天要进行的实验,就是利用ACM9226数据采集卡实施数据采集。

### 工程目标任务

本工程介绍如何通过利用AC620开发板上的SDRAM资源,实现ACM9226模块的串口数据采集功能。

本工程在实验条件下,期望达到如下功能要求:

1、实验通过数据采集模块实现模数转换,传递给开发板。在这里,我们采用ACM9226双通道数据采集模块作为数据采集卡进行数据采集。为了真实模拟数据采集的实验环境,我们借助信号发生器作为信号源,使用时可以通过设置其不同频率进行采样观察效果。

2、使用相关的串口通信软件,通过串口发码指令,可以设定需要采集的字节数,选择采集通道号,启动采集。

3、使用相关的串口通信软件,可以按设定的采集参数,接收采集的数据。数据通过串口发送到串口调试软件。将读取到的数据我们进行DAT文件的保存,便于后期分析。

4、采集到的数据经过matlab波形分析,能够得到和输入波形一致的输出波形,无数据丢失,无杂波。

### AD9226简介

芯路恒ACM9226双通道 12bit AD 采集模块,采用了两片 ADI 公司的 AD9226芯片,此芯片是一款单芯片、12 位、65 MSPS 模数转换器(ADC),采用单电源供电,内置一个片内高性能采样保持放大器和基准电压源。它采用多级差分流水线架构,数据速率达 65 MSPS,在整个工作温度范围内保证无失码。该 ADC 采用高速、低成本的
CMOS 工艺及新颖的架构,分辨率和速度可达到现有双极性方案的水平,而功耗成本却低得多。芯片结构框图如图2_ 1。

!(data/attachment/forum/202203/29/151232c5rbjs7zb7j96sys.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "2.png")

图2_ 1 芯片结构框图

AD9226 的输入能够与成像、超声和通信系统实现轻松对接。其利用真差分输入结构,用户可以选择包括单端应用在内的各种输入范围和偏移。其动态性能也极为出色,采样保持放大器既适用于在连续通道中切换满量程电平的多路复用系统,也适合采用最高
Nyquist 速率及更高的频率对单通道输入进行采样。

!(data/attachment/forum/202203/29/151254miijp83ozpjt3aoi.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "3.png")

图2_ 2 AD9226时序图

通过时序图2_ 2,我们可以看到:AD9226在使用时无需对 AD 芯片进行配置,只需要我们提供时钟CLOCK,芯片就可以直接进行数据采集了,操作非常简便。也就是说,用户在使用本模块的时候,无需编写任何驱动逻辑,只需要每个时钟上升沿从端口上读取一个 12 位数据,即可传递到应用逻辑进行存储或者运算处理。

### 程序设计

整体来说,程序的硬件架构如下图2_ 4所示,PC端发送指令信息到FPGA,FPGA对ADC采集的数据进行读取缓存,通过串口发送到PC端:

!(data/attachment/forum/202203/29/151312dxag7e76ggh676gh.jpg?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "4.jpg")

图2_ 4 硬件架构图

下面给出原理级的简易的状态转移图2_ 5:

!(data/attachment/forum/202203/29/151336h8uu6154fxm3s5z9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "5.png")

图2_ 5 状态转移图

初步分析程序的状态机核心部分,主要分为上电,空闲,采样,串口上传四个部分。

程序上电后,进入状态2空闲状态,此时可以通过串口指令设置采样个数,设置采样频率,下发采样开始的指令。

FPGA收到采样开始指令后,进入状态3开始进行ADC采样。采样的同时数据直接储存在SDRAM中。如果未达到采样个数,则进行状态3的循环,如果达到采样个数,则进入状态4串口上传。如果串口上传完成,则返回空闲状态,如果串口上传未完成,则继续进行串口上传。为实现本次实验功能,工程设计了9个子模块,如下图2_ 6。

!(data/attachment/forum/202203/29/151402gsfzummkr55xpgss.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "6.png")

图 2_6 系统模块框图

内部各子模块功能如下:

u0:50M时钟输入,各频率锁相环输出。

u1:串口接收模块的指令接收功能。

u2、u3:接收到的指令进行翻译拆解,指令分类。

u4:状态机模块,协调各个模块的信号控制,程序状态的总控制模块。

u5:ACM9226数据输入12bit到16bit的转换。

U6:SDRAM的fifo数据写使能控制模块。

U7:SDRAM的含fifo封装模块,主要负责整个数据的存储功能。

U8:串口数据输出模块。

在明确了工程的整体架构以后,接下来我们对各子模块进行进一步分析。

#### 锁相环模块(pll)

PLL时钟模块主要负责将系统的50M时钟倍频分频产生相应的时钟输送给对应模块,主要负责SDRAM_control_top模块和系统其它模块工作时钟的产生,PLL模块产生的时钟信号如下图2_ 7:

!(data/attachment/forum/202203/29/151422enj1dl6n4kzkujnn.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "7.png")

图2_ 7 锁相环模块

表 1 锁相环模块接口功能描述


| 接口名称 | I/O | 功能描述                                  |
| ---------- | ----- | ------------------------------------------- |
| clk      | I   | PLL输入工作时钟,频率为50MHz            |
| c0       | O   | SDRAM_control_top的工作时钟,频率为100MHz|
| c1       | O   | SDRAM存储器芯片工作时钟信号,频率为100MHz |
| c2       | O   | 系统时钟,频率为50MHz                     |
| locked   | O   | 相位锁定信号                              |

lC0:该信号为SDRAM_control_top的工作时钟信号,由于SDRAM的工作时钟为100MHz这里时钟频率为100MHz。

lC1:该信号为SDRAM存储器芯片的工作时钟信号,时钟频率为100MHz,为了确保SDRAM接收数据的稳定性和可靠性,我们需要让SDRAM的工作时钟相位偏移-150度,所以该信号为一个100MHz相位偏移-150度的时钟信号。

lC2:该模块的工作时钟为系统时钟,输出的时钟频率为50MHz,作为各模块的工作时钟,也为SDRAM内部写fifo模块的写数据时钟。

#### 串口接收和串口发送模块(uart_byte_rx\uart_byte_tx)

本次实验的指令配置信息由PC端从串口调试软件下发到FPGA,PFGA接收来自串口的指令信息,设置采样的数据量、采样通道和采样频率,接收到的指令信息将由下一个模块进行解析。本次实验的波特率设置为115200,图2_ 8为串口接收模块图。

!(data/attachment/forum/202203/29/151442p4uo4uhuvforsqjs.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "8.png")

图2_ 8 串口接收模块

表 2 串口接收模块接口功能描述


| 接口名称       | I/O | 功能描述                  |
| ---------------- | ----- | --------------------------- |
| clk            | I   | 输入工作时钟,频率为50MHz |
| reset_n      | I   | 模块复位,低电平复位      |
| uart_rx      | I   | 串口数据接收端口          |
| baud_set| I   | 波特率设置端口            |
| rx_done      | O   | 1byte数据接收完成标志信号 |
| Data_byte | O   | 指令数据八位输出端口      |

本实验AD9226采集到的数据缓存在SDRAM中,通过SDRAM读fifo来读出SDRAM中的数据,串口发送模块把采集的数据发送到PC端,不过SDRAM读fifo输出数据位宽为16位,需要在state_ctrl模块进行位宽转换为8位宽的数据。串口发送模块发出的数据可在PC端通过串口调试助手观察到,串口发送模块如图2_ 9。

!(data/attachment/forum/202203/29/151505o670hrr88rwqn3q3.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "9.png")

图2_ 9 串口发送模块

表 3 串口发送模块接口功能描述


| 接口名称       | I/O | 功能描述                  |
| ---------------- | ----- | --------------------------- |
| clk            | I   | 输入工作时钟,频率为50MHz |
| reset_n      | I   | 模块复位,低电平复位      |
| send_en      | I   | 发送使能信号            |
| baud_set| I   | 波特率设置端口            |
| Data_byte | I   | 待传输8bit数据            |
| tx_done      | O   | 1byte数据发送完成标志   |
| uart_tx      | O   | 串口输出信号            |

#### 串口指令接收和指令解析模块(uart_cmd\uart_byte_rx)

这两个模块的作用,是把串口接收到的指令进行拆解和识别。从串口接收到指令数据后,uart_byte_rx模块将串口数据从串行信号转为8位的并行数据uart_rx_data。指令数据在模块中根据包头与包尾信息判断8字节指令信息是否有效。指令有效,uart_cmd会读取寄存器地址设置信息和采集数据的配置数据信息,串口指令接收模块如图2_ 10。

!(data/attachment/forum/202203/29/151524z511yl9l9qrraawr.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "10.png")

图2_ 10 串口指令接收模块

表 4 串口指令接收模块接口功能描述


| 接口名称   | I/O | 功能描述                  |
| -------------- | ----- | --------------------------- |
| clk          | I   | 输入工作时钟,频率为50MHz |
| Reset_n      | I   | 模块复位,低电平复位      |
| rx_done      | I   | 1byte数据接收完成标志信号 |
| rx_data | I   | 指令数据输入端            |
| cmdvalid   | O   | 指令信息解析完成标志信号|
| adress| O   | 寄存器地址信息数据      |
| data   | O   | 采样设置配置数据信息      |

从uart_cmd模块接收到的8位并行数据在uart_cmd模块中被解析出地址、数据和使能信号。uart_cmd_rx将前面解析出的数据,作为各个类型,分别储存在各个寄存器中,对采样的数据量和采样速率进行设置,uart_cmd_rx如图2_ 11。

!(data/attachment/forum/202203/29/151650zx326px02zbrahbb.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "11.png")

图2_ 11 指令解析模块

表 5 指令解析模块接口功能描述


| 接口名称               | I/O | 功能描述                  |
| ------------------------ | ----- | --------------------------- |
| clk                  | I   | 输入工作时钟,频率为50MHz |
| reset_n                | I   | 模块复位,低电平复位      |
| cmdvalid               | I   | 指令信息解析完成标志信号|
| adress            | I   | 寄存器地址信息数据      |
| data             | I   | 采样设置配置数据信息      |
| Start_sample         | O   | 采样使能信号            |
| adc_ch_sel      | O   | 采样通道选择信号          |
| set_sample_num   | O   | 采样数据量信号            |
| set_sample_speed | O   | 采样率设置信号            |

在这里,我们给出指令解析的代码和讲解:

```
always@(posedge loc_clk50m or posedge g_reset)if(g_reset)begin
    uart_baud_set <= 3'd4; //默认115200bps
    adc_ch_sel <= 2'b00;
    set_sample_num <= 16'd32768;
    start_sample <= 1'b0;
end
else if(cmdvalid)begin
    case(cmd_addr)
      0: start_sample <= 1'b1;
      1: adc_ch_sel <= cmd_data;
      2: set_sample_num <= cmd_data;
      4:
          begin
            adc_ch_sel <= cmd_data;
            set_sample_num <= cmd_data;
            start_sample <= 1'b1;
          end
      5: uart_baud_set <= cmd_data;
      default:;
    endcase
end
else
    start_sample <= 1'b0;

```

串口一次发送的数据内容为1个字节,为了实现通过串口修改这些寄存器的值,需要发送多个字节才能实现,为此,设计了简单的串口数据帧,该帧一帧数据共8个字节,包含帧头、帧尾、地址段(决定任务设定目标)、数据段。帧格式如下表 1所示:AD9226的控制指令,由8个字节的数据组成,前两个字节D0,D1用55 A5,最后一个字节D7帧尾用F0,标明这是一个接收的指令,第三个字节D2,标明的是控制存储地址,本工程中,我们定义00是发送启动命令,01是采样通道号,02是采样深度。

表 6 指令帧格式


| 数据 | D0    | D1    | D2   | D3          | D4          | D5         | D6      | D7   |
| ------ | ------- | ------- | ------ | ------------- | ------------- | ------------ | ----------- | ------ |
| 功能 | 帧头0 | 帧头1 | 地址 | data | data | data | data | 帧尾 |
| 值   | 0x55| 0xA5| xx   | xx          | xx          | xx         | xx      | 0xF0 |

下面讲解一下典型的参数设置方法:

如果采512字节的数据,则设置为:55 A5 02 00 00 01 00 F0

如果采65536字节的数据,则设置为:55 A5 02 00 00 80 00 F0

采样速率如果是5k,整个字节为:55 A5 00 00 00 27 0F F0

采样通道如果是9226的第一通道,则设置为:55 A5 01 00 00 00 01 F0

采样通道如果是9226的第二通道,则设置为:55 A5 01 00 00 00 02 F0

#### 12bit转16bit模块(ad9226_12bit_to_16bit)

在计算机中,端表示数据在存储器中的存放顺序。大端与小端是两种数据的存储方式,大端方式将高位存放在低地址,小端方式将高位存放在高地址。(比如将16位数0x1234存放在地址0x00,0x01两个连续地址中时,按照大端方式应该0x00中存放0x12,而0x01中存放0x34,小端方式0x00中存放0x34,而0x01中存放0x12)。

如果我们对引脚采用相同的理论,则写出来的12bit数据和引脚绑定的高位和地位,将呈现镜像关系。比如,我们引脚输出的12bit数据是12’b1011_0111_1111,则实际反应的模拟采样值是12‘b1111_1110_1101,如果模拟量再提高一个分度值,则得到12’b1111_1110_1110。如果我们错误的处理了大端和小端,误认为存储值和管脚输出值一一对应,则模拟量再提高一个分度值,得到的12bit数据是12’b1011_1000_0000,这样,就会丢失数据采样的规律,得到错误的结果。

数据采集卡采集到的12bit数据不便于计算机存储,由于计算机对数据进行分析、存储的时候都以8位或16位数据作为统一的存储标准,则我们需要将12bit数据转换成16bit数据进行存储。

图2_ 12模块的功能,是将输入的12bit数据,转换为16bit数据。

!(data/attachment/forum/202203/29/151743gjaj7n2lstlirjja.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "12.png")

图2_ 12 12bit转16bit模块

表 7 12bit转16bit模块接口功能描述


| 接口名称      | I/O | 功能描述                  |
| ----------------- | ----- | --------------------------- |
| clk             | I   | 输入工作时钟,频率为50MHz |
| ad_sample_en    | I   | 模块复位,低电平复位      |
| adc_ch_sel | I   | 采样通道信息信号          |
| ad_in1    | I   | 通道一数据输入信号      |
| Ad_in2    | I   | 通道一数据输入信号      |
| ad_out_valid    | O   | 数据输出有效信号          |
| ad_out    | O   | 采集数据输出信号          |

#### SDRAM控制器(SDRAM_control)

该控制器模块和读写两个FIFO共同组成了SDRAM_control_top模块,其中写FIFO负责将采集的数据缓存,由SDRAM控制器读取并控制其存储到片外存储设备SDRAM中,读FIFO负责对SDRAM中要读出的数据缓存并在SDRAM控制器的控制下输出。为SDRAM控制器加入两个FIFO,该设计很好地解决了在某些特殊的时刻,有些读或写会被忽略掉,而且数据的写或读不能连续对数据流进行缓存,只能间歇式的读或写SDRAM 数据,导致数据存储或读取遗漏的问题。关于SDRAM控制器和两FIFO之间的关系框图如下图2_ 13:

!(data/attachment/forum/202203/29/151908z7z6zik5h777wbjz.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "13.png")

图2_ 13 SDRAM控制器模块

其中的sdram_control模块的写使能Wr和读使能Rd是分别通过判断写FIFO模块和读FIFO模块中所存储的数据量来决定的。在写FIFO模块中,当存放的数据量大于一次突发写长度数据量时就将写使能Wr拉高;在读FIFO模块中,当存放的数据量小于整个FIFO能存放数据量的一半时就读使能Rd拉高。这样就能解决上述在连续数据流读取时,数据读取存在遗漏的问题。

SDRAM控制器(SDRAM_control)的作用是负责控制SDRAM中数据的读取和刷新,整个SDRAM控制器采用状态机实现,状态机的状态转移图如下图2_ 14所示。

!(data/attachment/forum/202203/29/151936hprzp0n6zl51l162.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "14.png")

图2_ 14 状态机的状态转移图

SDRAM在上电后,系统处于空闲状态,在上电初始化完成后进入刷新状态,此状态主要负责自动刷新操作,在此状态如果有读或写请求到来,状态将会转移到相应的读或写状态。读或写状态各自主要负责读写数据操作。整个状态机中对刷新操作、写数据操作、读数据操作是有一个优先级的,也就是某两个或多个操作请求同时到来时,先执行哪个操作,这里默认的优先级是刷新操作>写数据操作>读数据操作。

注意由于数据在写入和读出FIFO时都为16位,所以在设置FIFO时要将其位宽设置为16位其余的具体设置如图2_ 15所示。

!(data/attachment/forum/202203/29/153605aaa29hs0lw6nva9j.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "15.0.png")

由于数据的写入和读出是同时进行的,所以这里FIFO设置为双时钟,数据深度这里设置为512。

!(data/attachment/forum/202203/29/153805hiozaqfsae33nuaa.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "15.1.png")

!(data/attachment/forum/202203/29/153815w32uzsjb3phl6x63.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "15.2.png")

#### 状态控制模块(state_ctrl)

状态控制模块是本系统的核心控制模块,其依据uart_byte_rx模块给出的数据采集量信息set_sample_num、start_sample、SDRAM控制器模块wrfifo_full信号对SDRAM控制器模块的wdfifo的数据写入进行协调控制,同时对从SDRAM控制器模块读数据进行控制,对从SDRAM控制器模块读出的数据进行转换并控制输出到uart_byte_tx模块,状态控制模块如图2_ 16。

!(data/attachment/forum/202203/29/153918d0hlxg5sfhrxwgk4.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "18.png")

图2_ 16 状态控制模块

表 9 状态控制模块接口功能描述


| 接口名称             | I/O | 功能描述                  |
| ---------------------- | ----- | --------------------------- |
| clk                  | I   | 输入工作时钟,频率为50MHz |
| reset_n            | I   | 模块复位,低电平复位      |
| Start_sample         | I   | 采集开始使能            |
| Set_sample_num | I   | 采集数据量                |
| Sdram_init_done      | I   | Sdram重置信号             |
| Uart_tx_done         | I   | Uart_tx发送完成信号       |
| Rdfifo_empty         | I   | Rdfifo空信号            |
| Rdfifo_dout    | I   | Rdfifo读出的数据          |
| Wrfifo_full          | I   | Wrfifo满信号            |
| Wrfifo_clr         | O   | Wrfifo清零信号            |
| Ad_sample_en         | O   | Ad采集的使能信号          |
| Rdfifo_clr         | O   | Rdfifo清零信号            |
| Rdfifo_rden          | O   | Rdfifo读使能            |
| Uart_send_en         | O   | 到uart_tx发送数据使能信号 |
| Uart_tx_data    | O   | 到uart_tx八位发送数据   |

在这个模块中,定义了10个状态:

状态0:空闲状态

状态1:写fifo清0状态

状态2:ADC采样状态

状态3:读fifo清0状态

状态4:延时过渡状态1

状态5:延时过渡状态2

状态6:低8位数据开始发送状态

状态7:低8位数据发送进行状态

状态8:高8位数据开始发送状态

状态9:高8位数据发送进行状态

状态10:判断发送是否完成状态

第一步:程序上电后,状态机进入空闲状态。当SDRAM初始化完成并且收到开始采样的指令,则进入状态1。

第二步:进入状态1后开始清除写fifo内的原始数据。进入清写fifo状态后,FPGA发送三拍的拉高信号清写fifo指令,并且给出10拍的基本延时保证,当写fifo内的原始数据清除完毕后,fifo内部会将写端fifo_full的信号拉低。如果收到写端fifo_full信号拉低,说明fifo已经不满,FPGA可以开始向fifo内传递从ACM9226采集到的数据。

```
      DDR_WR_FIFO_CLEAR: //1
            begin
            if(!wrfifo_full && (wrfifo_clr_cnt==9))
                state<=ADC_SAMPLE;
            else
                state<=DDR_WR_FIFO_CLEAR;
            end

```

清除写fifo的指令,由三拍延时信号拉高提供:

```
/*初始化成功后,进行一次清fifo,如果进入了SDRAM_WR_FIFO_CLEAR状态,则在wrfifo_clr_cnt为0,1或2时,清写fifo置1,否则wrfifo_clr为0*/
      always@(posedge clk or posedge reset)begin
      if (reset)
                wrfifo_clr<=0;
      else if(ddr3_init_done==1'b0)
                wrfifo_clr<=1'b1;
      else if(state==DDR_WR_FIFO_CLEAR)
      begin
         if(wrfifo_clr_cnt==0||wrfifo_clr_cnt==1||wrfifo_clr_cnt==2)
                wrfifo_clr<=1'b1;
         else
                wrfifo_clr<=1'b0;
      end
      else
                wrfifo_clr<=1'b0;
      end

```

在程序中regwrfifo_clr_cnt信号为写fifo清零的状态计数和保持,当进入写fifo清零状态后,首先开始计数,先保证计数完成,再等待wrfifo_full(写端fifo满信号)的信号拉低,拉低后,表示可以往fifo里写入数据,此时进入下一个状态。在清空(复位)fifo的时候,fifo的full信号会变高,可以认为在复位fifo时是不允许对fifo进行写操作的,即使写也是不可靠的,等fifo的复位结束后,full信号会变低,就允许对fifo进行写操作。清写端fifo的控制信号是由计数器(在前3个计数值将清除控制信号拉高)产生3个时钟周期的高电平脉冲。

第三步:设定采样参数。采样数据的速率,和FPGA的非SDRAM工作时钟频率保持一致,为每秒传递50M的16位数据,采样数据的个数设定,项目开发时准备了两种方案,一种是通过VIO进行设定,这种方案较初级,我们工程中采用的是更高级一点的,就是前面提到过的,通过串口指令的方式进行设定。

第四步:进入数据采样状态即状态3。状态wrfifo_full拉低,在这个状态,每发送完一个数,则计数器加1,当发到和设定的采样需求个数相同时,跳转进入下一个状态,开始清除读fifo。

第五步:一旦进入读fifo清零状态,我们做和前面写fifo清零相同的操作,发出三拍的清零指令,同时保证一个10拍的基本延时。等延时结束并且接收到读fifo反馈的rdfifo_empty信号后,进入下一个状态。

第六步:下一个状态是延时过渡状态1,在这一拍,我们可以开启向读fifo发送一个脉冲的数据读使能信号(rdfifo_rden==1)。再进入延时过渡状态2。

第七步:进入延时过渡状态2后,关闭读fifo的数据读使能信号(rdfifo_rden==0)。进入低8位数据开始发送状态,则通知串口可以向外发送低8位数据了。接下来,按照串口的节奏,进行数据的发送。

关于串口的数据发送,在设计之初也有两种预备方案,一种是通过总节拍数控制串口发送的结束,另一种,是利用串口发送完成后给出的tx_done信号,和提取数据的判定条件形成关联,每当一个串口字节发送完成后,利用串口给出的tx_done信号,切换到下一个字节的发送开始状态。这个tx_done信号直接控制和协调下一个小循环读fifo的16位数据提取工作,提取的数据缓存工作,缓存的数据拆解字节到串口寄存器的工作。在本工程中,我们从节约串口时间成本的角度考虑,使用了方案2,而没有纯粹追求更简单的串口控制方法。同时,单个字节发送完成的信号,也可以作为从发送低8位到发送高8位的判定信号条件。

接下来的几个步骤描述的是串口数据位的发送。其对应的逻辑关系图如下图2_ 17。由于rdfifo_rden的脉冲信号要到下一拍才能让数据从rdfifo中读出,而读出的数据发送到串口的send_en脉冲信号要等数据稳定后下一拍生效才能发出正确的数据,所以,每个16位的数据,完成从fifo中提取到发送到串口,至少要三拍延时。

!(data/attachment/forum/202203/29/153959r99u7pj46j0o447o.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "19.png")

图2_ 17 串口数据发送逻辑关系图

上图为:在状态机使用条件下,从读fifo中读取数据,数据发送到串口的三拍延时的触发启动流程。

到最后,就是状态10,状态10是个用来判断是否完成数据块发送的状态,如果确实数据块发送完成,则回到IDLE状态大循环收口关闭,如果没有达到数据总共发送次数,则表明没有发送完,回到delay1状态,发送下一个数据,本轮16位串口发送小循环收口关闭,进入下一个小循环。

所有模块的功能介绍完毕,读者可再工程中查看更为详细的RTL视图,与我们的设计进行比较验证,工程的RTL视图如图2_ 18。

!(data/attachment/forum/202203/29/154028y66uqtv4cn0j9z28.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "20.png")

图2_ 18 系统RTL视图

在此再次特别提醒:在引脚绑定的时候,我们要特别注意ACM9226模块的LSB引脚和MSB引脚,AD9226的12位输出数据接口中,bit11为 LSB、bit0为MSB。这与我们FPGA中对于多位宽信号的高低位的处理恰好相反,ACM9226模块对应的LSB是数据位最高位,而对应的MSB是数据位的最低位。如果在绑定引脚芯片的时候没有注意,则有可能会得到没有规律的输出数据。所以使用时,要么在分配引脚时直接调换过来,要么在程序中对所有位的高低位置进行调换,不然采集到的数据将无法进行准确分析。下图2_ 19为AD9226数据接口引脚分配图。

!(data/attachment/forum/202203/29/155104eutckjj3jt5i451w.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "21.png")

图2_ 19 AD9226数据接口引脚分配图

### 仿真验证

在程序的设计过程中,建立有效的仿真可以验证我们的设计是否正确,可以解决绝大多数的设计问题,提高设计纠错效率。在本次设计中建立仿真文件时在设计testbench文件的同时还需要加入SDRAM模型例化文件sdr.v、SDRAM参数文件sdr_parameters.h,如图2_ 20所示。

!(data/attachment/forum/202203/29/155124zen719jt92g9zkbs.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "22.png")

图2_ 20 添加testbench文件

testbench仿真程序的设计主要针对两个方面,一个是指令的配置,分别设置采样的数据量,采样通道和采样频率。如下图所示,仿真程序成功配置指令信息,串口接收模块接收并输出八位的指令信息,uart_cmd模块解析到寄存器地址信息,采集设置的数据信息,仿真配置指令如图2_ 21;

!(data/attachment/forum/202203/29/155144p9xyyxnnzymgummg.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "23.png")

图2_ 21 仿真配置指令

另一个是对数据采集进行模拟,本实验中ad_in1、ad_in2的数据被设置成计数器数据,便于对仿真数据进行观察比对。当cnt_req信号有效,ad_in1、ad_in2开始输入计数器数据信息,如图2_ 22所示。

!(data/attachment/forum/202203/29/155202pqzh0aglqs6s1we6.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "24.png")

图2_ 22 仿真模拟采集数据

可对工程uart_byte_tx模块的输入模块的数据和模块输出的数据进行分析,验证系统功能是否符合设计,对于在设计过程中的程序功能问题也可以通过仿真进行查找验证,uart_byte_tx模块data_byte输入数据与发送数据如图2_ 23。

!(data/attachment/forum/202203/29/155356puc72cbc0cn12inm.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "25.2.png")

图2_ 23 uart_byte_tx模块的数据输入输出

## 工程演示

对系统功能设计完成并仿真验证通过之后,准备好硬件设施,连接好硬件,就可以对设计的工程进行板级验证测试实验功能。

### 系统所需硬件

1.AC620开发板。

2.AD9226数据采集模块。

3.电源线。

4.程序下载线、串口数据线(AC620二合一)。

5.信号发生器。

### 硬件连接

根据前面的描述准备好硬件,我们可以进行连接:

1.连接好ACM9226模块到AC620。

2.信号发生器的输出端连接到ACM9226模块的通道输入端,可根据设置连接不同通道。

3.连接好FPGA开发板串口连接线、程序下载线(二合一)。

4.连接好开发板电源。

硬件连接完成后如下图3_ 1 。在以上所有模块和线路连接好之后就可以打开开关,开始下载程序。

!(data/attachment/forum/202203/29/155428s5n7xtpkngymrmgp.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "26.png")

图3_ 1 硬件连接图

### 数据采集与分析

打开sscom5.13.1串口调试工具,依次设定好com端口,波特率,然后打开串口。点击多字符串,点击勾选三个指令栏,填入指令:

采65536字节的数据,则设置为:55 A5 02 00 00 80 00 F0

采样通道为第一通道,则设置为:55 A5 01 00 00 00 01 F0

采样的速率为5k,指令设置为:55 A5 00 00 00 27 0F F0

清空计数器和接收区后,从上到下依次点击勾选的1,2,3条数据串发送按钮,数据设定完成后开始采集,串口调试助手设置界面如图3_ 3。

!(data/attachment/forum/202203/29/155542otogj8ofdpmfmgf9.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "27.png")

图3_ 3 串口调试设置

通过调试窗口可以看到,采集的数据量和下发的指令是匹配的都为65536,对采集的数据做进一步的分析可以验证数据采集是否符合期望,可对采集数据利用MATLAB进行绘图分析。

通过串口调试助手可以判断采集的数据量是否准确,采样得到的数据是否是和信号发生器输出一致,仅凭人工,无法完成这个分析工作。因此我们需要借助matlab的绘制函数图形的功能。

打开ADCdata_to_wave_v2_2.m,MATLAB采样结果数据处理函数如图3_ 4。

!(data/attachment/forum/202203/29/155600qztfmyy4sfmeyq4h.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "28.png")

图3_ 4 MATLAB数据分析程序

图3_ 5中可以看到,点击串口助手保存数据会产生两个数据文件,第一个是DAT格式的数据文件,第二个是文本格式的数据文件,读者可根据自身需求对不同格式的文件进行调用,本次实验调用的的是DAT格式的数据文件。采集数据文件路径都与安装的串口调试助手的路径有关,在串口调试窗口中点击数据保存时会有显示,下图显示的是sscom5.13.1串口调试工具安装于桌面的数据保存路径。

!(data/attachment/forum/202203/29/155639oz6dadsdshydrayr.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "29.png")

图3_ 5 保存数据位置信息

文件为二进制格式DAT文件,调用时可复制文件到MATLAB安装路径下,这样修改文件名就可以进行图像绘制。DAT文件如图3_ 6所示。

!(data/attachment/forum/202203/29/160958oxgvd6jg2l0ycaga.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "30.png")

图3_ 6 DAT文件

打开matlab代码的工程文件,修改好文件路径,进行保存后点击运行就可以进行图形的绘制。在进行新一次的数据绘制分析前要关闭前一次的图形绘制窗口,否则会导致新数据的图形绘制无法加载。输出得到的波形如图3_ 7。

!(data/attachment/forum/202203/29/161014gzda3g9og33ld3o1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/300 "31.png")

图3_ 7 绘制的数据波形图

这样,通过观察绘制的数据图形就可以对上板实验采集数据进行验证。通过分析,绘制数据与信号发生器上设定好采样频率数据一致,数据采集无误,采集系统功能验证符合设计要求。

## 总结

本实验实现了通过串口下发指令对ACM9226模块采集数据的数据量、采集通道、采样速率进行合理设置,利用SDRAM对采集数据进行缓存,再通过串口对采集到的数据发送到PC端的数据采集系统。介绍了ACM9226模块的功能特点、使用方式和硬件连接方法,工程设计的思路,串口发码程序向FPGA发布工作控制指令的设计和应用方法,仿真建立的关键设置,利用matlab进行数据绘图的操作方法。

修订记录


| V1.0 | 2021/08/02 | 首次发布 |
| ------ | ------------ | ---------- |
|      |            |          |

869533010 发表于 2024-2-23 14:15:03

写的很详细,虽然还没开始使用该ad,但是还是感谢作者:handshake
页: [1]
查看完整版本: 【实验指导手册】AC620_AD9226_sdram_uart工程贴