nkk1987
nkk1987

Reputation: 1

vhdl error 827: signal <> cannot be synthesized

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

Answers (2)

pwolfsberger
pwolfsberger

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

Philippe
Philippe

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:

  • Write all of your code in one single synchronous process. This gives you less risk of errors related to combinational processes (like latches, incomplete sensitivity lists)
  • You are using ieee.numeric_std, which is good. You don't need ieee.std_logic_unsigned and ieee.std_logic_arith.
  • The sensitivity list of your last process should include sample and should not include resetN.

Upvotes: 1

Related Questions