我在如何制作时钟分频器时发现了这段代码。我对如何使用计数器制作分频器有一个大致的了解,但我不确定这个代码在做什么以及它为什么这样做。
entity clkdiv is
Port ( mclk : in STD_LOGIC;
clr : in STD_LOGIC;
clk190 : out STD_LOGIC;
clk48 : out STD_LOGIC);
end clkdiv;
architecture clkdiv of clkdiv is
signal q: std_logic_vector(23 downto 0);
begin
--clock divider
process(mclk,clr)
begin
if clr ='1' then
q <= X"000000";
elsif mclk'event and mclk = '1' then
q <= q+1;
end if;
end process;
clk48 <= q(19);
clk190 <= q(17);
end clkdiv;
我知道这个例子是基于2板,输入时钟是50MHz。该代码应该产生48hz时钟信号和190hz时钟信号。
答案 0 :(得分:2)
50MHz / 48Hz = 104166.7,所以你无法准确到达那里。
如果您使用的计数器在50MHz时计数高达104167,您将获得接近48 Hz的单脉冲(47.9999846 Hz - 这对于大多数用途来说可能已经足够了)。
不要将计数器的输出用作时钟,当它作为时钟启用时使用单个脉冲 - 这样可以获得更好的结果。整个设计中的单个时钟与启用的部分是实现它的方法。
答案 1 :(得分:1)
上述代码的作用仅仅是它创建了一个包含24位计数器q
的VHDL模块,该计数器在主时钟mclk
的每个上升沿计数。然后通过将此计数器的不同位直接用作时钟信号,它导出clk190
和clk48
。
例如,当mclk
为50 MHz时,lsb(q(0)
)将有效地以25 MHz运行。 mclk
的每个上升沿为q(0)
提供一条边 - 同样向上,因此每个后续位的运行频率都是前一位的一半。
例如:
mclk = 50 MHz
q(0) = mclk / 2 = 25 Mhz
q(1) = q(0) / 2 = mclk / 4 = 12.5 MHz
...
q(n) = mclk / (2^(n+1))
您的派生时钟将取决于您的主时钟,并且是:
q(17) = 50 MHz / 262144 = 191 Hz
q(19) = 50 MHz / 1048576 = 48 Hz
然而 - 生成这样的时钟往往是错误的做法!
看起来好像你得到了很好的同步时钟,但实际上,它们相互之间会稍微偏斜,因为你正在生成所谓的门控时钟(许多工具甚至会警告你这个)。
此处有更多信息,包括使用时钟启用相同功能(但更好)的方法:VHDL: creating a very slow clock pulse based on a very fast clock