1 |
2 |
dimamali |
------------------------------------------------------------------------------
|
2 |
|
|
-- This file is a part of the GRLIB VHDL IP LIBRARY
|
3 |
|
|
-- Copyright (C) 2003, Gaisler Research
|
4 |
|
|
--
|
5 |
|
|
-- This program is free software; you can redistribute it and/or modify
|
6 |
|
|
-- it under the terms of the GNU General Public License as published by
|
7 |
|
|
-- the Free Software Foundation; either version 2 of the License, or
|
8 |
|
|
-- (at your option) any later version.
|
9 |
|
|
--
|
10 |
|
|
-- This program is distributed in the hope that it will be useful,
|
11 |
|
|
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
|
12 |
|
|
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
13 |
|
|
-- GNU General Public License for more details.
|
14 |
|
|
--
|
15 |
|
|
-- You should have received a copy of the GNU General Public License
|
16 |
|
|
-- along with this program; if not, write to the Free Software
|
17 |
|
|
-- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
18 |
|
|
-------------------------------------------------------------------------------
|
19 |
|
|
-- Entity: i2cslv
|
20 |
|
|
-- File: i2cslv.vhd
|
21 |
|
|
-- Author: Jan Andersson - Gaisler Research
|
22 |
|
|
-- jan@gaisler.com
|
23 |
|
|
--
|
24 |
|
|
-- Description: Simple I2C-slave with AMBA APB interface
|
25 |
|
|
--
|
26 |
|
|
-- Documentation of generics:
|
27 |
|
|
--
|
28 |
|
|
-- [hardaddr]
|
29 |
|
|
-- If this generic is set to 1 the core uses i2caddr as the hard coded address.
|
30 |
|
|
-- If hardaddr is set to 0 the core's address can be changed via the SLVADDR
|
31 |
|
|
-- register.
|
32 |
|
|
--
|
33 |
|
|
-- [tenbit]
|
34 |
|
|
-- Support for ten bit addresses.
|
35 |
|
|
--
|
36 |
|
|
-- [i2caddr]
|
37 |
|
|
-- The slave's (initial) i2c address.
|
38 |
|
|
--
|
39 |
|
|
-- [oepol]
|
40 |
|
|
-- Output enable polarity
|
41 |
|
|
--
|
42 |
|
|
-- The slave has four different modes operation. The mode is defined by the
|
43 |
|
|
-- value of the bits RMODE and TMODE.
|
44 |
|
|
-- RMODE TMODE I2CSLAVE Mode
|
45 |
|
|
-- 0 0 0
|
46 |
|
|
-- 0 1 1
|
47 |
|
|
-- 1 0 2
|
48 |
|
|
-- 1 1 3
|
49 |
|
|
--
|
50 |
|
|
-- RMODE 0:
|
51 |
|
|
-- The slave accepts one byte and NAKs all other transfers until software has
|
52 |
|
|
-- acknowledged the received byte.
|
53 |
|
|
-- RMODE 1:
|
54 |
|
|
-- The slave accepts one byte and keeps SCL low until software has acknowledged
|
55 |
|
|
-- the received byte
|
56 |
|
|
-- TMODE 0:
|
57 |
|
|
-- The slave transmits the same byte to all if the master requests more than
|
58 |
|
|
-- one byte in the transfer. The slave then NAKs all read requests unless the
|
59 |
|
|
-- Transmit Always Valid (TAV) bit in the control register is set.
|
60 |
|
|
-- TMODE 1:
|
61 |
|
|
-- The slave transmits one byte and then keeps SCL low until software has
|
62 |
|
|
-- acknowledged that the byte has been transmitted.
|
63 |
|
|
|
64 |
|
|
|
65 |
|
|
library ieee;
|
66 |
|
|
use ieee.std_logic_1164.all;
|
67 |
|
|
|
68 |
|
|
library gaisler;
|
69 |
|
|
use gaisler.misc.all;
|
70 |
|
|
|
71 |
|
|
library grlib;
|
72 |
|
|
use grlib.amba.all;
|
73 |
|
|
use grlib.devices.all;
|
74 |
|
|
use grlib.stdlib.all;
|
75 |
|
|
|
76 |
|
|
entity i2cslv is
|
77 |
|
|
generic (
|
78 |
|
|
-- APB generics
|
79 |
|
|
pindex : integer := 0; -- slave bus index
|
80 |
|
|
paddr : integer := 0;
|
81 |
|
|
pmask : integer := 16#fff#;
|
82 |
|
|
pirq : integer := 0; -- interrupt index
|
83 |
|
|
-- I2C configuration
|
84 |
|
|
hardaddr : integer range 0 to 1 := 0; -- See description above
|
85 |
|
|
tenbit : integer range 0 to 1 := 0;
|
86 |
|
|
i2caddr : integer range 0 to 1023 := 0;
|
87 |
|
|
oepol : integer range 0 to 1 := 0
|
88 |
|
|
);
|
89 |
|
|
port (
|
90 |
|
|
rstn : in std_ulogic;
|
91 |
|
|
clk : in std_ulogic;
|
92 |
|
|
-- APB signals
|
93 |
|
|
apbi : in apb_slv_in_type;
|
94 |
|
|
apbo : out apb_slv_out_type;
|
95 |
|
|
-- I2C signals
|
96 |
|
|
i2ci : in i2c_in_type;
|
97 |
|
|
i2co : out i2c_out_type
|
98 |
|
|
);
|
99 |
|
|
end entity i2cslv;
|
100 |
|
|
|
101 |
|
|
architecture rtl of i2cslv is
|
102 |
|
|
-----------------------------------------------------------------------------
|
103 |
|
|
-- Constants
|
104 |
|
|
-----------------------------------------------------------------------------
|
105 |
|
|
-- Core version
|
106 |
|
|
constant I2CSLV_REV : integer := 0;
|
107 |
|
|
|
108 |
|
|
-- AMBA PnP
|
109 |
|
|
constant PCONFIG : apb_config_type := (
|
110 |
|
|
|
111 |
|
|
1 => apb_iobar(paddr, pmask));
|
112 |
|
|
|
113 |
|
|
-- Register addresses
|
114 |
|
|
constant SLV_ADDR : std_logic_vector(7 downto 2) := "000000";
|
115 |
|
|
constant CTRL_ADDR : std_logic_vector(7 downto 2) := "000001";
|
116 |
|
|
constant STS_ADDR : std_logic_vector(7 downto 2) := "000010";
|
117 |
|
|
constant MSK_ADDR : std_logic_vector(7 downto 2) := "000011";
|
118 |
|
|
constant RD_ADDR : std_logic_vector(7 downto 2) := "000100";
|
119 |
|
|
constant TD_ADDR : std_logic_vector(7 downto 2) := "000101";
|
120 |
|
|
|
121 |
|
|
-- Core configuration
|
122 |
|
|
constant TENBIT_SUPPORT : integer := tenbit;
|
123 |
|
|
constant I2CADDRLEN : integer := 7 + tenbit*3;
|
124 |
|
|
constant HARDCADDR : integer := hardaddr;
|
125 |
|
|
constant I2CSLVADDR : std_logic_vector((I2CADDRLEN-1) downto 0) :=
|
126 |
|
|
conv_std_logic_vector(i2caddr, I2CADDRLEN);
|
127 |
|
|
|
128 |
|
|
-- Misc constants
|
129 |
|
|
constant I2C_READ : std_ulogic := '1'; -- R/Wn bit
|
130 |
|
|
constant I2C_WRITE : std_ulogic := '0';
|
131 |
|
|
|
132 |
|
|
constant OEPOL_LEVEL : std_ulogic := conv_std_logic(oepol = 1);
|
133 |
|
|
|
134 |
|
|
constant I2C_LOW : std_ulogic := OEPOL_LEVEL; -- OE
|
135 |
|
|
constant I2C_HIZ : std_ulogic := not OEPOL_LEVEL;
|
136 |
|
|
|
137 |
|
|
constant I2C_ACK : std_ulogic := '0';
|
138 |
|
|
|
139 |
|
|
constant TENBIT_ADDR_START : std_logic_vector(4 downto 0) := "11110";
|
140 |
|
|
|
141 |
|
|
-----------------------------------------------------------------------------
|
142 |
|
|
-- Types
|
143 |
|
|
-----------------------------------------------------------------------------
|
144 |
|
|
|
145 |
|
|
type ctrl_reg_type is record -- Control register
|
146 |
|
|
rmode : std_ulogic; -- Receive mode
|
147 |
|
|
tmode : std_ulogic; -- Transmit mode
|
148 |
|
|
tv : std_ulogic; -- Transmit valid
|
149 |
|
|
tav : std_ulogic; -- Transmit always valid
|
150 |
|
|
en : std_ulogic; -- Enable
|
151 |
|
|
end record;
|
152 |
|
|
|
153 |
|
|
type sts_reg_type is record -- Status/Mask registers
|
154 |
|
|
rec : std_ulogic; -- Received byte
|
155 |
|
|
tra : std_ulogic; -- Transmitted byte
|
156 |
|
|
nak : std_ulogic; -- NAK'd address
|
157 |
|
|
end record;
|
158 |
|
|
|
159 |
|
|
type slvaddr_reg_type is record -- Slave address register
|
160 |
|
|
tba : std_ulogic; -- 10-bit address
|
161 |
|
|
slvaddr : std_logic_vector((I2CADDRLEN-1) downto 0);
|
162 |
|
|
end record;
|
163 |
|
|
|
164 |
|
|
type i2cslv_reg_bank is record -- APB registers
|
165 |
|
|
slvaddr : slvaddr_reg_type;
|
166 |
|
|
ctrl : ctrl_reg_type;
|
167 |
|
|
sts : sts_reg_type;
|
168 |
|
|
msk : sts_reg_type;
|
169 |
|
|
receive : std_logic_vector(7 downto 0);
|
170 |
|
|
transmit : std_logic_vector(7 downto 0);
|
171 |
|
|
end record;
|
172 |
|
|
|
173 |
|
|
type i2c_in_array is array (6 downto 0) of i2c_in_type;
|
174 |
|
|
|
175 |
|
|
type slv_state_type is (idle, checkaddr, check10bitaddr, sclhold,
|
176 |
|
|
movebyte, handshake);
|
177 |
|
|
|
178 |
|
|
type i2cslv_reg_type is record
|
179 |
|
|
slvstate : slv_state_type;
|
180 |
|
|
--
|
181 |
|
|
reg : i2cslv_reg_bank;
|
182 |
|
|
irq : std_ulogic;
|
183 |
|
|
-- Transfer phase
|
184 |
|
|
active : boolean;
|
185 |
|
|
addr : boolean;
|
186 |
|
|
transmit : boolean;
|
187 |
|
|
receive : boolean;
|
188 |
|
|
-- Shift register
|
189 |
|
|
sreg : std_logic_vector(7 downto 0);
|
190 |
|
|
cnt : std_logic_vector(2 downto 0);
|
191 |
|
|
-- Synchronizers for inputs SCL and SDA
|
192 |
|
|
scl : std_ulogic;
|
193 |
|
|
sda : std_ulogic;
|
194 |
|
|
i2ci : i2c_in_array;
|
195 |
|
|
-- Output enables
|
196 |
|
|
scloen : std_ulogic;
|
197 |
|
|
sdaoen : std_ulogic;
|
198 |
|
|
end record;
|
199 |
|
|
|
200 |
|
|
-----------------------------------------------------------------------------
|
201 |
|
|
-- Subprograms
|
202 |
|
|
-----------------------------------------------------------------------------
|
203 |
|
|
-- purpose: Compares the first byte of a received address with the slave's
|
204 |
|
|
-- address. The tba input determines if the slave is using a ten bit address.
|
205 |
|
|
function compaddr1stb (
|
206 |
|
|
ibyte : std_logic_vector(7 downto 0); -- I2C byte
|
207 |
|
|
sr : slvaddr_reg_type) -- slave address register
|
208 |
|
|
return boolean is
|
209 |
|
|
variable correct : std_logic_vector(7 downto 1);
|
210 |
|
|
begin -- compaddr1stb
|
211 |
|
|
if sr.tba = '1' then
|
212 |
|
|
correct(7 downto 3) := TENBIT_ADDR_START;
|
213 |
|
|
correct(2 downto 1):= sr.slvaddr((I2CADDRLEN-1) downto (I2CADDRLEN-2));
|
214 |
|
|
else
|
215 |
|
|
correct(7 downto 1) := sr.slvaddr(6 downto 0);
|
216 |
|
|
end if;
|
217 |
|
|
return ibyte(7 downto 1) = correct(7 downto 1);
|
218 |
|
|
end compaddr1stb;
|
219 |
|
|
|
220 |
|
|
-- purpose: Compares the 2nd byte of a ten bit address with the slave address
|
221 |
|
|
function compaddr2ndb (
|
222 |
|
|
ibyte : std_logic_vector(7 downto 0); -- I2C byte
|
223 |
|
|
slvaddr : std_logic_vector((I2CADDRLEN-1) downto 0)) -- slave address
|
224 |
|
|
return boolean is
|
225 |
|
|
begin -- compaddr2ndb
|
226 |
|
|
return ibyte((I2CADDRLEN-3) downto 0) = slvaddr((I2CADDRLEN-3) downto 0);
|
227 |
|
|
end compaddr2ndb;
|
228 |
|
|
|
229 |
|
|
-----------------------------------------------------------------------------
|
230 |
|
|
-- Signals
|
231 |
|
|
-----------------------------------------------------------------------------
|
232 |
|
|
|
233 |
|
|
-- Register interface
|
234 |
|
|
signal r, rin : i2cslv_reg_type;
|
235 |
|
|
|
236 |
|
|
begin
|
237 |
|
|
|
238 |
|
|
comb: process (r, rstn, apbi, i2ci)
|
239 |
|
|
variable v : i2cslv_reg_type;
|
240 |
|
|
variable irq : std_logic_vector((NAHBIRQ-1) downto 0);
|
241 |
|
|
variable apbaddr : std_logic_vector(5 downto 0);
|
242 |
|
|
variable apbout : std_logic_vector(31 downto 0);
|
243 |
|
|
variable sclfilt : std_logic_vector(3 downto 0);
|
244 |
|
|
variable sdafilt : std_logic_vector(3 downto 0);
|
245 |
|
|
variable tba : boolean;
|
246 |
|
|
begin -- process comb
|
247 |
|
|
v := r; v.irq := '0'; irq := (others=>'0'); irq(pirq) := r.irq;
|
248 |
|
|
apbaddr := apbi.paddr(7 downto 2); apbout := (others => '0');
|
249 |
|
|
v.i2ci(0) := i2ci; v.i2ci(6 downto 1) := r.i2ci(5 downto 0); tba := false;
|
250 |
|
|
|
251 |
|
|
---------------------------------------------------------------------------
|
252 |
|
|
-- APB register interface
|
253 |
|
|
---------------------------------------------------------------------------
|
254 |
|
|
-- read registers
|
255 |
|
|
if (apbi.psel(pindex) and apbi.penable and (not apbi.pwrite)) = '1' then
|
256 |
|
|
case apbaddr is
|
257 |
|
|
when SLV_ADDR =>
|
258 |
|
|
apbout(31) := r.reg.slvaddr.tba;
|
259 |
|
|
apbout((I2CADDRLEN-1) downto 0) := r.reg.slvaddr.slvaddr;
|
260 |
|
|
when CTRL_ADDR =>
|
261 |
|
|
apbout(4 downto 0) := r.reg.ctrl.rmode & r.reg.ctrl.tmode &
|
262 |
|
|
r.reg.ctrl.tv & r.reg.ctrl.tav & r.reg.ctrl.en;
|
263 |
|
|
when STS_ADDR =>
|
264 |
|
|
apbout(2 downto 0) := r.reg.sts.rec & r.reg.sts.tra & r.reg.sts.nak;
|
265 |
|
|
when MSK_ADDR =>
|
266 |
|
|
apbout(2 downto 0) := r.reg.msk.rec & r.reg.msk.tra & r.reg.msk.nak;
|
267 |
|
|
when RD_ADDR =>
|
268 |
|
|
v.reg.sts.rec := '0';
|
269 |
|
|
apbout(7 downto 0) := r.reg.receive;
|
270 |
|
|
when TD_ADDR =>
|
271 |
|
|
apbout(7 downto 0) := r.reg.transmit;
|
272 |
|
|
when others => null;
|
273 |
|
|
end case;
|
274 |
|
|
end if;
|
275 |
|
|
|
276 |
|
|
-- write registers
|
277 |
|
|
if (apbi.psel(pindex) and apbi.penable and apbi.pwrite) = '1' then
|
278 |
|
|
case apbaddr is
|
279 |
|
|
when SLV_ADDR =>
|
280 |
|
|
if HARDCADDR = 0 then
|
281 |
|
|
if TENBIT_SUPPORT = 1 then
|
282 |
|
|
v.reg.slvaddr.tba := apbi.pwdata(31);
|
283 |
|
|
end if;
|
284 |
|
|
v.reg.slvaddr.slvaddr := apbi.pwdata((I2CADDRLEN-1) downto 0);
|
285 |
|
|
end if;
|
286 |
|
|
when CTRL_ADDR =>
|
287 |
|
|
v.reg.ctrl.rmode := apbi.pwdata(4);
|
288 |
|
|
v.reg.ctrl.tmode := apbi.pwdata(3);
|
289 |
|
|
v.reg.ctrl.tv := apbi.pwdata(2);
|
290 |
|
|
v.reg.ctrl.tav := apbi.pwdata(1);
|
291 |
|
|
v.reg.ctrl.en := apbi.pwdata(0);
|
292 |
|
|
when STS_ADDR =>
|
293 |
|
|
v.reg.sts.tra := r.reg.sts.tra and not apbi.pwdata(1);
|
294 |
|
|
v.reg.sts.nak := r.reg.sts.nak and not apbi.pwdata(0);
|
295 |
|
|
when MSK_ADDR =>
|
296 |
|
|
v.reg.msk.rec := apbi.pwdata(2);
|
297 |
|
|
v.reg.msk.tra := apbi.pwdata(1);
|
298 |
|
|
v.reg.msk.nak := apbi.pwdata(0);
|
299 |
|
|
when TD_ADDR =>
|
300 |
|
|
v.reg.transmit := apbi.pwdata(7 downto 0);
|
301 |
|
|
when others => null;
|
302 |
|
|
end case;
|
303 |
|
|
end if;
|
304 |
|
|
|
305 |
|
|
----------------------------------------------------------------------------
|
306 |
|
|
-- Bus filtering
|
307 |
|
|
----------------------------------------------------------------------------
|
308 |
|
|
for i in 0 to 3 loop
|
309 |
|
|
sclfilt(i) := r.i2ci(i+2).scl; sdafilt(i) := r.i2ci(i+2).sda;
|
310 |
|
|
end loop; -- i
|
311 |
|
|
if sclfilt = "1111" then v.scl := '1'; end if;
|
312 |
|
|
if sclfilt = "0000" then v.scl := '0'; end if;
|
313 |
|
|
if sdafilt = "1111" then v.sda := '1'; end if;
|
314 |
|
|
if sdafilt = "0000" then v.sda := '0'; end if;
|
315 |
|
|
|
316 |
|
|
---------------------------------------------------------------------------
|
317 |
|
|
-- I2C slave control FSM
|
318 |
|
|
---------------------------------------------------------------------------
|
319 |
|
|
case r.slvstate is
|
320 |
|
|
when idle =>
|
321 |
|
|
-- Release bus
|
322 |
|
|
if (r.scl and not v.scl) = '1' then
|
323 |
|
|
v.sdaoen := I2C_HIZ;
|
324 |
|
|
end if;
|
325 |
|
|
|
326 |
|
|
when checkaddr =>
|
327 |
|
|
tba := r.reg.slvaddr.tba = '1';
|
328 |
|
|
if compaddr1stb(r.sreg, r.reg.slvaddr) then
|
329 |
|
|
if r.sreg(0) = I2C_READ then
|
330 |
|
|
if (not tba or (tba and r.active)) then
|
331 |
|
|
if r.reg.ctrl.tv = '1' then
|
332 |
|
|
-- Transmit data
|
333 |
|
|
v.transmit := true;
|
334 |
|
|
v.slvstate := handshake;
|
335 |
|
|
else
|
336 |
|
|
-- No data to transmit, NAK
|
337 |
|
|
if (not v.reg.sts.nak and r.reg.msk.nak) = '1' then
|
338 |
|
|
v.irq := '1';
|
339 |
|
|
end if;
|
340 |
|
|
v.reg.sts.nak := '1';
|
341 |
|
|
v.slvstate := idle;
|
342 |
|
|
end if;
|
343 |
|
|
else
|
344 |
|
|
-- Ten bit address with R/Wn = 1 and slave not previously
|
345 |
|
|
-- addressed.
|
346 |
|
|
v.slvstate := idle;
|
347 |
|
|
end if;
|
348 |
|
|
else
|
349 |
|
|
v.receive := not tba;
|
350 |
|
|
v.slvstate := handshake;
|
351 |
|
|
end if;
|
352 |
|
|
else
|
353 |
|
|
-- Slave address did not match
|
354 |
|
|
v.active := false;
|
355 |
|
|
v.slvstate := idle;
|
356 |
|
|
end if;
|
357 |
|
|
v.sreg := r.reg.transmit;
|
358 |
|
|
|
359 |
|
|
when check10bitaddr =>
|
360 |
|
|
if compaddr2ndb(r.sreg, r.reg.slvaddr.slvaddr) then
|
361 |
|
|
-- Slave has been addressed with a matching 10 bit address
|
362 |
|
|
-- If we receive a repeated start condition, matching address
|
363 |
|
|
-- and R/Wn = 1 we will transmit data. Without start condition we
|
364 |
|
|
-- will receive data.
|
365 |
|
|
v.addr := true;
|
366 |
|
|
v.active := true;
|
367 |
|
|
v.receive := true;
|
368 |
|
|
v.slvstate := handshake;
|
369 |
|
|
else
|
370 |
|
|
v.slvstate := idle;
|
371 |
|
|
end if;
|
372 |
|
|
|
373 |
|
|
when sclhold =>
|
374 |
|
|
-- This state is used when the device has been addressed to see if SCL
|
375 |
|
|
-- should be kept low until the receive register is free or the
|
376 |
|
|
-- transmit register is filled. It is also used when a data byte has
|
377 |
|
|
-- been transmitted or received to SCL low until software acknowledges
|
378 |
|
|
-- the transfer.
|
379 |
|
|
if (r.scl and not v.scl) = '1' then
|
380 |
|
|
v.scloen := I2C_LOW;
|
381 |
|
|
v.sdaoen := I2C_HIZ;
|
382 |
|
|
end if;
|
383 |
|
|
if ((r.receive and (not r.reg.sts.rec or not r.reg.ctrl.rmode) = '1') or
|
384 |
|
|
(r.transmit and (r.reg.ctrl.tv or not r.reg.ctrl.tmode) = '1')) then
|
385 |
|
|
v.slvstate := movebyte;
|
386 |
|
|
v.scloen := I2C_HIZ;
|
387 |
|
|
end if;
|
388 |
|
|
v.sreg := r.reg.transmit;
|
389 |
|
|
|
390 |
|
|
when movebyte =>
|
391 |
|
|
if (r.scl and not v.scl) = '1' then
|
392 |
|
|
if r.transmit then
|
393 |
|
|
v.sdaoen := r.sreg(7) xor OEPOL_LEVEL;
|
394 |
|
|
else
|
395 |
|
|
v.sdaoen := I2C_HIZ;
|
396 |
|
|
end if;
|
397 |
|
|
end if;
|
398 |
|
|
if (not r.scl and v.scl) = '1' then
|
399 |
|
|
v.sreg := r.sreg(6 downto 0) & r.sda;
|
400 |
|
|
if r.cnt = "111" then
|
401 |
|
|
if r.addr then
|
402 |
|
|
v.slvstate := checkaddr;
|
403 |
|
|
elsif r.receive nor r.transmit then
|
404 |
|
|
v.slvstate := check10bitaddr;
|
405 |
|
|
else
|
406 |
|
|
v.slvstate := handshake;
|
407 |
|
|
end if;
|
408 |
|
|
v.cnt := (others => '0');
|
409 |
|
|
else
|
410 |
|
|
v.cnt := r.cnt + 1;
|
411 |
|
|
end if;
|
412 |
|
|
end if;
|
413 |
|
|
|
414 |
|
|
when handshake =>
|
415 |
|
|
-- Falling edge
|
416 |
|
|
if (r.scl and not v.scl) = '1' then
|
417 |
|
|
if r.addr then
|
418 |
|
|
v.sdaoen := I2C_LOW;
|
419 |
|
|
elsif r.receive then
|
420 |
|
|
-- Receive, send ACK/NAK
|
421 |
|
|
-- Acknowledge byte if core has room in receive register
|
422 |
|
|
-- This code assumes that the core's receive register is free if we are
|
423 |
|
|
-- in RMODE 1. This should always be the case unless software has
|
424 |
|
|
-- reconfigured the core during operation.
|
425 |
|
|
if r.reg.sts.rec = '0' then
|
426 |
|
|
v.sdaoen := I2C_LOW;
|
427 |
|
|
v.reg.receive := r.sreg;
|
428 |
|
|
if r.reg.msk.rec = '1' then
|
429 |
|
|
v.irq := '1';
|
430 |
|
|
end if;
|
431 |
|
|
v.reg.sts.rec := '1';
|
432 |
|
|
else
|
433 |
|
|
-- NAK the byte, the master must abort the transfer
|
434 |
|
|
v.sdaoen := I2C_HIZ;
|
435 |
|
|
v.slvstate := idle;
|
436 |
|
|
end if;
|
437 |
|
|
else
|
438 |
|
|
-- Transmit, release bus
|
439 |
|
|
v.sdaoen := I2C_HIZ;
|
440 |
|
|
-- Byte transmitted, unset TV unless TAV is set.
|
441 |
|
|
v.reg.ctrl.tv := r.reg.ctrl.tav;
|
442 |
|
|
-- Set status bit and check if interrupt should be generated
|
443 |
|
|
if (not v.reg.sts.tra and r.reg.msk.tra) = '1' then
|
444 |
|
|
v.irq := '1';
|
445 |
|
|
end if;
|
446 |
|
|
v.reg.sts.tra := '1';
|
447 |
|
|
end if;
|
448 |
|
|
if not r.addr and r.receive and v.sdaoen = I2C_HIZ then
|
449 |
|
|
if (not v.reg.sts.nak and r.reg.msk.nak) = '1' then
|
450 |
|
|
v.irq := '1';
|
451 |
|
|
end if;
|
452 |
|
|
v.reg.sts.nak := '1';
|
453 |
|
|
end if;
|
454 |
|
|
end if;
|
455 |
|
|
-- Risinge edge
|
456 |
|
|
if (not r.scl and v.scl) = '1' then
|
457 |
|
|
if r.addr then
|
458 |
|
|
v.slvstate := movebyte;
|
459 |
|
|
else
|
460 |
|
|
if r.receive then
|
461 |
|
|
-- RMODE 0: Be ready to accept one more byte which will be NAK'd if
|
462 |
|
|
-- software has not read the receive register
|
463 |
|
|
-- RMODE 1: Keep SCL low until software has acknowledged received byte
|
464 |
|
|
if r.reg.ctrl.rmode = '0' then
|
465 |
|
|
v.slvstate := movebyte;
|
466 |
|
|
else
|
467 |
|
|
v.slvstate := sclhold;
|
468 |
|
|
end if;
|
469 |
|
|
else
|
470 |
|
|
-- Transmit, check ACK/NAK from master
|
471 |
|
|
-- If the master NAKs the transmitted byte the transfer has ended and
|
472 |
|
|
-- we should wait for the master's next action. If the master ACKs the
|
473 |
|
|
-- byte the core will act depending on tmode:
|
474 |
|
|
-- TMODE 0:
|
475 |
|
|
-- If the master ACKs the byte we must continue to transmit and will
|
476 |
|
|
-- transmit the same byte on all requests.
|
477 |
|
|
-- TMODE 1:
|
478 |
|
|
-- IF the master ACKs the byte we will keep SCL low until software has
|
479 |
|
|
-- put new transmit data into the transmit register.
|
480 |
|
|
if r.sda = I2C_ACK then
|
481 |
|
|
if r.reg.ctrl.tmode = '0' then
|
482 |
|
|
v.slvstate := movebyte;
|
483 |
|
|
else
|
484 |
|
|
v.slvstate := sclhold;
|
485 |
|
|
end if;
|
486 |
|
|
else
|
487 |
|
|
v.slvstate := idle;
|
488 |
|
|
end if;
|
489 |
|
|
end if;
|
490 |
|
|
end if;
|
491 |
|
|
v.addr := false;
|
492 |
|
|
v.sreg := r.reg.transmit;
|
493 |
|
|
end if;
|
494 |
|
|
end case;
|
495 |
|
|
|
496 |
|
|
if r.reg.ctrl.en = '1' then
|
497 |
|
|
-- STOP condition
|
498 |
|
|
if sclfilt = "1111" and sdafilt = "0011" then
|
499 |
|
|
v.active := false;
|
500 |
|
|
v.slvstate := idle;
|
501 |
|
|
end if;
|
502 |
|
|
|
503 |
|
|
-- START or repeated START condition
|
504 |
|
|
if sclfilt = "1111" and sdafilt = "1100" then
|
505 |
|
|
v.slvstate := movebyte;
|
506 |
|
|
v.cnt := (others => '0');
|
507 |
|
|
v.addr := true;
|
508 |
|
|
v.transmit := false;
|
509 |
|
|
v.receive := false;
|
510 |
|
|
end if;
|
511 |
|
|
end if;
|
512 |
|
|
|
513 |
|
|
----------------------------------------------------------------------------
|
514 |
|
|
-- Reset and idle operation
|
515 |
|
|
----------------------------------------------------------------------------
|
516 |
|
|
|
517 |
|
|
if rstn = '0' then
|
518 |
|
|
v.slvstate := idle;
|
519 |
|
|
v.reg.slvaddr.slvaddr := I2CSLVADDR;
|
520 |
|
|
if TENBIT_SUPPORT = 1 then v.reg.slvaddr.tba := '1';
|
521 |
|
|
else v.reg.slvaddr.tba := '0'; end if;
|
522 |
|
|
v.reg.ctrl.en := '0';
|
523 |
|
|
v.reg.sts := ('0', '0', '0');
|
524 |
|
|
v.scl := '0';
|
525 |
|
|
v.active := false;
|
526 |
|
|
v.scloen := I2C_HIZ; v.sdaoen := I2C_HIZ;
|
527 |
|
|
end if;
|
528 |
|
|
|
529 |
|
|
----------------------------------------------------------------------------
|
530 |
|
|
-- Signal assignments
|
531 |
|
|
----------------------------------------------------------------------------
|
532 |
|
|
|
533 |
|
|
-- Update registers
|
534 |
|
|
rin <= v;
|
535 |
|
|
|
536 |
|
|
-- Update outputs
|
537 |
|
|
apbo.prdata <= apbout;
|
538 |
|
|
apbo.pirq <= irq;
|
539 |
|
|
apbo.pconfig <= PCONFIG;
|
540 |
|
|
apbo.pindex <= pindex;
|
541 |
|
|
|
542 |
|
|
i2co.scl <= '0';
|
543 |
|
|
i2co.scloen <= r.scloen;
|
544 |
|
|
i2co.sda <= '0';
|
545 |
|
|
i2co.sdaoen <= r.sdaoen;
|
546 |
|
|
end process comb;
|
547 |
|
|
|
548 |
|
|
reg: process (clk)
|
549 |
|
|
begin -- process reg
|
550 |
|
|
if rising_edge(clk) then
|
551 |
|
|
r <= rin;
|
552 |
|
|
end if;
|
553 |
|
|
end process reg;
|
554 |
|
|
|
555 |
|
|
-- Boot message
|
556 |
|
|
-- pragma translate_off
|
557 |
|
|
bootmsg : report_version
|
558 |
|
|
generic map (
|
559 |
|
|
"i2cslv" & tost(pindex) & ": I2C slave rev " &
|
560 |
|
|
tost(I2CSLV_REV) & ", irq " & tost(pirq));
|
561 |
|
|
-- pragma translate_on
|
562 |
|
|
|
563 |
|
|
end architecture rtl;
|