[FPGA3]IP核_PLL/RAM/ROM

调用IP核,PLL,RAM,ROM

PLL模块

  1. 首先新建一个工程,具体步骤如:[FPGA2]创建PL工程完整流程
  2. 点击"Project Manager -> IP Catalog",打开IP管理器
  3. 在IP Catalog界面中选择"FPGA Features and Design -> Clocking ->Clocking Wizard",双击IP打开配置页面
  4. 可在"Component Name"处设置模块名,该名即为之后需要原件例化的原件名
  5. 在时钟选项"Clocking Options"界面中,可选择MMCM或PLL选项,并设定输入时钟频率信息。
  6. MMCM 用于在与给定输入时钟有设定的相位和频率关系的情况下,生成不同的时钟信号。锁相环(PLL)主要用于频率综合,使用一个 PLL 可以从一个输入时钟信号生成多个时钟信号。
  7. 在输出时钟选项"Output Clocks"界面可以设定目标时钟的数量,频率及相位信息,点击OK完成设置
  8. 重新综合IP,在完成后该IP会自动添加至我们的项目中。
  9. 打开"Sources -> IP Sources"可以看到我们刚刚生成的PLL模块,点击"Instantiation Template"文件夹下的".veo"文件,这个文件中提供了该IP的实例化模板,我们可复制该模板添加至顶层设计文件中,元件例化该IP核。
  • 需要注意,由于时钟的输出是通过 PLL 对输入时钟信号的倍频和分频系数来得到的,所以并不是所有的时钟频率都可以用 PLL 能够精确产生的,当需要高精度时钟时,需要小心该问题。

RAM模块

配置RAM IP核

  1. 在"IP Catalog"中搜索"ram",找到"RAMs & Roms & BRAM -> Block Memory Generator"
  2. 打开IP设置,将Component Name 改为模块名,将"Memory Type"改为"Single Dual Prot RAM",也就是伪双口 RAM。
  • Memory Type 可分为5种,分别是单口 RAM(Single Port RAM)、伪双口 RAM(Simple Dual Port RAM)、真双口 RAM(True Dual Port RAM)、单口 ROM(Single Port ROM)、双口 ROM(Dual Port ROM)
  • 单口 RAM 只有一个时钟(clka)(时钟上升沿到来时对数据进行写入或者读出)、一组输入输出数据线(dina & douta)、一组地址线(addra)、一个使能端(ena)("ena == 1"时可进行读或写的操作,"ena == 0"时无法进行读或写的操作)、一个写使能端(wea)(在"ena == 1"的情况下:"wea == 1"时只写不读,"wea == 0"时只读不写)。单口读、写无法同时进行,只能或读或写
  • 伪双口 RAM 有两个时钟(clka & clkb)、一组输入输出数据线(dina & doutb)、两组地址线(addra & addrb),两个使能端(ena & enb)、一个写使能端(wea)。一个端口只读(Port a),另一个端口只写(Port b)。整体上,读、写可以同时进行,但地址线只有一组
  • 真双口 RAM 有两个时钟(clka & clkb)、两组输入输出数据线(dina & douta & dinb & doutb)、两组地址线(addra & addrb),两个使能端(ena & enb)、两个写使能端(wea & web)。两个端口都可以进行读写操作(Port a 和 Port b 可以一起读或者一起写或者一个读一个写)。真正意义上实现读、写的同时进行
  • 需要注意,不论是在使用双口RAM还是双口ROM,一定要避免在同一时刻对同一地址进行读或写的操作,防止发生冲突(这也是不允许的)。
  1. 切换到Port A Options 栏目下,修改RAM位宽"Port A Width",也就是数据宽度。修改RAM 深度"Port A Depth",深度指的是RAM里可以存放多少个数据。使能管脚"Enable Port Type"一般改为"Always Enable",即始终处于使能状态,也可根据需要设置读使能信号"Use ENB Pin"。
  2. RAM的工作模式分为三类:写优先,读优先以及 no change。写优先,在读写时钟异步的情况下,推荐使用。该模式会保证写操作优先发生,但读出的值为写入的新值。读优先,该模式以消耗更多 BRAM 资源的前提下,保证每次读操作读取到的都是先前的数据。输入数据会首先被缓存,与此同时在输出总线上输出先前值,一个周期的延迟之后,再输出输入数据。写入期间数据不变(no change),该模式很“佛性”,在写入期间数据不变,对读写冲突不闻不问,但优点在于节约 BRAM 功耗。
  3. 切换到 Port B Options 栏目下,修改RAM位宽"Port B Width",IP核向导会自动根据输入位宽、深度,计算出输出存储深度。设置使能管脚"Enable Port Type"。"Primitives Output Register"选项的功能是在输出数据处加上寄存器,可以有效改善时序,当开启该功能时会导致读出数据落后地址两个周期,若关闭该功能,则数据只会落后地址一个周期。
  4. 在"Other Option"选项栏中可以设置初始化RAM数据
  5. 最后一个Summary页面,提供完整的配置信息以供检查我们的设计,并告知我们该 IP 所使用的硬件资源。
  6. 完成后,点击OK重新综合IP核

RAM读写时序

  • RAM写入时序:端口A用于数据的写入,数据写入是按时钟的上升沿操作的,端口 A 数据写入的时候需要置高"wea"信号,同时提供地址和要写入的数据。时序图如下:
  • RAM读取时序:端口B用于数据的读取,数据写入是按时钟的上升沿操作的,只需要提供地址,在未开启"Primitives Output Register"选项的情况下,在下一个周期即可采集到目标数据。时序图如下:

ROM模块

  • FPGA本身是SRAM架构的,故无法实现真实的ROM,实际上FPGA是通过每次上电时将初始值写入RAM以实现ROM的功能。

ROM初始化文件

  • ROM预存储数据为以".coe"结尾的配置文件,文件具体格式如下:
MEMORY_INITIALIZATION_RADIX = 16; //数据格式,16表示数据格式为16进制
MEMORY_INITIALIZATION_VECTOR=  //后续为填入的数据,
    11, //每行分隔符为逗号
    22,
    33,
    44,
    55;//最后一行分隔符为分号

配置ROM IP核

  1. 在"IP Catalog"中搜索"ram",找到"RAMs & Roms & BRAM -> Block Memory Generator"
  2. 打开IP设置,将Component Name 改为模块名,将"Memory Type"改为"Single Prot ROM",也就是单口ROM。
  • 单口 ROM 只有一个时钟(clka)、一组输出数据线(douta)、一组地址线(addra)、一个使能端(ena)。只能进行读操作,且一个时钟只能读出某个地址上的一组数据
  • 双口 ROM 有两个时钟(clka & clkb)、两组输出数据线(douta & doutb)、两组地址线(addra & addrb)、两个使能端(ena & enb)。也是只能进行读操作,且每个端口中,一个时钟只能读出某个地址上的一组数据。双口ROM和单口 ROM没什么本质区别,可以当成是两个单口ROM拼接而成,只是存储的数据是共享的
  • 需要注意,不论是在使用双口RAM还是双口ROM,一定要避免在同一时刻对同一地址进行读或写的操作,防止发生冲突(这也是不允许的)。
  1. 切换到Port A Options 栏目下,修改ROM位宽"Port A Width",也就是数据宽度。修改ROM 深度"Port A Depth",深度指的是RAM里可以存放多少个数据。配置使能管脚"Enable Port Type"选用何种模式。是否需要开启"Primitives Output Register"选项
  2. 切换到 Other Options 栏目下,勾选 Load Init File,点击 Browse,选中之前制作好的".coe" 文件。
  3. 最后一个Summary页面,提供完整的配置信息以供检查我们的设计,并告知我们该 IP 所使用的硬件资源。
  4. 最后点击OK,重新综合生成IP核。

ROM读取时序

  • ROM的读取时序非常的简单,只需要在每个时钟改变ROM的地址,ROM就会在延迟1个/2个时钟周期(具体看是否开启"Primitives Output Register"选项)后输出当前地址对应的内部存储数据。

参考:
PG085