Перейти к содержанию
    

Как отловить ошибку в UART ? [РЕШЕНО]

Я написал в Quartus код для приема байтов по UART:
 

module uart_rx #(
	parameter CLK_FREQUENCY,
	parameter UART_BAUDRATE,
	parameter BITS_NUMBER
	)(
	input		clock,
	output reg	stop_rx,
	output		test,//---------------------------------
	output reg	[BITS_NUMBER-1:0]data_rx,
	input		rx_in
	);	
	parameter CLK_PERIOD	= 1000/CLK_FREQUENCY;
	parameter UART_PERIOD	= 1000_000_000/UART_BAUDRATE;
	parameter CLK_DIVIDER	= UART_PERIOD/CLK_PERIOD;

	enum {IDLE,
		START_WAIT,
		START_GET,
		BIT_WAIT,
		BIT_GET,
		STOP_WAIT,
		STOP_GET,
		END} fsm;
			
	reg [17:0]delay_cnt;
	reg [7:0]data_store;
	reg [3:0]bit_cnt;
	
	assign test = ~rx_in && stop_rx;//-------------------

	always @(posedge clock) begin
		case(fsm)
			IDLE:begin
				if(~rx_in) begin
					stop_rx	<= LOW;
					delay_cnt<= CLK_DIVIDER/2;
					fsm		<= START_WAIT;
				end
			end
			START_WAIT:begin
				delay_cnt <= delay_cnt - 1;
				if(delay_cnt == 0) begin
					bit_cnt	<= 0;
					fsm 		<= START_GET;
				end
			end
			START_GET:begin
				delay_cnt<= CLK_DIVIDER;
				bit_cnt	<= 0;
				fsm		<= BIT_WAIT;
			end
			BIT_WAIT:begin
				delay_cnt <= delay_cnt - 1;
				if(delay_cnt == 0) begin
					fsm 	<= BIT_GET;
				end
			end
			BIT_GET:begin
				data_store[bit_cnt] <= rx_in;
				bit_cnt <= bit_cnt + 1;
				delay_cnt<= CLK_DIVIDER;
				if(bit_cnt == BITS_NUMBER-1) begin
					fsm 	<= STOP_WAIT;
				end
				else begin
					fsm 	<= BIT_WAIT;
				end
			end
			STOP_WAIT:begin
				delay_cnt <= delay_cnt - 1;
				if(delay_cnt == 0) begin
					fsm 	<= STOP_GET;
				end
			end
			STOP_GET:begin
				data_rx	<= data_store;
				fsm 		<= END;
			end
			END:begin
				stop_rx	<= HIGH;
				fsm		<= IDLE;
			end
		endcase
	end
endmodule

На симуляторе всё (разумеется) отлично. В железе (DE0-Nano и ПЛИСом EP4CE22F17C6N) всё отлично. Почти. Код срабатывает где-то 9 из 10 раз.

CLK_FREQUENCY устанавливал в 50 и в 25.
UART_BAUDRATE - в 57600 и 9600.
Данные одни и те же - два ASCII-кода символов "A" и "B" подряд.
Пробовал менять их местами, частота ошибки вроде не поменялась.

Судя по осциллографу иногда конечный автомат не выходит из состояния IDLE, несмотря на нисходящий фронт старт-бита:

always @(posedge clock) begin
	case(fsm)
		IDLE:begin
			if(~rx_in) begin
				stop_rx	<= LOW;
				delay_cnt<= CLK_DIVIDER/2;
				fsm		<= START_WAIT;
			end
		end
...

Хотя, как видно по линии "test", сам стартовый бит вполне осознается ПЛИСом.
Осциллограмма снималась с дополнительных пинов ПЛИСа, которым были назначены (при помощи assign):
1) rx от UARTа
2) stop_rx от модуля
3) test от модуля

Сама ошибка возникает как в первом, так и во втором байте всей передачи, причем независимо от того передается ли "AB", или "BA".

Вопрос: в чем может быть причина и как отлавливать подобные ошибки?

scope.png

Изменено пользователем flammmable

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А на осциллограмме что есть что?
Как организовывается передача, между чем и чем? Я к тому что если между FPGA  и внешним устройством, то может попробовать loop-test, все передавать и принимать внутри FPGA? Что в этом случае будет

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

 

27 minutes ago, R6L-025 said:

А на осциллограмме что есть что?

 

Осциллограмма снималась с дополнительных пинов ПЛИСа, которым были назначены (при помощи assign):
1) (синий) rx от UARTа
2) (желтый) stop_rx от модуля
3) (зеленый) test от модуля

 

27 minutes ago, R6L-025 said:

Как организовывается передача, между чем и чем?

За ПЛИС - DE0-Nano (EP4CE22F17C6N). За UART - FT232 от Waveshare (FT232RL), txd/rxd которого соединены проводами с пинами демоплаты.

 

27 minutes ago, R6L-025 said:

Я к тому что если между FPGA  и внешним устройством, то может попробовать loop-test, все передавать и принимать внутри FPGA?

Учитывая, что осциллограмма снималась с дополнительных пинов ПЛИСа, одному из которых был назначен (при помощи assign) rx от UARTа (для FT232RL это, разумеется txd) и то, что биты, получаемые с rx видны на осциллограмме можно заключить, что сигнал вполне заходит внутрь ПЛИСа.

Т.е. в верхнем модуле есть input rx и output output_test_2. И rx подключен И к модулю uart_rx И выходному пину output_test_2. С которого снята синяя осциллограмма.

 

 

 

 


 

Изменено пользователем flammmable

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В SignalTap смотрел что происходит внутри? Может там что-то странное получится увидеть. Посмотреть на состояние fsm, stop_rx,  delay_cnt. Ну и еще яб добавил системе reset. Иначе нельзя гарантировать что система будет в известном состоянии на момент начала работы. Еще - можно добавить default ветку в switch-case, чтоб отлавливать ошибочные состояния (на всякий случай).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я бы тебе посоветовал шину rx_in завести на триггер в отдельном процессе и уже его анализировать. А ещё можно было бы поставить простенький фильтр из 3 регистров. Для этого надо провести входной сигнал по трем регистрам. И создать 4 сигнал, который будет отображать в себе следующее (reg1 and reg2) or (reg2 and reg 3) or (reg1 and 3).

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Изначально "fsm"  в каком состоянии? Теоретически на симуляторе все триггера автомата могут быть в  "0", а в ПЛИС в "1" и наоборот. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Приветствую!

7 minutes ago, mixa7109 said:

Я бы тебе посоветовал шину rx_in завести на триггер

Это   должен быть не совет а требование! Уже  много раз говорилось  -  внешние входные сигналы  нужно синхронизировать  перед использованием. 

Это  как  два триггера (подряд)  об  асфальт :acute: 

 

Удачи! Rob

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1) Поставить по всем входам по два последователньых триггера.

2) Пока компилируется читать про метастабильность.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Синхронизация с доменом входного сигнала + мажоритарный фильтр + выборка для фильтра в центре бита.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Творчески переосмыслив советы, добавил reg rx_inner; и в том же always прямо перед case добавил rx_inner <= rx_in; . А все дальнейшие операции с rx_in заменил на операции с rx_inner.

Ошибка больше не появляется. Всем спасибо!

Изменено пользователем flammmable

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

10 часов назад, flammmable сказал:

Творчески переосмыслив советы, добавил reg rx_inner; и в том же always прямо перед case добавил rx_inner <= rx_in; . А все дальнейшие операции с rx_in заменил на операции с rx_inner.

Ошибка больше не появляется. Всем спасибо!

 

Для надежного uart - этого мало.

Неплохо было бы поставить некий фильтр, который сглаживает всплески\проседания\пологие фронты.

Неплохо было бы выборку данных бита, делать в середине битового интервала

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

9 hours ago, Flip-fl0p said:

Неплохо было бы выборку данных бита, делать в середине битового интервала

Она и так делается в середине интервала. При переходе автомата в состояние START_WAIT задержка устанавливается в delay_cnt<= CLK_DIVIDER/2;
Далее при переходе в состояние BIT_WAIT задержка устанавливается в delay_cnt<= CLK_DIVIDER;

 

9 hours ago, Flip-fl0p said:

Неплохо было бы поставить некий фильтр, который сглаживает всплески\проседания\пологие фронты.

А вот это - вопрос дискуссионный. Можно сделать мажоритарный фильтр, можно включить в UART бит паритета, можно добавить handshake, можно прикрутить CRC16 и т.д.
Но все эти вещи не решают проблемы, а маскируют их.

Возможна ситуация, что необходима безошибочная работа устройства в течение 1 часа, а некая ошибка происходит раз в 6 часов. Вроде неплохо. Но и не хорошо. Прикручиваем CRC, к примеру, и ошибка возникает раз в 1 неделю (когда неизбежно случается коллизия контрольной суммы). Отлично!

А теперь предположим, что необходима безошибочная работа устройства в течение 1 часа, а некая ошибка происходит раз в 10 минут. Прикручиваем CRC и ошибка начинает повторяться раз в 6 часов. Затем устройство передается из производства в эксплуатацию, а там оказываются какие-либо специфические условия, не покрытые тестами. И - оп! Ошибка начинает появляться именно раз в 1 час. Но теперь её сложнее локализовать.

Представляется что у всех этих фильтров и контрольных сумм важной функцией является возможность разом их отключить для проведения диагностики.

Изменено пользователем flammmable

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

7 минут назад, flammmable сказал:

А вот это - вопрос дискуссионный. Можно сделать мажоритарный фильтр, можно включить в UART бит паритета, можно добавить handshake, можно прикрутить CRC16 и т.д.
Но все эти вещи не решают проблемы, а маскируют их.
 

 

Мажоритарный фильтр (МЖФ)- решает проблемы одноразовых всплесков\провалов в линии. Конечно если физическая среда - подвержена влиянию помех, и от каждого чиха в ней появляются проблемы, то МЖФ мало поможет. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

8 minutes ago, Flip-fl0p said:

Мажоритарный фильтр (МЖФ)- решает проблемы одноразовых всплесков\провалов в линии. Конечно если физическая среда - подвержена влиянию помех, и от каждого чиха в ней появляются проблемы, то МЖФ мало поможет. 

Одноразовых в пределах периода дискретизации. Если иглы толще двух периодов, то МЖФ из трех триггеров начнет распознавать их не как иглы, а как сигнал. Если иглы сильно тоньше одного периода, то они и так не повлияют на передачу.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

45 минут назад, flammmable сказал:

Одноразовых в пределах периода дискретизации. Если иглы толще двух периодов, то МЖФ из трех триггеров начнет распознавать их не как иглы, а как сигнал. Если иглы сильно тоньше одного периода, то они и так не повлияют на передачу.

Так МЖФ можно делать не на 3 отсчета, а на 5 например, или 7. Если у Вас столько игл - в сигнале, значит проблема на физическом уровне. Тут ничего не спасет.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...