TA的每日心情 | 奋斗 2019-11-21 15:17 |
---|
签到天数: 1 天 [LV.1]初来乍到
|
找到一个I2C Slave的代码,可惜Verlog看不懂,发上来给大家参考
) }3 |1 o3 I4 }' Q$ V
6 D# ~' x( {2 t8 I$ z/ o+ U% l5 j6 w/////////////////////////////////////////////////////////////////////////////// B- ?6 f. C5 B- ~0 O
//2 i, c; Q2 M5 x# k# w2 e8 @
// Alacron Inc. - Confidential: All Rights Reserved0 g5 Z0 k8 |2 u
// Copyright (C) 2003
. i1 r# `) U' V3 m//3 V4 q# j5 u4 |" Q% c4 R4 Z/ s
// Title : I2C Slave Control Logic
. ~. w' T9 ]( _! X// File : I2CSLAVE.v
( Y* h, M: e3 O! f// Author : Gabor Szakacs( u: Z' V0 R$ K- `/ z0 V
// Created : 25-May-2004 - Adapted from I2CSLAVE.abl
' Z4 h/ j/ |( L1 w: W- i U9 T//
5 [1 _$ `6 q7 v- n! y& ~, ~//( c, L8 S. @, ^5 Q0 D7 D9 O' h
///////////////////////////////////////////////////////////////////////////////
. X& T' C3 I) F" y// H9 f+ O" [+ C2 W& ^" U
// Description :
N2 s2 I- J- a// This code implements an I2C slave-only controller., x( Z: ^, l: x1 n( s0 K' ]0 I
// Access to internal registers uses the sub-address
; i! ]' }2 G* N! ^9 t, O// protocol like a serial EEPROM. No registers are
) E; a% F' G% S( j' r// implemented in this module, however the module
2 e& R+ I7 d9 I) E' P U6 V( o* G// provides a simple bus interface to external registers.
8 i0 I7 T9 w3 ?- O// GLS - 12/13/009 k5 T4 r; i3 z, t
// I2C inputs are oversampled by clk_in, which should run; J8 X& U0 A! b' Z2 N
// at a minimum of 5 MHz for a 100 KHz I2C bus. The
; s+ l' G. l) Z" }) u// debouncing on the inputs has been tested at up to 80 MHz., |3 K9 R% h# @' l
// The I2C 7-bit device address is set by i2c_address. Address
- n9 L [, |3 k- f+ W: L3 [// 0x6A was selected for FastImage because it doesn't' x1 m/ A4 O" h) M
// conflict with other devices on board." R5 A* c' |) k& z1 l1 ~
// Because of limitations in Xilinx Abel, the I/O buffers) @. b P4 Z" H4 B8 \
// for the I2C SDA and SCL signals were external to this2 F7 ^& W5 u4 J; y# |+ l
// macro.9 h5 `1 }1 d3 w8 p$ u1 s- I
// Three 8-bit buses are implemented for read data, write. ]8 C1 k7 D& l
// data and subaddress. For a simple implementation where ]* [+ @9 s3 E4 j% `- c' p9 D
// only one 8-bit register is required, the subaddress may! O2 A6 ^. a/ N) s# n
// be used as the register output using simple write and* g* ?# g1 r, F! `8 P$ P/ R; Z
// read protocol on the I2C bus. In this case looping the
% `; A9 K* ^7 A4 v) V% ^9 f// subaddress output to the read data bus allows register7 p; G- T) o# m& k5 O
// read-back. R7 d+ t. f9 C; p/ s4 }
// For use with multiple internal registers, the subaddress
& W* }# {# n, Y. k// provides the register address. The rd_wr_out output indicates+ _1 e& p2 F( D6 [$ F2 p
// the direction of the current I2C bus transaction and may, @4 p6 R) y2 [% s; |* k$ \/ M1 s ?
// be used to enable read data onto an externally combined
3 _& P% @) b! ?7 E+ {) a; E// read/write data bus. The wr_pulse_out signal can be used as& X( X' E J' D7 t+ [
// an active-high latch enable or clock enable for the
6 @$ D$ K$ R5 B' N- e, i// external registers. It comes on for one period of clk_in
3 @2 ^* L5 h; h) W3 Z. @// and the subaddress and data are valid for at least one, N- n& ?" U6 C! O+ @+ k2 e
// clk_in period before and after wr_pulse_out.* J/ z- l$ o4 e% Z0 \3 T. t+ ]- }" ]
// A rd_pulse_out output goes high for one clk_in period at the: y1 s1 v0 [) t* _7 B _
// beginning of each data byte read. This indicates the
5 Y9 ]1 \0 N' B. I* c! _// time when external data is latched from the read data0 M0 K9 F: i4 K8 d3 K+ c) }; Z
// bus. It may be used to create side-effects on read1 `/ J6 f4 @' W8 x# H! z
// such as clearing sticky status bits.
3 ~6 G: M$ Z: } v//7 D- |4 w" c. Y2 Q* Z5 A$ u
///////////////////////////////////////////////////////////////////////////////
9 e* E2 R- V, n- u4 c- b//
" o2 }2 x4 c, I0 e// Modules Instantiated: none0 S% m3 N8 v' z
//
5 U* |$ d. B5 T5 u! @3 K( X4 v/////////////////////////////////////////////////////////////////////////////// q, F( A, w- @3 t, u7 f
//
2 |9 d% n* ]( c8 n// Modification History:7 o& r. K u1 K
//& X9 d+ u3 a# v5 a q8 V$ J
// Added clock enable to slow down state logic with fast input clock
9 Q# c- |! E8 P: R" [" p. j// 6/9/05 - GLS.( x" Y, t$ z1 F- w' z0 t9 v; Z2 ^
//
3 l. f) A5 m) u3 Y) ]//* Y' B! B+ [7 g2 Q4 M0 ~, \! N
//////////////////////////////////////////////////////////////////////////////// \5 D% c* ?- z! \, \9 O
///////////////////////////////////////////////////////////////////////////////
0 f* y3 w$ R# c2 z0 O; M///////////////////////////////////////////////////////////////////////////////: t" h6 P% C. H K" ~1 c- K2 F9 E
`timescale 1 ns / 100 ps# E1 {3 @' ~3 R" ]% ^
module I2Cslave
7 r& {: O$ y5 m% n( ~ e! m" h(
% A( ~% R8 b- k$ x, W0 k sda_io,7 p5 G. F: P2 P4 @
scl_in,
' _( D+ W. q5 X W rd_bus_7_0_in,. t5 l6 ?! p; A7 {: ~; A6 n) D
clk_in,
( o' v# ~; }% {6 R: |! D6 c1 H clr_in,$ I0 J, B* g" ?- m* A5 z* q
subaddr_7_0_out,( b% |' X1 f! R0 i& K* F- k# Z+ \
wr_bus_7_0_out,' h6 J6 p/ F3 ^9 q# h, ]* f! d3 f
wr_pulse_out,
$ @ w) B0 j2 A& V# B8 M- ~ rd_pulse_out,; ^9 A$ ^$ p+ `' k
rd_wr_out& {- `3 h& s5 l6 k2 c
);
) w/ l* M1 {* y# r. B// Inputs:. p! w: Q# [6 f& b9 o
// I2C inputs (SDA is I/O externally)- t1 Q( S- v% `2 a- S" k; w
inout sda_io;
( X) J3 R6 `: X5 A2 [0 Einput scl_in;
( l' R2 f3 f5 f+ a// 8-bit bus for reading registers
5 o3 `5 h/ j$ Q& S2 h/ Tinput [7:0] rd_bus_7_0_in;$ Z0 m8 E) a, L3 Y- F% i8 O
// High-speed clock for state machine logic
4 J5 V" ?& M1 d* D n0 \input clk_in;
& A$ J* ` |! [% y4 t// Asynchronous reset can be grounded for synthesis
1 S$ B, O \/ o8 {3 binput clr_in;8 M# L5 ~1 L! s: h' W
// Outputs:
3 _( v0 J% W" `! P- [2 }1 L# v: ?// 8-bit subaddress for register selection
$ ?' \* p# l( n/ u( H, ioutput [7:0] subaddr_7_0_out;6 z) R# M- M% E7 o( G1 K
reg [7:0] subaddr_7_0_out;* F7 u$ g% ?1 m
// 8-bit bus for writing registers4 k1 C6 `" u/ M5 j' N% \
output [7:0] wr_bus_7_0_out;& D5 p" M% h0 o Q
reg [7:0] wr_bus_7_0_out;
- v+ o/ H: j5 q/ \- D; A; ^/ s// I2C data output drive low signal (1 = drive SDA low)7 b8 Y- |" X* E
reg drive_sda;: a" A) C9 J8 J3 C3 O
// Register write pulse. On for one clk_in cycle.
) B! f" b8 A9 @; G1 W; P6 voutput wr_pulse_out;
/ K% c6 c8 S; I& g' Y" Z# Y- d) |reg wr_pulse_out;
5 ]* e" n; e' N/ D4 H// Register read pulse. On for one clk_in cycle., h9 ?! x4 y" {5 k6 V% c( o
output rd_pulse_out;
( m% D' r' N0 u+ Y; x, `reg rd_pulse_out;
; A+ y$ t, W1 ]( ~// Read / not Write. For external bus drivers if necessary.
* J' L J# t9 V5 f# ?; soutput rd_wr_out;
}7 O! i- Q3 e6 a: f2 f0 Qreg rd_wr_out;
. ~; @4 y; ~, h// Internal Nodes:% O0 s5 p+ c, H4 }
// I2C input debounced nodes:
^# ?+ V7 h5 C! a: |reg [3:0] sda_sr, scl_sr;) D2 J" x6 T8 F
reg sda, scl;8 W4 b( W! }. E4 f$ C
// I2C edge detection nodes:! U- b J8 [. h
reg was_sda, was_scl;8 _4 ^+ c7 N; [
// Delayed pulses for address increment:
( G4 }- F4 u+ i9 {, Preg rd_pls_dly, wr_pls_dly;# t$ }) H& _$ T q& Q$ _; w8 `
// I2C protocol state nodes:/ d& X( x7 t) Q8 K9 ^ K( G
reg i2c_start, i2c_stop;1 s- |; v4 r( E- S7 H F1 M: `7 ~
reg [2:0] byte_count;6 a F& ?# Y/ Q/ K% ]# R
reg ack_cyc;4 S4 a/ R; O( O! K
reg addr_byte, addr_ack, subad_byte, subad_ack, data_byte;
( M( E) |' h# Y9 y" q// Edge detection:
) S! V- B# g; D! f; ^& q9 sreg was_ack;
" z3 y: O9 Q: A# i, x( O: K: creg my_cyc;
4 B$ |5 O2 E7 S. Q// Input data shift register1 z! p* _6 O8 d5 u0 t; f9 _
reg [7:0] in_sr;
6 k" h2 g/ G1 E" p6 y& k+ c3 J// Output data shift register( f+ L# v4 i" x( O: e
reg [7:0] out_sr;
5 s. m2 G+ i h// internal node for bidirectional SDA line:. f7 h+ }( L \$ }
wire sda_in;
5 @! }7 [1 W- X1 JIBUF sda_ibuf (.I (sda_io), .O (sda_in));
8 t* W. u" Q7 b- s8 |& f' |2 MOBUFE sda_obuf (.I (1'b0), .E (drive_sda), .O (sda_io));4 i G# K3 R7 H# \# R5 l2 p" l
parameter i2c_address = 7'b0110101; // 6A write, 6B read7 h" H! c1 \8 j3 S! x% }" ]% t
+ _) ]- O; o2 G4 C& I1 {// Equations. T. I& `8 H, D# G# s/ d8 l
// Debounce, then delay debounced signals for edge detection
. c3 M e, c* M9 lalways @ (posedge clk_in or posedge clr_in)
( V# e% c1 W# N9 g1 Y3 k if (clr_in)
, o) [* ?' U% P4 Z) b) V( j' s5 x6 k7 W begin5 e, C) Z/ D+ \/ G% N6 y; R
sda_sr <= 4'b1111; // Start up assuming quiescent state of inputs
?, c# w" b) _3 i( [ sda <= 1;
6 ~9 ^6 b2 y% ?( k6 O* b7 K* U was_sda <= 0;
* Z' h$ |( u9 |; {, j scl_sr <= 4'b1111; // Start up assuming quiescent state of inputs
/ ^1 ?2 r0 `' P- V) V% @ scl <= 1;
9 v4 q7 M& G$ W was_scl <= 0;) G; \' x j! s( B K1 T2 b$ w
end D# p( N- v" J$ u
else9 r+ |0 t9 p6 a$ V0 k
begin& v. H- c; I4 I |- C: K
sda_sr <= {sda_sr[2:0], sda_in};) ~6 {) H, [: t1 {
if (sda_sr == 4'b0000) sda <= 0;
. M5 u$ ]% W4 I! p! m! W else if (sda_sr == 4'b1111) sda <= 1;9 t$ D2 O- @" Q$ Q$ @* _
was_sda <= sda;- i; s# O4 R+ p- p
scl_sr <= {scl_sr[2:0], scl_in};. q1 q- R7 k' i9 z% q a
if (scl_sr == 4'b0000) scl <= 0;3 i! F* I8 i. G& s0 X) l, o0 r0 B
else if (scl_sr == 4'b1111) scl <= 1;' [7 x6 V4 ]) N7 P
was_scl <= scl;( |) l5 n' Q9 N! P l9 ~$ c
end$ F; ^' u( z1 }- G
// Detect start and stop conditions on I2C bus:6 }5 g# G# u/ U6 T: y* \1 K7 b( a
always @ (posedge clk_in or posedge clr_in)! k f2 c$ s# G9 N$ U1 R
if (clr_in)1 |! h' [' r/ ^. ~
begin
7 o8 a/ V/ v" v) ` i2c_start <= 0;
% v' k% s+ G! a2 i# V2 l i2c_stop <= 0;- e; ~- D3 V1 c' l) j
end# k5 @7 ^8 z' o+ N' S7 D, e
else+ A' A& `( N5 c7 N4 |5 I% n
begin
3 ]+ ~2 ^; C7 H6 q( B1 ^% s9 [ if (scl & was_scl & !sda & was_sda) i2c_start <= 1; // Falling edge of SDA with SCL high0 L4 G% @# O' G3 x, X( v4 F
else if (!scl & !was_scl) i2c_start <= 0; // Hold until SCL has fallen0 ] b2 v6 w( [- B8 k
i2c_stop <= scl & was_scl & sda & !was_sda ; // Rising edge of SDA with SCL high9 \% |# f8 y8 K* q( I* w
// i2c_stop is only on for one clock cycle8 B3 ~3 t! y: }' a" [5 A5 w
end8 i% e7 A( _ I) L& |& p7 O' f* B
// Increment bit counter on falling edges of the8 A7 z2 k/ Z. e- C2 f# f3 v
// SCL signal after the first in a packet.
0 a0 _5 \7 }7 c3 W3 _) R# O; k3 \// Count bit position within bytes:5 W7 s! y5 Q4 E5 ]
always @ (posedge clk_in or posedge i2c_start)
# }# m3 J) e6 v! K% I1 Y if (i2c_start)
* p5 N$ H* ]& N; V% j# Q r$ Q begin6 W; H9 i! S( o: l% X$ c9 b* @
ack_cyc <= 0;
) _' P0 L' A. U/ S" k byte_count <= 0;
0 @' ~ `0 }1 w end
) J5 N! c$ v7 ?( L% v% s else if (!scl & was_scl & !i2c_start)" Z0 N1 T. t3 p9 J- Q! Q- i$ S& i' |1 t
begin1 o7 M$ J- v- P; p. z( E6 t2 D
// ack_cyc is really bit 3 of byte_count, counting from 0 to 8
, c7 W' @' `! C' `) Q# w( `. ^ {ack_cyc,byte_count} <= ack_cyc ? 0 : {ack_cyc,byte_count} + 1;
/ x) ^' A! L; h# i: v; @& D9 z end
$ x+ P. _8 A) w. C% J// For edge detection of ack cycles:
/ \6 c) _; x V- valways @ (posedge clk_in or posedge clr_in)
7 a4 H3 x. F% s$ m$ \ if (clr_in)
) I( w' S* O x6 J begin5 @ \' m* x V% g" ]8 \
was_ack <= 0;
0 H' i0 M* L( M) e0 g) z0 s, @ end0 `& ] h) n3 I) w' ?
else
' M( o7 N, C) J+ G3 x) N begin4 n5 P$ c! ?$ _, ^2 W. d4 |$ C. ^
was_ack <= ack_cyc;
9 C* r; l9 o( E }+ Z end
9 c6 j8 G3 J1 @- walways @ (posedge clk_in or posedge clr_in)
/ @# R6 w( ], P( w/ J if (clr_in). _2 i' f- C' k( T
begin9 |8 J# s3 a8 P: N
addr_byte <= 0; ]) F T6 k1 F( ?) y% K- V
addr_ack <= 0;" c- i; r2 r+ P( E: s3 {
subad_byte <= 0;
" l7 A& R9 \8 N: g' r subad_ack <= 0;& Q6 W. a7 ^6 l0 p! x: P
wr_pulse_out <= 0;- V& p7 `0 R; j- r% R: M
rd_pulse_out <= 0;+ q3 |" @( I; F9 r6 i
end
- D# i: w C3 Y+ _ else
* i# f% j6 y: W l begin
* c& O2 ^; }: `$ s // addr_byte is on during the first byte transmitted after! U) J& _; x6 [) ?9 n& s: U
// a START condition.- j9 V% G+ L6 O1 x( P2 M
if (i2c_start) addr_byte <= 1;( \+ @$ k/ J! x* k
else if (ack_cyc) addr_byte <= 0;
; n9 I. T$ x9 q // addr_ack is on during acknowledge cycle of the address
. @# J' i; s, H8 B* ? // byte.
1 x G% P- t% g0 f$ A+ g5 D( a if (addr_byte & ack_cyc) addr_ack <= 1;
9 m" K4 M) j/ W4 Y$ f( } else if (!ack_cyc) addr_ack <= 0;+ Q7 O- D& W# `
// subad_byte is on for the second byte of my write cycle.0 e, g7 r8 F4 I4 S
if (addr_ack & !ack_cyc & !rd_wr_out & my_cyc) subad_byte <= 1;
' N1 u: n! V4 X* z else if (ack_cyc) subad_byte <= 0;7 Z" O/ l. A, u- N8 r
// subad_ack is on during the acknowledge cycle of the
b, N: {4 ^: A5 t( d6 D1 f // subaddress byte.6 K8 }: _% G, ^7 B2 s; H
if (subad_byte & ack_cyc) subad_ack <= 1; A; u; F! l7 |7 b
else if (!ack_cyc) subad_ack <= 0;
+ _ t' ^# g. f: Y // data_byte is on for my read or write data cycles. This is
5 T& M5 N6 X5 v& S+ W* r' C // any read cycle after the address, or write cycles after
- O0 W! Z" z$ i) [) G // the subaddress. It remains on until the I2C STOP event or) E% {& |- W: u0 \ A& ~+ B# ]0 P* y
// any NACK.8 l/ S2 v+ v# {* g0 s
if (addr_ack & !ack_cyc & rd_wr_out & my_cyc | subad_ack & !ack_cyc) data_byte <= 1;& q/ S* Q$ f! q% a3 L6 l/ @
else if (i2c_stop | ack_cyc & scl & sda) data_byte <= 0;- t2 I2 K$ l# r# J$ b! s0 d
// wr_pulse_out is on for one clock cycle while the data
8 j$ g$ B$ C0 |/ @ // on the output bus is valid.! w' m) h. g7 ?8 ]: D
wr_pulse_out <= data_byte & !ack_cyc & was_ack & !rd_wr_out;; S* b( `) l5 c1 f$ Y
// rd_pulse_out is on for one clock cycle when external
5 Y- x0 Q' o j1 O( O // read data is transfered into the output shift register, @* h# A9 {" _! ]8 M* \/ Z
// for transmission to the I2C bus./ _% r2 y0 R! y; J
rd_pulse_out <= addr_ack & !ack_cyc & rd_wr_out & my_cyc // First read cycle
( f$ C7 i+ v0 ~. K, r1 _( y9 t | data_byte & !ack_cyc & was_ack & rd_wr_out ; // Subsequent read cycles% P. f4 o' R4 G. i
end, a: l+ W! L- C
// wr_bus_7_0_out is loaded from the I2C input S/R at the
& [& ^3 T- R$ J( f; r, r// end of each write data cycle.
O* D c" K7 T) s! y, ~always @ (posedge clk_in or posedge clr_in)" Q0 t( @2 N1 x6 j' v
if (clr_in)) q1 n% K8 |5 s0 z4 Z! W
begin
: X9 \5 T7 b3 `" q% h ?+ i wr_bus_7_0_out <= 0;% g4 `! K2 p' n5 _. @
end
1 z l; ? A8 m. m else if (data_byte & ack_cyc & !was_ack & !rd_wr_out)
* V" q$ n/ a Q begin& _4 n* M r: O% ^% }/ {! ^6 S
wr_bus_7_0_out <= in_sr;
6 d+ R4 l5 N0 c) x end( O- c. \0 f& v, z+ [. L
// out_sr shifts data out to the I2C bus during read
/ N& o; }8 F/ T; c// data cycles. Transitions occur after the falling
/ ^' J- e0 H. ?// edge of SCL. Fills with 1's from right.- k5 ^5 S+ k" g; s+ |
always @ (posedge clk_in or posedge clr_in)
# L3 r8 y0 h% H2 m# A R7 a if (clr_in)" f& x9 Z; L" y8 O2 A) f5 R# m
begin8 c$ S& S. ^3 P8 f4 B: n; x
out_sr <= 8'b11111111;3 b7 G& J# i6 @' S/ h' Y
end/ Y2 C5 B! z+ r! c2 l
else$ q5 ^0 ?. M& l) U- ?) _4 Q
begin, j o( `; d( d7 F/ N2 F @
if (rd_pulse_out) out_sr <= rd_bus_7_0_in;
1 e" L* D* x: z& E# p0 [) F else if (!scl & was_scl) out_sr <= {out_sr[6:0],1'b1};
# M4 {- {* s6 C$ Z$ p9 \/ @) R end6 u6 Q! T9 ^: o$ P* m" D3 }9 J
// Delayed pulses for incrementing subaddress: R; E* N( c' f# d
always @ (posedge clk_in or posedge clr_in)
) @$ w9 h$ @+ `" s3 l$ Q if (clr_in)
- j+ |1 U0 \) ~6 B begin
' e* g* W$ r9 M* F1 e4 e* N o7 f wr_pls_dly <= 0;1 }: k. B9 ]6 U4 v' ^* m# }- f) k
rd_pls_dly <= 0;3 i4 P& c- a& H
end
7 d) ^( s% `" `/ H0 P& H1 Q5 v% Z8 G else/ Y Z2 G1 N, H$ x
begin
3 g8 O' P+ g, k, \/ l- o9 s3 }- O wr_pls_dly <= wr_pulse_out;
. i, m) v4 `! h& g3 z a2 o w rd_pls_dly <= rd_pulse_out;
! I" [) ]6 X, c0 s end
2 t/ B7 B+ X4 T# a4 D0 i// subaddr_7_0_out is loaded after the second byte of a write
1 y, C* Q- S; Q0 s$ A$ w- P0 x// cycle has fully shifted in. It increments after each4 d% F# g9 ^! K
// read or write access. f+ A; c/ Q3 G7 }( p, b5 ?
always @ (posedge clk_in or posedge clr_in)( D U# m: _6 D# O, h. o
if (clr_in)
5 d5 Y0 {" l* ?8 k begin' {2 M0 t) E& b' t
subaddr_7_0_out <= 0;' X- x" }2 u) w: `9 U" }
end
, {- E. q# ]7 V3 e else
! y4 Y' V. U8 A+ G/ y4 @ begin
, E. ~: X- x4 d5 D) I- m if (subad_byte & ack_cyc) subaddr_7_0_out <= in_sr;' B9 Y, W V3 r* {/ w) a. ^
// Leave Out this else clause for simple single register version
- A3 n% p; g& p& d8 E // In this case subaddr_7_0_out becomes the register output and should be0 M4 t* a* _3 a4 ^
// wrapped back to rd_bus_7_0_in externally
1 A! Q z/ J; `% u7 i( Y else if (wr_pls_dly | rd_pls_dly) subaddr_7_0_out <= subaddr_7_0_out + 1;
8 E& m) u6 s$ \# o* ^6 ] end
* _5 u2 ~9 U5 ]( v* L// Shift I2C data in after rising edge of SCL.
& e1 \/ A) ^5 nalways @ (posedge clk_in or posedge clr_in)+ @/ A# X O6 p2 E, F; l
if (clr_in)4 L7 g9 C3 v" a6 X1 r- G
begin. p( A# g7 }. C$ P, H
in_sr <= 0;
$ G2 k9 G; H% v+ T1 V end/ |; Z% r5 n4 [
else if (scl & !was_scl)
" p' p! i9 @% m" r* _% \ begin
$ y) w! e5 g/ G9 [, ]$ a in_sr <= {in_sr[6:0],sda};
1 @0 C3 ?- ^/ R; X% F; m end
" O3 _' ~4 N, \1 G r8 E// Read / not Write. For external bus drivers if necessary.* _" Q8 {* O+ d: w$ P' q& g% }' `
// Latch the Read bit of the address cycle.
. O( L4 q0 H5 malways @ (posedge clk_in or posedge clr_in)
; o! e5 e g, G* a if (clr_in)
9 c7 z8 s# X2 E# i y begin+ G$ h# t( d) g
rd_wr_out <= 0;
5 Z% R7 m$ ~8 `- u$ I end: M+ \( I$ R: v
else if (addr_byte & ack_cyc)3 ?4 V- A, O/ Y" `! e5 l0 S
begin
* w8 f6 ]3 ~) N! e$ v rd_wr_out <= in_sr[0];5 }4 u8 ~$ z4 `2 A# l
end4 S3 u4 C2 ]" l4 U. L6 u
// Decode address. My cycle if address upper 7 bits0 Q# p" X* P3 k/ z8 C
// match with i2c_address defined above.3 h0 D+ S/ q! l" p7 b
always @ (posedge clk_in or posedge i2c_start)
. W; o% _* G- Z if (i2c_start)3 y( ?; _2 a( u
begin
" A/ h9 _0 ]+ O1 x4 a4 M3 @- d end0 D% g$ C- Z* Y z6 m( i' S
else if (addr_byte & ack_cyc)
' {" R& J5 P7 G0 I begin
) t! ?- z: X0 j- P6 ^( P* V my_cyc <= (in_sr[7:1] == i2c_address);
' Q& i$ U# W( ]* `' X) G end! I# n1 d( }' B
// I2C data output drive low signal (1 = drive SDA low)
1 w4 h# T& ?* ~8 i! @// Invert this signal for T input of OBUFT or IOBUF+ r% k* P+ F+ H4 w4 Z0 H. I5 k
// or use it directly for OBUFE." z( k a' S0 o
always @ (posedge clk_in or posedge clr_in)9 G$ x- g, d6 L8 X4 b! N) W9 e
if (clr_in)
! D* G6 c0 B# O1 S: a begin
/ x. K9 k& a E& G2 A$ N. Z( v drive_sda <= 0;) p: z" {& s1 B* a6 q, x. |$ g9 ?
end* u$ }0 [6 c7 L
else
# h1 g2 w" e+ E begin
# V* A- M1 ^% P drive_sda <= my_cyc & addr_ack // Address acknowledge
+ L2 `9 m$ I; r8 j# y | my_cyc & !rd_wr_out & ack_cyc // Write byte acknowledge# [% l' Q2 {) e, T
| data_byte & rd_wr_out & !ack_cyc & !out_sr[7] ; // Read Data
: x. h6 `, q1 Z, L end
M% h+ q; i3 ?endmodule // I2Cslave |
|