The VHDL module "uart" (see symbol) transfers data by the universal asynchronous receiver/transmitter protocol.
It has a clock divider which is able to divide the incoming clock by non integer numbers to support each wished baudrate.
The module "uart" works full synchronous, this means all flipflops are clocked by the incoming clock signal.
The module is configurable by generics in order
The module "uart" was developed with HDL-SCHEM-Editor.
Port name | Direction | Description |
---|---|---|
res_i | input | asynchronous reset input, 1-active |
clk_i | input | clock input |
clock_divisor_i(g_divisor_width-1:0) | input | Determines the baudrate, must fulfill: clock_divisor_i>2 The resulting baudrate (for transmit and receive) is determined by: (frequency at clk_i)/clock_divisor_i If the resulting baudrate is not close enough to the wished baudrate, the inputs fraction_nominator_i/denominator_i can be used. Must be stable during sending and receiving. |
fraction_nominator_i(g_fraction_width-1:0) | input | If fraction_nominator_i is different from 0, then the resulting baudrate is determined by: (frequency at clk_i)/(clock_divisor_i + fraction_nominator_i/fraction_denominator_i) Must be stable during sending and receiving. |
fraction_denominator_i(g_fraction_width-1:0) | input | If fraction_nominator_i is different from 0, then the resulting baudrate is determined by: (frequency at clk_i)/(clock_divisor_i + fraction_nominator_i/fraction_denominator_i) Must be stable during sending and receiving. |
data_i(g_data_width-1:0) | input | Data to send Must be stable during sending. |
send_i | input | An 1-active impulse of 1 clock cycle width starts transmitting. |
tx_o | output | uart transmit output. Has value 1 at idle. |
ready_send_o | output | Changes from 1 to 0 after send_i=1. Changes from 0 to 1 after the last stopbit has been sent. |
rx_i | input | uart receive input. Expects 1 at idle. |
ready_receive_o | output | Is a 1-active impulse of one clock period. Gets active in the middle of the first stop bit. |
parity_err_o | output | Signals a parity error of the received data. Gets valid at the rising edge of ready_receive_o Changes to 0, when the next start bit is detected. |
data_o(g_data_width-1:0) | output | Received data. Gets valid in the middle of the last data bit (this means: before ready_receive_o=1). Stable until the middle of the first data bit of the next frame. Shall be sampled with ready_receive_o. |
Generic name | Minimum Value | Maximum Value | Description |
---|---|---|---|
g_divisor_width | 2 | n/a | Number of bits of clock_divisor_i |
g_fraction_width | 2 | n/a | Number of bits of fraction_nominator_i and fraction_denominator_i |
g_data_width | 1 | n/a | Number of bits of data_i, data_o and in the uart frame |
g_has_parity | false | true | If "true", then the uart frame will have a parity bit. |
g_odd_parity | false | true | When "true", then the number of ones together in databits and paritybit must be odd, else even. |
g_number_of_stopbits | 1 | g_data_width | This is the number of stop bits which are inserted at transmit. |
g_number_of_sync_flipflops | 0 | n/a | This is the number of flipflops which are used to synchronize rx_i. |
The module ""uart"" is a hierarchical module, which is built by 4 submodules.
Submodule name | Functionality |
---|---|
uart_clock_divider |
This submodule is a clock divider. It is used twice:
The submodule divides the incoming uart clock signal clk_i by the value provided at the uart input clock_divisor_i.
In this case the values at fraction_nominator_i and fraction_denominator_i can be used to create a send/receive clock-enable with the exact frequency by dividing in this way: (frequency at clk_i)/(clock_divisor_i + fraction_nominator_i/fraction_denominator_i) Of course the clock enable moments (or clock edges) of the divided clock are in this case not active at the exact moments where they should be, but jitter around these exact moments in a way that the difference to the exact moment is kept as small as possible. |
uart_send |
This submodule sends the data at input data_i to the output tx_o.
It starts transmitting as soon as an impulse is applied to the send_i input. |
uart_rx_sync |
This submodule synchronises the incoming uart receive signal rx_i with the clock signal clk_i. The number of flipflops used to avoid metastability must be configured by the generic g_number_of_sync_flipflops. |
uart_receive |
This submodule converts the synchronised uart receive signal into a data word at output data_o.
It samples the data at the centre of each data bit. |
Source code for HDL-SCHEM-Editor and HDL-FSM-Editor for module "uart" and its testbenches (Number of downloads =
31 ).
With these files the schematics and the state-diagram can be loaded into HDL-SCHEM-Editor or HDL-FSM-Editor and can be easily read and modified:
All module VHDL-files of the module "uart" (Number of downloads =
29 ).
These files were generated by HDL-SCHEM-Editor and HDL-FSM-Editor:
All testbench VHDL-files of the 2 testbenches of the module "uart" (Number of downloads =
31 ).
These files were generated by HDL-SCHEM-Editor and HDL-FSM-Editor:
You should extract all archives into a folder named "uart".
Then you should load the toplevel (probably the testbench) into HDL-SCHEM-Editor.
When you navigate through the design hierarchy by a double click at each symbol,
HDL-SCHEM-Editor will find the submodules on your disk and ask if it can replace
the original path to the submodule by the new one at your disk.
After storing the changed modules the relocation of the source files is ready
(instead you could replace "M:/gesicherte Daten/Programmieren/VHDL/uart" in all
"hdl_editor_designs/*.hse" source files by your path to this directory with your editor).
Now you can navigate through the design by HDL-SCHEM-Editor and generate HDL by HDL-SCHEM-Editor for
all modules except uart_send and uart_receive, for which the HDL must be generated by HDL-FSM-Editor.
Of course there is only need for generating HDL, if you change something at the modules, because you can find the HDL in VHDL_designs.zip and VHDL_testbenches.zip.
If you want to simulate or modify the modules by HDL-SCHEM-Editor you also must adapt the information in the Control-tab of the toplevel you want to work on.
There you must define a "Compile through hierarchy command", an "Edit command", the path to your HDL-FSM-Editor and a "Working directory".
Version 1.0 (24.02.2025):
If you detect any bugs or have any questions,
please send a mail to "matthias.schweikart@gmx.de".