summaryrefslogtreecommitdiff
path: root/FPGA/vhdl/i2c_master.vhd
diff options
context:
space:
mode:
Diffstat (limited to 'FPGA/vhdl/i2c_master.vhd')
-rw-r--r--FPGA/vhdl/i2c_master.vhd255
1 files changed, 255 insertions, 0 deletions
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 @@
1library ieee;
2use ieee.std_logic_1164.all;
3use ieee.numeric_std.all;
4
5entity i2C_master is
6 generic (
7 system_frequency : real := 50.0E6; -- 50 MHz
8 i2c_rate : real := 20.0E3 -- 20 kHz
9 );
10 port (
11 clk : in std_logic;
12 resetn : in std_logic;
13 go : in std_logic;
14 ready : out std_logic;
15 data_in : in std_logic_vector(23 downto 0); -- adress & command & data
16 ack : out std_logic;
17 -- i2c
18 i2c_scl : out std_logic; -- A6
19 i2c_sda : inout std_logic -- B6
20 );
21end entity;
22
23architecture rtl of i2c_master is
24 constant mod_ctr_tempo : positive := integer(system_frequency/(2.0*i2c_rate));
25 constant mod_ctr_bit : positive := 35;
26 type state is (wait_for_go, wait_for_i2clk, tx);
27 signal current_state : state;
28 signal next_state : state;
29 signal sdo : std_logic;
30 signal ctr_tempo : natural range 0 to mod_ctr_tempo-1;
31 signal end_tempo : std_logic;
32 signal ctr_bit : natural range 0 to mod_ctr_bit-1;
33 signal ack1 : std_logic;
34 signal ack2 : std_logic;
35 signal ack3 : std_logic;
36 signal reg_data : std_logic_vector(data_in'range);
37 signal cmd_data : std_logic_vector(1 downto 0);
38 signal cmd_bit : std_logic_vector(1 downto 0);
39 signal cmd_ack1 : std_logic_vector(1 downto 0);
40 signal cmd_ack2 : std_logic_vector(1 downto 0);
41 signal cmd_ack3 : std_logic_vector(1 downto 0);
42 signal sclk : std_logic;
43 signal i2c_clk : std_logic;
44 signal ready_i : std_logic;
45
46begin
47 i2c_sda <= 'Z' when sdo = '1'
48 else '0';
49 i2c_scl <= '1' when sclk='1'
50 else not i2c_clk when (ctr_bit>=4 and ctr_bit <= 30)
51 else '0';
52 ack <= ack1 or ack2 or ack3;
53 end_tempo <= '0' when ctr_tempo< mod_ctr_tempo-1 else '1';
54
55 process(resetn, clk) is
56 begin
57 if resetn = '0' then
58 i2c_clk <= '0';
59 ctr_tempo <= 0;
60 ctr_bit <= 0;
61 reg_data <= (others => '0');
62 --sclk <= '1';
63 ACK1 <= '0';
64 ACK2 <= '0';
65 ACK3 <= '0';
66 ready <= '1';
67 current_state <= wait_for_go;
68 elsif rising_edge(clk) then
69 current_state <= next_state;
70 ready <= ready_i;
71
72 -- temporisation et i2_clk
73 if current_state = wait_for_go then
74 ctr_tempo <= 0;
75 i2c_clk <= '0';
76 elsif end_tempo='0' then
77 ctr_tempo <= ctr_tempo +1;
78 else
79 ctr_tempo <= 0;
80 i2c_clk <= not i2c_clk;
81 end if;
82 -- reg_data
83 case cmd_data is
84 when "10" => reg_data <= data_in;
85 when "11" => reg_data <= reg_data(22 downto 0)&'0';
86 when others => null;
87 end case;
88 -- ctr_bit
89 case cmd_bit is
90 when "10" => ctr_bit <= 0;
91 when "11" => if ctr_bit<mod_ctr_bit-1 then ctr_bit <= ctr_bit+1;
92 else ctr_bit <= 0;
93 end if;
94 when others => null;
95 end case;
96 -- ack1
97 case cmd_ack1 is
98 when "10" => ack1 <= '0';
99 when "11" => ack1 <= '1';
100 when others => null;
101 end case;
102 -- ack2
103 case cmd_ack2 is
104 when "10" => ack2 <= '0';
105 when "11" => ack2 <= '1';
106 when others => null;
107 end case;
108 -- ack1
109 case cmd_ack3 is
110 when "10" => ack3 <= '0';
111 when "11" => ack3 <= '1';
112 when others => null;
113 end case;
114 end if;
115end process;
116--------------------------------
117-- FSM
118-------------------------------
119process(current_state, end_tempo, i2c_clk, go,reg_data(23), i2c_sda,ctr_bit) is
120begin
121 next_state <= current_state;
122 ready_i <= '0';
123 cmd_ack1 <= "00";
124 cmd_ack2 <= "00";
125 cmd_ack3 <= "00";
126 cmd_bit <= "00";
127 cmd_data <= "00";
128 sdo <= '1';
129 sclk <= '0';
130 case current_state is
131 when wait_for_go => if go = '1' then next_state <=wait_for_i2clk;
132 end if;
133 ready_i <= '1';
134 cmd_bit <= "10";
135 cmd_data <= "10";
136 sclk <= '1';
137 when wait_for_i2clk => if i2c_clk='0' and end_tempo='1' then next_state <=tx;
138 end if;
139 cmd_ack1 <= "10";
140 cmd_ack2 <= "10";
141 cmd_ack3 <= "10";
142 sclk <= '1';
143 when tx => if ctr_bit< mod_ctr_bit-1 then
144 if i2c_clk='0' and end_tempo='1'then
145 cmd_bit <= "11";
146 end if;
147 elsif end_tempo='1'then
148 next_state <= wait_for_go;
149 end if;
150 case ctr_bit is
151 when 0 => sdo <= '1'; sclk <= '1';
152 -- start
153 when 1 => sdo <= '0'; sclk <= '0';
154 when 2 => sdo <= '0'; sclk <= '0';
155 -- slave address
156 when 3 => sdo <= reg_data(23);
157 if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
158 end if;
159 when 4 => sdo <= reg_data(23);
160 if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
161 end if;
162 when 5 => sdo <= reg_data(23);
163 if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
164 end if;
165 when 6 => sdo <= reg_data(23);
166 if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
167 end if;
168 when 7 => sdo <= reg_data(23);
169 if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
170 end if;
171 when 8 => sdo <= reg_data(23);
172 if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
173 end if;
174 when 9 => sdo <= reg_data(23);
175 if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
176 end if;
177 when 10 => sdo <= reg_data(23);
178 if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
179 end if;
180 when 11 => sdo <= '1'; -- ack
181
182 -- command
183 when 12 => sdo <= reg_data(23);
184 if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
185 end if;
186 if i2c_sda='1' then cmd_ack1 <= "11" ;
187 else cmd_ack1 <= "10" ;
188 end if;
189 when 13 => sdo <= reg_data(23);
190 if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
191 end if;
192 when 14 => sdo <= reg_data(23);
193 if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
194 end if;
195 when 15 => sdo <= reg_data(23);
196 if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
197 end if;
198 when 16 => sdo <= reg_data(23);
199 if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
200 end if;
201 when 17 => sdo <= reg_data(23);
202 if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
203 end if;
204 when 18 => sdo <= reg_data(23);
205 if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
206 end if;
207 when 19 => sdo <= reg_data(23);
208 if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
209 end if;
210 when 20 => sdo <= '1'; -- ack
211 -- data
212 when 21 => sdo <= reg_data(23);
213 if i2c_clk='0' and end_tempo='1'then cmd_data <= "11";
214 end if;
215 if i2c_sda='1' then cmd_ack2 <= "11" ;
216 else cmd_ack2 <= "10" ;
217