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;
-
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\$user16324– user163242017年08月04日 12:45:31 +00:00Commented 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\$Griffo– Griffo2017年08月04日 12:58:45 +00:00Commented 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\$Blair Fonville– Blair Fonville2017年08月04日 16:34:06 +00:00Commented Aug 4, 2017 at 16:34
2 Answers 2
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.
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.