Michael Grover
Michael Grover

Reputation: 87

VHDL No Delta Delay Input to Output Assignment

I've got a situation like the following:

library ieee;
use ieee.std_logic_1164;

entity clkin_to_clkout is
port (
  clk_in : in std_logic;
  clk_out : out std_logic);
end entity clkin_to_clkout;

architecture arch of clkin_to_clkout is
begin

    clk_out <= clk_in;

end architecture arch;

The assignment of clk_in to clk_out isn't a problem for synthesis, but in a simulator it will induce a delta delay from clk_in to clk_out, thereby creating a clock crossing boundary. Is there any way to assign an entity output to an entity input without introducing a delta delay? Thanks.

Edit: Responses to some comments. First, I want this exact question answered, please. For clarification, I want the output port to behave exactly as if it were an alias of the input port. If the answer is, "In VHDL there is no possible way to make an output port an exact behavioral match of an input port", then that is the correct answer and I'll accept it as a limitation of the language. Second, if you don't see what the problem is, please instantiate the clkin_to_clkout entity in the following testbench and observe the difference between mr_sig_del_dly vs mr_sig_clk_dly when you simulate for a few clk1 cycles:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity delta_delay is
end entity delta_delay;

architecture arch of delta_delay is

  signal clk1: std_logic := '0';
  signal clk2 : std_logic;
  signal mr_sig : unsigned(7 downto 0) := (others => '0');
  signal mr_sig_del_dly : unsigned(7 downto 0);
  signal mr_sig_clk_dly : unsigned(7 downto 0);

  component clkin_to_clkout is
  port (
    clk_in : in std_logic;
    clk_out : out std_logic);
  end component clkin_to_clkout;

begin

  clk1 <= not clk1 after 10 ns;

  clk_inst : clkin_to_clkout
  port map (
    clk_in  => clk1,
    clk_out => clk2);

  mr_sig <= mr_sig + 1 when rising_edge(clk1);
  mr_sig_del_dly <= mr_sig when rising_edge(clk2);
  mr_sig_clk_dly <= mr_sig when rising_edge(clk1);

end architecture arch;

When you simulate, you will observe that mr_sig_clk_dly is delayed 1 clock cycle as expected because it is assigned on the same clock that mr_sig is on (clk1). mr_sig_del_dly is not delayed 1 clk1 cycle even though clk2 is just a passthrough of clk1 in the clkin_to_clkout module. This is because clk2 is a delta delayed version of clk1 because I used a signal assignment. Again, thanks for all your responses.

Upvotes: 0

Views: 1011

Answers (2)

JHBonarius
JHBonarius

Reputation: 11271

It seems you do not know what a delta delay is. A delta delay is an infinity small delay. Every assignment has (at least) a delta delay in simulation. That's just how VHDL works.

edit:

After your comments, I see where you are coming from. The issue you are encountering is probably simulation only, as synthesis will simplify it. However, there is a electronic equivalent, being the multi-phase clocks. Consider you want a 2-phase clock, i.e. differential signal, where the second signal is the inverse of the first. If you would realize these clocks by just using one invertor, the second signal would have a phase offset. This is due to the latency of the invertor component. Thus, in clock generating logic (like PLL and DCM) the not-inverted signal is also delayed (using a variable latency buffer). I.e. all clock signals need to be processed, giving them the same (delta) delay.

The same solution can be applied in VHDL. Example:

library ieee;
use ieee.std_logic_1164.all;

entity clk_buffers is
    port(
        clk : in std_logic;
        clk1 : out std_logic;
        clk2_n : out std_logic
        );
end entity;

architecture rtl of clk_buffers is begin
    clk1 <= clk;
    clk2_n <= not clk;
end architecture;

library ieee;

entity test_bench is end entity;
architecture behavioural of test_bench is
    use ieee.std_logic_1164.all;
    signal clk, clk1, clk2_n : std_logic := '1';
    signal base, child1, child2 : integer := 0;
begin
    clk <= not clk after 1 ns;

    clk_buffers_inst : entity work.clk_buffers
        port map(clk => clk, clk1 => clk1, clk2_n => clk2_n);
        
    base <= base+1 when rising_edge(clk1);
    child1 <= base when rising_edge(clk1);
    child2 <= base when falling_edge(clk2_n);
end architecture;

enter image description here

Upvotes: 0

Michael Grover
Michael Grover

Reputation: 87

In VHDL-2008 or before there is no possible way to make an output port an exact behavioral match of an input port. Reference Jim Lewis's comment to the original question. Thanks, Jim and to all who opined.

Upvotes: 0

Related Questions