dav*_*od2 5 spartan conventions clock vhdl xilinx-ise
在过去,我问了一个关于复位的问题,以及如何将高时钟频率分解为一系列较低时钟的方波频率,其中每个输出是彼此的谐波,例如第一个输出是10 Hz,第二个是20 Hz等等
我收到了几个非常有用的答案,建议使用时钟使能引脚创建较低频率的惯例.
我发生了另一种选择; 使用不断递增的位数,并将该数字的最后x位作为时钟输出,其中x是输出的数量.
它在我的综合中起作用 - 但我很想知道 - 因为我从未在网上或在SO上提到它,我错过了一些意味着它实际上是一个糟糕的想法,我只是为了以后创造问题?
我知道对此的限制是我只能产生输入频率除以2的幂的频率,所以大部分时间它只能接近所需的输出频率(但仍然是正确的)订购).这种限制是不推荐的唯一原因吗?
非常感谢!
大卫
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;
library UNISIM;
use UNISIM.VComponents.all;
use IEEE.math_real.all;
ENTITY CLK_DIVIDER IS
GENERIC(INPUT_FREQ : INTEGER; --Can only divide the input frequency by a power a of 2
OUT1_FREQ : INTEGER
);
PORT(SYSCLK : IN STD_LOGIC;
RESET_N : IN STD_LOGIC;
OUT1 : OUT STD_LOGIC; --Actual divider is 2^(ceiling[log2(input/freq)])
OUT2 : OUT STD_LOGIC); --Actual output is input over value above
END CLK_DIVIDER;
architecture Behavioral of Clk_Divider is
constant divider : integer := INPUT_FREQ / OUT1_FREQ;
constant counter_bits : integer := integer(ceil(log2(real(divider))));
signal counter : unsigned(counter_bits - 1 downto 0) := (others => '0');
begin
proc : process(SYSCLK)
begin
if rising_edge(SYSCLK) then
counter <= counter + 1;
if RESET_N = '0' then
counter <= (others => '0');
end if;
end if;
end process;
OUT1 <= counter(counter'length - 1);
OUT2 <= not counter(counter'length - 2);
end Behavioral;
Run Code Online (Sandbox Code Playgroud)
从功能上讲,两个输出OUT1可以OUT2用作时钟,但是这种制作时钟的方法无法扩展,并且很可能在实现中引起问题,因此这是一个坏习惯。然而,理解为什么会这样当然很重要。
它无法扩展的原因是,FPGA 中用作时钟的每个信号都将通过一个特殊的时钟网络进行分配,其中延迟和偏斜是明确定义的,因此每个时钟上的所有触发器和存储器都会同步更新。此类时钟网络的数量非常有限,在 FPGA 器件中通常在 10 到 40 个范围内,并且对使用和位置的一些限制使得规划时钟网络的使用通常变得更加重要。因此,通常需要仅为真正的异步时钟保留时钟网络,除了使用时钟网络之外别无选择。
它可能导致问题的原因是基于计数器中的位创建的时钟没有保证的时序关系。因此,如果需要在这些时钟域之间移动数据,则需要额外的同步约束,以确保正确处理时钟域交叉 (CDC)。这是通过综合和/或静态时序分析 (STA) 的约束来完成的,并且通常很难做到正确,因此使用简化 STA 的设计方法是节省设计时间的习惯。
因此,在可以使用公共时钟,然后生成同步时钟使能信号的设计中,这应该是首选方法。对于上述具体设计,可以简单地通过检测相关位的转变来'0'生成时钟使能,然后在检测到转变的单个周期中断言时钟使能。然后可以使用单个时钟网络以及 2 个时钟使能(如和 ),并且不需要特殊的 STA 约束。'1'counterCE1CE2
| 归档时间: |
|
| 查看次数: |
928 次 |
| 最近记录: |