我想将脉冲从一个时钟域clk1传输到另一个时钟域clk2,但是我们不知道哪个比另一个快! 最好的方法是什么?
谢谢
答案 0 :(得分:0)
您需要一个选通同步器。
选通同步器将输入的上升沿转换为电平变化(T-FF)。该电平变化通过2-FF同步器传输到第二个时钟域。然后通过XOR门恢复该信息。 (注意:T-FF是具有XOR的D-FF,用于在每个高输入上反转状态。)
此外,可以计算繁忙状态以将整个电路的状态通知发送时钟域。此繁忙信号可用于锁定输入的上升沿检测。
同时包含多个位的源代码:
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all;
library PoC;
use PoC.sync.all;
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)
SYNC_DEPTH : T_MISC_SYNC_DEPTH := T_MISC_SYNC_DEPTH'low -- generate SYNC_DEPTH many stages, at least 2
);
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 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
SYNC_DEPTH => SYNC_DEPTH
)
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
SYNC_DEPTH => SYNC_DEPTH
)
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
答案 1 :(得分:0)
另一种解决方法是Flancter,由Doulos最好地解释:
答案 2 :(得分:0)
嘿,我有此代码的Verilog版本与xilinx工具兼容,
src_pulse-> src_clk level_convertor-> 2级dest同步器-> dest_pulse检测器
这是在2个关系未知时钟域之间传输脉冲时要遵循的顺序步骤。
module pulse_cdc(
input src_clk,
input src_pulse,
input dest_clk,
output logic dest_pulse
);
(* ASYNC_REG = "TRUE" *)logic [2:0] dest_sync;
logic src_clk_level = '0;
//------------------------------//
//-- Pulse to level convertor --//
//------------------------------//
always_ff @(posedge src_clk)
if(src_pulse) src_clk_level <= #10 ~src_clk_level;
else src_clk_level <= #10 src_clk_level;
//----------------------------//
//------- Synchronizer -------//
//----------------------------//
always_ff @(dest_clk)begin
dest_sync[0] <= #10 src_clk_level;
dest_sync[1] <= #10 dest_sync[0];
dest_sync[2] <= #10 dest_sync[1];
end
//-------------------------//
//--- Pulse Generator -----//
//-------------------------//
always_comb dest_pulse = dest_sync[1] ^ dest_sync[2];
endmodule