Search code examples
vhdlquartussynthesis

Extra variable assignment in VHDL code makes it not work and get error "can't infer register" and "couldn't implement registers"


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.


Solution

  • 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;