Things get even more interesting for 2's complement ADCs where +FS is vref - 1LSB value, while -FS is Vref.
What do you mean? That is exactly the case I described for all Microchip discrete bipolar ADC chip series available at Mouser: the minimum is inclusive the minimum reference voltage, analog ground for unipolar ADCs; and the maximum is one step less than the maximum reference voltage.
I have yet to see a single ADC that yields conversion value \$2^N-1\$ for the positive reference voltage (as opposed to for one step or LSB below positive reference voltage). I have found some ADCs (like the built-in one on the PIC at hand) that do not explicitly or implicitly define the conversion, but all datasheets I can find that do define it, define the positive reference voltage as corresponding to ADC conversion value \$2^N\$, i.e. \$\text{LSB} = V_\text{ref} 2^{-N}\$.
Thanks, angry programmer horde straight from Mordor!
Nah, we all make mistakes; it's just a good idea to explore the region where such a common error occurs, and why.
(No anger at all at least on my part, just trying to show what I am basing my current understanding on, because opinions aren't interesting but the reasons behind those opinions are.)
PWM generation has a surprisingly similar issue. When you define the PWM period as
N cycles, there are actually
N+1 possible transition points per period. Most implementations have a delay or restriction, so that there must be two separate transitions per period, in which case only
N-1 different duty cycles are possible – from one cycle high and
N-1 cycles low, to
N-1 cycles high and one cycle low.
Some implementations do not have such limitations, so that with a PWM period of
N, zero yields an always low output, and
N yields an always high output, both with a possible "glitch" spike (narrower than a clock cycle) at the beginning of each period. When the PWM register is
N-bit, the maximum period length where both always-low and always-high is possible, is \$2^N-1\$; not \$2^N\$. That corresponds to TOP counter value of \$2^N-2\$, not \$2^N-1\$.
At the root of these both is the mathematical fact that the range from \$0\$, inclusive, to \$N\$ exclusive or \$N-1\$ inclusive, has exactly \$N\$ integers.
A successive approximation ADC uses a DAC and \$N\$ steps to find the DAC value that corresponds to the ADC sample voltage at \$N\$-bit precision, using a binary search. At each step, the DAC output corresponding to the middle value in the current range is compared to the sample. If larger, the upper range is chosen; if smaller or equal, the lower range is chosen. \$N\$ steps provides exactly \$2^N\$ different possible values.
There are only three ways how a SAR ADC could yield code \$2^N-1\$ for the upper reference voltage: one is by choosing the upper range is equal or larger, and lower range if smaller. That leads to an ADC that cannot discriminate between lower reference voltage (ground) and one step or LSB above it. The second is to prescale the reference voltage by a factor of \$2^N / (2^N - 1)\$ somehow. The third way is to use an additional step, but instead of doubling the range of ADC values, only use it to discriminate between two ADC values.
For delta-sigma ADCs, like MCP346x that use 5-level quantizers (\$+V_\text{ref}\$, \$+V_\text{ref}/2\$, \$0\$, \$-V_\text{ref}/2\$, and \$-V_\text{ref}\$), the modulator output (intermediate representation)
can describe input having either positive or negative reference voltage. It is the digital decimation filter phase that determines the output code range. However, filter window sizes and outputs that are composite numbers having only small factors are the easiest to implement, requiring the least amount of silicon, because the typical decimation filter stages (first- and third-order sinc filter integrators and differentiators) are very simple FIR or IIR filters consisting only of coefficients +1, -1, +3, and -3. Powers of two are the easiest, but for the exact same reason as the PWM with power of two period, cannot represent both minimum and maximum at the same time.
The simplest method to obtain an ADC that does yield code \$2^N - 1\$ for \$V_\text{in} = V_\text{ref}\$ and code \$0\$ for \$V_\text{in} = 0\$, is to
skip the middle-range code. That is, for intermediate code \$0 \le x \le 2^N\$, the actual output value \$y\$ is \$x\$ iff \$x \lt 2^{N-1}\$, and \$x - 1\$ for \$x \ge 2^{N-1}\$. This increases the mid-range "glitch" (step size between codes \$y = 2^{N-1} - 1\$ and \$y = 2^{N-1}\$), but allows the output to cover the entire range. Note that this is exactly \$y = x \times 2^N / (2^N - 1)\$ with proper rounding!