I do understand, that you have an internal clock SYS_CLK, which you use to drive the state machine generating SPI_CLK.
The flip-flop which generates SPI_CLK should be located in IOB, to ensure deterministic timing between SYS_CLK and SPI_CLK (you can specify the required maximum delay for SPI_CLK, using the OFFSET OUT).
Then you can specify your constraints using OFFSET IN (for MOSI) and OFFSET OUT (for MISO) with respect to SYS_CLK, considering the delay between SYS_CLK and SPI_CLK.
A concurrent signal assignment statement of the form:
OUTPUT <= CLK AND VAR;
Has an equivalent process (how it's simulated) of the form:
process
begin
OUTPUT <= CLK AND VAR;
wait on CLK, VAR; -- wait on 'sensitivity list'
end process;
With the wait statement the equivalent of putting both right hand side signals in a sensitivity list.
The second process is already sensitive to CLK events, the if CLK'EVENT
is redundant. I'd suggest that your synthesis tool should likely have generated a warning and may have not produced an assignment to OUTPUT, something examining synthesis warnings, any produced net list or generated schematic might indicate. Otherwise the second and third processes are equivalent.
You're likely to get warning for both the second and third process statements that VAR is missing from the sensitivity list, which is likely ignored for synthesis purposes. The effect of this is not have closure between simulation results pre- and post-synthesis.
Note that what you've defined is a gated clock and having VAR in the sensitivity list won't matter unless VAR transitions before the rising edge of CLK or after the falling edge of CLK, in which case it could move the OUTPUT clock edge (if OUTPUT'EVENT and OUTPUT = '1'
, if rising_edge(OUTPUT)
, or the same for the falling edge).
And if VAR could screw up your resulting 'clock' edge you have a problem that should be addressed anyway.
(And of course someone is bound to chime in that a sensitivity list can use the reserved word all to signify all right hand side signals in VHDL-2008).
addendum
The questioner has indicated he's trying to gate clocks, and from added information to his question shows this is using Xilinx tools.
Xilinx recommends against gating clocks this way [1], the most obvious reason is that clock skew becomes dependent on routing to and from a LUT as well as the the LUT delay itself. You could imagine trying to balance delays in all your clocks. With clocks generated from a higher clock rate you could for instance disable a clock with a clear or reset. The idea here is match delays on gated and non gated clocks as an FPGA implementation issue above and beyond all the measures you'd take to cross clock boundaries otherwise.
Xilinx supports gated clocks in series 7 FPGAs and ZYNQ devices using dedicated clock enables through the use of the paid version of ISE (Vivaldo), something called intelligent clock gating, where you don't gate your clocks, you let the tools do it for you.
You could also note the period constraint is lost passing through an non-sequential element manually gating clocks.
[1]
White Paper: HDL Coding Practices to Accelerate Design Performance, around Figure 11. Starting on Page 10, Clock Enable and Gated Clocks.
Best Answer
"signal_in" is not timed by the development tools until it is brought into a clocked element (i.e. register). Because of this there is nothing that says "not signal_in" has to be valid before/after "last" is updated.
Therefore, when "last" and "not signal_in" are ANDed together there is essentially a race condition, where the final result can vary (between builds due to routing and between FPGAs due to variations in the specific fabric). This is why signals should always be brought onto a clock before being used in calculations.