Xilinx selectIO 资源的使用——input方向

本文转载自:十年老鸟的CSDN博客

整体描述
7系列FPGA包含的基本I/O逻辑资源。这些
资源包括:
•组合输入/输出
•3状态输出控制
•寄存的输入/输出
•寄存的三态输出控制
•双数据速率(DDR)输入/输出
•DDR输出3状态控制
•IDELAY为用户提供可调、精细分辨率延迟抽头的控制
•ODELAY为用户提供可调节、精细分辨率延迟抽头的控制
•SAME_EDGE输出DDR模式
•SAME_EDGE和SAME_EDGE_PIPELINED输入DDR模式

图 2-1 显示了 1.8V HP bank 的 I/O 块。 图 2-2 显示了 3.3V HR bank 的 I/O 块。 SelectIO™ 输入、输出和三态驱动器位于输入/输出缓冲器 (IOB) 中。 HP bank 具有单独的 IDELAY 和 ODELAY 块。 除了 ODELAY 块之外,HR bank 具有与 HP bank 相同的逻辑元素。

ILOGIC Resources

ILOGIC能支持以下操作:
边沿触发的D触发器
IDDR模式(OPPOSITE_EDGE or SAME_EDGE or SAME_EDGE_PIPELINED).
Level sensitive latch
Asynchronous/combinatorial

其中关注前面这两种操作。

将管脚输入的第一个触发器使用ILOGIC来实现有助于每次编译过程中时序的确定性。因为ILOGIC到管脚PAD的路径不会变化的,但如果第一个触发器是slice中的话,你不知道工具会约束到哪个slice上面去,每次编译可能结果都不一样

使用到这个功能的时候,只需要在代码中进行约束就可以了

例如:
(* IOB = “true” *) reg r_data;

管脚的输入,第一拍就要打到r_data上面

IDDR模式
某些ADC器件是双沿都发数据的,这个时候就需要用到IDDR功能,将双沿数据并行化。

IDDR支持以下三种操作模式:
• OPPOSITE_EDGE mode
• SAME_EDGE mode
• SAME_EDGE_PIPELINED mode
直接看时序图就清楚他们之间的差别了:

我是喜欢用第三种方式的,基本已经跟我们排列好了。
如何使用呢,使用IDDR原语来进行调用

主要关注输出Q1和Q2,以及输入D这三个管脚就可以了

例如一个14bit的ADC输入,是双沿采样格式输入进来的话,那么可以采用下面的写法进行解析

genvar i1;
generate
for(i1 = 0;i1<7;i1 = i1 + 1)
begin:bit2
IDDR #(
.DDR_CLK_EDGE("SAME_EDGE_PIPELINED"), // "OPPOSITE_EDGE", "SAME_EDGE"
// or "SAME_EDGE_PIPELINED"
.INIT_Q1(1'b0), // Initial value of Q1: 1'b0 or 1'b1
.INIT_Q2(1'b0), // Initial value of Q2: 1'b0 or 1'b1
.SRTYPE("SYNC") // Set/Reset type: "SYNC" or "ASYNC"
) m_IDDR_DA_58c20 (
.Q1 ( in_din_even[i1] ), // 1-bit output for positive edge of clock
.Q2 ( in_din_odd[i1] ), // 1-bit output for negative edge of clock
.C ( in_clk ), // 1-bit clock input
.CE ( 1'b1 ), // 1-bit clock enable input
.D ( in_din_buf[i1] ), // 1-bit DDR data input
.R ( 1'b0 ), // 1-bit reset ~i_rst_n
.S ( 1'b0 ) // 1-bit set
);
end
endgenerate

always @(posedge in_clk)
in_din_a <= {
in_din_odd[6],in_din_even[6],in_din_odd[5],in_din_even[5],in_din_odd[4],in_din_even[4],
in_din_odd[3],in_din_even[3],in_din_odd[2],in_din_even[2],in_din_odd[1],in_din_even[1],in_din_odd[0],in_din_even[0]};

注意对于时钟输入C来说,D和C的关系是异步的,Q1、 Q2和C的关系是同步的。
这里就存在一个问题,如果输入时钟C和输入数据D的建立保持时间不满足怎么办呢。

接下来就引入了下一个资源块来解决

Input Delay Resources (IDELAY)
每个 I/O 块都包含一个称为 IDELAYE2 的可编程延迟原语。 IDELAY 可以连接到 ILOGICE2/ISERDESE2 或 ILOGICE3/ISERDESE2 块。
IDELAYE2 是一个 31 抽头、环绕式延迟原语,具有校准的抽头分辨率。 有关延迟值,请参阅 7 系列 FPGA 数据手册。 它可以应用于组合输入路径、注册输入路径或两者。 它也可以直接从 FPGA 访问
逻辑。 IDELAY 允许在单个输入引脚的基础上延迟输入信号。 抽头延迟分辨率通过使用 IDELAYCTRL 参考时钟连续校准,该参考时钟来自 7 系列 FPGA 数据手册中指定的范围。

IDELAYE2的原语如下:

在这里,我们关注几个管脚即可,
C——这里是一个freefun时钟,
LD ——加载延迟系数脉冲
CNTVALUEIN——延迟系数
CNTVALUEOUT——延迟系数生效回读
.IDATAIN——如果是来自于管脚的输入则使用这个,需要延迟的数据或者时钟
DATAIN——如果是来自于FPGA逻辑的输入则需要使用这个
DATAOUT——延迟后的结果

还有一些属性设置也需要设置对。
这里有一个参考频率REFCLK_FREQUENCY,这个一般是不改的,用于静态时序分析。

(* IODELAY_GROUP = "selectio_AA" *)
IDELAYE2
# (
.CINVCTRL_SEL ("FALSE"), // TRUE, FALSE
.DELAY_SRC ("IDATAIN"), // IDATAIN, DATAIN
.HIGH_PERFORMANCE_MODE ("FALSE"), // TRUE, FALSE
.IDELAY_TYPE ("VAR_LOAD"), // FIXED, VARIABLE, or VAR_LOADABLE
.IDELAY_VALUE (0), // 0 to 31
.REFCLK_FREQUENCY (200.0),
.PIPE_SEL ("FALSE"),
.SIGNAL_PATTERN ("CLOCK")) // CLOCK, DATA
idelaye2_bus
(
.DATAOUT (in_clk),
.DATAIN (1'b0), // Data from FPGA logic
.C (i_freerun_clk),
.CE (0),
.INC (0),
.IDATAIN (in_clk_tmp), // Driven by IOB
.LD (i_tap_load),
.REGRST (1'b0),
.LDPIPEEN (1'b0),
.CNTVALUEIN (i_delay_tap), //in_delay_tap_in),
.CNTVALUEOUT (o_delay_tap), //in_delay_tap_out),
.CINVCTRL (1'b0)
);

设置系数的方法虽然介绍了几种,我们就直接使用这种直接设置值的方式就好了。

重点说一下延迟系数,7系列FPGA延迟系数范围为0-31.
其延时的分辨率与参考时钟频率f有关,延时的分辨率delay_resolution计算公式如下:
                      delay_resolution = 1/(32 * 2 * f)*1000000(ps)

其中f单位为Mhz。当f=200Mhz时,delay_resolution=78ps(注:计算出来为78.125ps,但会取整,为78ps);

需要注意的是,只要使用IDELAYE2,尽管延迟系数设置为0,也会比不使用IDELAYE2的时候会有一个固定的延迟,最好是通过仿真能够确定下来。

这样整个的延迟范围可以将近达到2.5ns。基本上对于时钟比较高的接口,通过调整抽头系数来满足建立保持时间,这个范围已经足够了。

时序如下

至于INC/CE等接口全部置成0.

IDELAYCTRL
最后,还有一个 IDELAYCTRL 原语。注意,使用了IDELAYE2就必须使用IDELAYCTRL。为什么呢,IDELAYCTRL就是用来提供延迟校准时钟的,而且对于我这个7系列的器件而言,其时钟必须是要200MHz。这也是保证前面说的78ps精确的基础。

只需要对REFCLK输入 200MHz即可(7系列)。虽然我试过输入其他频率的时钟也能编译过去,但为了保证准确无误,最好还是能使用一个200MHz的时钟给这个REFCLK作为输入
(* IODELAY_GROUP = "selectio_AA" *)
IDELAYCTRL
delayctrl (
.RDY (o_rdy),
.REFCLK (i_refclk),
.RST (1'b0));

RST写0即可,RDY用于判断校准是否结束。
注意IDELAYE2 和 IDELAYCTRL需要采用一个IODELAY_GROUP来约束,使得两个原语资源处于一个区域时钟内。
注意IDELAYCTRL一个区域时钟内只有一个,而IDELAYE2是每个管脚都有的。

实际上由于vivado工具的智能化,如果只例化了一个IDELAYCTRL,而例化了多个区域时钟的IDELAYCTRL,这个时候,vivado综合的时候会自动进行其他区域时钟的IDELAYCTRL例化。

区域时钟域
区域时钟域简单说明下,打开布局布线图
这就是一个区域时钟域:X1Y0

每个区域时钟域只有一个IDELAYCTRL,就在红色框框处,放大一点看就是这样了

而每个管脚都是有 以下这些资源

这个资源图实际上就是对应着:

这个框图了。

典型应用
双沿采样的IDDR ADC的使用,一般有N对数据差分线,和 1对时钟差分线。当采样率较高的时候,例如采样率为245.76MHz,12bit精度的话,那么就需要6对数据差分线和1对时钟差分线,时钟频率为245.76MHz。
假设数据线基本等长,那么我们就需要对时钟线进行相移,以保证采样点位于数据中间。
同样的,我们也可以对每一对数据线进行相移,使得时序满足要求。

这里还有Ologic 和 odelay没有介绍,基本和输入差不多,暂时就没再写了,后续再补充吧

最新文章

最新文章