Hice la misma pregunta en stackoverflow pero no obtuve ninguna buena respuesta. Soy novato en FPGAs y VHDL. Esta vez, estoy tratando de enviar datos desde FPGA a TTL. Estoy usando pines GPIO para TX y GND y los datos se pueden cambiar con el conmutador en FPGA. Mi problema es que cuando presiono el botón en FPGA, siempre veo FF en el terminal. No pude encontrar dónde está el problema.
Aquí está el código de TX:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.NUMERIC_STD.ALL;
entity UART_Tx is
port(
CLK : in std_logic;
Reset : in std_logic;
Button : in std_logic;
Data : in std_logic_vector(7 downto 0);
Out_Tx : out std_logic
);
end entity;
Architecture Behavioral of UART_Tx is
constant Baudrate : integer := 9600;
constant CLK_Hiz : integer := 50000000;
constant CLK_Bit : integer := (CLK_Hiz / Baudrate) + 1;
signal tx_Data_ind : integer range 0 to 7;
signal counter_baud : integer range 0 to (CLK_Bit - 1) := 0;
signal shift_button : std_logic_vector (3 downto 0) := (others => '0');
signal button_out : std_ulogic := '1';
signal baud_pulse : std_ulogic := '0';
signal tx_enable : std_ulogic := '0';
signal tx_Data : std_logic_vector (7 downto 0) := (others => '0');
signal tx_out : std_ulogic;
signal tx_ok : std_ulogic := '0';
signal counter_del : std_ulogic := '0';
begin
process(CLK, Reset)
begin
if (Reset = '0') then
baud_pulse <= '0';
counter_baud <= 0;
elsif (rising_edge(CLK)) then
if (counter_baud < (CLK_Bit - 1)) then
counter_baud <= counter_baud + 1;
baud_pulse <= '0';
else
counter_baud <= 0;
baud_pulse <= '1';
end if;
if (counter_del = '1') then
counter_baud <= 0;
end if;
end if;
end process;
process(CLK, Reset)
begin
if (Reset = '0') then
tx_Data <= (others => '0');
tx_data_ind <= 0;
tx_enable <= '0';
elsif (rising_edge(CLK)) then
tx_out <= '1';
out_tx <= tx_out;
shift_button(3) <= button;
shift_button(2 downto 0) <= shift_button(3 downto 1);
if shift_button(3 downto 0) = "001" then
button_out <= '0';
end if;
if (button_out = '0') then
counter_del <= '1';
tx_out <= '0';
if (tx_out = '0') then
tx_enable <= '1';
end if;
if (tx_enable = '1') then
counter_del <= '0';
tx_Data <= Data;
if (baud_pulse = '1') then
tx_out <= tx_Data(tx_Data_ind);
if (tx_data_ind < 7) then
tx_Data_ind <= tx_Data_ind + 1;
else
tx_ok <= '1';
end if;
if (tx_ok = '1') then
tx_Data <= (others => '0');
tx_Data_ind <= 0;
tx_enable <= '0';
button_out <= '1';
tx_out <= '1';
end if;
end if;
end if;
end if;
end if;
end process;
end Architecture;
Aquí está el código de Testbench:
library ieee;
use ieee.std_logic_1164.all;
entity tb_UART_Tx is
end tb_UART_Tx;
architecture tb of tb_UART_Tx is
component UART_Tx
port (CLK : in std_logic;
Reset : in std_logic;
Button : in std_logic;
Data : in std_logic_vector (7 downto 0);
Out_Tx : out std_logic);
end component;
signal CLK : std_logic:='0';
signal Reset : std_logic:='1';
signal Button : std_logic:='1';
signal Data : std_logic_vector (7 downto 0);
signal Out_Tx : std_logic;
constant TbPeriod : time := 20 ns;
signal TbSimEnded : std_logic := '0';
begin
dut : UART_Tx
port map (CLK => CLK,
Reset => Reset,
Button => Button,
Data => Data,
Out_Tx => Out_Tx);
clk_process: process
begin
CLK <= '0';
wait for TbPeriod/2;
CLK <= '1';
wait for TbPeriod/2;
end process;
stimuli : process
begin
Reset <= '0';
wait for 20 ns;
Button <= '1';
Data <= "00110000";
wait for 30 ns;
Button <= '0';
wait for 50 ns;
Button <= '1';
wait for 1000 ns;
-- Button <= '0';
-- wait for 30 ns;
-- Button <= '1';
TbSimEnded <= '1';
wait;
end process;
end tb;
configuration cfg_tb_UART_Tx of tb_UART_Tx is
for tb
end for;
end cfg_tb_UART_Tx;
Resultados agregados de Testbench
EDITAR: Chicos, gracias a todos por su interés. Supongo que encontré la solución. El problema fue que mi botón de registro no tenía punto de partida. Entonces, cuando el código comienza, el registro comienza con 000 a 100. Así que agregué un punto de inicio de registro (111) y uso los pulsos de baudios en los lugares correctos. Ahora, el código funciona perfectamente.
Aquí está el código de trabajo:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.NUMERIC_STD.ALL;
entity UART_Tx is
port(
CLK: in std_logic;
nReset: in std_logic;
nButton: in std_logic;
Data: in std_logic_vector (7 downto 0);
Data_Tx: out std_logic
);
end UART_Tx;
architecture Behavioral of UART_Tx is
constant Baudrate: integer:= 9600;
constant CLK_Hiz: integer:= 50000000;
constant CLK_Bit: integer:= (CLK_Hiz / Baudrate) + 1;
signal tx_counter: integer range 1 to 9:= 1;
signal counter_baud: integer range 0 to (CLK_Bit - 1):= 0;
signal shift_nButton:std_logic_vector (3 downto 0):= (others => '1');
signal tx_reg: std_logic_vector (7 downto 0):= (others => '0');
signal nButton_out: std_ulogic:= '1';
signal baud_pulse: std_ulogic;
signal tx_out: std_ulogic:= '1';
signal counter_del: std_ulogic;
signal start_bit: std_ulogic:='0';
signal data_bit: std_ulogic:='0';
signal stop_bit: std_ulogic:='0';
begin
process(CLK,nReset)
begin
if(nReset = '0') then
baud_pulse <= '0';
counter_baud <= 0;
elsif(rising_edge(CLK)) then
if(counter_baud < (CLK_Bit - 1)) then
counter_baud <= counter_baud + 1;
baud_pulse <= '0';
else
counter_baud <= 0;
baud_pulse <= '1';
end if;
if(counter_del = '1') then
counter_baud <= 0;
end if;
end if;
end process;
process(CLK, nReset)
begin
Data_Tx <= tx_out;
if(nReset = '0') then
tx_reg <= (others => '0');
tx_counter <= 1;
elsif(rising_edge(CLK)) then
shift_nButton(3) <= nButton;
shift_nButton(2 downto 0) <= shift_nButton(3 downto 1);
if shift_nButton(2 downto 0) = "001" then
nButton_out <= '0';
counter_del <= '1';
start_bit <= '1';
end if;
if(nButton_out = '1') then
tx_out <= '1';
elsif(nButton_out = '0') then
counter_del <= '0';
if(start_bit = '1') then
tx_out <= '0';
tx_reg <= Data;
if(baud_pulse = '1') then
start_bit <= '0';
data_bit <= '1';
end if;
end if;
if(data_bit = '1')then
if(tx_counter > 0 and tx_counter < 10) then
tx_out <= tx_reg((tx_counter)-1);
if(baud_pulse = '1') then
tx_counter <= tx_counter + 1;
if(tx_counter = 9)then
data_bit <= '0';
stop_bit <= '1';
end if;
end if;
end if;
end if;
if(stop_bit = '1') then
tx_out <= '1';
tx_counter <= 1;
if(baud_pulse = '1') then
stop_bit <= '0';
nButton_out <= '1';
tx_reg <= (others => '0');
end if;
end if;
end if;
end if;
end process;
end Behavioral;