【问题标题】:Where does the error stem from in the process?过程中的错误来自哪里?
【发布时间】:2014-09-04 11:27:15
【问题描述】:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.all;


entity reset40 is
Port (  CLOCK : in  STD_LOGIC;  --50MHz
        CIKIS : out STD_LOGIC


        );

end reset40;

architecture Behavioral of reset40 is

    signal A:std_logic;
begin

    process(CLOCK)  --line20

        variable fcounter: unsigned(24 downto 0);
        variable counter_A:integer range 0 to 40:=0;

    begin

        if rising_edge (CLOCK) then   
            fcounter := fcounter+1;         
        end if;

        A<=fcounter(6);           --fa=fclock/2^6

        if ((rising_edge (A)) and (counter_A/=40)) then  
            counter_A:= counter_A+1;              
            CIKIS<=A;
        else
            CIKIS<='0';
        end if;

    end process;
end Behavioral;

ERROR:Xst:827 - "C:/Users/reset40/reset40.vhd" 第 20 行:CIKIS 信号 无法合成,同步描述不好。说明 您用来描述同步元素的样式(寄存器, 当前软件版本不支持内存等)。

关于时钟的错误是什么?怎么会是“糟糕的同步描述”?

【问题讨论】:

    标签: if-statement vhdl fpga


    【解决方案1】:

    您的基本错误是进程中的所有代码只需要在时钟的上升沿运行。这是因为目标芯片只有一个可以响应的触发器。

    由于这一行,您编写的进程对clock 的更改很敏感:

    process(clock)
    

    所以它对两个时钟边沿都很敏感。

    然后你把部分代码放在一个

    if rising_edge(clock) then
    

    这将活动限制在上升沿,这很好。不幸的是,您的其余代码不在if 子句之外,因此被描述为在时钟的每个边沿上运行,无论是上升沿还是下降沿。在模拟中这会很好,但是合成器找不到任何可以做到这一点的触发器,因此会出错。

    其他需要注意的事项 - 您需要以某种方式重置或初始化您的计数器。要么带有一个复位信号,因此只要复位信号为高电平,计数器就被设置回全零。或者使用初始化语句。

    您可以在没有它们的情况下进行纯合成,因为合成器会(在没有初始化或重置代码的情况下)在 FPGA 启动时自动将计数器设置为全零。虽然它的形式很差:

    • 它在模拟中不起作用,而模拟至关重要。您可能还没有意识到这一点,但您最终会意识到的!
    • 如果您将代码移植到另一个无法神奇地初始化事物的架构,您将在启动时在计数器中获得随机的 1 和 0。这可能很重要,也可能无关紧要,但最好避免必须做出决定。

    【讨论】:

    • “不幸的是,您的代码的其余部分不在 if 子句之外,因此被描述为在时钟的每个边沿上运行,无论是上升还是下降。”但是怎么做?我只使用上升沿。我是怎么跳出那个 if 子句的?
    • 你最好用一个if rising_edge(clk) then 并把其他所有东西都放在里面。否则合成器可能无法识别它(因为它使用“模板匹配”在代码中找到合适的结构)
    【解决方案2】:

    除了糟糕的同步描述之外,还有糟糕的编码风格:)

    首先,如果你想描述一个计数器,你不应该在进程中使用变量。所以使用在架构区域中声明的信号。

    2。 确定要用于计数器的信号类型:无符号或整数。我会建议未签名的。

    3。 信号 A 不在敏感度列表中。但是将 A 添加到您的进程的敏感度列表中并不是解决方案,因为在一个进程中拥有两个不同的时钟(时钟和 A)是 (a) 不是每个综合工具都支持和 (b) 糟糕的编码风格 => 所以使用第二个处理正在使用第二个时钟的第二个计数器。

    4。 您在“ifrising_edge(...) then”语句中使用 A。综合工具将为括号中给出的信号推断一个(新的)时钟信号。所以你的描述会导致异步描述,这也是不好的风格。一种好的方式是从 fcounter(x) 中导出时钟启用信号,该信号启用第二个计数器 (counter_A)。 counter_A 也与您的主时钟“时钟”同步

    5。 尽管 fcounter 是一个寄存器,但它没有初始值。

    6。 为什么 fcounter 有 25 位?您只使用 7 位。 除此之外,使用 fcounter(6) 中的第 6 位将产生 128 (2^7) 分频时钟。 使用 fcounter(0) 表示一个触发触发器,它输出 f/2。 fcounter(1) -> f74 等等...

    那么,它应该是什么样子?

    architecture [...]
      [...]
      signal fcounter : unsigned(6 downto 0) := (others => '0');
      signal counter_a : unsigned(5 downto 0) := (others => '0');
    begin
      process(clock)
      bein
        if rising_edge(clock) then
          -- I'm using one more bits for the counter overflow, which resets the fcounter
          if (fcounter(6) = '1') then
            fcounter <= (others => '0');
          else
            fcounter <= fcounter + 1;
          end if;
    
          -- enable counter_A every 64 cycles
          if (fcounter(6) = '1') then
            counter_A <= counter_A + 1;
            [...]
          end if;
        end if;
      end process;
    end;
    

    但最后还有一个问题:这个模块应该做什么?你想创建一个新的 /64 时钟还是想创建某种重置?还有其他方法可以生成此类信号。

    回复 Mehmet 的评论:

    通常一个脉冲串是由一个 n 位的移位寄存器产生的,它被重置为全 1 并且输入分配为“0”。对于短脉冲序列,这是一个很好的解决方案,但在您的情况下,计数器的资源效率更高:)

    短脉冲(恒定)列车示例

    input <= '0';
    --input <= any_signal;
    
    process(clock)
    begin
      if rising_edge(clock) then
        if (reset = '1') then
          pulse_train <= (others => '1');
        else
          pulse_train <= pulse_train(pulse_train'high - 1 downto 0) & input;
        end if;
      end if;
    end process;
    
    output <= pulse_train(pulse_train'high);
    

    好的,在为外部低频 IC 提供派生时钟的情况下,可以使用计数器。如果计数器无法提供推荐的频率和占空比,您可以使用计数器产生 f_out*2 并将此信号通过触发触发器提供。 T-FF 将占空比恢复为 50/50,并将时钟除以 2 到 f_out。

    【讨论】:

    • 非常感谢您感兴趣的回答。这对我会有用。我想制作一个包含 40 个连续 1 的脉冲序列来硬重置 IC。此外,由于 IC 的频率边界,我希望能够调整它的频率。感谢您的回复。
    • 抱歉,完全没有理由避免变量!
    • @MartinThompson 因为有一种用 VHDL 描述事物的方法并不意味着您应该使用它!特别是对于 VHDL 初学者来说,变量不是一个好的选择。
    • @Paebbels 避免得到良好支持的语言功能,这些功能可以在没有 very 的情况下实现更简洁的代码和更高的抽象,这基本上是cargo-cult programming,无论是否初学者!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-21
    • 1970-01-01
    • 1970-01-01
    • 2010-12-14
    相关资源
    最近更新 更多