VHDL:当涉及时钟信号时,多路复用器输出不跟随输入

Posted

技术标签:

【中文标题】VHDL:当涉及时钟信号时,多路复用器输出不跟随输入【英文标题】:VHDL : mux output not following inputs when it comes to clock signals 【发布时间】:2017-06-27 08:45:02 【问题描述】:

我正在创建一个架构来使用带有 L297 控制器的 FPGA 板来驱动步进电机。所以为了改变速度,我创建了一个时钟分频器来改变 L297 的时钟频率。时钟分频器工作得很好。我的问题是我创建了多个时钟输出,其中一个将使用板上的按钮选择,所以当我将这些信号连接到 MUX 时,输出在时钟输入信号方面并不完全正确,但它工作正常与 STD_LOGIC。 这是我用于 MUX 的代码

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
use IEEE.NUMERIC_STD.ALL;

entity TEST_MUX is
Port ( A : in  STD_LOGIC;
       B : in  STD_LOGIC;
       C : in  STD_LOGIC;
       D : in  STD_LOGIC;
       E : in  STD_LOGIC;
       choice_select : in  STD_LOGIC;
       choice_valid : in  STD_LOGIC;
       choice_reset : in  STD_LOGIC;
       Choice : out  STD_LOGIC);
  end TEST_MUX;

 architecture Behavioral of TEST_MUX is

signal count : integer  := 0;
signal S_out : STD_LOGIC ;

 begin

 process ( choice_select , choice_valid, choice_reset,A,B,C,D,E)
   begin
if (choice_reset = '0') THEN
            count <=0;
            S_out <= 'Z';
            else
            if (choice_select'event) and (choice_select ='1')  THEN
                    count <= count + 1;
                        if (choice_valid = '1')  THEN
                            case count is
                            when  1=>  S_out<=A ; 
                            when  2=>  S_out<=B ;  
                            when  3=>  S_out<=C ; 
                            when  4=>  S_out<=D; 
                            when  5=>  S_out<=E ;   
                            when others =>   S_out <= 'Z';
                            end case;
                        end if;
           end if;
end if;                                         
end process;

Choice<=S_out;

end Behavioral;

以下是输入为 STD_LOGIC 时的正确模拟结果: enter image description here

这里输入强制为时钟: enter image description here 谢谢你的帮助

【问题讨论】:

真是一团糟。我建议您尝试将您现在拥有的流程的组合部分和顺序部分分开。还要避免使用 ieee.std_arith。请改用 ieee.numeric_std。最重要的是不要同时使用两者。 你的意思是把组合部分和顺序部分分开。 if 和 case 语句不应该在进程内 你为什么在你的代码中使用'Z' = tristate?这在内部 FPGA 信号上不受支持。另外:我希望您知道您需要将时钟域同步器放在外部输入(按钮)上才能使用它们?否则,它们将通过违反建立和保持时间来搞砸内部逻辑 【参考方案1】:

让我们更仔细地看看你的过程的内容:

process ( choice_select , choice_valid, choice_reset,A,B,C,D,E)
begin
  if (choice_reset = '0') THEN
    -- Reset things
  else
    if (choice_select'event) and (choice_select ='1')  THEN
      -- Counter and multiplexer here
    end if;
  end if;                                         
end process;

您已经在敏感度列表中添加了很多信号,但实际上可以使您的进程执行任何操作的仅有两个信号是choice_resetchoice_select。至关重要的是,只有在 choice_select 信号中有 event(即转换)时,才会执行多路复用器和计数器所在的块。 AB 等中的更改不会启用此块,因此如果这些信号发生更改,您不会看到多路复用器执行任何操作。

您需要做的是将您的多路复用器移动到另一个非时钟进程:

process (count, choice_valid, choice_reset, A, B, C, D, E)
begin
  if (choice_reset = '0') THEN
      S_out <= 'Z';
  elsif (choice_valid = '1')  THEN
    case count is
      when 1 => S_out <=A; 
      when 2 => S_out <=B;  
      when 3 => S_out <=C; 
      when 4 => S_out <=D; 
      when 5 => S_out <=E;   
      when others => S_out <= 'Z';
    end case;
  end if;                                         
end process;

话虽如此,在大多数 FPGA 设备中实现时钟多路复用器的正确方法是利用设备可能拥有的任何专用时钟多路复用器。这可确保时钟保持在时钟路由网络上,甚至可以在时钟之间提供无故障切换。您可能能够确定基于 LUT 的多路复用器足以满足您的应用需求,但这不应作为开始的假设。


您可以使用函数 rising_edge()falling_edge() 作为代码中使用的 'event 样式(即 if rising_edge(choice_select) then)的更好替代方案。

根据评论,您也不应该use ieee.std_logic_arith.all;use ieee.std_logic_unsigned.all;.

【讨论】:

你说的确实更有意义,而且比我做的更合乎逻辑,我想我现在可以通过拆分多路复用器和案例声明来解决它,非常感谢先生,我真的很感激帮助

以上是关于VHDL:当涉及时钟信号时,多路复用器输出不跟随输入的主要内容,如果未能解决你的问题,请参考以下文章

VHDL多路复用器实现?

VHDL 多路复用和两个输出

VHDL组件多路复用器不在modelsim中返回值

4、试写出4选1多路选择器的VHDL描述,假设选择控制信号为S1、S0,输入信号为d3,d2,d1,d0,输出信号为y。

使用 4 对 1 实现 8 对 1 多路复用器的 VHDL 程序(结构建模)

hdl 中的管道多路复用器