VHDL state machine testbench - works when on board but not on simulation - vhdl

I have the VHDL implementation that works on board, it detects the sequence 01110 and will raise a flag for 2 clock counts. It detects overlapping sequences as well where 011101110 would raise the flag twice.
I've checked my implementation with a logic analyzer on the board and am fairly confident that it works. I am feeding in a repetition sequence of 0111 at 10 kHz, on the board, it has a clock at 100 MHz where I scale it to 10 kHz with a prescaler.
My problem is, when trying to recreate a similar scenario using a simulation, I do not get any outputs as expected
Image from logic analyzer from board
Image from Test Bench
Test Bench Code
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity test_FSM_prac4 is
-- Port ( );
end test_FSM_prac4;
architecture Behavioral of test_FSM_prac4 is
component FSM_prac4 is
port (
inputSignal : in STD_LOGIC;
pushButton : in STD_LOGIC;
clk100mhz : in STD_LOGIC;
logic_analyzer : out STD_LOGIC_VECTOR (7 downto 0);
LEDs: out STD_LOGIC
); end component;
signal inputSignal : std_logic := '0';
signal pushButton: std_logic := '0';
signal clk100mhz: std_logic := '0';
signal logic_analyzer: std_logic_vector(7 downto 0);
signal LEDs : std_logic;
begin
uut : FSM_prac4 port map(
inputSignal => inputSignal,
pushButton => pushButton,
clk100mhz => clk100mhz,
logic_analyzer => logic_analyzer,
LEDs => LEDs
);
--generate clock 100mhz
clock_tic: process begin
loop
clk100mhz <= '0';
wait for 5ns;
clk100mhz <= '1';
wait for 5ns;
end loop;
end process;
input_changes: process begin
loop
inputSignal <= '0';
wait for 100us;
inputSignal <= '1';
wait for 100us;
inputSignal <= '1';
wait for 100us;
inputSignal <= '1';
wait for 100us;
end loop;
end process;
end Behavioral;
To show the mapping for logic Analyzer
logic_analyzer(0) <= masterReset;
logic_analyzer(1) <= newClock -- 10Khz Clock;
logic_analyzer(2) <= outputZ;
--FSM States
logic_analyzer(3) <= '1' when y = A ELSE '0';
logic_analyzer(4) <= '1' when y = B ELSE '0';
logic_analyzer(5) <= '1' when y = C ELSE '0';
logic_analyzer(6) <= '1' when y = D ELSE '0';
logic_analyzer(7) <= '1' when y = E ELSE '0';
If anyone could direct to what I am doing wrong on the test bench and how to replicate to get similar results as the first image as it shows that in simulation, it always stays at state A and the new clock is not toggling meaning that clk100mhz is somehow not connected but I can't figure out why.
Any help is greatly appreciated, thanks guys
edit:
I wrote a simple program to test my scalar clock
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
entity scaler_clk is
Port (
pushButton : in std_logic;
indicator : out std_logic;
clk100mhz : in STD_LOGIC;
clk10khz: out STD_LOGIC
);
end scaler_clk;
architecture Behavioral of scaler_clk is
signal clockScalers : std_logic_vector (12 downto 0):= (others => '0') ;
signal prescaler: std_logic_vector(12 downto 0) := "1001110001000";
signal newClock: std_logic := '0';
signal masterReset : std_logic;
begin
clk10khz <= newClock;
masterReset <= pushButton;
process (clk100mhz,masterReset) begin
if(masterReset <= '1') then <--- error occurs here
clockScalers <= "0000000000000";
newClock <= '0';
indicator <= '1';
elsif (clk100mhz'event and clk100mhz = '1')then
indicator <= '0';
clockScalers <= clockScalers + 1;
if(clockScalers > prescaler) then
newClock <= not newClock;
clockScalers <= (others => '0');
end if;
end if;
end process;
end Behavioral;
test bench code
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity test_scaler_clk is
-- Port ( );
end test_scaler_clk;
architecture Behavioral of test_scaler_clk is
component scaler_clk Port (
pushButton : in std_logic;
indicator : out std_logic;
--input clock
clk100mhz : in STD_LOGIC;
clk10khz: out STD_LOGIC
);end component;
signal clk100mhz: std_logic := '0';
signal clk10khz : std_logic;
signal pushButton: std_logic;
signal indicator : std_logic;
begin
uut: scaler_clk port map(
pushButton => pushButton,
indicator => indicator,
clk100mhz => clk100mhz,
clk10khz => clk10khz
);
pushButton <= '0';
clock_tic: process begin
loop
clk100mhz <= '0';
wait for 5ns;
clk100mhz <= '1';
wait for 5ns;
end loop;
end process;
end Behavioral;
Even though I set pushButton to '0', it is still triggering masterReset, anyone knows why, that's why the 10 kHz clock isn't working

There are several things that you could (should) improve in your code. As Brian already explained, in your Behavioral architecture of scaler_clk, you should have:
if(masterReset = '1') then
instead of:
if(masterReset <= '1') then
Now, let's start with the most likely cause of your initial problem: unbound components. Your test benches instantiate the design to validate as components. VHDL components are kind of prototypes of actual entities. Prototypes are enough to compile because the compiler can perform all necessary syntax and type checking. But they are not enough to simulate because the simulator also needs the implementation behind the prototype. Some tools have a default binding strategy for unbound components: if they find an entity with the same name and if it has only one architecture, they use that. Your simulator apparently does not use such strategy (at least not by default, there is maybe an option for that but it is disabled). Note that most simulators I know issue warnings when they find unbound components. You probably missed these warnings.
Anyway, your component instances are unbound (they have no associated entity/architecture) and the simulator considers them as black boxes. Their outputs are not driven, except by the initial values you declared (1).
How to fix this? Two options:
Use a configuration to specify which entity/architecture pair shall be used for each component instance:
for all: scaler_clk use entity work.scaler_clk(Behavioral);
Use entity instantiations instead of components:
uut: entity work.scaler_clk(Behavioral) port map...
Now, let's go through some other aspects of your code that could be improved:
You are using non-standard packages, that are frequently not even compatible: IEEE.STD_LOGIC_ARITH and IEEE.STD_LOGIC_UNSIGNED. As they are not standard they should not even be in the standard IEEE library. You should use IEEE.NUMERIC_STD instead, and only that one. It declares the SIGNED and UNSIGNED types (with the same declaration as STD_LOGIC_VECTOR) and overloads the arithmetic operators on them.
Your test benches generate the 100MHz clock with:
clock_tic: process begin
loop
clk100mhz <= '0';
wait for 5ns;
clk100mhz <= '1';
wait for 5ns;
end loop;
end process;
The infinite loop is useless: a process is already an infinite loop:
clock_tic: process
begin
clk100mhz <= '0';
wait for 5ns;
clk100mhz <= '1';
wait for 5ns;
end process clock_tic;
would do the same. Same remark for your input_changes process.
Your input_changes process uses wait for <duration> statements. This is not a good idea because you do not know when the inputSignal signal toggles, compared to the clock. Is it just before, just after or exactly at the same time as the rising edge of clk100mhz? And if it is exactly at the same time, what will happen? Of course, you can carefully chose the <durations> to avoid such ambiguities but it is error prone. You should use the wait for <duration> only in the clock generating process. Everywhere else, it is better to synchronize with the clock:
input_changes: process
begin
inputSignal <= '0';
for i in 1 to 10000 loop
wait until rising_edge(clk100mhz);
end loop;
inputSignal <= '1';
for i in 1 to 10000 loop
wait until rising_edge(clk100mhz);
end loop;
inputSignal <= '1';
for i in 1 to 10000 loop
wait until rising_edge(clk100mhz);
end loop;
inputSignal <= '1';
for i in 1 to 10000 loop
wait until rising_edge(clk100mhz);
end loop;
end process input_changes;
This guarantees that inputSignal changes just after the rising edge of the clock. And you could rewrite it in a bit more elegant way (and probably a bit easier to maintain):
input_changes: process
constant values: std_logic_vector(0 to 3) := "0111";
begin
for i in values'range loop
inputSignal <= values(i);
for i in 1 to 10000 loop
wait until rising_edge(clk100mhz);
end loop;
end loop;
end process input_changes;
You are using resolved types (STD_LOGIC and STD_LOGIC_VECTOR). These types allow multiple drive, that is, having a hardware wire (VHDL signal) that is driven by several devices (VHDL processes). Usually you do not want this. Usually you even want to avoid this like the plague because it can cause short-circuits. In most cases it is wiser to use non-resolved types (STD_ULOGIC and STD_ULOGIC_VECTOR) because the compiler and/or the simulator will raise errors if you accidentally create a short circuit in your design.
One last thing: if, as its name suggests, you intend to use the clk10khz signal as a real clock, you should reconsider this decision. It is a signal that you generate with your custom logic. Clocks have very specific electrical and timing constraints that cannot really be fulfilled by regular signals. Before using clk10khz as a clock you must deal with clock skew, clock buffering... Not impossible but tricky. If you did use it as a clock your synthesizer probably issued critical warnings that you also missed (have a look maybe at the timing report). Moreover, this is probably useless in your case: an enable signal generated from clk100mhz could probably be used instead, avoiding all these problems. Instead of:
process (clk100mhz,masterReset) begin
if(masterReset = '1') then
clockScalers <= "0000000000000";
newClock <= '0';
indicator <= '1';
elsif (clk100mhz'event and clk100mhz = '1')then
indicator <= '0';
clockScalers <= clockScalers + 1;
if(clockScalers > prescaler) then
newClock <= not newClock;
clockScalers <= (others => '0');
end if;
end if;
end process;
use:
signal tick10khz: std_ulogic;
...
process(clk100mhz, masterReset) begin
if masterReset = '1') then
clockScalers <= "0000000000000";
tick10khz <= '0';
elsif rising_edge(clk100mhz) then
clockScalers <= clockScalers + 1;
tick10khz <= '0'
if(clockScalers > prescaler) then
tick10khz <= '1';
clockScalers <= (others => '0');
end if;
end if;
end process;
And then, instead of:
process(clk10khz)
begin
if rising_edge(clk10khz) then
register <= register_input;
end if;
end process;
use:
process(clk100mhz)
begin
if rising_edge(clk100mhz) then
if tick10khz = '1' then
register <= register_input;
end if;
end if;
end process;
The result will be the same but with only one single 100MHz clock, which avoids clock skew, clock buffering and clock domain crossing problems.
(1) This illustrates why declaring variables and signals with initial values is usually not a good idea: it hides potential problems. Without this your signals would have been stuck at 'U' (uninitialized) and it would maybe have helped understanding where the problem comes from.

Related

UART Transmitter only functions when embedded logic analyzer is running

I have been trying to implement a UART in order to communicate between my Lattice MachXO3D board and my computer. At the moment I am attempting to implement the transmission from the FPGA.
Upon testing on the hardware, I encountered a very strange issue. If run normally, it will function for a few seconds and then it will suddenly stop functioning (The CH340 connected to my computer will report it is receiving messages containing 0x0). However, if I embed a logic analyzer onto the FPGA through the Lattice Diamond software, and I run the analyzer, it will function perfectly for an extended period of time.
Sadly, I don't have a logic analyzer, so the embedded logic analyzer is my only chance at knowing what is actually being transmitted.
These are the files related to my implementation:
baud_gen
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
-- Generates 16 ticks per bit
ENTITY baud_gen IS
GENERIC(divider: INTEGER := 13 -- 24M/115200*16
);
PORT(
clk, reset: IN STD_LOGIC;
s_tick: OUT STD_LOGIC
);
END baud_gen;
ARCHITECTURE working OF baud_gen IS
BEGIN
PROCESS(clk)
VARIABLE counter: UNSIGNED(3 DOWNTO 0) := to_unsigned(0,4);
BEGIN
IF clk'EVENT AND clk='1' THEN
IF reset='1' THEN
s_tick <= '0';
counter := to_unsigned(0,4);
ELSIF counter=to_unsigned(divider-1,4) then
s_tick <= '1';
counter:= to_unsigned(0,4);
ELSE
s_tick <= '0';
counter := counter + 1;
END IF;
END IF;
END PROCESS;
END working;
rs232_tx
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
ENTITY rs232_tx IS
PORT(clk: IN std_logic;
tx: OUT std_logic;
rst: IN std_logic;
fifo_empty: IN std_logic;
fifo_RdEn, fifo_RdClock: OUT std_logic;
fifo_data: IN STD_LOGIC_VECTOR(7 DOWNTO 0);
Q: OUT STD_LOGIC_VECTOR(1 DOWNTO 0));
END rs232_tx;
ARCHITECTURE working OF rs232_tx IS
TYPE state IS (idle,start,data);
SIGNAL tx_pulse: STD_LOGIC := '1';
SIGNAL s_tick: STD_LOGIC;
SIGNAL pr_state, nx_state: state := idle;
SIGNAL data_val: std_logic_vector(7 DOWNTO 0):=(others=>'0');
SIGNAL data_count: unsigned(2 DOWNTO 0):=to_unsigned(0,3);
BEGIN
process(s_tick, rst)
VARIABLE count: unsigned(3 DOWNTO 0):= to_unsigned(0,4);
BEGIN
IF rising_edge(s_tick) THEN
count := count + to_unsigned(1,4);
IF count = to_unsigned(15,4) THEN
tx_pulse <= '1';
ELSE
tx_pulse <='0';
END IF;
END IF;
END PROCESS;
process(tx_pulse,rst)
BEGIN
IF rising_edge(tx_pulse) THEN
IF rst='1' THEN
pr_state <= idle;
data_val <= (others=>'0');
data_count <= to_unsigned(0,3);
ELSE
pr_state <= nx_state;
CASE pr_state IS
WHEN idle =>
data_count <= to_unsigned(0,3);
WHEN data =>
data_count <= data_count + to_unsigned(1,3);
WHEN start =>
data_val <= fifo_data;
WHEN OTHERS =>
END case;
END IF;
END IF;
END process;
process(fifo_empty,rst,data_count,pr_state,data_count)
BEGIN
case pr_state is
when idle =>
Q <= ('1','1');
fifo_RdEn <= '0';
tx <= '1';
IF fifo_empty='0' AND rst='0' THEN
nx_state <= start;
ELSE
nx_state <= idle;
END IF;
WHEN start =>
Q <= ('1','0');
fifo_RdEn <= '1';
tx <= '0';
nx_state <= data;
WHEN data =>
Q <= ('0','1');
fifo_RdEn <= '0';
tx <= data_val(to_integer(data_count));
if data_count=to_unsigned(7,3) then
nx_state <= idle;
ELSE
nx_state <= data;
end if;
end case;
END process;
fifo_RdClock <= tx_pulse;
baud_gen: ENTITY work.baud_gen
PORT MAP(clk,reset=>'0',s_tick=>s_tick);
END working;
testbench
LIBRARY IEEE;
USE IEEE.std_logic_1164.ALL;
USE IEEE.numeric_std.ALL;
ENTITY rs232_tx_test IS
GENERIC(clk_period: TIME := 41666666.7 fs;
baud_period: TIME := 8680.55556 ns);
END rs232_tx_test;
ARCHITECTURE working OF rs232_tx_test IS
SIGNAL clk: STD_LOGIC := '0';
SIGNAL tx, rst, fifo_empty, fifo_RdEn, fifo_RdClock: STD_LOGIC;
SIGNAL fifo_data: STD_LOGIC_VECTOR(7 DOWNTO 0);
BEGIN
clk <= NOT clk AFTER clk_period/2;
rst <= '1', '0' AFTER 100 ns;
PROCESS
BEGIN
fifo_empty <= '1';
WAIT FOR baud_period;
fifo_empty <= '0';
WAIT FOR baud_period*16;
END PROCESS;
fifo_data <= ('1','1','0','0','1','0','1','1') WHEN fifo_RdEn='1' ELSE (others=>'0');
dut: ENTITY work.rs232_tx
PORT MAP(clk,tx,rst,fifo_empty,fifo_RdEn,fifo_RdClock,fifo_data);
END working;
EDIT
I have tested another UART design I found online # 9600 bps and it fails in the same way. It can send a constant character, in this case 'a', to a terminal on my computer, and then it suddenly stops sending anything. However, if I start listening to the soft logic analyzer I generated in Lattice Diamond, it works without a problem and does not fail.
This smells like a classic timing issue.
In the comments, others have explained where there are weaknesses in the code that could indirectly lead to this. I'm going to concentrate on what is occurring.
As you have stated, in simulation your code works as you expect. However, that is only half the story. To create an FPGA bit stream the build tools take your code and several other files, synthesises, and conducts Place & Route. Your timing issue occurs during P&R. This is why your simulation doesn't pick up on any errors, as I'm assuming it's an RTL (pre-place & route) simulation.
During P&R the tools lay the logic in the best way to fit the timing model of the device so all paths meet their timing requirements. The path timing requirements are derived from explicit statements in a Timing Constraints file and inferred from your code (that's why your coding style matters btw).
Once P&R is complete, the tools will put the build artefact through a static timing analyser (STA) tool and report back whether the build fails to meet the timing requirements.
This leads to two questions:
Does the build report a timing error?
Do you have a Timing Constraints file - if you're unsure, the answer is no.
The way to debug your problem is to use the Timing Report generated by Lattice Diamond to see where the failures are.
If there are no reported failures it means your timing model is wrong because of a lack of appropriate timing constraints. As a minimum, you will need to constrain all IO in the design and describe all the clocks in your design.
Here is a good document to help you out:
https://www.latticesemi.com/-/media/LatticeSemi/Documents/UserManuals/RZ/Timing_Closure_Document.ashx?document_id=45588
The reason that your design works when you use the embedded Logic Analyser is that extra logic has been placed in the design, which changes the timing model. The P&R tools lay out the design differently, and by luck have placed the design in such a way as meet the real timing requirements on it.
As I often say to my Software Engineer colleagues, software languages create a set of instructions, HDL creates a set of suggestions.

Switch on LED after receiving Ethernet packets

I'm a novice in VHDL programming and currently try to execute a program where the LED on the FPGA board should switch on after transmitting every 10 Ethernet packets which I generate from a Linux server. The code I've written is in the following which doesn't work properly. I'm trying to figure out the problem but still undone. Any help would be much appreciated.
---------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
---------------------------------------------
entity notification is
port (clk, reset, qdv: in std_logic;
LED: out std_logic
);
end notification;
architecture behavior of notification is
signal qdv_a: std_logic;
signal qdv_b: std_logic;
signal packet_count: std_logic_vector (3 downto 0);
begin
no_1: process(clk, reset)
begin
if (reset = '1') then
qdv_a <= '0';
elsif rising_edge (clk) then
qdv_a <= qdv;
end if;
end process no_1;
qdv_b <= qdv and (not qdv_a);
no_2: process(clk, reset)
begin
if (reset = '1') then
packet_count <= "0000";
elsif rising_edge (clk) then
if qdv_b = '1' then
if packet_count < "1010" then
packet_count <= packet_count + 1;
LED <= '0';
else
LED <= '1';
packet_count <= (others => '0');
end if;
end if;
end if;
end process no_2;
end behavior;
I am making assumptions based on your code:
1) You are trying to increment packet_count every time you see a rising edge on qdv,
2) The pulse width of qdv is longer than a period of the 25MHz clock (clk_25MHz) - 40ns and
3) You want an asynchronous reset. (Trying to decide which is better - a synchronous or asynchronous reset - is like trying to decide which is a better - a Mac or a PC.)
So,
If (1) and (2) are true, you need a synchronous edge detector:
signal qdv_d : std_logic;
signal qdv_r : std_logic;
...
process (clk_25MHz, reset)
begin
if reset = '1' then
qdv_d <= '0';
elsif rising_edge (clk_25MHz) then
qdv_d <= qdv;
end if;
end process;
qdv_r <= qdv and not qdv_d;
Please draw this out as a schematic so that you can see how it works.
Then, assuming (3), you need to sort out your main process. If you're coding sequential logic, you should stick to a template. Here is the template for sequential logic with an asynchronous reset, which all synthesis tools should understand:
process(clock, async_reset) -- nothing else should go in the sensitivity list
begin
-- never put anything here
if async_reset ='1' then -- or '0' for an active low reset
-- set/reset the flip-flops here
-- ie drive the signals to their initial values
elsif rising_edge(clock) then -- or falling_edge(clock)
-- put the synchronous stuff here
-- ie the stuff that happens on the rising or falling edge of the clock
end if;
-- never put anything here
end process;
Only clock and reset go in the sensitivity list, because the outputs of the sequential process (though they depend on all the inputs) only change when clock and/or reset change. On a real D-type flip-flop, reset takes priority over clock, so we test that first and do the resetting should reset be asserted. If there is a change on clock (when reset is not asserted) and that change is a rising edge, then do all the stuff that should happen on the rising edge of a clock (stuff that will get synthesised to combinational logic driving the D inputs of the flip-flops).
So, using that template, here is how I would write your main process:
process(clk_25MHz, reset)
begin
if reset = '1' then
packet_count <= "0000";
elsif rising_edge (clk_25MHz) then
if qdv_r = '1' then
if packet_count < "1010" then
packet_count <= packet_count + 1;
LED <= '0';
else
LED <= '1';
packet_count <= (others => '0');
end if;
end if;
end if;
end process;
Now we have a synchronous process which increments packet_count and drives the LED output. (What is q bringing to the party?)
Please
bear in mind that I haven't simulated any of this
don't just type it in without trying to understand how it works

Xilinx / ISim seem claims value to be X but it has been declared

Have JUST started learning how to use this tool so if my question seems silly i apologize in advance. I have searched the error in numerous forums (already answered posts , not mine) and couldn't understand what i was doing wrong so here is my question:
My Behavioral Code:
----------------------------------------------------------------------------- -----
-- Company:
-- Engineer:
--
-- Create Date: 01:47:22 07/07/2015
-- Design Name:
-- Module Name: Module_1 - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------- -----
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned valuessss
--use IEEE.NUMERIC_STD.ALL;
-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;
entity Module_1 is
port (A,B,WE,reset : in std_logic;
clk : in std_logic;
DIN : in signed(3 downto 0);
FULL,EMPTY,ERROR : out std_logic:= '0';
PARKFREE : out signed(3 downto 0)
);
end Module_1;
architecture Behavioral of Module_1 is
signal current_state,next_state:std_ulogic_vector(1 downto 0);
signal empty_bf, full_bf :std_ulogic;
signal enter, reset_b : std_ulogic := '0' ;
constant s0: std_ulogic_vector (1 downto 0):="00";
constant s1: std_ulogic_vector (1 downto 0):="10";
constant s2: std_ulogic_vector (1 downto 0):="11";
constant s3: std_ulogic_vector (1 downto 0):="01";
signal park_counter,buffr: signed(3 downto 0):="0000";
signal PARKTOTAL,free_park_counter: signed(3 downto 0):= "1111";
begin
p1: process (clk,reset,reset_b)
begin
if (reset = '1') then
current_state <= s0;
elsif clk'event and clk = '1' then
current_state <= next_state;
end if;
end process p1;
p2: process (current_state,A,B)
begin
next_state <= current_state;
case current_state is
when s0 =>
if A = '1' then
enter <= '1';
next_state <= s1;
elsif B = '1' then
next_state <= s3;
end if;
when s1 =>
if A = '0' then
enter <= '0';
next_state <= s0;
elsif B = '1' then
next_state <= s2;
end if;
when s2 =>
if A = '0' then
next_state <= s3;
elsif B = '0' then
next_state <= s1;
end if;
when s3 =>
if B = '0' then
enter <= '0';
next_state <= s0;
elsif A = '1' then
next_state <= s2;
end if;
when others =>
end case;
end process p2;
p3: process(current_state,A,B)
begin
case current_state is
when s1 =>
if enter = '0' and A = '0' and empty_bf = '0' then
park_counter <= park_counter - 1;
free_park_counter <= free_park_counter + 1;
ERROR <= '0';
end if;
when s3 =>
if enter = '1' and B = '0' and full_bf = '0' then
park_counter <= park_counter + 1;
free_park_counter <= free_park_counter - 1;
ERROR <= '0';
end if;
when others =>
end case;
end process p3;
max: process(WE)
begin
if clk'event and clk = '1' and WE = '1' then
PARKTOTAL <= DIN ;
buffr <= DIN ;
if (free_park_counter < buffr - park_counter) then
ERROR <= '1';
reset_b <= '1';
else free_park_counter <= buffr - park_counter;
end if;
end if;
end process max;
incr: process(free_park_counter,DIN)
begin
PARKFREE <= free_park_counter;
if (free_park_counter = 15) then
EMPTY <= '1';
empty_bf <= '1';
else EMPTY <= '0';
empty_bf <= '0';
end if;
if (free_park_counter = 0) then
FULL <= '1';
full_bf <= '1';
else FULL <= '0';
full_bf <= '0';
end if;
end process incr;
end Behavioral;
My Testbench
----------------------------------------------------------------------------- ---
-- Company:
-- Engineer:
--
-- Create Date: 02:17:07 07/11/2015
-- Design Name:
-- Module Name: D:/Users/ErgasiaFPGA/Testbench.vhd
-- Project Name: ErgasiaFPGA
-- Target Device:
-- Tool versions:
-- Description:
--
-- VHDL Test Bench Created by ISE for module: Module_1
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
-- Notes:
-- This testbench has been automatically generated using types std_logic and
-- std_logic_vector for the ports of the unit under test. Xilinx recommends
-- that these types always be used for the top-level I/O of a design in order
-- to guarantee that the testbench will bind correctly to the post-implementation
-- simulation model.
--------------------------------------------------------------------------------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;
ENTITY Testbench IS
END Testbench;
ARCHITECTURE behavior OF Testbench IS
-- Component Declaration for the Unit Under Test (UUT)
COMPONENT Module_1
PORT(
A : IN std_logic;
B : IN std_logic;
WE : IN std_logic;
reset : IN std_logic;
clk : IN std_logic;
DIN : IN signed(3 downto 0);
FULL : OUT std_logic;
EMPTY : OUT std_logic;
ERROR : OUT std_logic;
PARKFREE : OUT signed(3 downto 0)
);
END COMPONENT;
--Inputs
signal A : std_logic := '0';
signal B : std_logic := '0';
signal WE : std_logic := '0';
signal reset : std_logic := '0';
signal clk : std_logic := '0';
signal DIN : signed(3 downto 0) := (others => '0');
--Outputs
signal FULL : std_logic;
signal EMPTY : std_logic;
signal ERROR : std_logic;
signal PARKFREE : signed(3 downto 0);
-- Clock period definitions
constant clk_period : time := 10 ns;
BEGIN
-- Instantiate the Unit Under Test (UUT)
uut: Module_1 PORT MAP (
A => A,
B => B,
WE => WE,
reset => reset,
clk => clk,
DIN => DIN,
FULL => FULL,
EMPTY => EMPTY,
ERROR => ERROR,
PARKFREE => PARKFREE
);
-- Clock process definitions
clk_process :process
begin
clk <= '0';
wait for clk_period/2;
clk <= '1';
wait for clk_period/2;
end process;
-- Stimulus process
stim_proc: process
begin
-- hold reset state for 100 ns.
reset <= '1' ;
wait for 100 ns;
reset <= '0' ;
wait for clk_period*10;
-- insert stimulus here
A <= '1' ;
wait for clk_period*5;
B <= '1' ;
wait for clk_period*5;
A <= '0' ;
wait for clk_period*5;
B <= '0' ;
wait for clk_period*5;
B <= '1' ;
wait for clk_period*5;
A <= '1' ;
wait for clk_period*5;
B <= '0' ;
wait for clk_period*5;
A <= '0' ;
wait;
end process;
END;
I posted the whole code just in case i'm missing something in some part of it that i wouldn't think about. So , when i ISim it , with any "succesful" trigger of p3...
Referencing it again here:
p3: process(current_state,A,B)
begin
case current_state is
when s1 =>
if enter = '0' and A = '0' and empty_bf = '0' then
park_counter <= park_counter - 1;
free_park_counter <= free_park_counter + 1;
ERROR <= '0';
end if;
when s3 =>
if enter = '1' and B = '0' and full_bf = '0' then
park_counter <= park_counter + 1;
free_park_counter <= free_park_counter - 1;
ERROR <= '0';
end if;
when others =>
end case;
end process p3;
...the ISim says that in this part
"There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es)."
and proceeds to make Xs of some of the values after that part , although all of the signals have been initialized (at least the ones in this part)
The "park_counter <= park_counter + 1;" part works correctly in the simulation but the "free_park_counter <= free_park_counter -1;" doesn't. This completely baffles me as they are declared as the same type and are both initialized the same way , even with different values.
So what am i missing or even doing blatantly wrong? Any help will be incredibly appreciated. Only looking for the error , if you could please contain optimizations since i'm looking to learn through trial and error and thought and would like to struggle to make it better myself
In addition , please be patient with my responses since i log on 2 to 3 times per day. Thanks in advance
Your design is non-workable per Brian's answer. Your testbench causes the messages when going from s3 or s1 to s0 before the clock edge. free_park_counter goes to 'U's. (Once it gets U's it won't loop further, no events occur without a signal value change).
Your counters should be clocked to prevent combinatorial looping, plus they likely won't synthesize a clock usefully due to uneven combinatorial delays. Sensitivity lists should likewise be complete, if for no other reason than the intent is to make simulation match the synthesized result.
Looking at the result of your testbench:
(clickable)
We can compare that with the messages from the arithmetic operators found in the Synopsys package std_logic_arith:
../../../src/synopsys/std_logic_arith.vhdl:315:20:#350ns:(assertion warning): There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
../../../src/synopsys/std_logic_arith.vhdl:315:20:#350ns:(assertion warning): There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
../../../src/synopsys/std_logic_arith.vhdl:315:20:#550ns:(assertion warning): There is an 'U'|'X'|'W'|'Z'|'-' in an arithmetic operand, the result will be 'X'(es).
The signals displayed in the waveform are selected in order of importance and appearance a first pass selection and we immediately see we also get 'U's on free_park_counter as well as ERROR.
ERROR catches attention because you hadn't mentioned it previously. When asking 'where to the 'U' come from ?' it becomes apparent the issue is there are drivers on ERROR and free_park_counter in both processes p3 and max. The messages are a side effect.
Each process assigning a signal provides a driver. Signals with multiple drivers are either resolved or result in an error for non-resolved types.
The resolved value of free_park_counter with one or more elements having a metavalue will cause the diagnostic messages produced by package std_logic_arith. The 'U's in the waveform are caused by the resolution of the two drivers.
The difficulty your audience had in noticing the two drivers may be in part due to your strong insistence on focusing on process p3, which is not well specified. The title and focus of your question also seems a bit unclear. Without a Minimal Complete and Verifiable example there was also bound to be less scrutiny.
You might expect as a minimum to consolidate all the assignments to ERROR and free_park_counter into a single process. ERROR should likely be registered, and I'd expect something named park_counter would likely want to be registered, too.
There is some confusion in the question title : declaring a signal and setting its value are entirely separate.
Initialising a signal (in the declaration) will influence its value, but not fully determine it. If the initialisation and another driving value are different, the result probably will be 'X'. Likewise if the signal is driven from different processes which disagree on its value.
Now, you are using a multiple-process form of state machine, where the operations are split between clocked and combinational processes. These are recommended by more than one textbook. This is unfortunate because they are notoriously difficult to get right, and for example, a moment's inspection will show that the sensitivity list on process P3 is wrong.
Fixing P3's sensitivity list may not affect the problem, because P3 also drives its own inputs in what is known as a combinational loop. Consider that, if the process wakes up several times because of glitches on the combinational inputs in its sensitivity list, the additions will take place several times...
Rewriting these three processes in the form of a single clocked process P1, (which is, unfortunately, not well taught in several textbooks) will avoid all of these difficulties.
In ISim, if you browse the tree menu on the left you are able to add to then signals window any internal signal you want. Add all of them, rerun the simulation and look for the signals that have 'U'|'X'|'W'|'Z'|'-' values. This should give us a lead to track down the problem.
If you are really new to VHDL, this answer of mine should help you undersand some of the basic concepts of this description language :)
VHDL - iSIM output uninitialised, doesn't change states
Another advice that I learned the hard way, but you can think about it after we solved this problem: textbooks and even Xilinx describe how to implement finite state machines with two or even three distinct processes. This comes from an educational approach where FSM are splitted in synchronous logic and asynchronous logic. In practice, this is doing more harm than good: most of the FSM can be described with a single synchronous process. Google it (or if you are interested we can talk about it) and try it, you will get the hang of it really quickly and it will really simplify the code (you won't even need two separate signals for the states anymore!).

Programming Altera DE2 for displaying colors on LCM in VHDL

Hi, i'm coding the main program structure for my LCM, called DE2_LCM2(in vhdl).
Within the main structure, there is a clock divider calls PLL2 (in verilog) and a I2S_LCM_Config (in verilog).
My PLL2.v and I2S_LCM.v are given by vendor, except for my DE2_LCM.vhd, myself coded. Compile successful, but stimulation failed.
FYI:
Horizontal scan:
1 Horizontal Line, there are 1171 counts or cycles of DCLK. The LCM_HSYNC goes low during falling edge of DCLK for 1 cycle. For the first 152 cycle, the data on LCM_DATA bus are invalid, start valid from cycle 153 to 1112, and invalid from cycle 1112 to 1171.
Vertical scan (Non-interlace):
After the last cycle of a horizontal line, the vertical counter shall be incremented by one. This LCM got 262 vertical lines in total, but only line 15 to (15+240)=255 is displayed.
LCM_PLL.v:
This file helps to convert system clock 50MHz to 18.42MHz. the DCLK or LCM_DCLK will be used for horizontal and vertical counter.
Below is my DE2_LCM.vhd codes, can't find what is going wrong on my code. Some more my teacher is on leave.
library ieee;
use ieee.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
entity DE2_LCM2 is port(CLOCK_50 : in std_logic;
KEY0 : in std_logic;
SW : in std_logic_vector(1 downto 0);
LCM_DATA : out std_logic_vector(7 downto 0);
LCM_DCLK, LCM_HSYNC, LCM_VSYNC,LCM_SCLK,LCM_SDAT,LCM_SCEN,LCM_GRST,LCM_SHDB : out std_logic
);
end DE2_LCM2;
architecture rtl of DE2_LCM2 is
constant H_SYNC_CYC: integer:=1;
constant H_SYNC_BACK: integer:=152;
constant H_SYNC_ACT: integer:=960;
constant H_SYNC_FRONT: integer:=59;
constant H_SYNC_TOTAL: integer:=1171;
constant V_SYNC_CYC: integer:=1;
constant V_SYNC_BACK: integer:=14;
constant V_SYNC_ACT: integer:=240;
constant V_SYNC_FRONT: integer:=8;
constant V_SYNC_TOTAL: integer:=262;
signal H_Cont: std_logic_vector(10 downto 0);
signal V_Cont: std_logic_vector(10 downto 0);
signal MOD_CNT: std_logic_vector(1 downto 0);
signal Tmp_DATA1: std_logic_vector(11 downto 0);
signal CLK_18: std_logic;
signal mSEL: std_logic_vector(1 downto 0);
signal iRST_N: std_logic;
signal I2S_SDAT: std_logic;
component LCM_PLL2 port(inclk0: in std_logic;
c0: out std_logic);
end component;
component I2S_LCM_Config is port(iCLK: in std_logic;
iRST_N: in std_logic;
I2S_SCLK: out std_logic;
I2S_SDAT: inout std_logic;
I2S_SCEN: out std_logic);
end component;
begin
LCM_GRST<=KEY0;
LCM_DCLK<=not(CLK_18);
LCM_SHDB<='1';
iRST_N<=KEY0;
LCM_SDAT<=I2S_SDAT; --add on
process(SW,MOD_CNT )
begin
if(SW="00")then
if(MOD_CNT="00")then
LCM_DATA<="01111111";
else LCM_DATA<="00000000";
end if;
elsif(SW="01")then
if(MOD_CNT="01")then
LCM_DATA<="01111111";
else LCM_DATA<="00000000";
end if;
elsif(SW="10")then
if(MOD_CNT="10")then
LCM_DATA<="01111111";
else LCM_DATA<="00000000";
end if;
else LCM_DATA<="00000000";
end if;
end process;
u0:LCM_PLL2 port map(inclk0=>CLOCK_50,
c0=>CLK_18);
u1:I2S_LCM_Config port map(iCLK=>CLOCK_50,
iRST_N=>KEY0,
I2S_SCLK=>LCM_SCLK,
I2S_SDAT=>I2S_SDAT,
I2S_SCEN=>LCM_SCEN);
process(CLK_18,iRST_N)
begin
if(rising_edge(CLK_18))then
if iRST_N = '0'then
MOD_CNT <= "11";
H_Cont <= "00000000000";
LCM_HSYNC <= '0';
V_Cont <= "00000000000";
LCM_VSYNC <= '0';
else
if((H_Cont >= H_SYNC_BACK) and (H_Cont<(H_SYNC_TOTAL-H_SYNC_FRONT)))then
if(MOD_CNT < "10") then
MOD_CNT <= MOD_CNT + '1';
else
MOD_CNT <= "00";
end if;
else MOD_CNT <= "11";
end if;
if(H_Cont < (H_SYNC_TOTAL-1)) then
H_Cont <= H_Cont + '1';
else H_cont <= "00000000000";
end if;
if(H_Cont < H_SYNC_CYC)then
LCM_HSYNC <= '0';
else LCM_HSYNC <= '1';
end if;
if(V_Cont <(V_SYNC_TOTAL-1)) then
V_Cont <= V_Cont+'1';
else V_Cont <= "00000000000";
end if;
if(V_Cont < V_SYNC_CYC) then
LCM_VSYNC <= '0';
else LCM_VSYNC <= '1';
end if;
end if;
end if;
end process;
end rtl;
Should be my coding style that is not suitable for hardware programming. Do let me know if PLL2.v and I2S_LCM_Config.v are needed for your testing. I'll send u through email.
Thanks in advance:)
Without checking your PLL or I2C, the vertical counter appears to be counting clocks and not lines:
There needs to be an additional qualifier to only increment V_cont when H_Cont is the maximum count (1170).
Something along the lines of:
if H_Cont = std_logic_vector (to_unsigned (H_SYNC_TOTAL-1,11)) then
if V_Cont < std_logic_vector(to_unsigned (V_SYNC_TOTAL-1, 11)) then
V_Cont <= std_logic_vector(unsigned(V_Cont) + 1);
else
V_Cont <= (others => '0');
end if;
end if;
(Ya, I used package numeric_std, sue me. Reformatted the heck out of your code to make it readable too).
And that gives you something that looks more reasonable (but hasn't really been checked, after all it's your design):
And the next Vertical event:
I also don't see any reason you couldn't use range constrained integers for H_Cont and V_Cont.
addendum
Because the answer caused confusion:
sorry, to be frank, i do understand what r u trying to achieve but i
dont understand your codes. – user317130 13 hours ago
I figured I'd redo the solution using the Synopsys version of std_logic packages. It makes the changes simpler and easier to see.
First, I created a CLOCK process that generated CLK_18 locally. This could have been in the test bench and simply driving CLK_18 with CLK_50, I didn't want any name confusion. I also commented out the I2C and PLL as being not supplied/uninvolved:
signal CLK_18: std_logic := '0'; -- default value to allow not in CLOCK process to run
Removing the unsupplied components:
-- component LCM_PLL2 port(inclk0: in std_logic;
-- c0: out std_logic);
-- end component;
--
-- component I2S_LCM_Config is port(iCLK: in std_logic;
-- iRST_N: in std_logic;
-- I2S_SCLK: out std_logic;
-- I2S_SDAT: inout std_logic;
-- I2S_SCEN: out std_logic);
-- end component;
And:
--
-- u0:LCM_PLL2 port map(inclk0=>CLOCK_50,
-- c0=>CLK_18);
-- u1:I2S_LCM_Config port map(iCLK=>CLOCK_50,
-- iRST_N=>KEY0,
-- I2S_SCLK=>LCM_SCLK,
-- I2S_SDAT=>I2S_SDAT,
-- I2S_SCEN=>LCM_SCEN);
And yes that leaves some signals undriven. We'll drive CLK_18 locally:
-- Dummy up CLK_18:
CLOCK:
process
begin
wait for 27.15 ns;
CLK_18 <= not CLK_18;
if Now > 80 ms then
wait;
end if;
end process;
-- Here instead of the test bench, could have jumpered CLOCK_50 to CLK_18
80 ms was rather excessive (a simulation will run until no events occur, everything is driven off the clock). Took a substantial length of time to simulate and the waveform dump was big (32 MB). It can be pared in half at least.
The change in operating the vertical counter is a bit more obvious using Synopsys standard logic libraries:
if H_Cont = H_SYNC_TOTAL - 1 then
if(V_Cont <(V_SYNC_TOTAL-1)) then
V_Cont <= V_Cont+'1';
else V_Cont <= "00000000000";
end if;
end if;
It consists of only operating the V_Cont counter in the last count of H_Cont so the counter only operates once per scan line.
The added test bench:
library ieee;
use ieee.std_logic_1164.all;
entity LCM_TB is
end entity;
architecture foo of LCM_TB is
signal CLOCK_50: std_logic := 'H';
signal KEY0: std_logic := '0';
signal SW: std_logic_vector(1 downto 0) := "11";
signal LCM_DATA: std_logic_vector(7 downto 0);
signal LCM_DCLK,
LCM_HSYNC,
LCM_VSYNC,
LCM_SCLK,
LCM_SDAT,
LCM_SCEN,
LCM_GRST,
LCM_SHDB: std_logic;
begin
-- CLOCK process found in DUT
DUT:
entity work.de2_lcm2
port map (
CLOCK_50 => CLOCK_50,
KEY0 => KEY0,
SW => SW,
LCM_DATA => LCM_DATA,
LCM_DCLK => LCM_DCLK,
LCM_HSYNC => LCM_HSYNC,
LCM_VSYNC => LCM_VSYNC,
LCM_SCLK => LCM_SCLK,
LCM_SDAT => LCM_SDAT,
LCM_SCEN => LCM_SCEN,
LCM_GRST => LCM_GRST,
LCM_SHDB => LCM_SHDB
);
STIMULUS: -- Just a reset
process
begin
wait for 100 ns;
KEY0 <= '1';
wait;
end process;
end architecture;
The build process:
ghdl -a --ieee=synopsys -fexplicit de2_lcm2.vhdl
ghdl -e --ieee=synopsys -fexplicit lcm_tb
ghdl -r lcm_tb --wave=lcm_tb.ghw
And because this is a Mac open *.ghw, or after establishing a save file open *.gtkw.
(OS X claims suffixes like Windows, the open command tells it to...).
And all this gives the same answer as the version using package numeric_std:
From the horizontal scroll bar in GTKWave you can see the simulation was twice as long as needed.
And instead of using std_logic_vector values you could have used unsigned with IEEE standard compliant package numeric_std with some slight modifications or converted H_Cont and V_Cont to range constrained integers (which will synthesize just fine), not forgetting to convert "00000000000" to 0 and ... + '1' to + 1 where appropriate.
I would have gotten back quicker but am in timezone GMT-12 (It's tomorrow here).

Uart Vhdl, simulation is ok but in fpga not work

I write simple vhdl code for Uart receiver.
Simulation (iSIM) is fine but when implemented I have wrong reading behavior.
When synthetized ISE tell me there are latches on state machine end on data_fill(x).
have you any suggestion.
thanks in advance
gian
here the code
library ieee;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_UNSIGNED.all;
entity rx_uart is
port (
clk : in STD_LOGIC;
rst : in STD_LOGIC;
rx_data : in STD_LOGIC;
data_out: out STD_LOGIC_VECTOR(7 downto 0)
);
end rx_uart;
architecture fizzim of rx_uart is
-- state bits
subtype state_type is STD_LOGIC_VECTOR(2 downto 0);
constant idle: state_type:="000"; -- receive_en=0 load_en=0 cnt_en=0
constant receive: state_type:="101"; -- receive_en=1 load_en=0 cnt_en=1
constant stop_load: state_type:="010"; -- receive_en=0 load_en=1 cnt_en=0
signal state,nextstate: state_type;
signal cnt_en_internal: STD_LOGIC;
signal load_en_internal: STD_LOGIC;
signal receive_en_internal: STD_LOGIC;
signal count : integer range 0 to 54686:=0;
signal cnt_en : STD_LOGIC;
signal load_en : STD_LOGIC;
signal receive_en : STD_LOGIC;
signal data_fill : STD_LOGIC_VECTOR(9 downto 0);
-- comb always block
begin
COUNTER_EN : process(clk,rst,cnt_en) begin
if (rst ='1') then
count <= 0;
elsif rising_edge(clk) then
if (cnt_en ='1') then
count <= count+1;
else
count <= 0;
end if;
end if;
end process;
LOADER: process(clk,rst,load_en) begin
if (rst='1') then
data_out <= (others =>'0');
elsif (rising_edge(clk) and load_en='1')then
data_out <= data_fill(8 downto 1);
end if;
end process;
ASSIGNATION : process(clk,rst,receive_en) begin
if (rst ='1') then
data_fill <= (others =>'0');
elsif (receive_en='1') then
case count is
when 7812 =>
data_fill(1) <= rx_data;
when 13020 =>
data_fill(2) <= rx_data;
when 18228 =>
data_fill(3) <= rx_data;
when 23436 =>
data_fill(4) <= rx_data;
when 28664 =>
data_fill(5) <= rx_data;
when 33852 =>
data_fill(6) <= rx_data;
when 39060 =>
data_fill(7) <= rx_data;
when 44268 =>
data_fill(8) <= rx_data;
when 49476 =>
data_fill(9) <= rx_data;
when others =>
data_fill(0) <= '0';
end case;
end if;
end process;
COMB: process(state,clk,count,rst,rx_data) begin
case state is
when idle =>
if (rx_data='0') then
nextstate <= receive;
elsif (rx_data='1') then
nextstate <= idle;
end if;
when receive =>
if (count<=54685) then
nextstate <= receive;
elsif (count>54685) then
nextstate <= stop_load;
end if;
when stop_load =>
nextstate <= idle;
when others =>
end case;
end process;
-- Assign reg'd outputs to state bits
cnt_en_internal <= state(0);
load_en_internal <= state(1);
receive_en_internal <= state(2);
-- Port renames for vhdl
cnt_en <= cnt_en_internal;
load_en <= load_en_internal;
receive_en <= receive_en_internal;
-- sequential always block
FF: process(clk,rst,nextstate) begin
if (rst='1') then
state <= idle;
elsif (rising_edge(clk)) then
state <= nextstate;
end if;
end process;
end fizzim;
You need to understand when latches are generated. Latches are generated when you have an incomplete assignment in combinational logic. Your case statements are combinational. You do not completely assign all possibilities of your data signal and your state machine. When you have an incomplete assignment in a combinational process you will always generate a latch. Latches are bad!
Use your when others properly to assign all of your signals under all conditions. Your data_fill signal will always generate a latch because you don't handle all conditions for data 0:9 on all cases.
Read more about how to avoid latches in VHDL
Edit: It seems too that you don't consistently create sequential logic in VHDL. You need to be creating a clocked process or remove clk from your sensitivity list in a combinational process.
your design has several bad code sites besides your latch problem. I'll number them for better reference.
(1)
Xilinx XST won't recognize the implemented state machine as a FSM. See your XST report or the *.syr file. There won't be a FSM section. If XST finds no FSM it's not able to choose "the best" state encoding and optimize your FSM.
You should use an enum as a state-type and also initialize your state signal:
type t_state is (st_idle, st_receive, st_stop);
signal state : t_state := st_idle;
signal nextstate : t_state;
Your FSM process also needs default assignments (see Russell's explanation) like
nextstate <= state;
(2)
asynchronous resets are no good design practice and complicate timing closure calculations.
(3)
you are handling raw input signals from outside you FPGA without any timing information. to prevent meta stability problems place two D-flip-flops on the rx_data path. you should also add the async-reg and no-srl-extract attribute to these 2 registers to prevent XST optimizations
SIGNAL I_async : STD_LOGIC := '0';
SIGNAL I_sync : STD_LOGIC := '0';
-- Mark register "I_async" as asynchronous
ATTRIBUTE ASYNC_REG OF I_async : SIGNAL IS "TRUE";
-- Prevent XST from translating two FFs into SRL plus FF
ATTRIBUTE SHREG_EXTRACT OF I_async : SIGNAL IS "NO";
ATTRIBUTE SHREG_EXTRACT OF I_sync : SIGNAL IS "NO";
[...]
BEGIN
[...]
I_async <= In WHEN rising_edge(Clock);
I_sync <= I_async WHEN rising_edge(Clock);
Let 'In' be your asynchronous input. Now you can use I_sync in your clock domain. I choose to describe these 2 registers in a one-liner, you can also use a classic process :) The suffix '_async' allows you to define a matching timing rule in your *.xcf and *.ucf files.

Resources