Quartus基本IP核调用及仿真

本文详细介绍了在Quartus中如何调用和仿真FPGA的重要组件:PLL、RAM和FIFO。通过实例演示了PLL的时钟倍频、分频和相位偏移配置,以及RAM的单时钟和双时钟操作,最后讲解了FIFO的读写共用时钟和跨时钟域操作。内容包括IP核的选择、配置、实例化和仿真流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文章目录

    • 一.PLL
      • PLL介绍
      • PLL的IP核调用
      • PLL仿真
    • 二.RAM
      • RAM介绍
      • RAM的IP核调用(单时钟)
      • RAM仿真(单时钟)
      • RAM的IP核调用(双时钟)
      • RAM仿真(双时钟)
    • 三.FIFO
      • FIFO介绍
      • FIFO的IP核调用(读写共用时钟)
      • FIFO仿真(读写共用时钟)
      • FIFO的IP核调用(读50MHZ时钟,写时钟100MHZ时钟)
      • FIFO仿真(读50MHZ时钟,写时钟100MHZ时钟)

一.PLL

PLL介绍

PLL全称Phase Locked Loop,也就是锁相环,是一种反馈控制电路。PLL对时钟网络进行系统级的时钟管理和偏移控制,具有时钟倍频、分频、相位偏移和可编程占空比的功能。PLL一般由模拟电路所实现。
在这里插入图片描述
PLL是FPGA重要的资源,不同FPGA的PLL 是不一样。以我们开发板的Cyclone IV为例,它有两个PLL,每个PLL可以提供5路输出。
PLL 的时钟输入可以是PLL 所在的 Bank 的时钟输入管脚或者其他 PLL 的输出,FPGA 内部产生的信号不能驱动PLL。Cyclone IV PLL 产生的时钟可以为单端时钟信号或差分时钟信号, 可以通过GCLK 网络直接驱动 FPGA 外部的 IO 口。

PLL的IP核调用

打开Quartus软件,新建一个项目后(命名为test_IP),在界面的最右侧,可以看见一个IP Catalog的栏目,在这里有很多的IP核可以供我们选择使用在这里插入图片描述
我们在这里需要选择PLL
在这里插入图片描述
资源比较多,可以在搜索栏搜索,双击选择ALTPLL后出现如下弹窗
在这里插入图片描述
点击…选择文件保存路径,这里使用我们创建工程文件夹里面的ip文件夹,将文件命名为pll.v,点击OK
在这里插入图片描述
我使用的是Cyclone IV系列的EP4CE6F17C8,只有一个50MHZ的晶振,时钟频率选择50MHZ就可以了,选择正常模式就可以了
在这里插入图片描述
选择创建一个’areset’输入异步重置锁相环
在这里插入图片描述
这一步默认就好了
在这里插入图片描述
Next
在这里插入图片描述
Next
在这里插入图片描述
原时钟频率为50MHZ,这里选择100MHZ,相当于把时钟倍频,占空比50%

在这里插入图片描述
第二个时钟,25MHZ,选择分频,且相位偏移90°,占空比50%
在这里插入图片描述
第三个时钟,5MHZ,占空比为25%
在这里插入图片描述
第四个时钟,先分频再倍频,75MHZ,占空比50%
这里只使用了4个时钟,第五个时钟不勾选
在这里插入图片描述
Next
在这里插入图片描述
选择生成pll_inst.v和pll_bb.v文件,点击Finish
现在PLL的相关资源已经添加到项目中了,在Quartus软件左侧选择IP Components就可以看见我们添加的pll了(其他IP核在后面介绍)
在这里插入图片描述

PLL仿真

我们可以自己编写例化
例如我们编写test_IP.v文件例化PLL模块

module test_IP(
    input           clk     ,//时钟信号
    input           rst_n   ,//上电复位低有效
    output          c0      ,
    output          c1      ,
    output          c2      ,
    output          c3      ,
    output          locked  ,
);
// //PLL
    pll	pll_inst (
    	.areset ( ~rst_n ),//IP复位高有效
    	.inclk0 ( clk    ),//输入时钟
    	.c0     ( c0     ),//输出时钟
    	.c1     ( c1     ),//输出时钟
    	.c2     ( c2     ),//输出时钟
    	.c3     ( c3     ),//输出时钟
    	.locked ( locked ) //时钟输出锁--锁定不稳定时钟输出
    	);
endmodule

再编写一个测试文件

`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介绍

RAM的英文全称是Random Access Memory,即随机存取存储器,它可以随时把数据写入任一指定地址的存储单元,也可以随时从任一指定地址中读出数据。其读写速度是由时钟频率决定的。RAM主要用来存放程序及程序执行过程中产生的中间数据、运算结果等。其特点适合双向交换数据。

其他类型的寄存器:

  • ROM(Read-Only Memory):只读存储器,系统上电后数据就被写入ROM,运行过程中智能从ROM中读取数据,而不能改变ROM中的数值。
  • FIFO(不寻址,操作简单)适合数据缓冲或跨时钟域数据同步处理;

总结:RAM、ROM、FIFO都是FPGA提供的存储单元

RAM的IP核调用(单时钟)

同样在IP Catalog中搜索RAM
在这里插入图片描述
双击选择RAM:1-PORT,同样保存在ip文件夹下,命名为RAM_1port.v
在这里插入图片描述
选择数据位大小,以及数据深度
在这里插入图片描述
在这里插入图片描述
Next
在这里插入图片描述
Next
在这里插入图片描述
同样勾选RAM_1port_inst.v和RAM_1port_bb.v文件

RAM仿真(单时钟)

同样,先例化
test_IP.v

module test_IP(
    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

编写测试文件test_tb.v

`timescale 1ns/1ps
module test_tb();

    reg             clk         ;
    reg             rst_n       ;
    reg             rden        ;
    reg             wren        ;
    reg    [7:0]    address     ;
    reg    [7:0]    data        ;
    wire   [7:0]    q           ;
    
//例化要仿真的文件
test_IP u_test_IP(
    .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的IP核调用(双时钟)

选择RAM:2-PORT
在这里插入图片描述
在这里插入图片描述
选择一个读模块一个写模块
在这里插入图片描述
默认就好了
在这里插入图片描述
选择读写时钟分开,也就是读写是两个单独的时钟
在这里插入图片描述
读出数据设置为q,同样选择复位清零
在这里插入图片描述
Next
在这里插入图片描述

RAM仿真(双时钟)

例化

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

测试文件:

`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介绍

FIFO的英文全称是First In First Out,即先进先出。FPGA使用的FIFO一般指的是对数据的存储具有先进先出特性的一个缓存器,常被用于数据的缓存或者高速异步数据的交互,也即所谓的跨时钟域信号传递。
它与FPGA内部的RAM和ROM的区别是没有外部读写地址线,采取顺序写入数据,顺序读出数据的方式,使用起来简单方便,由此带来的缺点就是不能像RAM和ROM那样可以由地址线决定读取或写入某个指定的地址。

FIFO的IP核调用(读写共用时钟)

在这里插入图片描述
在这里插入图片描述
选择读写使用同一个时钟
在这里插入图片描述
勾选如上信号
在这里插入图片描述
Next
在这里插入图片描述
Next
在这里插入图片描述

FIFO仿真(读写共用时钟)

例化:

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

编译仿真:

FIFO的IP核调用(读50MHZ时钟,写时钟100MHZ时钟)

同样选择上面的FIFO
在这里插入图片描述
选择读写时钟分开
在这里插入图片描述
在这里插入图片描述
勾选以上信号

在这里插入图片描述
在这里插入图片描述

FIFO仿真(读50MHZ时钟,写时钟100MHZ时钟)

这里要使用100MHZ时钟,就需要使用上面的PLL模块
例化:

module test_IP(
    input           clk     ,//时钟信号
    input           rst_n   ,//上电复位低有效

PLL
    output          c0      ,
    output          c1      ,
    output          c2      ,
    output          c3      ,
    output          locked  ,
    
//FIFO2
    input   [7:0]     data     ,
    input             rdreq    ,
    input             wrreq    ,
    output  [7:0]     q        ,
    output            rdempty  ,
    output            rdfull   ,
    output  [7:0]     rdusedw  ,
    output            wrempty  ,
    output            wrfull   ,
    output  [7:0]     wrusedw  

);

// //PLL
    pll	pll_inst (
    	.areset ( ~rst_n ),//IP复位高有效
    	.inclk0 ( clk    ),//输入时钟
    	.c0     ( c0     ),//输出时钟
    	.c1     ( c1     ),//输出时钟
    	.c2     ( c2     ),//输出时钟
    	.c3     ( c3     ),//输出时钟
    	.locked ( locked ) //时钟输出锁--锁定不稳定时钟输出
    	);
//FIFO2
    fifo2	fifo2_inst (
    	.aclr       ( ~rst_n    ),
    	.data       ( data      ),
    	.rdclk      ( clk       ),//50M
    	.rdreq      ( rdreq     ),
    	.wrclk      ( c0        ),//100M
    	.wrreq      ( wrreq     ),
    	.q          ( q         ),
    	.rdempty    ( rdempty   ),
    	.rdfull     ( rdfull    ),
    	.rdusedw    ( rdusedw   ),
    	.wrempty    ( wrempty   ),
    	.wrfull     ( wrfull    ),
    	.wrusedw    ( wrusedw   )
    	);
endmodule

仿真文件:

`timescale 1ns/1ps
module test_tb();

    reg             clk         ;
    reg             rst_n       ;

// //PLL
    wire            c0          ;
    wire            c1          ;
    wire            c2          ;
    wire            c3          ;

//FIFO2
    reg      [7:0]     data     ;
    reg                rdreq    ;
    reg                wrreq    ;
    wire     [7:0]     q        ;
    wire               rdempty  ;
    wire               rdfull   ;
    wire     [7:0]     rdusedw  ;
    wire               wrempty  ;
    wire               wrfull   ;
    wire     [7:0]     wrusedw  ;

//例化要仿真的文件
test_IP u_test_IP(
    .clk        (clk        ),//时钟信号
    .rst_n      (rst_n      ),//上电复位低有效

PLL   
    .c0         (c0         ),
    .c1         (c1         ),
    .c2         (c2         ),
    .c3         (c3         ),
    .locked     (locked     ),

//FIFO2
    .data       (data   ),
    .rdreq      (rdreq  ),
    .wrreq      (wrreq  ),
    .q          (q      ),
    .rdempty    (rdempty),
    .rdfull     (rdfull ),
    .rdusedw    (rdusedw),
    .wrempty    (wrempty),
    .wrfull     (wrfull ),
    .wrusedw    (wrusedw)

);

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;//主动产生上电复位
    
//FIFO2
    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 = {$random}%2;//高电平有效
        data = {$random};
        #20;
    end
    wrreq = 1'b0;//写完拉低
    #100;
    //rdreq  100M
    for(j=0;j<256;j=j+1)begin
        rdreq = {$random}%2;
        #20;
    end
    rdreq = 1'b0;
    #200;
    $stop;
end

endmodule

编译仿真:

### 关于Quartus IP的使用教程 在Quartus环境中,IP是一种预设计的功能模块,可以简化复杂电路的设计流程并提高开发效率。以下是关于几种常见IP(如FFT、FIR、FIFO和NCO)的具体使用方法: #### FFT IP 为了成功配置FFT IP,在准备阶段需确认所使用的Quartus版本支持该功能,并确保软件已正确安装且未受限于授权问题[^1]。如果遇到版本不兼容的情况,则可能需要下载对应的补丁程序或者升级至最新版。 具体操作指南可参照官方文档中的详细描述来完成设置向导的各项参数定义工作,包括但不限于输入/输出数据宽度的选择以及蝶形运算单元的数量设定等重要环节。 #### FIR滤波器IP 针对FIR ip的应用场景分析表明,尽管网络上存在较多基于旧版本的操作手册,但对于较新的Quartus 18.0而言,其内部集成有更为直观简便的新界面用于指导用户顺利完成整个创建过程[^2]。通过MegaWizard Plug-In Manager插件的帮助,能够轻松实现定制化需求下的各项调整选项填充任务。 #### FIFO存储缓冲区组件 当涉及到如何利用Quartus II平台上的资源构建简单的加法逻辑运算时,采用预先封装好的先进先出(FIFO)队列结构不失为一种高效解决方案之一[^3]。借助图形化的交互方式快速搭建起满足特定应用场合所需的临时寄存空间变得轻而易举起来。 #### 数字合成振荡源(NCO/DSP) 最后提到有关数字正交调制技术领域内的心组成部分——数控振荡器(Numerically Controlled Oscillator),即所谓的NCO或DDS(直接数字频率合成Direct Digital Synthesis)[^4]。按照既定步骤指引逐步推进直至最终生成目标文件为止即可达成预期效果。 以上各类IP Core均可以通过Altera官方网站获取最新的技术支持资料包链接地址;另外也可以尝试访问Intel FPGA开发者社区寻求更多实用技巧分享交流机会。 ```bash https://www.intel.com/content/www/us/en/software/fpga.html ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值