1 ------------------------------------------------------------------------------- 3 --! @author Hipolito Guzman-Miranda 4 --! @brief Emulates an UART receiver. 5 ------------------------------------------------------------------------------- 7 --! Use IEEE standard definitions library 9 --! Use std_logic* signal types 10 use ieee.std_logic_1164.
all;
11 --! Use arithmetic operations and unsigned types 12 use ieee.numeric_std.
all;
13 --! Use the chr function to convert integer to char 15 --! Include datatypes and procedures needed to write to files 17 --! Use the slv2string function present in the vhdl_verification package 20 --! @brief Emulates an UART receiver. Writes receiver characters to a file. 22 --! @details Waits for \c uart_input to leave rest state, and extracts data 23 --! from the serial line, performing some sanity checks. If \c PARITY is either 24 --! "even" or "odd", parity is also extracted from the serial line and checked 25 --! against the expected value. In the case of a parity mismatch, an error will be 26 --! printed in the simulation log. Received characters will be printed in \c 28 --! state of the leds each time any the input bit changes. Does not keep any 29 --! internal memory, \c led_input is assumed to be directly connected to the 33 OUTPUT_FILE : := "uart.log";
--! File where received chars will be written 34 VERBOSE : := false;
--! Log beginning and end of transactions, as well as individual bit values 35 DATA_BITS : := 8;
--! Number of data bits in the UART word 36 PARITY : := "none";
--! Can be either "even", "odd", or "none" 37 BIT_DURATION : := 104 us;
--! Duration of each bit, depends on baudrate (it is actually 1 second / baudrate) 41 uart_input : in --! Connect here the TX signal from your design 45 --! @brief Architecture is based on just a single process 47 --! @detailed An assertion has also been added to check that generics are 48 --! assigned supported values. 51 constant LINE_FEED : (7 downto 0) := x"0A";
54 signal expectedparity : ;
58 -- PARITY must be one of the three supported values 60 report "uart_emu: PARITY must be either even, odd or none" 63 -- STOP_BITS must be one of the two supported values 65 report "uart_emu: STOP_BITS must be either 1 or 2" 69 --! @brief Decode \c uart_input signal and write it to \c OUTPUT_FILE 71 --! @detailed Assuming the line is in the rest value ('1') when we are 72 --! outside of the process, when we enter the process it should be because 73 --! the line changed to the start bit ('0'). From that point, get all the 74 --! data values and the parity, performing some sanity checks. 75 --! Please note that this process does not check for signal stability 76 --! (we will not raise any errors if the signals change a bit sooner or later 77 --! than \c BIT_DURATION), we just measure the signal at half the bit time, 78 --! as a real UART receiver would do. 87 -- A transaction start when the line goes to a strong low level 90 report "uart_emu: uart transaction begin";
93 -- Offset half a bit so we measure at the center of each bit 96 -- Raise an error if we are not in the start bit 98 report "uart_emu: wrong value for start bit: expected: '0', actual: " & 'image(uart_input) severity failure;
106 report "uart_emu: sampled bit " & 'image(i) & ", got value: " & 'image(uart_input);
110 -- Print received data. If DATA_BITS = 8, print it also in ASCII 112 report "uart_emu: received data: " & slv2string(rxdata) & " (bin), " & slv2hexstring(rxdata) & " (hex), " & ascii(to_integer((rxdata))) & " (ASCII)";
114 report "uart_emu: received data: " & slv2string(rxdata) & " (bin), " & slv2hexstring(rxdata) & " (hex)";
117 -- If DATA_BITS = 8, write received data to output file. Data is always 118 -- prepared to be written to the output file, no matter if we have parity 121 -- We write the received char into the line variable, and not directly 122 -- into the file, unless we got a newline char (line feed, \n). Only when 123 -- we receive a newline char, we commit the line to the file. 125 -- This would probably be more convenient if we wrote to a pipe instead 126 -- of writing to a file, but I am not sure if that would work on Windows. 128 -- Since the file output seems to be buffered, normally it would not be 129 -- actually written to the log until we close the file, which should 130 -- happen automatically at the end of the simulation. But in that case 131 -- we would get all the text at the same time, instead of line by line as 132 -- the simulation progresses. So we will open and close the file each 133 -- time we have a complete line. 135 if rxdata /= LINE_FEED then 136 write (l, ascii(to_integer((rxdata))));
138 file_open(f, OUTPUT_FILE, append_mode);
144 -- If parity is even or odd, get parity bit 150 -- Calculate expected parity 152 expectedparity <= xor_reduce(rxdata);
154 expectedparity <= xnor_reduce(rxdata);
156 expectedparity <= '-';
159 -- Check if received parity matches expected, report an error if not 161 if rxparity /= expectedparity then 162 report "uart_emu: parity error! received parity bit: " & 'image(rxparity) & " expected: " & 'image(expectedparity) 167 -- Wait for stop bits, and raise errors if the value is incorrect. 168 -- We always will have at least one stop bit 171 report "uart_emu: wrong value for stop bit: expected: '1', actual: " & 'image(uart_input) severity failure;
174 -- But sometimes we will have a second stop bit 178 report "uart_emu: wrong value for second stop bit: expected: '1', actual: " & 'image(uart_input) severity failure;
182 -- We could do a last half-bit shift before we exit the process, but since 183 -- we will wait for an event on uart_input when we enter the process again, 184 -- that half-bit wait will be performed nevertheless. 185 -- Also, by not manualy waiting for a half-bit, we avoid missing the start 186 -- bit event on uart_input in the case of receiving a new transaction just 187 -- after the last stop bit. 190 report "uart_emu: uart transaction end";
in uart_inputstd_logic
Connect here the TX signal from your design.
Common datatypes and component declarations.
PARITYstring := "none"
Can be either "even", "odd", or "none".
STOP_BITSinteger := 1
Can be either 1 or 2.
OUTPUT_FILEstring := "uart.log"
File where received chars will be written.
uart_emu
Connect here the signal that drives the leds.
DATA_BITSinteger := 8
Number of data bits in the UART word.
VERBOSEboolean := false
Log beginning and end of transactions, as well as individual bit values.
BIT_DURATIONtime := 104 us
Duration of each bit, depends on baudrate (it is actually 1 second / baudrate)
Emulates an UART receiver. Writes receiver characters to a file.
Allows for text output in simulation.