一、图像采集显示设计架构的回顾
FPGA的外设有,图像传感器、DDR3芯片、VGA显示器。由于它们的特性不太一样,所以需要不同的时钟。FPGA内部需要一个PLL时钟管理单元分配好时钟。FPGA内部的跨时钟域模块的工作,需要通过FIFO来实现时钟域的同步。
图像采集 m_image_capture
图像缓存 m_ddr3_cache 它实现一个DDR3控制IP(DDR3的初始化,物理层都在这个模块)。
显示驱动 m_vga_driver
1、外设DDR3芯片需要400M的时钟频率。所以DDR3的控制IP最好能倍频到400M,选项200M。FPGA外部的晶振频率是50M。
2、图像缓存 m_ddr3_cache 实现两个FIFO,一个读,一个写。都是异步FIFO(DC FIFO)。DDR3 控制IP,与FPGA内部的模块之间的频率取决于接口的位宽。DDR3 控制IP的接口位宽是128bit。
那么怎么计算DDR3 控制IP与FPGA内部的时钟频率?
首先,DDR3 控制IP的位宽是128bit,而外设DDR3芯片的位宽是16bit。外设DDR3芯片的工作频率是400MHZ,吞吐率×2(400MHZ×2)。则由公式可以算出:(400M×2)÷(128÷16)=100M 。则读写FIFO与DDR3 控制IP的交互时钟都是 100M 。
3、FPGA外部与读写FIFO之间的时钟频率是多少?
与读FIFO是50M。
传感器sensor的工作时钟是有范围的。图像采集模块可以给传感器25MHZ的mclk时钟,传感器给图像采集模块也是25MHZ的pclk时钟。图像采集模块有一个DC FIFO ,它的写入时钟(左侧)是pclk,它的右侧读出时钟比 25MHZ高便可。所以选择了50MHZ。
与写FIFO是75M,这个75M是固定的时钟频率。
因为VGA显示驱动想要工作在720p(即1280×720),且@60HZ。而60HZ换算后,便是75MHZ。
图像采集给传感器的时钟mclk是25MHZ(这个是传感器的工作时钟),传感器给图像采集的DC FIFO时钟pclk是25MHZ(这个时钟根据系统帧率的要求可能会改变)。
图像缓存模块的写入DC FIFO接收到的时钟频率是50MHZ(这个值只要比pclk大便可),它和DDR3 控制IP的之间的时钟是200MHZ。
图像缓存模块的读出DC FIFO时钟频率是75MHZ(这个值是由VGA显示驱动的分辨率帧率决定的)。
显示驱动模块和外设VGA之间有个DAC芯片,它们之间的时钟频率是75MHZ,且相位偏差是180°
二、设计中各个模块的时钟频率定义
FPGA外部的晶振是50MHZ,它内部的PLL模块要产生这些时钟:
①、25MHZ的时钟提供给传感器sensor
②、50MHZ的时钟提供给FPGA内部的图像缓存模块
③、75MHZ的时钟提供给FPGA内部的显示驱动模块
④、75MHZ@180°的时钟提供给FPGA外部的DAC芯片(型号ADV7123)
⑤、200MHZ提供给DDR3控制IP
三、PLL的输入输出时钟信号拓扑图
1、PLL定义
PLL(Phase Locked Loop):为锁相回路或锁相环,用来统一整合时脉讯号,使内存能正确的存取资料。PLL用于振荡器中的反馈技术。许多电子设备要正常工作,通常需要外部的输入信号与内部的振荡信号同步,利用锁相环路就可以实现这个目的。
而我们在这里所说的PLL,没有上面一段定义那么晦涩难懂,大家记住PLL一个最主要的功能,即能够对输入的基准时钟信号进行一定范围内的分频或者倍频,从而产生多个输出时钟信号供芯片内部的各个功能模块使用。
2、多时钟设计
在FPGA的实际工程设计中,很难以一个特定的时钟频率打天下。由于FPGA具备丰富的接口协议,能以应对各种不同外设所需要的或高速、或低速、或差分、或单端、电平或高或低等不同接口。那么,要在这些外设之间游刃有余,平稳过度,就需要产生各种不同的时钟频率和提供跨时钟域的数据通信能力。这些,对于FPGA来说都是再基本不过的功能了。
以图像采集和显示设计为例,FPGA外接的图像传感器需要25MHz的时钟,而返回的有效数据也是以同样的同频不同相的时钟进行同步;在FPGA内部为了更好的达到时序收敛和性能水平,需要一个更稳定和能以满足处理需要的的时钟频率(如本设计的50MHz);接着是图像的缓存,其数据的同步时钟是由DDR3控制器IP给出的100MHz的时钟,而在此之前,需要有一个200MHz的时钟作为DDR3控制器IP的输入;最后的显示驱动,720p的分辨率,要达到60Hz的显示刷新率,就需要75MHz的时钟。这么一看,就这么个不大的设计,涉及的时钟频率还真不少。
四、Vivado中PLL IP的配置和添加
资料的文件结构。simulation_example是从第四课下载的,里面的自动化流程文件。sim_201是本次课的工程文件。我自己再创建一个 self_sim_201 文件,把simulation_example里的文件都加进去。然后sim_201的vivado文件加进去。然后接下来的所有操作都在self_sim_201进行。
1、用vivado打开工程。然而。。。教程打开的文件是已经配置好的PLL模块,悲。。。
2、为了学习怎么操作。我再建一个self_sim_201_001文件夹。但是,vivado_prj 里面是空的。接着创建一个工程存在这里。另外三个文件是自动化样本文件。
3、按照这个创建 工程名叫at7,器件叫xc7a35tftg256-1,存放在vivadio_prj 上面。
4、在vivado新建工程
5、开始按照视频的操作进行IP核的例化。
ok后,创建的IP核默认保存在 vivado_prj/at7.srcs/sources_1/ip 然后点击 generate 。
6、复制例化代码。
7、在testbench里新建一个文件夹 tb_pll 并且把这四个文件移到里面。这个目的是, run_simulation.bat这个批处理文件,每次会执行一次仿真自动化,而大型项目需要划分小模块独立仿真。因此新建一个专门单独存放 PLL仿真的文件夹 tb_pll 会更加方便管理。
所以独立的模块需要有独立的测试脚本,每个独立模块测试完后,再进行总模块的测试。
8、复制过来的 testbench_top 文件只是一个初步模板,具体的工程需要具体修改,才能应用。比如这个 testbench_top 是从第四课复制过来的,它上面还有第四课留下的端口信息。需要根据当前这个课的需求把它删了,加上本节课的端口。底下是本节课的 testbench_top 的全部代码。
9、compile.do 文件的内容设置
对于2022版的vivado软件,好像IP存放的位置不是 .src 了,而是在 .gen 。
compile.do 文件的脚本并不是都会运行,带有“#“的是注释,是不会运行的。红色圈起来的部分才会运行。可以看到,通过compile.do进行运行的文件有:glbl.v、clk_wiz_0_sim_netlist.v、testbench_top.v、wave.do 这四个文件。
glbl.v :
clk_wiz_0_sim_netlist.v:这个是源代码的网表文件
testbench_top.v:这个是仿真代码文件
wave.do:这个是添加波形的文件
对于灰色那句代码,意思是,当前是在 compile.do这个文件写代码。代码的起点便是compile.do文件,回退两级,则此时退到了testbench。而vivado_prj与testbench同级,接着直接按照路径进入,找到clk_wiz_0_sim_netlist.v 文件。
10、可以在 run_simulation.bat 里插入这句”tb_pll"会显示这次是对pll仿真。而 cd testbench/tb_pll 意思是切换目录到 tb_pll 文件夹,然后do compile.do ,即运行 compile.do 文件。
11、双击运行 run_simulation.bat 文件,然后输入”1“,回车,便可以自动化。然后在modelsim里面,点击”Run All“按钮,便可以显示波形。通过分析波形,可以发现:对于PLL时钟管理单元,复位信号拉高后不是立刻有输出波形的,而是等待一段时间才有输出波形。只有在 Locked 信号拉高后的输出时钟才是稳定时钟。因为PLL是锁相环,需要反馈消息,反馈稳定后,才会输出稳定的时钟。
点开testbench.top.v文件,这个文件写了单独对 PLL时钟单元仿真的文件。因为整个系统的外部的复位信号叫 rst_n,是低电平复位,而例化的 PLL单元的复位信号叫 reset ,我们想要FPGA整个系统都是拉高才复位。所以 系统外部的复位信号 rst_n 和 系统内部的复位信号 reset 是取反的关系。
locked 信号在 PLL输出稳定后会拉高。它会被用在FPGA整个系统的复位信号。
整个流程就是,系统外部的 rst_n 信号经过取反后,接入PLL时钟管理单元的reset 时钟端,等 PLL时钟管理单元输出时钟稳定后,Locked端拉高。这个Locked 信号拉高接入的是 FPGA的复位端。于是FPGA在有稳定时钟的同时,也进行了复位。
clk_25m_out 和 clk_75m_out 都是FPGA的外部时钟,分别是图像传感器sensor的工作时钟 和 显示驱动与外设VGA之间的ADC芯片的工作时钟。