特定时间的高信号
Signal high for a specific time
我做了一个包含 2 个模块的 VHDL 设计。一个以 100 Mhz 的频率处理通信和 运行s(我无法更改)。另一个模块进行计算,并且由于计时的原因,必须以 45 Mhz 运行。
第二个模块有一个名为 "newPair" 的输入引脚,我想在新数据准备就绪时将其设置为高电平,并且可以由第二个模块处理。现在我的第二个模块只在时钟的上升沿工作,所以我需要将这个引脚设置为一个 45 Mhz 时钟周期的高电平,然后将其拉低。这必须从模块 which 运行s at 45 Mhz 完成。我怎样才能做到这一点?我想为此目的创建一个 DCM,但这似乎有点过分了。
谢谢!
更新:
我正在研究 Spartan-6 (xc6slx150)
您的设计有 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 变体。
另请参阅赛灵思 ISE 设计的 UCF 文件中存储的这些时序约束:
- 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;
第 2 部分 - 特殊合成器电路
我假设您还将数据从一个时钟域传输到另一个时钟域。因此,您需要一个多位同步器(建立在选通同步器之上)或一个支持交叉时钟的 FIFO。
我贡献的 PoC 库也有多个 bit/vector 同步器。查看链接源文件夹中的其他模块。还有一个交叉时钟/独立时钟(ic)FIFO。
您不需要在特定时间内断言某些信号。
如果第一个模块和第二个模块之间的数据交换很少发生,您可以使用电平触发让第二个模块知道数据已准备就绪。 (您可以阅读 this answer 以了解电平触发和边沿触发之间的区别)。
如果您需要处理流数据,则需要使用异步 FIFO。 (This answer 可能会为您提供更多信息)。
作为建议,我不会对特定周期数方法使用信号断言,因为这不是可重用代码的好做法(它适用于此特定设计,但您可能需要重新校准周期数如果您的时钟周期因某种原因发生变化)。
我做了一个包含 2 个模块的 VHDL 设计。一个以 100 Mhz 的频率处理通信和 运行s(我无法更改)。另一个模块进行计算,并且由于计时的原因,必须以 45 Mhz 运行。
第二个模块有一个名为 "newPair" 的输入引脚,我想在新数据准备就绪时将其设置为高电平,并且可以由第二个模块处理。现在我的第二个模块只在时钟的上升沿工作,所以我需要将这个引脚设置为一个 45 Mhz 时钟周期的高电平,然后将其拉低。这必须从模块 which 运行s at 45 Mhz 完成。我怎样才能做到这一点?我想为此目的创建一个 DCM,但这似乎有点过分了。
谢谢!
更新:
我正在研究 Spartan-6 (xc6slx150)
您的设计有 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 变体。
另请参阅赛灵思 ISE 设计的 UCF 文件中存储的这些时序约束:
- 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;
第 2 部分 - 特殊合成器电路
我假设您还将数据从一个时钟域传输到另一个时钟域。因此,您需要一个多位同步器(建立在选通同步器之上)或一个支持交叉时钟的 FIFO。
我贡献的 PoC 库也有多个 bit/vector 同步器。查看链接源文件夹中的其他模块。还有一个交叉时钟/独立时钟(ic)FIFO。
您不需要在特定时间内断言某些信号。
如果第一个模块和第二个模块之间的数据交换很少发生,您可以使用电平触发让第二个模块知道数据已准备就绪。 (您可以阅读 this answer 以了解电平触发和边沿触发之间的区别)。
如果您需要处理流数据,则需要使用异步 FIFO。 (This answer 可能会为您提供更多信息)。
作为建议,我不会对特定周期数方法使用信号断言,因为这不是可重用代码的好做法(它适用于此特定设计,但您可能需要重新校准周期数如果您的时钟周期因某种原因发生变化)。