diff --git a/README.md b/README.md index 6a18cd1365a1391803af0c399600444d0e97febc..26f052d2a8228b4a9c14a58ce6d9c1d512d29533 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,9 @@ In [modules/common](modules/common) there are general purpose cores: array of std_logic, and some subprograms to handle it. * For clock-domain crossing or asynchronous signal register, use - [gc_sync_ffs](modules/common/gc_sync_ffs.vhd). It also has an edge - detector. + [gc_sync](modules/common/gc_sync.vhd). This is the basic synchronizer. + If you also need an edge detector, use + [gc_sync_ffs](modules/common/gc_sync_ffs.vhd). The other synchronizer [gc_sync_register](modules/common/gc_sync_register.vhd) is deprecated. It can synchronize multiple signals at the same time but doesn't ensure coherency between these signals. diff --git a/modules/common/Manifest.py b/modules/common/Manifest.py index 68c45dd86391755597f719032cea60b57eed49bb..7f356aeca3c09d3af48b70f2b1586041c81655de 100644 --- a/modules/common/Manifest.py +++ b/modules/common/Manifest.py @@ -11,6 +11,8 @@ files = [ "gc_serial_dac.vhd", "gc_sync_ffs.vhd", "gc_arbitrated_mux.vhd", + "gc_sync_register.vhd", + "gc_sync.vhd", "gc_pulse_synchronizer.vhd", "gc_pulse_synchronizer2.vhd", "gc_frequency_meter.vhd", @@ -25,7 +27,6 @@ files = [ "gc_big_adder.vhd", "gc_fsm_watchdog.vhd", "gc_bicolor_led_ctrl.vhd", - "gc_sync_register.vhd", "gc_single_reset_gen.vhd", "gc_async_signals_input_stage.vhd", "gc_dec_8b10b.vhd", diff --git a/modules/common/gc_sync.vhd b/modules/common/gc_sync.vhd new file mode 100644 index 0000000000000000000000000000000000000000..f287c9b9c3000c460deed5ddeae1bc98a990ff36 --- /dev/null +++ b/modules/common/gc_sync.vhd @@ -0,0 +1,79 @@ +-------------------------------------------------------------------------------- +-- CERN BE-CO-HT +-- General Cores Library +-- https://www.ohwr.org/projects/general-cores +-------------------------------------------------------------------------------- +-- +-- unit name: gc_sync +-- +-- description: Elementary synchronizer. +-- +-------------------------------------------------------------------------------- +-- Copyright CERN 2014-2018 +-------------------------------------------------------------------------------- +-- Copyright and related rights are licensed under the Solderpad Hardware +-- License, Version 2.0 (the "License"); you may not use this file except +-- in compliance with the License. You may obtain a copy of the License at +-- http://solderpad.org/licenses/SHL-2.0. +-- Unless required by applicable law or agreed to in writing, software, +-- hardware and materials distributed under this License is distributed on an +-- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express +-- or implied. See the License for the specific language governing permissions +-- and limitations under the License. +-------------------------------------------------------------------------------- + +library ieee; +use ieee.std_logic_1164.all; + +entity gc_sync is + port ( + clk_i : in std_logic; + rst_n_a_i : in std_logic; + d_i : in std_logic; + q_o : out std_logic; + +end gc_sync; + +-- make Altera Quartus quiet regarding unknown attributes: +-- altera message_off 10335 + +architecture rtl of gc_sync is + + -- Use an intermediate signal with a particular name and a keep attribute + -- so that it can be referenced in the constraints in order to ignore + -- timing (TIG) on that signal. + signal gc_sync_ffs_in : std_logic; + + signal sync0, sync1 : std_logic; + + attribute shreg_extract : string; + attribute shreg_extract of gc_sync_ffs_in : signal is "no"; + attribute shreg_extract of sync0 : signal is "no"; + attribute shreg_extract of sync1 : signal is "no"; + + attribute keep : string; + attribute keep of gc_sync_ffs_in : signal is "true"; + attribute keep of sync0 : signal is "true"; + attribute keep of sync1 : signal is "true"; + + attribute async_reg : string; + attribute async_reg of gc_sync_ffs_in : signal is "true"; + attribute async_reg of sync0 : signal is "true"; + attribute async_reg of sync1 : signal is "true"; + +begin + + process(clk_i, rst_n_a_i) + begin + if rst_n_a_i = '0' then + sync1 <= '0'; + sync0 <= '0'; + elsif rising_edge(clk_i) then + sync0 <= gc_sync_ffs_in; + sync1 <= sync0; + end if; + end process; + + gc_sync_ffs_in <= d_i; + q_o <= sync1; +end rtl;