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

目录

一、配置 PLL1.1 参数配置1.2 仿真测试

二、配置 RAM2.1 参数配置2.2 仿真测试

三、配置 FIFO3.1 参数配置3.2 仿真测试

一、配置 PLL

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

1.1 参数配置

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

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 中,选择哪一个仿真文件,就会仿真哪个,同时还要设置相应的顶层模块熬 仿真结果如下: 可以看到 c0 倍频,频率高了,时钟周期短了 c1 分频,频率低了,时钟周期长了 c2 相位偏移,右移了 π/2 个时钟周期 c3 设置占空比 20,高电平区间占一个时钟周期 20%这就是 PLL 的作用,将输出的 clock 时钟信号转变为其它类型的时钟信号

二、配置 RAM

2.1 参数配置

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

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

记得设置仿真文件 仿真结果: 第一段读操作是读的 hex 文件设置的内容,写操作写入新的数据,第二个读操作,读取的是写入的新数据

三、配置 FIFO

3.1 参数配置

FIFO 其实就是一个队列,先进先出的原则同样的,输入 FIFO/fifo 双击 选择存储路径 看自己的选择勾选与设置 默认设置即可 按照下图自己需要进行配置 默认就行 没勾选 一直到这一步,勾选个 inst 即可,生成个模块调用语句而已

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

仿真结果 可以看到队列先进先出的原则但是读余量前面一段时间为 0 ,但是明明有数据,结果却为了,过了几个时钟周期后才变成 1应该是由于写数据到 M9K 中这个过程需要时间,过了几个时钟周期后,读余量才检测到有数据,才读取数据

相关链接

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: