URL
https://opencores.org/ocsvn/i2c/i2c/trunk
Subversion Repositories i2c
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 29 to Rev 28
- ↔ Reverse comparison
Rev 29 → Rev 28
/trunk/rtl/verilog/i2c_master_byte_ctrl.v
37,10 → 37,10
|
// CVS Log |
// |
// $Id: i2c_master_byte_ctrl.v,v 1.5 2002-12-26 15:02:32 rherveille Exp $ |
// $Id: i2c_master_byte_ctrl.v,v 1.4 2002-11-30 22:24:40 rherveille Exp $ |
// |
// $Date: 2002-12-26 15:02:32 $ |
// $Revision: 1.5 $ |
// $Date: 2002-11-30 22:24:40 $ |
// $Revision: 1.4 $ |
// $Author: rherveille $ |
// $Locker: $ |
// $State: Exp $ |
47,9 → 47,6
// |
// 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. |
56,15 → 53,12
// 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, i2c_al, scl_i, scl_o, scl_oen, sda_i, sda_o, sda_oen ); |
cmd_ack, ack_out, dout, i2c_busy, scl_i, scl_o, scl_oen, sda_i, sda_o, sda_oen ); |
|
// |
// inputs & outputs |
90,7 → 84,6
output ack_out; |
reg ack_out; |
output i2c_busy; |
output i2c_al; |
output [7:0] dout; |
|
// I2C signals |
142,7 → 135,6
.cmd ( core_cmd ), |
.cmd_ack ( core_ack ), |
.busy ( i2c_busy ), |
.al ( i2c_al ), |
.din ( core_txd ), |
.dout ( core_rxd ), |
.scl_i ( scl_i ), |
181,7 → 173,7
else if (shift) |
dcnt <= #1 dcnt - 3'h1; |
|
assign cnt_done = ~(|dcnt); |
assign cnt_done = !(|dcnt); |
|
// |
// state machine |
199,7 → 191,7
c_state <= #1 ST_IDLE; |
ack_out <= #1 1'b0; |
end |
else if (rst | i2c_al) |
else if (rst) |
begin |
core_cmd <= #1 `I2C_CMD_NOP; |
core_txd <= #1 1'b0; |
245,7 → 237,7
cmd_ack <= #1 1'b1; |
end |
|
ld <= #1 1'b1; |
ld <= #1 1'b1; |
end |
|
ST_START: |
262,7 → 254,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.6 2002-12-26 15:02:32 rherveille Exp $ |
// $Id: i2c_master_bit_ctrl.v,v 1.5 2002-11-30 22:24:40 rherveille Exp $ |
// |
// $Date: 2002-12-26 15:02:32 $ |
// $Revision: 1.6 $ |
// $Date: 2002-11-30 22:24:40 $ |
// $Revision: 1.5 $ |
// $Author: rherveille $ |
// $Locker: $ |
// $State: Exp $ |
47,9 → 47,6
// |
// 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. |
// |
101,17 → 98,10
// 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, al, 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, din, dout, scl_i, scl_o, scl_oen, sda_i, sda_o, sda_oen); |
|
// |
// inputs & outputs |
124,12 → 114,10
input [15:0] clk_cnt; // clock prescale value |
|
input [3:0] cmd; |
output cmd_ack; // command complete acknowledge |
output cmd_ack; |
reg cmd_ack; |
output busy; // i2c bus busy |
output busy; |
reg busy; |
output al; // i2c bus arbitration lost |
reg al; |
|
input din; |
output dout; |
136,13 → 124,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; |
|
|
152,7 → 140,6
|
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) |
162,14 → 149,20
// module body |
// |
|
// whenever the slave is not ready it can delay the cycle by pulling SCL low |
// synchronize SCL and SDA inputs |
always @(posedge clk) |
begin |
sSCL <= #1 scl_i; |
sSDA <= #1 sda_i; |
end |
|
// 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) |
182,44 → 175,31
cnt <= #1 16'h0; |
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 if ( !(|cnt) || !ena) |
begin |
cnt <= #1 clk_cnt; |
clk_en <= #1 1'b1; |
end |
else |
begin |
cnt <= #1 cnt - 16'h1; |
if(!slave_wait) |
cnt <= #1 cnt - 16'h1; |
|
clk_en <= #1 1'b0; |
end |
|
|
// generate bus status controller |
reg dSCL, dSDA; |
reg 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 |
233,24 → 213,7
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 |
280,17 → 243,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 | al) |
else if (rst) |
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 |
320,7 → 283,6
|
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 |
329,7 → 291,6
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: |
337,7 → 298,6
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: |
345,7 → 305,6
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: |
353,7 → 312,6
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: |
362,7 → 320,6
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 |
371,7 → 328,6
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: |
379,7 → 335,6
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: |
387,7 → 342,6
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: |
396,7 → 350,6
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 |
405,7 → 358,6
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: |
413,15 → 365,14
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; // keep SDA tri-stated |
sda_chk <= #1 1'b0; // don't check SDA output |
sda_oen <= #1 1'b1; |
end |
|
rd_d: |
429,8 → 380,7
c_state <= #1 idle; |
cmd_ack <= #1 clk_en; |
scl_oen <= #1 1'b0; // set SCL low |
sda_oen <= #1 1'b1; // keep SDA tri-stated |
sda_chk <= #1 1'b0; // don't check SDA output |
sda_oen <= #1 1'b1; |
end |
|
// write |
439,7 → 389,6
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: |
447,7 → 396,6
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: |
455,7 → 403,6
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: |
464,7 → 411,6
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.7 2002-12-26 15:02:32 rherveille Exp $ |
// $Id: i2c_master_top.v,v 1.6 2002-11-30 22:24:40 rherveille Exp $ |
// |
// $Date: 2002-12-26 15:02:32 $ |
// $Revision: 1.7 $ |
// $Date: 2002-11-30 22:24:40 $ |
// $Revision: 1.6 $ |
// $Author: rherveille $ |
// $Locker: $ |
// $State: Exp $ |
47,9 → 47,6
// |
// 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. |
// |
61,7 → 58,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 ); |
|
126,8 → 123,6
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 |
136,9 → 131,6
// 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 |
158,6 → 150,7
endcase |
end |
|
|
// generate registers |
always @(posedge wb_clk_i or negedge rst_i) |
if (!rst_i) |
175,33 → 168,27
cr <= #1 8'h0; |
end |
else |
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 |
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 |
|
// 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 |
cr[2:1] <= #1 2'b00; // reserved bits |
cr[0] <= #1 cr[0] && irq_flag; // clear when irq_flag cleared |
end |
|
|
// decode command register |
233,7 → 220,6
.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 ), |
242,11 → 228,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; |
253,7 → 239,6
end |
else if (wb_rst_i) |
begin |
al <= #1 1'b0; |
rxack <= #1 1'b0; |
tip <= #1 1'b0; |
irq_flag <= #1 1'b0; |
260,10 → 245,9
end |
else |
begin |
al <= #1 i2c_al | (al & ~sta); |
rxack <= #1 irxack; |
tip <= #1 (rd | wr); |
irq_flag <= #1 (done | i2c_al | irq_flag) & ~iack; // interrupt request flag is always generated |
irq_flag <= #1 (done | irq_flag) & ~iack; // interrupt request flag is always generated |
end |
|
// generate interrupt request signals |
278,8 → 262,7
// assign status register bits |
assign sr[7] = rxack; |
assign sr[6] = i2c_busy; |
assign sr[5] = al; |
assign sr[4:2] = 3'h0; // reserved |
assign sr[5:2] = 4'h0; // reserved |
assign sr[1] = tip; |
assign sr[0] = irq_flag; |
|