本任务实现了通过FPGA的SPI接口对adis16505芯片进行数据读写,能够通过配置寄存器,连续读10个寄存器(160位)数据以及16个寄存器(256位)数据,并存到bram里。
首先Creat block design,添加软核、AXI Interconnect核、以及自己的SPI核,并连线。
SPI的四个脚SCLK、SDO、SDI、CS脚为物理引脚,将其引出。SPI核上还有一个bram接口,添加bram核,将其与SPI接连接,bram的出口接bram控制器,再通过AXI Interconnect 核接到软核。
为SPI核、bram控制器分配地址。
Generate output products,然后Create HDL wapper,生成HDL顶层文件,将PS端当做一个IP核来使用。
建立时钟IP核,为提供block design里的非物理引脚Clk、spi_master_clk提供时钟,分别为100Mhz和5Mhz,locked脚接RSTN脚。
新建V文件,分别例化时钟IP核以及Wrapper核。创建XDC文件,将物理引脚进行管脚约束和时钟约束。
编译综合后生成bit文件,Export Hardware,Launch SDK,启动 SDK 开发环境。
SDK里通过C语言进行编程,根据SPI核的代码对应编写了读使能函数和写使能函数,能够控制SPI对某个指定地址进行读或写。还可以通过memcpy函数进行不同地址之间数据的传递。
首先对PROD_ID寄存器进行读测试。根据芯片手册知,该寄存器的地址为0x72,通过SPI为该芯片写一个0x72,会读到0x7940。通过ILA进行CS信号下降沿的抓取,观察SPI读写信号。
可见是SDI端写入的是0x72,SDO端读到的是0x7940,是正确的。
在SDK观察bram对应地址的值,是正确的,说明数据读完后成功存到了bram里。
接下来解决的关键问题:
- 连续读出160位数据并存进BRAM
- 连续读出256位数据并存进BRAM
1.连续读出160位数据并存进BRAM
首先要根据芯片手册观察连续读160位时SPI四个信号的时序
可见SCLK信号和DIN信号与之前相同,应修改的是CS信号,将CS信号拉低时间延长。CS信号的拉低时间是根据计数器cnt进行控制的,将cnt改为cnt==data_in_width+data_out_width时清零,令data_in_width=16,data_out_width=160,即cnt的值为0到176时,cs信号拉低。
在SDK端发送0x68指令进行读,最终成功读出了160位数据。
接下来将读出160位数据存进BRAM,在之前的状态机的基础上再加一个状态,并定义一个计数器cnt,由于是将160位写进32位bram里,所以通过语句(cnt<((data_out_width>>5)-1))控制循环。即160除32得5,将160位数据分5次写进bram里。在SDK端读取bram的地址,可见数据与SPI端读到的一致。表示数据成功写进了bram里。
2.连续读出256位数据并存进BRAM
首先要根据芯片手册观察连续读256位时SPI四个信号的时序
首先要将CS信号拉低时间延长,修改了data_out_width=256,结果发现无法读出256位数据。最终将各个相关信号通过ila进行抓取,最终将问题锁定在cnt上,cnt应为9位,之前读160时设为了8位。修改cnt位数,最终成功读出了数据,但160位数据之后的数据都为0。继续阅读芯片手册,最终发现应对寄存器MSC_CTRL进行配置,将其第9位设置为1后才能读256位数据。
在SDK端的通过memcpy函数将0x02先存入bram,然后写使能,起始地址为MSC_CTRL的地址0x60,最终将0xe002写入,将芯片配置为读256位模式。接下来再发送0x68指令进行读,成功将256位数据读出。
与160位同理,将其分8次写进32位的bram里,并在SDK端进行读取
对数据进行求和校验,可见最后16位是前面所有字节的和,证明数据正确。