01signal.com

Source-synchronous 输出

介绍

本页讨论 source-synchronous data 输出。这种技术意味着数据输出(data outputs)与 FPGA 与这些输出(outputs)并行生成的时钟同步。

Source synchronous clocking with outputs only

如果与外部组件的接口仅由 FPGA中的输出端口(output ports)组成,则此方法是显而易见的选择。如本页底部所述,如果 I/O 是双向的,它也适用。还有一个单独的页面讨论了时钟和数据(data)之间的一般关系。

基本应用

考虑这 Verilog 示例:

module top (
   input clk,
   output reg [7:0] data_out,
   output reg sync_clk_out
);

   always @(posedge clk)
     begin
	sync_clk_out <= !sync_clk_out;
	if (sync_clk_out)
	  data_out <= data_out + 1;
     end
endmodule

请注意, @data_out 与 @sync_clk_out的下降沿(falling edge)同时更改其值: 当 @sync_clk_out 为低电平时, @data_out 不变。当 @sync_clk_out 为高电平时, @data_out 响应 @clk的上升沿(rising edge)变化为一个新值。

如果IOB 寄存器同时用于 @data_out 和 @sync_clk_out,则所有这些输出信号的值几乎同时改变。因此,接收这些信号的外部组件可以使用 @sync_clk_out 作为其时钟。通常,通过这种方式很容易满足外部组件的时序(timing)要求(假设 @data_out 的采样(sampling)与 @sync_clk_out的上升沿同步)。

使用 DDR 寄存器

上面的例子有一个明显的缺点: @sync_clk_out 的频率是 @clk的频率的一半。因此, @data_out 的传输速率(data rate)也限制为 @clk 的频率的一半。唯一的例外是如果外部组件对 @sync_clk_out的两个时钟边沿(clock edges)都敏感(即它有一个 DDR 输入)。通常情况并非如此。

可以使用输出 DDR register (output DDR register)来生成与数据输出对齐的输出时钟(output clock)。这个想法是使用一个触发器(flip-flop)来改变它在两个时钟边沿上的值。因此,这样的触发器(flip-flop)行为如下:

always @(posedge clk or negedge clk)
     if (clk)
       sync_clk_out <= 0;
     else
       sync_clk_out <= 1;

@sync_clk_out 响应上升沿或 @clk而变为低。下降沿则相反。结果是输出时钟和频率相同。

但是,这段 Verilog 代码无法与大多数综合工具(synthesizers)兼容,因为逻辑阵列(logic fabric)中的触发器通常无法同时对时钟边沿(clock edges)敏感。只有 IOB 寄存器才具备这种能力,而综合工具很少聪明到能够理解这种可能性。

因此,需要例化(instantiation)或逻辑 primitive (logic primitive)。 primitive 特定于所使用的 FPGA 。此示例显示了如何为 Kintex Ultrascale完成此操作:

ODDRE1 ODDR_ins
     (.C(clk), .Q(sync_clk_out),
      .D1(1'b0), .D2(1'b1),
      .SR(1'b0));

但现在时钟是用输出 DDR register 生成的,而数据信号(data signals)是用常规 IOB 寄存器生成的。数据和时钟之间的对齐并不像以前那么明显。因此,重要的是阅读所有输出的时序报告(timing reports),并验证时延(delays)之间的差异是否足够小。

也可以将输出 DDR registers (output DDR registers)用于数据: 如果给 D1 和 D2赋予相同的值,则输出对每个时钟周期(clock cycle)只改变一次:

module top (
   input clk,
   output [7:0] data_out,
   output sync_clk_out
);

   reg [7:0]  data;

   ODDRE1 ODDR_ins
     (.C(clk), .Q(sync_clk_out),
      .D1(1'b0), .D2(1'b1),
      .SR(1'b0));

   ODDRE1 ODDR_data_ins [7:0]
     (.C(clk), .Q(data_out),
      .D1(data), .D2(data),
      .SR(1'b0));

   always @(posedge clk)
     data <= data + 1;
endmodule

此方法确保数据和时钟对齐。输出 DDR registers 的显式例化也确保使用 IOB 寄存器。这种方法的唯一缺点是它特定于每 FPGA。

请注意,输出 DDR registers 的行为可能出乎意料且令人困惑。例如,注意 @data 与 @clk的 positive 边沿是同步的。但是 ODDRE1 在两个时钟边沿上都是活跃的。请务必阅读 FPGA 的文档,了解如何以及何时对两个数据输入(data inputs)进行采样。

另请注意,此示例中未使用复位(reset)。这可能是不安全的,特别是在复杂的 FPGAs上: 输出 DDR register 可以是 IOB内部更复杂的逻辑单元(logic element)的一部分。如果没有复位,此类逻辑单元可能无法正常运行。

时序约束(Timing constraints)

那么这种方法需要时序约束吗?如果时钟输出(clock output)和数据输出由于使用 IOB 寄存器而几乎完美对齐,这还不够吗?

答案是即使没有时序约束,这种方法也可以完美地工作。然而,利用时序约束仍然是个好主意。原因与关于 IOB 寄存器的页面中的相同主题相同。

其他注意事项

但是,使用 IOB 寄存器并不是唯一要确保的事情: 还要注意输出端口之间的物理距离。如果输出端口彼此相距较远,则此物理距离可能会对时钟偏移(clock skew)和 FPGA产生不良影响。 traces (即线(wires)和电路板)的长度差异也会产生负面影响。此外,所有输出的电气参数(电压、 I/O 标准、压摆率(slew rate)、 drive current 等)应相同。

如果 FPGA 没有 IOB 寄存器,那么时序约束就变得至关重要: 使用 source-synchronous 输出的基础是能够确保所有相关输出端口之间的低偏移(skew)。在触发器和 I/O 引脚之间控制时延通常就足够了: 如果此时延接近相关 FPGA可能的最小值,则输出之间的差异对于大多数用途而言足够小。

双向 I/O

source-synchronous 输出的主要特点是相关的时钟是由 FPGA生成的。当所有数据信号都指向外部组件时,这显然是合适的。但即使在两个方向上都有数据信号,依赖 FPGA生成的时钟也是有意义的。

但是请注意,数据输入(data inputs)与电路板上的时钟同步,而不是 FPGA 芯片内的时钟。当然,这两个时钟具有完全相同的频率。但存在一个时间差,这取决于输出端口的 clock-to-output 时延。这可能是几纳秒。

因此建议在电路板上做一个回环(loopback): 将 FPGA的时钟输出连接到输入端口。可以将此输入端口视为system synchronous 时钟 : 外部组件的行为就好像它的时钟来自专用的 oscillator,而不是来自 FPGA。这类似于system synchronous 时钟 ,因为 FPGA 和外部组件都依赖于电路板上的相同物理信号。

Source synchronous bidirectional data with loopback of clock

也可以将数据输入视为source-synchronous 输入 。特别是,如果使用相位 shifting (phase shifting)技术,则不需要时钟回环(clock loopback)。这实际上是与 DDR SDRAM memories接口的常用方式。

重要的结论是在电路板制造之前仔细规划输入信号的时序,必要时考虑增加一个时钟回环(clock loopback)。

此页面由英文自动翻译。 如果有不清楚的地方,请参考原始页面
Copyright © 2021-2024. All rights reserved. (b4b9813f)