From 12bbdb42cdcf5e6e39832d75fbbd31e3781d550a Mon Sep 17 00:00:00 2001 From: Pacien TRAN-GIRARD Date: Fri, 11 Apr 2014 19:29:53 +0200 Subject: Import fichiers projet Quartus --- FPGA/vhdl/i2c_master.vhd | 255 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 255 insertions(+) create mode 100644 FPGA/vhdl/i2c_master.vhd (limited to 'FPGA/vhdl/i2c_master.vhd') diff --git a/FPGA/vhdl/i2c_master.vhd b/FPGA/vhdl/i2c_master.vhd new file mode 100644 index 0000000..99b179b --- /dev/null +++ b/FPGA/vhdl/i2c_master.vhd @@ -0,0 +1,255 @@ +library ieee; +use ieee.std_logic_1164.all; +use ieee.numeric_std.all; + +entity i2C_master is + generic ( + system_frequency : real := 50.0E6; -- 50 MHz + i2c_rate : real := 20.0E3 -- 20 kHz + ); + port ( + clk : in std_logic; + resetn : in std_logic; + go : in std_logic; + ready : out std_logic; + data_in : in std_logic_vector(23 downto 0); -- adress & command & data + ack : out std_logic; + -- i2c + i2c_scl : out std_logic; -- A6 + i2c_sda : inout std_logic -- B6 + ); +end entity; + +architecture rtl of i2c_master is + constant mod_ctr_tempo : positive := integer(system_frequency/(2.0*i2c_rate)); + constant mod_ctr_bit : positive := 35; + type state is (wait_for_go, wait_for_i2clk, tx); + signal current_state : state; + signal next_state : state; + signal sdo : std_logic; + signal ctr_tempo : natural range 0 to mod_ctr_tempo-1; + signal end_tempo : std_logic; + signal ctr_bit : natural range 0 to mod_ctr_bit-1; + signal ack1 : std_logic; + signal ack2 : std_logic; + signal ack3 : std_logic; + signal reg_data : std_logic_vector(data_in'range); + signal cmd_data : std_logic_vector(1 downto 0); + signal cmd_bit : std_logic_vector(1 downto 0); + signal cmd_ack1 : std_logic_vector(1 downto 0); + signal cmd_ack2 : std_logic_vector(1 downto 0); + signal cmd_ack3 : std_logic_vector(1 downto 0); + signal sclk : std_logic; + signal i2c_clk : std_logic; + signal ready_i : std_logic; + +begin + i2c_sda <= 'Z' when sdo = '1' + else '0'; + i2c_scl <= '1' when sclk='1' + else not i2c_clk when (ctr_bit>=4 and ctr_bit <= 30) + else '0'; + ack <= ack1 or ack2 or ack3; + end_tempo <= '0' when ctr_tempo< mod_ctr_tempo-1 else '1'; + + process(resetn, clk) is + begin + if resetn = '0' then + i2c_clk <= '0'; + ctr_tempo <= 0; + ctr_bit <= 0; + reg_data <= (others => '0'); + --sclk <= '1'; + ACK1 <= '0'; + ACK2 <= '0'; + ACK3 <= '0'; + ready <= '1'; + current_state <= wait_for_go; + elsif rising_edge(clk) then + current_state <= next_state; + ready <= ready_i; + + -- temporisation et i2_clk + if current_state = wait_for_go then + ctr_tempo <= 0; + i2c_clk <= '0'; + elsif end_tempo='0' then + ctr_tempo <= ctr_tempo +1; + else + ctr_tempo <= 0; + i2c_clk <= not i2c_clk; + end if; + -- reg_data + case cmd_data is + when "10" => reg_data <= data_in; + when "11" => reg_data <= reg_data(22 downto 0)&'0'; + when others => null; + end case; + -- ctr_bit + case cmd_bit is + when "10" => ctr_bit <= 0; + when "11" => if ctr_bit null; + end case; + -- ack1 + case cmd_ack1 is + when "10" => ack1 <= '0'; + when "11" => ack1 <= '1'; + when others => null; + end case; + -- ack2 + case cmd_ack2 is + when "10" => ack2 <= '0'; + when "11" => ack2 <= '1'; + when others => null; + end case; + -- ack1 + case cmd_ack3 is + when "10" => ack3 <= '0'; + when "11" => ack3 <= '1'; + when others => null; + end case; + end if; +end process; +-------------------------------- +-- FSM +------------------------------- +process(current_state, end_tempo, i2c_clk, go,reg_data(23), i2c_sda,ctr_bit) is +begin + next_state <= current_state; + ready_i <= '0'; + cmd_ack1 <= "00"; + cmd_ack2 <= "00"; + cmd_ack3 <= "00"; + cmd_bit <= "00"; + cmd_data <= "00"; + sdo <= '1'; + sclk <= '0'; + case current_state is + when wait_for_go => if go = '1' then next_state <=wait_for_i2clk; + end if; + ready_i <= '1'; + cmd_bit <= "10"; + cmd_data <= "10"; + sclk <= '1'; + when wait_for_i2clk => if i2c_clk='0' and end_tempo='1' then next_state <=tx; + end if; + cmd_ack1 <= "10"; + cmd_ack2 <= "10"; + cmd_ack3 <= "10"; + sclk <= '1'; + when tx => if ctr_bit< mod_ctr_bit-1 then + if i2c_clk='0' and end_tempo='1'then + cmd_bit <= "11"; + end if; + elsif end_tempo='1'then + next_state <= wait_for_go; + end if; + case ctr_bit is + when 0 => sdo <= '1'; sclk <= '1'; + -- start + when 1 => sdo <= '0'; sclk <= '0'; + when 2 => sdo <= '0'; sclk <= '0'; + -- slave address + when 3 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 4 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 5 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 6 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 7 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 8 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 9 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 10 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 11 => sdo <= '1'; -- ack + + -- command + when 12 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + if i2c_sda='1' then cmd_ack1 <= "11" ; + else cmd_ack1 <= "10" ; + end if; + when 13 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 14 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 15 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 16 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 17 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 18 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 19 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 20 => sdo <= '1'; -- ack + -- data + when 21 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + if i2c_sda='1' then cmd_ack2 <= "11" ; + else cmd_ack2 <= "10" ; + end if; + when 22 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 23 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 24 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 25 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 26 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 27 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 28 => sdo <= reg_data(23); + if i2c_clk='0' and end_tempo='1'then cmd_data <= "11"; + end if; + when 29 => sdo <= '1'; -- ack + --stop + when 30 => sdo <= '0'; + if i2c_sda='1' then cmd_ack3 <= "11" ; + else cmd_ack3 <= "10" ; + end if; + sclk <= '0'; + when 31 => sdo <= '0'; sclk <= '1'; + when others => sdo <= '1'; sclk <= '1'; + end case; + + + end case; + +end process; + +end architecture; -- cgit v1.2.3