我正在使用的逻辑设置为期望差分对时钟端口。但是,对于一个特定应用,我只能输入单端时钟(由于硬件限制)。修改逻辑以接受单端时钟不是一种选择,因为涉及许多文件和代码行。有没有办法我可以输入一个单端口,并以某种方式将它馈送到模块的差分对端口?所以例如在我的顶级我想要一个像这样的端口:
input single_ended_clk
我想将它提供给一个带有以下端口的模块:
input diff_pair_clk_p;
input diff_pair_clk_n;
一种非常天真的方法是:
mymodule m_i (
.diff_pair_clk_p(single_ended_clk),
.diff_pair_clk_n(~single_ended_clk),
);
但我不认为这是正确的方法。
答案 0 :(得分:2)
大多数芯片设计,无论是ASIC还是FPGA,都明确地实例化时钟缓冲器而不是推断它们。在FPGA领域,合成引擎通常不够智能,无法识别时钟并将缓冲器输出挂接到专用时钟布线资源。所以你真的可能需要显式实例化一个时钟缓冲区。
现在,有时您需要单端时钟缓冲器,有时您需要双边沿时钟缓冲器。虽然您可以使用引用参数的generate语句来决定实例化哪个缓冲区,但您无法通过这种方式控制芯片的端口列表。您可以将时钟缓冲区保留在较低级别的模块中。
我不建议在芯片内重建差分信号。这有几个问题。首先,差分时钟缓冲器需要连接到外部引脚,而不是内部缓冲信号。其次,正负时钟之间存在时序不匹配,这可能会在缓冲区产生的时钟上产生毛刺,这会使您的设计变得非常混乱。
相反,将_n和_p输入保留到子模块,并使用generate选择要实例化的时钟缓冲区的类型。在单端时钟的情况下,_n输入保持未连接状态,仅使用_p输入。
以下是Xilinx FPGA的示例。缓冲区原型在其他类型的FPGA或ASIC库中的命名方式不同。
module clock_buffer (
input pin_clk_p,
input pin_clk_n,
output clk_int
);
parameter DIFF = 0;
generate
if (DIFF = 1)
clk_buf IBUFGDS(
.I (pin_clk_p),
.IB (pin_clk_n),
.O (clk_int)
);
else
clk_buf IBUFG(
.I (pin_clk_p),
.O (clk_int)
);
endgenerate
endmodule
答案 1 :(得分:1)
会有相位偏移,可能在容差范围内。如果不知道差分配对时钟和单个时钟的时序要求,时钟树的处理方式,缓冲器和逆变器的时序,很难说。您可以通过识别时钟和那里的关系从合成器中处理这个问题。为此,请在适当的层次结构级别单独分配时钟,也可以是自己的子模块。 diff_pair_clk_p
和single_ended_clk
在功能上是相同的,但它们应分开以实现负载平衡和时钟树平衡。
assign diff_pair_clk_p = single_ended_clk;
assign diff_pair_clk_n = ~single_ended_clk;
有时,预定义的模块是标准/宏单元库的一部分,旨在解决或简化特定的设计挑战。在需要时实例化这些模块,可能需要 dont_touch pragma。特别寻找描述为对称缓冲器和逆变器的电池。您可能仍需要为合成器提供额外的指导。