【发布时间】:2013-08-07 02:38:56
【问题描述】:
我正在创建一个可变频率脉冲序列来控制电机,并使用以下代码使用计数器生成脉冲,该计数器按某个输入增量值inc_i 进行计数。然后,我将计数器输出的 MSB dout_o[N-1] 通过管道传输到我的 FPGA 上的输出引脚。这应该给我一个所需频率的 50% 占空比方波,但我只是看到一个信号开始变低,变高,然后再也不会关闭。我的代码有明显的问题吗?
--****************************************************************************
-- Load required libraries
--****************************************************************************
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
--****************************************************************************
-- Define the inputs, outputs, and parameters
--****************************************************************************
entity var_count is
generic(N: integer :=32); -- for generic counter size
port(
inc_i : in std_logic_vector(N-1 downto 0);
load_i : in std_logic;
clk_i : in std_logic;
clear_i : in std_logic;
clk_en_i : in std_logic;
count_en_i : in std_logic;
msb_o : out std_logic
);
end var_count;
--****************************************************************************
-- Define the behavior of the counter
--****************************************************************************
architecture behavior of var_count is
-- Define our count variable. No need to initialize in VHDL.
signal count : unsigned(N-1 downto 0) := to_unsigned(0, N);
signal incr : unsigned(N-1 downto 0) := to_unsigned(0, N);
begin
-- Define our clock process
clk_proc : process(clk_i, clear_i, load_i)
begin
-- Asynchronous clear
if clear_i = '1' then
count <= to_unsigned(0, N);
end if;
-- Asynchronous load
if load_i = '1' then
incr <= unsigned(inc_i);
end if;
-- Define processes synch'd with clock.
if rising_edge(clk_i) and clk_en_i = '1' then
if count_en_i = '1' then -- increment the counter
count <= count + incr;
end if;
end if;
end process clk_proc;
-- Output the MSB for the sake of generating a nice easy square wave.
msb_o <= count(count'left);
end behavior;
对于 N 位计数器,方波频率应由公式 pulse_freq = clock_freq * inc_i / 2^N 给出。
我还试图通过将我的计数器输出 (msb_o(k)) 的 MSB 通过一位 D-Q 触发器来生成单个时钟周期脉冲以获取 msb_o(k-1),然后执行:
pulse = ~msb_o(k) * msb_o(k-1)
其中~ 表示逻辑NOT,* 表示逻辑AND。这应该只在计数器翻转时给我一个时钟周期脉冲。当我使用示波器读取输出引脚时,这和 MSB 本身(50% 占空比方波)都没有显示。如果您在我的代码中发现任何错误,请告诉我。
感谢您的帮助!
可以找到我用来将这些放在一起的参考资料 here、here 和 here。
编辑 1:我已根据用户提出的建议更新了问题中的代码。现在,当我输出计数器的 MSB 时,它会变高并且永远不会再次关闭。我需要在溢出时重置计数器(我在上面尝试过这样做)。关于如何做到这一点的任何建议?
编辑 2: 我意识到,由于我的增量值 inc_i 不一定是 1,因此对于翻转计算,我可能无法达到 2**N - 1 的值。因此,我将翻转条件更改为:
if count > (2**N - unsigned(inc_i) - 1) then
count <= to_unsigned(0, N);
我现在似乎得到了脉冲,但它们并不完全是 50% 的占空比(我认为这是有道理的),当我更改增量值 inc_i 时,它们似乎没有按预期改变。知道为什么费率没有变化吗?
编辑 3: 我意识到我对我的应用程序所关心的只是计数器的 MSB,因为我将使用它来生成 50% 占空比的方波,或者翻身时脉动。鉴于此,我将实体声明中的dout_o 替换为:
`msb_o : out std_logic`
我将最后的并发赋值语句替换为:
msb_o <= '1' when count > (2**(N-1) - 1) else '0';
我仍然收到非常奇怪的脉冲,它们根本不是 50% 的占空比或不一定是正确的频率。任何进一步的建议将不胜感激。
编辑 4: 更新了我的代码并进行了进一步的更改。还将this free book 添加到引用列表中。
编辑 5:将我的代码更新为(最终)工作版本。
【问题讨论】:
-
模拟是否按预期工作?
-
@BrianDrummond 我不确定如何理解模拟,因为使用它的整个程序非常庞大。我对所有的逻辑信号都有点迷失。我将尝试在模拟中找出这些信号的行为并返回结果。
-
执行单元测试是值得的——也许不是在大型项目的每个组件上——但也许是其中的大部分,而且绝对是像这样的关键测试。一个简单的测试台可用于以在顶级测试中难以安排的方式对组件施加压力,并获得答案,通常比等待 StackExchange 帖子更快!