Vhdl 制作时钟分频器
我在如何制作时钟分频器中找到了这段代码。我对如何使用计数器生成除法器有一个大致的了解,但我不确定这段代码在做什么以及为什么要这样做Vhdl 制作时钟分频器,vhdl,clock,Vhdl,Clock,我在如何制作时钟分频器中找到了这段代码。我对如何使用计数器生成除法器有一个大致的了解,但我不确定这段代码在做什么以及为什么要这样做 entity clkdiv is Port ( mclk : in STD_LOGIC; clr : in STD_LOGIC; clk190 : out STD_LOGIC; clk48 : out STD_LOGIC); end clkdiv; architecture clkd
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;
实体clkdiv是
端口(mclk:标准逻辑中;
clr:标准逻辑中;
clk190:输出标准逻辑;
clk48:输出标准逻辑);
结束clkdiv;
clkdiv的体系结构clkdiv是
信号q:std_逻辑_向量(23向下至0);
开始
--时钟分频器
进程(mclk、clr)
开始
如果clr='1',则
q上述代码的作用很简单,它创建了一个VHDL模块,其中包含一个24位计数器q
,该计数器从主时钟mclk
的每个上升沿开始计数。然后,它通过直接使用此计数器的不同位作为时钟信号来导出clk190
和clk48
例如,在50 MHz下使用mclk
,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
然而,这样生成时钟通常是错误的强>
看起来好像你得到了很好的同步时钟,但实际上,它们之间的比较会有点偏差,因为你正在生成所谓的门控时钟(许多工具甚至会警告你这一点)
关于这方面的更多信息,包括一种使用时钟启用做同样事情(但更好)的方法:50MHz/48Hz=104166.7,因此您无法准确到达那里
如果您使用的计数器在50MHz时计数高达104167,您将获得接近48 Hz的单脉冲(47.9999846 Hz-这对于大多数用途来说可能足够好)
不要使用计数器的输出作为时钟,当它环绕时使用单个脉冲作为时钟启用-这样可以获得更好的结果。在整个设计中,使用一个带有启用部分的时钟是实现这一点的方法。因此,如果我使用的是100MHz时钟,我如何生成这些频率(190hz、48hz)有那么难看到吗?;)我之所以问这个问题,是因为我确实把位移到了左边,信号不好,这是我尝试的第一件事,我想我做错了什么,但是谢谢你的例子,你说的“信号不好”是什么意思?有多快?正如Martin在他的回答中提到的,你不能精确地命中那些频率……你的意思是像这样的“clkdiv的架构clkdiv是信号计数5Hz:std_逻辑_向量(从27下降到0):=(其他=>“0”);常数clk5HzEndVal:STD_逻辑_向量(27向下至0):=X“2FAF080”;begin——时钟除法器进程(mclk,clr)开始,如果(clr='1'),那么Count5Hz我不能将该代码理解为注释,但我建议使用整数类型,因为它比std_逻辑_向量更容易处理这类事情。你也可以使用编译器来计算所需频率和已知时钟频率的最终值,而不仅仅是难以检查的硬编码常量。如果使用xilinx中的ip核,是的,我不知道如何使用。不,不需要ip核,只需使用integer
类型编写VHDL