Forum Discussion
Altera_Forum
Honored Contributor
19 years agoHi all,
here is some good news for those who want a better performance on UART, based on cal_uart. I could achieve a 1MBytes transfer at 115200 bps with no errors when "cat /dev/ttyS0 > /tmp/file&" is the only user task I run (Nios2\s at 72MHz). I get ~1% error on 1MBytes transfer when running several daemons at the same time. I did it with a 64 bytes FIFO and I had the same performances with a 1024 bytes FIFO. To do this I modified the VHDL file generated by cal_uart to change the rx irq conditions. The interrupt is requested when FIFO is 50% full or if bytes are present in buffer after a delay (so that even if FIFO never gets 50% full, bytes can be read). I still have some questions about this : - I don't know anything about the scripts that generate the VHDL from the SOPC builder .ptf file. Can someone tell me where I should add my code so that it is generated in the cal_uart component ? Is this in the em_uart.pl script ? Is there any documentation on how to use this kind of scripts ? For now I have to modify the VHDL file after generating the SOPC builder components, this is not very elegant (see below)... - To adjust performance, I can play with 3 parameters : FIFO size, FIFO level to request IRQ (50% full, 75% full....) and the timer delay. I tried with 64 bytes FIFO, 50% full and 7ms delay. Does anyone have an idea of the parameters commonly used in other FIFO'ed uarts ? If someone is interested, here is the small modifications to do to the uart_ext.vhd file generated when using a cal_uart at 115200 bauds, 8N1, RTSCTS enabled, baudrate divisor writeable, and a 64 bytes FIFO : At line 1288, replace signal tx_not_empty : STD_LOGIC;
signal tx_not_full : STD_LOGIC;
signal tx_overrun : STD_LOGIC;
signal tx_used : STD_LOGIC_VECTOR (5 DOWNTO 0); by signal tx_not_empty : STD_LOGIC;
signal tx_not_full : STD_LOGIC;
signal tx_overrun : STD_LOGIC;
signal tx_used : STD_LOGIC_VECTOR (5 DOWNTO 0);
signal rx_counter : STD_LOGIC_VECTOR (18 DOWNTO 0);
signal rx_fifo_timeout : STD_LOGIC; At line 1541, replace qualified_irq <= ((((((((((ie_dcts AND dcts_status_bit)) OR ((ie_any_error AND any_error))) OR ((ie_tx_shift_empty AND tx_shift_empty))) OR ((ie_tx_overrun AND tx_overrun))) OR ((ie_rx_overrun AND rx_overrun))) OR ((ie_break_detect AND break_detect))) OR ((ie_framing_error AND framing_error))) OR ((ie_parity_error AND parity_error))) OR ((ie_rx_char_ready AND x_not_empty))) OR ((ie_tx_ready AND tx_not_full)); by qualified_irq <= ((((((((((ie_dcts AND dcts_status_bit)) OR ((ie_any_error AND any_error))) OR ((ie_tx_shift_empty AND tx_shift_empty))) OR ((ie_tx_overrun AND tx_overrun))) OR ((ie_rx_overrun AND rx_overrun))) OR ((ie_break_detect AND break_detect))) OR ((ie_framing_error AND framing_error))) OR ((ie_parity_error AND parity_error))) OR ((ie_rx_char_ready AND (rx_used(5) OR rx_fifo_timeout )))) OR ((ie_tx_ready AND tx_not_full));
process (clk, reset_n)
begin
if reset_n = '0' then
rx_fifo_timeout <= '0';
rx_counter <= (others => '0');
elsif clk'event and clk = '1' then
if std_logic'(clk_en) = '1' then
if rx_counter(18) = '1' then
if rx_empty = '1' then
rx_counter <= (others => '0');
rx_fifo_timeout <= '0';
else
rx_fifo_timeout <= '1';
end if;
else
rx_counter <= rx_counter + 1;
rx_fifo_timeout <= '0';
end if;
end if;
end if;
end process; I hope someone can help me automate this :-) Any comments or help welcome. Regards Pierre-Olivier