FPGA学习笔记【使用vivado内置IP核】
时钟IP核的使用
Vivado内置了使用FPGA中时钟资源实现的时钟IP核,可以实现分频、倍频、调节相位、控制占空比等功能
可以使用时钟IP核对内/对外输出不同频率的时钟信号
FPGA时钟资源
Xilinx的7系列FPGA都配置了专用的全局时钟和区域时钟资源
CMT(Clock Management Tiles时钟管理片)提供时钟合成(Clock frequency synthesis)、倾斜校正(deskew)、抖动过滤(jitter filtering)的功能。1个CMT中包括1个MMCM混合时钟管理电路和1个PLL锁相环电路
不同的FPGA包含的CMT数量不一样
FPGA中的CMT被分为了多个时钟区域(Clock Region),时钟区域可以单独工作,也可以通过全局时钟线主干道(Clock Backbone)和水平时钟线(HROW)统一调配资源共同工作
FPGA时钟IP核的使用
在【IP Catalog】搜索clock出现clock wizard,双击即可进行设置
配置好自定义选项后生成IP核代码,打开IP视图可以找到示例的例化代码,将其复制到顶层模块,在顶层模块中加入IP核相关代码的例化就可以使用IP核了。
RAM IP核的使用
Xilinx家的FPGA自带称为块RAM(Block RAM)的片上资源,根据具体器件型号不同具有各种各样的配置数量
这些块RAM实际上使用FPGA内部的配置RAM实现,它们本来用于存储FPGA的控制块配置并供LUT存储数据使用,但是通过特殊的内部指令可以将它们汇总成为具有一般RAM功能的片上资源。
而LUT本身是基于RAM的,因此也可以“积少成多”用于RAM,它被称为Distributed Memory
只要使用Vivado内置的IP核就可以将块RAM加入自己的设计中
RAM IP核的使用
点击【IP Catalog】-搜索【RAM】-【Memories & storage Elements】
可以看到两个和RAM有关的创建入口
- Distributed Memory Generator:使用LUT实现RAM IP
- Block Memory Generator:使用块RAM实现RAM IP
用户可以根据自己的需求选择不同的入口,消耗不同的片上资源创建RAM IP
- 选择接口类型为Native(常规接口)
- RAM类型为Simple Dual Port RAM,简单双口RAM(也可以根据需要配置为其他类型)
- 选择输入端口位宽,设置输入深度
- 选择是否使用使能控制信号
- 配置输出端口位宽、是否使用输出寄存器(Latch),注意输出端口深度是由输入端口深度和位宽决定的
之后正常调用生成的模块即可
FIFO IP核的使用
FIFO就是队列的硬件实现,分为同步和异步两种
同步FIFO读写端的时钟是同步的,因此可以实现一边读一边写
异步FIFO读写端使用不同的时钟,因此不能一边读一边写,但是异步FIFO常常用作跨时钟域传输信号——实际上也只有用异步FIFO才能在两个不同频率时钟域之间实现信号传输
FIFO是使用触发器级联实现的,这就导致同步FIFO在高速情形下具有不稳定性,因为内部的触发器具有一定的响应时间(建立时间、保持时间),如果外部时钟过快,内部数据来不及变化就要输出,就会导致亚稳态发送
FIFO和RAM
FIFO和RAM都可以存储数据,并且都具有控制读写的信号;但是FIFO没有内部地址,只能以先入先出的形式读写数据,它的读写可以同时进行;而且如果FIFO满,那么就不能再写入数据,需要先将队头数据读出才能继续写入,否则电路会在此卡死,同理如果FIFO空,它也不能再读出新数据;
异步FIFO的Verilog实现
下面是一个典型的异步FIFO实现
作者使用了 加两级寄存器同步 + 格雷码的方法尽可能消除亚稳态,做到严谨的异步高速数据传递
转载自https://blog.csdn.net/u012357001/article/details/89945457
module fifo_async#(parameter data_width = 16,parameter data_depth = 256,parameter addr_width = 8
)
(input rst,input wr_clk,input wr_en,input [data_width-1:0] din, input rd_clk,input rd_en,output reg valid,output reg [data_width-1:0] dout,output empty,output full);reg [addr_width:0] wr_addr_ptr;//地址指针,比地址多一位,MSB用于检测在同一圈
reg [addr_width:0] rd_addr_ptr;
wire [addr_width-1:0] wr_addr;//RAM 地址
wire [addr_width-1:0] rd_addr;wire [addr_width:0] wr_addr_gray;//地址指针对应的格雷码
reg [addr_width:0] wr_addr_gray_d1;
reg [addr_width:0] wr_addr_gray_d2;
wire [addr_width:0] rd_addr_gray;
reg [addr_width:0] rd_addr_gray_d1;
reg [addr_width:0] rd_addr_gray_d2;reg [data_width-1:0] fifo_ram [data_depth-1:0];//=========================================================write fifo
genvar i;
generate
for(i = 0; i < data_depth; i = i + 1 )
begin:fifo_init
always@(posedge wr_clk or posedge rst)beginif(rst)fifo_ram[i] <= 'h0;//fifo复位后输出总线上是0,并非ram中真的复位。可无else if(wr_en && (~full))fifo_ram[wr_addr] <= din;elsefifo_ram[wr_addr] <= fifo_ram[wr_addr];end
end
endgenerate
//========================================================read_fifo
always@(posedge rd_clk or posedge rst)beginif(rst)begindout <= 'h0;valid <= 1'b0;endelse if(rd_en && (~empty))begindout <= fifo_ram[rd_addr];valid <= 1'b1;endelsebegindout <= 'h0;//fifo复位后输出总线上是0,并非ram中真的复位,只是让总线为0;valid <= 1'b0;endend
assign wr_addr = wr_addr_ptr[addr_width-1-:addr_width];
assign rd_addr = rd_addr_ptr[addr_width-1-:addr_width];
//=============================================================格雷码同步化
always@(posedge wr_clk )beginrd_addr_gray_d1 <= rd_addr_gray;rd_addr_gray_d2 <= rd_addr_gray_d1;end
always@(posedge wr_clk or posedge rst)beginif(rst)wr_addr_ptr <= 'h0;else if(wr_en && (~full))wr_addr_ptr <= wr_addr_ptr + 1;else wr_addr_ptr <= wr_addr_ptr;end
//=========================================================rd_clk
always@(posedge rd_clk )beginwr_addr_gray_d1 <= wr_addr_gray;wr_addr_gray_d2 <= wr_addr_gray_d1;end
always@(posedge rd_clk or posedge rst)beginif(rst)rd_addr_ptr <= 'h0;else if(rd_en && (~empty))rd_addr_ptr <= rd_addr_ptr + 1;else rd_addr_ptr <= rd_addr_ptr;end//========================================================== translation gary code
assign wr_addr_gray = (wr_addr_ptr >> 1) ^ wr_addr_ptr;
assign rd_addr_gray = (rd_addr_ptr >> 1) ^ rd_addr_ptr;assign full = (wr_addr_gray == {~(rd_addr_gray_d2[addr_width-:2]),rd_addr_gray_d2[addr_width-2:0]}) ;//高两位不同
assign empty = ( rd_addr_gray == wr_addr_gray_d2 );endmodule
推荐阅读《Verilog数字系统设计教程》(夏宇闻老师的经典著作),其中展示了一个非常经典的基于SRAM的FIFO设计
笔者能力有限,还处于学习阶段,暂时做不出这样优秀的硬件设计,因此不再多写
FIFO IP核的使用
Vivado中提供了FIFO的IP核供开发者使用,用户只要选择【IP Catalog】-搜索【fifo】-【Memories & storage Elements】,选择下方的【FIFO Generate】就可以进行可视化配置
- 修改FIFO名称
- 选择Native类型FIFO接口
- 选择【Independent Clock Block RAM】(独立时钟块RAM)实现FIFO(FIFO Implementation选项)
- Read Mode选择【First Word Fall Through】
- 设置输入数据尾款、读数据位宽、FIFO深度(注意FIFO深度必须是2的n次幂)
- 选择是否使用Reset控制复位、状态标志位、数据计数位等设置
最后直接点击OK即可通过FPGA内部的块RAM资源实现FIFO,可以达到比直接使用Verilog调用块RAM实现FIFO更高的效率
如果还想要更高效的FIFO实现,可以考虑专门使用Verilog配合Xilinx的Tcl语句优化
FIFO IP核可以配置成同步或异步,并快速加入SoC设计
FPGA学习笔记【使用vivado内置IP核】相关推荐
- FPGA学习笔记(十二)IP核之FIFO的学习总结
系列文章目录 一.FPGA学习笔记(一)入门背景.软件及时钟约束 二.FPGA学习笔记(二)Verilog语法初步学习(语法篇1) 三.FPGA学习笔记(三) 流水灯入门FPGA设计流程 四.FPGA ...
- FPGA 学习笔记:Vivado 2018.2 MicroBlaze Uartlite 配置
前言 Vivado 版本: Vivado 2018.2 + Vivado HLS 2018.2, Vivado HLS 2018.2 用于 SDK 开发,C语言开发 创建基于MicroBlaze的 [ ...
- XSL学习笔记6 XSLT内置模板规则
XSL学习笔记6 XSLT内置模板规则 定义正确的模板规则来匹配XML树中的节点是XSLT应用的关键.为了让源文档树的节点在没有明确匹配规则的情况下,能够被递归处理,XSLT定义了几个内置的模板规则, ...
- FPGA 学习笔记:Vivado 2020.2 MicroBlaze MIG 测试 DDR3 篇尾
FPGA 学习笔记:Vivado 2020.2 MicroBlaze MIG 测试 DDR3 篇一 FPGA 学习笔记:Vivado 2020.2 MicroBlaze MIG 测试 DDR3 篇二 ...
- FPGA 学习笔记:Vivado 2019.1 添加 IP MicroBlaze
前言 当前 FPGA 无所不能,能添加 MCU的核,也就是可以嵌入一个单片机的内核,当个单片机使用,这里添加 MicroBlaze,这个是RISC的核,还没有开始熟悉,估计与 ARM 或者 RISC- ...
- MySQL学习笔记_7_MySQL常用内置函数
MySQL常用内置函数 说明: 1)可以用在SELECT/UPDATE/DELETE中,及where,orderby,having中 2)在函数里将字段名作为参数,变量的值就是字段所对应的每一行的值. ...
- Python学习笔记3.2-python内置函数大全
学习python不可避免的首先要了解python的内置函数,熟悉了这些以后可以给编程带来很大的方便. 1.数学运算类 函数名 函数功能 备注 abs(x) 求绝对值 1.参数可以是整型,也可以是复数2 ...
- [云炬python学习笔记]Numpy中内置函数min(),max(),sum()与Python中内置函数min(),max(),sum()性能对比分析
众所周知,Python有许多内置函数(例如min(),max(),sum()),Numpy也有自己的内置函数(np.min(),np.max(),np.sum()).由于Numpy的函数是在编译码中执 ...
- Qt学习笔记之--Qt内置图标一览表
Qt内置了一批图标,一共有70个(Qt 5.9.5),不同的平台图标有差异.由于官方文档中只有描述没有图示,所以写个Demo把这些图标全部显示出来.下面展示了windows.Linux.android ...
最新文章
- Java字节流文件流的练习
- java p7 数字签名,p7结构的数字信封 | 学步园
- Win2008上.NET4.0部署出错HTTP 错误 500.21 - Internal Server Error的解决方法
- java 存储cookie_java设置cookie,存储和读取 | 学步园
- IOS遍历未知对象属性、函数
- python 西门子交换机_python读取交换机
- 【Android】ListView ViewHolder ArrayIndexOutOfBoundsException: length=2; index=2
- InnoDB存储引擎MVCC实现原理
- ghost 通过docker安装
- 数字频率系数测试软件,基于单片机简易数字频率计设计方案汇总
- /* global $ xxxx */ eslint注释
- hystrix 配置了较大的核心线程数导致wating线程过多的问题
- 恶意访问、黑产猖獗,如何做好业务安全“守门人”?丨创新场景50
- 短视频剪辑软件分享,短视频剪辑软件这几个很不错。​
- 【BW系列】SAP 讲讲BW/4 HANA和BW on HANA的区别
- 一个洗车店引发的思考:给谁发优惠券好呢?
- Esper学习之十三:EPL语法(九)
- 陀螺研究院×BSN丨解析区块链视角下的消费者权益保护访谈全文发布
- ise 时钟约束_ISE 约束文件完整讲解
- java计算机毕业设计 高考志愿填报系统 高考志愿推荐系统 高考志愿填报辅助系统 ssm高考填报系统 志愿填报机器人 高考学校实景3D地图(java+ssm+百度地图+实景3D地图)
热门文章
- 抖音==1/2个微信?抖音会是下一个巨头吗?
- 淘宝商品采集上架拼多多店铺(无货源数据采集接口,拼多多商品详情数据,淘宝商品详情数据,京东商品详情数据)接口代码对接教程
- Unirech-阿里云国际版云服务器ecs实例使用中的常见问题汇总
- 开发人员的人品问题 收藏
- STM32F105RCT6使用CubeMX初始化工程——2:初始化CAN通信
- python英汉互译 谷歌翻译 免费实现调用
- 每天学点统计学——频率和累计频数
- Hazel轻松管理文件
- 【PCDN】2020架构: 提高穿透和分享、BGP协议
- java-net-php-python-jspm人力外包服务公司招聘管理系统计算机毕业设计程序