You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nexys 4开发板VHDL实现UART整串发送无输出问题求助

Nexys 4开发板VHDL实现UART整串发送无输出问题求助

我正在学习VHDL和FPGA,手里有一块Digilent的Nexys 4开发板。之前我实现了按一次按钮发送一个字符的功能,现在想改成每次按按钮发送一整串字符串,但终端(我用Putty)完全没有输出。我怀疑问题出在顶层模块里,但不确定具体哪里错了,附上我的顶层模块代码:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity UART_tx_top is
port(btnC : in std_logic;
      clk : in std_logic;
     RsTx : out std_logic);
end UART_tx_top;

architecture behavioral of UART_tx_top is

signal string_to_send : string := "Hello World!";
constant string_length : integer := 12;
signal tx_index : integer := 0;
type state_type is (TX_WAIT_BTN, TX_SEND_CHAR, TX_SEND_WAIT); 

signal state   : state_type := TX_WAIT_BTN;  
signal uartRdy : std_logic;
signal uartSend: std_logic;
signal uartData: std_logic_vector (7 downto 0);
signal initStr : std_logic_vector (7 downto 0) := x"41";
signal btnCclr : std_logic;
signal btnC_prev : std_logic;
  
component UART_tx_ctrl
generic(baud : integer);
port(send : in std_logic;
      clk : in std_logic;
     data : in std_logic_vector (7 downto 0);
    ready : out std_logic;
  uart_tx : out std_logic);
end component;

component debounce is
port(clk : in std_logic;
     btn : in std_logic;
 btn_clr : out std_logic);
end component;

begin
process(clk)
begin
if rising_edge(clk) then
btnC_prev <= btnCclr;
case state is
when TX_WAIT_BTN => 
    if btnC_prev = '0' and btnCclr = '1' then 
    state <= TX_SEND_CHAR; 
    end if;
when TX_SEND_CHAR =>
    if tx_index < string_length then
    uartData <= std_logic_vector(to_unsigned(character'pos(string_to_send(tx_index + 1)), 8));
    --initStr <= std_logic_vector(unsigned(initStr) + 1);
    tx_index <= tx_index + 1;
    --state <= TX_SEND_WAIT;
    else
       uartData <= (others => '0');
       tx_index <=0;
       state <= TX_WAIT_BTN;
    end if;
when TX_SEND_WAIT =>    
    if uartRdy = '1' then state <= TX_WAIT_BTN; 
    end if;     
end case;
end if;
end process;

uartSend <= '1' when (state = TX_SEND_CHAR) else '0';

SX : UART_tx_ctrl generic map(baud => 19200)
port map(send => uartSend, data => uartData, clk => clk, ready => uartRdy, uart_tx => RsTx);

dbc : debounce port map(clk => clk, btn => btnC, btn_clr => btnCclr);

end behavioral;

Hey,我仔细看了你的代码和问题,之前单字符发送正常,现在整串发没输出,问题大概率出在状态机的逻辑流程上,咱们来捋一捋:

问题分析

  1. 状态机流程断裂:你定义了TX_SEND_WAIT状态,但把切换到这个状态的代码注释掉了(--state <= TX_SEND_WAIT;),导致状态一直卡在TX_SEND_CHAR里疯狂循环更新数据和索引,根本没给UART留出发送单个字符的时间——UART还没发完当前字符,下一个字符就覆盖了,终端自然收不到有效数据。
  2. UART触发信号错误:uartSend被设置为只要在TX_SEND_CHAR状态就保持高电平,但大部分UART发送控制器的send信号需要的是单个时钟周期的脉冲触发,持续高电平可能无法正确启动多次发送,甚至让控制器进入异常状态。
  3. 缺少发送完成等待逻辑:你没有等待UART的ready信号就连续切换字符,UART还没完成上一个字符的发送,新数据就进来了,完全没法正常工作。

修改方案

调整状态机流程,让每发送一个字符后,等待UART完成发送(uartRdy = '1')再发下一个,直到整串发完回到等待按钮状态,同时修正uartSend的触发逻辑为脉冲信号:

process(clk)
begin
if rising_edge(clk) then
btnC_prev <= btnCclr;
case state is
when TX_WAIT_BTN => 
    if btnC_prev = '0' and btnCclr = '1' then 
        tx_index <= 0; -- 按下按钮后重置字符索引
        state <= TX_SEND_CHAR; 
    end if;
when TX_SEND_CHAR =>
    uartSend <= '1'; -- 生成一个时钟周期的发送触发脉冲
    if tx_index < string_length then
        uartData <= std_logic_vector(to_unsigned(character'pos(string_to_send(tx_index + 1)), 8));
        tx_index <= tx_index + 1;
        state <= TX_SEND_WAIT; -- 切换到等待发送完成状态
    else
        tx_index <= 0;
        state <= TX_WAIT_BTN; -- 整串发送完成,回到等待按钮状态
    end if;
when TX_SEND_WAIT =>    
    uartSend <= '0'; -- 拉低触发信号
    if uartRdy = '1' then 
        -- 发送完成后判断是否还有剩余字符
        if tx_index < string_length then
            state <= TX_SEND_CHAR;
        else
            state <= TX_WAIT_BTN;
        end if;
    end if;     
end case;
end if;
end process;

-- 移除原来的uartSend赋值,改在状态机内处理
-- uartSend <= '1' when (state = TX_SEND_CHAR) else '0';

另外补充两个小提醒:

  • 确保你的UART_tx_ctrl模块中,ready信号会在发送完成后拉高,且能正确响应send的脉冲触发;
  • 你设置的string_length = 12和索引tx_index + 1是对的,因为VHDL的string类型是从1开始索引的,刚好匹配"Hello World!"的字符数。

备注:内容来源于stack exchange,提问作者user1583007

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.17 12:48:11