1
\$\begingroup\$

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;

Added Testbench results

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;
asked Aug 4, 2017 at 11:35
\$\endgroup\$
3
  • 1
    \$\begingroup\$ You've told us the issue, but you haven't asked a question. What do you want us to do, fix it for you? \$\endgroup\$ Commented Aug 4, 2017 at 12:45
  • \$\begingroup\$ @BrianDrummond Hi Brian. I just need when I press button on FPGA, I should send data from FPGA. \$\endgroup\$ Commented Aug 4, 2017 at 12:58
  • 1
    \$\begingroup\$ The code isn't real clear. Your question would be better asked if you could include some comments on how you are trying to solve the problem (ie. what does your code do; describe the signals) - not just what the final goal is. \$\endgroup\$ Commented Aug 4, 2017 at 16:34

2 Answers 2

0
\$\begingroup\$

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

if shift_button(3 downto 0) = "001" then

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:

elsif (rising_edge(CLK)) then
tx_out <= '1';
out_tx <= tx_out;
shift_button(3) <= button;
...

so your shift_button register will immediately go to all 1s.

answered Aug 4, 2017 at 16:19
\$\endgroup\$
0
\$\begingroup\$

My first guess from skimming your code is that it's related to your testbench asserting your reset (which is active-low in your code) and never de-asserting it. Is your issue only in simulation or do you also see it when implementing in hardware?

There may be other issues, but to be honest this code is not very readable, although if you wrote it it's much better than what I was producing as a newbie. I'm going to write the rest of this assuming you wrote the UART_tx code. If you got it from the internet, whoever wrote it is not qualified to disseminate code.

I've done UART modules many times since then and a much more readable way to do it is with explicitly defined states. Here's my favorite reference for FSMs every time I forget the syntax: Implementing a Finite State Machine in VHDL. This is good design practice and will make it easier for other people to help you (and you'll find it'll make your code less prone to errors as well).

If it's not the reset that is the issue, I recommend you use this as an opportunity to get comfortable simulating and analyzing waveforms. In ModelSim/ISE sim/whatever, run your test-bench in the waveform viewer. Drag in the internal signals and look to see if they're behaving as expected. I see some other parts of the code that look like potential mistakes (if-statements that seem to be written sequentially even though processes are simulated as parallel)--I can't be sure they are, and if you got it from the internet then who knows--but you might find things are happening on the wrong clock cycle or not at all.

Since you say you're new, I want to note some other things I noticed:

  • The resets are asynchronous, because in the processes you look for a reset outside of the clocked block. See this Xilinx forum post for an explanation of why that's bad: sync reset or async reset? Long story short, it messes up timing paths and prevents many optimizations. Best to keep everything synchronous to the clock whenever possible in an FPGA.

if (Reset = '0') then baud_pulse <= '0'; counter_baud <= 0; elsif (rising_edge(CLK)) then

Should be

if (rising_edge(CLK)) then if (Reset = '0') then baud_pulse <= '0'; counter_baud <= 0;

  • If you intended for your reset to be active-low, it's good coding practice to reflect this in the name. Call it nReset maybe.

  • I'm impressed you're using std_ulogic. Much safer than std_logic yet I've never seen it on the FPGA-projects I've worked on professionally.

  • With respect to your title. What you're doing is sending data from your FPGA through a UART module. TTL is a class of digital logic hardware (like CMOS and ECL), UART is a communications device.

  • I'm Iranian and I knew when I saw "tx_tamam" that you're probably from somewhere in or around the Middle East (for those that don't know Turkish/Farsi/Arabic, tamam means "finished"). I thought that was funny, but when posting on stackexchange it would be worth your time to change names to English to help people help you.

Hopefully that helps. Modules written from scratch never work the first time (or second or third or...), looking at waveforms to debug becomes a way of life after awhile.

answered Aug 4, 2017 at 12:47
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.