【ZYNQ 详细案例五】采用AXI4总线封装自定义VGA显示IP核 彩条实验 基于ZEDBOARD
第一部分:PL部分
首先我们先创建工程

然后创建block design

添加PS处理器

自动配置 ZEDBOARD的预设。
好了以后我们创建一个新 IP 核

因为我们要创建一个AXI4总线标准的IP核,所以这里我们选择AXI4总线的外设

NEXT

NEXT

这一步要选择接口类型、接口模式、以及数据位宽还有寄存器个数。
这里因为我们是一个作为VGA显示的驱动,所以数据是由上层输入给这个IP核,然后由这个IP在输出VGA口,所以我们是从设备,这里接口模式就选择从设备(Slave),数据位宽保持默认就好,因为会比较方便和其他IP连接。但实际上我们只用到里面一些数据。
寄存器个数这里使用默认的4个就足够了。
NEXT

FINISH
进入IP工程编辑窗口

来到这个界面我们即可开始实现我们的IP核。
首先将我们上一节写的代码拿出来。添加到工程中

这里Bram没有实现可以先暂时不用处理,我们最后用【IP Catalog】生成一个bram就行。这是上次案例的东西。
现在我们假想AXI4外部顶层是一个统一的包装。但是核心是我们的VGA驱动,但是用这个核心的包装我们可以和其他模块进行交流。因此,我们将我们需要输入输出的端口 在这个“包装”里面声名。也就是在AXI4 IP 核自动生成的顶层.v文件下加入我们的接口。
也就是下面的接口。

我们在如图所示的区域声名,vivado已经帮我们留出了位置

接下来,在【zed_vga_v1_0_S00_AXI_inst】模块例化时也要加上。
因为【Zed_vga_v1_0】模块相当于是一个外面的包装,【zed_vga_v1_0_S00_AXI_inst】是内包装,我们核心的【vga_driver】才是核心。他们的区别:
【Zed_vga_v1_0】是单纯为了实现包装而存在,而
【zed_vga_v1_0_S00_AXI_inst】是实际实现了AXI总线传输协议时序的模块。用户一般实例化自己的模块也是在这个.v文件里面例化。
现在我们先把【zed_vga_v1_0_S00_AXI_inst】完整例化,
从某中角度上说,我们现在是一个自顶向下操作的。

然后在【zed_vga_v1_0_S00_AXI_inst】模块中声明端口

【zed_vga_v1_0_S00_AXI_inst】代码可能比较多,但是绝大部分你都不用关心,声名了端口后,滑动到最下方有一个 Add user logic here 的注释,在这里,我们完成我们的关于AXI4总线的逻辑和核心模块的例化,以及他们两个的交互关系。


这里,我们对每一个信号逐一分析。
【sys_clk】:是系统输入的时钟,是写入缓存的时钟,所以是100MHZ的系统时钟,在这里我们可以直接用AXI的时钟 【S_AXI_ACLK】
【rst_i】:复位信号高电平有效 ,不复位的话,直接可以拉低 为【1’b0】
【we_addr】( 是否写入地址 )
【we_data】( 是否写入数据 )
这里对于we信号我们可以做一个逻辑判断,将【slv_reg_wren】与【axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB]】的值相遇,当都要写入的话,先判断【axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB]】的值是0还是1,如果是0就是【we_data】有效,是1就是【we_addr】有效。这个功能将会与我们在驱动内部实现的一个小部分对应。
【din】( 将要写入的数据) 【S_AXI_WDATA】
最后的实现:

现在【ctrl+s】保存看看我们的整个IP核结构

一层套一层。底层很复杂,越到上层接口越少,逻辑实现也越简单越简洁。就像代码语言一样,从下到上封装得越来越好,高级语言越来越简单方便。
现在,我们注意!在vga_driver中外部数据输入部分的缓存时钟是我们的系统时钟100MHZ,这是个爱出bug的点。若采用25MHZ最后生成图像会花屏,很恐怖。

最后一步工作了,我们该例化我们的bram IP核了。这个上节我们应该讨论过了。



这里初始化文件可以选也可以不用

对了,这里B,读出端口的 第一季缓存寄存器我们可以不用设置

然后生成一下BRAM IP

最后好了以后,回到这个界面

点一下更新

最后重新打包一下

现在完成IP核的创建了,我们回到bd界面,可以添加我们的IP核了。


现在添加一个25MHZ的时钟

连接好以后就点击自动连线就好,最后的布局:

然后生成bd


最低0.47元/天 解锁文章
1840





