URL
https://opencores.org/ocsvn/i2c/i2c/trunk
Subversion Repositories i2c
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 28 to Rev 29
- ↔ Reverse comparison
Rev 28 → Rev 29
/trunk/rtl/verilog/i2c_master_byte_ctrl.v
37,10 → 37,10
|
// CVS Log |
// |
// $Id: i2c_master_byte_ctrl.v,v 1.4 2002-11-30 22:24:40 rherveille Exp $ |
// $Id: i2c_master_byte_ctrl.v,v 1.5 2002-12-26 15:02:32 rherveille Exp $ |
// |
// $Date: 2002-11-30 22:24:40 $ |
// $Revision: 1.4 $ |
// $Date: 2002-12-26 15:02:32 $ |
// $Revision: 1.5 $ |
// $Author: rherveille $ |
// $Locker: $ |
// $State: Exp $ |
47,6 → 47,9
// |
// Change History: |
// $Log: not supported by cvs2svn $ |
// Revision 1.4 2002/11/30 22:24:40 rherveille |
// Cleaned up code |
// |
// Revision 1.3 2001/11/05 11:59:25 rherveille |
// Fixed wb_ack_o generation bug. |
// Fixed bug in the byte_controller statemachine. |
53,12 → 56,15
// Added headers. |
// |
|
// synopsys translate_off |
`include "timescale.v" |
// synopsys translate_on |
|
`include "i2c_master_defines.v" |
|
module i2c_master_byte_ctrl ( |
clk, rst, nReset, ena, clk_cnt, start, stop, read, write, ack_in, din, |
cmd_ack, ack_out, dout, i2c_busy, scl_i, scl_o, scl_oen, sda_i, sda_o, sda_oen ); |
cmd_ack, ack_out, dout, i2c_busy, i2c_al, scl_i, scl_o, scl_oen, sda_i, sda_o, sda_oen ); |
|
// |
// inputs & outputs |
84,6 → 90,7
output ack_out; |
reg ack_out; |
output i2c_busy; |
output i2c_al; |
output [7:0] dout; |
|
// I2C signals |
135,6 → 142,7
.cmd ( core_cmd ), |
.cmd_ack ( core_ack ), |
.busy ( i2c_busy ), |
.al ( i2c_al ), |
.din ( core_txd ), |
.dout ( core_rxd ), |
.scl_i ( scl_i ), |
173,7 → 181,7
else if (shift) |
dcnt <= #1 dcnt - 3'h1; |
|
assign cnt_done = !(|dcnt); |
assign cnt_done = ~(|dcnt); |
|
// |
// state machine |
191,7 → 199,7
c_state <= #1 ST_IDLE; |
ack_out <= #1 1'b0; |
end |
else if (rst) |
else if (rst | i2c_al) |
begin |
core_cmd <= #1 `I2C_CMD_NOP; |
core_txd <= #1 1'b0; |
237,7 → 245,7
cmd_ack <= #1 1'b1; |
end |
|
ld <= #1 1'b1; |
ld <= #1 1'b1; |
end |
|
ST_START: |
254,7 → 262,7
core_cmd <= #1 `I2C_CMD_WRITE; |
end |
|
ld <= #1 1'b1; |
ld <= #1 1'b1; |
end |
|
ST_WRITE: |
/trunk/rtl/verilog/i2c_master_bit_ctrl.v
37,10 → 37,10
|
// CVS Log |
// |
// $Id: i2c_master_bit_ctrl.v,v 1.5 2002-11-30 22:24:40 rherveille Exp $ |
// $Id: i2c_master_bit_ctrl.v,v 1.6 2002-12-26 15:02:32 rherveille Exp $ |
// |
// $Date: 2002-11-30 22:24:40 $ |
// $Revision: 1.5 $ |
// $Date: 2002-12-26 15:02:32 $ |
// $Revision: 1.6 $ |
// $Author: rherveille $ |
// $Locker: $ |
// $State: Exp $ |
47,6 → 47,9
// |
// Change History: |
// $Log: not supported by cvs2svn $ |
// Revision 1.5 2002/11/30 22:24:40 rherveille |
// Cleaned up code |
// |
// Revision 1.4 2002/10/30 18:10:07 rherveille |
// Fixed some reported minor start/stop generation timing issuess. |
// |
98,10 → 101,17
// Tbuf 4.7us 1.3us Bus free time between a stop and start condition |
// |
|
// synopsys translate_off |
`include "timescale.v" |
// synopsys translate_on |
|
`include "i2c_master_defines.v" |
|
module i2c_master_bit_ctrl(clk, rst, nReset, clk_cnt, ena, cmd, cmd_ack, busy, din, dout, scl_i, scl_o, scl_oen, sda_i, sda_o, sda_oen); |
module i2c_master_bit_ctrl( |
clk, rst, nReset, |
clk_cnt, ena, cmd, cmd_ack, busy, al, din, dout, |
scl_i, scl_o, scl_oen, sda_i, sda_o, sda_oen |
); |
|
// |
// inputs & outputs |
114,10 → 124,12
input [15:0] clk_cnt; // clock prescale value |
|
input [3:0] cmd; |
output cmd_ack; |
output cmd_ack; // command complete acknowledge |
reg cmd_ack; |
output busy; |
output busy; // i2c bus busy |
reg busy; |
output al; // i2c bus arbitration lost |
reg al; |
|
input din; |
output dout; |
124,13 → 136,13
reg dout; |
|
// I2C lines |
input scl_i; // i2c clock line input |
output scl_o; // i2c clock line output |
output scl_oen; // i2c clock line output enable (active low) |
input scl_i; // i2c clock line input |
output scl_o; // i2c clock line output |
output scl_oen; // i2c clock line output enable (active low) |
reg scl_oen; |
input sda_i; // i2c data line input |
output sda_o; // i2c data line output |
output sda_oen; // i2c data line output enable (active low) |
input sda_i; // i2c data line input |
output sda_o; // i2c data line output |
output sda_oen; // i2c data line output enable (active low) |
reg sda_oen; |
|
|
140,6 → 152,7
|
reg sSCL, sSDA; // synchronized SCL and SDA inputs |
reg dscl_oen; // delayed scl_oen |
reg sda_chk; // check SDA output (Multi-master arbitration) |
reg clk_en; // clock generation signals |
wire slave_wait; |
// reg [15:0] cnt = clk_cnt; // clock divider counter (simulation) |
149,20 → 162,14
// module body |
// |
|
// synchronize SCL and SDA inputs |
always @(posedge clk) |
begin |
sSCL <= #1 scl_i; |
sSDA <= #1 sda_i; |
end |
|
// whenever the slave is not ready it can delay the cycle by pulling SCL low |
// delay scl_oen |
always @(posedge clk) |
dscl_oen <= #1 scl_oen; |
|
// whenever the slave is not ready it can delay the cycle by pulling SCL low |
assign slave_wait = dscl_oen && !sSCL; |
|
|
// generate clk enable signal |
always @(posedge clk or negedge nReset) |
if(~nReset) |
175,31 → 182,44
cnt <= #1 16'h0; |
clk_en <= #1 1'b1; |
end |
else if ( !(|cnt) || !ena) |
begin |
cnt <= #1 clk_cnt; |
clk_en <= #1 1'b1; |
end |
else if ( ~|cnt || ~ena) |
if (~slave_wait) |
begin |
cnt <= #1 clk_cnt; |
clk_en <= #1 1'b1; |
end |
else |
begin |
cnt <= #1 cnt; |
clk_en <= #1 1'b0; |
end |
else |
begin |
if(!slave_wait) |
cnt <= #1 cnt - 16'h1; |
|
cnt <= #1 cnt - 16'h1; |
clk_en <= #1 1'b0; |
end |
|
|
// generate bus status controller |
reg dSDA; |
reg dSCL, dSDA; |
reg sta_condition; |
reg sto_condition; |
|
// synchronize SCL and SDA inputs |
// reduce metastability risc |
always @(posedge clk) |
begin |
sSCL <= #1 scl_i; |
sSDA <= #1 sda_i; |
|
dSCL <= #1 sSCL; |
dSDA <= #1 sSDA; |
end |
|
// detect start condition => detect falling edge on SDA while SCL is high |
// detect stop condition => detect rising edge on SDA while SCL is high |
always @(posedge clk) |
begin |
dSDA <= #1 sSDA; // generate a delayed version of sSDA |
|
sta_condition <= #1 ~sSDA & dSDA & sSCL; |
sto_condition <= #1 sSDA & ~dSDA & sSCL; |
end |
213,7 → 233,24
else |
busy <= #1 (sta_condition | busy) & ~sto_condition; |
|
// generate arbitration lost signal |
// aribitration lost when: |
// 1) master drives SDA high, but the i2c bus is low |
// 2) stop detected while not requested |
reg cmd_stop, dcmd_stop; |
always @(posedge clk) |
begin |
cmd_stop <= #1 cmd == `I2C_CMD_STOP; |
dcmd_stop <= #1 cmd_stop; |
|
al <= #1 (sda_chk & ~sSDA & sda_oen) | (sto_condition & ~dcmd_stop); |
end |
|
// generate dout signal (store SDA on rising edge of SCL) |
always @(posedge clk) |
if(sSCL & ~dSCL) |
dout <= #1 sSDA; |
|
// generate statemachine |
|
// nxt_state decoder |
243,17 → 280,17
begin |
c_state <= #1 idle; |
cmd_ack <= #1 1'b0; |
dout <= #1 1'b0; |
scl_oen <= #1 1'b1; |
sda_oen <= #1 1'b1; |
sda_chk <= #1 1'b0; |
end |
else if (rst) |
else if (rst | al) |
begin |
c_state <= #1 idle; |
cmd_ack <= #1 1'b0; |
dout <= #1 1'b0; |
scl_oen <= #1 1'b1; |
sda_oen <= #1 1'b1; |
sda_chk <= #1 1'b0; |
end |
else |
begin |
283,6 → 320,7
|
scl_oen <= #1 scl_oen; // keep SCL in same state |
sda_oen <= #1 sda_oen; // keep SDA in same state |
sda_chk <= #1 1'b0; // don't check SDA output |
end |
|
// start |
291,6 → 329,7
c_state <= #1 start_b; |
scl_oen <= #1 scl_oen; // keep SCL in same state |
sda_oen <= #1 1'b1; // set SDA high |
sda_chk <= #1 1'b0; // don't check SDA output |
end |
|
start_b: |
298,6 → 337,7
c_state <= #1 start_c; |
scl_oen <= #1 1'b1; // set SCL high |
sda_oen <= #1 1'b1; // keep SDA high |
sda_chk <= #1 1'b0; // don't check SDA output |
end |
|
start_c: |
305,6 → 345,7
c_state <= #1 start_d; |
scl_oen <= #1 1'b1; // keep SCL high |
sda_oen <= #1 1'b0; // set SDA low |
sda_chk <= #1 1'b0; // don't check SDA output |
end |
|
start_d: |
312,6 → 353,7
c_state <= #1 start_e; |
scl_oen <= #1 1'b1; // keep SCL high |
sda_oen <= #1 1'b0; // keep SDA low |
sda_chk <= #1 1'b0; // don't check SDA output |
end |
|
start_e: |
320,6 → 362,7
cmd_ack <= #1 1'b1; |
scl_oen <= #1 1'b0; // set SCL low |
sda_oen <= #1 1'b0; // keep SDA low |
sda_chk <= #1 1'b0; // don't check SDA output |
end |
|
// stop |
328,6 → 371,7
c_state <= #1 stop_b; |
scl_oen <= #1 1'b0; // keep SCL low |
sda_oen <= #1 1'b0; // set SDA low |
sda_chk <= #1 1'b0; // don't check SDA output |
end |
|
stop_b: |
335,6 → 379,7
c_state <= #1 stop_c; |
scl_oen <= #1 1'b1; // set SCL high |
sda_oen <= #1 1'b0; // keep SDA low |
sda_chk <= #1 1'b0; // don't check SDA output |
end |
|
stop_c: |
342,6 → 387,7
c_state <= #1 stop_d; |
scl_oen <= #1 1'b1; // keep SCL high |
sda_oen <= #1 1'b0; // keep SDA low |
sda_chk <= #1 1'b0; // don't check SDA output |
end |
|
stop_d: |
350,6 → 396,7
cmd_ack <= #1 clk_en; |
scl_oen <= #1 1'b1; // keep SCL high |
sda_oen <= #1 1'b1; // set SDA high |
sda_chk <= #1 1'b0; // don't check SDA output |
end |
|
// read |
358,6 → 405,7
c_state <= #1 rd_b; |
scl_oen <= #1 1'b0; // keep SCL low |
sda_oen <= #1 1'b1; // tri-state SDA |
sda_chk <= #1 1'b0; // don't check SDA output |
end |
|
rd_b: |
365,14 → 413,15
c_state <= #1 rd_c; |
scl_oen <= #1 1'b1; // set SCL high |
sda_oen <= #1 1'b1; // keep SDA tri-stated |
sda_chk <= #1 1'b0; // don't check SDA output |
end |
|
rd_c: |
begin |
c_state <= #1 rd_d; |
dout <= #1 sSDA; |
scl_oen <= #1 1'b1; // keep SCL high |
sda_oen <= #1 1'b1; |
sda_oen <= #1 1'b1; // keep SDA tri-stated |
sda_chk <= #1 1'b0; // don't check SDA output |
end |
|
rd_d: |
380,7 → 429,8
c_state <= #1 idle; |
cmd_ack <= #1 clk_en; |
scl_oen <= #1 1'b0; // set SCL low |
sda_oen <= #1 1'b1; |
sda_oen <= #1 1'b1; // keep SDA tri-stated |
sda_chk <= #1 1'b0; // don't check SDA output |
end |
|
// write |
389,6 → 439,7
c_state <= #1 wr_b; |
scl_oen <= #1 1'b0; // keep SCL low |
sda_oen <= #1 din; // set SDA |
sda_chk <= #1 1'b0; // don't check SDA output (SCL low) |
end |
|
wr_b: |
396,6 → 447,7
c_state <= #1 wr_c; |
scl_oen <= #1 1'b1; // set SCL high |
sda_oen <= #1 din; // keep SDA |
sda_chk <= #1 1'b1; // check SDA output |
end |
|
wr_c: |
403,6 → 455,7
c_state <= #1 wr_d; |
scl_oen <= #1 1'b1; // keep SCL high |
sda_oen <= #1 din; |
sda_chk <= #1 1'b1; // check SDA output |
end |
|
wr_d: |
411,6 → 464,7
cmd_ack <= #1 1'b1; |
scl_oen <= #1 1'b0; // set SCL low |
sda_oen <= #1 din; |
sda_chk <= #1 1'b0; // don't check SDA output (SCL low) |
end |
|
endcase |
/trunk/rtl/verilog/i2c_master_top.v
37,10 → 37,10
|
// CVS Log |
// |
// $Id: i2c_master_top.v,v 1.6 2002-11-30 22:24:40 rherveille Exp $ |
// $Id: i2c_master_top.v,v 1.7 2002-12-26 15:02:32 rherveille Exp $ |
// |
// $Date: 2002-11-30 22:24:40 $ |
// $Revision: 1.6 $ |
// $Date: 2002-12-26 15:02:32 $ |
// $Revision: 1.7 $ |
// $Author: rherveille $ |
// $Locker: $ |
// $State: Exp $ |
47,6 → 47,9
// |
// Change History: |
// $Log: not supported by cvs2svn $ |
// Revision 1.6 2002/11/30 22:24:40 rherveille |
// Cleaned up code |
// |
// Revision 1.5 2001/11/10 10:52:55 rherveille |
// Changed PRER reset value from 0x0000 to 0xffff, conform specs. |
// |
58,7 → 61,7
`include "i2c_master_defines.v" |
|
module i2c_master_top( |
wb_clk_i, wb_rst_i, arst_i, wb_adr_i, wb_dat_i, wb_dat_o, |
wb_clk_i, wb_rst_i, arst_i, wb_adr_i, wb_dat_i, wb_dat_o, |
wb_we_i, wb_stb_i, wb_cyc_i, wb_ack_o, wb_inta_o, |
scl_pad_i, scl_pad_o, scl_padoen_o, sda_pad_i, sda_pad_o, sda_padoen_o ); |
|
123,6 → 126,8
reg tip; // transfer in progress |
reg irq_flag; // interrupt pending flag |
wire i2c_busy; // bus busy (start signal detected) |
wire i2c_al; // i2c bus arbitration lost |
reg al; // status register arbitration lost bit |
|
// |
// module body |
131,6 → 136,9
// generate internal reset |
wire rst_i = arst_i ^ ARST_LVL; |
|
// generate wishbone signals |
wire wb_wacc = wb_cyc_i & wb_stb_i & wb_we_i; |
|
// generate acknowledge output signal |
always @(posedge wb_clk_i) |
wb_ack_o <= #1 wb_cyc_i & wb_stb_i & ~wb_ack_o; // because timing is always honored |
150,7 → 158,6
endcase |
end |
|
|
// generate registers |
always @(posedge wb_clk_i or negedge rst_i) |
if (!rst_i) |
168,27 → 175,33
cr <= #1 8'h0; |
end |
else |
if (wb_cyc_i && wb_stb_i && wb_we_i) |
begin |
if (!wb_adr_i[2]) |
case (wb_adr_i[1:0]) // synopsis full_case parallel_case |
2'b00 : prer [ 7:0] <= #1 wb_dat_i; |
2'b01 : prer [15:8] <= #1 wb_dat_i; |
2'b10 : ctr <= #1 wb_dat_i; |
2'b11 : txr <= #1 wb_dat_i; |
endcase |
else |
if (core_en && (wb_adr_i[1:0] == 2'b00) ) // only take new commands when i2c core enabled, pending commands are finished |
cr <= #1 wb_dat_i; |
end |
else |
begin |
if (done) |
cr[7:4] <= #1 4'h0; // clear command bits when done |
if (wb_wacc) |
case (wb_adr_i) // synopsis full_case parallel_case |
3'b000 : prer [ 7:0] <= #1 wb_dat_i; |
3'b001 : prer [15:8] <= #1 wb_dat_i; |
3'b010 : ctr <= #1 wb_dat_i; |
3'b011 : txr <= #1 wb_dat_i; |
endcase |
|
cr[2:1] <= #1 2'b00; // reserved bits |
cr[0] <= #1 cr[0] && irq_flag; // clear when irq_flag cleared |
end |
// generate command register (special case) |
always @(posedge wb_clk_i or negedge rst_i) |
if (~rst_i) |
cr <= #1 8'h0; |
else if (wb_rst_i) |
cr <= #1 8'h0; |
else if (wb_wacc) |
begin |
if (core_en & (wb_adr_i == 3'b100) ) |
cr <= #1 wb_dat_i; |
end |
else |
begin |
if (done | i2c_al) |
cr[7:4] <= #1 4'h0; // clear command bits when done |
// or when aribitration lost |
cr[2:1] <= #1 2'b0; // reserved bits |
cr[0] <= #1 cr[0] & irq_flag; // clear when irq_flag is cleared |
end |
|
|
// decode command register |
220,6 → 233,7
.ack_out ( irxack ), |
.dout ( rxr ), |
.i2c_busy ( i2c_busy ), |
.i2c_al ( i2c_al ), |
.scl_i ( scl_pad_i ), |
.scl_o ( scl_pad_o ), |
.scl_oen ( scl_padoen_o ), |
228,11 → 242,11
.sda_oen ( sda_padoen_o ) |
); |
|
|
// status register block + interrupt request signal |
always @(posedge wb_clk_i or negedge rst_i) |
if (!rst_i) |
begin |
al <= #1 1'b0; |
rxack <= #1 1'b0; |
tip <= #1 1'b0; |
irq_flag <= #1 1'b0; |
239,6 → 253,7
end |
else if (wb_rst_i) |
begin |
al <= #1 1'b0; |
rxack <= #1 1'b0; |
tip <= #1 1'b0; |
irq_flag <= #1 1'b0; |
245,9 → 260,10
end |
else |
begin |
al <= #1 i2c_al | (al & ~sta); |
rxack <= #1 irxack; |
tip <= #1 (rd | wr); |
irq_flag <= #1 (done | irq_flag) & ~iack; // interrupt request flag is always generated |
irq_flag <= #1 (done | i2c_al | irq_flag) & ~iack; // interrupt request flag is always generated |
end |
|
// generate interrupt request signals |
262,7 → 278,8
// assign status register bits |
assign sr[7] = rxack; |
assign sr[6] = i2c_busy; |
assign sr[5:2] = 4'h0; // reserved |
assign sr[5] = al; |
assign sr[4:2] = 3'h0; // reserved |
assign sr[1] = tip; |
assign sr[0] = irq_flag; |
|