SURF  1.0
i2c_master_byte_ctrl.vhd
Go to the documentation of this file.
1 ---------------------------------------------------------------------
2 ---- ----
3 ---- WISHBONE revB2 compl. I2C Master Core; byte-controller ----
4 ---- ----
5 ---- ----
6 ---- Author: Richard Herveille ----
7 ---- richard@asics.ws ----
8 ---- www.asics.ws ----
9 ---- ----
10 ---- Downloaded from: http://www.opencores.org/projects/i2c/ ----
11 ---- ----
12 ---------------------------------------------------------------------
13 ---- ----
14 ---- Copyright (C) 2000 Richard Herveille ----
15 ---- richard@asics.ws ----
16 ---- ----
17 ---- This source file may be used and distributed without ----
18 ---- restriction provided that this copyright statement is not ----
19 ---- removed from the file and that any derivative work contains ----
20 ---- the original copyright notice and the associated disclaimer.----
21 ---- ----
22 ---- THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ----
23 ---- EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ----
24 ---- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ----
25 ---- FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ----
26 ---- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ----
27 ---- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ----
28 ---- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ----
29 ---- GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ----
30 ---- BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ----
31 ---- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ----
32 ---- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ----
33 ---- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ----
34 ---- POSSIBILITY OF SUCH DAMAGE. ----
35 ---- ----
36 ---------------------------------------------------------------------
37 
38 -- CVS Log
39 --
40 -- $Id: i2c_master_byte_ctrl.vhd,v 1.5 2004/02/18 11:41:48 rherveille Exp $
41 --
42 -- $Date: 2004/02/18 11:41:48 $
43 -- $Revision: 1.5 $
44 -- $Author: rherveille $
45 -- $Locker: $
46 -- $State: Exp $
47 --
48 -- Change History:
49 -- $Log: i2c_master_byte_ctrl.vhd,v $
50 -- Revision 1.5 2004/02/18 11:41:48 rherveille
51 -- Fixed a potential bug in the statemachine. During a 'stop' 2 cmd_ack signals were generated. Possibly canceling a new start command.
52 --
53 -- Revision 1.4 2003/08/09 07:01:13 rherveille
54 -- Fixed a bug in the Arbitration Lost generation caused by delay on the (external) sda line.
55 -- Fixed a potential bug in the byte controller's host-acknowledge generation.
56 --
57 -- Revision 1.3 2002/12/26 16:05:47 rherveille
58 -- Core is now a Multimaster I2C controller.
59 --
60 -- Revision 1.2 2002/11/30 22:24:37 rherveille
61 -- Cleaned up code
62 --
63 -- Revision 1.1 2001/11/05 12:02:33 rherveille
64 --! @see entity
65  --! @ingroup protocols_i2c
66 -- Split i2c_master_core.vhd into separate files for each entity; same layout as verilog version.
67 -- Code updated, is now up-to-date to doc. rev.0.4.
68 -- Added headers.
69 --
70 
71 -- Modified by Jan Andersson (jan@gaisler.com:.
72 -- Changed std_logic_arith to numeric_std.
73 -- Propagate filter generic
74 
75 --
76 ------------------------------------------
77 -- Byte controller section
78 ------------------------------------------
79 --
80 library ieee;
81 use ieee.std_logic_1164.all;
82 --library grlib;
83 use work.stdlib.all;
84 
86  generic (filter : integer; dynfilt : integer);
87  port (
88  clk : in std_logic;
89  rst : in std_logic; -- synchronous active high reset (WISHBONE compatible)
90  nReset : in std_logic; -- asynchornous active low reset (FPGA compatible)
91  ena : in std_logic; -- core enable signal
92 
93  clk_cnt : in std_logic_vector(15 downto 0); -- 4x SCL
94 
95  -- input signals
96  start,
97  stop,
98  read,
99  write,
100  ack_in : std_logic;
101  din : in std_logic_vector(7 downto 0);
102  filt : in std_logic_vector((filter-1)*dynfilt downto 0);
103 
104  -- output signals
105  cmd_ack : out std_logic; -- command done
106  ack_out : out std_logic;
107  i2c_busy : out std_logic; -- arbitration lost
108  i2c_al : out std_logic; -- i2c bus busy
109  dout : out std_logic_vector(7 downto 0);
110 
111  -- i2c lines
112  scl_i : in std_logic; -- i2c clock line input
113  scl_o : out std_logic; -- i2c clock line output
114  scl_oen : out std_logic; -- i2c clock line output enable, active low
115  sda_i : in std_logic; -- i2c data line input
116  sda_o : out std_logic; -- i2c data line output
117  sda_oen : out std_logic -- i2c data line output enable, active low
118  );
119 end entity i2c_master_byte_ctrl;
120 
121 architecture structural of i2c_master_byte_ctrl is
122  component i2c_master_bit_ctrl is
123  generic (filter : integer; dynfilt : integer);
124  port (
125  clk : in std_logic;
126  rst : in std_logic;
127  nReset : in std_logic;
128  ena : in std_logic; -- core enable signal
129 
130  clk_cnt : in std_logic_vector(15 downto 0); -- clock prescale value
131 
132  cmd : in std_logic_vector(3 downto 0);
133  cmd_ack : out std_logic; -- command done
134  busy : out std_logic; -- i2c bus busy
135  al : out std_logic; -- arbitration lost
136 
137  din : in std_logic;
138  dout : out std_logic;
139 
140  filt : in std_logic_vector((filter-1)*dynfilt downto 0);
141 
142  -- i2c lines
143  scl_i : in std_logic; -- i2c clock line input
144  scl_o : out std_logic; -- i2c clock line output
145  scl_oen : out std_logic; -- i2c clock line output enable, active low
146  sda_i : in std_logic; -- i2c data line input
147  sda_o : out std_logic; -- i2c data line output
148  sda_oen : out std_logic -- i2c data line output enable, active low
149  );
150  end component i2c_master_bit_ctrl;
151 
152  -- commands for bit_controller block
153  constant I2C_CMD_NOP : std_logic_vector(3 downto 0) := "0000";
154  constant I2C_CMD_START : std_logic_vector(3 downto 0) := "0001";
155  constant I2C_CMD_STOP : std_logic_vector(3 downto 0) := "0010";
156  constant I2C_CMD_READ : std_logic_vector(3 downto 0) := "0100";
157  constant I2C_CMD_WRITE : std_logic_vector(3 downto 0) := "1000";
158 
159  -- signals for bit_controller
160  signal core_cmd : std_logic_vector(3 downto 0);
161  signal core_ack, core_txd, core_rxd : std_logic;
162  signal al : std_logic;
163 
164  -- signals for shift register
165  signal sr : std_logic_vector(7 downto 0); -- 8bit shift register
166  signal shift, ld : std_logic;
167 
168  -- signals for state machine
169  signal go, host_ack : std_logic;
170  -- Added init value to dcnt to prevent simulation meta-value
171  -- - jan@gaisler.com
172  -- removed init value as it is not compatible with Formality
173  -- - jiri@gaisler.com
174  signal dcnt : std_logic_vector(2 downto 0)
175 -- pragma translate_off
176  := (others => '0')
177 -- pragma translate_on
178  ; -- data counter
179  signal cnt_done : std_logic;
180 
181 begin
182  -- hookup bit_controller
184  generic map (filter, dynfilt)
185  port map(
186  clk => clk,
187  rst => rst,
188  nReset => nReset,
189  ena => ena,
190  clk_cnt => clk_cnt,
191  cmd => core_cmd,
192  cmd_ack => core_ack,
193  busy => i2c_busy,
194  al => al,
195  din => core_txd,
196  dout => core_rxd,
197  filt => filt,
198  scl_i => scl_i,
199  scl_o => scl_o,
200  scl_oen => scl_oen,
201  sda_i => sda_i,
202  sda_o => sda_o,
203  sda_oen => sda_oen
204  );
205  i2c_al <= al;
206 
207  -- generate host-command-acknowledge
208  cmd_ack <= host_ack;
209 
210  -- generate go-signal
211  go <= (read or write or stop) and not host_ack;
212 
213  -- assign Dout output to shift-register
214  dout <= sr;
215 
216  -- generate shift register
217  shift_register: process(clk, nReset)
218  begin
219  if (nReset = '0') then
220  sr <= (others => '0');
221  elsif (clk'event and clk = '1') then
222  if (rst = '1') then
223  sr <= (others => '0');
224  elsif (ld = '1') then
225  sr <= din;
226  elsif (shift = '1') then
227  sr <= (sr(6 downto 0) & core_rxd);
228  end if;
229  end if;
230  end process shift_register;
231 
232  -- generate data-counter
233  data_cnt: process(clk, nReset)
234  begin
235  if (nReset = '0') then
236  dcnt <= (others => '0');
237  elsif (clk'event and clk = '1') then
238  if (rst = '1') then
239  dcnt <= (others => '0');
240  elsif (ld = '1') then
241  dcnt <= (others => '1'); -- load counter with 7
242  elsif (shift = '1') then
243  dcnt <= dcnt -1;
244  end if;
245  end if;
246  end process data_cnt;
247 
248  cnt_done <= '1' when (dcnt = "000") else '0';
249 
250  --
251  -- state machine
252  --
253  statemachine : block
254  type states is (st_idle, st_start, st_read, st_write, st_ack, st_stop);
255  signal c_state : states;
256  begin
257  --
258  -- command interpreter, translate complex commands into simpler I2C commands
259  --
260  nxt_state_decoder: process(clk, nReset)
261  begin
262  if (nReset = '0') then
264  core_txd <= '0';
265  shift <= '0';
266  ld <= '0';
267  host_ack <= '0';
268  c_state <= st_idle;
269  ack_out <= '0';
270  elsif (clk'event and clk = '1') then
271  if (rst = '1' or al = '1') then
273  core_txd <= '0';
274  shift <= '0';
275  ld <= '0';
276  host_ack <= '0';
277  c_state <= st_idle;
278  ack_out <= '0';
279  else
280  -- initialy reset all signal
281  core_txd <= sr(7);
282  shift <= '0';
283  ld <= '0';
284  host_ack <= '0';
285 
286  case c_state is
287  when st_idle =>
288  if (go = '1') then
289  if (start = '1') then
290  c_state <= st_start;
292  elsif (read = '1') then
293  c_state <= st_read;
295  elsif (write = '1') then
296  c_state <= st_write;
298  else -- stop
299  c_state <= st_stop;
301  end if;
302 
303  ld <= '1';
304  end if;
305 
306  when st_start =>
307  if (core_ack = '1') then
308  if (read = '1') then
309  c_state <= st_read;
311  else
312  c_state <= st_write;
314  end if;
315 
316  ld <= '1';
317  end if;
318 
319  when st_write =>
320  if (core_ack = '1') then
321  if (cnt_done = '1') then
322  c_state <= st_ack;
324  else
325  c_state <= st_write; -- stay in same state
326  core_cmd <= I2C_CMD_WRITE; -- write next bit
327  shift <= '1';
328  end if;
329  end if;
330 
331  when st_read =>
332  if (core_ack = '1') then
333  if (cnt_done = '1') then
334  c_state <= st_ack;
336  else
337  c_state <= st_read; -- stay in same state
338  core_cmd <= I2C_CMD_READ; -- read next bit
339  end if;
340 
341  shift <= '1';
342  core_txd <= ack_in;
343  end if;
344 
345  when st_ack =>
346  if (core_ack = '1') then
347  -- check for stop; Should a STOP command be generated ?
348  if (stop = '1') then
349  c_state <= st_stop;
351  else
352  c_state <= st_idle;
354 
355  -- generate command acknowledge signal
356  host_ack <= '1';
357  end if;
358 
359  -- assign ack_out output to core_rxd (contains last received bit)
360  ack_out <= core_rxd;
361 
362  core_txd <= '1';
363  else
364  core_txd <= ack_in;
365  end if;
366 
367  when st_stop =>
368  if (core_ack = '1') then
369  c_state <= st_idle;
371 
372  -- generate command acknowledge signal
373  host_ack <= '1';
374  end if;
375 
376  when others => -- illegal states
377  c_state <= st_idle;
379  --report ("Byte controller entered illegal state.");
380 
381  end case;
382 
383  end if;
384  end if;
385  end process nxt_state_decoder;
386 
387  end block statemachine;
388 
389 end architecture structural;
390 
in filtstd_logic_vector(( filter- 1)* dynfilt downto 0)
in clk_cntstd_logic_vector( 15 downto 0)
std_logic_vector( 3 downto 0) := "0010" I2C_CMD_STOP
std_logic_vector( 2 downto 0) :=( others => '0') dcnt
in clk_cntstd_logic_vector( 15 downto 0)
std_logic_vector( 3 downto 0) := "0000" I2C_CMD_NOP
i2c_master_bit_ctrl bit_ctrlbit_ctrl
in filtstd_logic_vector(( filter- 1)* dynfilt downto 0)
std_logic_vector( 3 downto 0) := "1000" I2C_CMD_WRITE
std_logic_vector( 3 downto 0) := "0001" I2C_CMD_START
(st_idle,st_start,st_read,st_write,st_ack,st_stop) states
out doutstd_logic_vector( 7 downto 0)
in dinstd_logic_vector( 7 downto 0)
std_logic_vector( 7 downto 0) sr
in cmdstd_logic_vector( 3 downto 0)
std_logic_vector( 3 downto 0) core_cmd
std_logic_vector( 3 downto 0) := "0100" I2C_CMD_READ