完整版登陆后一楼可见
在FPGA设计中,使用存储单元几乎不可避免。xilinx UltraScale+ 和 Versal 系列中有三类存储资源,分别是分布式存储资源(LUTRAM)、Block RAM和UltraRAM。Vivado提供了四种方式使用这三类资源:使用IP Core(Block Memory Generator / FIFO Generator / Distributed Memory Generator)、使用原语(Primitive)直接实例化,使用XPM、使用RTL代码由工具推断。这四种方式各有优缺点。比如:使用IP Core,对于不同类型的RAM要反复调用IP Core,填入相应的参数,同时IP Core内部对用户是不可见的。但IP Core使用起来还是比较简单的。只是,如果目标芯片为Versal, Vivado 2020.2版本不再提供上述IP,取而代之的是Embedded Memory Generator,而且此IP只支持IPI流程。如果使用原语,会发现所有端口中用户都可见,用户具有最大的可控性,但使用起来很繁琐。倘若对器件结构不甚清楚,例如不了解URAM如何级联,很可能造成连接错误。同时,原语还有很多属性,深入了解第一个属性也很费时。如果使用RTL代码,就要求有良好和代码风格,同时对一些综合属性有所了解,如RAM_STYLE,CASCADE_HEIGHT等,否则会影响综合质量。相比下来,使用XPM更为妥当。
XPM全称为Xilinx Parameterized Macro, 给用户提供了一种参数化的方式使用存储单元、跨时钟域设计等。在Vivado Language Template中可以找到XPM,如下图所示。所以,只用在用户代码中实例化就可以了。
为了便于说明,我们以一个单端口RAM为例,相应的代码如下图所示。代码第38行至第76行就是对XPM的实例化。为了增强设计的复用性,我们提取出XPM常用的几个属性将其以参数parameter的形式列在我们自己的代码中,也就是代码第16至第24行。这里AW决定了地址位宽,从而也就决定了RAM的深度;DW决定了RAM的宽度;CASCADE_HEIGHT决定了可允许的级联高度(BRAM、URAM都是按列排列的);ECC_MODE决定了是否使用ECC;MEMORY_INIT_FILE用来设计RAM初始值文件,如果无需设定初始值,这里就设置为”None”;MEMORY_PRIMITIVE决定了RAM的实现方式(分布式RAM、Block RAM或者URAM;READ_LATENCY_A决定了输入地址有效到输出数据之间的时钟周期个数;WRITE_MODE_A决定了RAM的工作模式(针对发生读写冲突时)。
可以看到这些参数都是我们设计中经常用到的参数。至此,我们已经将XPM封装变为可参数化更强复用性的用户代码。如果设计中需要用到多个单端口RAM,差别无外乎上述几个参数的不同,因此只需要在实例化时根据具体需求填写对应参数即可。
这里有两点需要说明。不同于IPCore, XPM的初始化需要用.mem文件而不是.core文件,且要将文件以设计文件的形式添加到Vivado工程中。.mem文件中存储的是每个地址上的数据,且目前只支持十六进制形式。每个数据占一行即可,行与行之间无需其它符合分割。另外,XPM也支持第三方仿真工具仿真,如下图所示,是用QuestaSim进行的行为级仿真。
综上所述,我们可以看到使用XPM具有两个主要优势:
增强代码的可复用性
保证结合质量
在FPGA设计中,使用存储单元几乎不可避免。xilinx UltraScale+ 和 Versal 系列中有三类存储资源,分别是分布式存储资源(LUTRAM)、Block RAM和UltraRAM。Vivado提供了四种方式使用这三类资源:使用IP Core(Block Memory Generator / FIFO Generator / Distributed Memory Generator)、使用原语(Primitive)直接实例化,使用XPM、使用RTL代码由工具推断。这四种方式各有优缺点。比如:使用IP Core,对于不同类型的RAM要反复调用IP Core,填入相应的参数,同时IP Core内部对用户是不可见的。但IP Core使用起来还是比较简单的。只是,如果目标芯片为Versal, Vivado 2020.2版本不再提供上述IP,取而代之的是Embedded Memory Generator,而且此IP只支持IPI流程。如果使用原语,会发现所有端口中用户都可见,用户具有最大的可控性,但使用起来很繁琐。倘若对器件结构不甚清楚,例如不了解URAM如何级联,很可能造成连接错误。同时,原语还有很多属性,深入了解第一个属性也很费时。如果使用RTL代码,就要求有良好和代码风格,同时对一些综合属性有所了解,如RAM_STYLE,CASCADE_HEIGHT等,否则会影响综合质量。相比下来,使用XPM更为妥当。
XPM全称为Xilinx Parameterized Macro, 给用户提供了一种参数化的方式使用存储单元、跨时钟域设计等。在Vivado Language Template中可以找到XPM,如下图所示。所以,只用在用户代码中实例化就可以了。
为了便于说明,我们以一个单端口RAM为例,相应的代码如下图所示。代码第38行至第76行就是对XPM的实例化。为了增强设计的复用性,我们提取出XPM常用的几个属性将其以参数parameter的形式列在我们自己的代码中,也就是代码第16至第24行。这里AW决定了地址位宽,从而也就决定了RAM的深度;DW决定了RAM的宽度;CASCADE_HEIGHT决定了可允许的级联高度(BRAM、URAM都是按列排列的);ECC_MODE决定了是否使用ECC;MEMORY_INIT_FILE用来设计RAM初始值文件,如果无需设定初始值,这里就设置为”None”;MEMORY_PRIMITIVE决定了RAM的实现方式(分布式RAM、Block RAM或者URAM;READ_LATENCY_A决定了输入地址有效到输出数据之间的时钟周期个数;WRITE_MODE_A决定了RAM的工作模式(针对发生读写冲突时)。
可以看到这些参数都是我们设计中经常用到的参数。至此,我们已经将XPM封装变为可参数化更强复用性的用户代码。如果设计中需要用到多个单端口RAM,差别无外乎上述几个参数的不同,因此只需要在实例化时根据具体需求填写对应参数即可。
这里有两点需要说明。不同于IPCore, XPM的初始化需要用.mem文件而不是.core文件,且要将文件以设计文件的形式添加到Vivado工程中。.mem文件中存储的是每个地址上的数据,且目前只支持十六进制形式。每个数据占一行即可,行与行之间无需其它符合分割。另外,XPM也支持第三方仿真工具仿真,如下图所示,是用QuestaSim进行的行为级仿真。
综上所述,我们可以看到使用XPM具有两个主要优势:
增强代码的可复用性
保证结合质量