Yes, yes, yes and yes :).
See for example our PoC.io.uart.fifo module:
entity uart_fifo is
generic (
-- Communication Parameters
CLOCK_FREQ : FREQ;
BAUDRATE : BAUD;
ADD_INPUT_SYNCHRONIZERS : BOOLEAN := TRUE;
-- Buffer Dimensioning
TX_MIN_DEPTH : positive := 16;
TX_ESTATE_BITS : natural := 0;
RX_MIN_DEPTH : positive := 16;
RX_FSTATE_BITS : natural := 0;
-- Flow Control
FLOWCONTROL : T_IO_UART_FLOWCONTROL_KIND := UART_FLOWCONTROL_NONE;
SWFC_XON_CHAR : std_logic_vector(7 downto 0) := x"11"; -- ^Q
SWFC_XON_TRIGGER : real := 0.0625;
SWFC_XOFF_CHAR : std_logic_vector(7 downto 0) := x"13"; -- ^S
SWFC_XOFF_TRIGGER : real := 0.75
);
port (
-- ...
);
This module wraps a transmitter and receiver plus bit-clock generator in a single module and attaches two FIFOs. The module makes extensive use of generics in form of:
- standard types (BOOLEAN, POSITIVE, ...),
- physical types (FREQ, BAUD) and an
- enum (T_IO_UART_FLOWCONTROL_KIND).
The latter one is defined in the package PoC.uart
, which is referenced by a use
clause. The top-level module, that instantiates uart_fifo
, needs also to reference this package.
package uart is
type T_IO_UART_FLOWCONTROL_KIND is (
UART_FLOWCONTROL_NONE,
UART_FLOWCONTROL_XON_XOFF,
UART_FLOWCONTROL_RTS_CTS,
UART_FLOWCONTROL_RTR_CTS
);
constant C_IO_UART_TYPICAL_BAUDRATES : T_BAUDVEC := (
0 => 300 Bd, 1 => 600 Bd, 2 => 1200 Bd, 3 => 1800 Bd, 4 => 2400 Bd,
5 => 4000 Bd, 6 => 4800 Bd, 7 => 7200 Bd, 8 => 9600 Bd, 9 => 14400 Bd,
10 => 16000 Bd, 11 => 19200 Bd, 12 => 28800 Bd, 13 => 38400 BD, 14 => 51200 Bd,
15 => 56000 Bd, 16 => 57600 Bd, 17 => 64000 Bd, 18 => 76800 Bd, 19 => 115200 Bd,
20 => 128000 Bd, 21 => 153600 Bd, 22 => 230400 Bd, 23 => 250000 Bd, 24 => 256000 Bd,
25 => 460800 Bd, 26 => 500000 Bd, 27 => 576000 Bd, 28 => 921600 Bd
);
function io_UART_IsTypicalBaudRate(br : BAUD) return BOOLEAN;
-- ...
end package;