VHDL 代码中的额外变量赋值使其无法工作并出现错误 "can't infer register" 和 "couldn't implement registers"
Extra variable assignment in VHDL code makes it not work and get error "can't infer register" and "couldn't implement registers"
每当我在我的进程中得到额外的 "i2c_send_flag<='1';" 行时,我都会在下面的代码中遇到错误。
我不明白为什么代码在我添加此行之前有效,而在我添加它之后停止工作。
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;
当我取消注释 If 语句中代码的最后一部分时,出现以下错误:
- 错误 (10821):MAIN.vhd(304) 处的 HDL 错误:无法推断 "i2c_send_flag" 的寄存器,因为它的行为不匹配任何支持的寄存器模型
- 错误 (10822):MAIN.vhd(298) 处的 HDL 错误:无法在该时钟边沿实现用于分配的寄存器
我无法理解为什么当我再次添加这段代码(我在下面的 "Elsif" 中使用它并起作用)时它会失败。
一般来说,为了让综合工具满意,每个进程需要一个时钟,并且时钟语句中没有逻辑。应用于您的代码,需要将其重组为:
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;
每当我在我的进程中得到额外的 "i2c_send_flag<='1';" 行时,我都会在下面的代码中遇到错误。
我不明白为什么代码在我添加此行之前有效,而在我添加它之后停止工作。
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;
当我取消注释 If 语句中代码的最后一部分时,出现以下错误:
- 错误 (10821):MAIN.vhd(304) 处的 HDL 错误:无法推断 "i2c_send_flag" 的寄存器,因为它的行为不匹配任何支持的寄存器模型
- 错误 (10822):MAIN.vhd(298) 处的 HDL 错误:无法在该时钟边沿实现用于分配的寄存器
我无法理解为什么当我再次添加这段代码(我在下面的 "Elsif" 中使用它并起作用)时它会失败。
一般来说,为了让综合工具满意,每个进程需要一个时钟,并且时钟语句中没有逻辑。应用于您的代码,需要将其重组为:
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;