【问题标题】:Gated clock warning门控时钟警告
【发布时间】:2015-05-10 18:17:51
【问题描述】:

我是所有涉及 VHDL 物理描述代码的新手,我有一个大学项目要完成(Nexys2 或 Nexys3 板上的四个不同的文本动画)并且我不断收到以下警告消息:

WARNING:Xst:737 - 找到信号的 7 位锁存器。不完整的 case 或 if 语句可能会生成锁存器。我们不建议在 FPGA/CPLD 设计中使用锁存器,因为它们可能会导致时序问题。
警告:Xst:737 - 找到信号的 7 位锁存器。不完整的 case 或 if 语句可能会生成锁存器。我们不建议在 FPGA/CPLD 设计中使用锁存器,因为它们可能会导致时序问题。
警告:Xst:737 - 找到信号的 7 位锁存器。不完整的 case 或 if 语句可能会生成锁存器。我们不建议在 FPGA/CPLD 设计中使用锁存器,因为它们可能会导致时序问题。
警告:Xst:737 - 找到信号的 7 位锁存器。不完整的 case 或 if 语句可能会生成锁存器。我们不建议在 FPGA/CPLD 设计中使用锁存器,因为它们可能会导致时序问题。
警告:PhysDesignRules:372 - 门控时钟。时钟网络 temp_reg1_not0001 由组合引脚提供。这不是好的设计实践。使用 CE 引脚控制数据加载到触发器中。
警告:PhysDesignRules:372 - 门控时钟。时钟网络 temp_reg3_not0001 由组合引脚提供。这不是好的设计实践。使用 CE 引脚控制数据加载到触发器中。
警告:PhysDesignRules:372 - 门控时钟。时钟网络 temp_reg2_not0001 由组合引脚提供。这不是好的设计实践。使用 CE 引脚控制数据加载到触发器中。
警告:PhysDesignRules:372 - 门控时钟。时钟网络 temp_reg4_not0001 由组合引脚提供。这不是好的设计实践。使用 CE 引脚控制将数据加载到触发器中。

这是所有源文件的链接(我正在使用 Ise Design Suite 14.7) http://www.fileshare.ro/e31590660

编辑:不幸的是,我已经花了将近半天的时间,我仍然无法准确指出问题所在。 我只能粗略地说,它是在下面代码中的过程中(第 73 行及以后)。

 library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- Folosim mai jos pachetul nostru
use work.Constante_si_componente.all;          

entity Optiune1 is   
    port(
    clk_50M:in std_logic;
    reset:in std_logic;
    catozi: out std_logic_vector(0 to 6);
    anozi: out std_logic_vector(0 to 3);
    opt1, opt2, opt3, opt4: in std_logic);
end entity;

architecture Behavioral of Optiune1 is   

-- Instantierea semnalelor locale
signal local_clk_1Hz: std_logic;
signal local_clk_1Khz: std_logic;  
signal adresa: integer range 0 to nr_cuvinte_distincte-1;       
signal sec_4: integer range 0 to limita_sup:=0; -- Numara exact 5 secunde
signal cuvant: std_logic_vector(lungime_cuvinte-1 downto 0);   
signal reg1, reg2, reg3, reg4: std_logic_vector(0 to 6):=(others=>'0');  
signal temp_reg1, temp_reg2, temp_reg3, temp_reg4: std_logic_vector(0 to 6) := (others=> '0');

-- Declarare componente   
component ROM 
    port (addr : in integer range 0 to nr_cuvinte_distincte-1;
          data: out std_logic_vector(lungime_cuvinte-1 downto 0));
end component ROM;      
component numarator 
    port(reset: in std_logic;
         clk: in std_logic; 
         limita_numarare: in integer;
         count: out integer range 0 to limita_sup);

end component; 
component registru
    port(clk_1Hz: in std_logic;
         reset: in std_logic;
         write_mode: in std_logic;
         input: in std_logic_vector(0 to 6);
         output: out std_logic_vector(0 to 6));
end component; 
component RRate 
    port(clk_1KHz: in std_logic;
    reg1, reg2, reg3, reg4: in std_logic_vector(0 to 6);
    catozi: out std_logic_vector(0 to 6);
    b:out std_logic_vector(0 to 3));
end component;

begin               
    -- Instantiem divizoarele de tact
    COMP_CLOCK_tat: divizor port map(clk_50M=>clk_50M, reset => reset, clk_1Hz => local_clk_1Hz, clk_1KHz=>local_clk_1KHz);


    -- Instantiem numaratorul
    Numarator_1: numarator port map(reset => reset, clk => local_clk_1Hz, limita_numarare => nr_cuvinte_distincte-1, count => adresa);      
    Numarator_2: numarator port map(reset => reset, clk => local_clk_1Hz, limita_numarare => 4, count => sec_4);

    -- Instantiem memoria
    Memorie1: ROM port map(addr => adresa, data => cuvant);

    -- Instantiem registrul
    Registrul_1: registru port map(local_clk_1Hz, reset, '1', temp_reg1, reg1);   
    Registrul_2: registru port map(local_clk_1Hz, reset, '1', temp_reg2, reg2);
    Registrul_3: registru port map(local_clk_1Hz, reset, '1', temp_reg3, reg3);
    Registrul_4: registru port map(local_clk_1Hz, reset, '1', temp_reg4, reg4);  

    -- Instantiem refresh rate-ul de la anozi
    Refresh_Rate: RRate port map (local_clk_1KHz, reg1, reg2, reg3, reg4, catozi, anozi);

    process(opt1, opt2, opt3, opt4, local_clk_1Hz, temp_reg1, temp_reg2, temp_reg3, temp_reg4, cuvant, sec_4) 
    begin
        if(opt1='1')and(opt2='0')and(opt3='0')and(opt4='0')and(local_clk_1Hz='1') then     
            temp_reg1 <= cuvant;
            temp_reg2 <= temp_reg1;
            temp_reg3 <= temp_reg2;
            temp_reg4 <= temp_reg3;         
        elsif(opt1='0')and(opt2='1')and(opt3='0')and(opt4='0')and(local_clk_1Hz='1') then
            temp_reg4 <= cuvant;
            temp_reg3 <= temp_reg4;
            temp_reg2 <= temp_reg3;
            temp_reg1 <= temp_reg2; 
        elsif(opt1='0')and(opt2='0')and(opt3='1')and(opt4='0')and(local_clk_1Hz='1') then 
            if sec_4 = 0 then 
                temp_reg1 <= cuvant;
            elsif sec_4 = 1 then 
                temp_reg2 <= cuvant;
            elsif sec_4 = 2 then
                temp_reg3 <= cuvant;
            elsif sec_4 = 3 then
                temp_reg4 <= cuvant;
            elsif sec_4 = 4 then
                temp_reg1 <= "1111111"; 
                temp_reg2 <= "1111111";
                temp_reg3 <= "1111111";
                temp_reg4 <= "1111111";
            end if;
       elsif(opt1='0')and(opt2='0')and(opt3='0')and(opt4='1')and(local_clk_1Hz='1') then 
            if sec_4 = 0 then 
                temp_reg1 <= cuvant;
            elsif sec_4 = 1 then            
                temp_reg2 <= cuvant;
                temp_reg1<="1111111";
            elsif sec_4 = 2 then
                temp_reg3 <= cuvant;
                temp_reg2<="1111111";
            elsif sec_4 = 3 then
            temp_reg4 <= cuvant;
            temp_reg3<="1111111";
            elsif sec_4 = 4 then
                temp_reg1 <= "1111111"; 
                temp_reg2 <= "1111111";
                temp_reg3 <= "1111111";
                temp_reg4 <= "1111111";
            end if;
        else
            temp_reg1 <= (others => '0');
            temp_reg2 <= (others => '0');
            temp_reg3 <= (others => '0');
            temp_reg4 <= (others => '0');           
        end if;
    end process;

end architecture Behavioral;

最后一次编辑:我昨天必须提交项目,它在 Nexys2 FPGA 板上按预期工作,我将 David Koontz 的多路复用器代码添加到项目文档的“未来开发”部分.

非常感谢您的帮助:)

【问题讨论】:

  • 请更新问题以显示发出警告的最少代码。这样做的好处是,您实际上可以自己找到解决方案。

标签: vhdl


【解决方案1】:
process(opt1, opt2, opt3, opt4, local_clk_1Hz, temp_reg1, temp_reg2, temp_reg3, temp_reg4, cuvant, sec_4) 
begin
    if(opt1='1')and(opt2='0')and(opt3='0')and(opt4='0')and(local_clk_1Hz='1') then     
        temp_reg1 <= cuvant;
        temp_reg2 <= temp_reg1;
        temp_reg3 <= temp_reg2;
        temp_reg4 <= temp_reg3; 

这很可能是错误的。由于您的流程是组合的,分配给temp_reg1 将再次触发流程,这会将temp_reg1 的新值分配给temp_reg2 等等。基本上,这会将cuvant 分配给所有4 个temp_regs,但我不确定XST 是否可以适当地处理组合环回。

这可能不是你想要的。通常,这种过程会使用将regx 分配给temp_regx,这可能是您想要的:

temp_reg1 <= cuvant;
temp_reg2 <= reg1;
temp_reg3 <= reg2;
temp_reg4 <= reg3;

正如 David Koontz 指出的,这段代码负责锁存器:

if sec_4 = 0 then 
    temp_reg1 <= cuvant;
elsif sec_4 = 1 then            
    temp_reg2 <= cuvant;
    temp_reg1<="1111111";
elsif sec_4 = 2 then
    temp_reg3 <= cuvant;
    temp_reg2<="1111111";
elsif sec_4 = 3 then
temp_reg4 <= cuvant;
temp_reg3<="1111111";
elsif sec_4 = 4 then
   temp_reg1 <= "1111111"; 
   temp_reg2 <= "1111111";
   temp_reg3 <= "1111111";
   temp_reg4 <= "1111111";
end if;

在组合过程中,在过程中分配的每个信号必须在通过该过程的每条路径中分配,否则您将获得锁存器。在这种情况下,temp_reg2 不被分配,例如 sec_4 = 0

【讨论】:

  • 非常感谢您的努力,我会在不久的将来修改它,但是项目大约8小时后到期,最后15小时我完全没有睡觉在 Active-HDL 中工作(我的意思是为每个选项获取正确的波形),所以我现在试着睡觉。
  • 该项目在 nexys2 或 nexys3 上的 7 段显示上大约有 4 个不同的文本动画,我已在此处上传文件:fileshare.ro/e31591315,但修改后我收到了一些其他警告(它有效如意@Active-HDL 波形)
【解决方案2】:

在翻译完所有罗马尼亚语名称和 cmets 并注意到 temp_reg1 - temp_reg4 是寄存器的输入后,它看起来并不是您想要的锁存器。

无意推断的锁存器是由于缺乏完整的条件分配覆盖,并且由于目标器件中不同数量的“门”等效物的延迟差异,无法保证组合时钟(或锁存器启用)不会出现故障, 由于放置以及上升和下降时间的差异导致的“布线”延迟。防止闩锁需要在 case 语句中的每个条件或选择下进行赋值,本质上是可访问的 elseothers

Jonathan 注意到由影响模拟的敏感性列表引起的模拟循环。摆脱敏感列表问题可以通过将过程分解为单独的多路复用器来完成。

这是两个问题的示例解决方案。它是通过并发信号分配语句实现的。

我为组件divizor 添加了一个声明以供分析(它可能位于非包含包Constante_si_componente 中)。

在将三个必要的声明(nr_cuvinte_distinctelimita_suplungime_cuvinte)生成到一个虚拟包 constante_si_componente 之后,我替换了过程语句。

我添加了以下本地信号实例作为架构声明项:

-- added declarations

    component divizor is
        port (
            clk_50M:    in  std_logic;
            reset:      in  std_logic;
            clk_1Hz:    out std_logic;
            clk_1KHz:   out std_logic
        ) ;
    end component;

    signal some_cond0:     std_logic;
    signal some_cond1:     std_logic;
    signal some_cond2:     std_logic;
    signal some_cond3:     std_logic;

begin

这些代替未标记过程中指定的外部 if 语句条件:

-- new concurrent signal assignment statements:

    some_cond0 <= opt1 and not opt2 and not opt3 and not opt4 and local_clk_1Hz;

    some_cond1 <= not opt1 and opt2 and not opt3 and not opt4 and local_clk_1Hz;

    some_cond2 <= not opt1 and not opt2 and opt3 and not opt4 and local_clk_1Hz;

    some_cond3 <= not opt1 and not opt2 and not opt3 and opt4 and local_clk_1Hz;

可以命名这些以反映条件所代表的内容。看起来您也可以将opt1opt4 二进制编码为两个信号,它们是互斥的。

这个想法主要是为了简化多路复用器的描述。

多路复用器是使用条件信号分配实现的:

MUX1: 
    temp_reg1 <= cuvant    when  some_cond0 = '1' else
                 temp_reg2 when  some_cond1 = '1' else 
                 cuvant    when  (some_cond2 = '1' or some_cond3 = '1') and
                                 sec_4 < 4                                 else
                 "1111111" when (some_cond2 = '1' or some_cond3 = '1')  and
                                 sec_4 = 4                                 else
                 (others => '0');
MUX2:                
    temp_reg2 <= temp_reg1 when  some_cond0 = '1' else
                 temp_reg3 when  some_cond1 = '1' else 
                 cuvant    when  (some_cond2 = '1' or some_cond3 = '1') and
                                 sec_4 < 4                                 else
                 "1111111" when (some_cond2 = '1' or some_cond3 = '1')  and
                                 sec_4 = 4                                 else
                 (others => '0');
MUX3:                
     temp_reg3 <= temp_reg2 when  some_cond0 = '1' else
                  temp_reg4 when  some_cond1 = '1' else 
                  cuvant    when  (some_cond2 = '1' or some_cond3 = '1') and
                                  sec_4 < 4                                 else
                  "1111111" when (some_cond2 = '1' or some_cond3 = '1')  and
                                  sec_4 = 4                                 else
                  (others => '0');  
MUX4:                 
    temp_reg4 <= temp_reg3 when  some_cond0 = '1' else
                 cuvant    when  some_cond1 = '1' else 
                 cuvant    when  (some_cond2 = '1' or some_cond3 = '1') and
                                  sec_4 < 4                                 else
                 "1111111" when (some_cond2 = '1' or some_cond3 = '1')  and
                                  sec_4 = 4                                 else
                 (others => '0');    

分离多路复用器后,没有导致失败的敏感度列表项目,并且总是有一个分配 - 每个多路复用器中的最终else

您可以在条件赋值语句中进行各种优化,此示例旨在可追溯到原始过程。

如果 op1op4 在两个信号上编码为选择,local_clk_1Hz 用作启用,则可以实例化四个 4:1 多路复用器 lungime_cuvinte 宽。

修改您的设计后,它分析但没有 divizorROMnumaratorregistruRRate 的实体/架构对我无法详细说明或模拟您的设计。

附录

我分解并下载了你的 RAR,清理了我修改后的问题代码副本以使用你的头包。一切都分析过了,虽然我删掉了一些不需要的 use 子句。

详细说明了,但 numarator 中存在运行时模拟错误,这是由 inter 递增超出 count 的界限引起的,这也说明您没有先模拟这个。

整数的默认值(numarator 中的inter)是左边界(通常为 –2147483647)。在初始化期间,将有一个分配给count (range 0 to limita_sup),这将导致绑定检查失败。

signal inter: integer; -- acest semnal chiar e intermediar fiindca nu prea

应该输入positive而不是整数,以便默认值在count的范围内,或者应该在count' bounds (0`内提供默认值。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-09
    • 2015-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多