1

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

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

仅供参考,这是我的 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;
4

2 回答 2

2

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

您的测试台已经为 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 counter的答案)。

因为您已选择将 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 中添加组件声明和实例化语句,以及向 tb 添加 sRESET,并将其初始化为 true,如果在某个间隔后为 false,则 T_FF 模拟如下所示:

t_ff 仿真,添加了 RESET 和合格的时钟事件

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

于 2013-11-04T03:13:40.657 回答
0

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

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

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

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

2)关于代码:

  • Q 是缓冲区,不是 inout
  • 包括 "and clk='1'" (->rising_edge(clk))
  • 消除变量hold1,hold2
  • 使用 Q <= T xor Q 而不是 Q <= (T and notQ) 或 (not T and 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;
--------------------------------------------
于 2013-11-06T19:09:36.150 回答