0 / 0 / 1
Регистрация: 05.04.2017
Сообщений: 64
1

Модуль UART на ПЛИС

21.06.2021, 15:58. Показов 331. Ответов 1

Здравствуйте, уважаемые форумчане.
Пробую написать UART на VHDL, с которым раньше не работал.
Ради учебных целей, решил не брать готовые реализации, а написать самостоятельно.
По итогу передатчик работает, а вот приемник в симуляторе тоже работает, а на деле нет.
У меня три файла: основной, модуль приемника и модуль передатчика. Скорость, требуемая для обмена - 1 Мбод.
В основном своём модуле я по нажатию кнопки отправляю в первый UART байт данных. С выхода передатчика сигнал поступает на вход приемника. Затем принятый байт я отправляю по другому передатчику UART и смотрю осциллографом что получаю. В итоге ничего не бьется.
Посмотрите пожалуйста на код.
Это основной модуль
Код
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity s_6kv is
    port(
        clk_i    : in std_logic;         -- тактирование
        rst_i    : in std_logic;         -- ресет
        rx_i : in std_logic;             -- вход приемника uart
        tx1_start_i : in std_logic;       -- кнопка запуска передатчика uart

		tx_o     : out std_logic;        -- выход передатчика uart
        tx2_o     : out std_logic;        -- выход передатчика uart
        link_led_o : out std_logic      -- светодиод LINK
    );
end s_6kv;

architecture s_6kv_arch of s_6kv is
    ------ декларация компонента uart_tx ---------
    component uart_tx
        generic(
            FREQ : positive := 16000000; -- frequency. Default 16 MHz
            BAUD : positive := 1000000    -- data transfert speed 1Mbit
        );
        port(
            clk_i      : in std_logic;
            rst_i      : in std_logic;
            tx_start_i : in std_logic;
            data_i     : in unsigned(7 downto 0);
            busy_o     : out std_logic;
            tx_o       : out std_logic
	);
    end component;

    ------ декларация компонента uart_rx ---------
    component uart_rx
        port(
        clk_i : in std_logic;
        rst_i : in std_logic;
        rx_i : in std_logic;
        busy_o : out std_logic;              -- флаг занятости приемника
        receive_cmpl_o : out std_logic;
        rx_o : out unsigned(7 downto 0)
    );
    end component;

    --------- константы ---------

    --------- сигналы --------- 
    signal tx1_start : std_logic;         -- включение передатчика uart
    signal tx_busy : std_logic;          -- флаг занятости передатчика uart
    signal rx_busy : std_logic;          -- флаг занятости приемника uart
    signal tx : std_logic;               -- выход передатчика
    signal tp : std_logic;
    signal link_led_on : std_logic;      -- сигнал включения светодиода LINK
    signal tx_buf : unsigned(7 downto 0);-- буфер передатчика
    signal rx_buf : unsigned(7 downto 0);-- буфер передатчика
    signal receive_cmpl : std_logic;     -- флаг завершения приема

    signal tx2_start : std_logic;         -- включение передатчика uart
    signal tx2_busy : std_logic;          -- флаг занятости передатчика uart
    signal tx2_buf : unsigned(7 downto 0);-- буфер передатчика
    signal tx2 : std_logic;               -- выход передатчика
    
begin
    --------- создание компонента uart_tx_comp -----------
    uart_tx_comp : uart_tx
        port map(
            clk_i      => clk_i,
            rst_i      => rst_i,
            tx_start_i => tx1_start,
            data_i     => tx_buf,
            busy_o     => tx_busy,
            tx_o       => tx
        );

        --------- создание компонента uart_tx2_comp -----------
    uart_tx2_comp : uart_tx
        port map(
            clk_i      => clk_i,
            rst_i      => rst_i,
            tx_start_i => tx2_start,
            data_i     => tx2_buf,
            busy_o     => tx2_busy,
            tx_o       => tx2
        );

    --------- создание компонента uart_rx_comp -----------
    uart_rx_comp : uart_rx
        port map(
            clk_i => clk_i,
            rst_i => rst_i,
            rx_i => rx_i,
            busy_o => rx_busy,
            receive_cmpl_o => receive_cmpl,
            rx_o => rx_buf
        );

    process(rst_i, clk_i, tx1_start_i)
    begin
        if rst_i = '0' then
            tx1_start <= '0';
        elsif rising_edge (clk_i)then
            if tx1_start_i = '0' then
                tx_buf <= "01000001";
                tx1_start <= '1';
            end if;
        end if;
    end process;



    process(clk_i, rst_i, receive_cmpl)
    begin
        if rst_i = '0' then
            tx2_start <= '0';
        elsif rising_edge (clk_i) then
            if receive_cmpl = '1' then
                tx2_buf <= rx_buf;
                tx2_start <= '1';
            else
                tx2_start <= '0';
            end if;
        end if;
    end process;

    ----- выходы ------
    tx_o <= tx;
    tx2_o <= tx2;

end s_6kv_arch;
Это приемник
Код
library ieee;
use ieee.std_logic_1164.all;
use ieee.math_real.all;
use ieee.numeric_std.all;

entity uart_rx is
    port(
        clk_i : in std_logic;
        rst_i : in std_logic;
        rx_i : in std_logic;
        busy_o : out std_logic;              -- флаг занятости приемника
        receive_cmpl_o : out std_logic;      -- флаг завершения приема байта
        rx_o : out unsigned(7 downto 0)
    );
end uart_rx;

architecture uart_rx_arch of uart_rx is
    type t_uart_rx_sm is (
        s_idle,
        s_start,
        s_data,
        s_stop,
        s_out
    );
    signal rx_state     : t_uart_rx_sm;
    signal rx_nextState : t_uart_rx_sm;
    ---- сигналы счетчика передискретизации -----
    signal clk16_start : std_logic;              -- запуск счетчика
    signal clk16_cnt   : unsigned(4 downto 0);   -- сам счетчик
    signal clk16_stop  : std_logic;              -- сигнал окончания счета
    signal clk16_half  : std_logic;              -- счет до половины ширины бита

    ---- сигналы счетчика принятых битов -----
    signal bit_cnt_start : std_logic;
    signal bit_cnt       : unsigned (3 downto 0);
    signal bit_cnt_stop  : std_logic;


    signal uart_buf : unsigned(7 downto 0);       -- принятый байт
    signal rx_temp : std_logic; 
	signal MULT : integer := 16;
    signal err_frame : std_logic;
    signal receive_cmpl : std_logic;              -- флаг завершения приема
    signal led_on : std_logic;
    signal busy : std_logic;

    constant START_BIT    : std_logic := '0';
	constant STOP_BIT     : std_logic := '1'; 
begin
    process(rst_i, clk_i, MULT, clk16_start, bit_cnt_start)
	begin
        if rst_i = '0' then
            clk16_cnt <= (others => '0');
            bit_cnt   <= (others => '0');
        elsif rising_edge (clk_i) then
            if clk16_cnt = 7 then
                clk16_half <= '1';
            else
                clk16_half <= '0';
            end if;
            if clk16_cnt = (MULT - 1) then
                clk16_cnt <= (others => '0');
                clk16_stop <= '1';
            elsif clk16_start = '1' then
                clk16_cnt <= clk16_cnt + 1;
                clk16_stop <= '0';
                bit_cnt_stop <= '0';
            end if;

            if bit_cnt = 8 then
                if clk16_cnt = (MULT - 1)  then
                    bit_cnt <= (others => '0');
                    bit_cnt_stop <= '1';
                end if;
            elsif bit_cnt_start = '1' then
                bit_cnt <= bit_cnt + 1;
                bit_cnt_stop <= '0';
            end if;
        end if;
    end process;

    -------------------------------------
    ---------- конечный автомат ---------
    -------------------------------------

    ---------- регистр -----------
    process (rst_i, clk_i)
    begin
        if rst_i = '0' then
            rx_state <= s_idle;
        elsif rising_edge(clk_i) then
            rx_state <= rx_nextState;
        end if;
    end process;
    ------------------------------

    process (rx_state, rx_i)
    begin
        case rx_state is
            when s_idle =>
                clk16_start <= '0';
                receive_cmpl  <= '0';
                busy          <= '0';
            when s_start =>
                clk16_start <= '1';
                receive_cmpl  <= '0';
                busy          <= '1';
            when s_data =>
                clk16_start <= '1';
                receive_cmpl  <= '0';
                busy          <= '1';
            when s_stop =>
                clk16_start <= '1';
                receive_cmpl  <= '0';
                busy          <= '1';
            when s_out =>
                clk16_start <= '0';
                receive_cmpl  <= '1';
                busy          <= '1';
        end case;
    end process;

    ------------ логика перехода в следующее состояние------------
    process (rx_state, rx_i, clk16_stop, bit_cnt_stop, clk16_half, rx_temp)
    begin
        case rx_state is
            when s_idle =>
                err_frame <= '0';
                uart_buf <= (others => '0');
                if rx_i = '0' then
                    rx_nextState <= s_start;
                else
                    rx_nextState <= s_idle;
                end if;
            when s_start =>
                if clk16_stop = '1' then
                    if rx_temp = START_BIT then
                        err_frame <= '0';
                        rx_nextState <= s_data;
                    else
                        err_frame <= '1';
                        rx_nextState <= s_idle;
                    end if;
                else
                    rx_nextState <= s_start;
                end if;
            when s_data =>
                if clk16_half = '1' then
                    bit_cnt_start <= '1';
                    uart_buf <= rx_temp & uart_buf(7 downto 1);
                else
                    uart_buf <= uart_buf;
                    bit_cnt_start <= '0';
                end if;

                if bit_cnt_stop = '1' then
                    rx_nextState <= s_stop;
                else
                    rx_nextState <= s_data;
                end if;
            when s_stop =>
                if clk16_stop = '1' then
                    if rx_temp = STOP_BIT then
                        err_frame <= '0';
                        rx_nextState <= s_out;
                    else
                        err_frame <= '1';
                        rx_nextState <= s_idle;
                    end if;
                else
                    rx_nextState <= s_stop;
                end if;
            when s_out =>
                --rx_o <= uart_buf;
                rx_nextState <= s_idle;
        end case;
    end process;

    process(clk16_half)
    begin
        if clk16_half = '1' then
            rx_temp <= rx_i;
        else
            rx_temp <= rx_temp;
        end if;
    end process;

    ------- выходы --------
    receive_cmpl_o <= receive_cmpl;
    rx_o <= uart_buf;

end uart_rx_arch;
Это передатчик
Код
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity uart_tx is
	generic(
		FREQ : positive := 16000000; -- frequency. Default 16 MHz
		BAUD : positive := 1000000    -- data transfert speed
	);
	port(
        clk_i      : in std_logic;
        rst_i      : in std_logic;
        tx_start_i : in std_logic;
        data_i     : in unsigned(7 downto 0);
        busy_o     : out std_logic;
		tx_o         : out std_logic
	);
end uart_tx;

architecture uart_tx_arch of uart_tx is
	------ декларация компонента uart_tx_fsm ---------
	component uart_tx_fsm
		port(
			clk_i          : in std_logic;
			rst_i          : in std_logic;
			tx_en_i        : in std_logic;
			cnt_stop_i     : in std_logic;
			bit_cnt_stop_i : in std_logic;
			tx_ready_o     : out std_logic;
			cnt_en_o       : out std_logic;
			bit_cnt_en_o   : out std_logic;
			ld_en_o        : out std_logic
		);
	end component;

	--------- константы ---------
	constant START_BIT    : std_logic := '0';
	constant STOP_BIT     : std_logic := '1';
	constant cnt_len      : natural := FREQ/BAUD;			-- 16000000 / 1000000 = 16
	constant bit_cnt_len  : natural := 10;
	
	----- сигналы управления и состояния автомата -------
	signal tx_en    : std_logic;           					-- включение передатчика
	signal tx_ready : std_logic;           					-- флаг состояния передатчика
	signal ld_en    : std_logic;           					-- загрузка данных в регистр сдвига

	----- входные и выходные сигналы -------
	signal tx       : std_logic;                    		-- выходной сигнал
    signal tx_reg   : unsigned (9 downto 0); 				-- регистр данных для отправки
	
	------ сигналы для счётчиков ----------
	signal cnt           : unsigned (8 downto 0);
	signal cnt_en        : std_logic;
	
    signal bit_cnt       : unsigned (3 downto 0);
    signal bit_cnt_en    : std_logic;
    signal cnt_stop      : std_logic;
	signal bit_cnt_stop  : std_logic;

begin
	--------- создание компонента uart_tx_fsm_comp -----------
	uart_tx_fsm_comp : uart_tx_fsm
		port map(
			clk_i          => clk_i,
			rst_i          => rst_i,
			tx_en_i        => tx_en,
			ld_en_o        => ld_en,
			cnt_stop_i     => cnt_stop,
			bit_cnt_stop_i => bit_cnt_stop,
			tx_ready_o     => busy_o,
			cnt_en_o       => cnt_en,
			bit_cnt_en_o   => bit_cnt_en
		);
	-----------------------------------------------------------

    process(rst_i, clk_i, tx_start_i)
	begin
        if rst_i = '0' then
            tx_en <= '0';
        elsif rising_edge (clk_i) then
            if tx_start_i = '1' then
                tx_en <= '1';
            else
                tx_en <= '0';
            end if;
        end if;
    end process;

	process (rst_i, clk_i)
    begin
        if rst_i = '0' then
            tx <= STOP_BIT;
        elsif rising_edge (clk_i) then
            tx <= tx_reg(0);
        end if;
	end process;
	
	process (rst_i, clk_i, ld_en, cnt_stop)
    begin
        if rst_i = '0' then
            tx_reg <= (others => '1');
        elsif rising_edge (clk_i) then
            if ld_en = '1' then
                tx_reg <= STOP_BIT & data_i & START_BIT;
            elsif cnt_stop = '1' then
                tx_reg <= STOP_BIT & tx_reg (9 downto 1);
            end if;
        end if;
	end process;
	
	-- счётчики
    process (rst_i, clk_i)
    begin
        if rst_i = '0' then
            cnt     <= (others => '0');
            bit_cnt <= (others => '0');
        elsif rising_edge(clk_i) then
            if cnt = cnt_len then
                cnt <= (others => '0');     -- обнуление счётчика
                cnt_stop <= '1';            -- выставление флага окончания счёта
            elsif cnt_en = '1' then
                cnt <= cnt + 1;
                cnt_stop <= '0';
            end if;

            if bit_cnt_en = '1' then
                if bit_cnt = 10 then
                    bit_cnt <= (others => '0'); -- обнуление счётчика
                    bit_cnt_stop <= '1';        -- выставление флага окончания счёта
                else
                    bit_cnt <= bit_cnt + 1;
                    bit_cnt_stop <= '0';
                end if;
            end if;
        end if;
    end process;

	------ выходы --------
	tx_o <= tx;
	

end uart_tx_arch;

----------------------------------------------------------------
--------------------- конечный автомат -------------------------
----------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity uart_tx_fsm is
port(
	clk_i          : in std_logic;
	rst_i          : in std_logic;
	tx_en_i        : in std_logic;
	ld_en_o        : out std_logic;
	cnt_stop_i     : in std_logic;
	bit_cnt_stop_i : in std_logic;
	tx_ready_o     : out std_logic;
	cnt_en_o       : out std_logic;
	bit_cnt_en_o   : out std_logic
);
end uart_tx_fsm;

architecture uart_tx_fsm_arch of uart_tx_fsm is
	type t_UART_TX_SM is (
        s_Idle,
        s_LoadData,
        s_ShiftData,
        s_Cnt
	);
	signal UART_TX_State     : t_UART_TX_SM;
    signal UART_TX_NextState : t_UART_TX_SM;
begin
	---------- регистр -----------
	process (rst_i, clk_i)
    begin
        if rst_i = '0' then
            UART_TX_State <= s_Idle;
        elsif rising_edge(clk_i) then
            UART_TX_State <= UART_TX_NextState;
        end if;
	end process;
	-------------------------------
	
	------------- логика перехода в следующее состояние------------
	process (UART_TX_State, tx_en_i, cnt_stop_i, bit_cnt_stop_i)
    begin
        case UART_TX_State is
            when s_Idle =>
                if tx_en_i = '1' then
                    UART_TX_NextState <= s_LoadData;
                else
                    UART_TX_NextState <= s_Idle;
                end if;
            when s_LoadData =>
                UART_TX_NextState <= s_ShiftData;
            when s_ShiftData =>
                UART_TX_NextState <= s_Cnt;
            when s_Cnt =>
                if bit_cnt_stop_i = '1' then
                    UART_TX_NextState <= s_Idle;
                elsif cnt_stop_i = '1' then
                    UART_TX_NextState <= s_ShiftData;
                else
                    UART_TX_NextState <= s_Cnt;
                end if;
        end case;
	end process;
	----------------------------------------------------------------

	------------ автомат Мура-----------
	process (UART_TX_State)
    begin
        case UART_TX_State is
            when s_Idle =>
				tx_ready_o   <= '1';
                cnt_en_o     <= '0';
                bit_cnt_en_o <= '0';
                ld_en_o      <= '0';
            when s_LoadData =>
				tx_ready_o   <= '0';
                cnt_en_o     <= '0';
                bit_cnt_en_o <= '0';
                ld_en_o      <= '1';
            when s_ShiftData =>
				tx_ready_o   <= '0';
                bit_cnt_en_o <= '1';
                ld_en_o      <= '0';
            when s_Cnt =>
				tx_ready_o   <= '0';
                cnt_en_o     <= '1';
                bit_cnt_en_o <= '0';
                ld_en_o      <= '0';
        end case;
	end process;
	-------------------------------------
end uart_tx_fsm_arch;
__________________
Помощь в написании контрольных, курсовых и дипломных работ здесь
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
21.06.2021, 15:58
Ответы с готовыми решениями:

VHDL. Реализация UART на ПЛИС
Добрый день. Была поставлена задача реализовать передачу данных через UART (com порт) интерфейс...

Atmega16, модуль UART
Народ кто внесет ясность? Спаял преобразователь usb-uart на ftdi232rl. Написал простейший код на...

[ Решено ] A6 GSM модуль - проблема с UART
Играюсь с GSM модулем Aithinker A6. Подключил его к компьютеру через USB - UART адаптер. Сам...

GSM модуль для разного питания UART
Появилась задачка сделать GSM модуль, чтобы можно было управлять системой через SMS сообщения....

1
0 / 0 / 1
Регистрация: 05.04.2017
Сообщений: 64
21.06.2021, 16:03  [ТС] 2
На фото жёлтый луч это отправляемые данные с первого uart, а синий со второго
Миниатюры
Модуль UART на ПЛИС  
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
21.06.2021, 16:03

GPS модуль EB-500. Работа с UART через AT89C51
помогите разобраться с uart к com port подключаю GPS модуль ранее настроен на терминале на...

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

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

Два TX UART на один RX. Мультиплексирование UART.
Привет, сообщество. Возник небольшой затык. Есть необходимость при одном UART на Atmego32 подавать...

Найти модуль скорости; модуль тангенциального ускорения; модуль нормального ускорения; модуль полного ускорения
1. Материальная точка движется по плоскости. Движение точки в векторном виде описывается уравнением...

ПЛИС
Приветствую! Поработав некоторое время с МК, меня все равно тянет в сторону ПЛИС :) Собственно и...


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

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

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