cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Highlighted
Visitor
Visitor
681 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
670 Views
Registered: ‎03-15-2012

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
671 Views
Registered: ‎03-15-2012

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