There’s a long and comprehensive article at Bridging the Gap about what goes into a Functional Requirements document.
It goes into quite a bit of detail about how this can work. In my experience though, the level of detail needs to reflect the risk, or uncertainty, about how the eventual outputs are supposed to work.
For instance, if you are going to be delivering a complicated user interface, then it would be foolish to specify exactly how this is going to work, if you haven’t designed it in advance, or spoken to users about it. I would completely expect you to have to change what you specified in the functional requirements, as a better understanding evolves.
The dilemma that does come out of this approach though, is that the requirements may not be obviously testable, based on a vague, high-level description. However, I have found that with a bit of further explanation, testers are able to use the higher-level requirements in conjunction with what’s in front of them.
I think it’s suicide to specify in great detail something that you don’t know for a fact that you can build. You’ll end up boxing yourself into a solution you can’t actually deliver.
The functional requirements should reflect the level of risk and uncertainty of the project.