SURF  1.0
I2cMaster.vhd
Go to the documentation of this file.
1 ------------------------------------------------------------------------------
2 -- This file is a part of the GRLIB VHDL IP LIBRARY
3 -- Copyright (C) 2003 - 2008, Gaisler Research
4 -- Copyright (C) 2008 - 2012, Aeroflex Gaisler
5 --
6 -- This program is free software; you can redistribute it and/or modify
7 -- it under the terms of the GNU General Public License as published by
8 -- the Free Software Foundation; either version 2 of the License, or
9 -- (at your option) any later version.
10 --
11 -- This program is distributed in the hope that it will be useful,
12 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
13 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 -- GNU General Public License for more details.
15 --
16 -- You should have received a copy of the GNU General Public License
17 -- along with this program; if not, write to the Free Software
18 -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 -------------------------------------------------------------------------------
20 -- Entity: I2cMaster
21 -- File: I2cMaster.vhd
22 -- Author: Jan Andersson - Gaisler Research
23 -- Contact: support@gaisler.com
24 -- Description:
25 --
26 -- Generic interface to OpenCores I2C-master. This is a wrapper
27 -- that instantiates the byte- and bit-controller of the OpenCores I2C
28 -- master (OC core developed by Richard Herveille, richard@asics.ws).
29 --
30 -- Modifications:
31 -- 10/2012 - Ben Reese <bareese@slac.stanford.edu>
32 -- Removed AMBA bus register based interfaced and replaced with generic
33 -- IO interface for use anywhere within a firmware design.
34 -- Interface based on transactions consisting of a i2c device address
35 -- followed by up to 4 byte-reads or 4 byte-writes.
36 --
37 -- Dynamic filter and bus speed adjustment have been left in as features,
38 -- though they will probably be rarely used.
39 
40 library ieee;
41 use ieee.std_logic_1164.all;
42 use ieee.numeric_std.all;
43 use work.StdRtlPkg.all;
44 use work.I2cPkg.all;
45 
46 --! @see entity
47  --! @ingroup protocols_i2c
48 entity I2cMaster is
49  generic (
50  TPD_G : time := 1 ns; -- Simulated propagation delay
51  OUTPUT_EN_POLARITY_G : integer range 0 to 1 := 0; -- output enable polarity
52  FILTER_G : integer range 2 to 512 := 126; -- filter bit size
53  DYNAMIC_FILTER_G : integer range 0 to 1 := 0);
54  port (
55  clk : in sl;
56  srst : in sl := '0';
57  arst : in sl := '0';
58  -- Front End
61 
62  -- I2C signals
64  i2co : out i2c_out_type
65  );
66 end entity I2cMaster;
67 
68 architecture rtl of I2cMaster is
69  -----------------------------------------------------------------------------
70  -- Constants
71  -----------------------------------------------------------------------------
72 
73  -----------------------------------------------------------------------------
74  -- Types
75  -----------------------------------------------------------------------------
76  -- i2c_master_byte_ctrl IO
77  type ByteCtrlInType is record
78  start : sl;
79  stop : sl;
80  read : sl;
81  write : sl;
82  ackIn : sl;
83  din : slv(7 downto 0);
84  end record;
85 
86  type ByteCtrlOutType is record
87  cmdAck : sl;
88  ackOut : sl;
89  al : sl;
90  busy : sl;
91  dout : slv(7 downto 0);
92  end record;
93 
94  type StateType is (WAIT_TXN_REQ_S,
95  ADDR_S,
96  WAIT_ADDR_ACK_S,
97  READ_S,
98  WAIT_READ_DATA_S,
99  WRITE_S,
100  WAIT_WRITE_ACK_S);
101 
102  -- Module Registers
103  type RegType is record
104  byteCtrlIn : ByteCtrlInType;
105  state : StateType;
106  tenbit : sl;
108  end record RegType;
109 
110  constant REG_INIT_C : RegType := (
111  byteCtrlIn => (
112  start => '0',
113  stop => '0',
114  read => '0',
115  write => '0',
116  ackIn => '0',
117  din => (others => '0')),
118  state => WAIT_TXN_REQ_S,
119  tenbit => '0',
120  i2cMasterOut => (
121  busAck => '0',
122  txnError => '0',
123  wrAck => '0',
124  rdValid => '0',
125  rdData => (others => '0')));
126 
127 
128  --------------------------------------------------------------------------------------------------
129  -- Signals
130  --------------------------------------------------------------------------------------------------
131  -- Register interface
132  signal r : RegType := REG_INIT_C;
133  signal rin : RegType;
134 
135  -- Outputs from byte_ctrl block
136  signal byteCtrlOut : ByteCtrlOutType;
137  signal iSclOEn : sl; -- Internal SCL output enable
138  signal iSdaOEn : sl; -- Internal SDA output enablee
139  signal filter : slv((FILTER_G-1)*DYNAMIC_FILTER_G downto 0); -- filt input to byte_ctrl
140  signal arstL : sl;
141 
142 begin
143 
144  arstL <= not arst;
145 
146  -- Byte Controller from OpenCores I2C master,
147  -- by Richard Herveille (richard@asics.ws). The asynchronous
148  -- reset is tied to '1'. Only the synchronous reset is used.
149  -- OC I2C logic has active high reset.
151  generic map (
152  filter => FILTER_G,
154  port map (
155  clk => clk,
156  rst => srst,
157  nReset => arstL,
158  ena => i2cMasterIn.enable,
159  clk_cnt => i2cMasterIn.prescale,
160  start => r.byteCtrlIn.start,
161  stop => r.byteCtrlIn.stop,
162  read => r.byteCtrlIn.read,
163  write => r.byteCtrlIn.write,
164  ack_in => r.byteCtrlIn.ackIn,
165  din => r.byteCtrlIn.din,
166  filt => filter,
167  cmd_ack => byteCtrlOut.cmdAck,
168  ack_out => byteCtrlOut.ackOut,
169  i2c_busy => byteCtrlOut.busy,
170  i2c_al => byteCtrlOut.al,
171  dout => byteCtrlOut.dout,
172  scl_i => i2ci.scl,
173  scl_o => i2co.scl,
174  scl_oen => iscloen,
175  sda_i => i2ci.sda,
176  sda_o => i2co.sda,
177  sda_oen => isdaoen);
178 
180 
181  -- Fix output enable polarity
182  soepol0 : if OUTPUT_EN_POLARITY_G = 0 generate
183  i2co.scloen <= iscloen;
184  i2co.sdaoen <= isdaoen;
185  end generate soepol0;
186  soepol1 : if OUTPUT_EN_POLARITY_G /= 0 generate
187  i2co.scloen <= not iscloen;
188  i2co.sdaoen <= not isdaoen;
189  end generate soepol1;
190 
191 
192 
193 
194  comb : process (r, byteCtrlOut, i2cMasterIn, srst)
195  variable v : RegType;
196  variable indexVar : integer;
197  begin -- process comb
198  v := r;
199 
200  -- byteCtrl commands default to zero
201  -- unless overridden in a state below
202  v.byteCtrlIn.start := '0';
203  v.byteCtrlIn.stop := '0';
204  v.byteCtrlIn.read := '0';
205  v.byteCtrlIn.write := '0';
206  v.byteCtrlIn.ackIn := '0';
207 
208  v.i2cMasterOut.wrAck := '0'; -- pulsed
209  v.i2cMasterOut.busAck := '0'; -- pulsed
210 
211  if (i2cMasterIn.rdAck = '1') then
212  v.i2cMasterOut.rdValid := '0';
213  v.i2cMasterOut.txnError := '0';
214  end if;
215 
216  case (r.state) is
217  when WAIT_TXN_REQ_S =>
218  -- Reset front end outputs
219  v.i2cMasterOut.rdData := (others => '0'); -- Necessary?
220  -- If new request and any previous rdData has been acked.
221  if (i2cMasterIn.txnReq = '1') and (r.i2cMasterOut.rdValid = '0') and (r.i2cMasterOut.busAck = '0') then
222  v.state := ADDR_S;
224  end if;
225 
226  when ADDR_S =>
227  v.byteCtrlIn.start := '1';
228  v.byteCtrlIn.write := '1';
229  if (r.tenbit = '0') then
230  if (i2cMasterIn.tenbit = '0') then
231  -- Send normal 7 bit address
232  v.byteCtrlIn.din(7 downto 1) := i2cMasterIn.addr(6 downto 0);
233  v.byteCtrlIn.din(0) := not i2cMasterIn.op;
234  else
235  -- Send second half of 10 bit address
236  v.byteCtrlIn.din := i2cMasterIn.addr(7 downto 0);
237  end if;
238  else
239  -- Send first half of 10 bit address
240  v.byteCtrlIn.din(7 downto 3) := "00000";
241  v.byteCtrlIn.din(2 downto 1) := i2cMasterIn.addr(9 downto 8);
242  v.byteCtrlIn.din(0) := not i2cMasterIn.op;
243  end if;
244  v.state := WAIT_ADDR_ACK_S;
245 
246 
247  when WAIT_ADDR_ACK_S =>
248  if (byteCtrlOut.cmdAck = '1') then -- Master sent the command
249  if (byteCtrlOut.ackOut = '0') then -- Slave ack'd the transfer
250  if (r.tenbit = '1') then -- Must send second half of addr if tenbit set
251  v.tenbit := '0';
252  v.state := ADDR_S;
253  else
254  -- Do read or write depending on op
255  if (i2cMasterIn.op = '0') then
256  v.state := READ_S;
257  else
258  v.state := WRITE_S;
259  end if;
260  end if;
261  else
262  -- Slave did not ack the transfer, fail the txn
263  v.i2cMasterOut.txnError := '1';
264  v.i2cMasterOut.rdValid := '1';
266  v.state := WAIT_TXN_REQ_S;
267  end if;
268  if (r.tenbit = '0') and (i2cMasterIn.busReq = '1') then
269  v.i2cMasterOut.busAck := '1';
270  v.state := WAIT_TXN_REQ_S;
271  end if;
272  end if;
273 
274 
275  when READ_S =>
276  if (r.i2cMasterOut.rdValid = '0') then -- Previous byte has been ack'd
277  v.byteCtrlIn.read := '1';
278  -- If last byte of txn send nack.
279  -- Send stop on last byte if enabled (else repeated start will occur on next txn).
280  v.byteCtrlIn.ackIn := not i2cMasterIn.txnReq;
281  v.byteCtrlIn.stop := not i2cMasterIn.txnReq and i2cMasterIn.stop;
282  v.state := WAIT_READ_DATA_S;
283  end if;
284 
285 
286  when WAIT_READ_DATA_S =>
287  v.byteCtrlIn.stop := r.byteCtrlIn.stop; -- Hold stop or it wont get seen
288  v.byteCtrlIn.ackIn := r.byteCtrlIn.ackIn; -- This too
289  if (byteCtrlOut.cmdAck = '1') then -- Master sent the command
290  v.byteCtrlIn.stop := '0'; -- Drop stop asap or it will be repeated
291  v.byteCtrlIn.ackIn := '0';
292  v.i2cMasterOut.rdData := byteCtrlOut.dout;
293  v.i2cMasterOut.rdValid := '1';
294  if (i2cMasterIn.txnReq = '0') then -- Last byte of txn
295  v.i2cMasterOut.txnError := '0'; -- Necessary? Should already be 0
296  v.state := WAIT_TXN_REQ_S;
297  else
298  -- If not last byte, read another.
299  v.state := READ_S;
300  end if;
301  end if;
302 
303  when WRITE_S =>
304  -- Write the next byte
305  if (i2cMasterIn.wrValid = '1' and r.i2cMasterOut.wrAck = '0') then
306  v.byteCtrlIn.write := '1';
307  -- Send stop on last byte if enabled (else repeated start will occur on next txn).
308  v.byteCtrlIn.stop := not i2cMasterIn.txnReq and i2cMasterIn.stop;
309  v.byteCtrlIn.din := i2cMasterIn.wrData;
310  v.state := WAIT_WRITE_ACK_S;
311  end if;
312 
313  when WAIT_WRITE_ACK_S =>
314  v.byteCtrlIn.stop := r.byteCtrlIn.stop;
315  if (byteCtrlOut.cmdAck = '1') then -- Master sent the command
316  if (byteCtrlOut.ackOut = '0') then -- Slave ack'd the transfer
317  v.byteCtrlIn.stop := '0';
318  v.i2cMasterOut.wrAck := '1'; -- Pass wr ack to front end
319  if (i2cMasterIn.txnReq = '0') then -- Last byte of txn
320  v.i2cMasterOut.txnError := '0'; -- Necessary, should already be 0?
321  v.state := WAIT_TXN_REQ_S;
322  else
323  -- If not last byte, write nother
324  v.state := WRITE_S;
325  end if;
326  else
327  -- Slave did not ack the transfer, fail the txn
328  v.i2cMasterOut.txnError := '1';
329  v.i2cMasterOut.rdValid := '1';
331  v.state := WAIT_TXN_REQ_S;
332  end if;
333  end if;
334 
335  when others => v.state := WAIT_TXN_REQ_S;
336  end case;
337 
338  -- Must always monitor for arbitration loss
339  if (byteCtrlOut.al = '1') then
340  -- Retry the entire TXN. Nothing done has been valid if arbitration is lost.
341  -- Should probably have a retry limit.
342  v.state := WAIT_TXN_REQ_S;
343  v.i2cMasterOut.txnError := '1';
344  v.i2cMasterOut.rdValid := '1';
346  end if;
347 
348  ------------------------------------------------------------------------------------------------
349  -- Synchronous Reset
350  ------------------------------------------------------------------------------------------------
351  if (srst = '1') then
352  v := REG_INIT_C;
353  end if;
354 
355  ------------------------------------------------------------------------------------------------
356  -- Signal Assignments
357  ------------------------------------------------------------------------------------------------
358  -- Update registers
359  rin <= v;
360 
361  -- Assign outputs
363 
364  end process comb;
365  filter <= i2cMasterIn.filter when DYNAMIC_FILTER_G = 1 else (others => '0');
366 
367  reg : process (clk, arst)
368  begin
369  if (arst = '1') then
370  r <= REG_INIT_C after TPD_G;
371  elsif rising_edge(clk) then
372  r <= rin after TPD_G;
373  end if;
374  end process reg;
375 
376 
377 end architecture rtl;
sl op
Definition: I2cPkg.vhd:62
I2cMasterInType
Definition: I2cPkg.vhd:56
in filtstd_logic_vector(( filter- 1)* dynfilt downto 0)
sl rdValid
Definition: I2cPkg.vhd:75
in clk_cntstd_logic_vector( 15 downto 0)
slv( 7 downto 0) rdData
Definition: I2cPkg.vhd:76
in clksl
Definition: I2cMaster.vhd:55
OUTPUT_EN_POLARITY_Ginteger range 0 to 1:= 0
Definition: I2cMaster.vhd:51
i2c_in_type
Definition: I2cPkg.vhd:34
std_logic sl
Definition: StdRtlPkg.vhd:28
sl txnReq
Definition: I2cPkg.vhd:60
sl stop
Definition: I2cPkg.vhd:61
out i2coi2c_out_type
Definition: I2cMaster.vhd:65
in arstsl := '0'
Definition: I2cMaster.vhd:57
TPD_Gtime := 1 ns
Definition: I2cMaster.vhd:50
slv( 7 downto 0) := X"01" I2C_INVALID_ADDR_ERROR_C
Definition: I2cPkg.vhd:52
I2cMasterOutType
Definition: I2cPkg.vhd:71
DYNAMIC_FILTER_Ginteger range 0 to 1:= 0
Definition: I2cMaster.vhd:53
FILTER_Ginteger range 2 to 512:= 126
Definition: I2cMaster.vhd:52
in i2cMasterInI2cMasterInType
Definition: I2cMaster.vhd:59
slv( 7 downto 0) wrData
Definition: I2cPkg.vhd:67
i2c_out_type
Definition: I2cPkg.vhd:41
sl rdAck
Definition: I2cPkg.vhd:68
slv( 15 downto 0) filter
Definition: I2cPkg.vhd:59
sl txnError
Definition: I2cPkg.vhd:73
sl tenbit
Definition: I2cPkg.vhd:65
slv( 7 downto 0) := X"02" I2C_WRITE_ACK_ERROR_C
Definition: I2cPkg.vhd:53
in i2cii2c_in_type
Definition: I2cMaster.vhd:63
i2c_master_byte_ctrl byte_ctrlbyte_ctrl
Definition: I2cMaster.vhd:177
sl busAck
Definition: I2cPkg.vhd:72
in srstsl := '0'
Definition: I2cMaster.vhd:56
slv( 9 downto 0) addr
Definition: I2cPkg.vhd:64
out doutstd_logic_vector( 7 downto 0)
in dinstd_logic_vector( 7 downto 0)
slv( 7 downto 0) := X"03" I2C_ARBITRATION_LOST_ERROR_C
Definition: I2cPkg.vhd:54
sl busReq
Definition: I2cPkg.vhd:63
std_ulogic scloen
Definition: I2cPkg.vhd:43
sl wrValid
Definition: I2cPkg.vhd:66
out i2cMasterOutI2cMasterOutType
Definition: I2cMaster.vhd:60
std_ulogic enable
Definition: I2cPkg.vhd:46
sl wrAck
Definition: I2cPkg.vhd:74
std_ulogic sdaoen
Definition: I2cPkg.vhd:45
std_logic_vector slv
Definition: StdRtlPkg.vhd:29