我想弄清楚为什么简单计数器的输出不稳定。我使用的是基于 GW2A-LV18PG256C8/I7 FPGA 的 Sipeed Tang Primer 20k 开发板。我创建了简单的项目,它使用时钟分频器从输入 27 Mhz 全局时钟获取输出时钟 ~5.5 Mhz。
counter_tester.vhd
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity counter_tester is
port(
CLK_IN_27MHZ : in STD_LOGIC;
PROCESSOR_RST : in STD_LOGIC;
BT656_OUT : out STD_LOGIC_VECTOR(7 downto 0);
BT656_LLC_OUT : out STD_LOGIC
);
end counter_tester;
architecture counter_tester of counter_tester is
---- Component declarations -----
component Gowin_CLKDIV
port(
hclkin : in STD_LOGIC;
resetn : in STD_LOGIC;
clkout : out STD_LOGIC
);
end component;
component my_counter
port(
CLK : in STD_LOGIC;
RST : in STD_LOGIC;
Q : out STD_LOGIC_VECTOR(7 downto 0)
);
end component;
---- Signal declarations used on the diagram ----
signal NET672 : STD_LOGIC;
signal NET693 : STD_LOGIC;
begin
---- Component instantiations ----
U1 : my_counter
port map(
CLK => NET672,
RST => NET693,
Q => BT656_OUT
);
NET693 <= not(PROCESSOR_RST);
U4 : Gowin_CLKDIV
port map(
hclkin => CLK_IN_27MHZ,
resetn => PROCESSOR_RST,
clkout => NET672
);
---- Terminal assignment ----
-- Output\buffer terminals
BT656_LLC_OUT <= NET672;
end counter_tester;
这是计数器本身的代码: my_counter.vhd
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity my_counter is
port(
CLK : in STD_LOGIC;
RST : in STD_LOGIC;
Q : out STD_LOGIC_VECTOR(7 downto 0)
);
end my_counter;
architecture my_counter of my_counter is
signal s_Q_OUT: UNSIGNED (7 downto 0);
begin
Q <= STD_LOGIC_VECTOR(s_Q_OUT);
process( CLK )
begin
if (rising_edge(CLK)) then
if (RST = '1') then
s_Q_OUT <= (others => '0');
else
if(s_Q_OUT = x"FF") then
s_Q_OUT <= (others => '0');
else
s_Q_OUT <= s_Q_OUT + 1;
end if;
end if;
end if;
end process;
end my_counter;
我还可能包含Gowin生成的时钟分频器模块的代码,但它没有什么有趣的,它只是工作: Gowin_CLKDIV.vhd
--Copyright (C)2014-2024 Gowin Semiconductor Corporation.
--All rights reserved.
--File Title: IP file
--Tool Version: V1.9.9.02
--Part Number: GW2A-LV18PG256C8/I7
--Device: GW2A-18
--Created Time: Sun Jul 21 23:14:25 2024
library IEEE;
use IEEE.std_logic_1164.all;
entity Gowin_CLKDIV is
port (
clkout: out std_logic;
hclkin: in std_logic;
resetn: in std_logic
);
end Gowin_CLKDIV;
architecture Behavioral of Gowin_CLKDIV is
signal gw_gnd: std_logic;
--component declaration
component CLKDIV
generic (
GSREN: STRING := "false";
DIV_MODE : STRING := "2"
);
port (
CLKOUT: out std_logic;
HCLKIN: in std_logic;
RESETN: in std_logic;
CALIB: in std_logic
);
end component;
begin
gw_gnd <= '0';
clkdiv_inst: CLKDIV
generic map (
GSREN => "false",
DIV_MODE => "5"
)
port map (
CLKOUT => clkout,
HCLKIN => hclkin,
RESETN => resetn,
CALIB => gw_gnd
);
end Behavioral; --Gowin_CLKDIV
FPGA 中除一个引脚外的所有输出均配置为使用相同的 IO 组:
我将采样频率为 100 Mhz 的逻辑分析仪连接到输出引脚。首先,这是我们在 DSLogic 分析仪上得到的整体图像。正如我们所看到的,计数器在一般情况下会递增:
在这里我们看到时钟频率仅为~5 Mhz。在解码器设置中,我选择在时钟 BT656_LLC_OUT 的上升沿解码数据。
但是计数器经常会丢失输出值。一些数据通道在时钟上升沿 20 ns 后发生变化。我放置了两个标记,在右下角我们可以看到计算出的时间差。
我为每个数据通道添加了颜色并对其进行缩放以更清晰地展示:
D5 行与 BT656_LLC_OUT 更改 0 -> 1 同时更改 0 -> 1 但所有其他行仅在 20 ns 后才从 0 变为 1!我觉得无稽之谈。该计数器在时钟上升沿产生太多错误值。有谁知道这可能是什么原因?我几天来一直在努力寻找解决方案...
这是我的开发板如何与逻辑分析仪连接。连接探针的板未通过 FFC 连接到其他板(ADV7391 编码器)
我还在Gowin EDA中设置了时序约束: fpga_project_4.sdc
create_clock -name CLK_IN_27MHZ -period 37.037 -waveform {0 18.518} [get_ports {CLK_IN_27MHZ}] -add
将不胜感激任何帮助!
我还尝试将输出分配移到rising_edge(clk)下的进程内,但结果是相同的。只需要在GowinEDA中增加寄存器即可
UPD:同样在创建这个主题之后,我有一个关于在输出上添加 8 位 D 寄存器的想法,该寄存器将在反向时钟上工作 - 在下降沿。像这样:
所以我添加了它并用真实的 FPGA 进行了测试。真是哇!输出中没有错误的数字,只是一些数字电子大学书籍中的完美计数器!
在 FPGA 设计中添加带有反向时钟的附加输出寄存器到输出是正常做法吗?
在真实的硬件上,您永远不会有多个输出在完全相同的时间点发生变化。尤其是当您测量不同的值变化(从 0 到 1 以及从 1 到 0)时尤其如此,因为在数字化实际模拟电压时硬件行为不同。
这就是现实、电子学和物理。
即使您像以前那样添加寄存器,也会有时序差异。
因此,您必须忍受触发时钟沿之后无效值的“毛刺”。没有办法避免它们。
“after”一词已经说明了为什么添加具有反转时钟的输出寄存器并不常见。常见的做法是使用一个时钟的同步设计。
逻辑的下一个阶段将在“下一个”时钟沿获取当前阶段的输出。不同的传播延迟并不重要,因为当前时钟沿是“在”电平变化之前。下一阶段看到以前的值。 只需确保您的时钟不会太快以满足下一阶段的设置时间。顺便说一句,通过插入的寄存器,您可以将此最大频率降低到 50%,因为该寄存器在 50% 的时钟周期后需要稳定的电平。不过,你的设计似乎很慢。
您的观察结果基于低采样率的单次测量。采样时钟与设计时钟无关。当信号变化的同时采样时,它可以随机是旧的或新的水平。每个信号上始终会有一个采样周期的抖动。
这可能是您测量的场景:
____________________
Actual clock ____/ | | |
| |_____|_____|___
Actual D5 ___|____/| | |
___|_____|_____| |
Actual D4 | | |\____|___
| | | |
Sample trigger X X X X
_______________
Sampled clock _________/
_______________
Sampled D5 _________/
_____________________
Sampled D4 \___
提高采样率,你会发现间隔变短了。进行多次测量,您会发现不同的延迟。