From aac0b7f4e8714a0f4ab2e1a003daa58d796f3034 Mon Sep 17 00:00:00 2001 From: Eric Kooistra <kooistra@astron.nl> Date: Tue, 18 Feb 2020 16:55:47 +0100 Subject: [PATCH] Explained delta-cycles in VHDL simulation. --- libraries/base/common/hdllib.cfg | 1 + .../common/tb/vhdl/tb_delta_cycle_demo.vhd | 137 ++++++++++++++++++ 2 files changed, 138 insertions(+) create mode 100644 libraries/base/common/tb/vhdl/tb_delta_cycle_demo.vhd diff --git a/libraries/base/common/hdllib.cfg b/libraries/base/common/hdllib.cfg index d5624d00cb..df646d9c66 100644 --- a/libraries/base/common/hdllib.cfg +++ b/libraries/base/common/hdllib.cfg @@ -193,6 +193,7 @@ test_bench_files = tb/vhdl/tb_requantize.vhd tb/vhdl/tb_resize.vhd tb/vhdl/tb_round.vhd + tb/vhdl/tb_delta_cycle_demo.vhd tb/vhdl/tb_tb_common_add_sub.vhd tb/vhdl/tb_tb_common_adder_tree.vhd diff --git a/libraries/base/common/tb/vhdl/tb_delta_cycle_demo.vhd b/libraries/base/common/tb/vhdl/tb_delta_cycle_demo.vhd new file mode 100644 index 0000000000..c27c92bf26 --- /dev/null +++ b/libraries/base/common/tb/vhdl/tb_delta_cycle_demo.vhd @@ -0,0 +1,137 @@ +------------------------------------------------------------------------------- +-- +-- Copyright 2020 +-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/> +-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands +-- +-- Licensed under the Apache 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://www.apache.org/licenses/LICENSE-2.0 +-- +-- Unless required by applicable law or agreed to in writing, software +-- distributed under the 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. +-- +------------------------------------------------------------------------------- + +------------------------------------------------------------------------------- +-- +-- Author: E. Kooistra +-- Purpose: Demonstrate harmful effect of delta-cycle difference between a +-- clock and a copied clock and how to solve this. +-- Description: +-- 1) The problem: +-- The assignment of clk2 <= clk1 causes that in simulation clk2 differs from +-- clk1 by one delta cycle and that results in that in simulation d1 /= d2, +-- while on hardware d1 = d2, because the delta cycle on the clk2 does not +-- impact synthesis, because in hardware clk1 and clk2 are the same clock +-- tree. The clk1 is typically a clock that comes from an PLL in the design, +-- so it is generated in the FPGA. +-- +-- 2) The solution +-- a)If an assignment like clk2 <= clk1 is done, then make sure that this is +-- the only place where clk1 is used. +-- +-- b)For a clk1 that is needed within a certain component and also outside +-- that component there are two solutions: +-- 1) Assign clk2_out <= clk1, where clk2_out is an OUT port on that +-- component. The component then also needs a clk2 IN port and then both +-- clk2_out OUT and clk2 IN are mapped to the same clk2 signal. The clk2 +-- signal has the same delta cycle phase inside the component and outside +-- the component, because going through the component IO hierarchy does +-- not cause extra delta-cycles delays. The PORT MAP of the instanciated +-- component then has: +-- +-- PORT MAP ( +-- ... +-- clk2_out => clk2 +-- clk2 => clk2 +-- --- +-- ); +-- +-- and both internally in the component and externally only clk2 is used +-- for clocking logic. +-- 2) Balance the delta-cycle delays, so assign clk2_out <= clk1 for the +-- OUT port and assign clk2_int <= clk1 for internal usage inside this +-- component. Both clk2_out and clk2_int have the same delta-cycle +-- phase, so logic can be clocked at either clock without affecting the +-- timing in simulation. +-- +-- Conclusion: +-- Scheme 2b1 is used in ctrl_unb*_board.vhd and in the io_ddr.vhd. However +-- scheme 2b2 is preferred, because it avoids that clk1 has to traverse up +-- and back down the hierarchy of one or more components in an FPGA design, +-- to reach a common single high level that can source the clk1 back down +-- to every where it is used.. +-- +-- Note that it is not allowed in VHDL to use (read) an OUT port. To read +-- an OUT port it is necessary to use an auxiliary signal, e.g. i_xout for +-- OUT xout and then do x_out <= i_x_out and i_xout can be used internally. +-- This scheme cannot be used for clk2 OUT, because then clk2 <= i_clk2 +-- would again cause the delta-cycle delay difference between i_clk2 and +-- clk2 that needs to be avoided. Therefore the solution 2b is needed if a +-- clk2 that is created inside a component (e.g. by an PLL) is also used +-- outside this component. +-- +-- Usage: +-- +-- Modelsim> as 5 +-- Modelsim> run -a +-- Observe in Wave Window that d1 /= d2. +-- +------------------------------------------------------------------------------- + +LIBRARY IEEE; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.NUMERIC_STD.ALL; + + +ENTITY tb_delta_cycle_demo IS +END tb_delta_cycle_demo; + +ARCHITECTURE tb OF tb_delta_cycle_demo IS + + CONSTANT clk_period : TIME := 10 ns; + + SIGNAL tb_end : STD_LOGIC := '0'; + SIGNAL clk1 : STD_LOGIC := '1'; + SIGNAL clk2 : STD_LOGIC := '1'; + SIGNAL data : STD_LOGIC := '0'; + SIGNAL d1 : STD_LOGIC; + SIGNAL d2 : STD_LOGIC; + +BEGIN + + -- Stimuli + clk1 <= NOT clk1 OR tb_end AFTER clk_period/2; + clk2 <= clk1; + + p_data : PROCESS + BEGIN + data <= '0'; + FOR I IN 0 TO 2 LOOP WAIT UNTIL rising_edge(clk1); END LOOP; + data <= '1'; + FOR I IN 0 TO 2 LOOP WAIT UNTIL rising_edge(clk1); END LOOP; + END PROCESS; + + p_clk1 : PROCESS (clk1) + BEGIN + IF rising_edge(clk1) THEN + d1 <= data; + END IF; + END PROCESS; + + p_clk2 : PROCESS (clk2) + BEGIN + IF rising_edge(clk2) THEN + d2 <= data; + END IF; + END PROCESS; + + tb_end <= '0', '1' AFTER 1 us; + +END tb; -- GitLab