0 / 0 / 1
Регистрация: 05.04.2017
Сообщений: 64
|
|
1 | |
Модуль UART на ПЛИС21.06.2021, 15:58. Показов 713. Ответов 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
|
|
21.06.2021, 15:58 | |
Ответы с готовыми решениями:
1
VHDL. Реализация UART на ПЛИС Atmega16, модуль UART
[ Решено ] A6 GSM модуль - проблема с UART |
0 / 0 / 1
Регистрация: 05.04.2017
Сообщений: 64
|
|
21.06.2021, 16:03 [ТС] | 2 |
На фото жёлтый луч это отправляемые данные с первого uart, а синий со второго
0
|
21.06.2021, 16:03 | |
21.06.2021, 16:03 | |
Помогаю со студенческими работами здесь
2
GSM модуль для разного питания UART GPS модуль EB-500. Работа с UART через AT89C51 Работа через терминал хост-компьютера с ПЛИС через USB-to-UART Конфигурация UART и просмотр файла, в который приходят данные с UART Сообщения для 2 UART выводятся в 1 UART, STM32F103C8T6 Два TX UART на один RX. Мультиплексирование UART. Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |