UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Visitor juanfrias
Visitor
487 Views
Registered: ‎11-06-2018

Vivado Fails to synthesize Moore State Machine

Jump to solution

I´m working on a project about a PS2 keyboard interface to a computer. Since 5 days i´ve had an issue: the last module added to my project allways give´s this error: [Common 17-69] Command failed: Vivado Synthesis failed, and notthing else. No other information in the TCL console or Log files to identify where does the error comes from. I posted another post but nobody answered me.

Trying to fix this issue a created a new project with only one module, the only one that is giving me problems, and start comment parts of code and sinthesize, and repeate, and repeat. What I found is this:

In my normal code I have case statements inside rising_edge statement something like this :

 

case actual_state is
when lower_case => letter <= "000";
    if rising_edge(new_char) then
          case ps2_data is
                 when.......
          end case;
     end if;
when............... end when;

 

 If I remove the if statement the I don't get eny error, something like this:

 

case actual_state is
when lower_case => letter <= "000";
          case ps2_data is
                 when.......
          end case;
when............................
end case;

So, my question about that is Can I not put a case statement inside a rising_edge statement or a case statement inside a rising_edge statement?

 

Another peculiar thing is that the error only does not appear if I remove the piece of code that relate the actual state with the the next state. This is, if I remove if rising_edge clause, but not remove the piece of code that relate the actual state with the next state the error still appears. It only does not appear if a remove both pieces of code. To our better understanding this is my complete code, and I'll comment the piece of code that I Have to eliminate to avoid the error appears. The problem is in Output logic.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;


entity ps2_to_ascii is
    generic(    LShift : std_logic_vector(7 downto 0) := x"12";
                RShift : std_logic_vector(7 downto 0) := x"59";
                ALT : std_logic_vector(7 downto 0) := x"11";
                CTRL : std_logic_vector(7 downto 0) := x"14";
                CAPS : std_logic_vector(7 downto 0) := x"58";
                ESC : std_logic_vector(7 downto 0) := x"76";
                break : std_logic_vector(7 downto 0) := x"F0");
    Port (  ps2_data : in std_logic_vector(7 downto 0);
            ascii_data : out std_logic_vector(7 downto 0);
            ps2_code_new_in : in std_logic;
            char_new : out std_logic);
end ps2_to_ascii;

architecture Behavioral of ps2_to_ascii is
type key_states is (lower_case, shift_state, caps_state,ctrl_state, ignore_break, ignore_shift_break, ignore_caps_break, ignore_ctrl_break);

signal new_char : std_logic := '0';
signal caps_num : integer range 0 to 3 := 0;
signal letter : std_logic_vector(2 downto 0) := "000";
signal next_state : key_states := lower_case;
signal actual_state : key_states := lower_case;

begin
------------------------------------------------------------------------------------------------------------------
------------------------------next state logic----------------------------------------------------------
process(ps2_code_new_in, ps2_data, actual_state, caps_num)
begin
new_char <= '0';

case actual_state is
when lower_case =>
    if rising_edge(ps2_code_new_in) then
        if ps2_data = LShift or ps2_data = RShift then
            next_state <= shift_state;
        elsif ps2_data = CAPS then
            next_state <= caps_state;
            caps_num <= 3;
        elsif ps2_data = CTRL then
            next_state <= ctrl_state;
        elsif ps2_data = break then
            next_state <= ignore_break;
        else
            next_state<= lower_case;
            new_char <= '1';
        end if;
    end if;
when shift_state =>
    if rising_edge(ps2_code_new_in) then
        if ps2_data = break then
            next_state <= ignore_shift_break;
        elsif ps2_data = RShift or ps2_data = LShift or ps2_data = CTRL or ps2_data = CAPS then
            next_state <= shift_state;
        else
            next_state <= shift_state;
            new_char <= '1';
        end if;
    end if;
when ignore_shift_break =>
    if rising_edge(ps2_code_new_in) then
        if ps2_data = RShift or ps2_data = LShift then
            next_state <= lower_case;
        else
            next_state <= shift_state;
        end if;
    end if;
when caps_state =>
    if caps_num = 0 then
        next_state <= lower_case;
    elsif rising_edge(ps2_code_new_in) then
        if ps2_data = break then
            next_state <= ignore_caps_break;
        elsif ps2_data = CAPS then
            next_state <= caps_state;
            caps_num <= caps_num - 1;
        elsif ps2_data = RShift or ps2_data = LShift or ps2_data = CTRL then
            next_state <= caps_state;
        else
            next_state <= caps_state;
            new_char <= '1';
        end if;
    end if;
when ignore_caps_break =>
    if rising_edge(ps2_code_new_in) then
        if ps2_data = CAPS then
            next_state <= caps_state;
            caps_num <= caps_num - 1;
        else
            next_state <= caps_state;
        end if;
    end if;
when ctrl_state =>
    if rising_edge(ps2_code_new_in) then
        if ps2_data = break then
            next_state <= ignore_ctrl_break;
        elsif ps2_data = RShift or ps2_data = LShift or ps2_data = CAPS or ps2_data = CTRL then
            next_state <= ctrl_state;
        else
            next_state <= ctrl_state;
            new_char <= '1';
        end if;
    end if;
when ignore_ctrl_break =>
    if rising_edge(ps2_code_new_in) then
        if ps2_data = CTRL then
            next_state <= lower_case;
        else
            next_state <= ctrl_state;
        end if;
    end if;
when ignore_break =>
    if rising_edge(ps2_code_new_in) then
        next_state <= lower_case;
    end if;
end case;
end process;
-----------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------
----------------------------------Output logic--------------------------------------------------------------
process(actual_state, new_char)
begin
case actual_state is
when lower_case => letter <= "000";
--    if rising_edge(new_char) then
            case ps2_data is
            when x"1C" =>           --a
                ascii_data <= x"61";
            when others =>
                ascii_data <= x"DB";        --null
            end case;
--    end if;

when shift_state => letter <= "001";
--    if rising_edge( new_char) then
       case ps2_data is
            when x"1C" =>           --A
                ascii_data <= x"41";
            when others =>          --null
                ascii_data <= x"DB";
            end case;
--            end if;

when caps_state => letter <= "010";
--    if rising_edge(new_char) then
       case ps2_data is
     when x"1C" =>           --A
         ascii_data <= x"41";
        when others =>
            ascii_data <= x"DB";        --null
        end case;
--        end if;

when ctrl_state => letter <= "011";
--if rising_edge(new_char) then
        case ps2_data is
        when x"3B" =>               --j
            ascii_data <= x"0A";
        when x"3A" =>               --m
            ascii_data <= x"0A";b
            ascii_data <= x"09";
         when x"76" =>           --esc
            ascii_data <= x"1B";
         when x"66" =>           --backspace
            ascii_data <= x"08";
         when others =>
            ascii_data <= x"00";
        end case;
--end if;
when others => letter <= "111";
--    if rising_edge(new_char) then
        ascii_data <= x"00";
--    end if;
end case;
end process;

--actual_state <= next_state;
char_new <= new_char;

end Behavioral;

 

<Note: I eliminate some when clauses to limitate the size of the code (for understanding)>

0 Kudos
1 Solution

Accepted Solutions
Highlighted
Adventurer
Adventurer
476 Views
Registered: ‎03-15-2012

Re: Vivado Fails to synthesize Moore State Machine

Jump to solution

hi,

sorry to say, but this is bad coding style which is not supported by (i think) any tools. There are 2 types of logic, synchronous and combinational. And you cannot mix them (as you did).

For every process, you have to decide, if you need a synchronous (with clock) or a combinational (without) process.

1. If you have one with clock, then everything (except an async reset) has to be inside ONE (!!!)

if rising_edge(clk) then
... end if;

First a case statement and inside that a rising_edge is not allowed (how should that be created as hardware? can draw a schematic for that?)

2. If you have a process without a clock, then check that no latches are created (missing assignment in at least one path).

3. "new_char" is NOT a clock, therefore belongs not inside a rising_edge condition. For that you need a one clock stobe signal (which in general you will get, when you use a "edge-detection" code template).

 

PS: The rising_edge function is not meant to be used for edge detection. It is used for defining, which signal a clock is and therefore be connected to the clock-input of a sequential primitive.

View solution in original post

1 Reply
Highlighted
Adventurer
Adventurer
477 Views
Registered: ‎03-15-2012

Re: Vivado Fails to synthesize Moore State Machine

Jump to solution

hi,

sorry to say, but this is bad coding style which is not supported by (i think) any tools. There are 2 types of logic, synchronous and combinational. And you cannot mix them (as you did).

For every process, you have to decide, if you need a synchronous (with clock) or a combinational (without) process.

1. If you have one with clock, then everything (except an async reset) has to be inside ONE (!!!)

if rising_edge(clk) then
... end if;

First a case statement and inside that a rising_edge is not allowed (how should that be created as hardware? can draw a schematic for that?)

2. If you have a process without a clock, then check that no latches are created (missing assignment in at least one path).

3. "new_char" is NOT a clock, therefore belongs not inside a rising_edge condition. For that you need a one clock stobe signal (which in general you will get, when you use a "edge-detection" code template).

 

PS: The rising_edge function is not meant to be used for edge detection. It is used for defining, which signal a clock is and therefore be connected to the clock-input of a sequential primitive.

View solution in original post