IP核是什么
IP即是知识产权。在半导体产业将IP核定义为“用于ASIC或FPGA的预先设计好的电路功能模块”简而言之,IP就是电路功能模块。
在数字电路中,将常用的并且及比较复杂的功能模块设计成参数可修改的模块,让其他用户可以直接调用这些模块,就是IP核。
常用的有FIFO、RAM、SDRAM。
存在形式
- HDL语言形式–软核
硬件描述语言;可进行参数调整、复用性强;布局、布线灵活;设计周期短、设计投入少。 - 网表形式–固核
完成了综合的功能块,可预布线或分配特定的布线资源。 - 版图形式–硬核
硬核是完成提供设计的最终阶段产品–掩膜(Mask);缺乏灵活性、可移植性差;更易于实现IP核的保护。
IP核的缺陷
IP核往往不能跨平台使用,IP核不透明、看不见内部核心代码,定制IP需要额外收费。
常用IP核调用
PLL
简介
PLL是最常用的IP核,可以对输入到FPGA的时钟信号进行任意分频、倍频、相位调整、占空比调整,从而输出一个期望的时钟。
模拟锁相环的相位连续可调,但是温度过高会导致失锁。
如图所示,锁相环是一个反馈系统,输入到锁相环的时钟是一个参考时钟,FD/PD是一个鉴频鉴相器。FD是鉴频、PD是鉴相。其作用是比较参考时钟与对比时钟的差异,如果参考时钟的频率与对比时钟相等则会输出零,参考时钟大于对比时钟,输出变大成正比的值,反之输出变小成正比的值。
LF是环路滤波器,用于控制噪声的带宽,并且更具上述的输入,输出不同的电压,VCO的输入电压越高则输出的电压也越高。
DIV用来给信号分频,可以调节其值,用来倍频。
配置
搜索ip当中的如图的iP核进入ip核设置界面
如下图所示,左上角有三个选项:选项一为打开参考文件,选项二为存放地址,选项三为重置设置。
左下图为生成的期间图,右边为设置建模:
时钟选择:
1、Clock Monitor:可以用来使能时钟的控制。允许时钟监控功能。时钟监控功能通常是指对输入时钟信号进行监测和检测,以确保时钟信号的稳定性和可靠性。通过启用时钟监控,IP核可以检测时钟信号的频率、相位和其他参数,从而帮助确保锁相环的正常工作。
2、MMCN与PLL两者存在一些不同
如图所示,MMCM有七路输出,并且四路为差分输出还可以实习相位的精准调整等功能,而PLL只有六路输出并且都为单向输出。PLL可以看作MMCM的一部分。
3、对时钟特征进行修改
如上图所示,一般勾选的为允许倍频、相位保持(一般与输入相位一致)、抖动优化选择均衡带宽。
4、输入信号的设置:可以更改名字与时钟频率,除了主频率还能有副时钟信号。
输出信号选择:
如图所示,可以勾选多个输出信号,并且可以色湖之名称、频率、相位角、占空比等参数。
最后生成ip核
IP核调用
点击ip source当中的.veo文件,可以获得模块化的ip核进行调用
module pll_ip(
input wire sys_clk ,
input wire reset, //在设置界面可以设置为高或低电平复位,默认为高电平复位
output wire clk_100m ,
output wire clk_25m ,
output wire clk_s_90 ,
output wire clk_d_20 ,
output wire locked /输出locked为高,则表明输出稳定
);
clk_wiz_0 clk_wiz_0_inst
(
// Clock out ports
.clk_100m(clk_100m),
.clk_25m(clk_25m),
.clk_s_90(clk_s_90),
.clk_d_20(clk_d_20),
// Status and control signals
.reset(reset),
.locked(locked),
// Clock in ports
.pll_clk(sys_clk)
);
endmodule
仿真
对仿真进行编写:给与时钟一个50mhz的信号得到如下图所示的波形,如下图所示,locked为低时,其他输出不稳定。
当locked输出为高时,就能得到稳定输出的时钟。
FIFO
简介
FIFO就是First In First Out,即先入先出,是一种数据缓冲器,用来实现数据的先入先出的读写方式。
FIFO存储器主要作为缓存,在同步时钟系统、异步时钟系统中经常被使用,如多比特数据做跨时钟域处理、前后带宽不同步等都会使用FIFO。
FIFO分类可以分为SCFIFO(同步FIFO,时钟相同),DCFIFO(异步FIFO,时钟不同)
配置
1、接口类型有三种,选择通用的类型。
2、同步fifo根据存储器的类型不同可以分为四种,异步fifo可以根据存储器的不同可以分为三种,其对称性不太相同。
- 读端口与写端口位宽可以不同。
- 第一个字会被前置,对下一个字进行预判但是不读取。
- 使用内部fifo基本单元
- 是否支持纠错
其调用与上述的ppl相似。
仿真
代码如下
module tb_dcfifo_ip();
reg wr_clk;
reg rd_clk;
reg [7:0] data_in;
reg wr_en;
reg rd_en;
reg sys_rst_n;
wire [15:0] data_out;
wire full_flag;
wire empty_flag;
wire [6:0] rd_data_c;
wire [7:0] wr_data_c;
reg full_flag01;
reg full_flag02;
initial
begin
wr_clk = 1'b1;
rd_clk = 1'b1;
sys_rst_n <=1'b0;
#20
sys_rst_n <= 1'b1;
end
always #10 wr_clk <= ~wr_clk;
always #20 rd_clk <= ~rd_clk;
//生成写使能模拟延迟
reg [1:0] cnt;
always@(posedge wr_clk or negedge sys_rst_n)
if(!sys_rst_n)
cnt <= 1'd0;
else if(cnt == 1'd3)
cnt <= 1'd0;
else
cnt <=cnt +1'd1;
//写使能信号
always@(posedge wr_clk or negedge sys_rst_n)
if(!sys_rst_n)
wr_en <= 1'b0;
else if(rd_en == 1'b0 && cnt == 2'd0)
wr_en <= 1'b1;
else
wr_en <= 1'b0;
//写数据
always@(posedge wr_clk or negedge sys_rst_n)
if(!sys_rst_n)
data_in <= 8'd0;
else if(wr_en == 1'b1 && data_in == 8'd255)
data_in <= 8'd0;
else if(wr_en ==1'd1)
data_in <= data_in+1'b1;
//读使能
always@(posedge rd_clk or negedge sys_rst_n)
if(!sys_rst_n)
begin
full_flag01<=1'b0;
full_flag02<=1'b0;
end
else
begin
full_flag01 <= full_flag;
full_flag02 <= full_flag01;
end
//读使能
always@(posedge rd_clk or negedge sys_rst_n)
if(!sys_rst_n)
rd_en <= 1'b0;
else if(full_flag02 == 1'b1)
rd_en <= 1'b1;
else if(empty_flag == 1'b1)
rd_en <= 1'b0;
dcfifo_ip fifo_ip_inst(
.wr_clk (wr_clk),
.rd_clk (rd_clk),
.data_in (data_in) ,
.wr_en (wr_en),
.rd_en (rd_en),
.data_out (data_out) ,
.full_flag (full_flag),
.empty_flag (empty_flag),
.rd_data_c (rd_data_c),
.wr_data_c (wr_data_c)
);
endmodule
关于full信号的转变为什么要延迟几拍,是因为尽量避免亚稳态:full在读时钟时,进行复制,存在输入与时钟是异步的,可能会产生亚稳态的问题,可以参考这篇文章亚稳态
ROM
简介
RO,是只读存储器的简称,是一种只能读出事先存储数据的固态半导体,其特性是一旦存储资源无法改变或者删除,且资料不会因为掉电而消失。其本质还是RAM,通过处理使其无法写入,通过coe文件进行初始化。
输入:地址总线、使能信号、输出端口寄存器信号、时钟
配置
进入的配置界面如下图所示:
- 基本配置
1、 接口类型:有普通接口以及native接口,其左侧为创建32位地址。
2、选择存储类型:有单端口ROM、双端口ROM、以及RAM等选项,当为双端口时,右侧可选是否同时钟
3、纠错类型,单端口不能选择。
4、写使能,rom用不到
5、算法 - A端口配置
1、选择端口宽度
2、选择存储深度
3、RAM读写优先级、使能信号设置
4、使用输出端口寄存器配置会使得输出延迟一个时钟。
5、复位端口等。 - coe文件
生成coe测试文件的python代码
import os
with open("test.coe","w") as f:
data = "memory_initialization_radix = 10;\r\n"
f.write(data)
data = "memory_initialization_vector =\r\n"
f.write(data)
for j in range(256):
if(j==255):
f.write(str(j)+";"+"\r\n")
else:
f.write(str(j)+","+"\r\n")
f.close()
调用
设置时钟与地址输入端口、设置输出数据端口。
- 仿真文件如下
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/2c8def9d2d0a4719babf66c06c1863e4.png
仿真
选择输出寄存器延迟之后,其输出就会延迟两拍。
RAM
RAM是随机存储器的简称,其工作时可以对任何一个指定的地址写入或读取数据,