文章目录
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 口。
打开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核在后面介绍)

我们可以自己编写例化
例如我们编写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的英文全称是Random Access Memory,即随机存取存储器,它可以随时把数据写入任一指定地址的存储单元,也可以随时从任一指定地址中读出数据。其读写速度是由时钟频率决定的。RAM主要用来存放程序及程序执行过程中产生的中间数据、运算结果等。其特点适合双向交换数据。
其他类型的寄存器:
总结:RAM、ROM、FIFO都是FPGA提供的存储单元
同样在IP Catalog中搜索RAM

双击选择RAM:1-PORT,同样保存在ip文件夹下,命名为RAM_1port.v

选择数据位大小,以及数据深度


Next

Next

同样勾选RAM_1port_inst.v和RAM_1port_bb.v文件
同样,先例化
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:2-PORT


选择一个读模块一个写模块

默认就好了

选择读写时钟分开,也就是读写是两个单独的时钟

读出数据设置为q,同样选择复位清零

Next

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


选择读写使用同一个时钟

勾选如上信号

Next

Next

例化:
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

选择读写时钟分开


勾选以上信号


这里要使用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
编译仿真:
略
我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file
我有一个存储主机名的Ruby数组server_names。如果我打印出来,它看起来像这样:["hostname.abc.com","hostname2.abc.com","hostname3.abc.com"]相当标准。我想要做的是获取这些服务器的IP(可能将它们存储在另一个变量中)。看起来IPSocket类可以做到这一点,但我不确定如何使用IPSocket类遍历它。如果它只是尝试像这样打印出IP:server_names.eachdo|name|IPSocket::getaddress(name)pnameend它提示我没有提供服务器名称。这是语法问题还是我没有正确使用类?输出:ge
如何在ruby中调用C#dll? 最佳答案 我能想到几种可能性:为您的DLL编写(或找人编写)一个COM包装器,如果它还没有,则使用Ruby的WIN32OLE库来调用它;看看RubyCLR,其中一位作者是JohnLam,他继续在Microsoft从事IronRuby方面的工作。(估计不会再维护了,可能不支持.Net2.0以上的版本);正如其他地方已经提到的,看看使用IronRuby,如果这是您的技术选择。有一个主题是here.请注意,最后一篇文章实际上来自JohnLam(看起来像是2009年3月),他似乎很自在地断言RubyCL
我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www
我需要一些关于TDD概念的帮助。假设我有以下代码defexecute(command)casecommandwhen"c"create_new_characterwhen"i"display_inventoryendenddefcreate_new_character#dostufftocreatenewcharacterenddefdisplay_inventory#dostufftodisplayinventoryend现在我不确定要为什么编写单元测试。如果我为execute方法编写单元测试,那不是几乎涵盖了我对create_new_character和display_invent
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt
?博客主页:https://xiaoy.blog.csdn.net?本文由呆呆敲代码的小Y原创,首发于CSDN??学习专栏推荐:Unity系统学习专栏?游戏制作专栏推荐:游戏制作?Unity实战100例专栏推荐:Unity实战100例教程?欢迎点赞?收藏⭐留言?如有错误敬请指正!?未来很长,值得我们全力奔赴更美好的生活✨------------------❤️分割线❤️-------------------------
说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时
项目介绍随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱小学生兴趣延时班预约小程序的设计与开发被用户普遍使用,为方便用户能够可以随时进行小学生兴趣延时班预约小程序的设计与开发的数据信息管理,特开发了小程序的设计与开发的管理系统。小学生兴趣延时班预约小程序的设计与开发的开发利用现有的成熟技术参考,以源代码为模板,分析功能调整与小学生兴趣延时班预约小程序的设计与开发的实际需求相结合,讨论了小学生兴趣延时班预约小程序的设计与开发的使用。开发环境开发说明:前端使用微信微信小程序开发工具:后端使用ssm:VU
如何找到调用此方法的位置?defto_xml(options={})binding.pryoptions=options.to_hifoptions&&options.respond_to?(:to_h)serializable_hash(options).to_xml(options)end 最佳答案 键入caller。这将返回当前调用堆栈。文档:Kernel#caller.例子[0]%rspecspec10/16|===================================================62=====