计数器输出与真实fpga中vhdl中的clk不同步

问题描述 投票:0回答:1

我想弄清楚为什么简单计数器的输出不稳定。我使用的是基于 GW2A-LV18PG256C8/I7 FPGA 的 Sipeed Tang Primer 20k 开发板。我创建了简单的项目,它使用时钟分频器从输入 27 Mhz 全局时钟获取输出时钟 ~5.5 Mhz。

顶层设计 counter_tester.vhd 如下所示: enter image description here

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 组: enter image description here

我将采样频率为 100 Mhz 的逻辑分析仪连接到输出引脚。首先,这是我们在 DSLogic 分析仪上得到的整体图像。正如我们所看到的,计数器在一般情况下会递增: enter image description here

现在让我们放大 enter image description here

在这里我们看到时钟频率仅为~5 Mhz。在解码器设置中,我选择在时钟 BT656_LLC_OUT 的上升沿解码数据。

但是计数器经常会丢失输出值。一些数据通道在时钟上升沿 20 ns 后发生变化。我放置了两个标记,在右下角我们可以看到计算出的时间差。

我为每个数据通道添加了颜色并对其进行缩放以更清晰地展示:

enter image description here

D5 行与 BT656_LLC_OUT 更改 0 -> 1 同时更改 0 -> 1 但所有其他行仅在 20 ns 后才从 0 变为 1!我觉得无稽之谈。该计数器在时钟上升沿产生太多错误值。有谁知道这可能是什么原因?我几天来一直在努力寻找解决方案...

这是我的开发板如何与逻辑分析仪连接。连接探针的板未通过 FFC 连接到其他板(ADV7391 编码器) enter image description here

我还在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 寄存器的想法,该寄存器将在反向时钟上工作 - 在下降沿。像这样: enter image description here

所以我添加了它并用真实的 FPGA 进行了测试。真是哇!输出中没有错误的数字,只是一些数字电子大学书籍中的完美计数器!

在 FPGA 设计中添加带有反向时钟的附加输出寄存器到输出是正常做法吗?

vhdl fpga
1个回答
0
投票

在真实的硬件上,您永远不会有多个输出在完全相同的时间点发生变化。尤其是当您测量不同的值变化(从 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 \___

提高采样率,你会发现间隔变短了。
进行多次测量,您会发现不同的延迟。
  • 你会发现你的寄存器也有这些故障。

© www.soinside.com 2019 - 2024. All rights reserved.