0

I am facing a error in the code below every time I got an extra "i2c_send_flag<='1';" line inside my process.

I don't understand why the code works before I add this line and stop working after I add it.

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;

ENTITY MAIN IS
    PORT(
        PIN_CLOCK_50MHZ : IN std_logic;
        PIN_KEY             : IN std_logic_vector (3 downto 0); 
        LEDR                : OUT std_logic_vector (17 downto 0):="000000000000000000";
        LEDG                : OUT std_logic_vector (8 downto 0):="000000000";
        PIN_SW            : IN std_logic_vector (2 downto 0); 
        PIN_I2C_SCLK        : OUT std_logic;
        PIN_I2C_SDA         : INOUT std_logic;
        PIN_MCLK                : OUT std_logic;    
        PIN_BCLK                : OUT std_logic;    
        PIN_ADC_DATA        : IN std_logic; 
        PIN_ADC_LRCK        : OUT std_logic;                                                                                
        PIN_DAC_DATA        : OUT std_logic;    
        PIN_DAC_LRCK        : OUT std_logic                                         
    );
END MAIN;

ARCHITECTURE main OF MAIN IS

    SIGNAL i2c_busy      : std_logic;
    SIGNAL i2c_send_flag : std_logic;
    SIGNAL i2c_data      : std_logic_vector(15 downto 0);
    SIGNAL i2c_done     : std_logic;
    SIGNAL clock_12mhz      : std_logic;
    SIGNAL clock_2m4hz          : std_logic;
    SIGNAL clock_100hz      : std_logic;
    SIGNAL clock_6mhz           : std_logic;
    SIGNAL adc_dac_bclk     : std_logic;
    SIGNAL adc_data         : std_logic;
    SIGNAL adc_lrck         : std_logic;
    SIGNAL dac_data         : std_logic;
    SIGNAL dac_lrck         : std_logic;

    COMPONENT i2c IS
        PORT(
            I2C_CLOCK_12MHZ: IN std_logic                               :='0';
            I2C_DEVICE_ADDR: IN std_logic_vector (7 downto 0)   :="00000000";
            I2C_DATA            : IN std_logic_vector (15 downto 0) :="0000000000000000";

            I2C_START_FLAG  : IN std_logic                              :='0';
            I2C_BUSY            : OUT std_logic                         :='0';
            I2C_DONE            : OUT std_logic                         :='0';

            I2C_SCLK            : OUT std_logic                         :='1';
            I2C_SDA         : INOUT std_logic                           :='1'
        );
    END COMPONENT i2c;

    COMPONENT pll IS
        PORT (
            inclk0  : IN STD_LOGIC  := '0';
            c0          : OUT STD_LOGIC 
        );
    END COMPONENT pll;

    COMPONENT divclk_12M_2M4 IS
        PORT (
            clk_in   : IN std_logic;
            clk_out  : OUT std_logic
        );
    END COMPONENT divclk_12M_2M4;

    COMPONENT divclk_12M_100 IS
        PORT (
            clk_in   : IN std_logic;
            clk_out  : OUT std_logic
        );
    END COMPONENT divclk_12M_100;

    COMPONENT divclk_12M_6M IS
        PORT (
            clk_in   : IN std_logic;
            clk_out  : OUT std_logic
        );
    END COMPONENT divclk_12M_6M;    

    COMPONENT adc_dac_controller IS
        PORT(
            CTRL_BCLK       :  IN std_logic;

            CTRL_ADC_DATA   :  IN  std_logic;
            CTRL_ADC_LRCK   :  OUT std_logic;

            CTRL_DAC_DATA   :  OUT std_logic;
            CTRL_DAC_LRCK   :  OUT std_logic
        );
    END COMPONENT adc_dac_controller;

    BEGIN

            WM8731: COMPONENT i2c 
                            PORT MAP(
                                I2C_CLOCK_12MHZ=>   clock_12mhz,
                                I2C_DEVICE_ADDR=>   "00110100",
                                I2C_DATA            =>  i2c_data,

                                I2C_START_FLAG  =>  i2c_send_flag,
                                I2C_BUSY            =>  i2c_busy,

                                I2C_DONE            =>  i2c_done,

                                I2C_SCLK            =>  PIN_I2C_SCLK,
                                I2C_SDA         =>  PIN_I2C_SDA 
                            );  
            PLL12:  COMPONENT pll 
                            PORT MAP(
                                inclk0          =>  PIN_CLOCK_50MHZ,
                                c0                  =>  clock_12mhz 
                            );

            Divclk_2M4Hz:   COMPONENT divclk_12M_2M4 
                                    PORT MAP(
                                        clk_in  =>  clock_12mhz,
                                        clk_out =>  clock_2m4hz
                                    );                                              
            Divclk_6MHz:    COMPONENT divclk_12M_6M 
                                    PORT MAP(
                                        clk_in  =>  clock_12mhz,
                                        clk_out =>  clock_6mhz
                                    );                              
            Divclk_100Hz:   COMPONENT divclk_12M_100 
                                    PORT MAP(
                                        clk_in  =>  clock_12mhz,
                                        clk_out =>  clock_100hz
                                    );                                              

            adc_dac_ctrl:   COMPONENT adc_dac_controller
                                    PORT MAP(

                                        CTRL_BCLK       => clock_12mhz,


                                        CTRL_ADC_DATA   => adc_data,
                                        CTRL_ADC_LRCK   => adc_lrck,

                                        CTRL_DAC_DATA   => dac_data,
                                        CTRL_DAC_LRCK   => dac_lrck
                                    );                                  


    PIN_MCLK        <= clock_12mhz;
    PIN_BCLK        <= clock_12mhz;
    adc_data        <= PIN_ADC_DATA;
    PIN_ADC_LRCK<= adc_lrck;
    PIN_DAC_DATA<= dac_data;
    PIN_DAC_LRCK<= dac_lrck;
    LEDG(7)     <= i2c_done;

    PROCESS (clock_100hz)
    BEGIN

        IF rising_edge (clock_100hz) THEN
            IF (PIN_KEY="1111") THEN
                 i2c_send_flag <='0';
            END IF;
        END IF;

        IF rising_edge(clock_100hz) AND i2c_busy='0' THEN

            IF (PIN_SW (0)='1' AND PIN_KEY(0)='0') THEN                             
                        i2c_data(15 downto 9)<="0000000";
                        i2c_data(8)<='0'; 
                        i2c_data(7)<='0';
                        i2c_data(6 downto 5)<="00";
                        i2c_data(4 downto 0)<="11111";
                        i2c_send_flag<='1'; 
                    ------------------------------------------------------
            ELSIF (PIN_SW (0)='1' AND PIN_KEY(1)='0') THEN
                        i2c_data(15 downto 9)<="0000001";
                        i2c_data(8)<='1';
                        i2c_data(7)<='0';
                        i2c_data(4 downto 0)<="11111";
                        i2c_send_flag<='1';
                    ------------------------------------------------------
            ELSIF (PIN_SW (0)='1' AND PIN_KEY(2)='0') THEN      
                        i2c_data(15 downto 9)<="0000010";
                        i2c_data(8)<='0';
                        i2c_data(7)<='1';
                        i2c_data(6 downto 0)<="1111000";
                        i2c_send_flag<='1';
            ELSIF (PIN_SW (0)='1' AND PIN_KEY(3)='0') THEN
                        i2c_data(15 downto 9)<="0000011";
                        i2c_data(8)<='1';
                        i2c_data(7)<='1'; 
                        i2c_data(6 downto 0)<="1111000";
                        i2c_send_flag<='1';             
            ELSIF (PIN_SW (1)='1' AND PIN_KEY(0)='0') THEN
                        i2c_data(15 downto 9)<="0000100";
                        i2c_data(8)<='0';                       
                        i2c_data(7 downto 6)<="11";
                        i2c_data(5)<='0'; 
                        i2c_data(4)<='1'; 
                        i2c_data(3)<='0';
                        i2c_data(2)<='0';
                        i2c_data(1)<='1';
                        i2c_data(0)<='0';
                        i2c_send_flag<='1';
            ELSIF (PIN_SW (1)='1' AND PIN_KEY(1)='0') THEN
                        i2c_data(15 downto 9)<="0000101";
                        i2c_data(8 downto 5)<="0000";   
                        i2c_data(4)<='0'; 
                        i2c_data(3)<='0'; 
                        i2c_data(2 downto 1)<="11";
                        i2c_data(0)<='0'; 
                        i2c_send_flag<='1';                             
            ELSIF (PIN_SW (1)='1' AND PIN_KEY(2)='0') THEN
                        i2c_data(15 downto 9)<="0000110";
                        i2c_data(8)<='0';
                        i2c_data(7)<='0';
                        i2c_data(6)<='1';
                        i2c_data(5)<='1';
                        i2c_data(4)<='0';
                        i2c_data(3)<='0';
                        i2c_data(2)<='0'; 
                        i2c_data(1)<='1'; 
                        i2c_data(0)<='0';
                        i2c_send_flag<='1';                             
            ELSIF (PIN_SW (1)='1' AND PIN_KEY(3)='0') THEN
                        i2c_data(15 downto 9)<="0000111";
                        i2c_data(8)<='0';
                        i2c_data(7)<='0';
                        i2c_data(6)<='0';
                        i2c_data(5)<='0';
                        i2c_data(4)<='1';
                        i2c_data(3 downto 2)<="00";
                        i2c_data(1 downto 0)<="10";
                        i2c_send_flag<='1';                         
            ELSIF (PIN_SW (2)='1' AND PIN_KEY(0)='0') THEN
                        i2c_data(15 downto 9)<="0001000";
                        i2c_data(8)<='0';
                        i2c_data(7)<='0';
                        i2c_data(6)<='0';
                        i2c_data(5 downto 2)<="0000";
                        i2c_data(1)<='0'; 
                        i2c_data(0)<='1';
                        i2c_send_flag<='1';                         
            ELSIF (PIN_SW (2)='1' AND PIN_KEY(1)='0') THEN
                        i2c_data(15 downto 9)<="0001001"; 
                        i2c_data(8 downto 1)<="00000000";
                        i2c_data(0)<='1';
                        i2c_send_flag<='1';         
--          ELSIF (PIN_SW (2)='1' AND PIN_KEY(3)='0') THEN
--                      i2c_data(15 downto 9)<="0001111";
--                      i2c_data(8 downto 0)<="000000000";
--                      i2c_data(15 downto 0)<="0001111000000000";
--                      i2c_send_flag<='1';
            END IF;

        END IF;
    END PROCESS;

END main;

When I Uncomment the last part of code in the If statment I get the following erros:

  • Error (10821): HDL error at MAIN.vhd(304): can't infer register for "i2c_send_flag" because its behavior does not match any supported register model
  • Error (10822): HDL error at MAIN.vhd(298): couldn't implement registers for assignments on this clock edge

I can't understand why this piecce of code (which i use in the "Elsif" below and work) fail when I added it one more time.

4
  • It appears you want to have all assignments to i2c_send_flag inside the same if statement with an edge event condition. Commented May 31, 2020 at 22:07
  • See [HELP] VHDL "cant infer register.". Commented May 31, 2020 at 22:17
  • What do you mean by "works"? Compiles and simulates correctly? Synthesizes without warning? Synthesizes and works in the lab? Note only the last one counts. Commented Jun 1, 2020 at 15:24
  • @naguall did you try the suggestion below? Commented Jun 3, 2020 at 16:30

1 Answer 1

1

Generally speaking to make the synthesis tools happy, you need one clock per process and no logic in the clock statement. Applied to your code it would need to be restructured as:

PROCESS (clock_100hz)
BEGIN

    IF rising_edge (clock_100hz) THEN
        IF (PIN_KEY="1111") THEN
             i2c_send_flag <='0';
        END IF;
        if i2c_busy='0' THEN

          IF (PIN_SW (0)='1' AND PIN_KEY(0)='0') THEN                             
                    i2c_data(15 downto 9)<="0000000";
                    i2c_data(8)<='0'; 
                    i2c_data(7)<='0';
                    i2c_data(6 downto 5)<="00";
                    i2c_data(4 downto 0)<="11111";
                    i2c_send_flag<='1'; 
                ------------------------------------------------------
          ELSIF (PIN_SW (0)='1' AND PIN_KEY(1)='0') THEN
                    i2c_data(15 downto 9)<="0000001";
                    i2c_data(8)<='1';
                    i2c_data(7)<='0';
                    i2c_data(4 downto 0)<="11111";
                    i2c_send_flag<='1';
          ELSIF ...
                ...
          END IF;
        END IF;
      END IF;
Sign up to request clarification or add additional context in comments.

2 Comments

This of course does not explain why adding the extra code caused it issues. However tools are known to have issues when there are multiple "rising_edge" in a single process - so this is a good starting point. The only thing I can see in the code that is different in this "ELSIF" than the others is the extra assignment to all of the bits of i2c_data and this has nothing to do with i2c_send_flag
Thanks a lot @Jim Louis, it works perfectly with that modification.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.