【发布时间】:2025-12-11 18:20:04
【问题描述】:
我正在用 VHDL 实现 RS-232 发射器。 我想获取使用 PS-2 键盘输入的数据并将其显示在串行端口终端中。 我有工作的接收器,我知道除了这个发射器之外,其余的元素都在工作。
我写了以下代码:
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;
SER_FREQ : integer := 115200
);
port (
clk : in std_logic;
rst : in std_logic;
tx : out std_logic;
tx_req : in std_logic;
tx_data : in std_logic_vector(7 downto 0);
rx_ready : out std_logic;
rx_data : out std_logic_vector(7 downto 0)
);
end uart;
architecture Behavioral of uart is
constant UART_IDLE : std_logic := '1';
constant UART_START : std_logic := '0';
constant RST_LVL : std_logic := '1';
type state is (idle,data,stop);
signal tx_state : state;
signal tx_next_state : state;
signal tx_clk_en : std_logic;
signal tx_data_tmp : std_logic_vector(7 downto 0);
signal tx_data_cnt : std_logic_vector(2 downto 0);
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
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;
end if;
end process;
tx_process:process(clk, tx_state)
begin
if tx_clk_en = '0' then
tx_next_state <= tx_state;
case tx_state is
when idle =>
if tx_req = '0' then
tx <= '0';
tx_data_tmp <= tx_data;
tx_next_state <= data;
tx_data_cnt <= (others=>'1');
else
tx <= '1';
tx_next_state <= idle;
tx_data_cnt <= (others=>'1');
tx_data_tmp <= (others=>'1');
end if;
when data =>
tx <= tx_data_tmp(0);
if tx_data_cnt = 0 then
tx_next_state <= stop;
tx_data_cnt <= (others=>'1');
tx_data_tmp <=(others=>'1');
else
tx_next_state <= data;
tx_data_tmp <= '0' & tx_data_tmp(7 downto 1);
tx_data_cnt <= tx_data_cnt - 1;
end if;
when stop =>
tx <= '1';
tx_next_state <= idle;
tx_data_cnt <= (others=>'1');
tx_data_tmp <=(others=>'1');
end case;
end if;
end process;
tx_next:process(tx_next_state)
begin
tx_state <= tx_next_state;
end process;
end Behavioral;
在实施设计期间有一些警告:
One or more signals are missing in the process sensitivity list. To enable synthesis of FPGA/CPLD hardware, XST will assume that all necessary signals are present in the sensitivity list. Please note that the result of the synthesis may differ from the initial design specification. The missing signals are:<tx_clk_en>, <tx_req>, <tx_data>
Found 3-bit latch for signal <tx_data_cnt>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
Found 8-bit latch for signal <tx_data_tmp>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
Found 3-bit latch for signal <tx_next_state>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
Found 1-bit latch for signal <tx>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems.
请帮帮我。 提前致谢。
编辑:
我根据您的提示调整了我的代码,现在没有任何警告,但我仍然不确定它是否能正常工作。任何人都可以在硬件上检查它吗?或者只是评论新版本。
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;
SER_FREQ : integer := 115200
);
port (
clk : in std_logic;
rst : in std_logic;
tx : out std_logic;
tx_req : in std_logic;
tx_data : in std_logic_vector(7 downto 0);
);
end uart;
architecture Behavioral of uart is
constant UART_IDLE : std_logic := '1';
constant UART_START : std_logic := '0';
constant RST_LVL : std_logic := '1';
type state is (idle, active);
signal tx_state : state;
signal tx_next_state : state;
signal tx_clk_en : std_logic;
signal tx_data_packet : std_logic_vector(9 downto 0);
signal tx_data_cnt : std_logic_vector(3 downto 0);
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
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;
end if;
end process;
tx_reset:process(clk)
begin
if clk'event and clk = '1' then
if rst = '0' then
tx_state <= idle;
else
tx_state <= tx_next_state;
end if;
end if;
end process;
tx_process:process(clk, tx_state, tx_req, tx_clk_en)
begin
if clk'event and clk = '1' then
if tx_clk_en = '0' then
tx_next_state <= tx_state;
case tx_state is
when idle =>
if tx_req = '0' then
tx_data_packet(9) <= '0';
tx_data_packet(8 downto 1) <= tx_data;
tx_data_packet(0) <= '1';
tx_next_state <= active;
tx_data_cnt <= "1010";
else
tx <= '1';
tx_next_state <= idle;
tx_data_cnt <= (others=>'1');
tx_data_packet <= (others=>'1');
end if;
when active =>
tx <= tx_data_packet(0);
if tx_data_cnt = 0 then
tx_next_state <= idle;
tx_data_cnt <= (others=>'1');
tx_data_packet <=(others=>'1');
else
tx_next_state <= active;
tx_data_packet <= '0' & tx_data_packet(9 downto 1);
tx_data_cnt <= tx_data_cnt - 1;
end if;
end case;
else
tx <= '1';
tx_data_packet <= (others=>'1');
tx_data_cnt <= (others=>'1');
end if;
end if;
end process;
end Behavioral;
#
#
大家好! 我现在有以下代码,我在硬件上进行了测试,但它仍然无法正常工作。你有什么想法可能是错的吗?
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;
SER_FREQ : integer := 115200
);
port (
clk : in std_logic;
rst : in std_logic;
rx : in std_logic;
tx : out std_logic;
tx_req : in std_logic;
tx_data : in std_logic_vector(7 downto 0);
);
end uart;
architecture Behavioral of uart is
constant UART_IDLE : std_logic := '1';
constant UART_START : std_logic := '0';
constant RST_LVL : std_logic := '1';
type state is (idle, active);
signal tx_busy :std_logic;
signal tx_state : state;
signal tx_next_state : state;
signal tx_clk_en : std_logic;
signal tx_data_packet : std_logic_vector(8 downto 0);
signal tx_data_cnt : std_logic_vector(3 downto 0);
begin
--
tx_clk_gen:process(clk, tx_req)
variable counter : integer range 0 to conv_integer((CLK_FREQ*1_000_000)/SER_FREQ-1);
begin
if rising_edge(clk) then
if tx_busy = '1' then
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;
end if;
end if;
end process;
tx_reset:process(clk)
begin
if rising_edge(clk) then
if rst = '0' then
tx_state <= idle;
else
tx_state <= tx_next_state;
end if;
end if;
end process;
tx_process:process(clk, tx_state, tx_req, tx_clk_en)
begin
if rising_edge(clk) then
case tx_state is
when idle =>
if tx_req = '1' then
tx <= '0';
tx_data_packet(7 downto 0) <= tx_data;
tx_data_packet(8) <= '1';
tx_next_state <= active;
tx_data_cnt <= "1010";
tx_busy <= '1';
else
tx <= '1';
tx_next_state <= idle;
tx_data_cnt <= (others=>'1');
tx_data_packet <= (others=>'1');
end if;
when active =>
if tx_clk_en = '1' then
tx <= tx_data_packet(0);
if tx_data_cnt = 0 then
tx_next_state <= idle;
tx_data_cnt <= (others=>'1');
tx_data_packet <=(others=>'1');
tx <= '1';
tx_busy <= '0';
else
tx_next_state <= active;
tx_data_packet <= '1' & tx_data_packet(8 downto 1);
tx_data_cnt <= tx_data_cnt - 1;
end if;
end if;
end case;
end if;
end process;
【问题讨论】:
-
注意:如果在传输一个 8 位字节时,它可能会简化事情,而不是“前置”一个起始位 0 并附加一个停止位 1,形成一个 10 位“数据”来发送,从而减少状态到 2 个条件:活跃,不活跃。
标签: serial-port vhdl fpga