lemart92
Newbie level 4

Hi All - I'm fairly new to vhdl and I need to add an avalon memory mapped master to an I2C slave block. I've looked through a few pages but nothing really explains it. It looks like it's not that bad but I'm not really that good yet on writing the state machines.My code is pasted below:
Code:
-- Define libraries used
LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_arith.all;
USE ieee.std_logic_unsigned.all;
USE ieee.std_logic_arith.all;
--use work.bud_lite_pkg.all;
ENTITY i2c_rcvr IS
PORT (
clk : IN std_logic;
resetn : IN std_logic;
ack_test : OUT std_logic;
data_in : IN std_logic_vector(7 downto 0); -- status register to be read by uP
addr_reg : OUT std_logic_VECTOR(7 downto 0);
wr_rd : OUT std_logic;
scl : IN std_logic;
sda : INOUT std_logic;
dout : OUT std_logic_vector(7 downto 0) -- data received over i2c data byte (write data from uP)
-- interface for AvMM-master
mstr_en_n : out std_logic;
mstr_address : out std_logic_vector(10 downto 0);
mstr_write_n : out std_logic;
mstr_read_n : out std_logic;
mstr_data_in : in std_logic_vector(31 downto 0);
mstr_data_out : out std_logic_vector(31 downto 0);
mstr_waitrequest_n : in std_logic
);
END i2c_rcvr;
ARCHITECTURE rtl OF i2c_rcvr IS
CONSTANT cIDLE_CNT : integer := 24; -- was 4
CONSTANT cSAMPLE : integer := 18;
CONSTANT cDEVICE_EOF : integer := 6;
CONSTANT cEOF : integer := 9; --
CONSTANT cRESET : STD_LOGIC := '0'; -- chip reset
CONSTANT cDADDR : std_logic_vector(6 DOWNTO 0) := "1000011"; -- 0x43 BL i2c official device address
TYPE i2c_state_type IS (start,stop,dev_addr,local_addr,ack,write_data,read_data,no_ack);
-- sequential signals
SIGNAL i2c_state : i2c_state_type;
SIGNAL bit_cnt : integer RANGE 0 TO 9;
SIGNAL idle_cnt : integer RANGE 0 TO 24; -- was 9
SIGNAL delay_cnt : integer RANGE 0 TO 18; -- min sample requirement
SIGNAL ack_flag : std_logic; -- ack
SIGNAL shift_reg : std_logic_vector(8 downto 0);
SIGNAL start_flag : std_logic;
SIGNAL stop_flag : std_logic;
SIGNAL dout_s : std_logic_vector(7 downto 0);
SIGNAL sda_in : std_logic;
--SIGNAL active : std_logic;
SIGNAL rd_flag : std_logic;
SIGNAL wr_flag : std_logic;
SIGNAL lcl_flag : std_logic;
SIGNAL start_rst : std_logic;
SIGNAL start_i : std_logic;
SIGNAL stop_i : std_logic;
--SIGNAL active_i : std_logic;
SIGNAL data_in_reg : std_logic_vector(7 downto 0);
SIGNAL data_in_reg_i : std_logic_vector(7 downto 0);
SIGNAL ack_flag_i : std_logic;
SIGNAL ack_flag_reg : std_logic;
SIGNAL no_ack_flag : std_logic;
SIGNAL scl_rclock_edge : std_logic;
SIGNAL scl_fclock_edge : std_logic;
SIGNAL scl_clock_samp : std_logic_vector(1 DOWNTO 0);
SIGNAL scl_rclk : std_logic;
SIGNAL scl_fclk : std_logic;
BEGIN
i2c_rcvr_fsm : PROCESS (resetn,scl_rclk,start_i,stop_i)
BEGIN
IF(resetn= cRESET) THEN
bit_cnt <= 8;
no_ack_flag <= '0';
delay_cnt <= cSAMPLE;
ack_flag <= '0';
stop_flag <= '0';
start_flag <= '0';
start_rst <= '0';
rd_flag <= '0';
wr_flag <= '0';
lcl_flag <= '0';
i2c_state <= start;
dout_s <= (OTHERS => '0');
dout <= (OTHERS => '0');
---shift_reg <= "000000000";
shift_reg <= (OTHERS => '0');
addr_reg <= (OTHERS => '0');
ELSIF(rising_edge(scl_rclk)) THEN -- was scl, now in 4Mhz domain
start_rst <= start_i;
CASE i2c_state IS
WHEN start => -- idle pattern all one's
bit_cnt <= 8;
ack_flag <= '0';
dout_s <= (OTHERS => '0');
stop_flag <= '0';
start_flag <= '0';
rd_flag <= '0';
wr_flag <= '0';
--shift_reg <= "000000000";
shift_reg <= (OTHERS => '0');
IF start_i = '1' THEN
shift_reg <= shift_reg(7 DOWNTO 0) & sda_in;
start_flag <= '1';
bit_cnt <= 7;
i2c_state <= dev_addr;
ELSE
i2c_state <= start;
END IF;
WHEN dev_addr =>
start_flag <= '0';
IF bit_cnt > 0 THEN
bit_cnt <= bit_cnt - 1;
shift_reg <= shift_reg(7 DOWNTO 0) & sda_in;
i2c_state <= dev_addr;
IF (bit_cnt = 1 AND shift_reg(6 DOWNTO 0) = cDADDR) THEN
ack_flag <= '1';
ELSE
ack_flag <= '0';
END IF;
ELSE
IF ack_flag = '1' THEN
--IF shift_reg(7 DOWNTO 1) = cDADDR THEN -- removed 7-16-15
rd_flag <= shift_reg(0); -- read or write operation
bit_cnt <= 8;
ack_flag <= '0';
i2c_state <= ack;
ELSE
shift_reg <= (OTHERS => '0');
i2c_state <= start;
END IF;
END IF;
WHEN ack =>
ack_flag <= '0';
IF rd_flag = '1' THEN
--data_in_reg <= data_in;
bit_cnt <= 7;
i2c_state <= read_data;
ELSIF start_i = '1' THEN
bit_cnt <= 8;
i2c_state <= dev_addr;
ELSIF lcl_flag = '1' THEN
bit_cnt <= 7; -- was 8
shift_reg <= shift_reg(7 DOWNTO 0) & sda_in;
i2c_state <= write_data;
ELSIF wr_flag = '1' THEN
wr_flag <= '0';
shift_reg <= (OTHERS => '0'); -- new
i2c_state <= start; -- used to be stop for simulation
ELSE
bit_cnt <= 7;
i2c_state <= local_addr;
END IF;
WHEN local_addr =>
ack_flag <= '0';
IF bit_cnt > 0 THEN
bit_cnt <= bit_cnt - 1;
shift_reg <= shift_reg(7 DOWNTO 0) & sda_in;
i2c_state <= local_addr;
if bit_cnt = 1 THEN
ack_flag <= '1';
end if;
ELSE
addr_reg <= shift_reg(7 DOWNTO 0);
bit_cnt <= 8;
ack_flag <= '0';
lcl_flag <= '1';
i2c_state <= ack;
END IF;
IF bit_cnt = 0 THEN
wr_flag <= '1';
END IF;
WHEN read_data =>
IF bit_cnt > 0 THEN
bit_cnt <= bit_cnt - 1;
-----data_in_reg <= data_in_reg(6 downto 0) & '1';
i2c_state <= read_data;
ELSE
bit_cnt <= 8;
rd_flag <= '0';
no_ack_flag <= '1';
i2c_state <= no_ack;
END IF;
WHEN write_data =>
ack_flag <= '0';
lcl_flag <= '0';
IF start_i = '1' THEN
shift_reg <= shift_reg(7 DOWNTO 0) & sda_in;
I2c_state <= dev_addr;
wr_flag <= '0';
bit_cnt <= 7;
ELSE
IF bit_cnt > 0 THEN
bit_cnt <= bit_cnt - 1;
shift_reg <= shift_reg(7 DOWNTO 0) & sda_in;
i2c_state <= write_data;
IF bit_cnt = 1 THEN
ack_flag <= '1';
END IF;
ELSE
dout <= shift_reg(7 DOWNTO 0);
ack_flag <= '0';
bit_cnt <= 8;
i2c_state <= ack;
END IF;
END IF;
WHEN no_ack =>
rd_flag <= '0';
no_ack_flag <= '0';
ack_flag <= '0'; -- added 11/6/14 and change to start
shift_reg <= (OTHERS => '0'); -- new
i2c_state <= start; -- used to be stop for simulation
WHEN stop =>
IF stop_i = '1' THEN
ack_flag <= '0';
i2c_state <= start;
ELSE
i2c_state <= stop;
END IF;
WHEN OTHERS => i2c_state <= start; -- go to bloody idle
END CASE;
END IF;
END PROCESS i2c_rcvr_fsm;
------------------------------------------------------------------------------
-- start condition detection,( good noise tolerance )
------------------------------------------------------------------------------
PROCESS (sda_in,start_rst,rd_flag,ack_flag)
BEGIN
IF (start_rst = '1' or rd_flag = '1' or ack_flag = '1' ) THEN
start_i <= '0';
ELSIF (sda_in'event AND sda_in = '0') THEN
start_i <= scl;
END IF;
END PROCESS;
------------------------------------------------------------------------------
-- stop condition detection
PROCESS (resetn,scl,sda_in,start_i,rd_flag,no_ack_flag,ack_flag,lcl_flag,wr_flag)
BEGIN
IF resetn = cRESET or scl = '0' or start_i = '1' or rd_flag = '1' OR no_ack_flag = '1'
or ack_flag = '1' or lcl_flag = '1' or wr_flag = '1' THEN
stop_i <= '0';
ELSIF sda_in = '1' AND sda_in'event THEN
IF scl = '1' then
stop_i <= '1';
END IF;
END IF;
END PROCESS;
PROCESS (resetn,clk) -- was scl
BEGIN
IF resetn = cRESET THEN
data_in_reg_i <= (OTHERS => '0');
ELSIF(rising_edge(clk)) THEN
IF ack_flag_reg = '1' THEN
data_in_reg_i <= data_in;
END IF;
END IF;
END PROCESS;
--===========
PROCESS (resetn,scl_fclk) -- was scl, now 4Mhz domain
BEGIN
IF resetn = cRESET THEN
data_in_reg <= (OTHERS => '0');
ELSIF(rising_edge(scl_fclk)) THEN
IF rd_flag = '1' AND ack_flag_reg = '0' THEN
data_in_reg <= data_in_reg (6 downto 0) & '1';
ELSE
data_in_reg <= data_in_reg_i;
END IF;
END IF;
END PROCESS;
PROCESS (resetn,scl_fclk)
BEGIN
IF resetn = cRESET THEN
ack_flag_reg <= '0';
ELSIF(rising_edge(scl_fclk)) THEN
ack_flag_reg <= ack_flag;
END IF;
END PROCESS;
PROCESS (resetn,clk)
BEGIN
IF resetn = cRESET THEN
scl_clock_samp <= (OTHERS => '0');
ELSIF(rising_edge(clk)) THEN
scl_clock_samp <= scl_clock_samp(0) & scl;
END IF;
END PROCESS;
PROCESS (resetn,clk)
BEGIN
IF resetn = cRESET THEN
scl_rclk <= '0';
scl_fclk <= '0';
ELSIF(falling_edge(clk)) THEN
scl_rclk <= scl_rclock_edge;
scl_fclk <= scl_fclock_edge;
END IF;
END PROCESS;
scl_rclock_edge <= '1' WHEN scl_clock_samp(1) = '0' AND scl_clock_samp(0) = '1' ELSE '0';
scl_fclock_edge <= '1' WHEN scl_clock_samp(1) = '1' AND scl_clock_samp(0) = '0' ELSE '0';
--active <= active_i;
--active <= ack_flag;
wr_rd <= rd_flag;
sda_in <= sda;
ack_test <= '1' WHEN (ack_flag_reg = '1' AND shift_reg(7 DOWNTO 1) = cDADDR) ELSE '0';
--sda <= '0' WHEN (ack_flag_reg = '1' AND shift_reg(7 DOWNTO 1) = cDADDR) ELSE data_in_reg(7) WHEN (rd_flag = '1' AND ack_flag_reg = '0') ELSE
sda <= '0' WHEN ack_flag_reg = '1' ELSE data_in_reg(7) WHEN (rd_flag = '1' AND ack_flag_reg = '0') ELSE 'Z';
END rtl;