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

Реализация Uart На Плис


Lessberg

Рекомендуемые сообщения

Добрый день!

Извиняюсь, начну сразу с вопроса: Как можно код в спойлер убрать ?

Мне была поставлена задача реализовать UART приемопередатчик через com port RS-232 для обмена данными между ПЛИС и ПК.

ПЛИС -> Altera DE2 Board Cyclone II EP2C 35F 672C6 (Вложен файл для визуального понимания работы проекта)

ПК -----> Com Port Toolkit 4.0

Проект делаю в стандартной программе Алтеры: Quartus II v 12.1

post-167913-0-43936200-1359640199_thumb.jpg

Необходимо передать число от 0 до FF из ПК на ПЛИС и так же задав входные данных на ПЛИС передать на ПК.

Я взял готовый проект:

----------------------------------------------------
-- UART RS232
-- Ver. 1.0 - 10.07.2003
---------------------------------------------------
library ieee;
use IEEE.STD_LOGIC_1164.all;
USE IEEE.numeric_std.all;
entity UART is
generic (UART_Speed : integer := 115200 ; -- UART Speed
	 System_CLK : integer := 50000000 -- System CLK in Hz
 );
port (
 CLK	 : in std_logic;	 -- system clk
 RST_N : in std_logic;	 -- system reset#
 DATA_IN : in std_logic_vector(7 downto 0); -- Transmit data
 DATA_OUT : out std_logic_vector(7 downto 0); --Recieved data
 RX_VALID : out std_logic; -- RX buffer data ready
 TX_VALID : in std_logic;		 -- Data for TX avaible
 RXD	 : in std_logic;		 -- RX pin
 TXD	 : out std_logic ;	 -- TX pin
 TX_BUSY : out std_logic; -- TX pin
 RX_BUSY : out std_logic
);
end UART;
---------------------------------------------------
-- Architecture for UART
---------------------------------------------------
architecture rtl of UART is
signal TxBuf : Std_Logic_Vector(7 downto 0); -- transmit buffer
signal RxBuf : Std_Logic_Vector(7 downto 0); -- recieve buffer
signal prevRXD : Std_Logic;		 -- RXD buffer register
signal RxReady : Std_Logic;
signal TXRead : Std_Logic;
signal TxBitCnt : integer range 0 to 9;
signal TxReady : Std_Logic;
signal CntRX : integer range 0 to System_CLK/(UART_Speed);
signal CntTX : integer range 0 to System_CLK/(UART_Speed);
signal RxBitCnt: integer range 0 to 10;
begin
UART_Tx: process(CLK, RST_N)
begin
if RST_N='0' then
TXD <= '1';
TxBitCnt <= 0;
TxBuf <= (others => '0');
CntTX <= 0;
TxReady <= '1';
elsif (rising_edge(CLK)) then
if (TX_VALID = '1' and TxReady = '1') then
 TxBuf(7 downto 0) <= DATA_IN(7 downto 0);
 TxReady <= '0';
 TxBitCnt <= 0;
 CntTX <= 0;
end if;
if (TxReady = '0') then
 if CntTX=(System_CLK/(UART_Speed)) then
 CntTX <= 0;
 case TxBitCnt is
	 when 0 = >
	 TXD <= '0';	 -- start bit
	 TxBitCnt <= TxBitCnt+1;
	 when 1|2|3|4|5|6|7|8 =>
	 TXD	 <= TxBuf(0);
	 TxBuf <= '0' & TxBuf(7 downto 1);
	 TxBitCnt <= TxBitCnt+1;
	 when 9 =>
	 TXD	 <= '1'; -- stop bit
	 TxBuf <= (others => '0');
	 TxBitCnt <= 0;
	 TxReady <= '1';	
 end case;
 else
 CntTX <= CntTX+1;
 end if;
end if;
end if;
end process UART_Tx;
TX_BUSY <= not (TxReady);
UART_Rx: process(CLK, RST_N)
begin
if RST_N='0' then
RxBitCnt <=0;
RxBuf <= (others => '0');
RxReady <= '1';
prevRXD <= '1';
CntRX <= 0;
elsif (rising_edge(CLK)) then
if (RxReady = '1') then
 prevRXD <= RXD;
 if (RXD='0' and prevRXD='1') then -- Start bit,
 RxBitCnt <= 0;			 -- RX Bit counter
 RxReady <= '0'; -- Start receiving
 RxBuf <= (others => '0');
 CntRX <= 0;
 end if;
else
 if CntRX=(System_CLK/(UART_Speed*2)) then
 case RxBitCnt is
	 when 0 =>
	 if (RXD='1') then -- start bit failed
		 RxReady <= '1';
	 end if;
	 when 1|2|3|4|5|6|7|8 =>
	 RxBuf <= RXD & RxBuf(7 downto 1);
	 RxReady <= '0';
	 when 9 =>
	 RxReady <= '1';
	 when others => RxReady <= '0';
 end case;
 CntRX <= CntRX+1;
 RxBitCnt <= RxBitCnt+1;
 elsif (CntRX=(System_CLK/(UART_Speed))) then
 CntRX <= 0;
 else
 CntRX <= CntRX+1;
 end if;
end if;
end if;
end process UART_Rx;
DATA_OUT(7 downto 0) <= RxBuf(7 downto 0) when RxReady='1'
	 else (others => '0');
RX_VALID <= RxReady;
RX_BUSY <= not (RxReady);
end rtl;

Доработав его под свои нужды получил следующие:

1. Вывод принятых данных с ПК на 2 семисегментных индикатора в формате от 00 до FF

2. Так же вывод дублируется на 8 светодиодов, дабы видеть соответствие двоичному коду. (более для удобства в отладке программы чем необходимость)

3. Данные для передачи с ПЛИС на ПК задаю 8 тумблерами. Данные для передачи так же выводятся на семисегментные индикаторы (HEX0 HEX1). По нажатию кнопки КЕЙ 0 данные передаются на ПК.

Вот мой код:

-- UART RS232
-- Ver. 1.0 - 10.07.2003
---------------------------------------------------
library ieee;
use IEEE.STD_LOGIC_1164.all;
USE IEEE.numeric_std.all;
entity uart is
generic (UART_Speed : integer := 9600 ; -- скорость UART
	 System_CLK : integer := 50000000 -- частота в герцах (Гц)
 );
port (
--============================ ВХОД ==============================
CLK	 : in std_logic;		 -- частота
RST	 : in std_logic;		 -- сброс
DATA_IN : in std_logic_vector (7 downto 0); -- Ввод данных в виде двоичного кода через тумблеры SW[0...7]
TX_VALID : in std_logic;		 -- Data for TX avaible / Данные для передачи доступны
UART_RXD : in std_logic;		 -- RX линия приема
--============================ ВЫХОД =============================
HEX4 : out std_logic_vector(7 downto 0); -- Вывод переданных данных с ПК на семисегментный индикатор
HEX5 : out std_logic_vector(7 downto 0); -- Вывод переданных данных с ПК на семисегментный индикатор
LEDG	 : out std_logic_vector(7 downto 0); -- Вывод данных в виде двоичного кода на светодиоды
RX_VALID : out std_logic;		 -- RX buffer data ready / Буферизация данных приема готова
UART_TXD : out std_logic;		 -- TX линия передачи
 TX_BUSY : out std_logic;		 -- Флаг - линия передачи занята
RX_BUSY : out std_logic;	 -- Флаг - линия приема занята
HEX0 : out std_logic_vector(7 downto 0); -- Вывод передаваемых данных с ПЛИС на семисегментный индикатор
HEX1 : out std_logic_vector(7 downto 0); -- Вывод передаваемых данных с ПЛИС на семисегментный индикатор
--== Выключение незадействованных семисегментных индикаторов =====
HEX2 : out std_logic_vector(6 downto 0);
HEX3 : out std_logic_vector(6 downto 0);
HEX6 : out std_logic_vector(6 downto 0);
HEX7 : out std_logic_vector(6 downto 0)
);
end uart;
--========= Архитектура для UART ===========
architecture rtl of UART is

signal DATA_OUT : std_logic_vector(7 downto 0); --Вспомогательный сигнал вывода данных
signal TxBuf : Std_Logic_Vector(7 downto 0); -- буфер передатчик
signal RxBuf : Std_Logic_Vector(7 downto 0); -- буфер приеманика
signal prevRXD : Std_Logic;		 -- RXD buffer register / Буферный регистрт линии приема
signal RxReady : Std_Logic;
signal TXRead : Std_Logic;
signal TxBitCnt : integer range 0 to 9;
signal TxReady : Std_Logic;
signal CntRX : integer range 0 to System_CLK/(UART_Speed); -- счет принятых битов
signal CntTX : integer range 0 to System_CLK/(UART_Speed); -- счет отправленных битов
signal RxBitCnt : integer range 0 to 10;
begin
HEX2 <= "1111111";
HEX3 <= "1111111";
HEX6 <= "1111111";
HEX7 <= "1111111";
-- Вывод передаваемых данных с ПЛИС на семисегментные индикаторы
UART_HEX:process(DATA_IN)
begin
case DATA_IN (3 downto 0) is
when "0000" => HEX0 <= "11000000"; --"0"
when "0001" => HEX0 <= "11111001"; --"1"
when "0010" => HEX0 <= "10100100"; --"2"
when "0011" => HEX0 <= "10110000"; --"3"
when "0100" => HEX0 <= "10011001"; --"4"
when "0101" => HEX0 <= "10010010"; --"5"
when "0110" => HEX0 <= "10000010"; --"6"
when "0111" => HEX0 <= "11111000"; --"7"
when "1000" => HEX0 <= "10000000"; --"8"
when "1001" => HEX0 <= "10010000"; --"9"
when "1010" => HEX0 <= "10001000"; --"A"
when "1011" => HEX0 <= "10000011"; --"b"
when "1100" => HEX0 <= "11000110"; --"C"
when "1101" => HEX0 <= "10100001"; --"d"
when "1110" => HEX0 <= "10000110"; --"E"
when "1111" => HEX0 <= "10001110"; --"F"
when others => HEX0 <= "11111111";
end case;
case DATA_IN (7 downto 4) is
when "0000" => HEX1 <= "11000000"; --"0"
when "0001" => HEX1 <= "11111001"; --"1"
when "0010" => HEX1 <= "10100100"; --"2"
when "0011" => HEX1 <= "10110000"; --"3"
when "0100" => HEX1 <= "10011001"; --"4"
when "0101" => HEX1 <= "10010010"; --"5"
when "0110" => HEX1 <= "10000010"; --"6"
when "0111" => HEX1 <= "11111000"; --"7"
when "1000" => HEX1 <= "10000000"; --"8"
when "1001" => HEX1 <= "10010000"; --"9"
when "1010" => HEX1 <= "10001000"; --"A"
when "1011" => HEX1 <= "10000011"; --"b"
when "1100" => HEX1 <= "11000110"; --"C"
when "1101" => HEX1 <= "10100001"; --"d"
when "1110" => HEX1 <= "10000110"; --"E"
when "1111" => HEX1 <= "10001110"; --"F"
when others => HEX1 <= "11111111";
end case;
end process;
--========= Передатчик =========
UART_Tx: process(CLK, RST)
begin
if RST='0' then
UART_TXD <= '1';
TxBitCnt <= 0;
TxBuf <= (others => '0');
CntTX <= 0;
TxReady <= '1';
elsif (rising_edge(CLK)) then
if (TX_VALID = '0' and TxReady = '1') then
 TxBuf(7 downto 0) <= DATA_IN (7 downto 0);
 TxReady <= '0';
 TxBitCnt <= 0;
 CntTX <= 0;
end if;
if (TxReady = '0') then
 if CntTX=(System_CLK/(UART_Speed)) then
 CntTX <= 0;
 case TxBitCnt is
	 when 0 =>
	 UART_TXD <= '0';	 -- старт бит
	 TxBitCnt <= TxBitCnt+1;
	 when 1|2|3|4|5|6|7|8 =>
	 UART_TXD	 <= TxBuf(0);
	 TxBuf <= '0' & TxBuf(7 downto 1);
	 TxBitCnt <= TxBitCnt+1;
	 when 9 =>
	 UART_TXD	 <= '1'; -- стоп бит
	 TxBuf <= (others => '0');
	 TxBitCnt <= 0;
	 TxReady <= '1';	
 end case;
 else
 CntTX <= CntTX+1;
 end if;
end if;
end if;
end process UART_Tx;
TX_BUSY <= not (TxReady);
--=========== Приемник =============
UART_Rx: process(CLK, RST)
begin
if RST='0' then
HEX4 <= "11111111";
HEX5 <= "11111111";
RxBitCnt <=0;
RxBuf <= (others => '0');
RxReady <= '1';
prevRXD <= '1';
CntRX <= 0;
elsif (rising_edge(CLK)) then
if (RxReady = '1') then -- Если на момент фронта сигнала CLK RxReady = 1 тогда
 prevRXD <= UART_RXD; -- после прохождения фронта CLK prevRXD будет равно RXD
 if (UART_RXD='0' and prevRXD='1') then -- Старт бит /если на момент фронта CLK RXD='0' и prevRXD='1' мы словили старт бит
 RxBitCnt <= 0;				 -- Счетчик битов приема
 RxReady <= '0';		 -- Начало приема
 RxBuf <= (others => '0');
 CntRX <= 0;
 end if;
else
 if CntRX=(System_CLK/(UART_Speed*2)) then
 case RxBitCnt is
	 when 0 =>
	 if (UART_RXD='1') then -- Условие необнаружения стартового бита
		 RxReady <= '1';
	 end if;
	 when 1|2|3|4|5|6|7|8 =>
	 RxBuf <= UART_RXD & RxBuf(7 downto 1);
	 RxReady <= '0';
	 when 9 =>
	 RxReady <= '1';
	 when others => RxReady <= '0';
 end case;

 case RxBuf (3 downto 0) is
when "0000" => HEX4 <= "11000000"; --"0"
when "0001" => HEX4 <= "11111001"; --"1"
when "0010" => HEX4 <= "10100100"; --"2"
when "0011" => HEX4 <= "10110000"; --"3"
when "0100" => HEX4 <= "10011001"; --"4"
when "0101" => HEX4 <= "10010010"; --"5"
when "0110" => HEX4 <= "10000010"; --"6"
when "0111" => HEX4 <= "11111000"; --"7"
when "1000" => HEX4 <= "10000000"; --"8"
when "1001" => HEX4 <= "10010000"; --"9"
when "1010" => HEX4 <= "10001000"; --"A"
when "1011" => HEX4 <= "10000011"; --"b"
when "1100" => HEX4 <= "11000110"; --"C"
when "1101" => HEX4 <= "10100001"; --"d"
when "1110" => HEX4 <= "10000110"; --"E"
when "1111" => HEX4 <= "10001110"; --"F"
when others => HEX4 <= "11111111";
end case;

case RxBuf (7 downto 4) is
when "0000" => HEX5 <= "11000000"; --"0"
when "0001" => HEX5 <= "11111001"; --"1"
when "0010" => HEX5 <= "10100100"; --"2"
when "0011" => HEX5 <= "10110000"; --"3"
when "0100" => HEX5 <= "10011001"; --"4"
when "0101" => HEX5 <= "10010010"; --"5"
when "0110" => HEX5 <= "10000010"; --"6"
when "0111" => HEX5 <= "11111000"; --"7"
when "1000" => HEX5 <= "10000000"; --"8"
when "1001" => HEX5 <= "10010000"; --"9"
when "1010" => HEX5 <= "10001000"; --"A"
when "1011" => HEX5 <= "10000011"; --"b"
when "1100" => HEX5 <= "11000110"; --"C"
when "1101" => HEX5 <= "10100001"; --"d"
when "1110" => HEX5 <= "10000110"; --"E"
when "1111" => HEX5 <= "10001110"; --"F"
when others => HEX5 <= "11111111";
end case;

 CntRX <= CntRX+1;
 RxBitCnt <= RxBitCnt+1;
 elsif (CntRX=(System_CLK/(UART_Speed))) then
 CntRX <= 0;
 else
 CntRX <= CntRX+1;
 end if;
end if;
end if;
end process UART_Rx;
DATA_OUT(7 downto 0) <= RxBuf(7 downto 0) when RxReady='1'
	 else (others => '0');
LEDG <= DATA_OUT;

RX_VALID <= RxReady;
RX_BUSY <= not (RxReady);
end rtl;

Что хотелось бы еще реализовать, но не получается в связи с недолгим изучением VHDL.

1. Самая важная ошибка, точнее недороботка заключается в том что с ПЛИС на ПК передается не 1 БАЙТ (8 бит) а целая пачка. Зависит конечно от времени нажатия на кнопку КЕЙ0 (передать данные). Стандартная скорость в проекте была 115200. Я пробовал уменьшить и минимальная скорость при которой проект работает верно это 300-600 БОД.

К примеру при скорости 115200 передается примерно 100 Байт информации. При 300 БОД 9-10 байт. Если уж сильно постарать быстро нажать и отпустить кнопку передачи у меня выходило 4 байта )))

Пробовал ставить задержку из ряда Триггеров.. не особо помогло.

Бьюсь уже не первый день не могу додуматься как в код внести условие чтобы передавал 8 Бит то есть 1 раз ,, данные которые введены на ПЛИС (тумблерами)по нажатию кнопки передачи.

​2. Вторая проблема она не так существенна, но хотелось бы что в проекте присутствовал бит четности.

Логика работы его понятна, сложить все 8 бито по модулю 2 (xor). Далее сумму 8 бит сложить по модулю 2 с битом четности (пусть будет 1 (проверка на четность)) и уже результат их добавить как 9-ый бит к фрейму. Или как 0 - ой ?

ЗЫ. Постарался разжевать смысл проекта. Надеюсь на Вашу помощь и буду рад любым замечаниям и комментариям.

post-167913-0-43936200-1359640199_thumb.jpg

Изменено пользователем Lessberg
Ссылка на комментарий
Поделиться на другие сайты

Реклама: ООО ТД Промэлектроника, ИНН: 6659197470, Тел: 8 (800) 1000-321

По п.1. Сделайте счетчик с периодом переполнения 0,1 с. Далее по его переполнению заносите в сдвиговый регистр состояние кнопки. Реистр достаточно иметь на 3-4 разряда. Далее выделяете по своему усмотрению передний или задний фронт от нажатия и запускаете передачу. Делаю таким образом:

variable shift:std_logic_vector(2 downto 0);

variable flag:std_logic;

.........

begin

if(rising_edge(clk))then

shift(2 downto 1):=shift(1 downto 0);--Сдвиг состояния кнопки

shift(0):=key;

if(shift="001")then

flag:='1';--Разрешаем работу передатчика

end if;

end if;

По п.2 бит четности надо добавлять после передачи информационных битов, т.е. сначала старт-бит, затем Х0, Х1,...Х7, бит-четности, 1 или 2 стоп-бита.

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

20% скидка на весь каталог электронных компонентов в ТМ Электроникс!

Акция "Лето ближе - цены ниже", успей сделать выгодные покупки!

Плюс весь апрель действует скидка 10% по промокоду APREL24 + 15% кэшбэк и бесплатная доставка!

Перейти на страницу акции

Реклама: ООО ТМ ЭЛЕКТРОНИКС, ИНН: 7806548420, info@tmelectronics.ru, +7(812)4094849

Организация питания на основе надежных литиевых аккумуляторов EVE и микросхем азиатского производства

Качественное и безопасное устройство, работающее от аккумулятора, должно учитывать его физические и химические свойства, профили заряда и разряда, их изменение во времени и под влиянием различных условий, таких как температура и ток нагрузки. Мы расскажем о литий-ионных аккумуляторных батареях EVE и нескольких решениях от различных китайских компаний, рекомендуемых для разработок приложений с использованием этих АКБ. Представленные в статье китайские аналоги помогут заменить продукцию западных брендов с оптимизацией цены без потери качества. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

В догонку, признак Флаг, необходимо обнулять по окончанию передачи (байта или строки, в зависимости от задачи). Так же можно принудительно его ставить в нуль по второму (незадействованному) фронту - для надежности

Изменено пользователем Meteor77
Ссылка на комментарий
Поделиться на другие сайты

Сравнительное тестирование аккумуляторов EVE Energy и Samsung типоразмера 18650

Инженеры КОМПЭЛ провели сравнительное тестирование аккумуляторов EVE и Samsung популярного для бытовых и индустриальных применений типоразмера 18650. 

Для теста были выбраны аккумуляторы литий-никельмарганцевой системы: по два образца одного наименования каждого производителя – и протестированы на двух значениях тока разряда: 0,5 А и 2,5 А. Испытания проводились в нормальных условиях на электронной нагрузке EBD-USB от ZKEtech, а зарядка осуществлялась от лабораторного источника питания в режиме CC+CV в соответствии с рекомендациями в даташите на определенную модель. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

пока чтото не получается....

Вот компонент передатчик. При компиляции выдает ошибки...

UART_Tx: process(CLK, RST)
variable shift:std_logic_vector(2 downto 0);
variable flag:std_logic;
begin
if RST='0' then
UART_TXD <= '1';
TxBitCnt <= 0;
TxBuf <= (others => '0');
CntTX <= 0;
TxReady <= '1';
elsif (rising_edge(CLK)) then
 shift(2 downto 1):=shift(1 downto 0);--Сдвиг состояния кнопки
shift(0):=TX_VALID;
elsif (shift="001")then
flag:='1';--Разрешаем работу передатчика
if (TX_VALID = '0' and TxReady = '1' and flag = '1') then
TxBuf(7 downto 0) <= DATA_IN (7 downto 0);
TxReady <= '0';
TxBitCnt <= 0;
CntTX <= 0;
end if;
if (TxReady = '0') then
 if CntTX=(System_CLK/(UART_Speed)) then
 CntTX <= 0;
 case TxBitCnt is
	 when 0 =>
	 UART_TXD <= '0';	 -- старт бит
	 TxBitCnt <= TxBitCnt+1;
	 when 1|2|3|4|5|6|7|8 =>
	 UART_TXD	 <= TxBuf(0);
	 TxBuf <= '0' & TxBuf(7 downto 1);
	 TxBitCnt <= TxBitCnt+1;
	 when 9 =>
	 UART_TXD	 <= '1'; -- стоп бит
	 TxBuf <= (others => '0');
	 TxBitCnt <= 0;
	 TxReady <= '1';	
flag := '0';
 end case;
 else
 CntTX <= CntTX+1;
 end if;
end if;
end if;
end process UART_Tx;

Лог ошибок

Error (10818): Can't infer register for "TxReady" at uart.vhd(125) because it does not hold its value outside the clock edge

Error (10818): Can't infer register for "CntTX[0]" at uart.vhd(125) because it does not hold its value outside the clock edge

Error (10818): Can't infer register for "CntTX[1]" at uart.vhd(125) because it does not hold its value outside the clock edge

Error (10818): Can't infer register for "CntTX[2]" at uart.vhd(125) because it does not hold its value outside the clock edge

Error (10818): Can't infer register for "CntTX[3]" at uart.vhd(125) because it does not hold its value outside the clock edge

Error (10818): Can't infer register for "CntTX[4]" at uart.vhd(125) because it does not hold its value outside the clock edge

Error (10818): Can't infer register for "CntTX[5]" at uart.vhd(125) because it does not hold its value outside the clock edge

Error (10818): Can't infer register for "CntTX[6]" at uart.vhd(125) because it does not hold its value outside the clock edge

Error (10818): Can't infer register for "CntTX[7]" at uart.vhd(125) because it does not hold its value outside the clock edge

Error (10818): Can't infer register for "CntTX[8]" at uart.vhd(125) because it does not hold its value outside the clock edge

Error (10818): Can't infer register for "CntTX[9]" at uart.vhd(125) because it does not hold its value outside the clock edge

Error (10818): Can't infer register for "CntTX[10]" at uart.vhd(125) because it does not hold its value outside the clock edge

Error (10818): Can't infer register for "CntTX[11]" at uart.vhd(125) because it does not hold its value outside the clock edge

Error (10818): Can't infer register for "CntTX[12]" at uart.vhd(125) because it does not hold its value outside the clock edge

Error (10818): Can't infer register for "TxBuf[0]" at uart.vhd(125) because it does not hold its value outside the clock edge

Error (10818): Can't infer register for "TxBuf[1]" at uart.vhd(125) because it does not hold its value outside the clock edge

Error (10818): Can't infer register for "TxBuf[2]" at uart.vhd(125) because it does not hold its value outside the clock edge

Error (10818): Can't infer register for "TxBuf[3]" at uart.vhd(125) because it does not hold its value outside the clock edge

Error (10818): Can't infer register for "TxBuf[4]" at uart.vhd(125) because it does not hold its value outside the clock edge

Error (12153): Can't elaborate top-level user hierarchy

Error: Quartus II 64-Bit Analysis & Synthesis was unsuccessful. 20 errors, 12 warnings

Error: Peak virtual memory: 490 megabytes

Error: Processing ended: Thu Jan 31 23:04:05 2013

Error: Elapsed time: 00:00:01

Error: Total CPU time (on all processors): 00:00:01

Error (293001): Quartus II Full Compilation was unsuccessful. 22 errors, 12 warnings

Займусь пока проверкой четности, тут мне хоть понятно как должно работать.

А вот с задержкой хоть и выложили пример готовый, но все равно тяжеловато понять :(

Изменено пользователем Lessberg
Ссылка на комментарий
Поделиться на другие сайты

Литиевые аккумуляторы EVE Energy и решения для управления перезаряжаемыми источниками тока (материалы вебинара)

Опубликованы материалы вебинара Компэл, посвященного литиевым аккумуляторам EVE Energy и решениям для управления перезаряжаемыми источниками тока.

На вебинаре мы представили информацию не только по линейкам аккумуляторной продукции EVE, но и по решениям для управления ею, что поможет рассмотреть эти ХИТ в качестве дополнительной альтернативы для уже выпускающихся изделий. Также рассмотрели нюансы работы с производителем и сервисы, предоставляемые Компэл по данной продукции. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

Опять блок передатчика разбираю...

Выкинул пока мысль о задержках, Добавил бит четности "1". Все работает. Но вот в чем проблема:

Добавил сигнал выхода "error" сигнализировал об ошибке при передачи данных, если такова была, но светодиод всегда горит, тем самым говоря что данные всегда передаются с ошибкой.. хотя это не правда :(



UART_Tx: process(CLK)
begin
 if RST='0' then
   UART_TXD <= '1';
   TxBitCnt <= 0;
   TxBuf <= (others => '0');
   CntTX <= 0;
   TxReady <= '1';
 elsif (rising_edge(CLK)) then
   if (TX_VALID = '0' and TxReady = '1') then
     TxBuf(7 downto 0) <= DATA_IN (7 downto 0);
     TxReady <= '0';
     TxBitCnt <= 0;
     CntTX  <= 0;
   end if;

   if (TxReady = '0') then
     if CntTX=(System_CLK/(UART_Speed)) then
       CntTX <= 0;
       case TxBitCnt is
         when 0 =>
           UART_TXD  <=  '0';       -- старт бит
           TxBitCnt <= TxBitCnt+1;
         when 1|2|3|4|5|6|7|8 =>
           UART_TXD      <= TxBuf(0);
           TxBuf    <= '0' & TxBuf(7 downto 1);
           TxBitCnt <= TxBitCnt+1;
         when 9 =>                  -- бит четности "1"
            a <= TxBuf (7 downto 0);
            b <= a(0) xor a(1) xor a(2) xor a(3) xor a(4) xor a(5) xor a(6) xor a(7);
            c <= parity xor b; -- parity константа равная "1"
            if c = parity then
                TxBuf <= '1' & TxBuf (7 downto 1);
                TxBitCnt <= TxBitCnt+1;
            else 
                error <= '1';
                TxBitCnt <= TxBitCnt+1;
            end if;
         when 10 =>
           UART_TXD      <= '1';    -- стоп бит
           TxBuf    <= (others => '0');
           TxBitCnt <= 0;
           TxReady  <= '1';        
       end case;
     else
       CntTX <= CntTX+1;
     end if;
   end if;
 end if;
end process UART_Tx;

Изменено пользователем Lessberg
Ссылка на комментарий
Поделиться на другие сайты

Литиевые батарейки и аккумуляторы от мирового лидера  EVE в Компэл

Компания Компэл, официальный дистрибьютор EVE Energy, бренда №1 по производству химических источников тока (ХИТ) в мире, предлагает продукцию EVE как со склада, так и под заказ. Компания EVE широко известна в странах Европы, Америки и Юго-Восточной Азии уже более 20 лет. Недавно EVE была объявлена поставщиком новых аккумуляторных элементов круглого формата для электрических моделей «нового класса» компании BMW.

Продукция EVE предназначена для самого широкого спектра применений – от бытового до промышленного. Подробнее>>

Реклама: АО КОМПЭЛ, ИНН: 7713005406, ОГРН: 1027700032161

хм.. ну прям чудеса творятся... Дорабатывал проверку на бит четности, и тут взял и стал передавать на ПК по 1 Байту ))).. сейчас еще проверю

Почему так, не понимаю. Но меня это больше чем устраивает )))

Вот часть кода, где описывал бит четности. При такой записи бит четности работает (правда без оповещения об ошибке) и данные на ПК по 1 Байту передаются.

Но все равно есть загвоздка... ЧТобы пердать следующий байт с другой информацией, требуется нажать кнопку сброса, и только потом кнопку передачи данных... Иначе не передаются данные. А т.к. сброс общий, то и пришедшие с ПК данные сбрасываются. Надо тоже доработать.

   when 9 =>				  -- бит четности "1"
   a <= TxBuf (7 downto 0);
   b <= a(0) xor a(1) xor a(2) xor a(3) xor a(4) xor a(5) xor a(6) xor a(7);
   c <= parity xor b; -- parity константа равная "1"
   if c = parity then
 TxBuf <= TxBuf (6 downto 0) & '1';
   end if;

Изменено пользователем Lessberg
Ссылка на комментарий
Поделиться на другие сайты

Ох..

Стараюсь делать так:

Процесс передатчика

Процесс приемника

Процесс формирователя синхросигналов (в том числе таймеров для антидребезга)

Все пересылки - через сигналы

Ну например для частоты 50 МГц

Architecture /////////
signal ovf_s:std_logic;
begin
timeout:process(clk)
variable cnt:unsigned(22 downto 0);
variable ovf:std_logic:='0';
constant zero:unsigned(22 downto 0):="00000000000000000000000";
constant step:unsigned(22 downto 0):="00000000000000000000001";
constant max:unsigned(22 downto 0):="10011000100101001000000";
begin
if(rising_edge(clk))then
cnt:=cnt+step;
if(cnt=max-3)then
 ovf:='1';
elsif(cnt=max)then
 ovf:='0';
 cnt:=zero;
end if;
ovf_s<=ovf;
end if;
end process;

key:process(ovf_s)
variable shift:std_logic_vector(2 downto 0);
begin
if(rising_edge(ovf_s))then
 shift(2 downto 0):=shift(1 downto 0);
 shift(0):=key;
 if(shift="001")then
 flag:='1';
 end if;
 flag_s<=flag;
end if;
end process;

UART:process(clk)
if(rising_edge(clk))then
begin
if(flag_s)then
тут надо поместить описание передачи
 end if;
end if;
end process;

Изменено пользователем Meteor77
Ссылка на комментарий
Поделиться на другие сайты

не помогает :( Точно так же пачкой передает

signal ovf_s:std_logic;
signal flag_s:std_logic;
.........
timeout:process(clk)
variable cnt: std_LOGIC_vector(22 downto 0);
variable ovf:std_logic:='0';
constant zero: std_LOGIC_vector(22 downto 0):="00000000000000000000000";
constant step: std_LOGIC_vector(22 downto 0):="00000000000000000000001";
constant max: std_LOGIC_vector(22 downto 0):="10011000100101001000000";
begin
if(rising_edge(clk))then
cnt:=cnt+step;
 if(cnt=max-3)then
	 ovf:='1';
 elsif(cnt=max)then
	 ovf:='0';
	 cnt:=zero;
 end if;
ovf_s<=ovf;
end if;
end process;
Key:process(ovf_s)
variable shift:std_logic_vector(2 downto 0);
variable flag : std_Logic;
begin
if(rising_edge(ovf_s))then
	 shift(2 downto 1):=shift(1 downto 0);
	 shift(0):=TX_INT;
	 if(shift="001")then
	 flag:='1';
	 end if;
	 flag_s<=flag;
end if;
end process;
UART_Tx: process(CLK, RST_N, TxClk, TxBufEmpty, TX_INT, TXRead)
variable TxBitCnt: integer range 0 to 9;
begin
 if RST_N='0' then
	 TxD<='1';
	 TxBitCnt:=0;
	 TxBuf<=(others=>'0');
	 TxBufEmpty<='1';
	 TXRead<='0';
 else
	 if (rising_edge(clk) ) then
if(flag_s = '1')then
	 if TXRead='1' then
		 TXRead<='0';
	 end if;
	 if (TxBufEmpty='1' and TX_INT='0') then -- ***
		 TXRead<='1';
		 TxBuf(7 downto 0)<=SW(7 downto 0);
		 TxBufEmpty<='0';
	 end if;
	 if (TxClk='1' and TxBufEmpty='0') then
			 case TxBitCnt is
			 when 0 =>
				 TxD<='0'; -- start bit
				 TxBitCnt:=TxBitCnt+1;
			 when 1|2|3|4|5|6|7|8 =>
				 TxD<= TxBuf(0);	
				 TxBuf<='1' & TxBuf(7 downto 1);
				 TxBitCnt:=TxBitCnt+1;
			 when 9 =>
				 TxD<='1'; -- stop bit
				 TxBuf<='1' & TxBuf(7 downto 1);
				 TxBitCnt:=0;
				 TxBufEmpty<='1';
		 end case;
	 end if;
	 end if;
 end if;
end if;
end process UART_Tx;

Изменено пользователем Lessberg
Ссылка на комментарий
Поделиться на другие сайты

Еще предложили приделать разрешающий сигнал для сдвигового регистра.

Вот схема (то что ниже схемы. это просто заметки не относящиеся к этой схеме)

643fcf1d2040t.jpg

Вот моя реализация схемы, для простоты расписал пока отдельными компонентами



-- Сигнали управления кнопкой передачи
signal reset, q1,q2, Q : std_Logic; -- сигналы первого Т триггера
signal en : std_Logic; -- сигналы счетчика
signal enable : std_Logic;
signal count : integer;
.........

Trigger1:process(TxClk,reset,Tx_INT)
begin
if (reset = '1') then
 q1 <= '1';
 elsif (TxClk'event and TxClk = '1') then
	 q1 <= Tx_INT;
 end if;
end process;

Counter:process(TxClk,reset,Tx_INT)
variable cnt : integer range 0 to 10;
begin
en <= q1;
 if (reset = '1') then
	 cnt:= 0;
 elsif (TxClk'event and TxClk = '1') then
	 if (en = '0') then
 if (cnt = 10) then
 cnt:= 0;
else
		 cnt := cnt + 1;
end if;
else cnt := 0;
	 end if;
 end if;
 count <= cnt ;
end process;


Comparator:process(count)
variable V : integer:= 10;
begin
 if count = V then
	 q2 <= '1';
else
 q2 <= '0';
end if;
Q <= q2;
end process;


Trigger2:process(TxClk,reset)
begin
 if (TxClk'event and TxClk = '1') then
 enable <= not(Q);
end if;
reset <= not(enable);
end process;

Сигнал разрешения "enable" подключаю к сдвиговому регистру

UART_Tx: process(CLK, RST, TxClk, TxBufEmpty, TX_INT, TXReady,enable)
variable TxBitCnt: integer range 0 to 10;
begin
 if RST='0' then
	 TxD<='1';
	 TxBitCnt:=0;
	 TxBuf<=(others=>'0');
	 TxBufEmpty<='1';
	 TXReady<='0';
 else
	 if (CLK'event and CLK='1') then
	 if TXReady='1' then
		 TXReady<='0';
	 end if;
	 if (TxBufEmpty='1' and TX_INT='0' and enable = '0') then
		 TXReady<='1';
		 TxBuf(7 downto 0)<= Data_IN(7 downto 0);
		 TxBufEmpty<='0';
--	 enable <= '1';
	 end if;
	 if (TxClk='1' and TxBufEmpty='0' ) then
			 case TxBitCnt is
			 when 0 =>
				 TxD<='0'; -- Старт бит
				 TxBitCnt:=TxBitCnt+1;
			 when 1|2|3|4|5|6|7|8 =>
				 TxD<= TxBuf(0);	
				 TxBuf<='1' & TxBuf(7 downto 1);
				 TxBitCnt:=TxBitCnt+1;
 when 9 =>
		 a <= TxBuf (7 downto 0);
		 b <= a(0) xor a(1) xor a(2) xor a(3) xor a(4) xor a(5) xor a(6) xor a(7);
		 c <= parity xor b; -- parity константа равная "1"
		 if c = parity then

				 TxBitCnt := TxBitCnt+1;
 error_1 <= '0';
 else
	 TxBuf <= parity & TxBuf (6 downto 0);
	 error_1 <= '1'; -- датчик ошибки четности "1" на передаче
				 end if;
			 when 10 =>
				 TxD<='1'; -- стоп бит
				 TxBuf<='1' & TxBuf(7 downto 1);
				 TxBitCnt:=0;
				 TxBufEmpty<='1';
		 end case;
	 end if;
	 end if;
 end if;
end process UART_Tx;

Но в итоге передает все равно пачку :(

Вариантов уже кучу испробовал.. может кто ткнет носом куда надо ?

Изменено пользователем Lessberg
Ссылка на комментарий
Поделиться на другие сайты

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

Тактовая частота 40 МГц. Отсылается один байт при установке сигнала записи Tx_write в состояние лог 1.

По окончании, выдается сигнал Tx_empty. Данные желательно устанавливать до перехода 1-0 (задний фронт) по линии Tx_write.

Результат работы показан в скане. Частота посылок 115200 б/с. Есть четность, 1 стоп-бит.

library ieee;
use ieee.numeric_std.all;
use ieee.std_logic_1164.all;
Entity UART IS
PORT(
clk40, RxD, Tx_write:in std_logic;
TxD,Rx_empty, Tx_empty, P_error, Rec_error:out std_logic;
RDB: out std_logic_vector(7 downto 0);
TDB:in std_logic_vector(7 downto 0)
);
End UART;
ARCHITECTURE arch OF UART IS

begin
--------------------------------------------------------------
transmite:process(clk40)
variable cnt_dev:unsigned(8 downto 0):="000000000";
variable cnt_bit:unsigned(3 downto 0):="1111";
variable par_t:std_logic;
variable buf_0:std_logic_vector(7 downto 0);
variable buf_1:std_logic_vector(11 downto 0);
variable T_empty:std_logic:='1';
variable TWB:std_logic_vector(3 downto 0):="0000";
constant max:unsigned(8 downto 0):="101011011";
constant step:unsigned(8 downto 0):="000000001";
constant zero:unsigned(8 downto 0):="000000000";
begin
if(rising_edge(clk40))then
TWB(3 downto 1):=TWB(2 downto 0);--Write comand buffer
TWB(0):=Tx_write;
Tx_empty<=T_empty;
if(TWB="1110")then
cnt_dev:="000000000";
cnt_bit:="0000";
elsif(TWB="0001")then
buf_0:=TDB;
buf_1(11 downto 10):="11";
buf_1(0):='0';
elsif(TWB="0011")then
par_t:= buf_0(7) xor buf_0(6) xor buf_0(5) xor buf_0(4) xor buf_0(3) xor buf_0(2) xor buf_0(1) xor buf_0(0);
elsif(TWB="0111")then
buf_1(8 downto 1):=buf_0;
buf_1(9):=par_t;
T_empty:='0';
elsif(TWB="1111")then
if(T_empty='0')then
cnt_dev:=cnt_dev+step;
if(cnt_dev=max)then
 cnt_bit:=cnt_bit+"0001";
 cnt_dev:=zero;
end if;
case cnt_bit IS
 when "0000" => TxD<=buf_1(0);
 when "0001" => TxD<=buf_1(1);
 when "0010" => TxD<=buf_1(2);
 when "0011" => TxD<=buf_1(3);
 when "0100" => TxD<=buf_1(4);
 when "0101" => TxD<=buf_1(5);
 when "0110" => TxD<=buf_1(6);
 when "0111" => TxD<=buf_1(7);
 when "1000" => TxD<=buf_1(8);
 when "1001" => TxD<=buf_1(9);
 when "1010" => TxD<=buf_1(10);
 when others => TxD<='1'; T_empty:='1';cnt_bit:="1111";
end case;
end if;
end if;
end if;
end process;
-----------------------------------------------------------------------------
----------------------------------------------------------------------------
recieve:process(clk40)
variable cnt_dev:unsigned(5 downto 0):="000000";
variable cnt_bit:unsigned(2 downto 0):="000";
variable cnt_sh:unsigned(2 downto 0):="000";
variable cnt_bf:unsigned(3 downto 0):="0000";
variable shift_in:std_logic_vector(7 downto 0):="11111111";
variable shift_dt:std_logic_vector(11 downto 0):="111111111111";
variable takt:std_logic:='0';
variable start:std_logic:='0';
variable det:std_logic_vector(2 downto 0);
variable dbit:std_logic;
variable par:std_logic;
variable buf_out:std_logic_vector(7 downto 0);
constant step_1:unsigned(5 downto 0):="000001";
constant max_dev:unsigned(5 downto 0):="101011";
constant imp_dev:unsigned(5 downto 0):="101010";
begin
if(rising_edge(clk40))then
cnt_dev:=cnt_dev+step_1;
if(cnt_dev=imp_dev)then
takt:='1';
elsif(cnt_dev=max_dev)then
takt:='0';
cnt_dev:="000000";
shift_in(7 downto 1):=shift_in(6 downto 0);
shift_in(0):=RxD;
if((shift_in="11111110")and (start='0'))then
cnt_bit:="000";
cnt_sh:="000";
shift_dt:="111111111111";
Rx_empty<='0';
else
cnt_bit:=cnt_bit+"001";
end if;

if(cnt_bit="111")then
det(0):=shift_in(0);
det(1):=shift_in(4);
det(2):=shift_in(7);
case det IS
 when "000" => dbit:='0';
 when "001" => dbit:='0';
 when "010" => dbit:='0';
 when "100" => dbit:='0';
 when others => dbit:='1';
end case;
end if;
if(cnt_bf="0000")then
if((dbit='0')and(start='0'))then
 start:='1';
 cnt_bf:="0001";
end if;
elsif(cnt_bf="1011")then
START:='0';
cnt_bf:="0000";
buf_out:=shift_dt(10 downto 3);
par:=shift_dt(9) xor shift_dt(8) xor shift_dt(7) xor shift_dt(6) xor shift_dt(5) xor shift_dt(4) xor shift_dt(3) xor shift_dt(2) xor shift_dt(10);-- xor shift_dt(0);
Rec_error<= shift_dt(1)xor shift_dt(0);
cnt_bf:="0000";
Rx_empty<='1';
end if;

end if;
--test1<=start;
--test2<=takt;
if(start='1')then
if(takt='1')then
cnt_sh:=cnt_sh+"001";
if(cnt_sh="111")then
 shift_dt(10 downto 0):=shift_dt(11 downto 1);
 shift_dt(11):=dbit;
 cnt_bf:=cnt_bf+"0001";
end if;
end if;
end if;
P_error<=par;
RDB<=buf_out;
end if;
end process;
----------------------------------------------------------------------------
End arch;

post-95351-0-21855200-1360173940_thumb.jpg

Изменено пользователем Meteor77
Ссылка на комментарий
Поделиться на другие сайты

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

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

Гость
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

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

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

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

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

Загрузка...
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...