I understand that this is an example, and that the OP will need to
modify it or add to it per their purposes, but...
If you let the user set the period of the sample counter (via a
generic or a port), and you simply use half that sample period as your
sampling point (divide by two is free in HW), then the user can use
this module, untouched, for almost any baud rate and clock frequency,
without having to generate a clock enable timebase, so long as the
counter does not get too big or too small (2 < n < 2**31 - 1, for a
natural counter).
A few coding related recommendations:
Use numeric_std packages which contain SL-based types and operators
for unsigned and signed arithmetic, or bettter yet, use integer
subtypes (which you did for bit_pos, but not sample_cnt). Std_logic_
[arith/signed/unsigned] are _NOT_ IEEE controlled, standard packages,
and their implementations can vary across different tools.
Adopt a single process coding style with the following advantages: it
uses fewer signals, has simpler sensitivity lists, cannot generate
latches, integrates clock enable and functional behavior, is more
efficient to simulate, and allows optimal use of variables. If you
MUST use combinatorial processes (doubtful), put all of your default
assignments right up front in the process. This makes auditing/
reviewing your combinatorial process simpler to ensure that every
output is written in every execution of your process (to avoid
latches). I understand that most textbooks still promote dual
combinatorial & clocked process pairs, but the state of the art in
industry has moved beyond that for the most part.
When possible, avoid combinatorial outputs from architectures in
synthesizable code. This avoids glitches on outputs, and simplifies
timing optimizattion.
I hate to discourage using a block statement (they are often not used
when they should be), but you should avoid using blocks which are
redundant with the architecture's scope. It needlessly extends net
names in the synthesis netlist, not to mention the source code and
indentation levels. Blocks are a useful structure to limit scope
within an architecture that contains multiple processes, or
combinatorial/clocked process pairs (I prefer only clocked processes
with variables, but a block for each pair can accomplish the same
scope control with signals).
Andy