|
找到一个I2C Slave的代码,可惜Verlog看不懂,发上来给大家参考% g" m. p' w! _( w' r3 ?
+ N7 X1 z* L1 V) B
///////////////////////////////////////////////////////////////////////////////
" X* `6 l, M' u. w3 w//: p( Z& k8 T' A2 J& `
// Alacron Inc. - Confidential: All Rights Reserved* K& b/ A* @2 v4 x* t( `! a
// Copyright (C) 2003
# R1 n( u2 m: R+ [//
7 T, ^; A* K+ [8 x6 t3 ~( R Z4 m, ]/ F// Title : I2C Slave Control Logic
0 I1 `6 i# g8 x H// File : I2CSLAVE.v/ U' n! t, F! d9 s6 _4 J2 |
// Author : Gabor Szakacs
8 d' `2 _5 U2 I8 c0 k// Created : 25-May-2004 - Adapted from I2CSLAVE.abl6 V' n# K- t: X( G7 Y5 k
//8 {+ s6 m* ]6 \8 l. x) A
//) z8 M) x' ]& u- X& [
///////////////////////////////////////////////////////////////////////////////! x: u# m7 d. V. M; H
//
2 x* N, u8 Z3 N6 h% x; u# |// Description :- W# {; S8 w' x. T' X' M
// This code implements an I2C slave-only controller.
7 j+ s) A3 a, _// Access to internal registers uses the sub-address
% e- C! T% q9 G- `9 ~; H// protocol like a serial EEPROM. No registers are+ n- s# N0 ?! C3 e2 X- C6 G% d
// implemented in this module, however the module- O( E1 I. a1 [1 ?4 j
// provides a simple bus interface to external registers.
6 Z! A0 B6 l; Q) X; t$ W& ^* {// GLS - 12/13/00% ]1 S' [9 K! y8 h0 [3 {* n0 e
// I2C inputs are oversampled by clk_in, which should run
7 R5 d" h0 ]6 s2 O// at a minimum of 5 MHz for a 100 KHz I2C bus. The, f, E8 b( a1 K) I
// debouncing on the inputs has been tested at up to 80 MHz.+ U6 u+ R8 N6 O2 K# w% H. ?
// The I2C 7-bit device address is set by i2c_address. Address" w j8 f' m4 r$ s, [! d
// 0x6A was selected for FastImage because it doesn't1 w+ z9 ]& A3 i2 u- G6 W8 _
// conflict with other devices on board.
$ g- P7 N) }$ i& ?- n1 s// Because of limitations in Xilinx Abel, the I/O buffers/ v, J# w0 T, I, F O$ b$ m- M6 s
// for the I2C SDA and SCL signals were external to this" P: Q6 z: N, U4 R) }
// macro.
% d5 B0 r4 `9 m// Three 8-bit buses are implemented for read data, write' r9 p% P3 @: Z9 i: `
// data and subaddress. For a simple implementation where$ L2 z) U }4 W- v
// only one 8-bit register is required, the subaddress may0 `7 a$ Q9 W; Q2 e% {
// be used as the register output using simple write and$ {, e* U( H1 T2 C; `$ {2 l: [
// read protocol on the I2C bus. In this case looping the
3 B+ E$ O8 {0 b) F// subaddress output to the read data bus allows register
, b3 L. T5 f) W# i$ g// read-back./ U5 B2 N; x, q8 W/ O4 v9 q8 G
// For use with multiple internal registers, the subaddress O6 k! N5 w5 r l: R
// provides the register address. The rd_wr_out output indicates! f6 P' d4 U& e5 q) v/ {. l8 i
// the direction of the current I2C bus transaction and may* l5 y1 O, P3 A! p+ l* M: d" G
// be used to enable read data onto an externally combined" ?; J8 P+ [ p( b9 V% ?% J1 ?
// read/write data bus. The wr_pulse_out signal can be used as
# g, X. O- s! H, c9 m// an active-high latch enable or clock enable for the
4 L0 R7 s& a# ~* Z' n6 P2 v" j2 H// external registers. It comes on for one period of clk_in/ m5 g# G5 ~# i' k+ C$ ?
// and the subaddress and data are valid for at least one5 ^ w- L8 i5 W% p" A% e6 y9 K6 r
// clk_in period before and after wr_pulse_out.
, i4 s0 @/ d' P0 D// A rd_pulse_out output goes high for one clk_in period at the s% n' F8 g1 c$ f3 |
// beginning of each data byte read. This indicates the' _3 ]3 K1 x, [ x6 {$ a
// time when external data is latched from the read data: y! Z# x7 b% P8 N' t3 J* R4 i
// bus. It may be used to create side-effects on read
6 R; |- z8 m4 m& b6 r9 K" h! g: I// such as clearing sticky status bits.
; R3 J& s3 N% u: s# L: u//
9 Y+ w2 V* g+ j///////////////////////////////////////////////////////////////////////////////
( M; H& ]- w" v0 V; @6 e( X7 G//
6 }6 c) S% }: s" Z7 Z0 h- v6 m7 b// Modules Instantiated: none
: @% ]" @0 Y) C3 q" T//0 V* ~! E% i( m+ C
///////////////////////////////////////////////////////////////////////////////4 c+ N. Z3 v0 L8 ^
//
% h4 q8 T- u$ Y9 C9 h% N// Modification History:# X! ]6 Q! y/ B% R* U; K2 R$ z
//
- P" F, O9 k* X) T// Added clock enable to slow down state logic with fast input clock
, a; y( c8 S6 `* X4 G* V' b// 6/9/05 - GLS.
- h1 B* `( j% H//* L l; _% L% E- F, |
//
/ J6 R6 W0 o2 e2 K: L( b8 r: p///////////////////////////////////////////////////////////////////////////////
/ k6 ?6 N3 M9 s( f/ A0 L2 g* z* z///////////////////////////////////////////////////////////////////////////////
8 J' e0 G# Q/ g5 r$ m0 E///////////////////////////////////////////////////////////////////////////////# B R, X, R+ A3 k( g: i
`timescale 1 ns / 100 ps t7 W- n' N! f- X0 _" H2 L
module I2Cslave
+ x3 u1 ]. v& R- x. ~9 U5 b, \(
! Y6 D: i& l5 A4 P' X1 K sda_io,
" W2 ] E# `8 m I3 h0 \ scl_in,$ l f8 @1 R* O$ R/ X" n3 w
rd_bus_7_0_in,8 F" A' B+ R, b( ~" J y: V7 R, k
clk_in,
& p Z! o- H; E clr_in,. ^8 l5 S) |3 `, a/ R
subaddr_7_0_out,
8 U. Z; x' Z! w5 z: o) i wr_bus_7_0_out,$ ?9 I0 N, ]( [! W
wr_pulse_out,& _& H" K' B R' q s
rd_pulse_out,. I F `( Y3 d. f+ \& b3 z' Q$ b- u
rd_wr_out; O/ X0 f/ Y4 N) A( n2 _0 I
);
~9 {1 z8 b* U7 ]( F7 \* o7 `// Inputs:6 ~7 |- ^6 s/ G7 g6 @4 E$ ]( v
// I2C inputs (SDA is I/O externally)
3 w4 V- U7 K+ B1 y& s- U. {; N- dinout sda_io; _" Y" w+ E9 b$ ]7 C
input scl_in;
9 N0 p- M5 C" r// 8-bit bus for reading registers
% O, I5 b) U7 q Y" y0 s4 vinput [7:0] rd_bus_7_0_in;/ R. G! i8 g J6 D/ _
// High-speed clock for state machine logic
* g7 Y9 H7 A! m( _, ~' iinput clk_in;$ X6 b1 A! n# D K5 x( ^. @
// Asynchronous reset can be grounded for synthesis
0 ^3 M( F5 c9 Linput clr_in;6 d: I9 T) j E: T1 \
// Outputs:
5 u. P7 M9 }/ w6 ^+ c1 R! r4 R' ^) j& U// 8-bit subaddress for register selection1 V2 @3 J$ p6 ~5 f" }
output [7:0] subaddr_7_0_out;
% e- } Q# L5 I; B' P0 l$ ?8 i( e. dreg [7:0] subaddr_7_0_out;0 c' }4 D3 v/ E0 i
// 8-bit bus for writing registers( p3 N. H0 E+ ?
output [7:0] wr_bus_7_0_out;
" p6 |) t9 @0 X2 Q( Mreg [7:0] wr_bus_7_0_out;' q" B1 @5 V- C' W* }
// I2C data output drive low signal (1 = drive SDA low)
3 L+ \, O9 ~& \6 i5 ^# J4 C/ Vreg drive_sda;6 P7 k$ |* t! K& k! y9 `1 u
// Register write pulse. On for one clk_in cycle.
0 m- O- p' ^+ m+ \. W Coutput wr_pulse_out;% l S9 A( [6 M1 L; J7 r
reg wr_pulse_out;/ p/ y: B& x. o# o
// Register read pulse. On for one clk_in cycle.8 P) u8 J& x9 { ^4 Q
output rd_pulse_out;; c- F& k) |7 R( B4 {
reg rd_pulse_out;
+ Q9 z/ _+ C' f$ x* J// Read / not Write. For external bus drivers if necessary.
) J2 g) e- [8 Z7 x4 T# Joutput rd_wr_out;1 }8 V, D+ e9 o9 R7 [7 _
reg rd_wr_out;
( l, Y" h4 Y6 Q; t" ~: l3 {, F; b// Internal Nodes:2 D5 v" ` j* R( Q4 e
// I2C input debounced nodes: T8 k/ D4 h3 }1 y1 l
reg [3:0] sda_sr, scl_sr;
# I9 H4 x7 m. V- F/ c" M* Ireg sda, scl;7 d V9 Y3 `4 h* M" S
// I2C edge detection nodes:+ T" @' e4 B' l0 S& O% [! J1 w
reg was_sda, was_scl; V. X& @+ n- f% Z+ f
// Delayed pulses for address increment:: d8 |: W5 D8 E& U
reg rd_pls_dly, wr_pls_dly;
6 ]3 n; y4 T. z# Z" ~// I2C protocol state nodes: u$ I4 I& Z) S6 b
reg i2c_start, i2c_stop;% c) l. N; k7 N
reg [2:0] byte_count;
2 f R; J; ^, _ V1 `8 F+ f% ?reg ack_cyc;6 `: u, r4 d! W. _) ]& ~# x$ }' y
reg addr_byte, addr_ack, subad_byte, subad_ack, data_byte;" ^( P( c3 @( t B2 S6 y0 ^
// Edge detection:
3 V; ? {0 V+ F( u; m9 Dreg was_ack;
+ L- m w' G. i- ~* U: preg my_cyc;
3 w7 ^* I, e7 @- Y// Input data shift register5 _* Q) K1 U' _* v; a9 K
reg [7:0] in_sr;" V& q; f+ j; S( p% P
// Output data shift register: U( M- j }) ~# t" t9 a. o
reg [7:0] out_sr;
6 c- T0 l+ m. ?$ m9 T p% y2 Z// internal node for bidirectional SDA line:
, r- T) d6 t8 ]+ r' M! swire sda_in;" _! c& E1 ^6 V& M. l; c6 o
IBUF sda_ibuf (.I (sda_io), .O (sda_in));0 N; f) j! }1 |' h. [1 a' j/ Q! u
OBUFE sda_obuf (.I (1'b0), .E (drive_sda), .O (sda_io));
5 O6 C* P1 \- wparameter i2c_address = 7'b0110101; // 6A write, 6B read: d; b& W# g0 H% r- U$ K
7 _+ ]0 a, [) K* T& j# _7 z// Equations; z- N: k9 O' c1 i. b
// Debounce, then delay debounced signals for edge detection
0 q6 m1 h* l2 O1 I! xalways @ (posedge clk_in or posedge clr_in)( e( V2 `* s$ n. _
if (clr_in)
1 U* t) h# E$ I3 l( E; j begin
. O! w2 z7 t8 s sda_sr <= 4'b1111; // Start up assuming quiescent state of inputs. L2 Q/ Q. U3 T0 ~( t/ @8 B
sda <= 1;
' |6 Y2 X& w! ^* i6 j5 ^ was_sda <= 0;
$ M9 |( y3 ]" {9 e( M scl_sr <= 4'b1111; // Start up assuming quiescent state of inputs6 [, e1 N& e, V$ h8 Z$ W% j
scl <= 1;
' ]- q4 P$ O- C% q4 b9 G, d& W8 t was_scl <= 0;! T Z$ ^3 F8 J1 r" }% i9 P Z
end- k* k' P0 j) F0 t1 n
else: Y6 n9 c" ]$ i2 g* G, E" c
begin
( [5 x( U: f+ e4 s0 X5 c sda_sr <= {sda_sr[2:0], sda_in};3 ]- z4 u% T. R/ }8 r7 Y0 B! c
if (sda_sr == 4'b0000) sda <= 0;
" N/ w, |2 w' ?; M& }! z+ M else if (sda_sr == 4'b1111) sda <= 1;: J& s; g7 V( f3 W4 M
was_sda <= sda;8 i# q3 y# I* ^6 J1 J
scl_sr <= {scl_sr[2:0], scl_in};
, s n6 G. L$ T( {' H- \8 L6 } if (scl_sr == 4'b0000) scl <= 0;
; H. I1 o7 T, j! C8 ` else if (scl_sr == 4'b1111) scl <= 1;1 l: {0 ?: ~: C1 A$ n
was_scl <= scl;) j" Q( ~7 }! D$ [& b2 n. x
end
/ m6 W& S) y# ]. Q% b6 L: b" p// Detect start and stop conditions on I2C bus:
z1 B* R! z, \. o% yalways @ (posedge clk_in or posedge clr_in)) e1 P7 m" D7 y& J; Q) l
if (clr_in)
, L" y, L- i. ^ begin
* |* |. Q- q+ N# L i2c_start <= 0;
% S$ a8 e% i x% O% X6 k/ | i2c_stop <= 0;" K6 ? Q1 V- g& g8 D y
end
6 y; I: T! }3 ?' }* s5 y else# H/ |7 l; e/ F4 `; I* j/ E
begin8 d( C4 s5 l2 a f- \; ?
if (scl & was_scl & !sda & was_sda) i2c_start <= 1; // Falling edge of SDA with SCL high
( H) i/ Y0 C+ }: T# J$ d# e0 N else if (!scl & !was_scl) i2c_start <= 0; // Hold until SCL has fallen
% o9 i( o1 y: j) `" u8 H i2c_stop <= scl & was_scl & sda & !was_sda ; // Rising edge of SDA with SCL high! Y% v h6 ~" W
// i2c_stop is only on for one clock cycle/ ~3 g; z( |2 t7 a$ y: V/ [
end4 V5 Q1 ]2 n9 ? G
// Increment bit counter on falling edges of the$ L P& Z8 s) X8 i) S' A
// SCL signal after the first in a packet.
; w: l! Q0 [2 K. G5 B// Count bit position within bytes:
+ d/ ], U* `2 A7 valways @ (posedge clk_in or posedge i2c_start)% P/ l5 \$ Z, M: F! V7 i7 B. |
if (i2c_start); T$ H1 ^2 K$ M+ K1 X
begin1 i u9 G2 j; n: Z) [% N+ {+ J
ack_cyc <= 0;, ]) Y' b) b# ^1 M: n
byte_count <= 0;
4 O' g! |$ y. M' w, s5 b end
9 e# p2 Z, {4 V: l else if (!scl & was_scl & !i2c_start)/ W$ V2 G0 t' L D, A- W
begin
( z; l9 Z" M. T- [7 ]1 L // ack_cyc is really bit 3 of byte_count, counting from 0 to 8/ g, ~% x4 B& v6 R
{ack_cyc,byte_count} <= ack_cyc ? 0 : {ack_cyc,byte_count} + 1;
5 u6 r7 q0 d) R end Z" g3 J6 \+ [* F2 j+ d8 D/ m
// For edge detection of ack cycles:
9 W, l9 F: L' p8 o" kalways @ (posedge clk_in or posedge clr_in)
/ Z; q: Q% i( j if (clr_in)5 g0 T8 g+ ?! ?. U5 s7 t
begin
1 @, C9 l: M9 c7 M. c was_ack <= 0;* y \8 R, K: I( z
end" p% H" p& K1 O- `: o8 e) Q$ M3 o0 s
else
|5 p9 C/ D, [5 r3 _ begin( e5 b b t( r+ i& [0 ]
was_ack <= ack_cyc;
8 R% I" g2 v$ y: @7 d end
4 Q& y" S; B. p+ Y) H/ v$ Jalways @ (posedge clk_in or posedge clr_in)
, \4 \3 `6 F( T% V, y0 a* l2 J if (clr_in)
$ I# J" y+ D- E. v( R9 W begin3 B7 X" J3 t* |; k. Q
addr_byte <= 0;( v/ p2 _$ l, O9 l
addr_ack <= 0;
5 y$ I6 Y. I( f1 C) [3 z subad_byte <= 0;3 u! _' j- G/ A
subad_ack <= 0;
" j5 f0 z& ?( Y- w& i wr_pulse_out <= 0;
/ v, N+ M; s2 ~ C7 i$ D2 \ rd_pulse_out <= 0;
# G+ \0 g0 _+ e; K) G- ~1 z end
5 G8 t; G: c/ r# t( T else4 l) P! p+ M6 C4 j+ ~2 X0 t6 P% _1 @9 W
begin* d g; n' Q2 f t1 h( p
// addr_byte is on during the first byte transmitted after
: O0 e* E$ t4 i // a START condition.
4 s7 z U% r/ J# C+ L if (i2c_start) addr_byte <= 1;- N0 G1 l7 R/ E8 ^
else if (ack_cyc) addr_byte <= 0;
6 X2 Y3 g) D4 ^5 Q) o y4 k // addr_ack is on during acknowledge cycle of the address
; u! E! w! V& s5 X7 z$ Y0 ~( K // byte.! n4 F- H* T0 W7 l+ z2 D
if (addr_byte & ack_cyc) addr_ack <= 1;
$ Y1 \% M0 c1 X6 I- }% p e else if (!ack_cyc) addr_ack <= 0;
, d2 ?* f" c, n ^3 S9 @ // subad_byte is on for the second byte of my write cycle.
0 B+ M- `2 P2 e# k if (addr_ack & !ack_cyc & !rd_wr_out & my_cyc) subad_byte <= 1;& A. u3 W$ B1 I" ^" Z
else if (ack_cyc) subad_byte <= 0;2 K- v9 e* d G
// subad_ack is on during the acknowledge cycle of the
+ K4 @" |8 E8 Z: j // subaddress byte.. y2 p# c: `* ]
if (subad_byte & ack_cyc) subad_ack <= 1;
8 w5 }: q( ^& r# `" G' M" r else if (!ack_cyc) subad_ack <= 0;7 Q6 q1 U* Z) r( c$ f, C4 i
// data_byte is on for my read or write data cycles. This is/ ]1 t. p6 ?# r$ ]# k' O
// any read cycle after the address, or write cycles after! o6 p+ {# |# x/ O9 B4 }
// the subaddress. It remains on until the I2C STOP event or
) J# G' J# P6 v9 k2 h$ h9 W- _ // any NACK.( O9 R6 |# ^4 _2 ?7 N' l
if (addr_ack & !ack_cyc & rd_wr_out & my_cyc | subad_ack & !ack_cyc) data_byte <= 1;
+ W l8 K4 G3 O0 E0 s* z else if (i2c_stop | ack_cyc & scl & sda) data_byte <= 0;
. D0 A! m2 J3 R& K. a // wr_pulse_out is on for one clock cycle while the data
8 Z$ I* I+ i0 J0 g# y% C // on the output bus is valid.
' o" M) I# B& l* {9 Z wr_pulse_out <= data_byte & !ack_cyc & was_ack & !rd_wr_out;9 `8 h: W* Q, f( C- r
// rd_pulse_out is on for one clock cycle when external
$ G: m8 O4 g9 K$ Q G // read data is transfered into the output shift register
% k u4 R' n+ ]5 } H9 M // for transmission to the I2C bus.# n8 ~( `5 u6 b6 s
rd_pulse_out <= addr_ack & !ack_cyc & rd_wr_out & my_cyc // First read cycle
9 x/ ?6 D7 ]7 Y0 q+ `* m* _; s | data_byte & !ack_cyc & was_ack & rd_wr_out ; // Subsequent read cycles. K% ]9 Q- x; I& n! D
end, }4 ^- L i" _: T/ H. x
// wr_bus_7_0_out is loaded from the I2C input S/R at the1 a! `8 u+ G- {8 q3 U3 H. W# u
// end of each write data cycle.1 t/ o3 _' j) S; c; \. r2 Y2 N
always @ (posedge clk_in or posedge clr_in)
- b2 U% D) C8 i+ J3 e2 m+ n if (clr_in)
: N% [ O7 c6 A+ @/ {2 h begin2 t7 s% u( n0 @2 v, _1 }8 @: K
wr_bus_7_0_out <= 0;
$ R9 D- y! @. d0 ?+ v9 ~8 G end
" r# w6 l5 R1 J/ W( j/ q" s, k else if (data_byte & ack_cyc & !was_ack & !rd_wr_out)
! x8 a6 Q7 D G+ j# V begin
4 f5 U0 x. J9 y1 s; j wr_bus_7_0_out <= in_sr;5 L' n5 _% c: K
end7 \6 S( X) G0 {6 w
// out_sr shifts data out to the I2C bus during read
" v. p: \$ b }2 F5 o// data cycles. Transitions occur after the falling' u6 @" Q1 Y5 c( m
// edge of SCL. Fills with 1's from right.
) R# i) U$ i( l2 Balways @ (posedge clk_in or posedge clr_in)
6 E/ W; I4 O2 g) U if (clr_in)) @' d" ^3 H4 p
begin8 j& a# g+ ~- w0 S6 k9 |4 y
out_sr <= 8'b11111111;
4 n! n: [, [" o" O end
; F% Q2 l. y+ E5 w& F else
. S& q5 q# s0 y; X$ ?/ O o/ _ begin1 R5 U1 i5 E4 T, M) W
if (rd_pulse_out) out_sr <= rd_bus_7_0_in;( M' t; M, P( U- g
else if (!scl & was_scl) out_sr <= {out_sr[6:0],1'b1};
5 G h9 m. W8 d& [8 f end7 D6 Q' k6 u+ [) r- w6 y
// Delayed pulses for incrementing subaddress:
5 M3 T/ O! Q0 e1 Zalways @ (posedge clk_in or posedge clr_in)/ x3 K( t5 l! \4 Q
if (clr_in)7 x% M- h+ B3 U
begin) E# Y7 \+ U3 F* N8 c
wr_pls_dly <= 0;5 w* {, Q, K# C: r, k6 H
rd_pls_dly <= 0;) y2 T2 A; Y5 B
end
( V% L B' G; \2 n: u. { else5 [" n `7 c( ^5 K$ ^+ `7 Q) E& n
begin+ ^5 n9 M, h W$ A
wr_pls_dly <= wr_pulse_out;# ?. B6 C2 }$ A& H
rd_pls_dly <= rd_pulse_out;
! l; |+ l0 T( d1 h% Y7 c end; l6 p4 V$ M! ?) |- w+ Z/ [$ O
// subaddr_7_0_out is loaded after the second byte of a write
/ {$ t# M! Q) n/ f6 g1 t// cycle has fully shifted in. It increments after each6 X9 F) v2 }$ V8 r7 p
// read or write access.
3 a, f$ b2 u# b) G f5 Halways @ (posedge clk_in or posedge clr_in)
0 Z G2 @# d- U, g if (clr_in)/ y% o2 c% v+ ^) c- a- S' d) [
begin
8 m7 D8 c2 X7 i subaddr_7_0_out <= 0;5 T( B- a3 k$ O6 o
end
' I& Y+ f: P. C/ S' U else: P& }; N- R( r; v- y' U
begin
5 W: v! k4 }) S/ Y' i if (subad_byte & ack_cyc) subaddr_7_0_out <= in_sr;
% m: v) J3 v; E: r) H // Leave Out this else clause for simple single register version
2 F8 ?. A7 G8 B6 s9 x // In this case subaddr_7_0_out becomes the register output and should be: h f3 x' P# I; z
// wrapped back to rd_bus_7_0_in externally
, I: _) l- x3 p1 \% `6 H3 f else if (wr_pls_dly | rd_pls_dly) subaddr_7_0_out <= subaddr_7_0_out + 1;
, u% T! H( j0 j6 H, ^# a4 q end
5 P2 u9 T2 q: [* P// Shift I2C data in after rising edge of SCL.& [5 x; {8 x6 S/ n$ \( S
always @ (posedge clk_in or posedge clr_in)) w9 V+ o4 d- A+ l
if (clr_in). v! z& I |3 b# w
begin
8 ~* \$ }8 t, b/ F( x9 l6 d8 b; \ in_sr <= 0;
, T6 i) ^5 _% i! W end
0 ^- b% `0 _3 m& [' b- n. a else if (scl & !was_scl)
3 y# s5 v. { K" J5 r% S! { begin
0 o7 z; u& F: u. B; C/ { in_sr <= {in_sr[6:0],sda};
! p. Q2 y, u) E end' h9 [+ c& k( u2 K' x7 D$ ^
// Read / not Write. For external bus drivers if necessary.
% Y3 g" h# s5 r7 O// Latch the Read bit of the address cycle.
- ]/ o/ R+ G( u6 ?$ }. @9 Y! _ [always @ (posedge clk_in or posedge clr_in)
, R3 s3 N* P3 D5 k if (clr_in)
5 ^- i9 g& c0 b9 J4 w8 v7 f8 [ begin/ m4 q) `3 b$ x* f. V: Q
rd_wr_out <= 0;
$ }1 F& U8 V. ~ end
9 t$ \% B: P( x6 X2 f; b* L7 \. n; r else if (addr_byte & ack_cyc)
2 K1 o) @( O5 T8 _! o0 \/ c begin) \2 t( X+ B. y1 R. a
rd_wr_out <= in_sr[0];
" Z! V; o3 C3 s0 f0 L5 S+ F end* H( G Q5 A4 e4 w+ s
// Decode address. My cycle if address upper 7 bits2 R) q' M" x3 s/ a+ j- R. Q0 ^
// match with i2c_address defined above.
9 a1 l0 e# M* K1 q+ }1 palways @ (posedge clk_in or posedge i2c_start)9 X+ W" Z' j* n6 J
if (i2c_start)
* J' Q1 R0 b- M2 e' i" E$ y begin/ I8 |0 o0 J( `- q: l+ R
end* y0 h, ?+ }! @& p3 T
else if (addr_byte & ack_cyc)
, Y# L* X c+ r0 n begin1 ]3 b' Z# v' P0 S, E M) X. R
my_cyc <= (in_sr[7:1] == i2c_address);- V% i$ C& o' N; F1 L# Q
end
1 q& H% y) _3 _- s+ o7 S// I2C data output drive low signal (1 = drive SDA low)% s8 l0 T2 i' F0 k5 Z
// Invert this signal for T input of OBUFT or IOBUF3 p; V& q/ H5 A9 C3 j" J
// or use it directly for OBUFE.4 C$ U. j' g0 \# m
always @ (posedge clk_in or posedge clr_in)
! F: i5 |# g2 C6 n! x if (clr_in)7 R3 d! T3 J3 B, {/ P0 u
begin
. z- W! w% p& L drive_sda <= 0;
. ^% l6 O6 D; R. ~ end1 K( R+ ^ Z; u. x; V
else
$ I! J; E$ L6 i/ n' m begin. ] W. B1 N1 v( B
drive_sda <= my_cyc & addr_ack // Address acknowledge. R0 c3 y G. S' R3 k
| my_cyc & !rd_wr_out & ack_cyc // Write byte acknowledge
$ K2 G' k# S* q4 [3 I/ q | data_byte & rd_wr_out & !ack_cyc & !out_sr[7] ; // Read Data
% o6 s2 w4 j# D5 u" A4 p end
) C7 J; R/ X( ^9 q e* C: k( Wendmodule // I2Cslave |
|