cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
SoC_Designer
Observer
Observer
982 Views
Registered: ‎04-29-2020

Timing Constraints Warnings During Translate

So I have an embedded system which is constrained with these constraints.

 

TIMEGRP uPC_RST = FFS(RST_CPU);
TIMEGRP Sys_RST = FFS(RST_SYSTEM);
#
#
TIMEGRP clk_1_grp = RISING  "SoC_CLK_AsymDualCore_SoC_PLL_clkout0";
TIMEGRP clk_2_grp = RISING  "SoC_CLK_AsymDualCore_SoC_PLL_clkout1";
TIMEGRP clk_3_grp = RISING  "SoC_CLK_AsymDualCore_SoC_PLL_clkout2";
TIMEGRP clk_4_grp = RISING  "SoC_CLK_AsymDualCore_SoC_PLL_clkout3";

##====================================================================================
##                              MULTICYCLE CLOCK PATHS
##====================================================================================
TIMESPEC TS_EXT_CLK_TO_CLK1 = FROM "EXT_CLK" TO "clk_1_grp" TS_EXT_CLK ;
TIMESPEC TS_CLK1_TO_EXT_CLK = FROM "clk_1_grp" TO "EXT_CLK" TS_EXT_CLK ;
 
TIMESPEC TS_clk1_to_clk2 = FROM "clk_1_grp" TO "clk_2_grp" SoC_CLK_AsymDualCore_SoC_PLL_clkout0  DATAPATHONLY;
TIMESPEC TS_clk2_to_clk1 = FROM "clk_2_grp" TO "clk_1_grp" SoC_CLK_AsymDualCore_SoC_PLL_clkout0  DATAPATHONLY;
TIMESPEC TS_clk1_to_clk3 = FROM "clk_1_grp" TO "clk_3_grp" SoC_CLK_AsymDualCore_SoC_PLL_clkout0  DATAPATHONLY;
TIMESPEC TS_clk3_to_clk1 = FROM "clk_3_grp" TO "clk_1_grp" SoC_CLK_AsymDualCore_SoC_PLL_clkout0  DATAPATHONLY;
                                
TIMESPEC TS_clk1_to_clk4 = FROM "clk_1_grp" TO "clk_4_grp" SoC_CLK_AsymDualCore_SoC_PLL_clkout0  DATAPATHONLY;
TIMESPEC TS_clk4_to_clk1 = FROM "clk_4_grp" TO "clk_1_grp" SoC_CLK_AsymDualCore_SoC_PLL_clkout0  DATAPATHONLY;

TIMESPEC TS_SYS_RST_to_CLKGRP_1 = FROM "Sys_RST" TO "clk_1_grp" SoC_CLK_AsymDualCore_SoC_PLL_clkout0  DATAPATHONLY;
TIMESPEC TS_SYS_RST_to_CLKGRP_2 = FROM "Sys_RST" TO "clk_2_grp" SoC_CLK_AsymDualCore_SoC_PLL_clkout0  DATAPATHONLY;
TIMESPEC TS_uPC_RST_to_CLKGRP_1 = FROM "uPC_RST" TO "clk_1_grp" SoC_CLK_AsymDualCore_SoC_PLL_clkout0  DATAPATHONLY;
TIMESPEC TS_uPC_RST_to_CLKGRP_2 = FROM "uPC_RST" TO "clk_2_grp" SoC_CLK_AsymDualCore_SoC_PLL_clkout0  DATAPATHONLY;

 

The PLL Block generating these output clock signals is below .... 

 

-- Input buffering
  --------------------------------------
  
  clkin1_buf : IBUFG
  port map
   (O => CLK_IN1,
    I => EXT_CLK);

  CLKIN_IBUFG_OUT <= CLK_IN1;
  
  AsymDualCore_SoC_PLL : entity work.AsymDualCore_SoC_PLL
  port map (
  
    -- Clock in ports
    CLK_IN1  => CLK_IN1,
    -- Clock out ports
    CLK_OUT1 => clkout0,
    CLK_OUT2 => clkout1,
    CLK_OUT3 => clkout2,
    CLK_OUT4 => clkout3,
    -- Status and control signals
    RESET    => RESET,
    LOCKED   => LOCKED
    );
    
  CLK_OUT1 <= clkout0;
  CLK_OUT2 <= clkout1;
  CLK_OUT3 <= clkout2;
  CLK_OUT4 <= clkout3;  
    
  -- Processor clock enables
  
  uPC0_CLK_BUFGCE : BUFGCE
   port map (
      O  => uPC0_CLK,    -- 1-bit output: Clock buffer output
      CE => uPC_CLK_EN(0), -- 1-bit input: Clock buffer select
      I  => clkout0      -- 1-bit input: Clock buffer input (S=0)
   );
   
   uPC1_CLK_BUFGCE : BUFGCE
   port map (
      O  => uPC1_CLK,    -- 1-bit output: Clock buffer output
      CE => uPC_CLK_EN(1), -- 1-bit input: Clock buffer select
      I  => clkout0      -- 1-bit input: Clock buffer input (S=0)
   );
   
   uPC2_CLK_BUFGCE : BUFGCE
   port map (
      O  => uPC2_CLK,    -- 1-bit output: Clock buffer output
      CE => uPC_CLK_EN(2), -- 1-bit input: Clock buffer select
      I  => clkout0      -- 1-bit input: Clock buffer input (S=0)
   );
   
   uPC3_CLK_BUFGCE : BUFGCE
   port map (
      O  => uPC3_CLK,    -- 1-bit output: Clock buffer output
      CE => uPC_CLK_EN(3), -- 1-bit input: Clock buffer select
      I  => clkout0      -- 1-bit input: Clock buffer input (S=0)
   );

I'm receiving these warning during translate ...

Annotating constraints to design from ucf file
"constraints_files/AsymDualCore_SoC_NAND_PL1.ucf" ...
Resolving constraint associations...
Checking Constraint Associations...
INFO:ConstraintSystem:123 - Constraint '<TIMEGRP "clk_1_grp" = RISING
   "SoC_CLK_AsymDualCore_SoC_PLL_clkout0";>
   [constraints_files/AsymDualCore_SoC_NAND_PL1.ucf(42)]' includes bel
   'SoC_CLK/uPC3_CLK_BUFGCE' which has multiple clock pins.  Any timing
   calculations for this constraint will apply to all RISING clock pins on that
   bel.

INFO:ConstraintSystem:123 - Constraint '<TIMEGRP "clk_1_grp" = RISING
   "SoC_CLK_AsymDualCore_SoC_PLL_clkout0";>
   [constraints_files/AsymDualCore_SoC_NAND_PL1.ucf(42)]' includes bel
   'SoC_CLK/uPC2_CLK_BUFGCE' which has multiple clock pins.  Any timing
   calculations for this constraint will apply to all RISING clock pins on that
   bel.

INFO:ConstraintSystem:123 - Constraint '<TIMEGRP "clk_1_grp" = RISING
   "SoC_CLK_AsymDualCore_SoC_PLL_clkout0";>
   [constraints_files/AsymDualCore_SoC_NAND_PL1.ucf(42)]' includes bel
   'SoC_CLK/uPC1_CLK_BUFGCE' which has multiple clock pins.  Any timing
   calculations for this constraint will apply to all RISING clock pins on that
   bel.

INFO:ConstraintSystem:123 - Constraint '<TIMEGRP "clk_1_grp" = RISING
   "SoC_CLK_AsymDualCore_SoC_PLL_clkout0";>
   [constraints_files/AsymDualCore_SoC_NAND_PL1.ucf(42)]' includes bel
   'SoC_CLK/uPC0_CLK_BUFGCE' which has multiple clock pins.  Any timing
   calculations for this constraint will apply to all RISING clock pins on that
   bel.

INFO:ConstraintSystem:178 - TNM 'EXT_CLK', used in period specification
   'TS_EXT_CLK', was traced into PLL_ADV instance PLL_ADV. The following new TNM
   groups and period specifications were generated at the PLL_ADV output(s): 
   CLKOUT3: <TIMESPEC TS_SoC_CLK_AsymDualCore_SoC_PLL_clkout3 = PERIOD
   "SoC_CLK_AsymDualCore_SoC_PLL_clkout3" TS_EXT_CLK HIGH 50%>

INFO:ConstraintSystem:178 - TNM 'EXT_CLK', used in period specification
   'TS_EXT_CLK', was traced into PLL_ADV instance PLL_ADV. The following new TNM
   groups and period specifications were generated at the PLL_ADV output(s): 
   CLKOUT1: <TIMESPEC TS_SoC_CLK_AsymDualCore_SoC_PLL_clkout1 = PERIOD
   "SoC_CLK_AsymDualCore_SoC_PLL_clkout1" TS_EXT_CLK * 3 HIGH 50%>

INFO:ConstraintSystem:178 - TNM 'EXT_CLK', used in period specification
   'TS_EXT_CLK', was traced into PLL_ADV instance PLL_ADV. The following new TNM
   groups and period specifications were generated at the PLL_ADV output(s): 
   CLKOUT0: <TIMESPEC TS_SoC_CLK_AsymDualCore_SoC_PLL_clkout0 = PERIOD
   "SoC_CLK_AsymDualCore_SoC_PLL_clkout0" TS_EXT_CLK * 1.5 HIGH 50%>

OK so I have no idea why I am getting these warnings can some one shed some light on this for me?

 

0 Kudos
16 Replies
avrumw
Guide
Guide
930 Views
Registered: ‎01-23-2009

To be honest, I'm not sure how much people can help you...

Even at its peak, it was very difficult to "reverse engineer" a UCF file. UCF has a hodge-podge of syntax accumulated over decades of evolution from its earliest days as a simple constraint language (if you can even call it that) for CPLDs. As it evolved more and more syntax became unnecessary as it was replaced by newer syntax, but UCF maintained backward compatibility all the way to the beginning. And even without this, the syntax was confusing.

Moreover, most legacy UCF files have weird things in them - things that are probably not the "right" way of doing things, and things that are of unknown origins. I have encountered many UCF files where when I ask "Why is this here and what is it supposed to do", I would get answers like "We have no idea - it has been in our UCF files for many generation, no one knows what it is supposed to do, but it seems to work..."

And that was 10 years ago when people were using UCF all the time. It has been many years since I have had to deal with UCF files, and I have begun to forget things...

So lets get back to basics... First, what technology is this for? Spartan-6? Something older? Early 7 series? If it is for 7 series (which I doubt) then I would recommend throwing this all out and redoing everything from scratch in Vivado. If it is something that still needs ISE then I would probably recommend the same thing - throw it out and re-write the UCF file from scratch...

I don't know what this stuff is supposed to do - many of these lines are "questionable" syntax, and possibly not correct - they may even all be in this category.

To "properly" specify the constraints for a number of clocks driven by a PLL you only need one constraint - the PERIOD constraint on the input clock; the tool takes care of everything else, including figuring out the requirements for the synchronous clock crossings between all the related PLL outputs. My suspicion is that this entire set of commands is being done on the assumption that you have to do it manually.

Furthermore, many of these constraints are "odd".

TIMEGRP uPC_RST = FFS(RST_CPU);

This is an archaic syntax - I think it makes a group of all flip-flops that are driven by the net RST_CPU, but I am not sure.

TIMEGRP clk_1_grp = RISING "SoC_CLK_AsymDualCore_SoC_PLL_clkout0";

This one creates a new group from another group. Where is the group SoC_CLK_AsymDualCore_SoC_PLL_clkout0 defined? Is it in another UCF? Is it an autogenerated name; the tool generates timespecs automatically when PLLs/DCMs are encountered, and their names are somewhat deterministic, but the format has changed from version to version, so if this UCF file is from an older version of ISE, it might not work in the newest one. Furthermore, why do you want this group? It is the same group with the RISING keyword - all this does is filter out the falling edge clocked elements from the group. Are there falling edge clocked elements? If so, why do you want to filter them out? Again, its pretty hard to determine the intent of this command from its syntax.

TIMESPEC TS_clk1_to_clk2 = FROM "clk_1_grp" TO "clk_2_grp" TS_SoC_CLK_AsymDualCore_SoC_PLL_clkout0 DATAPATHONLY;

All of these look like clock domain crossing constraints (due to the DATAPATHONLY) but they are defining the value of the constraint from the TS_SoC_CLK_AsymDualCore_SoC_PLL_clkout0 timespec. Where is this timespec defined? Again, in another UCF? Auto-generated by the tool? From the error messages, the tool can't find it - maybe the name format has changed.

And why would you need this - this looks like two different outputs of the same PLL - why would you need a clock domain crossing circuit between them - they are synchronous! A DATAPATHONLY constraint between them is incorrect...

So I go back to my original statement - you may need to reverse engineer the design - figure out what it is actually doing, and then rewrite the constraints from scratch to match the needs of the design. Starting from this old UCF file is likely not going to get you to the place you need to be...

Avrum

0 Kudos
SoC_Designer
Observer
Observer
909 Views
Registered: ‎04-29-2020

Hmmmm I have no idea actually why it would be too complicated for Physical Timing Engineers to handle.

This project is targeting a Spartan 6.  I don’t think it can be done with Vivado?

The system (believe it or not) isn’t that complicated, there are only 3 clock domains.    But for some reason the translate process keeps invalidating the constraints.  So obviously they are not written correctly, or somehow targeting the wrong nets,clocks, etc.

There are two primary clock domains CLK0 and CLK1 (2X CLK0).  CLK0 is the system CLK, CLK1 clocked the ccRAMs, which need to run at 2X the system clock to respond within 1 clock cycle to both uPCs.  Ignore CLK3 & CLK2 for right now.

The uPC clocks are gated by a BUFCE to allow for software controlled power.

Reset is handled by a state machine which is running on the external oscillator which drives the PLL.  This reset state machine has two resets one for the uPCs and another for the rest of the system.  The reset process is triggered by the PLL Lock.  If the Lock is LO the reset is triggered, waiting for the Lock to go HI.

System wide resets are all asynchronous (I know, I know, all of a sudden asynchronous resets are very, very bad I FPGA, blah, blah) I wish this was always Xilinx’s stance, anyway.  

That’s is the system at a glance.

0 Kudos
SoC_Designer
Observer
Observer
896 Views
Registered: ‎04-29-2020

To answer your questions:

1. Furthermore, many of these constraints are "odd"?

TIMEGRP uPC_RST = FFS(RST_CPU);

This is an archaic syntax - I think it makes a group of all flip-flops that are driven by the net RST_CPU, but I am not sure.

R1. This is a timing group for all of the uPC resets.  It’s used to constrain the timing from the CPU reset to all FF in the uPCs.

2. clk_1_grp = RISING "SoC_CLK_AsymDualCore_SoC_PLL_clkout0";

This one creates a new group from another group. Where is the group SoC_CLK_AsymDualCore_SoC_PLL_clkout0 defined? Is it in another UCF? Is it an autogenerated name; the tool generates timespecs automatically when PLLs/DCMs are encountered, and their names are somewhat deterministic, but the format has changed from version to version, so if this UCF file is from an older version of ISE, it might not work in the newest one.

R2. The constraint is defined in the UCF file.

3.  TS_clk1_to_clk2 = FROM "clk_1_grp" TO "clk_2_grp" TS_SoC_CLK_AsymDualCore_SoC_PLL_clkout0 DATAPATHONLY;

All of these look like clock domain crossing constraints (due to the DATAPATHONLY) but they are defining the value of the constraint from the TS_SoC_CLK_AsymDualCore_SoC_PLL_clkout0 timespec. Where is this timespec defined? Again, in another UCF? Auto-generated by the tool? From the error messages, the tool can't find it - maybe the name format has changed.

And why would you need this - this looks like two different outputs of the same PLL - why would you need a clock domain crossing circuit between them - they are synchronous! A DATAPATHONLY constraint between them is incorrect...

R3. I do believe the two clocks are synchronous, however they are running at different frequencies, CLK1 (2X CLK0) runs the ccRAMs and the output of the RAMs goes to the uPCs running on CLK0.  The constraint are there so the timing analyzer realizes that CLK1 RAM outputs should be expected to arrive at CLK0 not CLK1.

 

Hopefully this helps.

0 Kudos
SoC_Designer
Observer
Observer
832 Views
Registered: ‎04-29-2020

SoC_CLKs.png 

Red Line CLK1 (2X CLK0) 

Blue Line CLK0 

Purple Line Data Lines

Orange Line Processor Instructions clocked on CLK1, received on CLK0

 

0 Kudos
avrumw
Guide
Guide
732 Views
Registered: ‎01-23-2009

There are two primary clock domains CLK0 and CLK1 (2X CLK0). CLK0 is the system CLK, CLK1 clocked the ccRAMs, which need to run at 2X the system clock to respond within 1 clock cycle to both uPCs.

If this is the majority of the complexity, then your constraints are WAY over-complicated (and slightly wrong).

When you constrain the input port of an FPGA with a PERIOD constraint, and that port drives a PLL, the tool automatically generates the derived clocks for the outputs of the PLL based on the programming of the PLL. These automatically generated PERIOD constraints are visible in one of the ndgbuild log files - I can't remember which (maybe the .bld file?) - in fact they are the three INFO messages you posted with your error warning messages. From these messages, we see that clkkout0 is 1.5x your input clock, clkout1 is 3x your input clock (hence 2:1 with respect to clkout0) and clkout2 is the same frequency as your input clock.

With these constraints, the relationship of these clocks are completely defined, including the tool understanding that a synchronous clock crossings between clkout0 and clkout1 (in both directions) are constrained to one period of the faster clock (clkout0).

This means that your TIMESPECS for clk1 to clk2 (which are clkout0 to clkout1) and vice versa are unnecessarily (and incorrect). They are unnecessarily since the tool already knows the relationship and are incorrect since they use the DATAPATHONLY flag, which instructs the tool ignore clock skew - this leads to over or undersconstraining these paths by the amount of the clock skew. Since you don't need these TIMESPECs (TS_clk*_to_clk*) you don't need the groups you created (clk_*_grp).

Now this leaves the reset stuff. If I understand correctly you are using a state machine running on the input clock (TS_EXT_CLK), which is looking at the PLL LOCK and generating resets for the two different subsystems.

First, the state machine itself will be properly constrained by the TS_EXT_CLK timespec.

Second, the LOCK input is asynchronous so must have a proper synchronization circuit on it (two back to back flip-flops). The synchronizer will need some constraints; an ASYNC_REG property on both flip-flops in the synchronizer and maybe a TIG between the LOCK and the first flip-flop (I'm not sure if LOCK is considered a static timing path startpoint).

Next the resets to the subsystems must come directly from flip-flops (not combinatorial logic). Furthermore, each of these outputs must go through a proper reset synchronizer (reset bridge) - even though the flip-flops in the design use "asynchronous" presets and clears, the signal driving it MUST BE synchronous (at least the deasserting edge). This reset bridge also needs constraints; setting the ASYNC_REG on the two flip-flops of the bridge and a TIG (or FROM TO MAXDELAY) between the synchronous flip-flop on the input clock and the first flip-flop of the bridge.

With all that (assuming you described everything) your design should be properly constrained.

Avrum

0 Kudos
SoC_Designer
Observer
Observer
719 Views
Registered: ‎04-29-2020

Thanks for your response and input.

"With these constraints, the relationship of these clocks are completely defined, including the tool understanding that a synchronous clock crossings between clkout0 and clkout1 (in both directions) are constrained to one period of the faster clock (clkout0)."

No, the constraint must be on the period of the slower clock (CLK0) not the fastest clock.  Both clocks are synchronous to each other, therefore I should be able to latch the data and instructions coming from the fast clock (CLK1) on the rising edge of the slow clock CLK0 ( the system CLK ).  Therefore I need a constraint that helps the tool to see this, does this help? ...

We will get back to the reset synchronizes after we clear this part up.

 

 

 

 

0 Kudos
avrumw
Guide
Guide
706 Views
Registered: ‎01-23-2009

No, the constraint must be on the period of the slower clock (CLK0) not the fastest clock. Both clocks are synchronous to each other, therefore I should be able to latch the data and instructions coming from the fast clock (CLK1) on the rising edge of the slow clock CLK0 ( the system CLK )

This is only true if you have taken special steps to ensure that the launch and capture flip-flops on the faster domain (on the clock crossing paths) only change values or capture data on the rising edges of the fast clock that align to the rising edge of the slower clock. If the flip-flop on the fast clock domain can change value or capture on every clock (or on an arbitrary clock) then these paths are all single cycle paths of the faster clock domain.

To implement a circuit that only updates/captures on the "correct" edge of the faster clock, you usually need to have a circuit that can figure out which edge of the fast clock corresponds to the rising edge of the slow clock.

Only if you implement this can you have a constraint to relax the timing on these paths. However, I wonder what the point is. The point of running the RAM at twice the speed is so that you can have enough bandwidth to service the two engines... Assuming both engines are running on the rising edge of the slow clock then one of the two paths in each direction is only a single 2x clock period...

Avrum

0 Kudos
SoC_Designer
Observer
Observer
662 Views
Registered: ‎04-29-2020

I'm not 100% sure I follow this comment.

 

"This is only true if you have taken special steps to ensure that the launch and capture flip-flops on the faster domain (on the clock crossing paths) only change values or capture data on the rising edges of the fast clock that align to the rising edge of the slower clock. If the flip-flop on the fast clock domain can change value or capture on every clock (or on an arbitrary clock) then these paths are all single cycle paths of the faster clock domain."

As long as the domains are synchronous it shouldn't matter, if data doesn't arrive on the rising edge of the slow clock (CLK0) that is perfectly acceptable, the CLK0 domain will just latch the data on the next clock cycle.

Perhaps a bit of explanation will help.  The fast clock in this instance is used to overclock the ALU math portion of the uPC, to cut down on the latency of these operation.  They are not single cycle operations anyway so I don't expect a new ouput every clock cycle there are multiple CLK0 cycles inbetween each operation.

"To implement a circuit that only updates/captures on the "correct" edge of the faster clock, you usually need to have a circuit that can figure out which edge of the fast clock corresponds to the rising edge of the slow clock."

Ahhhh hmm I appreciate this, I was using something a bit more complicated ....

SoC_Synchro.png

 

I think this should work just fine?

"However, I wonder what the point is. The point of running the RAM at twice the speed is so that you can have enough bandwidth to service the two engines... Assuming both engines are running on the rising edge of the slow clock then one of the two paths in each direction is only a single 2x clock period..."

Wellll no, the ccRAMs need to run at 2X the system clock so that the Fetch unit can be a single cycle unit, and now have to wait on the 2 cycle delay through the ccRAMs that it would normally have to wait if the ccRAMs were running at the CLK0 rate.

 

So this over clocking has two purposes.

 

1. Speed up the instruction ccRAMs to sychronize the requests from the Fetch Unit to one cycle.

2. Speed up the math operations in the ALU to decrease latency of certain math operations.

 

** I almost forgot, now with all of this said, do you see why the constraints look the way they do?

 

 

 

0 Kudos
SoC_Designer
Observer
Observer
602 Views
Registered: ‎04-29-2020

OK resets

"Now this leaves the reset stuff. If I understand correctly you are using a state machine running on the input clock (TS_EXT_CLK), which is looking at the PLL LOCK and generating resets for the two different subsystems."

This should be automatic as the EXT_CLK is constrained, and that is the clock driving the state machine.

"Second, the LOCK input is asynchronous so must have a proper synchronization circuit on it (two back to back flip-flops). The synchronizer will need some constraints; an ASYNC_REG property on both flip-flops in the synchronizer and maybe a TIG between the LOCK and the first flip-flop (I'm not sure if LOCK is considered a static timing path startpoint)."

Yes I'm doing this, I believe?  Here is the code for the PLL Lock Debouncer

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity pll_lock_debouncer is
port( CLK               :  IN std_logic;
      PLL_LOCK          :  IN std_logic;
      PLL_RST           : OUT std_logic;
      INITIAL_RST       : OUT std_logic
        );
end pll_lock_debouncer;

architecture RTL of pll_lock_debouncer is


type state_type is (idle, rst_pll, wait4edge, debounce_lock, locked); 
signal pr_state : state_type := idle;
signal nx_state : state_type;

SIGNAL Q1               : std_logic := '0'; 
SIGNAL Q2               : std_logic := '0'; 
SIGNAL Q3               : std_logic := '0'; 
SIGNAL Q4               : std_logic := '0'; 
SIGNAL Q5               : std_logic := '0'; 
SIGNAL Q6               : std_logic := '0';
                          
SIGNAL true_edge        : std_logic := '0'; 
SIGNAL rst_latch        : std_logic := '0';
      
SIGNAL edge_detector    : std_logic := '0';
SIGNAL pll_lock_sync    : std_logic := '0';
SIGNAL rst_confirmed    : std_logic := '0';
SIGNAL debouncer_rst    : std_logic := '0';       

SIGNAL i_initial_rst    : std_logic := '0';   
SIGNAL release_reset    : std_logic := '0'; 

SIGNAL cntr_en          : std_logic := '0'; 
SIGNAL clr_cntrs        : std_logic := '0';
                     
SIGNAL lock             : std_logic := '0';
SIGNAL unlock           : std_logic := '0';
SIGNAL i_pll_rst        : std_logic := '0';

SIGNAL debounce_cntr    : std_logic_vector(31 downto 0) := (OTHERS => '0');

attribute KEEP : string;                              
attribute KEEP of INITIAL_RST : signal is "TRUE";


begin

--Syncing the PLL lock to the System Reset module's clock.
LOCK_SYNC :
entity work.syncing_ic_nosrt
PORT MAP (
    CLK      => CLK,
    ASYNC_IN => PLL_LOCK,
    SYNC_OUT => PLL_LOCK_SYNC
);

-- True edge detection for external PLL lock
process(CLK)
begin
    if (CLK'event and CLK = '1') then
    
        Q1            <= PLL_LOCK_SYNC;
        Q2            <= Q1;
        Q3            <= Q2;
        Q4            <= Q3;                
        true_edge     <= ( Q1 and Q2 and Q3 and not Q4 );        
        rst_latch     <= true_edge;
        edge_detector <= true_edge AND NOT rst_latch;
   end if;
end process;

process (CLK)
begin
    if (CLK'event and CLK = '1') then   
        PLL_RST   <= i_pll_rst;
        pr_state  <= nx_state;       
    end if;
end process;


process ( pr_state, edge_detector, debounce_cntr, PLL_LOCK_SYNC )
begin

    lock          <= '0';
    cntr_en       <= '0';
    clr_cntrs     <= '0';
    i_pll_rst     <= '0';
    i_initial_rst <= '0';
    release_reset <= '0';
    nx_state      <= pr_state;  --default is to stay in current state
        
    case (pr_state) is
    
        -- IDLE: In this state we are simply resetting the counters
        -- and the JKff's state. From here we jump to the RESET PLL
        -- state.
        when idle =>

            clr_cntrs     <= '1';
            i_initial_rst <= '1';
            nx_state      <= rst_pll;
        -- RESET PLL : In this state we are resetting the PLL using the
        -- counter to time how long we drive the reset signal to the PLL
        -- once the terminal count is reached we reset the counter and 
        -- jump to the WAIT 4 EDGE state. 
        when rst_pll => 
        
            cntr_en   <= '1';
            i_pll_rst <= '1';
                    
            if ( debounce_cntr = x"000000FF" ) then

                clr_cntrs     <= '1';
                nx_state      <= wait4edge;                 
            end if;
        -- WAIT FOR EDGE : In this state we are wating for the PLL Lock
        -- to be asserted high, signifing that the PLL has achievec lock
        -- once this happens we jump to the DEBOUNCE LOCK state 
        when wait4edge =>

            clr_cntrs     <= '1';
            i_initial_rst <= '1';

            if ( edge_detector = '1' ) then
                nx_state <= debounce_lock;
            end if;
        -- DEBOUNCE LOCK : In this state we are debouncing the PLL 
        -- lock signal ie using a counter to count how long the signal
        -- remains stable at one level.  If the signal bounces or changes
        -- state we jump back to the IDLE state.  If the counter reaches
        -- the terminal count, we reset the counters and jump to the LOCKED
        -- state.           
        when debounce_lock => 
        
            cntr_en <= '1';
                    
            if ( PLL_LOCK_SYNC = '0' ) then 
            
                nx_state <= idle;
        
            elsif ( debounce_cntr = x"8F0D180" ) then

                clr_cntrs     <= '1';
                release_reset <= '1';
                nx_state      <= locked;                    
            end if;
        -- PLL LOCKED : In this state we are simply monitoring the PLL
        -- lock's state.  If the state changes we jump back to IDLE, 
        -- and start the process over again.
        when locked => 
        
            if ( PLL_LOCK_SYNC = '0' ) then         
                nx_state <= idle;
            end if;
    end case;           
end process;

-- Debounce Counter
process(CLK)
begin
    if (CLK'event and CLK = '1') then   
         if ( clr_cntrs = '1' ) then         
             debounce_cntr  <= (OTHERS => '0');           
         elsif ( cntr_en = '1' ) then     
             debounce_cntr  <= debounce_cntr + 1;       
         end if;    
    end if;
end process;

reset_jkff: 
entity work.jk_ff 
PORT MAP(
    CLK     => CLK,              
    J       => i_initial_rst,  
    K       => release_reset,       
    Q       => INITIAL_RST,
    Q_bar   => open 
);


end RTL;

"Next the resets to the subsystems must come directly from flip-flops (not combinatorial logic). Furthermore, each of these outputs must go through a proper reset synchronizer (reset bridge) - even though the flip-flops in the design use "asynchronous" presets and clears, the signal driving it MUST BE synchronous (at least the deasserting edge). This reset bridge also needs constraints; setting the ASYNC_REG on the two flip-flops of the bridge and a TIG (or FROM TO MAXDELAY) between the synchronous flip-flop on the input clock and the first flip-flop of the bridge."

OK 

  Again I believe I am doing this, with the exception of this "bridge" you speak of?  Never heard of this but it if works, I'll use it, here is the reset logic.

library IEEE;
--library work;                  
use IEEE.STD_LOGIC_1164.ALL;    
--use IEEE.STD_LOGIC_ARITH.ALL; 
USE ieee.numeric_std.ALL;  
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.STD_LOGIC_MISC.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity system_reset is
port( 

      RST         :  IN std_logic; -- External Reset connected to a debouncer which is sourced by the PLL Lock
      CLK         :  IN std_logic; -- External Oscilator, same oscilator which drives the system PLL
      SOFT_RST    :  IN std_logic; -- Internal software reset signal.
      
      RST_CPU     : OUT std_logic; -- Processor Reset
      RST_SYSTEM  : OUT std_logic  -- System Reset
    );
end system_reset;

architecture RTL of system_reset is

type bringup_reset is (idle, upc_reset, soc_reset, monitor_soft_rst); 
signal pr_state, nx_state  : bringup_reset;


SIGNAL reset_pulse   : std_logic;                        
SIGNAL true_edge     : std_logic; 
SIGNAL rst_latch     : std_logic;
      
SIGNAL edge_detector : std_logic;
SIGNAL debouncer_rst : std_logic;       

SIGNAL cntr_en       : std_logic;
SIGNAL clr_cntrs     : std_logic;
                     
SIGNAL soc_rst_i     : std_logic;
SIGNAL upc_rst_i     : std_logic;
                     
SIGNAL soc_rst       : std_logic;
SIGNAL upc_rst       : std_logic;

SIGNAL reset_delay_cntr : std_logic_vector(15 downto 0);

begin


process (CLK, RST)
begin   
    if (RST = '1') then
        pr_state <= idle;       
    elsif (CLK'event and CLK = '1') then    
        pr_state <= nx_state;        
    end if;
end process;

process(CLK,RST)
begin
    if ( RST = '1' ) then        
        reset_delay_cntr <= (OTHERS => '0');
    elsif (CLK'event and CLK = '1') then 
        if ( clr_cntrs = '1' ) then      
            reset_delay_cntr <= (OTHERS => '0');      
        elsif ( cntr_en = '1' ) then              
            reset_delay_cntr <= reset_delay_cntr + 1;       
        end if;    
   end if;
end process;

process (pr_state, SOFT_RST, reset_delay_cntr)
begin
    
    soc_rst    <= '0';
    clr_cntrs  <= '0';
    upc_rst    <= '0';
    cntr_en    <= '0';
    nx_state   <= pr_state;
    
    case (pr_state) is
        
        -- IDLE : In this state we are simply resetting the
        -- counter and jumping to the Processor Reset state.
        when idle =>

            clr_cntrs <= '1';
            nx_state  <= upc_reset;
        -- PROCESSOR RESET : In this state we are driving the
        -- processor reset signal.  The signal is simply driven
        -- for a specified amount of time to allow the signal time
        -- to proprogate to all modules of the processors.  From 
        -- this state jump to the SoC RESET state.                          
        when upc_reset => 
        
            upc_rst <= '1';
            cntr_en <= '1';
            
            if ( reset_delay_cntr = x"1388" ) then 
                clr_cntrs <= '1';
                nx_state  <= soc_reset;
            end if;
        -- SoC RESET : In this state we are driving the
        -- system reset signal.  The signal is simply driven
        -- for a specified amount of time to allow the signal time
        -- to proprogate to all peripheral modules of the processors's
        -- subsystem.  From this state we jump to the MONITOR SOFTWARE
        -- RESET state.         
        when soc_reset => 

            soc_rst <= '1';
            upc_rst <= '1';
            cntr_en <= '1';
        
            if ( reset_delay_cntr = x"1388" ) then
                clr_cntrs <= '1';
                nx_state  <= monitor_soft_rst;
            end if;
        -- MONITOR SOFTWARE RESET : In this state we are monittoring
        -- the software driven reset, when this reset signal is asserted
        -- we return to IDLE to start the Hardware reset process all over.  
        when monitor_soft_rst => 
        
            if ( SOFT_RST = '1' ) then

                nx_state  <= idle;
            end if; 
    end case;   
end process;

process (CLK, RST)
begin
    
    if (RST = '1') then
   
        RST_CPU    <= '1';
        RST_SYSTEM <= '1';
        
        soc_rst_i  <= '1';
        upc_rst_i  <= '1';
        
    elsif (CLK'event and CLK = '1') then    

        soc_rst_i  <= soc_rst;
        upc_rst_i  <= upc_rst;
        
        RST_SYSTEM <= soc_rst_i;
        RST_CPU    <= upc_rst_i;       
    end if;
end process;

end RTL;

I'll add in this "reset bridge" although, I'd like to see more literature on it.

So the Reset Circuitry looks like this. The "Reset Trigger" signal is the asynchronous reset signal for the System Reset module.  This signal has to be asynchronous as it is applied when we loose lock and there the clock CLK0 is not stable and can not be used to dive synchronous resets.

.... 

SoC_reset.png Synchronize Code

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

---- Uncomment the following library declaration if instantiating
---- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity syncing_ic is
    Port ( RST      : IN   std_logic;
           CLK      : IN   std_logic;
           ASYNC_IN : IN   std_logic;
           SYNC_OUT : OUT  std_logic
           );
end syncing_ic;

architecture Behavioral of syncing_ic is

signal sreg : std_logic_vector(1 downto 0);

attribute ASYNC_REG : string;
attribute ASYNC_REG of sreg : signal is "TRUE";

begin


process (RST, CLK)
begin
    if ( RST = '1' ) then
   
        SYNC_OUT  <= '0'; 
        sreg      <= (OTHERS => '0');
        
    elsif (clk'event and clk='1') then 
     
        SYNC_OUT <= sreg(1);
        sreg     <= sreg(0) & ASYNC_IN;
   end if;
end process;

end Behavioral;

OK so this give you the information you need on how reset is done ... standing by for comments.

0 Kudos
SoC_Designer
Observer
Observer
555 Views
Registered: ‎04-29-2020

No Xilinx employee has any input?  One of you guys must have something to say.

0 Kudos
mike.mandeville
Contributor
Contributor
480 Views
Registered: ‎06-27-2017

If I had to guess, the clocking resource guide says the following:

"The BUFGCE is built from the BUFGMUX by multiplexing a fixed value for one input. The
default value is Low when disabled".  

The BUFMUX would have multiple clock inputs so this warning might just be suggesting that your constraint would apply to each and every clock input of that BUFMUX even though in your useage, the other clock inputs are tied high/low.

I'm not sure what you're attempting to do, because if I remember from ISE days, creating separate TimeGroups is telling the tools that these clocks (in different groups) have no relation to each other, but since it appears that they are all created from the same PLL, they have a very well known (and fixed) relationship to each other.

0 Kudos
mike.mandeville
Contributor
Contributor
475 Views
Registered: ‎06-27-2017

You might check out this manual to double check your syntax.  If you look at page 24 (Asynchronous Clock Domains), it talks about why you would want to create Time Groups.

https://www.xilinx.com/support/documentation/sw_manuals/xilinx14_7/ug612.pdf

0 Kudos
mike.mandeville
Contributor
Contributor
469 Views
Registered: ‎06-27-2017

Because your reset check occurs OUTSIDE (before) the CLK'event, it is asynchronous ... meaning the RST will happen regardless of where the clock edge is.  Your process sensitivity list (CLK, RST) forces this process to run ANYTIME either of those two signals change ... in either direction.  This means that this process will check this RST signal on both rising and falling edge of CLK (not synchronous).  To make this reset synchronous, it would have to happen INSIDE the CLK'event and CLK='1'.  That forces the reset to wait until the rising clock edge occurs to be checked (which is the definition of a synchronous reset).

 

process (CLK, RST)
begin   
    if (RST = '1') then
        pr_state <= idle;       
    elsif (CLK'event and CLK = '1') then    
        pr_state <= nx_state;        
    end if;
end process;

process(CLK,RST)
begin
    if ( RST = '1' ) then        
        reset_delay_cntr <= (OTHERS => '0');
    elsif (CLK'event and CLK = '1') then 
        if ( clr_cntrs = '1' ) then      
            reset_delay_cntr <= (OTHERS => '0');      
        elsif ( cntr_en = '1' ) then              
            reset_delay_cntr <= reset_delay_cntr + 1;       
        end if;    
   end if;
end process;

 

0 Kudos
SoC_Designer
Observer
Observer
467 Views
Registered: ‎04-29-2020

All resets in the entire SoC have been switched to synchronious resets.  So there are now “no” asynchronous resets in the design.

 

As a consequence Synthesis reports a max frequency of 3Mhz SLOWER than the Asynchronous Reset Design!  

so much for Xilinx’s recommendation that all resets be synchronous!

0 Kudos
SoC_Designer
Observer
Observer
466 Views
Registered: ‎04-29-2020

These elements are working as intended.  No issues here.  They are clock enable buffers used to do just what they were designed to do.

0 Kudos
SoC_Designer
Observer
Observer
465 Views
Registered: ‎04-29-2020

I don’t follow what you are trying to say.

0 Kudos