Recientemente comencé a aprender VHDL y he intentado hacer un transmisor UART simple. Aquí está el código que he encontrado hasta ahora.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity uart_tx is
generic (clk_div: integer := 3332);
port (
clk : in std_logic; -- Clock signal
rst : in std_logic; -- Reset signal
tx_en : in std_logic; -- if '1', data is latched and ready
tx_data : in std_logic_vector(7 downto 0);
tx_ready : out std_logic; -- if '1', transmitter is ready to take in next byte
tx : out std_logic -- Data out
);
end uart_tx;
architecture Behavioral of uart_tx is
signal data_sr : std_logic_vector(7 downto 0) := (others => '0');
-- FSM variables
type uart_state is (idle, start, data, stop);
signal prev_state, next_state : uart_state;
begin
-- Sequential logic for FSM
fsm_seq : process (clk, rst)
variable count : integer range 0 to clk_div := 0;
begin
if (rst = '1') then
count := 0;
prev_state <= idle;
elsif rising_edge(clk) then
count := count + 1;
if (count >= clk_div) then
prev_state <= next_state;
count := 0;
end if;
end if;
end process;
-- Combinational logic for FSM
fsm_comb : process (prev_state, tx_data, tx_en, rst)
variable bit_cnt : integer range 0 to 7 := 0;
begin
if (rst = '1') then
data_sr(7 downto 0) <= (others => '0');
tx <= '1';
tx_ready <= '1';
bit_cnt := 0;
next_state <= idle;
else
case prev_state is
when idle =>
data_sr(7 downto 0) <= (others => '0');
tx <= '1';
tx_ready <= '1';
bit_cnt := 0;
if tx_en = '1' then
next_state <= start;
else
next_state <= idle;
end if;
when start =>
data_sr(7 downto 0) <= tx_data(7 downto 0); -- Load data into shift register
tx <= '0'; -- Start bit
tx_ready <= '0'; -- Busy
bit_cnt := 0;
next_state <= data;
when data =>
-- Shift register, LSB out first
data_sr(7 downto 0) <= '0' & data_sr(7 downto 1);
tx <= data_sr(0);
tx_ready <= '0';
bit_cnt := bit_cnt + 1;
if (bit_cnt >= 7) then
next_state <= stop;
else
next_state <= data;
end if;
when stop =>
data_sr(7 downto 0) <= (others => '0');
tx <= '1'; -- Stop bit
tx_ready <= '1'; -- Ready to receive next byte
bit_cnt := 0;
next_state <= idle;
end case;
end if;
end process;
end Behavioral;
Tengo problemas para diagnosticar el origen de estas advertencias:
WARNING:Xst:2170 - Unit uart_tx : the following signal(s) form a combinatorial loop: prev_state_FSM_FFd2-In, Madd_prev_state_add0000_lut<2>, prev_state_cmp_ge0001, prev_state_add0000<2>.
WARNING:Xst:2170 - Unit uart_tx : the following signal(s) form a combinatorial loop: Madd_prev_state_add0000_cy<0>.
WARNING:Xst:2170 - Unit uart_tx : the following signal(s) form a combinatorial loop: Madd_prev_state_add0000_lut<1>.
¿Qué estaría causando esto? He intentado mirar los esquemas pero hay tantas cosas que realmente no puedo saber por dónde empezar.
También, agradecería mucho cualquier otro puntero. Si estoy haciendo algo ridículo o el programa podría simplificarse drásticamente, hágamelo saber para que pueda aprender de mis errores.