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

Subversion Repositories attiny_atmega_xmega_core

[/] [attiny_atmega_xmega_core/] [trunk/] [rtl/] [io/] [twi_s.v] - Blame information for rev 15

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 7 morgothcre
/*
2
 * This IP is a TWI IO adapter implementation.
3
 *
4
 * Copyright (C) 2018  Iulian Gheorghiu
5
 *
6
 * This program is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU General Public License
8
 * as published by the Free Software Foundation; either version 2
9
 * of the License, or (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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19
 */
20
 
21
`timescale 1ns / 1ps
22
 
23
`include "io_s_h.v"
24
 
25
module twi_s #(
26
        parameter DINAMIC_BAUDRATE = "TRUE",
27
        parameter BAUDRATE_DIVIDER = 255,
28
        parameter ADDRESS = 0,
29
        parameter BUS_ADDR_DATA_LEN = 16
30
    )(
31
        input rst,
32
        input clk,
33
        input [BUS_ADDR_DATA_LEN-1:0]addr,
34
        input wr,
35
        input rd,
36
        input [7:0]bus_in,
37
        output reg[7:0]bus_out,
38
        output int_tx_cmpl,
39
        output int_rx_cmpl,
40
        input int_tx_rst,
41
        input int_rx_rst,
42
 
43
        inout scl,
44
        inout sda
45
    );
46
 
47
reg [7:0]CTRLA;
48
reg [7:0]CTRLB;
49
reg [7:0]CTRLC;
50
reg [7:0]STATUS;
51
reg [7:0]BAUD;
52
reg [7:0]DATA;
53
 
54
wire cs_int = addr >= ADDRESS && addr < (ADDRESS + 16);
55
wire rd_int = cs_int && rd;
56
wire wr_int = cs_int && wr;
57
 
58
reg [7:0]baud_cnt;
59
reg [1:0]cmd;
60
reg tx_mode;
61
reg start_sent;
62
reg rcv_ack;
63
reg send_ack;
64
reg send_ack_st2;
65
reg [1:0]stage;
66
reg [2:0]bit_count;
67
reg scl_int;
68
reg sda_int;
69
reg send_ack_int;
70
 
71
localparam [2:0]CMD_NOP = {1'b1, 2'b00};
72
localparam [2:0]CMD_RESTART = {1'b0, 2'b01};
73
localparam [2:0]CMD_RECEIVE = {1'b0, 2'b10};
74
localparam [2:0]CMD_STOP = {1'b0, 2'b11};
75
 
76
always @ (*)
77
begin
78
        bus_out <= 'hz;
79
        if(rd_int)
80
        begin
81
                case(addr[3:0])
82
                `TWI_MASTER_CTRLA: bus_out <= CTRLA;
83
                `TWI_MASTER_CTRLB: bus_out <= CTRLB;
84
                `TWI_MASTER_CTRLC: bus_out <= CTRLC;
85
                `TWI_MASTER_STATUS: bus_out <= STATUS;
86
                `TWI_MASTER_BAUD: bus_out <= BAUD;
87
                `TWI_MASTER_DATA: bus_out <= DATA;
88
                endcase
89
        end
90
end
91
 
92
always @ (posedge clk or posedge rst)
93
begin
94
        if(rst)
95
        begin
96
                CTRLA <= 'h0;
97
                CTRLB <= 'h0;
98
                CTRLC <= 'h0;
99
                STATUS <= 'h0;
100
                BAUD <= 'h0;
101
                DATA <= 'h0;
102
                baud_cnt <= 'h00;
103
                cmd <= 'h00;
104
                tx_mode <= 1'b0;
105
                start_sent <= 1'b0;
106
                scl_int <= 1'b1;
107
                sda_int <= 1'b1;
108
                rcv_ack <= 1'b0;
109
                send_ack <= 1'b0;
110
                send_ack_st2 <= 1'b0;
111
                stage <= 'h00;
112
                send_ack_int <= 1'b1;
113
        end
114
        else
115
        begin
116
                if(DINAMIC_BAUDRATE == "TRUE" ? baud_cnt == BAUD : baud_cnt == {BAUDRATE_DIVIDER})
117
                begin
118
                        baud_cnt <= 'h00;
119
                        if(CTRLA[`TWI_MASTER_ENABLE_bp])
120
                        begin
121
                                case({tx_mode, cmd})
122
                                CMD_NOP:
123
                                begin
124
                                        if(~start_sent)
125
                                        begin/* Send the start sequence */
126
                                                stage <= stage + 1;
127
                                                case(stage)
128
                                                'h0:
129
                                                begin
130
                                                        scl_int <= 1'b1;
131
                                                        sda_int <= 1'b0;
132
                                                end
133
                                                'h1:
134
                                                begin
135
                                                        scl_int <= 1'b0;
136
                                                        bit_count <= 'hF;
137
                                                        start_sent <= 1'b1;
138
                                                        stage <= 'h0;
139
                                                end
140
                                                endcase
141
                                        end
142
                                        else
143
                                        begin/* Send bits */
144
                                                stage <= stage + 1;
145
                                                case(stage)
146
                                                'h0:
147
                                                begin
148
                                                        case(rcv_ack)
149
                                                        1'b0:
150
                                                        begin
151
                                                                sda_int <= DATA[bit_count];
152
                                                        end
153
                                                        1'b1:
154
                                                                sda_int <= 1'b1;
155
                                                        endcase
156
                                                end
157
                                                'h1:
158
                                                begin
159
                                                        scl_int <= 1'b1;
160
                                                end
161
                                                'h2:
162
                                                begin
163
                                                        if(rcv_ack)
164
                                                                STATUS[`TWI_MASTER_RXACK_bp] <= sda;
165
                                                end
166
                                                'h3:
167
                                                begin
168
                                                        stage <= 'h0;
169
                                                        scl_int <= 1'b0;
170
                                                        case(rcv_ack)
171
                                                        1'b0:
172
                                                        begin
173
                                                                if(~|bit_count)
174
                                                                        rcv_ack <= 1'b1;
175
                                                                bit_count <= bit_count - 1;
176
                                                        end
177
                                                        1'b1:
178
                                                        begin
179
                                                                tx_mode <= 1'b0;
180
                                                                STATUS[`TWI_MASTER_WIF_bp] <= 1'b1;
181
                                                                rcv_ack <= 1'b0;
182
                                                        end
183
                                                        endcase
184
                                                end
185
                                                endcase
186
                                        end
187
                                end
188
                                CMD_RESTART:
189
                                begin/* Send restart */
190
                                        stage <= stage + 1;
191
                                        case(stage)
192
                                        'h0:
193
                                        begin
194
                                                sda_int <= 1'b1;
195
                                        end
196
                                        'h1:
197
                                        begin
198
                                                scl_int <= 1'b1;
199
                                        end
200
                                        'h2:
201
                                        begin
202
                                                sda_int <= 1'b0;
203
                                        end
204
                                        'h3:
205
                                        begin
206
                                                scl_int <= 1'b0;
207
                                                bit_count <= 'hF;
208
                                                start_sent <= 1'b1;
209
                                                stage <= 'h0;
210
                                                cmd <= 'h0;
211
                                                CTRLC[`TWI_MASTER_CMD_gp + 1:`TWI_MASTER_CMD_gp] <= 'h0;
212
                                        end
213
                                        endcase
214
                                end
215
                                CMD_RECEIVE:
216
                                begin/* Receive bits */
217
                                        stage <= stage + 1;
218
                                        case(stage)
219
                                        'h0:
220
                                        begin
221
                                                if(send_ack && ~send_ack_st2)
222
                                                        sda_int <= send_ack_int;
223
                                                else if(send_ack_st2)
224
                                                begin
225
                                                        STATUS[`TWI_MASTER_RIF_bp] <= 1'b1;
226
                                                        cmd <= 'h0;
227
                                                        CTRLC[`TWI_MASTER_CMD_gp + 1:`TWI_MASTER_CMD_gp] <= 'h0;
228
                                                        sda_int <= 1'b1;
229
                                                end
230
                                        end
231
                                        'h1:
232
                                        begin
233
                                                scl_int <= 1'b1;
234
                                        end
235
                                        'h2:
236
                                        begin
237
                                                if(~send_ack)
238
                                                        DATA[bit_count] <= sda;
239
                                        end
240
                                        'h3:
241
                                        begin
242
                                                scl_int <= 1'b0;
243
                                                stage <= 'h0;
244
                                                case(send_ack)
245
                                                1'b0:
246
                                                begin
247
                                                        if(~|bit_count)
248
                                                                send_ack <= 1'b1;
249
                                                        bit_count <= bit_count - 1;
250
                                                end
251
                                                1'b1: send_ack_st2 <= 1'b1;
252
                                                endcase
253
                                        end
254
                                        endcase
255
                                end
256
                                CMD_STOP:
257
                                begin/* Send stop */
258
                                        stage <= stage + 1;
259
                                        case(stage)
260
                                        'h0: sda_int <= 1'b0;
261
                                        'h1: scl_int <= 1'b1;
262
                                        'h2:
263
                                        begin
264
                                                sda_int <= 1'b1;
265
                                                start_sent <= 1'b0;
266
                                                stage <= 'h0;
267
                                                cmd <= 'h0;
268
                                                CTRLC[`TWI_MASTER_CMD_gp + 1:`TWI_MASTER_CMD_gp] <= 'h0;
269
                                        end
270
                                        endcase
271
                                end
272
                        endcase
273
                        end
274
                end
275
                else
276
                begin
277
                        baud_cnt <= baud_cnt + 1;
278
                end
279
                if(CTRLA[`TWI_MASTER_ENABLE_bp])
280
                begin
281
                        if(CTRLC[`TWI_MASTER_CMD_gp + 1:`TWI_MASTER_CMD_gp] && ~|cmd && ~tx_mode)
282
                        begin
283
                                cmd <= CTRLC[`TWI_MASTER_CMD_gp + 1:`TWI_MASTER_CMD_gp];
284
                                stage <= 'h0;
285
                                send_ack <= 1'b0;
286
                                send_ack_st2 <= 1'b0;
287
                                send_ack_int <= CTRLC[`TWI_SLAVE_ACKACT_bp];
288
                        end
289
                end
290
                if(wr_int)
291
                begin
292
                        case(addr[3:0])
293
                        `TWI_MASTER_CTRLA: CTRLA <= bus_in;
294
                        `TWI_MASTER_CTRLB: CTRLB <= bus_in;
295
                        `TWI_MASTER_CTRLC: CTRLC <= bus_in;
296
                        `TWI_MASTER_STATUS: STATUS <= STATUS ^ bus_in;
297
                        `TWI_MASTER_BAUD: BAUD <= bus_in;
298
                        //`TWI_MASTER_ADDR: ADDR <= bus_in;
299
                        `TWI_MASTER_DATA:
300
                        begin
301
                                if(~|CTRLC[`TWI_MASTER_CMD_gp + 1:`TWI_MASTER_CMD_gp])
302
                                begin
303
                                        DATA <= bus_in;
304
                                        tx_mode <= 1'b1;
305
                                        STATUS[`TWI_MASTER_WIF_bp] <= 1'b0;
306
                                end
307
                        end
308
                        endcase
309
                end
310
                if(rd_int)
311
                begin
312
                        case(addr[3:0])
313
                        `TWI_MASTER_DATA:
314
                        begin
315
                                STATUS[`TWI_MASTER_RIF_bp] <= 1'b0;
316
                        end
317
                        endcase
318
                end
319
        end
320
end
321
 
322
PULLUP PULLUP_scl_inst (
323
        .O(scl)  // 1-bit output: Pullup output (connect directly to top-level port)
324
);
325
PULLUP PULLUP_sda_inst (
326
        .O(sda)  // 1-bit output: Pullup output (connect directly to top-level port)
327
);
328
 
329
 
330
assign scl = scl_int ? 1'bz : scl_int;
331
assign sda = sda_int ? 1'bz : sda_int;
332
 
333
endmodule

powered by: WebSVN 2.1.0

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