OpenCores
URL https://opencores.org/ocsvn/i2c/i2c/trunk

Subversion Repositories i2c

[/] [i2c/] [trunk/] [bench/] [verilog/] [i2c_slave_model.v] - Blame information for rev 10

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 10 rherveille
//
2
// I2C slave model
3
//
4
 
5
`include "timescale.v"
6
 
7
module i2c_slave_model (scl, sda);
8
 
9
        //
10
        // parameters
11
        //
12
        parameter I2C_ADR = 7'b001_0000;
13
 
14
        //
15
        // input && outpus
16
        //
17
        input scl;
18
        inout sda;
19
 
20
        //
21
        // Variable declaration
22
        //
23
        reg [7:0] mem [3:0]; // initiate memory
24
        reg [7:0] mem_adr;   // memory address
25
        reg [7:0] mem_do;    // memory data output
26
 
27
        reg sta, d_sta;
28
        reg sto, d_sto;
29
 
30
        reg [7:0] sr;        // 8bit shift register
31
        reg       rw;        // read/write direction
32
 
33
        wire      my_adr;    // my address called ??
34
        wire      i2c_reset; // i2c-statemachine reset
35
        reg [2:0] bit_cnt;   // 3bit downcounter
36
        wire      acc_done;  // 8bits transfered
37
        reg       ld;        // load downcounter
38
 
39
        reg       sda_o;     // sda-drive level
40
 
41
        // statemachine declaration
42
        parameter idle        = 3'b000;
43
        parameter slave_ack   = 3'b001;
44
        parameter get_mem_adr = 3'b010;
45
        parameter gma_ack     = 3'b011;
46
        parameter data        = 3'b100;
47
        parameter data_ack    = 3'b101;
48
 
49
        reg [2:0] state; // synopsys enum_state
50
 
51
        //
52
        // module body
53
        //
54
 
55
        initial
56
                begin
57
                        sda_o = 1'b1;
58
                        state = idle;
59
                end
60
 
61
        // generate shift register
62
        always@(posedge scl)
63
                sr <= #1 {sr[6:0],sda};
64
 
65
        //detect my_address
66
        assign my_adr = (sr[7:1] == I2C_ADR);
67
 
68
        //generate bit-counter
69
        always@(posedge scl)
70
                if (ld)
71
                        bit_cnt <= #1 3'b111;
72
                else
73
                        bit_cnt <= #1 bit_cnt - 3'h1;
74
 
75
        //generate access done signal
76
        assign acc_done = !(|bit_cnt);
77
 
78
        //detect start condition
79
        always@(negedge sda)
80
                if (scl)
81
                        sta <= #1 1'b1;
82
                else
83
                        sta <= #1 1'b0;
84
 
85
        always@(posedge scl)
86
                d_sta <= #1 sta;
87
 
88
        // detect stop condition
89
        always@(posedge sda)
90
                if (scl)
91
                        sto <= #1 1'b1;
92
                else
93
                        sto <= #1 1'b0;
94
 
95
        //generate i2c_reset signal
96
        assign i2c_reset = sta || sto;
97
 
98
        // generate statemachine
99
        always@(negedge scl or posedge sto)
100
                if (sto || (sta && !d_sta) )
101
                        begin
102
                                state <= #1 idle; // reset statemachine
103
 
104
                                sda_o <= #1 1'b1;
105
                                ld    <= #1 1'b1;
106
                        end
107
                else
108
                        begin
109
                                // initial settings
110
                                sda_o <= #1 1'b1;
111
                                ld    <= #1 1'b0;
112
 
113
                                case (state) // synopsys full_case parallel_case
114
                                        idle: // idle state
115
                                                if (acc_done && my_adr)
116
                                                                begin
117
                                                                        state <= #1 slave_ack;
118
                                                                        rw <= #1 sr[0];
119
 
120
                                                                        sda_o <= #1 1'b0; // generate i2c_ack
121
                                                                end
122
 
123
                                        slave_ack:
124
                                                begin
125
                                                        if (rw)
126
                                                                begin
127
                                                                        state <= #1 data;
128
                                                                        sda_o <= #1 mem_do[7];
129
                                                                end
130
                                                        else
131
                                                                state <= #1 get_mem_adr;
132
 
133
                                                        ld    <= #1 1'b1;
134
                                                end
135
 
136
                                        get_mem_adr: // wait for memory address
137
                                                if (acc_done)
138
                                                        begin
139
                                                                state <= #1 gma_ack;
140
                                                                mem_adr <= #1 sr; // store memory address
141
 
142
                                                                sda_o <= #1 !(sr <= 15); // generate i2c_ack, for valid address
143
                                                        end
144
 
145
                                        gma_ack:
146
                                                begin
147
                                                        state <= #1 data;
148
                                                        ld    <= #1 1'b1;
149
                                                end
150
 
151
                                        data: // receive or drive data
152
                                                begin
153
                                                        if (rw)
154
                                                                sda_o <= #1 mem_do[7];
155
 
156
                                                        if (acc_done)
157
                                                                begin
158
                                                                        state <= #1 data_ack;
159
 
160
                                                                        mem_adr <= #1 mem_adr + 8'h1;
161
 
162
                                                                        if (!rw)
163
                                                                                mem[ mem_adr[3:0] ] <= #1 sr; // store data in memory
164
 
165
                                                                        sda_o <= #1 (rw && (mem_adr <= 15) ); // send ack on write, receive ack on read
166
                                                                end
167
                                                end
168
 
169
                                        data_ack:
170
                                                begin
171
                                                        ld    <= #1 1'b1;
172
 
173
                                                        if (rw)
174
                                                                if (sda) // read operation && master send NACK
175
                                                                        begin
176
                                                                                state <= #1 idle;
177
                                                                                sda_o <= #1 1'b1;
178
                                                                        end
179
                                                                else
180
                                                                        begin
181
                                                                                state <= #1 data;
182
                                                                                sda_o <= #1 mem_do[7];
183
                                                                        end
184
                                                        else
185
                                                                begin
186
                                                                        state <= #1 data;
187
                                                                        sda_o <= #1 1'b1;
188
                                                                end
189
                                                end
190
 
191
                                endcase
192
                        end
193
 
194
        // read data from memory
195
        always@(posedge scl)
196
                if (acc_done)
197
                        mem_do <= #1 mem[mem_adr];
198
                else
199
                        mem_do <= #1 {mem_do[6:0], 1'b1}; // insert 1'b1 for host ack generation
200
 
201
        // generate tri-states
202
        assign sda = sda_o ? 1'bz : 1'b0;
203
 
204
endmodule
205
 
206
 
207
 
208
 
209
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.