GCC Code Coverage Report
Directory: generated/vunit_out/preprocessed/ Exec Total Coverage
File: generated/vunit_out/preprocessed/resync/resync_level.vhd Lines: 13 13 100.0 %
Date: 2021-06-12 04:12:08 Branches: 29 40 72.5 %

Line Branch Exec Source
1
960
-- -------------------------------------------------------------------------------------------------
2
-- Copyright (c) Lukas Vik. All rights reserved.
3
--
4
-- This file is part of the tsfpga project.
5
-- https://tsfpga.com
6
-- https://gitlab.com/tsfpga/tsfpga
7
-- -------------------------------------------------------------------------------------------------
8
-- Resync a single bit from one clock domain to another.
9
--
10
-- The two registers will be placed in the same slice, in order to minimize
11
-- MTBF. This guarantees proper resynchronization of semi static "level" type
12
-- signals without meta stability on rising/falling edges. It can not handle
13
-- "pulse" type signals. Pulses can be missed and single-cycle pulse behaviour
14
-- will not work.
15
--
16
-- The clk_in port does not necessarily have to be set. But if you want to have
17
-- a deterministic latency through the resync block (via a set_max_delay
18
-- constraint) it has to be set. If not, a simple set_false_path constraint will
19
-- be used and the latency can be arbitrary, depending on the placer/router.
20
--
21
-- There is an option to include a register on the input side before the async_reg flip-flop chain.
22
-- This option is to prevent sampling of data when the input is in a transient "glitch" state, which
23
-- can occur if it is driven by a LUT as opposed to a flip-flop. If the input is already driven by
24
-- a flip-flop, you can safely set the generic to 'false' in order to save resources.
25
-- Note that this is a separate issue from meta-stability.
26
-- When this option is enabled, the 'clk_in' port must be driven with the correct clock.
27
--
28
-- Some motivation why this is needed:
29
-- While LUTs are designed to be glitch-free in order to save switching power, this can only be
30
-- achieved as long as only one LUT input value changes state. (See e.g. this thread:
31
-- https://forums.xilinx.com/t5/Other-FPGA-Architecture/Interior-switching-of-LUT5-SRAM/td-p/835012)
32
-- When more than one input changes state per clock cycle, glitches will almost ceratinly appear on
33
-- the LUT output before reaching its steady state.
34
-- This is partly due to difference in propagation delay between the inputs, and partly due to
35
-- the electrical structure of a LUT. In a regular synchronous design, the Vivado timing engine
36
-- guarantees that all these glitches have been resolved and LUT output has reached its
37
-- steady state before the value is sampled by a FF. When the value is fed to our async_reg FF
38
-- chain however there is no control over this, and we may very well sample an erroneous
39
-- glitch value.
40
-- So given this knowledge the rule of thumb is to always drive resync_level input by a FF.
41
-- However since LUTs are glitch-free in some scenarios, exceptions can be made if we are sure
42
-- of what we are doing. For example if the value is inverted in a LUT before being fed to
43
-- resync_level, then that is a scenario where we do not actually need the extra FF.
44
-- -------------------------------------------------------------------------------------------------
45
46
library ieee;
47
use ieee.std_logic_1164.all;
48
49
library common;
50
use common.attribute_pkg.all;
51
52
53

76113
entity resync_level is
54
  generic (
55
    -- Enable or disable a register on the input side before the async_reg flip-flip chain.
56
    -- Must be used if the input can contain glitches. See header for more details.
57
    -- The 'clk_in' port must be assigned if this generic is set to 'true'.
58
    enable_input_register : boolean;
59
    -- Initial value for the ouput that will be set for a few cycles before the first input
60
    -- value has propagated.
61
    default_value : std_logic := '0'
62
  );
63
  port (
64
    clk_in : in std_logic := '-';
65
    data_in : in std_logic;
66
67
    clk_out : in std_logic;
68
    data_out : out std_logic
69
  );
70
end entity;
71
72
architecture a of resync_level is
73
160
  signal data_in_int, data_in_p1, data_out_int : std_logic := default_value;
74
75
  attribute async_reg of data_in_p1 : signal is "true";
76
  attribute async_reg of data_out_int : signal is "true";
77
begin
78
79
  -- This check will trigger in simulation, but will probably not work in synthesis
80
76527
  assert clk_in /= '-' or not enable_input_register
81
    report "Must assign clock when using input register"
82
    severity failure;
83
84


11487
  data_out <= data_out_int;
85
86
87
  ------------------------------------------------------------------------------
88
  assign_input : if enable_input_register generate
89
90
    ------------------------------------------------------------------------------
91
213
    input_register : process
92
    begin
93

9793
      wait until rising_edge(clk_in);
94
95

4886
      data_in_int <= data_in;
96
    end process;
97
98
  else generate
99
100


173629
    data_in_int <= data_in;
101
102
  end generate;
103
104
105
  ------------------------------------------------------------------------------
106
160
  main : process
107
  begin
108

171738
    wait until rising_edge(clk_out);
109

42920
    data_out_int <= data_in_p1;
110

86000
    data_in_p1 <= data_in_int;
111
  end process;
112
113
end architecture;