2017-08-26 103 views
2

我有VHDL实现可以在板上工作,它检测到序列01110,并且会产生一个2个时钟计数的标志。它还检测重叠序列,以及011101110将两次提升标志。VHDL状态机测试台 - 在机器上工作,但不能在模拟机上工作

我检查了我的实施与板上的逻辑分析仪,我相当有信心,它的工作原理。我在电路板上以10 kHz的频率重复序列0111,它有一个100 MHz的时钟,我用预分频器将它的频率调整到10 kHz。

我的问题是,尝试使用模拟重新建立一个类似的情景时,我没有得到任何输出,从逻辑分析仪预计

图片由董事会从试验台enter image description here

图片 enter image description here

试验台代号

library IEEE; 
use IEEE.STD_LOGIC_1164.ALL; 
use IEEE.STD_LOGIC_ARITH.ALL; 
use IEEE.STD_LOGIC_UNSIGNED.ALL; 

entity test_FSM_prac4 is 
-- Port (); 
end test_FSM_prac4; 

architecture Behavioral of test_FSM_prac4 is 

component FSM_prac4 is 
    port ( 
     inputSignal : in STD_LOGIC; 
     pushButton : in STD_LOGIC; 
     clk100mhz : in STD_LOGIC; 
     logic_analyzer : out STD_LOGIC_VECTOR (7 downto 0); 
     LEDs: out STD_LOGIC 
); end component; 

signal inputSignal : std_logic := '0'; 
signal pushButton: std_logic := '0'; 
signal clk100mhz: std_logic := '0'; 
signal logic_analyzer: std_logic_vector(7 downto 0); 
signal LEDs : std_logic; 

begin 

uut : FSM_prac4 port map(
    inputSignal => inputSignal, 
    pushButton => pushButton, 
    clk100mhz => clk100mhz, 
    logic_analyzer => logic_analyzer, 
    LEDs => LEDs 
    ); 

--generate clock 100mhz 
clock_tic: process begin 
    loop 
    clk100mhz <= '0'; 
    wait for 5ns; 
    clk100mhz <= '1'; 
    wait for 5ns; 
    end loop; 
end process; 

input_changes: process begin 
    loop 
    inputSignal <= '0'; 
    wait for 100us; 
    inputSignal <= '1'; 
    wait for 100us; 
    inputSignal <= '1'; 
    wait for 100us; 
    inputSignal <= '1'; 
    wait for 100us; 
    end loop; 
end process; 

end Behavioral; 

要显示地图平逻辑分析仪

logic_analyzer(0) <= masterReset; 
logic_analyzer(1) <= newClock -- 10Khz Clock; 
logic_analyzer(2) <= outputZ; 
--FSM States 
logic_analyzer(3) <= '1' when y = A ELSE '0'; 
logic_analyzer(4) <= '1' when y = B ELSE '0'; 
logic_analyzer(5) <= '1' when y = C ELSE '0'; 
logic_analyzer(6) <= '1' when y = D ELSE '0'; 
logic_analyzer(7) <= '1' when y = E ELSE '0'; 

如果有人可以直接向我在做什么错在测试平台上,以及如何复制得到类似的结果作为第一个图像,因为它表明,在模拟中,它始终保持在国家一并且新时钟不翻转意味着clk100mhz在某种程度上没有连接,但我无法弄清楚原因。

任何帮助是极大的赞赏,感谢你们

编辑:

我写了一个简单的程序来测试我的标时钟

library IEEE; 
use IEEE.STD_LOGIC_1164.ALL; 
use IEEE.STD_LOGIC_ARITH.ALL; 
use IEEE.STD_LOGIC_UNSIGNED.ALL; 

entity scaler_clk is 
Port ( 
      pushButton : in std_logic; 
      indicator : out std_logic; 
      clk100mhz : in STD_LOGIC; 
      clk10khz: out STD_LOGIC 
      ); 
end scaler_clk; 

architecture Behavioral of scaler_clk is 
    signal clockScalers : std_logic_vector (12 downto 0):= (others => '0') ; 
    signal prescaler: std_logic_vector(12 downto 0) := "1001110001000"; 
    signal newClock: std_logic := '0'; 
    signal masterReset : std_logic;  

begin 

    clk10khz <= newClock; 
    masterReset <= pushButton; 

    process (clk100mhz,masterReset) begin 
     if(masterReset <= '1') then <--- error occurs here 
      clockScalers <= "0000000000000"; 
      newClock <= '0'; 
      indicator <= '1'; 
     elsif (clk100mhz'event and clk100mhz = '1')then 
      indicator <= '0'; 
      clockScalers <= clockScalers + 1; 
      if(clockScalers > prescaler) then 
       newClock <= not newClock; 
       clockScalers <= (others => '0'); 
      end if; 
     end if; 
    end process; 

end Behavioral; 

测试台代码

library IEEE; 
use IEEE.STD_LOGIC_1164.ALL; 

entity test_scaler_clk is 
-- Port (); 
end test_scaler_clk; 

architecture Behavioral of test_scaler_clk is 

    component scaler_clk Port ( 
      pushButton : in std_logic; 
      indicator : out std_logic; 
      --input clock 
      clk100mhz : in STD_LOGIC; 
      clk10khz: out STD_LOGIC 
      );end component; 

    signal clk100mhz: std_logic := '0'; 
    signal clk10khz : std_logic; 
    signal pushButton: std_logic; 
    signal indicator : std_logic; 

begin 

uut: scaler_clk port map(
    pushButton => pushButton, 
    indicator => indicator, 
    clk100mhz => clk100mhz, 
    clk10khz => clk10khz 
    );  

    pushButton <= '0'; 
    clock_tic: process begin 
     loop 
     clk100mhz <= '0'; 
     wait for 5ns; 
     clk100mhz <= '1'; 
     wait for 5ns; 
     end loop; 
    end process; 


end Behavioral; 

即使虽然我将pushButton设置为'0',但它仍然触发masterReset,任何人都知道为什么,这就是为什么10 kHz时钟不工​​作

enter image description here

+0

明显的不同:日志显示时钟和刺激的速度相同,但在结核病中它们的速率不同。现在我们不知道组件的内部,因此我们无法进一步追踪这种差异。 –

+0

是的,在板上我有一个100MHz的输入时钟,我把它缩小到10khz的输出,然后反映在逻辑分析仪(1)上,我使用10khz时钟作为我的fsm –

+0

我试图模拟相同的事情在测试台上通过产生100mhz时钟。它应该显示在TB上的逻辑分析仪(1)上一个10khz时钟,但它没有显示。我想知道是因为我的synthex还是我错过了一些东西 –

回答

2

有几件事情,你可以(应该)在你的代码提高。正如布莱恩已经解释过,在你Behavioral建筑scaler_clk,你应该有:

if(masterReset = '1') then 

代替:

if(masterReset <= '1') then 

现在,让我们开始与您最初的问题的最可能的原因:未结合的成分。您的测试台将实例化设计以验证组件。 VHDL组件是实际实体的原型。原型足以编译,因为编译器可以执行所有必要的语法和类型检查。但是它们不足以模拟,因为模拟器在原型后面还需要执行的。有些工具对未绑定的组件具有默认的绑定策略:如果他们发现具有相同名称的实体并且只有一个体系结构,则它们使用该策略。你的模拟器显然不使用这种策略(至少在默认情况下,可能有一个选项,但它被禁用)。请注意,我知道的大多数模拟器在发现未绑定组件时都会发出警告。你可能错过了这些警告。

无论如何,您的组件实例都是未绑定的(它们没有关联的实体/体系结构),并且模拟器将它们视为黑盒子。除了你声明的初始值(1)外,它们的输出不被驱动。

如何解决这个问题?两种选择:

  1. 使用配置来指定哪些实体/架构对应被用于每个组件实例:

    for all: scaler_clk use entity work.scaler_clk(Behavioral); 
    
  2. 使用实体实例化,而不是组件:

    uut: entity work.scaler_clk(Behavioral) port map... 
    

现在,我们来看看代码中可以改进的一些其他方面:

  1. 您正在使用非标准封装,是经常不兼容甚至:IEEE.STD_LOGIC_ARITHIEEE.STD_LOGIC_UNSIGNED。由于它们不是标准的,它们甚至不应该在标准的IEEE库中。您应该使用IEEE.NUMERIC_STD代替,并且只使用那一个。它声明了SIGNEDUNSIGNED类型(声明与STD_LOGIC_VECTOR相同)并重载算术运算符。

  2. 你的测试平台生成具有100MHz的时钟:

    clock_tic: process begin 
        loop 
        clk100mhz <= '0'; 
        wait for 5ns; 
        clk100mhz <= '1'; 
        wait for 5ns; 
        end loop; 
    end process; 
    

    的无限循环是无用的:一个进程已经是一个无限循环:

    clock_tic: process 
    begin 
        clk100mhz <= '0'; 
        wait for 5ns; 
        clk100mhz <= '1'; 
        wait for 5ns; 
    end process clock_tic; 
    

    会做同样的。 input_changes过程的相同说明。

  3. 您的input_changes程序使用wait for <duration>陈述。这不是一个好主意,因为与时钟相比,您不知道信号何时触发。是否在clk100mhz的上升沿之前,之后或恰好与此同时?如果它恰好在同一时间,会发生什么?当然,您可以仔细选择<durations>以避免这种歧义,但容易出错。您只能在时钟生成过程中使用wait for <duration>。在其他地方,它是更好地与时钟同步:

    input_changes: process 
    begin 
        inputSignal <= '0'; 
        for i in 1 to 10000 loop 
         wait until rising_edge(clk100mhz); 
        end loop; 
        inputSignal <= '1'; 
        for i in 1 to 10000 loop 
         wait until rising_edge(clk100mhz); 
        end loop; 
        inputSignal <= '1'; 
        for i in 1 to 10000 loop 
         wait until rising_edge(clk100mhz); 
        end loop; 
        inputSignal <= '1'; 
        for i in 1 to 10000 loop 
         wait until rising_edge(clk100mhz); 
        end loop; 
    end process input_changes; 
    

    这可以保证只在时钟的上升沿后inputSignal变化。你可以重写它有点更优雅的方式(可能有点更容易维护):

    input_changes: process 
        constant values: std_logic_vector(0 to 3) := "0111"; 
    begin 
        for i in values'range loop 
         inputSignal <= values(i); 
         for i in 1 to 10000 loop 
          wait until rising_edge(clk100mhz); 
         end loop; 
        end loop; 
    end process input_changes; 
    
  4. 您使用解决类型(STD_LOGICSTD_LOGIC_VECTOR)。这些类型允许多个驱动器,即具有由多个设备(VHDL进程)驱动的硬件线(VHDL信号)。通常你不想要这个。通常你甚至希望避免这种瘟疫,因为它可能导致短路。在大多数情况下,使用未分辨类型(STD_ULOGICSTD_ULOGIC_VECTOR)更明智一些,因为如果在设计中意外造成短路,编译器和/或模拟器将引发错误。最后一件事:如果顾名思义,你打算使用clk10khz信号作为真正的时钟,你应该重新考虑这个决定。这是您用自定义逻辑生成的信号。时钟具有非常特定的电气和时序约束,这些约束无法通过常规信号来实现。在使用clk10khz作为时钟之前,您必须处理时钟偏移,时钟缓冲...不是不可能,而是棘手。如果你确实使用它作为时钟,你的合成器可能会发出你也错过了的重要警告(可能会在时间报告中看到)。而且,这在你的情况下可能没有用处:从clk100mhz生成的使能信号可能可以用来代替,避免所有这些问题。相反的:

    process (clk100mhz,masterReset) begin 
        if(masterReset = '1') then 
         clockScalers <= "0000000000000"; 
         newClock <= '0'; 
         indicator <= '1'; 
        elsif (clk100mhz'event and clk100mhz = '1')then 
         indicator <= '0'; 
         clockScalers <= clockScalers + 1; 
         if(clockScalers > prescaler) then 
          newClock <= not newClock; 
          clockScalers <= (others => '0'); 
         end if; 
        end if; 
    end process; 
    

    使用:

    signal tick10khz: std_ulogic; 
    ... 
    process(clk100mhz, masterReset) begin 
        if masterReset = '1') then 
         clockScalers <= "0000000000000";  
         tick10khz <= '0'; 
        elsif rising_edge(clk100mhz) then 
         clockScalers <= clockScalers + 1; 
         tick10khz <= '0' 
         if(clockScalers > prescaler) then 
          tick10khz <= '1'; 
          clockScalers <= (others => '0'); 
         end if; 
        end if; 
    end process; 
    

    然后,而不是:

    process(clk10khz) 
    begin 
        if rising_edge(clk10khz) then 
         register <= register_input; 
        end if; 
    end process; 
    

    使用:

    process(clk100mhz) 
    begin 
        if rising_edge(clk100mhz) then 
         if tick10khz = '1' then 
          register <= register_input; 
         end if; 
        end if; 
    end process; 
    

    结果将是相同的,但只有一个100MHz时钟,避免时钟偏移,时钟缓冲ng和时钟域交叉问题。

(1)这说明了为什么使用初始值声明变量和信号通常不是一个好主意:它隐藏了潜在的问题。如果没有这个,你的信号会被卡在'U'(未初始化),这可能有助于理解问题的来源。

相关问题