文章来源:OpenFPGA
AMD-Xilinx 的 Vivado 开发工具具有很多方便FPGA开发功能,我最喜欢的功能之一是block design的设计流程。Vivado 中的block design是使用RTL IP形式的图形表示进行设计,在block design中使用 RTL 模块的方便之处在于,它将自动检测某些类型的信号,例如时钟、复位和总线接口,然后,检测这些信号进行IP间的自动化连接。Vivado 中包含大量预构建 IP 模块(官方IP)。
为了方便用户进行相关设计,Vivado 提供了一个内置的 IP 封装编辑器工具,它可以为 AXI IP 生成框架,只需将自己的 RTL 代码插入其中。同时也提供了相关的驱动文件,可以在Vitis中方便调试。
为了演示究竟上面流程“好”在哪里,接下来我们创建一个AXI FIR IP 模块,然后将IP添加到我们设计中最后验证功能。
创建 Vivado 项目
首先,启动 Vivado 并针对自己的FPGA创建一个新项目。
添加 MicroBlaze,对于这个项目来说,使用 BRAM 就足够了。
选择 Add IP 选项并搜索 MicroBlaze,将其添加到模块设计中并运行 Block Automation,该模块会在窗口顶部的绿色横幅中弹出。接下来添加中断控制器。
验证并保存块设计,接下来我们将开始我们的IP设计。
创建新的 AXI4 外设
要使用自己的 RTL 创建新的 AXI 外设并将其封装为 IP ,请选择工具>创建和打包新 IP...
在弹出的窗口中,按照提示逐步浏览屏幕,选择Create AXI4 Peripheral选项,指定 IP 块的所需名称、位置目录以及 IP 将具有的 AXI 接口数量以及 AXI类型。
Vivado 中使用了三种主要类型的 AXI:
AXI4 (full) AXI4-Lite AXI4-Stream
每种类型都适合不同的用例,在这个项目中,我们正在创建自己的 AXI FIR 滤波器 IP 。由于 FIR 滤波器输入并输出具有已知数据包边界和流量控制要求的恒定数据流,因此 AXI4-Stream 是最适合的类型。它将需要一个从接口来输入数据样本,并需要一个主接口来输出处理后的样本。
作为参考,FIR 是一个运行速度为 100 MS/s 的 LPF,具有 15 个抽头,接收带符号的 16 位数据并输出带符号的 32 位数据。它有一个从 1MHz 到 10MHz 的通带和一个从 20MHz 开始的阻带。
接下来,选择编辑 IP并单击完成。IP 包编辑 Vivado 项目将重新打开一个gui。
将自定义 RTL 添加到 AXI4-Stream IP
从Flow Navigator中选择Add Sources添加我们要设计的 FIR Verilog 文件。
在使用 Add Files 选项指向 FIR Verilog 文件后,取消选中Scan and add RTL include files into project复选框。由于这不是一个普通的 Vivado 项目,并且 Verilog 代码被打包到一个 IP 块中,因此选中该选项后将引发错误。
添加后,源层次结构更新并且 FIR Verilog 文件独立于 AXI Verilog 源文件。
根据生成 IP 编辑器 Vivado 项目时所做的选择,会为此 AXI4-Stream 外设生成三个 RTL 源文件:
从接口功能 RTL。 主接口功能 RTL。 具有物理接口声明和主从接口实例化的顶层文件。
在设计之前,需要将几个默认未启用的可选 AXI4-Stream 接口信号添加到主 AXI 端口和从 AXI 端口。大多数 DSP IP 模块,例如 DDS 利用了 AXI4-Stream 额外的keep 和 tlast信号。
添加这些可选信号很简单,但最初并不清楚。导航到Package IP窗口中的Customization Parameters选项卡。
主接口和从接口都需要添加它们,因此右键单击每个接口并选择Edit Interface 。
在“Parameters”选项卡中启用HAS_TKEEP ,方法是单击每个选项,然后单击单个箭头将其从左列移动到右列。
然后切换到Port Mapping选项卡,将 tkeep 和 tlast 映射到 AXI IP 块的物理接口。在Interface's Logical Ports列和IP's Physical Ports列中分别匹配 tkeep 和 tlast 信号。然后在下面的Mapped Ports Summary列中验证它们的映射。
由于默认情况下不启用 tkeep,因此还必须手动将其端口声明添加到所有三个 AXI 接口 RTL 源文件的用户定义端口声明部分。它还需要添加到顶级 AXI 包装器中的 AXI 主接口和从接口实例中。
在注释Add user logic here标记的部分中实例化 FIR Verilog 模块。
现在,虽然 AXI 接口的基本功能分别在每个 RTL 源文件中自动生成,但如何从输入数据流中提取数据并传递到自己的自定义逻辑中由自己来定义。以及如何将自定义逻辑的数据输出馈送到主 AXI 接口进行输出。因此,会在三个自动生成的 RTL 源文件中注意到相同的 Add user 逻辑。
另一点需要注意的是,AXI4-Stream 接口的功能需要进行一些修改,以便将 tkeep 和 tlast 信号功能添加到主 AXI 接口和从 AXI 接口。
这个项目的最后一个独特的要求是,因为这个逻辑的核心是一个 FIR 滤波器,所以主从 AXI 接口和 FIR 都需要由相同的时钟作为 FIR 采样时钟。所以只是将从 AXI 接口时钟传递给 FIR 和主 AXI 接口。
封装 AXI IP 块
返回到 Package IP 窗口,让我们浏览每个选项卡并验证,然后最终将其打包。
第一个选项卡中是输出 AXI 外设 IP 包的基本显示信息。
第二个标签很重要。默认情况下,AXI 外设 IP 仅支持启动 IP 包编辑器的主 Vivado 所针对的 FPGA 芯片系列。大多数时候,可能希望能够将 AXI 外设 IP 块与其他 Xilinx FPGA 芯片系列一起使用,就需要添加我们需要的目标FPGA芯片。
对于其余选项卡,默认需求即可。
在最后一个选项卡中,单击窗口底部的Package IP按钮。将出现一个提示,询问是否要关闭 IP 编辑器 Vivado 项目。
此时,FIR AXI IP 块被打包并放置在 Package IP 窗口的第一个选项卡指定的目录中的存储库中。
将自定义 AXI4-Stream FIR 添加到项目
现在自定义 FIR AXI IP 模块已经完成并封装,我们可以返回原始 Vivado 项目,将其添加到模块设计中。
我们的验证项目如下:
其中DDS IP设置如下:
创建仿真平台
首先创建仿真文件,并在sim文件夹下的 Sources 选项卡中,右键单击它并选择Set as Top 。
在这种情况下,只需在块设计中实例化块设计,并为其提供差分系统时钟和主 FPGA 复位。一旦接收到时钟和复位信号,相位增量状态机就会自行运行。
`timescale 1ns / 1ps
module sp701_bd_tb;
reg clk_p, clk_n, reset;
always begin
clk_p = 1; clk_n = 0; #5;
clk_p = 0; clk_n = 1; #5;
end
always begin
reset = 1; #40;
reset = 0; #1000000000;
end
sp701_bd sp701_bd_i (
.reset(reset),
.sys_diff_clock_clk_n(clk_p),
.sys_diff_clock_clk_p(clk_n)
);
endmodule
这里注意一下主 AXI 接口输出信号和 tlast、tvalid 和 tdata 需要进行初始化。否则仿真将会报错。
单击Flow Navigator窗口中的Run Simulation并选择Run Behavioral Simulation 。
注意仿真结果显示格式。
参考
总结
上面的一些创建细节没有全部展现,因为本身对于IP的创建不是我们的核心,我们只想说明使用目前这种BD设计可以达达简化设计,尤其是目前Verilog的一些缺点。
最后说一下调试中的注意点,就是使用ILA查看AXI-Stream输出时候,会造成FIR的时序与采样混淆导致 FIR 不再工作,可能会查看不到任何波形,使用AXIS的专用调试IP即可,后续我们在说明这方面的知识。
示例工程