The architecture version governs the basic instruction sets, registers, etc., so any "v7" code will run on any v7 architecture (noting that v7-M only supports the Thumb instruction set) - but may be incompatible with v6 and earlier if it uses any v7-specific instructions.
However, there are a number of optional architecture extensions that may or may not be present on any given implementation, such as floating point, NEON, the security extensions, etc. Any portable code that relies on these extensions should check for the capabilities by reading standard system registers before trying to use features that may not be there and possibly causing an exception. For instance, the A15 has the virtualisation extensions and large physical address extensions that the A9 does not.
There are also a few features within the base architecture that are defined to be implementation-defined, such as the ACTLR
(auxiliary control register) which is typically used to expose details of a core's microarchitecture (e.g. a control bit to enable/disable the branch predictor). The meaning and use of these can vary even between different revisions of a core, but are generally such low-level things that most folks shouldn't need to even look at them.