axi_i2s_adi: Overhaul CDC
* Generate a separate synchronous reset for the data clock domain. * Add missing stage to toggle synchronizers. * Give a common prefix to CDC elements and add the proper constraints to the XDC file * Remove some unnecessary resets Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>main
parent
8289262807
commit
dfc22fc7de
|
@ -0,0 +1,26 @@
|
|||
set ctrl_clk [get_clocks -of_objects [get_ports S_AXI_ACLK]]
|
||||
set data_clk [get_clocks -of_objects [get_ports DATA_CLK_I]]
|
||||
|
||||
set_property ASYNC_REG TRUE \
|
||||
[get_cells -hier cdc_sync_stage1_*_reg] \
|
||||
[get_cells -hier cdc_sync_stage2_*_reg]
|
||||
|
||||
set_false_path \
|
||||
-from [get_cells -hier cdc_sync_stage0_*_reg -filter {PRIMITIVE_SUBGROUP == flop}] \
|
||||
-to [get_cells -hier cdc_sync_stage1_*_reg -filter {PRIMITIVE_SUBGROUP == flop}]
|
||||
|
||||
# TX FIFO
|
||||
set_max_delay \
|
||||
-from $ctrl_clk \
|
||||
-to [get_cells -hier out_data_reg* -filter {PRIMITIVE_SUBGROUP == flop && NAME =~ *tx_sync*}] \
|
||||
[get_property PERIOD $data_clk] -datapath_only
|
||||
|
||||
# RX FIFO
|
||||
set_max_delay \
|
||||
-from $data_clk \
|
||||
-to [get_cells -hier out_data_reg* -filter {PRIMITIVE_SUBGROUP == flop && NAME =~ *rx_sync*}] \
|
||||
[get_property PERIOD $ctrl_clk] -datapath_only
|
||||
|
||||
# Reset
|
||||
set_false_path \
|
||||
-to [get_pins -hier data_reset_vec_reg*/PRE]
|
|
@ -15,9 +15,12 @@ adi_ip_files axi_i2s_adi [list \
|
|||
"i2s_tx.vhd" \
|
||||
"i2s_clkgen.vhd" \
|
||||
"fifo_synchronizer.vhd" \
|
||||
"axi_i2s_adi.vhd" ]
|
||||
"axi_i2s_adi.vhd" \
|
||||
"axi_i2s_adi_constr.xdc" \
|
||||
]
|
||||
|
||||
adi_ip_properties_lite axi_i2s_adi
|
||||
adi_ip_constraints axi_spdif_tx axi_i2s_adi_constr.xdc late
|
||||
|
||||
adi_add_bus "DMA_ACK_RX" "slave" \
|
||||
"xilinx.com:interface:axis_rtl:1.0" \
|
||||
|
|
|
@ -45,13 +45,14 @@ entity fifo_synchronizer is
|
|||
WIDTH : integer := 2
|
||||
);
|
||||
port (
|
||||
resetn : in std_logic;
|
||||
|
||||
in_clk : in std_logic;
|
||||
in_resetn : in std_logic;
|
||||
in_data : in std_logic_vector(WIDTH - 1 downto 0);
|
||||
in_tick : in std_logic;
|
||||
|
||||
out_clk : in std_logic;
|
||||
out_resetn : in std_logic;
|
||||
out_data : out std_logic_vector(WIDTH - 1 downto 0);
|
||||
out_tick : out std_logic
|
||||
);
|
||||
|
@ -65,22 +66,31 @@ architecture impl of fifo_synchronizer is
|
|||
signal rd_addr : natural range 0 to DEPTH - 1;
|
||||
signal wr_addr : natural range 0 to DEPTH - 1;
|
||||
|
||||
signal cdc_sync_stage0_tick : std_logic;
|
||||
signal cdc_sync_stage1_tick : std_logic;
|
||||
signal cdc_sync_stage2_tick : std_logic;
|
||||
signal cdc_sync_stage3_tick : std_logic;
|
||||
signal tick : std_logic;
|
||||
signal tick_d1 : std_logic;
|
||||
signal tick_d2 : std_logic;
|
||||
begin
|
||||
|
||||
process (in_clk)
|
||||
begin
|
||||
if rising_edge(in_clk) then
|
||||
if resetn = '0' then
|
||||
if in_tick = '1' then
|
||||
cdc_sync_stage0_tick <= not cdc_sync_stage0_tick;
|
||||
fifo(wr_addr) <= in_data;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (in_clk)
|
||||
begin
|
||||
if rising_edge(in_clk) then
|
||||
if in_resetn = '0' then
|
||||
wr_addr <= 0;
|
||||
tick <= '0';
|
||||
else
|
||||
if in_tick = '1' then
|
||||
fifo(wr_addr) <= in_data;
|
||||
wr_addr <= (wr_addr + 1) mod DEPTH;
|
||||
tick <= not tick;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
|
@ -89,20 +99,34 @@ begin
|
|||
process (out_clk)
|
||||
begin
|
||||
if rising_edge(out_clk) then
|
||||
if resetn = '0' then
|
||||
rd_addr <= 0;
|
||||
tick_d1 <= '0';
|
||||
tick_d2 <= '0';
|
||||
else
|
||||
tick_d1 <= tick;
|
||||
tick_d2 <= tick_d1;
|
||||
out_tick <= tick_d1 xor tick_d2;
|
||||
if (tick_d1 xor tick_d2) = '1' then
|
||||
rd_addr <= (rd_addr + 1) mod DEPTH;
|
||||
out_data <= fifo(rd_addr);
|
||||
cdc_sync_stage1_tick <= cdc_sync_stage0_tick;
|
||||
cdc_sync_stage2_tick <= cdc_sync_stage1_tick;
|
||||
cdc_sync_stage3_tick <= cdc_sync_stage2_tick;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
tick <= cdc_sync_stage2_tick xor cdc_sync_stage3_tick;
|
||||
out_tick <= tick;
|
||||
|
||||
process (out_clk)
|
||||
begin
|
||||
if rising_edge(out_clk) then
|
||||
if tick = '1' then
|
||||
out_data <= fifo(rd_addr);
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (out_clk)
|
||||
begin
|
||||
if rising_edge(out_clk) then
|
||||
if out_resetn = '0' then
|
||||
rd_addr <= 0;
|
||||
else
|
||||
if tick = '1' then
|
||||
rd_addr <= (rd_addr + 1) mod DEPTH;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
end;
|
||||
|
|
|
@ -86,9 +86,10 @@ constant NUM_RX : integer := C_HAS_RX * C_NUM_CH;
|
|||
|
||||
signal enable : Boolean;
|
||||
|
||||
signal tick : std_logic;
|
||||
signal tick_d1 : std_logic;
|
||||
signal tick_d2 : std_logic;
|
||||
signal cdc_sync_stage0_tick : std_logic;
|
||||
signal cdc_sync_stage1_tick : std_logic;
|
||||
signal cdc_sync_stage2_tick : std_logic;
|
||||
signal cdc_sync_stage3_tick : std_logic;
|
||||
|
||||
signal BCLK_O_int : std_logic;
|
||||
signal LRCLK_O_int : std_logic;
|
||||
|
@ -114,37 +115,43 @@ signal tx_sync_fifo_in : std_logic_vector(3 + NUM_TX downto 0);
|
|||
signal rx_sync_fifo_out : std_logic_vector(3 + NUM_RX downto 0);
|
||||
signal rx_sync_fifo_in : std_logic_vector(3 + NUM_RX downto 0);
|
||||
|
||||
signal data_resetn : std_logic;
|
||||
signal data_reset_vec : std_logic_vector(2 downto 0);
|
||||
|
||||
begin
|
||||
enable <= rx_enable or tx_enable;
|
||||
|
||||
const_1 <= '1';
|
||||
process (data_clk, resetn)
|
||||
begin
|
||||
if resetn = '0' then
|
||||
data_reset_vec <= (others => '1');
|
||||
elsif rising_edge(data_clk) then
|
||||
data_reset_vec(2 downto 1) <= data_reset_vec(1 downto 0);
|
||||
data_reset_vec(0) <= '0';
|
||||
end if;
|
||||
end process;
|
||||
|
||||
data_resetn <= not data_reset_vec(2);
|
||||
|
||||
-- Generate tick signal in the DATA_CLK_I domain
|
||||
process (data_clk)
|
||||
begin
|
||||
if rising_edge(data_clk) then
|
||||
if resetn = '0' then
|
||||
tick <= '0';
|
||||
else
|
||||
tick <= not tick;
|
||||
end if;
|
||||
cdc_sync_stage0_tick <= not cdc_sync_stage0_tick;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
process (clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if resetn = '0' then
|
||||
tick_d1 <= '0';
|
||||
tick_d2 <= '0';
|
||||
else
|
||||
tick_d1 <= tick;
|
||||
tick_d2 <= tick_d1;
|
||||
end if;
|
||||
cdc_sync_stage1_tick <= cdc_sync_stage0_tick;
|
||||
cdc_sync_stage2_tick <= cdc_sync_stage1_tick;
|
||||
cdc_sync_stage3_tick <= cdc_sync_stage2_tick;
|
||||
end if;
|
||||
end process;
|
||||
|
||||
tx_tick <= tick_d2 xor tick_d1;
|
||||
tx_tick <= cdc_sync_stage2_tick xor cdc_sync_stage3_tick;
|
||||
|
||||
tx_sync_fifo_in(0) <= tx_channel_sync;
|
||||
tx_sync_fifo_in(1) <= tx_frame_sync;
|
||||
|
@ -152,10 +159,11 @@ begin
|
|||
tx_sync_fifo_in(3) <= tx_lrclk;
|
||||
tx_sync_fifo_in(3 + NUM_TX downto 4) <= tx_sdata;
|
||||
|
||||
|
||||
process (data_clk)
|
||||
begin
|
||||
if rising_edge(data_clk) then
|
||||
if resetn = '0' then
|
||||
if data_resetn = '0' then
|
||||
BCLK_O <= (others => '1');
|
||||
LRCLK_O <= (others => '1');
|
||||
SDATA_O <= (others => '0');
|
||||
|
@ -190,11 +198,12 @@ begin
|
|||
WIDTH => NUM_TX + 4
|
||||
)
|
||||
port map (
|
||||
resetn => resetn,
|
||||
in_resetn => resetn,
|
||||
in_clk => clk,
|
||||
in_data => tx_sync_fifo_in,
|
||||
in_tick => tx_tick,
|
||||
|
||||
out_resetn => data_resetn,
|
||||
out_clk => data_clk,
|
||||
out_data => tx_sync_fifo_out
|
||||
);
|
||||
|
@ -271,11 +280,12 @@ begin
|
|||
WIDTH => NUM_RX + 4
|
||||
)
|
||||
port map (
|
||||
resetn => resetn,
|
||||
in_resetn => data_resetn,
|
||||
in_clk => data_clk,
|
||||
in_data => rx_sync_fifo_in,
|
||||
in_tick => const_1,
|
||||
|
||||
out_resetn => resetn,
|
||||
out_clk => clk,
|
||||
out_data => rx_sync_fifo_out
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue