分类: 嵌入式
2012-08-31 17:44:52
首先我们需要有点理论依托,那么好好读读ug382是个不错的选择。其中提到的几个概念是我们需要区分清楚的,对应文档中的三个章节提到了三组概念,即Clock Resources、Clock Management Technology和Phase-Locked Loops。单从字意上理解,Clock Resources即时钟资源,从广义上来讲,时钟资源不仅包括了文档中重点阐述的器件内部时钟专用的布线资源、IO资源和buffer资源,也包括了后面两章所提到的CMT block(Clock Management Tiles)中包含的DCM(Digital Clock Managers)和PLL(Phase-Locked Loops)。一个CMT block包括了两个DCM和一个PLL,通常Spartan-6器件中都有数个CMT block。DCM是基于DLL的时钟管理单元,即用数字方式实现时钟频率的倍频、分频或相移输出,有较大的局限性。早期的Xilinx器件中大都是基于DLL或DCM技术进行时钟管理,而Spartan-6器件则在此基础上引入了PLL(锁相环),基于PLL的模拟时钟管理方式显然要灵活方便许多。PLL的配置使用也很简单,只要在ISE中添加Clocking Wizard的IP核并进行GUI配置,最后例化到工程源码中即可。
在第一个工程的基础上,我们添加一个Clocking Wizard的IP核。菜单栏上点击ProjectàNew Source…,弹出如图1所示的Wizard中,选择source type为IP(CORE Generator & Architecture Wizard),File name输入myclocking,然后点击Next。
图1 新建IP核
稍等片刻,当IP目录出现的时候,选择FPGA Features and DesignàClockingàClocking Wizard,如图2所示,接着点击Next,再点击Finish等待Clocking Wizard配置页面出现。
图2 IP目录
Clocking Wizard配置页面出现后,根据需要开启相应的接口信号,并且输入相关的参数完成设置。详细的使用参考在Clocking Wizard的菜单Documents下罗列出的几个文档,如图3所示。
图3 Clocking Wizard参考文档
本实例只简单的设置输入时钟为100MHz,输出4个频率分别为100MHz、50MHz、25MHz和12.5MHz的时钟。在page1和page2分别设置如图4和图5所示。
图4 page1输入时钟设置
图5 pgae2输出时钟设置
完成以上配置后,点击右下角的Generate按钮生成IP核源代码。当ISE的Console窗口出现信息“INFO:ProjectMgmt - Parsing design hierarchy completed successfully.”时,已经完成代码生成。此时在Hierarchy下面出现了一个新的名为myclocking.xco的文件,此时若选中该文件,则Processes下相应出现如图6所示的CORE Generator功能选项。
图6
我们接下来要做的是将myclocking例化到顶层代码中,双击View HDL Instantiation Template,复制HDL例化模板(如下的代码段)到顶层文件中。
//----------- Begin Cut here for INSTANTIATION Template ---// INST_TAG
myclocking instance_name
(// Clock in ports
.CLK_IN1(CLK_IN1), // IN
// Clock out ports
.CLK_OUT1(CLK_OUT1), // OUT
.CLK_OUT2(CLK_OUT2), // OUT
.CLK_OUT3(CLK_OUT3), // OUT
.CLK_OUT4(CLK_OUT4), // OUT
// Status and control signals
.RESET(RESET),// IN
.LOCKED(LOCKED)); // OUT
// INST_TAG_END ------ End INSTANTIATION Template ---------
在顶层文件中,修改信号接口(对应括号内的信号)与实际接口相匹配。在本实例中,将使用clocking输出的4个不同频率时钟分别进行分频驱动4个LED,实现4个不用时钟和计数器分频的LED同时闪烁的效果。此外,也分别用4个时钟的二分频信号驱动另外4个LED,用户可以观察这4个LED亮度有所不同,若是用示波器测量对应IO输出的波形,则其频率分别是50MHz、25MHz、12.5MHz和6.25MHz。
修改后的顶层源代码如下:
module testled(
clk,rst_n,
led
);
input clk; //100MHz
input rst_n; //低电平复位信号
output[7:0] led; //连接到LED指示灯
wire clk_100m; //clocking输出100MHz
wire clk_50m; //clocking输出50MHz
wire clk_25m; //clocking输出25MHz
wire clk_12m5; //clocking输出12.5MHz
wire clk_locked; //clocking输出完成标志位
//---------------------------------------------------
//IP核Clocking Wizard例化
//----------- Begin Cut here for INSTANTIATION Template ---// INST_TAG
myclocking uut_myclocking
(// Clock in ports
.CLK_IN1(clk), // IN
// Clock out ports
.CLK_OUT1(clk_100m), // OUT
.CLK_OUT2(clk_50m), // OUT
.CLK_OUT3(clk_25m), // OUT
.CLK_OUT4(clk_12m5), // OUT
// Status and control signals
.RESET(!rst_n),// IN
.LOCKED(clk_locked)); // OUT
// INST_TAG_END ------ End INSTANTIATION Template ---------
//---------------------------------------------------
reg[24:0] cnt0; //100MHz时钟分频计数器
always @ (posedge clk_100m or negedge rst_n) //异步复位
if(!rst_n) cnt0 <= 25'd0;
else cnt0 <= cnt0+1'b1; //寄存器cnt0循环计数
assign led[0] = cnt0[24];
//---------------------------------------------------
reg[23:0] cnt1; //50MHz时钟分频计数器
always @ (posedge clk_50m or negedge rst_n) //异步复位
if(!rst_n) cnt1 <= 24'd0;
else cnt1 <= cnt1+1'b1; //寄存器cnt1循环计数
assign led[1] = cnt1[23];
//---------------------------------------------------
reg[22:0] cnt2; //25MHz时钟分频计数器
always @ (posedge clk_25m or negedge rst_n) //异步复位
if(!rst_n) cnt2 <= 23'd0;
else cnt2 <= cnt2+1'b1; //寄存器cnt2循环计数
assign led[2] = cnt2[22];
//---------------------------------------------------
reg[21:0] cnt3; //12.5MHz时钟分频计数器
always @ (posedge clk_12m5 or negedge rst_n) //异步复位
if(!rst_n) cnt3 <= 22'd0;
else cnt3 <= cnt3+1'b1; //寄存器cnt3循环计数
assign led[3] = cnt3[21];
//---------------------------------------------------
//4个clocking输出时钟2分频寄存器,用于示波器观察
assign led[7:4] = {cnt0[0],cnt0[1],cnt0[2],cnt0[3]};
endmodule
Hierarchy下选中顶层源代码testled.v,然后双击Processes下的Generate Programming File进行编译并生产烧录文件。“Process "Generate Programming File" completed successfully ”信息出现在Console时,可以打开Digilent Adept使用Config功能烧录新生成的testled.bit文件。