I asked same question in stackoverflow but didn't get any good answer. I'm newbie in FPGAs and VHDL. This time, I m trying to send Data from FPGA to TTL. I' m using GPIO pins for TX and GND and Data can be changed with switch on FPGA. My issue is whenever i press the button on FPGA, I always see FF on terminal. I couldn't find where the problem is.
Here is TX code:
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;
Here is Testbench code:
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;
EDIT: Guys thank you all for your interest. I guess I found the solution. The problem was my button register had no starting point. So when the code starts, register starts with 000 to 100. So I added a register starting point (111) and use baud pulses in right places. Now, code works perfectly.
Here is the working code:
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;
Best Answer
First, drawing a state-flow diagram for your design would help both you and us to solve the problem.
A couple of things jump out at me:
1. Where you write
should be
if shift_button(2 downto 0) = "001" then
2. When you press your button, you are going to be holding it for many clock cycles. Your design shifts a 1 into
shift_button
at evey clock cycle, per:so your
shift_button
register will immediately go to all 1s.