【问题标题】:Signal high for a specific time特定时间的高信号
【发布时间】:2015-12-19 09:17:58
【问题描述】:

我做了一个由 2 个模块组成的 VHDL 设计。一个处理通信并以 100 Mhz 运行(我无法更改)。另一个模块进行计算,并且由于时间原因必须以 45 Mhz 运行。

第二个模块有一个名为“newPair”的输入引脚,当新数据准备好并可以由第二个模块处理时,我想将其设置为高电平。现在我的第二个模块只在时钟的上升沿工作,所以我需要将此引脚设置为 45 Mhz 时钟周期高,然后将其拉低。这必须通过以 45 Mhz 运行的模块来完成。我怎样才能做到这一点?我想为此创建一个 DCM,但这似乎有点过于强大了。

谢谢!

更新:

我正在开发 Spartan-6 (xc6slx150)

【问题讨论】:

  • 你的目标平台和设备是什么?
  • 我刚刚更新了它。对不起

标签: vhdl


【解决方案1】:

您的设计有 2 个时钟域,因此您需要同步器电路将信息从一个时钟域传输到另一个时钟域。

第 1 部分 - 同步器

基本同步器是由 2 个链式 D-FF 构建的。该同步器可用于标志信号(这些信号不经常变化)。它不能用于选通信号(这些是高 1 个周期的信号),因为在目标时钟域上可能会丢失或重复看到选通信号。

2 D-FF 同步器:

genLoop : for i in Input'range generate
  signal Data_async : STD_LOGIC;
  signal Data_meta      : STD_LOGIC     := '0');
  signal Data_sync      : STD_LOGIC     := '0' ;
begin
  Data_async    <= Input(i);
  process(Clock)
  begin
    if rising_edge(Clock) then
      Data_meta <= Data_async;
      Data_sync     <= Data_meta;
    end if;
  end process;
  Output(i) <= Data_sync;
end generate;

可以通过供应商特定的 VHDL 属性改进此代码。有关通用、Altera 和 Xilinx 变体,请参阅我的链接源代码。

来源: PoC.misc.sync.Bits

另请参阅存储在 UCF 文件中的 Xilinx ISE 设计的这些时序约束:
- https://github.com/VLSI-EDA/PoC/blob/master/ucf/MetaStability.ucf
- https://github.com/VLSI-EDA/PoC/blob/master/ucf/misc/sync/sync_Bits_Xilinx.ucf

第 2 部分 - 为频闪信号构建合成器电路

具有频闪功能的跨时钟同步器由以下组件构建:

  • 1 T-FF 用于编码源时钟域中的信号变化
  • 2 D-FF 作为标志同步器,如第 1 部分所述
  • 一个变化检测器,用于恢复目标时钟域中的原始值(1 个 D-FF 和一个 XOR)

此同步器可用于将您的newPair 信号传输到 45 MHz 时钟域。您将需要相同的电路返回:)

以下示例实现了一个忙信号来指示传输过程。在Busy 为高电平时断言Input 会导致被忽略的频闪。

entity sync_Strobe IS
  generic (
    BITS                                : POSITIVE      := 1;                                                       -- number of bit to be synchronized
    GATED_INPUT_BY_BUSY : BOOLEAN           := TRUE                                                 -- use gated input (by busy signal)
  );
  port (
    Clock1                          : in    STD_LOGIC;                                                          -- <Clock>  input clock domain
    Clock2                          : in    STD_LOGIC;                                                          -- <Clock>  output clock domain
    Input                               : in    STD_LOGIC_VECTOR(BITS - 1 downto 0);        -- @Clock1: input bits
    Output                          : out STD_LOGIC_VECTOR(BITS - 1 downto 0);      -- @Clock2: output bits
    Busy                                : out   STD_LOGIC_VECTOR(BITS - 1 downto 0)         -- @Clock1: busy bits
  );
end entity;

architecture rtl of sync_Strobe is
  attribute SHREG_EXTRACT                                       : STRING;

  signal syncClk1_In        : STD_LOGIC_VECTOR(BITS - 1 downto 0);
  signal syncClk1_Out       : STD_LOGIC_VECTOR(BITS - 1 downto 0);
  signal syncClk2_In        : STD_LOGIC_VECTOR(BITS - 1 downto 0);
  signal syncClk2_Out       : STD_LOGIC_VECTOR(BITS - 1 downto 0);
begin
  gen : for i in 0 to BITS - 1 generate
    signal D0                           : STD_LOGIC         := '0';
    signal T1                           : STD_LOGIC         := '0';
    signal D2                           : STD_LOGIC         := '0';

    signal Changed_Clk1     : STD_LOGIC;
    signal Changed_Clk2     : STD_LOGIC;
    signal Busy_i                   : STD_LOGIC;

    -- Prevent XST from translating two FFs into SRL plus FF
    attribute SHREG_EXTRACT OF D0   : signal is "NO";
    attribute SHREG_EXTRACT OF T1   : signal is "NO";
    attribute SHREG_EXTRACT OF D2   : signal is "NO";

  begin

    process(Clock1)
    begin
        if rising_edge(Clock1) then
            -- input delay for rising edge detection
            D0      <= Input(I);

            -- T-FF to converts a strobe to a flag signal
            if (GATED_INPUT_BY_BUSY = TRUE) then
                T1  <= (Changed_Clk1 and not Busy_i) xor T1;
            else
                T1  <= Changed_Clk1 xor T1;
            end if;
        end if;
    end process;

    -- D-FF for level change detection (both edges)
    D2  <= syncClk2_Out(I) when rising_edge(Clock2);

    -- assign syncClk*_In signals
    syncClk2_In(I)  <= T1;
    syncClk1_In(I)  <= syncClk2_Out(I); -- D2

    Changed_Clk1        <= not D0 and Input(I);             -- rising edge detection
    Changed_Clk2        <= syncClk2_Out(I) xor D2;      -- level change detection; restore strobe signal from flag
    Busy_i                  <= T1 xor syncClk1_Out(I);      -- calculate busy signal

    -- output signals
    Output(I)               <= Changed_Clk2;
    Busy(I)                 <= Busy_i;
  end generate;

  syncClk2 : entity PoC.sync_Bits
    generic map (
        BITS                => BITS                     -- number of bit to be synchronized
    )
    port map (
        Clock               => Clock2,              -- <Clock>  output clock domain
        Input               => syncClk2_In,     -- @async:  input bits
        Output          => syncClk2_Out     -- @Clock:  output bits
    );

  syncClk1 : entity PoC.sync_Bits
    generic map (
        BITS                => BITS                     -- number of bit to be synchronized
    )
    port map (
        Clock               => Clock1,              -- <Clock>  output clock domain
        Input               => syncClk1_In,     -- @async:  input bits
        Output          => syncClk1_Out     -- @Clock:  output bits
    );
end architecture;

来源:PoC.misc.sync.Strobe

第 2 部分 - 特殊合成器电路

我假设您还将数据从一个时钟域传输到另一个时钟域。所以你需要一个多位同步器(建立在选通同步器的基础上)或一个支持交叉时钟的 FIFO。

我参与的 PoC 库也具有多位/矢量同步器。查看链接源文件夹中的其他模块。还有一个交叉时钟/独立时钟(ic)FIFO。

【讨论】:

  • 很棒的答案。谢谢:)
【解决方案2】:

您无需在特定时间内断言某个信号。

如果第一个和第二个模块之间的数据交换很少发生,您可以使用级别触发让第二个模块知道数据已准备好。 (可以阅读this answer了解电平触发和边沿触发的区别)。

如果您需要处理流数据,则需要使用异步 FIFO。 (This answer 可能会为您提供更多信息)。

作为建议,我不会将信号断言用于特定周期数的方法,因为这对于可重用代码来说不是一个好习惯(它适用于这种特定设计,但您可能需要重新校准周期数,如果由于某种原因,您的时钟周期会发生变化)。

【讨论】:

  • 非常感谢您的回答。我选择另一个作为答案,但你也帮助了我,谢谢:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-17
  • 2019-12-01
  • 2010-10-07
  • 1970-01-01
相关资源
最近更新 更多