目录
- 第一章 什么是IP核?
- 第二章 什么是LPM?
- 第一节 设置LPM_COUNTER模块参数
- 第二节 仿真
- 第三章 什么是PLL?
- 第一节 设置ALTPLL(嵌入式锁相环)模块参数
- 第二节 仿真
- 第四章 什么是RAM?
- 第一节 RAM_1PORT的调用
- 第二节 配置RAM_1PORT
- 第三节 RAM_2PORT的调用
- 第四节 配置RAM_2PORT
- 第五章 什么是FIFO?
- 第一节 FIFO模块参数配置
- 第二节 配置FIFO
- 参考文献
第一章 什么是IP核?
IP核就是知识产权核或知识产权模块的意思,在EDA技术开发中具有十分重要的地位。美国著名的Dataquest咨询公司将半导体产业的IP定义为“用于ASIC或FPGA中的预先设计好的电路功能模块”。IP主要分为软IP、固IP和硬IP。软IP是用Verilog/VHDL等硬件描述语言描述的功能块,但是并不涉及用什么具体电路元件实现这些功能。固IP是完成了综合的功能块。硬IP提供设计的最终阶段产品——掩膜。[1]
第二章 什么是LPM?
LPM即参数化模块库(Library of Parameterized Modules),是Altera 公司FPGA/CPLD设计软件Quartus II自带的一些宏功能模块,如:锁相环(PLLs), LVDS,数字信号处理(DSP) 模块等。这些功能是对Altera器件的优化,设计者在用这些模块时,不耗用器件的逻辑资源(Logic Cell)。[2]
第一节 设置LPM_COUNTER模块参数
-
新建项目,点击
IP Catalog
,在搜索框内输入counter,点击LPM_COUNTER
,然后将其保存为myLPM_counter.v
,点击Ok开始配置
-
基础设置
-
设置输入并点击NEXT。
-
多次点击NEXT,出现如下界面后选择需要文件,点击Finish完成配置,在弹出界面点击Yes
第二节 仿真
- 新建Verilog HDL File,然后写入代码,生成需要的模型,将其保存为
Updown_counter10.v
module Updown_counter10 (aclr,cp_en,cp,updown,co,q);
input aclr;
input cp_en;
input cp;
input updown;
output co;
output [3:0] q;
myLPM_counter myLPM_counter_inst(
.aclr(aclr),
.clk_en(cp_en),
.clock(cp),
.updown(updown),
.cout(co),
.q (q)
);
endmodule
文件目录如下
- 设置LPM_COUNTER,修改
myLPM_counter.qip
文件下的myLPM_counter.v
,使其符合期望
`timescale 1 ps / 1 ps
module myLPM_counter (aclr,clk_en,clock,sclr,updown,cout,q);
input aclr;
input clk_en;
input clock;
input sclr;
input updown;
output cout;
output [3:0] q;
wire sub_wire0;
wire [3:0] sub_wire1;
wire cout = sub_wire0;
wire [3:0] q = sub_wire1[3:0];
lpm_counter LPM_COUNTER_component (
.clk_en (clk_en),
.clock (clock),
// .sclr (sclr),
.updown (updown),
.cout (sub_wire0),
.q (sub_wire1),
.aclr (1'b0),
.aload (1'b0),
.aset (1'b0),
.cin (1'b1),
.cnt_en (1'b1),
.data ({4{1'b0}}),
.eq (),
.sclr(1'b0),
.sload (1'b0),
.sset (1'b0));
defparam
LPM_COUNTER_component.lpm_direction = "UNUSED",
LPM_COUNTER_component.lpm_modulus = 10,
LPM_COUNTER_component.lpm_port_updown = "PORT_USED",
LPM_COUNTER_component.lpm_type = "LPM_COUNTER",
LPM_COUNTER_component.lpm_width = 4;
endmodule
- 开始完整编译,编译通过后,新建
University Program VWF
进行仿真
- 仿真
观察仿真结果发现,结果与预期相同
第三章 什么是PLL?
PLL即锁相环 (phase locked loop)是一种利用相位同步产生的电压,去调谐压控振荡器以产生目标频率的负反馈控制系统。根据自动控制原理,这是一种典型的反馈控制电路,利用外部输入的参考信号控制环路内部振荡信号的频率和相位,实现输出信号频率对输入信号频率的自动跟踪,一般用于闭环跟踪电路。是无线电发射中使频率较为稳定的一种方法,主要有VCO(压控振荡器)和PLL IC (锁相环集成电路),压控振荡器给出一个信号,一部分作为输出,另一部分通过分频与PLL IC所产生的本振信号作相位比较,为了保持频率不变,就要求相位差不发生改变,如果有相位差的变化,则PLL IC的电压输出端的电压发生变化,去控制VCO,直到相位差恢复,达到锁相的目的。能使受控振荡器的频率和相位均与输入信号保持确定关系的闭环电子电路。[3]
第一节 设置ALTPLL(嵌入式锁相环)模块参数
-
选择ALTPLL,与第二章第一节相同的处理方法,在IP Catalog中搜索
PLL
,选择ALTPLL在点击左下角的Add
按钮将其保存为mypll.v
文件并开始配置
-
根据选择的芯片设置合适的晶振,ep4ce115f29c7的晶振为50MHZ,使用时钟频率选择50MHZ,模式为正常
-
以下配置默认即可
-
设置时钟
c0:设置100MHZ,将时钟倍频,占空比设置50%
c1:25MHZ,选择分频,且相位偏移90°,占空比50%
c2:5MHZ,占空比为25%
c3:先分频再倍频,75MHZ,占空比50%
目前只选择4个时钟,第5个时钟不启用 -
多次点击next,直到出现此界面,勾选
mypll_inst.v
文件和mypll_bb.v
文件
第二节 仿真
- 新建
Verilog HDL File
,写入下面的模型代码,保存为test_IP.v
module test_IP(
input clk , // 时钟信号
input rst_n , // 上电复位低有效
output c0 ,
output c1 ,
output c2 ,
output c3 ,
output locked
);
// PLL
mypll mypll_inst (
.areset ( ~rst_n ), // IP复位高有效
.inclk0 ( clk ), // 输入时钟
.c0 ( c0 ), // 输出时钟
.c1 ( c1 ), // 输出时钟
.c2 ( c2 ), // 输出时钟
.c3 ( c3 ), // 输出时钟
.locked ( locked ) // 时钟输出锁--锁定不稳定时钟输出
);
endmodule
以及测试代码test_tb.v
`timescale 1ns/1ps
module test_tb();
reg clk ;
reg rst_n ;
wire c0 ;
wire c1 ;
wire c2 ;
wire c3 ;
//例化要仿真的文件
test_IP u_test_IP(
.clk (clk ),//时钟信号
.rst_n (rst_n ),//上电复位低有效
.c0 (c0 ),
.c1 (c1 ),
.c2 (c2 ),
.c3 (c3 ),
.locked (locked )
);
always #10 clk = ~clk;//产生50M仿真时钟
integer i = 0,j = 0;//用于产生地址,写入数据
initial begin
clk = 1'b1;
rst_n = 1'b1;
#200.1;
rst_n = 1'b0;//主动产生上电复位
#200;
rst_n = 1'b1;
#20000;
$stop;
end
endmodule
- 进行完整编译,编译通过后开始仿真
- 仿真
观察仿真结果发现与预期相同
第四章 什么是RAM?
RAM即随机存取存储器(英语:Random Access Memory,缩写:RAM),也叫主存,是与CPU直接交换数据的内部存储器。它可以随时读写(刷新时除外),而且速度很快,通常作为操作系统或其他正在运行中的程序的临时数据存储介质。RAM工作时可以随时从任何一个指定的地址写入(存入)或读出(取出)信息。它与ROM的最大区别是数据的易失性,即一旦断电所存储的数据将随之丢失。RAM在计算机和数字系统中用来暂时存储程序、数据和中间结果。[4]
第一节 RAM_1PORT的调用
-
搜索
RAM
选择RAM_1PORT
并添加保存为RAM_1PORT.v
-
设置位宽和数据深度
-
多次点击NEXT直到出现此界面,并勾选
RAM_1PORT_inst.v
和RAM_1PORT_bb.v
第二节 配置RAM_1PORT
- 新建Verilog HDL File,写入模型的代码
module RAM_1port_test(
input clk ,//时钟信号
input rst_n ,//上电复位低有效
input rden ,
input wren ,
input [7:0] address ,
input [7:0] data ,
output [7:0] q
);
//RAM_1port
RAM_1PORT RAM_1PORT_inst (
.aclr ( ~rst_n ),
.address ( address ),
.clock ( clk ),
.data ( data ),
.rden ( rden ),
.wren ( wren ),
.q ( q )
);
endmodule
以及测试的代码
`timescale 1ns/1ps
module RAM_1port_test_tb();
reg clk ;
reg rst_n ;
reg rden ;
reg wren ;
reg [7:0] address ;
reg [7:0] data ;
wire [7:0] q ;
//例化要仿真的文件
RAM_1port_test u_RAM_1port_test(
.clk (clk ),//时钟信号
.rst_n (rst_n ),//上电复位低有效
.rden (rden ),
.wren (wren ),
.address (address ),
.data (data ),
.q (q )
);
always #10 clk = ~clk;//产生50M仿真时钟
integer i = 0,j = 0;//用于产生地址,写入数据
initial begin
clk = 1'b1;
rst_n = 1'b1;
#200.1;
rst_n = 1'b0;//主动产生上电复位
//RAM_1PORT
wren = 1'b0;//复位有效,赋初值
rden = 1'b0;
data = 0;
address = 0;
#200;
rst_n = 1'b1;
#200;
//wren 50M
for(i=0;i<256;i=i+1)begin
wren = 1'b1;//高电平有效
address = i;
data = i+1;
#20;
end
wren = 1'b0;//写完拉低
#100;
//rden 100M
for(j=0;j<256;j=j+1)begin
rden = 1'b1;
address = j;
#20;
end
rden = 1'b0;//读完拉低
#200;
$stop;
end
endmodule
- 完全编译
第三节 RAM_2PORT的调用
- 同样,找到RAM_2PORT并添加,保存为
RAM_2port.v
- 配置读写模块
- 配置数据深度为1024
- 选择读写时钟分开
- 读出数据设置为q,同样选择复位清零
- 多次点击next直到出现此界面,选择
RAM_2port_inst.v
及RAM_2port_bb.v
第四节 配置RAM_2PORT
- 同样编译模型代码和测试代码
test_IP.v
module test_IP(
input clk ,//时钟信号
input rst_n ,//上电复位低有效
input [7:0] data ,
input [7:0] rdaddress ,
input rden ,
input [7:0] wraddress ,
input wrclock ,
input wren ,
output [7:0] q
);
// //RAM_2port
RAM_2port RAM_2port_inst (
.data ( data ),
.rd_aclr ( ~rst_n ),
.rdaddress ( rdaddress ),
.rdclock ( clk ),
.rden ( rden ),
.wraddress ( wraddress ),
.wrclock ( wrclock ),
.wren ( wren ),
.q ( q )
);
endmodule
测试代码test_tb.v
`timescale 1ns/1ps
module test_tb();
reg clk ;
reg rst_n ;
reg [7:0] data ;
reg [7:0] rdaddress ;
reg rden ;
reg [7:0] wraddress ;
reg wrclock ;
reg wren ;
wire [7:0] q ;
//例化要仿真的文件
test_IP u_test_IP(
.clk (clk ),//时钟信号
.rst_n (rst_n ),//上电复位低有效
.data (data ),
.rdaddress (rdaddress ),
.rden (rden ),
.wraddress (wraddress ),
.wrclock (clk ),
.wren (wren ),
.q (q )
);
always #10 clk = ~clk;//产生50M仿真时钟
integer i = 0,j = 0;//用于产生地址,写入数据
initial begin
clk = 1'b1;
rst_n = 1'b1;
#200.1;
rst_n = 1'b0;//主动产生上电复位
wren = 1'b0;//复位有效,赋初值
rden = 1'b0;
rdaddress = 0;
wraddress = 0;
data = 0;
#200;
rst_n = 1'b1;
#200;
//wren 50M
for(i=0;i<256;i=i+1)begin
wren = 1'b1;//高电平有效
wraddress = i;
data = i+1;
#20;
end
wren = 1'b0;//写完拉低
#100;
//rden 100M
for(j=0;j<256;j=j+1)begin
rden = 1'b1;
rdaddress = j;
#20;
end
rden = 1'b0;//读完拉低
#200;
$stop;
end
endmodule
- 完整编译通过
第五章 什么是FIFO?
FIFO( First Input First Output)简单说就是指先进先出。由于微电子技术的飞速发展,新一代FIFO芯片容量越来越大,体积越来越小,价格越来越便宜。作为一种新型大规模集成电路,FIFO芯片以其灵活、方便、高效的特性,逐渐在高速数据采集、高速数据处理、高速数据传输以及多机处理系统中得到越来越广泛的应用。[5]
第一节 FIFO模块参数配置
1.在IP Catelog搜索FIFO,选择FIFO并添加,保存为fifo.v
- 选择读写使用同一个时钟
- 配置SCFIFO
- 默认即可,点击next
- 默认即可
- 勾选
fifo_inst.v
和fifo_bb.v
第二节 配置FIFO
- 与前面相同,新建Verilog HDL File,写入如下代码并保存
模型代码:
module test_IP(
input clk ,//时钟信号
input rst_n ,//上电复位低有效
input [7:0] data ,
input rdreq ,
input wrreq ,
output empty ,
output full ,
output [7:0] q ,
output [7:0] usedw
);
// //FIFO
fifo fifo_inst (
.aclr ( ~rst_n ),
.clock ( clk ),
.data ( data ),
.rdreq ( rdreq ),
.wrreq ( wrreq ),
.empty ( empty ),
.full ( full ),
.q ( q ),
.usedw ( usedw )
);
endmodule
测试代码:
`timescale 1ns/1ps
module test_tb();
reg clk ;
reg rst_n ;
reg wrreq ;
reg rdreq ;
reg [7:0] data ;
wire [7:0] q ;
wire empty ;
wire full ;
wire usedw ;
//例化要仿真的文件
test_IP u_test_IP(
.clk (clk ),//时钟信号
.rst_n (rst_n ),//上电复位低有效
.data (data ),
.rdreq (rdreq ),
.wrreq (wrreq ),
.empty (empty ),
.full (full ),
.q (q ),
.usedw (usedw )
);
always #10 clk = ~clk;//产生50M仿真时钟
integer i = 0,j = 0;//用于产生地址,写入数据
initial begin
clk = 1'b1;
rst_n = 1'b1;
#200.1;
rst_n = 1'b0;//主动产生上电复位
rdreq = 1'b0;
wrreq = 1'b0;
data = 0;
#200;
rst_n = 1'b1;
#200;
//wrreq 50M
for(i=0;i<256;i=i+1)begin
wrreq = 1'b1;//高电平有效
data = {$random};
#20;
end
wrreq = 1'b0;//写完拉低
#100;
//rdreq 100M
for(j=0;j<256;j=j+1)begin
rdreq = 1'b1;
#20;
end
rdreq = 1'b0;
#200;
$stop;
end
endmodule
- 全部编译通过
参考文献
[1] 潘松·EDA技术与Verilog HDL·北京:清华大学出版社,2010
[2] LPM(FPGA参数化模块库) -百度百科
[3] 锁相环(无线电术语)-百度百科
[4] 杨颂华,冯毛官,孙万蓉,初秀琴,胡力山编著·数字电子技术基础:西安电子科技大学出版社,2016.07
[5] FIFO存储器 -百度百科
[6] Quartus基本IP核调用及仿真
[7] 罗杰.Verilog HDL 与FPGA数字系统设计 第二版[M].机械工业出版社:北京,2022:198-210.