基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证

本文内容:基于 Cyclone IV在 Quartus 中配置 IP 核中的 PLL 、 RAM 与 FIFO 的详细步骤

目录

  • 一、配置 PLL
    • 1.1 参数配置
    • 1.2 仿真测试
  • 二、配置 RAM
    • 2.1 参数配置
    • 2.2 仿真测试
  • 三、配置 FIFO
    • 3.1 参数配置
    • 3.2 仿真测试

一、配置 PLL

  • 在我看来哈,PLL 的作用就是将输入时钟通过倍频分频相位偏移设置占空比等操作,将输入的时钟信号转变为另外一种形式的时钟信号,这个主要看自己的需求

1.1 参数配置

  • 首先需要新建一个工程,在工程里面配置 PLL
  • 在【IP Catalog】界面的搜索框中输入【PLL】,双击【ALTPLL】即可
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第1张图片
  • 如果没有【IP Catalog】界面,在【View】中可以设置
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第2张图片
  • 点击【…】选择 IP 核的保存路径
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第3张图片
  • 最好新建一个 ip 文件夹,输入文件名后保存(图中有文件,是之前加的)
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第4张图片
  • 再点击【OK】
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第5张图片
  • Cyclone IV 选择 8 通道、50 MHz(细心的兄弟会发现左边的 PLL_demo 有 c0 - c3 多个输出,但是自己的界面只有个 c0 ,没关系,这是后面才配置出来的,我这个是配置好的)
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第6张图片
  • 勾选上【Create ‘locked’ output】
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第7张图片
  • 默认即可
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第8张图片
  • 默认即可
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第9张图片
  • 默认即可
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第10张图片
  • 主要的配置界面如下:
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第11张图片
    Clock multiplication factor——时钟倍频参数
    Clock division factor——时钟分频参数
    Clock phase shift——时钟相位偏移参数
    Clock duty cycle(%)——时钟占空比
  • 这里我们让每一个输出设置一种参数类型来看看实际的效果
  • 首先让 c0 设置倍频参数为 2,可以看到它的时钟频率变为了 100 MHz,再点击【Next>】
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第12张图片
  • c1 让它分频参数设为 2 ,可以看到它的频率变为了 25 MHz,再点【Next>】
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第13张图片
  • c2 相位偏移设为 90,单位是 deg,表示角度,也就是偏移了 π/2 个时钟周期,除了角度还有时间单位 ns、ps
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第14张图片
  • c3 时间占空比设为 20,之后可以具体看看是什么样子
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第15张图片
  • c4 我就没有勾选上了,因为就那么四个参数,没必要再搞一个 c4 输出了
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第16张图片
  • 继续点击【Next>】
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第17张图片
  • 勾选上【PLL_demo_inst.v】,这个可以生成相应的模块调用格式
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第18张图片

1.2 仿真测试

  • 写一个仿真文件,直接调用这个模块就可以,如果不怎么会仿真的话,可以参考博客:
    Quartus 与 ModelSim 联合仿真详细步骤
    基于 FPGA 按键控制呼吸灯原理、仿真及验证全过程
  • 贴一下仿真代码
`timescale 1ns/1ns

module tb_pll;

// Parameter definition
    parameter       CYC_CLK             = 20            ;

// Drive signal
    reg                                 tb_clk          ;
    reg                                 tb_rst_n        ;

// Observation signal
    wire                                c0              ;
    wire                                c1              ;
    wire                                c2              ;
    wire                                c3              ;
    wire                                locked          ;


// Module calls
    PLL_demo	PLL_demo_inst (
        /*input */  .inclk0             (tb_clk     ),
    	/*input */  .areset             (~tb_rst_n  ),
    	/*output*/  .c0                 (c0         ),
    	/*output*/  .c1                 (c1         ),
    	/*output*/  .c2                 (c2         ),
    	/*output*/  .c3                 (c3         ),
    	/*output*/  .locked             (locked     )
	);
    

// System initialization
    initial tb_clk = 1'b1;
    always #10 tb_clk = ~tb_clk;

    initial begin
        tb_rst_n = 1'b0;
        #20;
        tb_rst_n = 1'b1;

        #(500 * CYC_CLK);

        $stop;
    end
endmodule
  • 在【Simulation】选择 Test Benches 中,选择哪一个仿真文件,就会仿真哪个,同时还要设置相应的顶层模块熬
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第19张图片
  • 仿真结果如下:
    在这里插入图片描述
  • 可以看到
    c0 倍频,频率高了,时钟周期短了
    c1 分频,频率低了,时钟周期长了
    c2 相位偏移,右移了 π/2 个时钟周期
    c3 设置占空比 20,高电平区间占一个时钟周期 20%
  • 这就是 PLL 的作用,将输出的 clock 时钟信号转变为其它类型的时钟信号

二、配置 RAM

2.1 参数配置

  • 同样在【IP Catalog】搜索 RAM,选择 1-PORT 单端口的,2-PORT 表示双端口,学会了单端口那么双端口也依葫芦画瓢就会了
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第20张图片
  • 同样的操作步骤
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第21张图片
  • 这里表示一个数据字节为 8 bits,共 256 个字节,Auto 自动配置即可,勾选 Single clock 表示单个时钟信号控制输入输出就行
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第22张图片
  • 勾选上 q 也就是数据输出,同时勾选上复位信号 aclr 和读使能信号 rden
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第23张图片
  • 这里设置 Don’t Care 即可
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第24张图片
  • 在这里使用一个 hex 文件初始化 RAM,看下面怎么创建 hex 文件
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第25张图片
  • 切回 Quartus 主界面,点击【File】→【New…】
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第26张图片
  • 点击【Hexadecimal (Intel-Format) File】创建基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第27张图片
  • 新建的文件,里面是没有数据,选中所有的字节,右键点击【Custom Fill Cells…】
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第28张图片
  • Starting address:开始地址
    Ending address:结束地址
    Starting value:初始值
    Increment:递增操作
    by:步长
  • 最后点击 OK
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第29张图片
  • 保存到 prj 下面,一定要是 prj 下面!!!
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第30张图片
  • 回到刚刚的窗口,添加 hex 文件到 RAM 中
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第31张图片
  • 再点击【Next>】
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第32张图片
  • 最后勾选上【inst】即可
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第33张图片

2.2 仿真测试

  • 仿真代码如下:
`timescale 1ns/1ns

module tb_ram;

// Parameter definition
    parameter       CYC_CLK             = 20            ;

// Drive signal
    reg                                 tb_clk          ;
    reg                                 tb_rst_n        ;
    reg             [ 7:0]              address         ;
    reg             [ 7:0]              data            ;
    reg                                 rden            ;
    reg                                 wren            ;

// Observation signal
    wire            [ 7:0]              q_out           ;

// Module calls
    RAM_demo	RAM_demo_inst (
        .clock                          (tb_clk         ),
	    .aclr                           (~tb_rst_n      ),
	    .address                        (address        ),
	    .data                           (data           ),
	    .rden                           (rden           ),
	    .wren                           (wren           ),
	    .q                              (q_out          )
	);

// System initialization
    initial tb_clk = 1'b1;
    always #10 tb_clk = ~tb_clk;

    initial begin
        address = 8'd25;
        data = 8'd51;
        rden = 1'b0;
        wren = 1'b0;
        tb_rst_n = 1'b0;
        #20;
        tb_rst_n = 1'b1;

        // 读操作
        rden = 1'b1;
        repeat (256) begin
            address = address + 8'd1;
            #(CYC_CLK);
        end
        rden = 1'b0;

        #(500 * CYC_CLK);

        // 写操作
        wren = 1'b1;
        repeat (256) begin
            data = data + 8'd2;
            address = address + 8'd1;
            #(CYC_CLK);
        end
        wren = 1'b0;

        #(500 * CYC_CLK);

        // 读操作
        rden = 1'b1;
        repeat (256) begin
            address = address + 8'd1;
            #(CYC_CLK);
        end
        rden = 1'b0;

        #(500 * CYC_CLK);

        $stop;
    end
endmodule
  • 记得设置仿真文件
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第34张图片
  • 仿真结果:
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第35张图片
  • 第一段读操作是读的 hex 文件设置的内容,写操作写入新的数据,第二个读操作,读取的是写入的新数据

三、配置 FIFO

3.1 参数配置

  • FIFO 其实就是一个队列,先进先出的原则
  • 同样的,输入 FIFO/fifo 双击
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第36张图片
  • 选择存储路径
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第37张图片
  • 看自己的选择勾选与设置
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第38张图片
  • 默认设置即可
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第39张图片
  • 按照下图自己需要进行配置
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第40张图片
  • 默认就行
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第41张图片
  • 没勾选
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第42张图片
  • 一直到这一步,勾选个 inst 即可,生成个模块调用语句而已
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第43张图片

3.2 仿真测试

  • 这里使用一个 Verilog 顶层模块调用 FIFO,并不断地写数据,同时不断地读数据
  • 再写一个仿真测试文件来看看仿真波形

fifo_top.v

module fifo_top (
    input                               clk             ,
    input                               rst_n           ,
    
    output          [15:0]              q               ,
    output                              rdempty         ,
    output          [ 7:0]              rdusedw         ,
    output                              wrfull          ,
    output          [ 8:0]              wrusedw         
);

// Parameter definition
    

// Signal definition
    reg             [ 7:0]              data            ;
    reg                                 rdreq           ;
    reg                                 wrreq           ;
    

// Module calls
    FIFO_512_8	FIFO_512_8_inst (
    	/*input           */    .aclr       (~rst_n  ),// 复位信号,高电平有效
    	/*input     [ 7:0]*/    .data       (data    ),// 写数据,8bits
    	/*input           */    .rdclk      (clk     ),// 读时钟信号
    	/*input           */    .rdreq      (rdreq   ),// 读使能信号,高电平读
    	/*input           */    .wrclk      (clk     ),// 写时钟信号
    	/*input           */    .wrreq      (wrreq   ),// 写使能信号,高电平写
    	/*output    [15:0]*/    .q          (q       ),// 读数据,16bits
    	/*output          */    .rdempty    (rdempty ),// 读空使能,表示读的时候队列中是否为空,1表示空,0表示非空
    	/*output    [ 7:0]*/    .rdusedw    (rdusedw ),// 读余量,表示读的时候队列中有多少个16bits的数据
    	/*output          */    .wrfull     (wrfull  ),// 写满使能,表示写的时候队列中是否写满了,1表示满,0表示非满
    	/*output    [ 8:0]*/    .wrusedw    (wrusedw ) // 写余量,表示写的时候队列中有多少个8bits的数据 
    );
    
// Logic description
    // 读使能
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            rdreq <= 'd0;
        end
        else if (rdempty) begin
            rdreq <= 'd0;
        end
        else begin
            rdreq <= 'd1;
        end
    end

    // 写使能
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            wrreq <= 'd0;
        end
        else if (wrfull) begin
            wrreq <= 'd0;
        end
        else begin
            wrreq <= 'd1;
        end
    end

    // 写数据
    always @(posedge clk or negedge rst_n) begin
        if (!rst_n) begin
            data <= 'd20;
        end
        else if (wrreq) begin
            if (data >= 255) begin
                data <= 0;
            end
            else begin
                data <= data + 'd2;
            end
        end
        else begin
            data <= 'd20;
        end
    end

endmodule
  • 仿真文件

tb_fifo.v

`timescale 1ns/1ns

module tb_fifo;

// Parameter definition
    parameter       CYC_CLK             = 20            ;

// Drive signal
    reg                                 tb_clk          ;
    reg                                 tb_rst_n        ;

// Observation signal
    wire 	        [15:0]              tb_q            ;
	wire 	                            tb_rdempty      ;
	wire 	        [ 7:0]              tb_rdusedw      ;
	wire 	                            tb_wrfull       ;
	wire 	        [ 8:0]              tb_wrusedw      ;

// Module calls
    fifo_top U_fifo_top(
        /*input                 */  .clk            (tb_clk     ),
        /*input                 */  .rst_n          (tb_rst_n  ),
        /*output          [15:0]*/  .q              (tb_q       ),
        /*output                */  .rdempty        (tb_rdempty ),
        /*output          [ 7:0]*/  .rdusedw        (tb_rdusedw ),
        /*output                */  .wrfull         (tb_wrfull  ),
        /*output          [ 8:0]*/  .wrusedw        (tb_wrusedw )
    );

// System initialization
    initial tb_clk = 1'b1;
    always #10 tb_clk = ~tb_clk;

    initial begin
        tb_rst_n = 1'b0;
        #20;
        tb_rst_n = 1'b1;

        #(200 * CYC_CLK);

        $stop;
    end
endmodule
  • 仿真结果
    基于 Cyclone IV 在 Quartus 中配置 IP 核中的 PLL、RAM 与 FIFO 的详细步骤及仿真验证_第44张图片
  • 可以看到队列先进先出的原则
  • 但是读余量前面一段时间为 0 ,但是明明有数据,结果却为了,过了几个时钟周期后才变成 1
  • 应该是由于写数据到 M9K 中这个过程需要时间,过了几个时钟周期后,读余量才检测到有数据,才读取数据

你可能感兴趣的:(fpga)