Reputation: 1
I know that this question was asked before, but I believe that my issue is different. I'm trying to write code for UART receiver and get error 827. I'm quite new for VHDL and don't know what am I doing wrong. Can please someone help me figure it out?
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
use ieee.numeric_std.all;
entity RX_STATE_MACHINE is
port(rxD,DataAck,resetN,Clk_D: in std_logic;
Data: out std_logic_vector(7 downto 0);
DataRdy,ParityErr,StopErr: out std_logic);
end RX_STATE_MACHINE;
architecture Behavioral of RX_STATE_MACHINE is
type stateType is(st1,st2,st3,st4,st5,st6);
signal NS,PS :stateType := st1;
signal cnt : integer range 0 to 15 :=0;
signal sample: integer range 0 to 15;
begin
--Process for memmory system with asynchronic resetN
process(Clk_D,resetN)
begin
if (resetN='0') then
PS <= st1;
elsif rising_edge(Clk_D) then
PS <= NS;
end if;
end process;
--process that generating 16 steps counter
process(Clk_D)
begin
if rising_edge(Clk_D) then
cnt <= (cnt+1) mod(16);
end if;
end process;
process(rxD,cnt,DataAck,resetN,PS)
-- process(rxD,PS)
variable a: integer range 0 to 7;
variable dat: std_logic_vector(7 downto 0);
begin
sample <= (sample+1) mod(16);
case PS is
when st1 =>
if falling_edge(rxD) then
NS <= st2;
else
NS <= st1;--
end if;
when st2 =>
if (rxD='0') then
if (cnt=7) then
NS <= st3;
sample <= 0;
else
NS <= st2;
end if;
else
NS <= st1;
end if;
when st3 =>
if (a<8) then
if (sample=15) then
dat(a):=rxD;
a:=a+1;
end if;
NS <= st3;--
else
a:=0;
NS <= st4;
end if;
-- Data <= (dat(0),dat(1),dat(2),dat(3),dat(4),dat(5),dat(6),dat(7));
when st4 =>
if (sample=15) then
if((dat(0) xor dat(1) xor dat(2) xor dat(3) xor dat(4) xor dat(5) xor dat(6) xor dat(7))=rxD) then
ParityErr <= '0';
else
ParityErr <= '1';
end if;
NS <= st5;
else
NS <= st4;--
end if;
when st5 =>
if (sample=15) then
if(rxD='1') then
StopErr <= '0';
else
StopErr <= '1';
end if;
NS <= st6;
else
NS <= st5;--
end if;
when st6 =>
if rising_edge(DataAck) then
NS <= st1;
else
NS <= st6;--
end if;
end case;
end process;
end Behavioral;
Thank you!
Upvotes: 0
Views: 140
Reputation: 366
If you have not done so already, I would read this article by Xilinx: AR# 14047
The code you provided falls under the second example of a scenario that would cause this type of error.
The key point that you want to take away from this article is:
In order for XST to infer a synchronous element, the 'event VHDL attribute must be present in the topmost "IF" statement of your process.
The rising_edge()
and falling_edge()
functions both use the 'event' attribute of the passed in signal.
If Clk_D
is a fixed frequency faster then the transition speed of RxD
or DataAck
(e.g MHz versus KHz), which, in the case of a UART bus, is probably true, then you could consider synchronizing those inputs to Clk_D
. This would allow you to make your FSM synchronous, which (IMO) is much easier to understand and debug.
I've created an example of what a synchronous FSM used to process UART recived data might look like:
process(clk_D, ResetN)
begin
if (resetN = '1') then
state <= S_IDLE;
elsif (rising_edge(clk_D)) then
rxD_s_d <= rxD_s;
case state is
when S_IDLE =>
cnt <= 0;
bit_cnt <= 0;
-- Wait for start bit.
if (rxD_s = '0' and rxD_s_d = '1') then -- falling edge detect
state <= S_WAIT8;
endif;
when S_WAIT8 =>
-- Wait 8 clock cycles after start bit detect
-- to align count to center of bit.
if (cnt = 8) then
state <= S_WAIT16;
cnt <= 0;
else
cnt <= cnt + 1;
end if;
when S_WAIT16 =>
-- Wait 16 clock cycles to align data to center of
-- next bit.
if (cnt = 16) then
state <= S_CAPTURE;
cnt <= 0;
else
cnt <= cnt + 1;
end if;
when S_CAPTURE =>
-- Shift in Rx data;
data <= data(6 downto 0) & rxD_s;
if (bit_cnt = 7) then
-- All 8 bits captured; we're done.
-- Could do stop bit detection instead of going
-- back to idle.
state <= S_IDLE;
else
bit_cnt <= bit_cnt + 1;
state <= S_WAIT16;
endif;
end case;
end if;
end process;
This example assumes that clk_D
is running 16 times faster then the UART baud rate. It uses a counter to try to center the sampling point of the received data line (synchronized to clk_D
) to avoid capturing rxD_s
at metastable states (transition edges). It also assumes no parity, which can easily be added.
Also I have not simulated this, but would suggest you do for a better understanding.
Upvotes: 0
Reputation: 3730
In synthesizable code, rising_edge can only be used to infer registers, for example:
process (clk, rst) is
begin
if rst = '1' then
-- reset code
elsif rising_edge(clk) then
-- actual code
end if;
end process;
You are passing a control signal (rather than a clock) as argument to the rising_edge function, and you use the rising_edge function in a case statement in your process. That will not synthesize.
To fix this: you can delay your control signal with one clock so that you can write:
if DataAck_d = '0' and DataAck = '1' then
Other tips:
ieee.numeric_std
, which is good. You don't need ieee.std_logic_unsigned
and ieee.std_logic_arith
.sample
and should not include resetN
.Upvotes: 1