这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » FPGA » 以xilinx xc4vsx55为例管脚分配时需注意事项

共3条 1/1 1 跳转至

以xilinx xc4vsx55为例管脚分配时需注意事项

菜鸟
2017-06-29 15:21:48     打赏
FPGA管脚分配时需注意的一些事项(以xilinx xc4vsx55为例)
平台:XC4VSX55  ISE10.1


设计过FPGA的原理图,看FPGA的手册,说管脚的分配问题,如时钟管脚要用GC类管脚,而且单端时钟输入时要用P类型的管脚,不能用N类型管脚等等。
一直以来都没有试验过,今天试验一把,以求各种验证。

1)GC类全局时钟管脚是否可用作普通IO使用?
所谓GC类管脚,就是在管脚的称是诸如IO_L1P_GC_LC等带有GC的管脚。其实手册中说的是GC类管脚可以用作IO的,但在《Xilinx FPGA开发实用教程》(清华出版社)574页倒数第八行提到:“所有从全局时钟管脚输入的信号必须经过IBUF元,否则在布局布线时会报错”,于是今天我试了一下,将某一GC类管脚分配给一个普通的输入口(也试验了分配给一个普通的输出口),经布局布线后,未出错。
因此得出结论:GC类全局时钟管脚可以作为普通IO使用。(不知道是不是我对书中提到的全局时钟管脚理解有误,如果是,请网友别拍我,敬请留言指正)

2)非GC类全局时钟管脚是否可以作时钟使用?
其实至于说能否作为时钟使用,这里有另一层函义。当然,如果你把一个普通IO口配置成输入口,就把它的输入信号作为时钟,那是没问题的。但我们一般不这么做,因为时钟信号对于我们来说是一个很重要的信号,因此FPGA在内部会有特殊照顾,如果你使用FPGA传门为时钟预留的管脚,并作一些处理,那么你的时钟对于各种模块的时延是可以忽略的,因为时钟在布线时是单独走的一层,而如果你就仅用普通IO的话,经过FPGA内部布局布线后,从它的输到,再到各个使用时钟的地方,有的线长,有的线短,它的时延将是不一样的。这些东西还是看一些FPGA结构的内容吧。
在xilinx里有专门的DCM IP核可供调用,在ISE中执行project——>New Source——>IP(CORE Generator & Architecture Wizard)——>FPGA Features and Design——>Clocking——>Virtex-4——>Single DCM ADV v9.1i,可得如下界面:

需要特别注意的是CLKIN Source需要选择是External还是Internal,各自生成的源文件如下:
==========================选择External=========================
`timescale 1ns / 1ps
module clk_test(CLKIN_IN, 
                CLKIN_IBUFG_OUT, 
                CLK0_OUT, 
                LOCKED_OUT);
    input CLKIN_IN;
   output CLKIN_IBUFG_OUT;
   output CLK0_OUT;
   output LOCKED_OUT;
   
   wire CLKFB_IN;
   wire CLKIN_IBUFG;
   wire CLK0_BUF;
   wire GND_BIT;
   wire [6:0] GND_BUS_7;
   wire [15:0] GND_BUS_16;
   
   assign GND_BIT = 0;
   assign GND_BUS_7 = 7'b0000000;
   assign GND_BUS_16 = 16'b0000000000000000;
   assign CLKIN_IBUFG_OUT = CLKIN_IBUFG;
   assign CLK0_OUT = CLKFB_IN;
   IBUFG CLKIN_IBUFG_INST (.I(CLKIN_IN), 
                           .O(CLKIN_IBUFG));

   BUFG CLK0_BUFG_INST (.I(CLK0_BUF), 
                        .O(CLKFB_IN));
   DCM_ADV DCM_ADV_INST (.CLKFB(CLKFB_IN), 
                         .CLKIN(CLKIN_IBUFG), 
                         .DADDR(GND_BUS_7[6:0]), 
                         .DCLK(GND_BIT), 
                         .DEN(GND_BIT), 
                         .DI(GND_BUS_16[15:0]), 
                         .DWE(GND_BIT), 
                         .PSCLK(GND_BIT), 
                         .PSEN(GND_BIT), 
                         .PSINCDEC(GND_BIT), 
                         .RST(GND_BIT), 
                         .CLKDV(), 
                         .CLKFX(), 
                         .CLKFX180(), 
                         .CLK0(CLK0_BUF), 
                         .CLK2X(), 
                         .CLK2X180(), 
                         .CLK90(), 
                         .CLK180(), 
                         .CLK270(), 
                         .DO(), 
                         .DRDY(), 
                         .LOCKED(LOCKED_OUT), 
                         .PSDONE());
   defparam DCM_ADV_INST.CLK_FEEDBACK = "1X";
   defparam DCM_ADV_INST.CLKDV_DIVIDE = 2.0;
   defparam DCM_ADV_INST.CLKFX_DIVIDE = 1;
   defparam DCM_ADV_INST.CLKFX_MULTIPLY = 4;
   defparam DCM_ADV_INST.CLKIN_DIVIDE_BY_2 = "FALSE";
   defparam DCM_ADV_INST.CLKIN_PERIOD = 16.129;
   defparam DCM_ADV_INST.CLKOUT_PHASE_SHIFT = "NONE";
   defparam DCM_ADV_INST.DCM_AUTOCALIBRATION = "TRUE";
   defparam DCM_ADV_INST.DCM_PERFORMANCE_MODE = "MAX_SPEED";
   defparam DCM_ADV_INST.DESKEW_ADJUST = "SYSTEM_SYNCHRONOUS";
   defparam DCM_ADV_INST.DFS_FREQUENCY_MODE = "LOW";
   defparam DCM_ADV_INST.DLL_FREQUENCY_MODE = "LOW";
   defparam DCM_ADV_INST.DUTY_CYCLE_CORRECTION = "TRUE";
   defparam DCM_ADV_INST.FACTORY_JF = 16'hF0F0;
   defparam DCM_ADV_INST.PHASE_SHIFT = 0;
   defparam DCM_ADV_INST.STARTUP_WAIT = "FALSE";
endmodule


==========================选择Internal=========================
`timescale 1ns / 1ps
module clk1_test(CLKIN_IN, 
                 CLK0_OUT, 
                 LOCKED_OUT);
    input CLKIN_IN;
   output CLK0_OUT;
   output LOCKED_OUT;
   
   wire CLKFB_IN;
   wire CLK0_BUF;
   wire GND_BIT;
   wire [6:0] GND_BUS_7;
   wire [15:0] GND_BUS_16;
   
   assign GND_BIT = 0;
   assign GND_BUS_7 = 7'b0000000;
   assign GND_BUS_16 = 16'b0000000000000000;
   assign CLK0_OUT = CLKFB_IN;
   BUFG CLK0_BUFG_INST (.I(CLK0_BUF), 
                        .O(CLKFB_IN));
   DCM_ADV DCM_ADV_INST (.CLKFB(CLKFB_IN), 
                         .CLKIN(CLKIN_IN), 
                         .DADDR(GND_BUS_7[6:0]), 
                         .DCLK(GND_BIT), 
                         .DEN(GND_BIT), 
                         .DI(GND_BUS_16[15:0]), 
                         .DWE(GND_BIT), 
                         .PSCLK(GND_BIT), 
                         .PSEN(GND_BIT), 
                         .PSINCDEC(GND_BIT), 
                         .RST(GND_BIT), 
                         .CLKDV(), 
                         .CLKFX(), 
                         .CLKFX180(), 
                         .CLK0(CLK0_BUF), 
                         .CLK2X(), 
                         .CLK2X180(), 
                         .CLK90(), 
                         .CLK180(), 
                         .CLK270(), 
                         .DO(), 
                         .DRDY(), 
                         .LOCKED(LOCKED_OUT), 
                         .PSDONE());
   defparam DCM_ADV_INST.CLK_FEEDBACK = "1X";
   defparam DCM_ADV_INST.CLKDV_DIVIDE = 2.0;
   defparam DCM_ADV_INST.CLKFX_DIVIDE = 1;
   defparam DCM_ADV_INST.CLKFX_MULTIPLY = 4;
   defparam DCM_ADV_INST.CLKIN_DIVIDE_BY_2 = "FALSE";
   defparam DCM_ADV_INST.CLKIN_PERIOD = 16.129;
   defparam DCM_ADV_INST.CLKOUT_PHASE_SHIFT = "NONE";
   defparam DCM_ADV_INST.DCM_AUTOCALIBRATION = "TRUE";
   defparam DCM_ADV_INST.DCM_PERFORMANCE_MODE = "MAX_SPEED";
   defparam DCM_ADV_INST.DESKEW_ADJUST = "SYSTEM_SYNCHRONOUS";
   defparam DCM_ADV_INST.DFS_FREQUENCY_MODE = "LOW";
   defparam DCM_ADV_INST.DLL_FREQUENCY_MODE = "LOW";
   defparam DCM_ADV_INST.DUTY_CYCLE_CORRECTION = "TRUE";
   defparam DCM_ADV_INST.FACTORY_JF = 16'hF0F0;
   defparam DCM_ADV_INST.PHASE_SHIFT = 0;
   defparam DCM_ADV_INST.STARTUP_WAIT = "FALSE";
endmodule


比较以上两段代码,区别在于选择是External时CLKIN经过了IBUFG才到的DCM_ADV,而选择Internal的CLKIN则直接到了DCM_AV,而IBUFG就是原语“全局时钟缓冲”单元,我们使用时要选择External,只有当我们的级联两个DCM模块时,直接与外面相连的选External,而另一个选择Internal。
这也是本文的一个知识点吧:两个DCM级联时,直接与外面相连的选External,而另一个选择Internal。
所以本段的主题是“非GC类全局时钟管脚是否可以作时钟使用?”其实更多应该指的是“非GC类全局时钟管脚是否可以接到IBUFG?”
试验中,我们将External的DCM的输入CLKIN输入引脚配置成一个普通的IO口,即非GC类全局时钟管脚,布局布线阶段出现以下错误:
ERROR: Place:645 - A clock IOB clock component is not placed at an optimal clock IOB site. The clock IOB component <clk>
因此得出结论:非GC类全局时钟管脚不可以作时钟使用(其实是不可以接到IBUFG的输入端)。

3)在Xilinx手册中提到,如果使用单端输入时钟,要使用P类型GC全局时钟管脚,那么空间N类型的管脚是否可以么?
所谓P类型还是N类型其实指的是IO_L1P_GC_LC或IO_L1N_GC_LC,注意这里的L1P和L1N,这就标识这个管脚是P类型还是N类型。
试验中,我们将N类型全局时钟管脚配置给CLKIN,结果布局布线时出现与(2)中一样的错误。
因此得出结论:GC类全局时钟管脚N类型管脚不可以作为单端时钟输入管脚(其实也是不能作为IBUFG的输入端)

4)差分时钟输入时钟管脚能否配置普通IO?N类型管脚和P类型管脚必须分别给配置P类型GC全局时钟管脚和N类型GC全局时钟管脚?
<4.1>使用了一对普通IO配置给DCM的CLKIN_N_IN和CLKIN_P_IN,并且将这对普通的IO的P型分配给DCM的CLKIN_N_IN型输入,IO的N型分配给DCM的CLKIN_P_IN型输入,出现如下错误:
ERROR: Place:604 - The I/O components "clkp" and "clkn" are the P- and N-sides of a  differental I/O pair. The component
<4.2>使用了一对普通IO配置给DCM的CLKIN_N_IN和CLKIN_P_IN,并且对应地将这对普通的IO的P型分配给DCM的CLKIN_P_IN型输入,IO的N型分配给DCM的CLKIN_N_IN型输入,出现如下错误:
ERROR: Place:645 - A clock IOB clock component is not placed at an optimal clock IOB site. The clock IOB component <clkp>
<4.3>使用一对GC类全局时钟IO管脚配置给DCM的CLKIN_N_IN和CLKIN_P_IN,并且将这对普通的IO的P型分配给DCM的CLKIN_N_IN型输入,IO的N型分配给DCM的CLKIN_P_IN型输入,出现与4.1中相同的错误。
<4.4>正常配置,即使用了一对GC类全局时钟IO管脚配置给DCM的CLKIN_N_IN和CLKIN_P_IN,并且对应地将这对普通的IO的P型分配给DCM的CLKIN_P_IN型输入,IO的N型分配给DCM的CLKIN_N_IN型输入,则完全正确。
因此得出结论:差分时钟输入时必须使用一对GC类全局时钟IO管脚配置给DCM的CLKIN_N_IN和CLKIN_P_IN,且N类型和P类型要匹配。
其实这个归根到底还是原语IBUFGDS在作怪,查看一下差分输入DCM的原文件就行了:
   IBUFGDS CLKIN_IBUFGDS_INST (.I(CLKIN_P_IN), 
                               .IB(CLKIN_N_IN), 
                               .O(CLKIN_IBUFGDS));

5)那么如果将输入输出口配置成非IO管脚会怎么样呢?
在试验中,将某一VCCO配置成了给了输出口,结果在映射阶段出现如下错误:
ERROR:MapLib:30 - LOC constraint AF17 on q<2> is invalid: No such site on the
因此,不能将输入输出口配置成非IO管脚,当然这样配置本身也是不合理的。


高工
2020-04-30 15:30:10     打赏
2楼

学习一下,多谢楼主分享


工程师
2020-05-02 23:42:00     打赏
3楼

感谢分享


共3条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]