Forum Discussion
CMcga
New Contributor
6 years ago--synthesis VHDL_INPUT_VERSION VHDL_2008
library ieee;
use ieee.std_logic_1164.all;
entity i2c_master is
generic(
clk_freq : integer := 50_000_000;
i2c_freq : integer := 300_000;
slaveWR0 : std_logic_vector(8 downto 0) := "000000010";
slaveRD0 : std_logic_vector(8 downto 0) := "000000011";
reg0WR0 : std_logic_vector(8 downto 0) := "010000101";
reg0RD0 : std_logic_vector(8 downto 0) := "010000101";
slvData0 : std_logic_Vector(8 downto 0) := "001100101"
);
port(
clk50,
-- slvAddress,
WR, RD,
reset : in std_logic := '0';
SCL : out std_logic := '0';
SDA : inout std_logic := '0'
-- output : out std_logic_vector(7 downto 0) := (others => '0')
);
end i2c_master;
architecture FSM of i2c_master is
type masterState is (
Idle, Start, Slave_Address, Ack1, Stop, Hold,
WR_Address, Ack2, Write_Data, Ack3,
RD_Address, Ack4, restartL, restartR, Initiate_Read, Ack5, Read_Data, noAck
);
signal prev_State, next_State : masterState;
signal i2c_clk : std_logic := '0';
signal i, iReg : natural range 0 to 8;
signal j, jReg : natural range 0 to 7;
signal storeData : std_logic_vector(7 downto 0) := (others => '0');
signal wr_Reg : std_logic := '0';
--constant slaveAddress0 : std_logic_vector(7 downto 0) := slaveWR0;
begin
process(i2c_clk, reset)
begin
if (reset = '1') then prev_State <= Idle;
iReg <= 0;
jReg <= 0;
elsif(falling_edge(i2c_clk)) then prev_State <= next_State;
iReg <= i;
jReg <= j;
end if;
end process;
process(all)
variable clk_counter : natural range 0 to clk_freq/(2*i2c_freq);
begin
if(rising_edge(clk50)) then clk_counter := clk_counter + 1;
if(clk_counter = clk_freq/(2*i2c_freq)) then i2c_clk <= not i2c_clk;
clk_counter := 0;
end if;
end if;
end process;
process(all)
begin
SCL <= i2c_clk;
i <= 0;
j <= 0;
case (prev_State) is
when Idle =>
SCL <= '1';
SDA <= '1';
if(WR = '1') then next_State <= Start;
else next_State <= Idle;
end if;
when Start =>
SCL <= '1';
SDA <= '0';
next_State <= Slave_Address;
when Slave_Address =>
SDA <= slaveWR0(8-i);
i <= iReg + 1;
if(i = 8) then next_State <= Ack1;
else next_State <= Slave_Address;
end if;
when Ack1 =>
SDA <= 'Z';
if(wr_Reg = '1') then next_State <= WR_Address;
else next_State <= RD_Address;
end if;
when Stop =>
SDA <= '0';
next_State <= Hold;
when Hold =>
SCL <= '1';
SDA <= '1';
if(wr = '0' and rd = '0') then next_State <= Idle;
else next_State <= Hold;
end if;
when WR_Address =>
SDA <= reg0WR0(8-i);
i <= iReg + 1;
if(i = 8) then next_State <= Ack2;
else next_State <= WR_Address;
end if;
when Ack2 =>
SDA <= 'Z';
next_State <= Write_Data;
when Write_Data =>
SDA <= slvData0(8-i);
i <= iReg + 1;
if(i = 8) then next_State <= Ack3;
else next_State <= Write_Data;
end if;
when Ack3 =>
SDA <= 'Z';
next_State <= Stop;
when RD_Address =>
SDA <= reg0RD0(8-i);
i <= iReg + 1;
if(i = 8) then next_State <= Ack4;
else next_State <= RD_Address;
end if;
when Ack4 =>
SDA <= 'Z';
next_State <= restartL;
when restartL =>
SCL <= '0';
SDA <= '1';
next_State <= restartR;
when restartR =>
SCL <= '1';
SDA <= not i2c_clk;
next_State <= Initiate_Read;
when Initiate_Read =>
SDA <= slaveRD0(8-i);
i <= iReg + 1;
if(i = 8) then next_State <= Ack5;
else next_State <= Initiate_Read;
end if;
when Ack5 =>
SDA <= 'Z';
next_State <= Read_Data;
when Read_Data =>
SDA <= 'Z';
i <= iReg + 1;
if(i = 8) then next_State <= noAck;
else next_State <= Read_Data;
end if;
when noAck =>
SDA <= '1';
next_State <= Stop;
end case;
end process;
process(clk50)
begin
if(rising_edge(clk50)) then
if(prev_State = Start) then wr_Reg <= WR;
end if;
end if;
end process;
process(i2c_clk)
begin
if(rising_edge(i2c_clk)) then
if(prev_State = Read_Data) then storeData(8-i) <= SDA;
end if;
end if;
--
-- if(falling_edge(i2c_clk)) then
-- if(prev_State = Read_Data and i = 8) then output <= storeData;
-- end if;
-- end if;
end process;
end FSM;Here is the master just in case.