The basic idea is something like this:
Consider a module with an ideal flop in it. Now, there exists a data path (from primary inputs of module to D of flop) and a clock path (from primary inputs to CLK of flop). Suppose the data path delay is DD and clock path delay is 0 . Therefore, if we consider the clock pulse reaching at the primary input of the module as the reference time, the clock pulse will reach CLK pin (of flop) at 0. The data pulse will reach D pin at DD. Therefore, for setup check to be met, the data pulse must reach the primary inputs of the module, at -D, which means the setup requirement is D.
Now consider a clock path delay of CD. This means that the clock pulse now reaches the flop, only after time CD. This means, the data pulse need not begin so early, and rather it has to begin at -DD+CD time(just right shifting the pulse by CD time). This means the setup requirement is now DD-CD. In this case, if CD>DD, then the setup requirement becomes negative, which means, the data pulse can reach the primary input of the module after the clock pulse has reached there.
Similarly for hold: Consider that the data delay is 0 and the clock delay is CD. Now, the data must not change for atleast CD time, for the flop to be able to latch it. Therefore, the hold requirement is CD. Now, consider a data delay of DD. This means that, now the data need not change only for CD -DD. This is the new hold requirement. If DD>CD, then hold requirement is negative.
If we analyse these results mathematically, we can see that setup relation + hold relation =0. Physically, this implies that an infinitesimally short pulse (a delta pulse) can be captured; which is of course not possible. A more accurate model would be:setup_val<DD-CD (for setup to be met, the time at which data begins should be atleast DD-CD before 0)
hold_val < CD-DD (for hold to be met, the time for which the data should be stable should always be greater than the hold_val)
Now, the model we described, regarding the module with an ideal flop, is actually a real world flop. In an actual flop, there are more than one data paths and 8 clock paths. Therefore the more accurate description would be: DDmax-CDmin >= setup_val (for setup to be met)
CDmax-DDmin >= hold_val (for hold to be met)
These kind of relationships, especially the ones, where a negative relations can hold cause problems in simulators. Take for example a data pulse, which rises at 0.0 and falls at 2.0. Now the clock pulse rises at 3.0 . Lets say data delay is 1.0
Assume the origin at the clock pulse (3.0) . Therefore data rise is at -3.0, fall is at -2.0 .
The setup relationship may be specified as 2.0, which means data should be present at 0.0-2.0=-2.0 . Now data will arrive at -3.0+DD-CD=-3.0+1.0+0.0=-2.0 (setup OK)
The hold relationship may be specified as -1.0, which means data must not change till 0.0+(-1.0)=-1.0. Now, according to our relationship, data will not change till 0.0+CD-DD=0.0-1.0=-1.0.
All looks hunky dory...but...
There is no problem with the timing checks, however in software, the simulator would capture the falling 2.0 edge rather than the high edge. So the simulator will get the functionally incorrect results, though timing accurate. If both setup and hold relationships were positive, then this would never have happened. So now what ?
Very simple actually, instead of taking an ideal clock, the simulator takes a delayed clock. Therefore all calculations are done wrt this delayed clock (in the above example clock is delayed -1 wr.t data), so the simulator will not latch the falling edge.