Форум программистов, компьютерный форум, киберфорум
Программируемая логика: ПЛИС, ПАИС
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.91/82: Рейтинг темы: голосов - 82, средняя оценка - 4.91
Lessberg
1

VHDL. Реализация UART на ПЛИС

28.01.2013, 16:52. Просмотров 16583. Ответов 3
Метки нет (Все метки)

Добрый день.
Была поставлена задача реализовать передачу данных через UART (com порт) интерфейс rs-232 передачу данных (чисел) с ПК на плату altera DE2.

За основу решил брать уже готовый проект. Их множество. Мой выбор пал вот на этот:
Код
----------------------------------------------------------------------------------
-- Creation Date: 21:12:48 05/06/2010 
-- Module Name: RS232/UART Interface - Behavioral
-- Used TAB of 4 Spaces
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity uart is
generic (
	CLK_FREQ	: integer := 50;		-- Main frequency (MHz)
	SER_FREQ	: integer := 9600		-- Baud rate (bps)
);
port (
	-- Control
	clk			: in	std_logic;		-- Main clock
	rst			: in	std_logic;		-- Main reset
	-- External Interface
	rx			: in	std_logic;		-- RS232 received serial data
	tx			: out	std_logic;		-- RS232 transmitted serial data
	-- RS232/UART Configuration
	par_en		: in	std_logic;		-- Parity bit enable
	-- uPC Interface
	tx_req		: in	std_logic;						-- Request SEND of data
	tx_end		: out	std_logic;						-- Data SENDED
	tx_data		: in	std_logic_vector(7 downto 0);	-- Data to transmit
	rx_ready	: out	std_logic;						-- Received data ready to uPC read
	rx_data		: out	std_logic_vector(7 downto 0)	-- Received data 
);
end uart;

architecture Behavioral of uart is

	-- Constants
	constant UART_IDLE	:	std_logic := '1';
	constant UART_START	:	std_logic := '0';
	constant PARITY_EN	:	std_logic := '1';
	constant RST_LVL	:	std_logic := '1';

	-- Types
	type state is (idle,data,parity,stop1,stop2);			-- Stop1 and Stop2 are inter frame gap signals

	-- RX Signals
	signal rx_fsm		:	state;							-- Control of reception
	signal rx_clk_en	:	std_logic;						-- Received clock enable
	signal rx_rcv_init	:	std_logic;						-- Start of reception
	signal rx_par_bit	:	std_logic;						-- Calculated Parity bit
	signal rx_data_deb	:	std_logic;						-- Debounce RX data
	signal rx_data_tmp	:	std_logic_vector(7 downto 0);	-- Serial to parallel converter
	signal rx_data_cnt	:	std_logic_vector(2 downto 0);	-- Count received bits

	-- TX Signals
	signal tx_fsm		:	state;							-- Control of transmission
	signal tx_clk_en	:	std_logic;						-- Transmited clock enable
	signal tx_par_bit	:	std_logic;						-- Calculated Parity bit
	signal tx_data_tmp	:	std_logic_vector(7 downto 0);	-- Parallel to serial converter
	signal tx_data_cnt	:	std_logic_vector(2 downto 0);	-- Count transmited bits

begin

	tx_clk_gen:process(clk)
		variable counter	:	integer range 0 to conv_integer((CLK_FREQ*1_000_000)/SER_FREQ-1);
	begin
		if clk'event and clk = '1' then
			-- Normal Operation
			if counter = (CLK_FREQ*1_000_000)/SER_FREQ-1 then
				tx_clk_en	<=	'1';
				counter		:=	0;
			else
				tx_clk_en	<=	'0';
				counter		:=	counter + 1;
			end if;
			-- Reset condition
			if rst = RST_LVL then
				tx_clk_en	<=	'0';
				counter		:=	0;
			end if;
		end if;
	end process;

	tx_proc:process(clk)
		variable data_cnt	: std_logic_vector(2 downto 0);
	begin
		if clk'event and clk = '1' then
			if tx_clk_en = '1' then
				-- Default values
				tx_end					<=	'0';
				tx						<=	UART_IDLE;
				-- FSM description
				case tx_fsm is
					-- Wait to transfer data
					when idle =>
						-- Send Init Bit
						if tx_req = '1' then
							tx			<=	UART_START;
							tx_data_tmp	<=	tx_data;
							tx_fsm		<=	data;
							tx_data_cnt	<=	(others=>'1');
							tx_par_bit	<=	'0';
						end if;
					-- Data receive
					when data =>
						tx				<=	tx_data_tmp(0);
						tx_par_bit		<=	tx_par_bit xor tx_data_tmp(0);
						if tx_data_cnt = 0 then
							if par_en = PARITY_EN then
								tx_fsm	<=	parity;
							else
								tx_fsm	<=	stop1;
							end if;
							tx_data_cnt	<=	(others=>'1');
						else
							tx_data_tmp	<=	'0' & tx_data_tmp(7 downto 1);
							tx_data_cnt	<=	tx_data_cnt - 1;
						end if;
					when parity =>
						tx				<=	tx_par_bit;
						tx_fsm			<=	stop1;
					-- End of communication
					when stop1 =>
						-- Send Stop Bit
						tx				<=	UART_IDLE;
						tx_fsm			<=	stop2;
					when stop2 =>
						-- Send Stop Bit
						tx_end			<=	'1';
						tx				<=	UART_IDLE;
						tx_fsm			<=	idle;
					-- Invalid States
					when others => null;
				end case;
				-- Reset condition
				if rst = RST_LVL then
					tx_fsm				<=	idle;
					tx_par_bit			<=	'0';
					tx_data_tmp			<=	(others=>'0');
					tx_data_cnt			<=	(others=>'0');
				end if;
			end if;
		end if;
	end process;

	rx_debounceer:process(clk)
		variable deb_buf	:	std_logic_vector(3 downto 0);
	begin
		if clk'event and clk = '1' then
			-- Debounce logic
			if deb_buf = "0000" then
				rx_data_deb		<=	'0';
			elsif deb_buf = "1111" then
				rx_data_deb		<=	'1';
			end if;
			-- Data storage to debounce
			deb_buf				:=	deb_buf(2 downto 0) & rx;
		end if;
	end process;

	rx_start_detect:process(clk)
		variable rx_data_old	:	std_logic;
	begin
		if clk'event and clk = '1' then
			-- Falling edge detection
			if rx_data_old = '1' and rx_data_deb = '0' and rx_fsm = idle then
				rx_rcv_init		<=	'1';
			else
				rx_rcv_init		<=	'0';
			end if;
			-- Default assignments
			rx_data_old			:=	rx_data_deb;
			-- Reset condition
			if rst = RST_LVL then
				rx_data_old		:=	'0';
				rx_rcv_init		<=	'0';
			end if;
		end if;
	end process;


	rx_clk_gen:process(clk)
		variable counter	:	integer range 0 to conv_integer((CLK_FREQ*1_000_000)/SER_FREQ-1);
	begin
		if clk'event and clk = '1' then
			-- Normal Operation
			if counter = (CLK_FREQ*1_000_000)/SER_FREQ-1 or rx_rcv_init = '1' then
				rx_clk_en	<=	'1';
				counter		:=	0;
			else
				rx_clk_en	<=	'0';
				counter		:=	counter + 1;
			end if;
			-- Reset condition
			if rst = RST_LVL then
				rx_clk_en	<=	'0';
				counter		:=	0;
			end if;
		end if;
	end process;

	rx_proc:process(clk)
	begin
		if clk'event and clk = '1' then
			-- Default values
			rx_ready		<=	'0';
			-- Enable on UART rate
			if rx_clk_en = '1' then
				-- FSM description
				case rx_fsm is
					-- Wait to transfer data
					when idle =>
						if rx_data_deb = UART_START then
							rx_fsm		<=	data;
						end if;
						rx_par_bit		<=	'0';
						rx_data_cnt		<=	(others=>'0');
					-- Data receive
					when data =>
						-- Check data to generate parity
						if par_en = PARITY_EN then
							rx_par_bit		<=	rx_par_bit xor rx;
						end if;

						if rx_data_cnt = 7 then
							-- Data path
							rx_data(7)		<=	rx;
							for i in 0 to 6 loop
								rx_data(i)	<=	rx_data_tmp(6-i);
							end loop;

							-- With parity verification
							if par_en = PARITY_EN then
								rx_fsm		<=	parity;
							-- Without parity verification
							else
								rx_ready	<=	'1';
								rx_fsm		<=	idle;
							end if;
						else
							rx_data_tmp		<=	rx_data_tmp(6 downto 0) & rx;
							rx_data_cnt		<=	rx_data_cnt + 1;
						end if;
					when parity =>
						-- Check received parity
						rx_fsm				<=	idle;
						if rx_par_bit = rx then
							rx_ready		<=	'1';
						end if;
					when others => null;
				end case;
				-- Reset condition
				if rst = RST_LVL then
					rx_fsm			<=	idle;
					rx_ready		<=	'0';
					rx_data			<=	(others=>'0');
					rx_data_tmp		<=	(others=>'0');
					rx_data_cnt		<=	(others=>'0');
				end if;
			end if;
		end if;
	end process;

end Behavioral;
На ПК стоит программа COM Port Tool Kit.

Входные данные я задаю 8-ми тумблерами тем самым передавая значения от 00 до FF. Все хорошо. ПК их принимает.

Вся загвоздка с выводом данных при передачи с ПК на ПЛИС. В конце хотелось бы получить конечно отображение на семисегментных индикаторах, но для начала, вывод подключаю на 8 светодиодов, чтобы понимать какой код пришел.

Данные посылаются в виде HEX чеез программу на ПК. Например я хочу получить '1' Отправляю значит "01" с ПК но загораются все 8 диодов сразу. Если введу "01,01" тоже все 8 горят. "01,02" уже получается что пришел сигнал "1111 1110". В общем не могу понять как с компа верно посылать данные..

Код
					when data =>
						-- Check data to generate parity
						if par_en = PARITY_EN then
							rx_par_bit		<=	rx_par_bit xor rx;
						end if;

						if rx_data_cnt = 7 then
							-- Data path
							rx_data(7)		<=	rx;

							for i in 0 to 6 loop
								rx_data(i)	<=	rx_data_tmp(6-i);
							end loop;
Вопрос в том, как верно передать данные, в каком формате. COM port Tool Kit передает HEX значения по парам например "00" "01,02,03" "10,50,32,98" и тд

Добавлено через 1 час 54 минуты
в принципе с проблемой разобрался. Позже выложу проект готовый, может комуто пригодится в учебных целях.
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
28.01.2013, 16:52
Ответы с готовыми решениями:

Реализация ОЗУ в ПЛИС
реализовать ОЗУ для 8 разрядных значений с возможностью чтения по адресам задаваемым через свич и...

Мигание светодиодов (ПЛИС,VHDL)
Устройство моргания 4-мя светодиодами.По сути,программа очень простая.Но у меня в итоге светодиоды...

ПЛИС длинный сдвиговый регистр с параллельной загрузкой VHDL
Подтолкните в нужную сторону, никак не могу сообразить. С одной стороны поступают байты по...

Реализация АЛУ на VHDL
Помогите пожалуйста разобраться. Передо мною стоит задача - описать на VHDL 32 разрядное АЛУ, с...

3
10205 / 6587 / 493
Регистрация: 28.12.2010
Сообщений: 21,165
Записей в блоге: 1
02.06.2013, 15:15 2
opencores.org:
- UART 16550 core
- UART to Bus
- Serial Uart
0
Вложения
Тип файла: zip miniuart2.zip (2.96 Мб, 289 просмотров)
Тип файла: zip uart2bus.zip (259.6 Кб, 261 просмотров)
Тип файла: zip uart16550.zip (1.73 Мб, 258 просмотров)
75 / 75 / 8
Регистрация: 24.09.2015
Сообщений: 342
25.09.2015, 12:03 3
UART надо бы и самому написать, тогда разберешься, как ПЛИС работает.

Сперва промоделировать. Подключить передатчик к приемнику и посмотреть, как на моделе всё работает. При этом желательно сделать разными и некратными внутренние тактовые частоты у передатчика и приёмника (потому что внутренняя частота ПК другая, чем у ПЛИС). Например, у передатчика сделать тактовую частоту 33.333 МГц, у приёмника 20 МГц. Частоты передачи и приёма дожны быть согласованы, с точностью лучше, чем ~5%.

Затем реализовать проект прибавления к принятому байту единицы и отсылка обратно. На терминале на ПК набираешь 'a', в ответ приходит 'b'.

При работе с железом надо соблюдать некоторую осторожность при подключение COM кабеля. Включать питание на плате надо после подключения кабеля к компьютеру. Иначе рано или поздно сгорит одна из микросхем драйверов физического уровня либо на плате, либо в компьютере. Еще надо иметь ввиду, что USB-COM адаптеры часто очень капризные и не хотят работать, так что не плохо смотреть иногда сигналы TxD, RxD осцилографом.
0
-20 / 0 / 4
Регистрация: 04.08.2015
Сообщений: 346
02.12.2017, 12:43 4
По необходимости гуглил тему UART для ПЛИС. Оказалось, что реализаций на VHDL Verilog большое количество вариантов. А на opencores вообще имеется код полного UART https://opencores.org/project,uart16550. Остановился на http://acvarif.info/prvhdl/com... ml#prvhdl7, где есть тест с COM port Tool Kit на скорости 115200.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
02.12.2017, 12:43

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

Расчет и реализация КИХ фильтра на VHDL
Здравствуйте, У меня есть плата HELPER LMD-System c АЦП, ЦАП(в виде шим фильтра), cyclon 3. Я...

Реализация кода Рида-Соломона на ПЛИС фирмы Altera типа FPGA
Всем привет! Нужна помощь в реализации кода Рида-Соломона на ПЛИС фирмы Altera типа FPGA. Среда...

Программная реализация UART на AT89S8253 в Keil
Добрый день! Использую AT89S8253 для приема-отправки данных по встроенному протоколу UART ....

Сообщения для 2 UART выводятся в 1 UART, STM32F103C8T6
Почему может неправильно работать uart? Подключил 1 uart к пк через usb/uart переходник, а второй к...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
4
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2020, vBulletin Solutions, Inc.