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

Subversion Repositories attiny_atmega_xmega_core

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 6 to Rev 7
    Reverse comparison

Rev 6 → Rev 7

/attiny_atmega_xmega_core/trunk/io/twi_s.v
0,0 → 1,333
/*
* This IP is a TWI IO adapter implementation.
*
* Copyright (C) 2018 Iulian Gheorghiu
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
 
`timescale 1ns / 1ps
 
`include "io_s_h.v"
 
module twi_s #(
parameter DINAMIC_BAUDRATE = "TRUE",
parameter BAUDRATE_DIVIDER = 255,
parameter ADDRESS = 0,
parameter BUS_ADDR_DATA_LEN = 16
)(
input rst,
input clk,
input [BUS_ADDR_DATA_LEN-1:0]addr,
input wr,
input rd,
input [7:0]bus_in,
output reg[7:0]bus_out,
output int_tx_cmpl,
output int_rx_cmpl,
input int_tx_rst,
input int_rx_rst,
inout scl,
inout sda
);
 
reg [7:0]CTRLA;
reg [7:0]CTRLB;
reg [7:0]CTRLC;
reg [7:0]STATUS;
reg [7:0]BAUD;
reg [7:0]DATA;
 
wire cs_int = addr >= ADDRESS && addr < (ADDRESS + 16);
wire rd_int = cs_int && rd;
wire wr_int = cs_int && wr;
 
reg [7:0]baud_cnt;
reg [1:0]cmd;
reg tx_mode;
reg start_sent;
reg rcv_ack;
reg send_ack;
reg send_ack_st2;
reg [1:0]stage;
reg [2:0]bit_count;
reg scl_int;
reg sda_int;
reg send_ack_int;
 
localparam [2:0]CMD_NOP = {1'b1, 2'b00};
localparam [2:0]CMD_RESTART = {1'b0, 2'b01};
localparam [2:0]CMD_RECEIVE = {1'b0, 2'b10};
localparam [2:0]CMD_STOP = {1'b0, 2'b11};
 
always @ (*)
begin
bus_out <= 'hz;
if(rd_int)
begin
case(addr[3:0])
`TWI_MASTER_CTRLA: bus_out <= CTRLA;
`TWI_MASTER_CTRLB: bus_out <= CTRLB;
`TWI_MASTER_CTRLC: bus_out <= CTRLC;
`TWI_MASTER_STATUS: bus_out <= STATUS;
`TWI_MASTER_BAUD: bus_out <= BAUD;
`TWI_MASTER_DATA: bus_out <= DATA;
endcase
end
end
 
always @ (posedge clk or posedge rst)
begin
if(rst)
begin
CTRLA <= 'h0;
CTRLB <= 'h0;
CTRLC <= 'h0;
STATUS <= 'h0;
BAUD <= 'h0;
DATA <= 'h0;
baud_cnt <= 'h00;
cmd <= 'h00;
tx_mode <= 1'b0;
start_sent <= 1'b0;
scl_int <= 1'b1;
sda_int <= 1'b1;
rcv_ack <= 1'b0;
send_ack <= 1'b0;
send_ack_st2 <= 1'b0;
stage <= 'h00;
send_ack_int <= 1'b1;
end
else
begin
if(DINAMIC_BAUDRATE == "TRUE" ? baud_cnt == BAUD : baud_cnt == {BAUDRATE_DIVIDER})
begin
baud_cnt <= 'h00;
if(CTRLA[`TWI_MASTER_ENABLE_bp])
begin
case({tx_mode, cmd})
CMD_NOP:
begin
if(~start_sent)
begin/* Send the start sequence */
stage <= stage + 1;
case(stage)
'h0:
begin
scl_int <= 1'b1;
sda_int <= 1'b0;
end
'h1:
begin
scl_int <= 1'b0;
bit_count <= 'hF;
start_sent <= 1'b1;
stage <= 'h0;
end
endcase
end
else
begin/* Send bits */
stage <= stage + 1;
case(stage)
'h0:
begin
case(rcv_ack)
1'b0:
begin
sda_int <= DATA[bit_count];
end
1'b1:
sda_int <= 1'b1;
endcase
end
'h1:
begin
scl_int <= 1'b1;
end
'h2:
begin
if(rcv_ack)
STATUS[`TWI_MASTER_RXACK_bp] <= sda;
end
'h3:
begin
stage <= 'h0;
scl_int <= 1'b0;
case(rcv_ack)
1'b0:
begin
if(~|bit_count)
rcv_ack <= 1'b1;
bit_count <= bit_count - 1;
end
1'b1:
begin
tx_mode <= 1'b0;
STATUS[`TWI_MASTER_WIF_bp] <= 1'b1;
rcv_ack <= 1'b0;
end
endcase
end
endcase
end
end
CMD_RESTART:
begin/* Send restart */
stage <= stage + 1;
case(stage)
'h0:
begin
sda_int <= 1'b1;
end
'h1:
begin
scl_int <= 1'b1;
end
'h2:
begin
sda_int <= 1'b0;
end
'h3:
begin
scl_int <= 1'b0;
bit_count <= 'hF;
start_sent <= 1'b1;
stage <= 'h0;
cmd <= 'h0;
CTRLC[`TWI_MASTER_CMD_gp + 1:`TWI_MASTER_CMD_gp] <= 'h0;
end
endcase
end
CMD_RECEIVE:
begin/* Receive bits */
stage <= stage + 1;
case(stage)
'h0:
begin
if(send_ack && ~send_ack_st2)
sda_int <= send_ack_int;
else if(send_ack_st2)
begin
STATUS[`TWI_MASTER_RIF_bp] <= 1'b1;
cmd <= 'h0;
CTRLC[`TWI_MASTER_CMD_gp + 1:`TWI_MASTER_CMD_gp] <= 'h0;
sda_int <= 1'b1;
end
end
'h1:
begin
scl_int <= 1'b1;
end
'h2:
begin
if(~send_ack)
DATA[bit_count] <= sda;
end
'h3:
begin
scl_int <= 1'b0;
stage <= 'h0;
case(send_ack)
1'b0:
begin
if(~|bit_count)
send_ack <= 1'b1;
bit_count <= bit_count - 1;
end
1'b1: send_ack_st2 <= 1'b1;
endcase
end
endcase
end
CMD_STOP:
begin/* Send stop */
stage <= stage + 1;
case(stage)
'h0: sda_int <= 1'b0;
'h1: scl_int <= 1'b1;
'h2:
begin
sda_int <= 1'b1;
start_sent <= 1'b0;
stage <= 'h0;
cmd <= 'h0;
CTRLC[`TWI_MASTER_CMD_gp + 1:`TWI_MASTER_CMD_gp] <= 'h0;
end
endcase
end
endcase
end
end
else
begin
baud_cnt <= baud_cnt + 1;
end
if(CTRLA[`TWI_MASTER_ENABLE_bp])
begin
if(CTRLC[`TWI_MASTER_CMD_gp + 1:`TWI_MASTER_CMD_gp] && ~|cmd && ~tx_mode)
begin
cmd <= CTRLC[`TWI_MASTER_CMD_gp + 1:`TWI_MASTER_CMD_gp];
stage <= 'h0;
send_ack <= 1'b0;
send_ack_st2 <= 1'b0;
send_ack_int <= CTRLC[`TWI_SLAVE_ACKACT_bp];
end
end
if(wr_int)
begin
case(addr[3:0])
`TWI_MASTER_CTRLA: CTRLA <= bus_in;
`TWI_MASTER_CTRLB: CTRLB <= bus_in;
`TWI_MASTER_CTRLC: CTRLC <= bus_in;
`TWI_MASTER_STATUS: STATUS <= STATUS ^ bus_in;
`TWI_MASTER_BAUD: BAUD <= bus_in;
//`TWI_MASTER_ADDR: ADDR <= bus_in;
`TWI_MASTER_DATA:
begin
if(~|CTRLC[`TWI_MASTER_CMD_gp + 1:`TWI_MASTER_CMD_gp])
begin
DATA <= bus_in;
tx_mode <= 1'b1;
STATUS[`TWI_MASTER_WIF_bp] <= 1'b0;
end
end
endcase
end
if(rd_int)
begin
case(addr[3:0])
`TWI_MASTER_DATA:
begin
STATUS[`TWI_MASTER_RIF_bp] <= 1'b0;
end
endcase
end
end
end
 
PULLUP PULLUP_scl_inst (
.O(scl) // 1-bit output: Pullup output (connect directly to top-level port)
);
PULLUP PULLUP_sda_inst (
.O(sda) // 1-bit output: Pullup output (connect directly to top-level port)
);
 
 
assign scl = scl_int ? 1'bz : scl_int;
assign sda = sda_int ? 1'bz : sda_int;
 
endmodule

powered by: WebSVN 2.1.0

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