【问题标题】:VHDL Define a signal when undefinedVHDL 未定义时定义信号
【发布时间】:2013-11-04 01:33:51
【问题描述】:

所以,我一直在做一些 VHDL 作业,但我的测试台遇到了一些问题。基本上,我的测试台正在运行许多触发器的不同可能性。但是,由于其中一个人字拖导致我不断得到“U”,虽然我确切地知道原因,但我不知道如何解决它。

基本上,对于我的 T 触发器,由于在执行 XOR 操作时未设置 Q,因此程序永远不会在 XOR 操作之后为 Q 赋值。所以基本上,如果 Q 尚未定义,我需要一种将 Q 设置为 0 的方法。

仅供参考,这是我的 T 触发器代码

library ieee;
use ieee.std_logic_1164.all;

entity T_FF is
  port (
        T, clk : in std_logic;
        Q : inout std_logic);
end T_FF;

architecture behv of T_FF is
begin
  process (clk) is
    variable hold1, hold2 : std_logic;
    begin
      if (clk'event) then
        hold1 := Q and (not T);
        hold2 := T and (not Q);
        Q <= hold1 or hold2;
      end if;
  end process;
end behv;

还有测试台:

library ieee;
use ieee.std_logic_1164.all;

entity tb is
end tb;

architecture behv of tb is
  -- Component declaration
  component T_FF is 
    port (
        T, clk : in std_logic;
        Q : inout std_logic);
  end component;

  signal sT : std_logic :='0';
  signal sclk : std_logic :='0';

  signal sQT : std_logic :='0';

  for TFF : T_FF use entity work.T_FF(behv);

  begin
    TFF: T_FF port map (T=>sT, clk=>sclk, Q=>sQT);

    sclk <= not sclk after 50 ns;
    sT <= not sT after 100 ns;

end;

【问题讨论】:

标签: vhdl flip-flop


【解决方案1】:

我向 Chris Laplante 道歉,但您的问题似乎是一个非常有效的 VHSIC 硬件描述语言 (VHDL) 问题。 (VHSIC 是超大规模集成电路的首字母缩写词)。尽管 Wiki 描述良好,但 VHDL 不是通用编程语言。执行受限于仿真时间或以实现相关的方式,连续增量周期数。借用 Harry Harrison 的一句话,VHDL 是硬件。所有这一切都说electronics.stackexchange.com vhdl tag 可以使用流量。

您的测试台已经为 sT 提供了一个默认值,即实例化 T_FF 中正式 T 的实际值。从未标记的过程中,我们看到变量 hold1 和 hold 2 是 T 和 Q 的乘积,因此问题是在包主体 std_logic_1164 中查找 AND 表或 NOT 表的 Q 值以产生除“U”之外的一些值:

-- truth table for "not" function
CONSTANT not_table: stdlogic_1d :=
--  -------------------------------------------------
--  |   U    X    0    1    Z    W    L    H    -   |
--  -------------------------------------------------
     ( 'U', 'X', '1', '0', 'X', 'X', '1', '0', 'X' );

-- truth table for "and" function
CONSTANT and_table : stdlogic_table := (
--      ----------------------------------------------------
--      |  U    X    0    1    Z    W    L    H    -         |   |
--      ----------------------------------------------------
        ( 'U', 'U', '0', 'U', 'U', 'U', '0', 'U', 'U' ),  -- | U |
        ( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ),  -- | X |
        ( '0', '0', '0', '0', '0', '0', '0', '0', '0' ),  -- | 0 |
        ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ),  -- | 1 |
        ( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ),  -- | Z |
        ( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' ),  -- | W |
        ( '0', '0', '0', '0', '0', '0', '0', '0', '0' ),  -- | L |
        ( 'U', 'X', '0', '1', 'X', 'X', '0', '1', 'X' ),  -- | H |
        ( 'U', 'X', '0', 'X', 'X', 'X', '0', 'X', 'X' )   -- | - |
);

从这两个表中我们看到,输入必须是“0”、“1”、“H”或“L”之一,才能提供“U”或“X”以外的内容。 (水平轴代表一个输入,垂直轴代表另一个输入,对于两个输入 AND 函数,结果值在与一个或两个轴相交的值数组中找到。

所以 Q 必须初始化为这四个值之一。有两种方法可以做到这一点,要么反映 FPGA 中的初始化,提供对置位或复位条件的自然偏差,要么通过对 Q 应用主动复位。(参见相关问题 VHDL - Asynchronous up/down counteranswer)。

因为您已选择将 Q 端口模式设为 inout 并直接在反馈中使用它,所以您最好的选择是提供重置。在您的 T_FF 中还有一个设计错误,您在两个时钟边沿上操作可以通过使用 clk = '1' 限定 clk' 事件以仅在一个边沿(上升沿)上操作来解决:

  process (clk, RESET) is
    variable hold1, hold2 : std_logic;
    begin
        if RESET = '1' then
            Q <= '0';
        else 
            if (clk'event AND clk = '1') then
                hold1 := Q and (not T);
                hold2 := T and (not Q);
                Q <= hold1 or hold2;
            end if;
        end if;
  end process;

('使用双沿的故障模式是产生一个正确频率但只对时钟的低波特有效的输出,试试看)。

因此,在 T_FF 中向端口添加异步 RESET,在 tb 中添加组件声明和实例化语句,以及将 sRESET 添加到 tb,并将其初始化为 true,如果在某个间隔后为 false,则 T_FF 模拟如下所示:

有一个关于综合兼容 VHDL 的 IEEE 标准,IEEE Std 1076.6-2004,名为 IEEE Standard for VHDL Register Transfer Level (RTL) Synthesis,它描述了此处使用的结构,请参阅 6.1.3 建模边缘敏感存储元素。请注意,RESET 已添加到 T_FF 中未标记的流程语句的敏感度列表中。

【讨论】:

  • 好的,太棒了。我知道 VHDL 是为表示硬件而设计的,我遇到的问题是缺少重置检查现在把它放进去,我的代码似乎工作正常。谢谢你的帮助!此外,关于在上升沿和下降沿上运行的代码,它适用于这个特定的应用程序,尽管我可能在说明中遗漏了一些东西。再次感谢!
【解决方案2】:

这里实际上有两个问题:(1)关于您要构建的内容; (2) 关于代码本身。

1) 关于您要构建的内容:

您正在尝试构建一个 T 型触发器。这通常是用 D 型触发器构建的,只需将其输出的反相版本连接回其输入即可。在您的情况下,您还需要一个“切换启用”信号(在您的代码中称为 T),以允许在 T=0 时停止 TFF。这意味着 TFF 输入必须通过 XOR 门,仅此而已。

可以像您一样(AND-OR 层)或直接使用 XOR 门来构建此类 XOR 门。因为 FPGA 中的 DFF 已经构建了一个启用端口(DFF 内部的 XOR 功能),所以最好使用 XOR 选项,节省逻辑并加快运行速度。但显然,另一个选项也将起作用。

2) 关于代码:

  • Q 是缓冲区,不是 inout
  • 包括“and clk='1'”(->rising_edge(clk))
  • 消除变量hold1、hold2
  • 使用 Q

library ieee;
use ieee.std_logic_1164.all;
--------------------------------------------
entity T_FF is
  port (
    T, clk: in std_logic;
    Q : buffer std_logic); 
end T_FF;
--------------------------------------------
architecture behv of T_FF is
begin
  process (clk) is
  begin
    if rising_edge(clk) then
      Q <= (T and not Q) or (not T and Q);
      --Q <= T xor Q; --preferred option
    end if;
  end process;
end behv;
--------------------------------------------

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-02-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多