September 24, 2016
作者:dengshuai_super
出处:http://blog.csdn.net/dengshuai_super/article/details/52649265
声明:转载请注明作者及出处。
PLL(Phase Locked Loop): 为锁相回路或锁相环,用来统一整合时脉讯号,使高频器件正常工作,如内存的存取资料等。PLL用于振荡器中的反馈技术。 许多电子设备要正常工作,通常需要外部的输入信号与内部的振荡信号同步。一般的晶振由于工艺与成本原因,做不到很高的频率,而在需要高频应用时,有相应的器件VCO,实现转成高频,但并不稳定,故利用锁相环路就可以实现稳定且高频的时脉冲讯号。
主要用于时钟的分频或者倍频。
实际中PLL能让时钟更稳定吗?答案是并不能提高很多,它主要是受参考源的影响。参考源的时钟稳定度高,那么经过PLL同样更稳定。如果时钟源不够稳定,再经过PLL也没什么用,有可能PLL还会失锁,还会带来一些其他的问题。
Quartus II 工具栏介绍:
1.File—>new:New Quartus II Project 创建工程;Design Files:常用的是Verilog HDL,VHDL File;
Memory Files(初始化RAM和Rom的文件):Hexadecimal File(16进制格式);Memory Initialzation File(mif文件)
Verification /Debugging Files:常用的是SignalTap II Logic Analyzer File
2.Project—>Clean Project(有些时候Project里面产生很多文件,编译的时候会有一些 错误,当清除一下工程里边无效的文件的时候,有时候就编译过了)
3.Assignments—>Improt Assignments(加载一些管脚绑定的文件)
4.Processing—>Start Compilation(编译整个工程)
5.Tool—>Launch Dedign Space Explorer(在做完一个工程的时候,如果想达到某种目标的时序,可以通过这个软件去搜索时序);TimeQuest Timing Anlyzer (时序分析的工具);
Chip Planner(直接可以看到芯片内部的布线结果,可以看到大致的结构);
Design Partion Planner(可以按块来约束我们的资源)
SignalTap II Logic Analyzer(逻辑分析仪)
Programmer(下载硬件流)
MegaWizard Plug-In Manager(IP Core初始化工具,用来创建IP核)
Tcl Scripts(运行一些官方给的例子的时候,它有一些tcl脚本文件)
(之所以命名为ipcore_dir是为了和ISE统一,移植的时候方便)
选择左侧的ip核时,发现PLL部分都是灰色的(一个是因为没有License权限;另一个是当前器件不支持这个库,Cyclone IV E换成Cyclone V就有可以用的了(此处不换))。
最开始的时候PLL是定义在了I/O这个模块里面,因为实际上PLL也是需要有参考时钟的,参考时钟属于输入,所以它就被定义放到I/O里边,名字叫ALTPLL。
(Altera的PLL是模拟的锁相环跟xilinx里面的DCM(数字时钟管理模块)是有差别的,
模拟锁相环优点:它输出的稳定度高相位连续可调,延时连续可调;Xilinx的FPGA中集成的专用时钟资源与数字延迟锁相环(DLL),输出时钟要么是90度要么是270度。比如160度它是出不来的。在Altera 的PLL里是可以的。
模拟锁相环缺点:在温度或者实际工作环境中受到影响的时候,比如温度过高或电磁辐射过强的时候很容易让我们模拟锁相环失锁)**
ALLPLL设置:
速度等级:7(altera里面越大的值芯片速度越慢,8l指的是低电压的或者叫低功耗的)
频率:50MHZ
PLL Type:实际PLL的类型,这里就一种PLL,不能选。
Operation Mode操作模式:有一般正常模式;源同步补偿模式;0延时模式。
当选择In Source-synchronous Compensation mode时
图片来自:cyclone4-handbook.pdf
当我的数据输入进来,colck在数据管脚再到我们内部第一级寄存器的位置它会保持,使得进管脚的位置这个上升沿跟数据的相位关系到了第一级寄存器时它会保持不变。
实现原理:芯片内部它是知道它的时钟走线延时是多少,它会自动调整我们PLL的这个延时或者相移,使得它再到第一级寄存器位置的时候,它的相位还是没有发生变化。这就是我们在做输入接口的时候一个非常重要的应用,在做输入源同步的高速数据的时候,PLL要选择In Source-synchronous Compensation mode。
(1).源同步补偿模式:
时钟拓扑图:
实际我们的时钟和数据可能会有延时,所以呢通过PLL会帮我们补偿回来。
如果不通过PLL到达寄存器位置时,时钟上升沿可能就不和数据的中心对齐了。
可能比中心线靠右,可能再偏一点保持时间就不足了。也可能靠左。
这些是因为路径传输的延时造成的。源同步模式就可以使得输入的数据在端口那是什么样,到达第一级寄存器就还是什么样。就保证了它的时序特性。
相当于源同步模式中没有经过PLL,该到第一级寄存器是什么样子,就是什么样子。没有任何补偿。它不会帮我们去移相。
(4).Zero Delay Buffer Mode:
如果你想使得你输出的时钟跟你参考时钟同相位的话就选择这个模式
这里是应用与内部寄存器我们选择Normal Mode模式。
Optional Inputs:Create an ‘areset’ input to asynchronously reset the PLL.
这是异步复位,不选。一般情况下PLL不让它复位,有时候你复位控制不好,就使得PLL一直处在失锁状态,特别麻烦。
Lock Output:Create ‘locked’ output 选上,为了比如说在Debug的时候,看看参考源是不是有问题。如果给出的晶振参考源有问题,就会看到locked的震荡信号来回的变。这是debug的一个手段。使得可以观察PLL是否失锁。
Enable self-reset on loss lock:这个也不要加,PLL在做高温测试的时候,如果选上这个自动复位,PLL就一直工作不了了,一直就在那复位。
重配置PLL,实际在用的过程中可以动态的去配置它(通过配置文件配置它什么时候用哪个参数来工作。)
PLL有5路输出,
PLL原理:
PLL是一个反馈系统,数字与信号中的反馈都是和PLL相关的。
无分频:
**这里的Clock Multiplication Factor相当于倍频;
Clock Division Factor相当于分频。**
Clock phase shift:(移动的相位):(deg是以相位为单位),调90度的时候,移相90度就相当于向后移动四分之一个周期;移180度就是反转。
Clock duty cycle(%) :占空比。就是高电平和周期的比值。
选择Finish
跳转到Summary
把模版文件(pll1_inst.v(Instantiation template file))生成就行了,其他的我们不要。如图所示:
点击Finish生成IP Core
发现在工程里面生成一个ipcore_dir/pll1.qip的文件
//pll1_inst.v
pll1 pll1_inst (
.inclk0 ( inclk0_sig ),
.c0 ( c0_sig ),
.c1 ( c1_sig ),
.locked ( locked_sig )
);
//ex_ipcore.v
module ex_ipcore(
input wire sclk,
output wire oclk1,
output wire oclk2,
output wire locked
);
pll1 pll1_inst (
.inclk0 ( sclk ),
.c0 ( oclk1 ),
.c1 ( oclk2 ),
.locked ( locked )
);
endmodule
//tb_ex_ipcore.v
`timescale 1ns /1ns
module tb_ex_ipcore;
reg sclk;
wire oclk1,oclk2,locked;
initial begin
sclk =0;
end
always #10 sclk =~sclk;
ex_ipcore ex_ipcore_inst(
.sclk (sclk),
.oclk1 (oclk1),
.oclk2 (oclk2),
.locked (locked)
);
endmodule
#run.do
quit -sim
.main clear
vlib work
#work是默认的库,-work work就可以省略了。
vlog -work work ./tb_ex_ipcore.v
vlog ./altera_lib/*.v
vlog ./../design/*.v
vlog ./../quartus_prj/ipcore_dir/pll1.v
vsim -voptargs=+acc work.tb_ex_ipcore
add wave tb_ex_ipcore/ex_ipcore_inst/*
run 1000ns
当写完design文件,testbanch文件和run.do文件之后,需要添加库。这个库可以在
Tool—>MegaWizard Plug-In Manager—>Edit an existing custom megafunction variation—>ipcore_dir\pll1.v—>next—>EDA—>显示:Simulation Libraries: altera_mf ,Altera megafunction simulation library
需要添加仿真库:altera_mf
找到:D:\altera\13.1\quartus\eda\sim_lib\altera_mf.v
放到 D:\VivadoProjects\FPGA_From_e_to_c\ex_6\sim\altera_lib下
在ModelSim下新建一个项目,并运行脚本do run.do
在Quatus II中Fitter(Place & Route)之后,在Tools
—>Chip Planner中可以查看芯片内部的构造。
所有PLL输出来的时钟都会连接到全局时钟网络上来,如果我们自己分频的时钟,它直接是数据时钟走的是数据线。连接到ClockControl上面的线都是金线,延时非常小,而且到达每一级寄存器的延时是一样的。如果使用自己分频的时钟它走的是数据线,使得数据线到达寄存器时钟端延时不一样。这就是为什么不建议用计数器分频再作为时钟的原因。
所以如果想分频,就要用PLL;自己分频的时钟千万别用到触发器里面去。
always @(posedge ockl1)
if(div_flag == 1'b1)
cnt<=cnt+1'b1;
RAM : 在做数据处理的时候,如果没有RAM你就不知道怎么缓冲。
Tools—>MegaWizard Plug-In Manager—>Create an new custom megafunction variation—>ipcore_dir\rom_8x256—>Memory Compoler—>ROM:1-PORT
Which ports should be registered?
选择这个选项’q’ output port ,为了读RAM的时钟频率可以跑得更高一些。(假如两个寄存器之间是10ns,相当于100M,再俩个寄存器之间在放一个寄存器,就相当于它和两个寄存器都是5ns了,所以可以是频率更高。)
接下来是Mem Init —>有两种初始化文件一种是.hex十六进制,还有一种是.mif的。
new—>Memory File—>Hexadcimal File—>Number of words:256(深度);word size:8(相当于一共256个单元,列数为8,行数为256/8=32的表)—>在地址表的顶部选项栏右键,可以改显示的进制—>Ctrl+S保存为ipcore_dir/rom_8x256.hex—>
切换到创建IP核的目录—>Browse..打开文件Open(如果颜色是黑色的说明加载成功,如果是红色说明加载有问题)—>next–>next—>选择产生例化的文件rom_8x256_inst.v—>Finish.
ex_ipcore.v改为:
//ex_ipcore.v
module ex_ipcore(
input wire sclk,
output wire oclk1,
output wire oclk2,
output wire locked,
output reg [1:0] cnt,
output wire [7:0] odata
);
reg [7:0] raddr=0;
always @(posedge oclk1)
cnt <=cnt + 1'b1;
always @(posedge oclk1)
raddr <=raddr + 1'b1;
pll1 pll1_inst (
.inclk0 ( sclk ),
.c0 ( oclk1 ),
.c1 ( oclk2 ),
.locked ( locked )
);
rom_8x256 rom_8x256_inst (
.address ( raddr ),
.clock ( oclk1 ),
.q ( odata )
);
endmodule
run.do改为:
quit -sim
.main clear
vlib work
#work是默认的库,-work work就可以省略了。
vlog -work work ./tb_ex_ipcore.v
vlog ./altera_lib/*.v
vlog ./../design/*.v
vlog ./../quartus_prj/ipcore_dir/pll1.v
vlog ./../quartus_prj/ipcore_dir/rom_8x256.v
vsim -voptargs=+acc work.tb_ex_ipcore
add wave tb_ex_ipcore/ex_ipcore_inst/*
run 1000ns
用.mif文件初始化Memory。
new—>Memory Initialization File—>Number of words:256(深度);word size:8
将rom_8x256.mif拷贝到sim目录下,运行do run.do。
如何来生成.mif文件,可以用Matlab。
现将miffile.m函数复制到D:\VivadoProjects\FPGA_From_e_to_c\ex_6\matlab_sim下。
在Matlab下新建一个脚本gen_mif.m。
a=0:255;
miffile('rom_8x26.mif',a,8,256);
运行生成matlab_sim/rom_8x256.mif。
放到quartus_prj/ipcore_dir和sim文件夹下。
来源:至芯科技录播课
https://ke.qq.com/user/index/index.html#cid=66019&term_id=100056181