Lessberg

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

28.01.2013, 16:52. Показов 22618. Ответов 4
Метки нет (Все метки)

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

За основу решил брать уже готовый проект. Их множество. Мой выбор пал вот на этот:
Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
----------------------------------------------------------------------------------
-- 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". В общем не могу понять как с компа верно посылать данные..

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
                    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 минуты
в принципе с проблемой разобрался. Позже выложу проект готовый, может комуто пригодится в учебных целях.
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
28.01.2013, 16:52
Ответы с готовыми решениями:

[VHDL/Verilog] Измеритель температуры
Здравствуйте, появилась задача написать код на VHDL или verilog для измерителя темпратуры, где интерфейс вывода и ввода информации будет...

[VHDL] Мигание светодиодов
Устройство моргания 4-мя светодиодами.По сути,программа очень простая.Но у меня в итоге светодиоды &quot;бегают&quot; (т.е. загорелся...

Модуль UART на ПЛИС
Здравствуйте, уважаемые форумчане. Пробую написать UART на VHDL, с которым раньше не работал. Ради учебных целей, решил не брать...

4
 Аватар для raxper
10234 / 6612 / 498
Регистрация: 28.12.2010
Сообщений: 21,154
Записей в блоге: 1
02.06.2013, 15:15
opencores.org:
- UART 16550 core
- UART to Bus
- Serial Uart
Вложения
Тип файла: zip miniuart2.zip (2.96 Мб, 340 просмотров)
Тип файла: zip uart2bus.zip (259.6 Кб, 303 просмотров)
Тип файла: zip uart16550.zip (1.73 Мб, 306 просмотров)
0
 Аватар для Papayaved
75 / 75 / 8
Регистрация: 24.09.2015
Сообщений: 342
25.09.2015, 12:03
UART надо бы и самому написать, тогда разберешься, как ПЛИС работает.

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

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

При работе с железом надо соблюдать некоторую осторожность при подключение COM кабеля. Включать питание на плате надо после подключения кабеля к компьютеру. Иначе рано или поздно сгорит одна из микросхем драйверов физического уровня либо на плате, либо в компьютере. Еще надо иметь ввиду, что USB-COM адаптеры часто очень капризные и не хотят работать, так что не плохо смотреть иногда сигналы TxD, RxD осцилографом.
0
-13 / 6 / 6
Регистрация: 04.08.2015
Сообщений: 558
02.12.2017, 12:43
По необходимости гуглил тему UART для ПЛИС. Оказалось, что реализаций на VHDL Verilog большое количество вариантов. А на opencores вообще имеется код полного UART https://opencores.org/project,uart16550. Остановился на http://acvarif.info/prvhdl/com... ml#prvhdl7, где есть тест с COM port Tool Kit на скорости 115200.
0
6 / 5 / 2
Регистрация: 04.11.2012
Сообщений: 225
15.05.2024, 13:48
О, отличная и очень интересная тема!!!
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
15.05.2024, 13:48
Помогаю со студенческими работами здесь

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

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

[VHDL] Реализация 32-разрядного АЛУ
Помогите пожалуйста разобраться. Передо мною стоит задача - описать на VHDL 32 разрядное АЛУ, с операциями:+,-,*,/ и логикой AND OR XOR...

Реализация на ПЛИС
Здравствуйте Может кто знает как блоками реализуется структурная схема на плис на камеру приходит изображение с точечным объектом -...

Работа через терминал хост-компьютера с ПЛИС через USB-to-UART
Здравствуйте! Мне нужно организовать связь компьютера с платой от фирмы Xilinx ZC702. Решил ничего не выдумывать и использовать терминал...


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

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

Новые блоги и статьи
SwiftUI Data Flow: Передача данных между представлениями
mobDevWorks 24.03.2025
При первом знакомстве со SwiftUI кажется, что фреймворк предлагает избыточное количество механизмов для передачи данных: @State, @Binding, @StateObject, @ObservedObject, @EnvironmentObject и другие. . . .
Моки в Java: Сравниваем Mockito, EasyMock, JMockit
Javaican 24.03.2025
Как протестировать класс, который зависит от других сложных компонентов, таких как базы данных, веб-сервисы или другие классы, с которыми и так непросто работать в тестовом окружении? Для этого и. . .
Архитектурные паттерны микросервисов: ТОП-10 шаблонов
ArchitectMsa 22.03.2025
Популярность микросервисной архитектуры объясняется множеством важных преимуществ. К примеру, она позволяет командам разработчиков работать независимо друг от друга, используя различные технологии и. . .
Оптимизация рендеринга в Unity: Сортировка миллиона спрайтов
GameUnited 22.03.2025
Помните, когда наличие сотни спрайтов в игре приводило к существенному падению производительности? Время таких ограничений уходит в прошлое. Сегодня геймдев сталкивается с задачами совершенно иного. . .
Образование и практика
Igor3D 22.03.2025
Добрый день А вот каково качество/ эффективность ВУЗовского образования? Аналитическая геометрия изучается в первом семестре и считается довольно легким курсом, что вполне справедливо. Ну хорошо,. . .
Lazarus. Таблица с объединением ячеек.
Massaraksh7 21.03.2025
Понадобилась представление на экране таблицы с объединёнными ячейками. И не одной, а штук триста, и все разные. На Delphi я использовал для этих целей TStringGrid, и то, кривовато получалось. А в. . .
Async/await в Swift: Асинхронное программировани­е в iOS
mobDevWorks 21.03.2025
Асинхронное программирование долго было одной из самых сложных задач для разработчиков iOS. В течение многих лет мы сражались с замыканиями, диспетчеризацией очередей и обратными вызовами, чтобы. . .
Колмогоровская сложность: Приёмы упрощения кода
ArchitectMsa 21.03.2025
Наверное, каждый программист хотя бы раз сталкивался с кодом, который напоминает запутанный лабиринт — чем дальше в него погружаешься, тем сложнее найти выход. И когда мы говорим о сложности кода, мы. . .
PostgreSQL в Kubernetes: Подготовка кластера и настройка
Mr. Docker 21.03.2025
Когда доходит до контейнеризации баз данных и особенно таких требовательных к ресурсам системах как PostgreSQL, многие команды до сих пор колеблются, прежде чем перенести их в контейнерную. . .
C++26: Индексирование пакетов и метапрограммиро­вание
bytestream 21.03.2025
Эволюция C++ продолжается стремительными темпами – каждый новый стандарт приносит функциональность, о которой мы мечтали годами. Звучит слишком громко? Если вы когда-либо боролись с вариадическими. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru