我正在创建一个可变频率脉冲序列来控制电机,并使用以下代码使用计数器生成脉冲,该计数器按一些输入增量值inc_i
计数。然后,我将计数器dout_o[N-1]
输出的MSB传送到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通过单位DQ触发器来生成单个时钟周期脉冲,以获得msb_o(k-1)
,然后执行:
pulse = ~msb_o(k) * msb_o(k-1)
其中~
代表逻辑NOT
,*
代表逻辑AND
。这应该只在计数器翻转时给我一个时钟周期脉冲。当我使用示波器读取输出引脚时,这个和MSB本身(50%占空比方波)都没有出现。如果您在我的代码中发现任何错误,请通知我。
感谢您的帮助!
编辑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:将我的代码更新为(最终)工作版。
答案 0 :(得分:3)
该流程不符合要识别的流程的一般规则 合成工具的触发器,因为条件的外层确实如此 不覆盖过程灵敏度列表中的信号。综合工具有 可能会给出一个或多个警告。
重写流程以遵守可合成的一般规则的一种方法 人字拖鞋是:
clk_proc : process (CLK)
begin
if (CLK'event and CLK = '1') then
if CLEAR = '1' then -- clear the counter
COUNT <= COUNT - COUNT;
elsif CLK_EN = '1' then -- increment the counter
COUNT <= COUNT + INC;
end if;
end if;
end process clk_proc;
这将时钟边缘的检查放在外层,并假定为 CLEAR是同步的。
例如,有关寄存器的VHDL编码风格的更多信息 Xilinx XST User Guide
您对单个时钟周期脉冲的描述看起来不错,所以原因就在于此 它不起作用可能源于上述。
可以考虑对模块进行更大的重写,以便应用这些 有用的VHDL编码规则:
(others => '0')
清除,而不是COUNT - COUNT
,因为这有效
在模拟中,即使COUNT都是X的以下代码中的示例:
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity var_count is
port(
inc_i : in std_logic_vector(31 downto 0);
clk_i : in std_logic;
clear_i : in std_logic;
clk_en_i : in std_logic;
dout_o : out std_logic_vector(31 downto 0));
end var_count;
architecture behavior of var_count is
-- Define our count variable
signal count : std_logic_vector(31 downto 0);
begin
-- Define our clock process
clk_proc : process (clk_i)
begin
if rising_edge(clk_i) then
if clear_i = '1' then -- clear the counter
count <= (others => '0');
elsif clk_en_i = '1' then -- increment the counter
count <= std_logic_vector(unsigned(count) + unsigned(inc_i));
end if;
end if;
end process clk_proc;
-- Concurrent assignment statement
dout_o <= count;
end behavior;
如果您还没有使用模拟器,那么ModelSim可能很棒 改进你的工具箱。 Alera有ModelSim-Altera Starter Edition 这是免费的,可以用于小型设计。
答案 1 :(得分:2)
CLEAR
不敏感,IEEE.numeric_std.all
会在此过程中读取。我假设你想要一个异步CLEAR。COUNT-COUNT
直接添加,建议在不同工具之间兼容。(others => '0')
将它们全部驱动为零时,重置寄存器library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity VAR_COUNT is
port(
INC : in std_logic_vector(31 downto 0);
CLK : in std_logic;
CLEAR : in std_logic;
CLK_EN : in std_logic;
DOUT : out std_logic_vector(31 downto 0)
);
end VAR_COUNT;
architecture behavior of VAR_COUNT is
-- Initialising a signal has no effect in hardware
signal COUNT:std_logic_vector(31 downto 0) := x"00_00_00_00";
-- Define our clock process, your clocked process was not senstive to CLEAR
begin clk_proc:process(CLK,CLEAR)
begin
if CLEAR = '1' then -- clear the counter
COUNT <= (others=>'0'); --always use this to reset
elsif CLK_EN = '1' then -- increment the counter
if (CLK'EVENT AND CLK = '1') then
COUNT <= std_logic_vector(unsigned(COUNT) + unsigned(INC));
end if;
end if;
end process clk_proc;
-- concurrent assignment statement
DOUT <= COUNT;
end behavior;
没有意义。请参阅下面的代码。
{{1}}