samarawickrama写道:
1)为什么Xilinx DCM级联无法满足时序约束?
有没有办法解决这个问题?
阅读数据表。
我不认为任何Xilinx FPGA系列的DCM都可以使用低至6.144 MHz的时钟输入,当然它们都不能输出48 kHz时钟。
所以并不是说你没有达到时间限制;
我打赌这些工具会抛出不同的错误。
请发布确切的错误消息。
2)有没有办法在VHDL中实现时钟分频而不降低工作频率?
6.144 MHz是一个非常低的频率,你不能满足时间安排。
也许你有很多组合逻辑?
更多 ...
采用时钟并用计数器将其分频是合理的,并将切换位用作时钟。
当你这样做时,你必须意识到一些事情。
您必须确保分频时钟位于全局时钟缓冲区上。
合成后,检查报告以查看它是否已放入全球网络。
只要触发位不是触发器时钟,合成器应该做正确的事情。
但如果没有,那就很容易在网上实例化一个BUFG。
以通常的方式将PERIOD约束放在分频时钟上。
请注意,分频时钟与产生它的时钟稍有延迟。
这是由于切换位的时钟到输出以及到达全局时钟缓冲器的延迟。
这意味着当您从高频时钟跨越时钟域到分频时钟时,您必须考虑该延迟。
为了处理关于延迟的最后一点,通常建议不要使用计数器并切换一点并使用切换位作为时钟。
相反,你应该做的是进行计数,当计数终止时,在一个时钟周期内选通一个新位。
喜欢这个:
常数DIVPERIOD:自然:= 128;
signal clk48kHzEnable:std_logic_vector:='0';
myClkEnable:process(clk)是
变量divcnt:自然范围(0到DIVPERIOD - 1):= 0;
开始
如果rising_edge(clk)那么
如果divcnt = 0那么
clk48kHzEnable
其他
clk48kHzEnable
万一;
divcnt:=(divcnt + 1)mod DIVPERIOD;
万一;
结束进程myClkEnable;
现在,在其余逻辑中,需要在48 kHz时钟上运行的所有内容都应使用该启用:
myLogic:进程(clk)是
开始
如果rising_edge(clk)那么
at48kHz:如果clk48kHzEnable ='1'那么
.. 做东西
如果在48kHz时结束;
万一;
结束过程myLogic;
你应该在clk48kHzEnable启用的所有内容上创建一个多周期约束。
----------------------------是的,我这样做是为了谋生。
以上来自于谷歌翻译
以下为原文
samarawickrama wrote:
1) Why Xilinx DCM cascading failed to meet the timing constrains? Is there a way to solve this problem?
Read the data sheet. I don't think any Xilinx FPGA family's DCM can work with a clock input as low as 6.144 MHz, and certainly none of them can output a 48 kHz clock. So it's not that you're not meeting timing constraints; I bet the tools are throwing a different error. Post the exact error message, please.
2) Is there a way I can implement clock division in VHDL without degrading the operating frequency?
6.144 MHz is quite a low frequency and it's a surprise that you're not meeting timing. Perhaps you have a ton of combinatorial logic?
More ...
It's reasonable to take a clock and divide it down with a counter as you do, and to use the toggling bit as a clock. When you do this, you have to realize a few things.
- You must make sure that your divided clock is on a global clock buffer. After synthesis, check the report to see that it was put onto a global net. As long as that toggling bit goes nowhere other than to flip-flop clocks, the synthesizer should do the right thing. But if it doesn't, it's easy enough to instantiate a BUFG on that net.
- Put a PERIOD constraint the divided clock in the usual way.
- Note that the divided clock is slightly delayed from the clock from which it is generated. This is due to the clock-to-out on the toggling bit and the delay getting to the global clock buffer. This means that when you cross the clock domain from the higher-frequency clock to the divided clock, you must account for that delay.
To handle the last point about the delay, the usual recommendation is to not take a counter and toggle a bit and use the toggling bit as a clock. Instead, what you should do is to do the count, and when the count terminates, strobe a new bit for one clock cycle. Like this:
constant DIVPERIOD : natural := 128;
signal clk48kHzEnable : std_logic_vector := '0';
myClkEnable : process (clk) is
variable divcnt : natural range (0 to DIVPERIOD - 1) := 0;
begin
if rising_edge(clk) then
if divcnt = 0 then
clk48kHzEnable <= '1';
else
clk48kHzEnable <= '0';
end if;
divcnt := (divcnt + 1) mod DIVPERIOD;
end if;
end process myClkEnable;
Now in the rest of your logic, everything that needs to run on the 48 kHz clock should use that enable:
myLogic : process (clk) is
begin
if rising_edge(clk) then
at48kHz : if clk48kHzEnable = '1' then
.. do stuff
end if at48kHz;
end if;
end process myLogic;
and you should create a multicycle constraint on everything which is enabled by
clk48kHzEnable.
----------------------------Yes, I do this for a living.