📄 i2c_iir.vhd
字号:
LIBRARY ieee;USE ieee.std_logic_1164.ALL;USE ieee.std_logic_arith.ALL;USE ieee.std_logic_unsigned.ALL;ENTITY i2c_iir IS GENERIC ( fa_wid : integer := 8 ); PORT ( scl : IN STD_LOGIC; datain : IN STD_LOGIC_VECTOR (7 DOWNTO 0); i_coef : OUT STD_LOGIC_VECTOR (15 DOWNTO 0); q_coef : OUT STD_LOGIC_VECTOR (15 DOWNTO 0); fa_w : OUT STD_LOGIC_VECTOR (fa_wid-1 DOWNTO 0); out_en : OUT STD_LOGIC; sda : INOUT STD_LOGIC );END i2c_iir;ARCHITECTURE ach OF i2c_iir IS TYPE state_type IS (IDLE, HEADER, ACK_HEADER, RX_DATA,ACK_DATA,--RX_ADD,ACK_ADD, TX_DATA, WAIT_ACK); SIGNAL state : state_type; SIGNAL start_flg : STD_LOGIC := '0'; -- sign of judgement for start, '1' is start SIGNAL stop_flg : STD_LOGIC := '0'; -- sign of judgement for stop, '1' is stop SIGNAL bit_num : STD_LOGIC_VECTOR (3 DOWNTO 0) := "0000"; --SIGNAL add_num : STD_LOGIC_VECTOR (4 DOWNTO 0) := "00000"; SIGNAL bit_cnt_en : STD_LOGIC; SIGNAL bit_cnt_ld : STD_LOGIC; SIGNAL i2c_header_ld : STD_LOGIC; SIGNAL ctr_byte : STD_LOGIC_VECTOR (7 DOWNTO 0) := "11111111"; --SIGNAL lut_add : STD_LOGIC_VECTOR (15 DOWNTO 0); --SIGNAL dreg_en : STD_LOGIC; --SIGNAL dreg_ld : STD_LOGIC; SIGNAL byte_cnt_ld : STD_LOGIC := '0'; SIGNAL byte_num : STD_LOGIC_VECTOR (2 DOWNTO 0); SIGNAL data_rec : STD_LOGIC_VECTOR (31 DOWNTO 0); SIGNAL ds_out : STD_LOGIC_VECTOR (7 DOWNTO 0); BEGIN start:PROCESS(sda,start_flg) BEGIN IF (sda'EVENT AND sda = '0') THEN IF (scl = '1') THEN start_flg <= '1'; ELSE start_flg <= '0'; END IF; END IF; END PROCESS start; stop:PROCESS(sda,start_flg) BEGIN IF (start_flg = '1') THEN stop_flg <= '0'; ELSIF (sda'EVENT AND sda = '1') THEN IF (scl = '1') THEN stop_flg <= '1'; ELSE stop_flg <= '0'; END IF; END IF; END PROCESS stop; sm: PROCESS (scl,stop_flg) BEGIN IF (stop_flg = '1') THEN state <= IDLE; ELSIF (scl'EVENT and scl = '0') THEN CASE state IS ------------- IDLE STATE ------------- WHEN IDLE => IF (start_flg = '1') THEN state <= HEADER; END IF; ------------- HEADER STATE ------------- WHEN HEADER => IF (bit_num = 8) THEN state <= ACK_HEADER; END IF; ------------- ACK_HEADER STATE ------------- WHEN ACK_HEADER => IF (ctr_byte = 16) THEN state <= RX_DATA;--RX_ADD; ELSIF (ctr_byte = 17) THEN state <= TX_DATA; ELSE -- not addressed, go back to IDLE state <= IDLE; END IF; ------------- RX_ADD State -------------- --WHEN RX_ADD => -- check for repeated start --IF (start_flg = '1') THEN -- state <= HEADER; --ELSIF (bit_num = 8) THEN -- Send an acknowledge -- state <= ACK_ADD; --END IF; ------------- ACK_ADD STATE ------------- --WHEN ACK_ADD => --IF (add_num = 16) THEN -- state <= RX_DATA; --ELSE -- not addressed, go back to IDLE -- state <= RX_ADD; --END IF; ------------- RX_DATA State -------------- WHEN RX_DATA => -- check for repeated start IF (start_flg = '1') THEN state <= HEADER; ELSIF (bit_num = 8) THEN -- Send an acknowledge state <= ACK_DATA; END IF; ------------ TX_DATA State -------------- WHEN TX_DATA => -- check for repeated start IF (start_flg = '1') THEN state <= HEADER; ELSIF (bit_num = 8) THEN -- Wait for acknowledge state <= WAIT_ACK; END IF; ------------- ACK_DATA State -------------- WHEN ACK_DATA => state <= RX_DATA; ------------- WAIT_ACK State -------------- WHEN WAIT_ACK => IF (sda = '0') THEN state <= TX_DATA; ELSE -- no ack received, generate a stop and return -- to IDLE state state <= IDLE; END IF; END CASE; END IF; END PROCESS sm; bit_cnt_en <= '1' WHEN (state = HEADER) OR (state = RX_DATA) --OR (state = RX_ADD) OR (state = TX_DATA) ELSE '0'; bit_cnt_ld <= '1' WHEN (state = IDLE) OR (state = ACK_HEADER) OR (state = ACK_DATA) --OR (state = ACK_ADD) OR (state = WAIT_ACK) ELSE '0'; bitcnt:PROCESS(scl,state) BEGIN IF (state = IDLE) THEN bit_num <= "0000"; ELSIF(scl'EVENT AND scl = '1') THEN IF (bit_cnt_ld = '1') THEN bit_num <= "0000"; ELSIF (bit_cnt_en = '1' ) THEN bit_num <= bit_num + 1; END IF; END IF; END PROCESS bitcnt; -- Header/Address Shift Register i2c_header_ld <= '0' WHEN (state = HEADER) OR (state = ACK_HEADER) ELSE '1'; I2CHEDER_REG:PROCESS(scl,i2c_header_ld) BEGIN IF (scl'EVENT AND scl = '1') THEN IF (i2c_header_ld = '1') THEN ctr_byte <= (OTHERS => '1'); ELSIF (state = HEADER) THEN ctr_byte <= (ctr_byte(6 downto 0) & sda); ELSE ctr_byte <= ctr_byte; END IF; END IF; END PROCESS I2CHEDER_REG; -- receive lut address --Rx_lut_add:PROCESS(scl,state) --BEGIN -- IF (state = ACK_HEADER) THEN -- add_num <= "00000"; -- lut_add <= (OTHERS => '0'); -- ELSIF(scl'EVENT AND scl = '1') THEN -- IF (state = RX_ADD) THEN -- add_num <= add_num + 1; -- lut_add <= (lut_add(14 downto 0) & sda); -- END IF; -- END IF; --END PROCESS Rx_lut_add; -- I2C Data Shift Register --dreg_en <= '1' WHEN (state = RX_DATA) OR (state = TX_DATA) ELSE -- '0' ; I2CDATA_REG: PROCESS(scl,state) BEGIN IF (state = ACK_HEADER) THEN data_rec <= (OTHERS => '0'); ELSIF (scl'EVENT AND scl = '1') THEN IF (state = RX_DATA) THEN data_rec <= (data_rec(30 downto 0) & sda); END IF; END IF; END PROCESS I2CDATA_REG; byte_cnt:PROCESS(scl,state) BEGIN IF (state = ACK_HEADER) THEN byte_num <= "000"; ELSIF (scl'EVENT AND scl = '1') THEN IF (byte_cnt_ld = '1') THEN byte_num <= "001"; ELSIF (state = ACK_DATA) THEN byte_num <= byte_num + 1; END IF; END IF; END PROCESS byte_cnt; byte_cnt_ld <= '1' WHEN ((byte_num > 3) AND (state = ACK_DATA)) ELSE -- OR ((state = ACK_ADD) AND (add_num = 16)) '0'; -- output receive data RX_data_out: PROCESS(scl,state)--,add_num) VARIABLE fa_ww : STD_LOGIC_VECTOR (15 DOWNTO 0); BEGIN IF (state = ACK_HEADER) THEN --(state = ACK_ADD AND add_num = 16) i_coef <= (OTHERS => '0'); q_coef <= (OTHERS => '0'); fa_ww := "0000000000000000"; ELSIF (scl'EVENT AND scl = '1') THEN IF (state = ACK_DATA) AND (byte_num = 3) THEN i_coef <= data_rec(31 DOWNTO 16); q_coef <= data_rec(15 DOWNTO 0); fa_ww := fa_ww + 1; END IF; fa_w <= fa_ww(fa_wid-1 DOWNTO 0); END IF; END PROCESS RX_data_out; RX_data_outen: PROCESS(scl,state)--,add_num) BEGIN IF (state = ACK_HEADER) THEN --(state = ACK_ADD AND add_num = 16) out_en <= '0'; ELSIF (scl'EVENT AND scl = '1') THEN IF (state = ACK_DATA) AND (byte_num = 3) THEN out_en <= '1'; ELSE out_en <= '0'; END IF; END IF; END PROCESS RX_data_outen; -- input transmit data and change to bit ds_out <= datain WHEN (state = ACK_HEADER AND ctr_byte = 3) OR (state = WAIT_ACK) ELSE (ds_out(6 DOWNTO 0) & '0') WHEN (state = TX_DATA) ELSE (OTHERS => '0'); sda <= '0' WHEN (state = ACK_HEADER) OR (state = ACK_DATA) ELSE --OR (state = ACK_ADD) ds_out(7) WHEN (state = TX_DATA) ELSE 'Z';END ach;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -