URL
https://opencores.org/ocsvn/i2c/i2c/trunk
Subversion Repositories i2c
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 26 to Rev 27
- ↔ Reverse comparison
Rev 26 → Rev 27
/trunk/rtl/verilog/i2c_master_byte_ctrl.v
37,10 → 37,10
|
// CVS Log |
// |
// $Id: i2c_master_byte_ctrl.v,v 1.3 2001-11-05 11:59:25 rherveille Exp $ |
// $Id: i2c_master_byte_ctrl.v,v 1.4 2002-11-30 22:24:40 rherveille Exp $ |
// |
// $Date: 2001-11-05 11:59:25 $ |
// $Revision: 1.3 $ |
// $Date: 2002-11-30 22:24:40 $ |
// $Revision: 1.4 $ |
// $Author: rherveille $ |
// $Locker: $ |
// $State: Exp $ |
47,6 → 47,11
// |
// Change History: |
// $Log: not supported by cvs2svn $ |
// Revision 1.3 2001/11/05 11:59:25 rherveille |
// Fixed wb_ack_o generation bug. |
// Fixed bug in the byte_controller statemachine. |
// Added headers. |
// |
|
`include "timescale.v" |
`include "i2c_master_defines.v" |
122,51 → 127,51
|
// hookup bit_controller |
i2c_master_bit_ctrl bit_controller ( |
.clk(clk), |
.rst(rst), |
.nReset(nReset), |
.ena(ena), |
.clk_cnt(clk_cnt), |
.cmd(core_cmd), |
.cmd_ack(core_ack), |
.busy(i2c_busy), |
.din(core_txd), |
.dout(core_rxd), |
.scl_i(scl_i), |
.scl_o(scl_o), |
.scl_oen(scl_oen), |
.sda_i(sda_i), |
.sda_o(sda_o), |
.sda_oen(sda_oen) |
.clk ( clk ), |
.rst ( rst ), |
.nReset ( nReset ), |
.ena ( ena ), |
.clk_cnt ( clk_cnt ), |
.cmd ( core_cmd ), |
.cmd_ack ( core_ack ), |
.busy ( i2c_busy ), |
.din ( core_txd ), |
.dout ( core_rxd ), |
.scl_i ( scl_i ), |
.scl_o ( scl_o ), |
.scl_oen ( scl_oen ), |
.sda_i ( sda_i ), |
.sda_o ( sda_o ), |
.sda_oen ( sda_oen ) |
); |
|
// generate go-signal |
assign go = (read || write || stop) && !cmd_ack; |
assign go = (read | write | stop) & ~cmd_ack; |
|
// assign dout output to shift-register |
assign dout = sr; |
|
// generate shift register |
always@(posedge clk or negedge nReset) |
if (!nReset) |
sr <= #1 8'h0; |
else if (rst) |
sr <= #1 8'h0; |
else if (ld) |
sr <= #1 din; |
else if (shift) |
sr <= #1 {sr[6:0], core_rxd}; |
always @(posedge clk or negedge nReset) |
if (!nReset) |
sr <= #1 8'h0; |
else if (rst) |
sr <= #1 8'h0; |
else if (ld) |
sr <= #1 din; |
else if (shift) |
sr <= #1 {sr[6:0], core_rxd}; |
|
// generate counter |
always@(posedge clk or negedge nReset) |
if (!nReset) |
dcnt <= #1 3'h0; |
else if (rst) |
dcnt <= #1 3'h0; |
else if (ld) |
dcnt <= #1 3'h7; |
else if (shift) |
dcnt <= #1 dcnt - 3'h1; |
always @(posedge clk or negedge nReset) |
if (!nReset) |
dcnt <= #1 3'h0; |
else if (rst) |
dcnt <= #1 3'h0; |
else if (ld) |
dcnt <= #1 3'h7; |
else if (shift) |
dcnt <= #1 dcnt - 3'h1; |
|
assign cnt_done = !(|dcnt); |
|
175,158 → 180,147
// |
reg [4:0] c_state; // synopsis enum_state |
|
always@(posedge clk or negedge nReset) |
if (!nReset) |
begin |
core_cmd <= #1 `I2C_CMD_NOP; |
core_txd <= #1 1'b0; |
|
shift <= #1 1'b0; |
ld <= #1 1'b0; |
|
cmd_ack <= #1 1'b0; |
c_state <= #1 ST_IDLE; |
|
ack_out <= #1 1'b0; |
end |
else if (rst) |
begin |
core_cmd <= #1 `I2C_CMD_NOP; |
core_txd <= #1 1'b0; |
|
shift <= #1 1'b0; |
ld <= #1 1'b0; |
|
cmd_ack <= #1 1'b0; |
c_state <= #1 ST_IDLE; |
|
ack_out <= #1 1'b0; |
end |
always @(posedge clk or negedge nReset) |
if (!nReset) |
begin |
core_cmd <= #1 `I2C_CMD_NOP; |
core_txd <= #1 1'b0; |
shift <= #1 1'b0; |
ld <= #1 1'b0; |
cmd_ack <= #1 1'b0; |
c_state <= #1 ST_IDLE; |
ack_out <= #1 1'b0; |
end |
else if (rst) |
begin |
core_cmd <= #1 `I2C_CMD_NOP; |
core_txd <= #1 1'b0; |
shift <= #1 1'b0; |
ld <= #1 1'b0; |
cmd_ack <= #1 1'b0; |
c_state <= #1 ST_IDLE; |
ack_out <= #1 1'b0; |
end |
else |
begin |
// initially reset all signals |
core_txd <= #1 sr[7]; |
|
shift <= #1 1'b0; |
ld <= #1 1'b0; |
begin |
// initially reset all signals |
core_txd <= #1 sr[7]; |
shift <= #1 1'b0; |
ld <= #1 1'b0; |
cmd_ack <= #1 1'b0; |
|
cmd_ack <= #1 1'b0; |
case (c_state) // synopsis full_case parallel_case |
ST_IDLE: |
if (go) |
begin |
if (start) |
begin |
c_state <= #1 ST_START; |
core_cmd <= #1 `I2C_CMD_START; |
end |
else if (read) |
begin |
c_state <= #1 ST_READ; |
core_cmd <= #1 `I2C_CMD_READ; |
end |
else if (write) |
begin |
c_state <= #1 ST_WRITE; |
core_cmd <= #1 `I2C_CMD_WRITE; |
end |
else // stop |
begin |
c_state <= #1 ST_STOP; |
core_cmd <= #1 `I2C_CMD_STOP; |
|
case (c_state) // synopsis full_case parallel_case |
ST_IDLE: |
if (go) |
begin |
if (start) |
begin |
c_state <= #1 ST_START; |
core_cmd <= #1 `I2C_CMD_START; |
end |
else if (read) |
begin |
c_state <= #1 ST_READ; |
core_cmd <= #1 `I2C_CMD_READ; |
end |
else if (write) |
begin |
c_state <= #1 ST_WRITE; |
core_cmd <= #1 `I2C_CMD_WRITE; |
end |
else // stop |
begin |
c_state <= #1 ST_STOP; |
core_cmd <= #1 `I2C_CMD_STOP; |
// generate command acknowledge signal |
cmd_ack <= #1 1'b1; |
end |
|
// generate command acknowledge signal |
cmd_ack <= #1 1'b1; |
end |
ld <= #1 1'b1; |
end |
|
ld <= #1 1'b1; |
end |
ST_START: |
if (core_ack) |
begin |
if (read) |
begin |
c_state <= #1 ST_READ; |
core_cmd <= #1 `I2C_CMD_READ; |
end |
else |
begin |
c_state <= #1 ST_WRITE; |
core_cmd <= #1 `I2C_CMD_WRITE; |
end |
|
ST_START: |
if (core_ack) |
begin |
if (read) |
begin |
c_state <= #1 ST_READ; |
core_cmd <= #1 `I2C_CMD_READ; |
end |
else |
begin |
c_state <= #1 ST_WRITE; |
core_cmd <= #1 `I2C_CMD_WRITE; |
end |
ld <= #1 1'b1; |
end |
|
ld <= #1 1'b1; |
end |
ST_WRITE: |
if (core_ack) |
if (cnt_done) |
begin |
c_state <= #1 ST_ACK; |
core_cmd <= #1 `I2C_CMD_READ; |
end |
else |
begin |
c_state <= #1 ST_WRITE; // stay in same state |
core_cmd <= #1 `I2C_CMD_WRITE; // write next bit |
shift <= #1 1'b1; |
end |
|
ST_WRITE: |
if (core_ack) |
if (cnt_done) |
begin |
c_state <= #1 ST_ACK; |
core_cmd <= #1 `I2C_CMD_READ; |
end |
else |
begin |
c_state <= #1 ST_WRITE; // stay in same state |
core_cmd <= #1 `I2C_CMD_WRITE; // write next bit |
ST_READ: |
if (core_ack) |
begin |
if (cnt_done) |
begin |
c_state <= #1 ST_ACK; |
core_cmd <= #1 `I2C_CMD_WRITE; |
end |
else |
begin |
c_state <= #1 ST_READ; // stay in same state |
core_cmd <= #1 `I2C_CMD_READ; // read next bit |
end |
|
shift <= #1 1'b1; |
end |
shift <= #1 1'b1; |
core_txd <= #1 ack_in; |
end |
|
ST_READ: |
if (core_ack) |
begin |
if (cnt_done) |
begin |
c_state <= #1 ST_ACK; |
core_cmd <= #1 `I2C_CMD_WRITE; |
end |
else |
begin |
c_state <= #1 ST_READ; // stay in same state |
core_cmd <= #1 `I2C_CMD_READ; // read next bit |
end |
ST_ACK: |
if (core_ack) |
begin |
if (stop) |
begin |
c_state <= #1 ST_STOP; |
core_cmd <= #1 `I2C_CMD_STOP; |
end |
else |
begin |
c_state <= #1 ST_IDLE; |
core_cmd <= #1 `I2C_CMD_NOP; |
end |
|
shift <= #1 1'b1; |
core_txd <= #1 ack_in; |
end |
// assign ack_out output to bit_controller_rxd (contains last received bit) |
ack_out <= #1 core_rxd; |
|
ST_ACK: |
if (core_ack) |
begin |
if (stop) |
begin |
c_state <= #1 ST_STOP; |
core_cmd <= #1 `I2C_CMD_STOP; |
end |
else |
begin |
c_state <= #1 ST_IDLE; |
core_cmd <= #1 `I2C_CMD_NOP; |
end |
// generate command acknowledge signal |
cmd_ack <= #1 1'b1; |
|
// assign ack_out output to bit_controller_rxd (contains last received bit) |
ack_out <= #1 core_rxd; |
core_txd <= #1 1'b1; |
end |
else |
core_txd <= #1 ack_in; |
|
// generate command acknowledge signal |
cmd_ack <= #1 1'b1; |
|
core_txd <= #1 1'b1; |
end |
else |
core_txd <= #1 ack_in; |
ST_STOP: |
if (core_ack) |
begin |
c_state <= #1 ST_IDLE; |
core_cmd <= #1 `I2C_CMD_NOP; |
end |
|
ST_STOP: |
if (core_ack) |
begin |
c_state <= #1 ST_IDLE; |
core_cmd <= #1 `I2C_CMD_NOP; |
end |
|
endcase |
end |
endcase |
end |
endmodule |
|
|
/trunk/rtl/verilog/i2c_master_bit_ctrl.v
37,10 → 37,10
|
// CVS Log |
// |
// $Id: i2c_master_bit_ctrl.v,v 1.4 2002-10-30 18:10:07 rherveille Exp $ |
// $Id: i2c_master_bit_ctrl.v,v 1.5 2002-11-30 22:24:40 rherveille Exp $ |
// |
// $Date: 2002-10-30 18:10:07 $ |
// $Revision: 1.4 $ |
// $Date: 2002-11-30 22:24:40 $ |
// $Revision: 1.5 $ |
// $Author: rherveille $ |
// $Locker: $ |
// $State: Exp $ |
47,6 → 47,9
// |
// Change History: |
// $Log: not supported by cvs2svn $ |
// Revision 1.4 2002/10/30 18:10:07 rherveille |
// Fixed some reported minor start/stop generation timing issuess. |
// |
// Revision 1.3 2002/06/15 07:37:03 rherveille |
// Fixed a small timing bug in the bit controller.\nAdded verilog simulation environment. |
// |
197,8 → 200,8
begin |
dSDA <= #1 sSDA; // generate a delayed version of sSDA |
|
sta_condition <= #1 !sSDA && dSDA && sSCL; |
sto_condition <= #1 sSDA && !dSDA && sSCL; |
sta_condition <= #1 ~sSDA & dSDA & sSCL; |
sto_condition <= #1 sSDA & ~dSDA & sSCL; |
end |
|
// generate bus busy signal |
208,7 → 211,7
else if (rst) |
busy <= #1 1'b0; |
else |
busy <= #1 (sta_condition || busy) && !sto_condition; |
busy <= #1 (sta_condition | busy) & ~sto_condition; |
|
|
// generate statemachine |
233,111 → 236,8
parameter [16:0] wr_c = 17'b0_1000_0000_0000_0000; |
parameter [16:0] wr_d = 17'b1_0000_0000_0000_0000; |
|
reg [16:0] c_state, nxt_state; // synopsis enum_state |
reg icmd_ack, store_sda; |
reg [16:0] c_state; // synopsis enum_state |
|
always @(c_state or cmd) |
begin |
nxt_state = c_state; |
icmd_ack = 1'b0; // default no command acknowledge |
store_sda = 1'b0; |
|
case (c_state) // synopsis full_case parallel_case |
// idle state |
idle: |
case (cmd) // synopsis full_case parallel_case |
`I2C_CMD_START: |
nxt_state = start_a; |
|
`I2C_CMD_STOP: |
nxt_state = stop_a; |
|
`I2C_CMD_WRITE: |
nxt_state = wr_a; |
|
`I2C_CMD_READ: |
nxt_state = rd_a; |
|
default: |
nxt_state = idle; |
|
endcase |
|
// start |
start_a: |
nxt_state = start_b; |
|
start_b: |
nxt_state = start_c; |
|
start_c: |
nxt_state = start_d; |
|
start_d: |
nxt_state = start_e; |
|
start_e: |
begin |
nxt_state = idle; |
icmd_ack = 1'b1; |
end |
|
// stop |
stop_a: |
nxt_state = stop_b; |
|
stop_b: |
nxt_state = stop_c; |
|
stop_c: |
nxt_state = stop_d; |
|
stop_d: |
begin |
nxt_state = idle; |
icmd_ack = 1'b1; |
end |
|
// read |
rd_a: |
nxt_state = rd_b; |
|
rd_b: |
nxt_state = rd_c; |
|
rd_c: |
begin |
nxt_state = rd_d; |
store_sda = 1'b1; |
end |
|
rd_d: |
begin |
nxt_state = idle; |
icmd_ack = 1'b1; |
end |
|
// write |
wr_a: |
nxt_state = wr_b; |
|
wr_b: |
nxt_state = wr_c; |
|
wr_c: |
nxt_state = wr_d; |
|
wr_d: |
begin |
nxt_state = idle; |
icmd_ack = 1'b1; |
end |
|
endcase |
end |
|
|
// generate registers |
always @(posedge clk or negedge nReset) |
if (!nReset) |
begin |
344,6 → 244,8
c_state <= #1 idle; |
cmd_ack <= #1 1'b0; |
dout <= #1 1'b0; |
scl_oen <= #1 1'b1; |
sda_oen <= #1 1'b1; |
end |
else if (rst) |
begin |
350,155 → 252,173
c_state <= #1 idle; |
cmd_ack <= #1 1'b0; |
dout <= #1 1'b0; |
scl_oen <= #1 1'b1; |
sda_oen <= #1 1'b1; |
end |
else |
begin |
cmd_ack <= #1 1'b0; // default no command acknowledge + assert cmd_ack only 1clk cycle |
|
if (clk_en) |
begin |
c_state <= #1 nxt_state; |
if (store_sda) |
dout <= #1 sSDA; |
end |
case (c_state) // synopsis full_case parallel_case |
// idle state |
idle: |
begin |
case (cmd) // synopsis full_case parallel_case |
`I2C_CMD_START: |
c_state <= #1 start_a; |
|
cmd_ack <= #1 icmd_ack && clk_en; |
end |
`I2C_CMD_STOP: |
c_state <= #1 stop_a; |
|
// |
// convert states to SCL and SDA signals |
// |
`I2C_CMD_WRITE: |
c_state <= #1 wr_a; |
|
// assign scl and sda output (always gnd) |
assign scl_o = 1'b0; |
assign sda_o = 1'b0; |
`I2C_CMD_READ: |
c_state <= #1 rd_a; |
|
// assign scl and sda output_enables |
always @(posedge clk or negedge nReset) |
if (!nReset) |
begin |
scl_oen <= #1 1'b1; |
sda_oen <= #1 1'b1; |
end |
else if (rst) |
begin |
scl_oen <= #1 1'b1; |
sda_oen <= #1 1'b1; |
end |
else if (clk_en) |
case (c_state) // synopsis full_case parallel_case |
default: |
c_state <= #1 idle; |
endcase |
|
// idle state |
idle: |
begin |
scl_oen <= #1 scl_oen; // keep SCL in same state |
sda_oen <= #1 sda_oen; // keep SDA in same state |
end |
scl_oen <= #1 scl_oen; // keep SCL in same state |
sda_oen <= #1 sda_oen; // keep SDA in same state |
end |
|
// start |
start_a: |
begin |
scl_oen <= #1 scl_oen; // keep SCL in same state |
sda_oen <= #1 1'b1; // set SDA high |
end |
// start |
start_a: |
begin |
c_state <= #1 start_b; |
scl_oen <= #1 scl_oen; // keep SCL in same state |
sda_oen <= #1 1'b1; // set SDA high |
end |
|
start_b: |
begin |
scl_oen <= #1 1'b1; // set SCL high |
sda_oen <= #1 1'b1; // keep SDA high |
end |
start_b: |
begin |
c_state <= #1 start_c; |
scl_oen <= #1 1'b1; // set SCL high |
sda_oen <= #1 1'b1; // keep SDA high |
end |
|
start_c: |
begin |
scl_oen <= #1 1'b1; // keep SCL high |
sda_oen <= #1 1'b0; // set SDA low |
end |
start_c: |
begin |
c_state <= #1 start_d; |
scl_oen <= #1 1'b1; // keep SCL high |
sda_oen <= #1 1'b0; // set SDA low |
end |
|
start_d: |
begin |
scl_oen <= #1 1'b1; // keep SCL high |
sda_oen <= #1 1'b0; // keep SDA low |
end |
start_d: |
begin |
c_state <= #1 start_e; |
scl_oen <= #1 1'b1; // keep SCL high |
sda_oen <= #1 1'b0; // keep SDA low |
end |
|
start_e: |
begin |
scl_oen <= #1 1'b0; // set SCL low |
sda_oen <= #1 1'b0; // keep SDA low |
end |
start_e: |
begin |
c_state <= #1 idle; |
cmd_ack <= #1 1'b1; |
scl_oen <= #1 1'b0; // set SCL low |
sda_oen <= #1 1'b0; // keep SDA low |
end |
|
// stop |
stop_a: |
begin |
scl_oen <= #1 1'b0; // keep SCL low |
sda_oen <= #1 1'b0; // set SDA low |
end |
// stop |
stop_a: |
begin |
c_state <= #1 stop_b; |
scl_oen <= #1 1'b0; // keep SCL low |
sda_oen <= #1 1'b0; // set SDA low |
end |
|
stop_b: |
begin |
scl_oen <= #1 1'b1; // set SCL high |
sda_oen <= #1 1'b0; // keep SDA low |
end |
stop_b: |
begin |
c_state <= #1 stop_c; |
scl_oen <= #1 1'b1; // set SCL high |
sda_oen <= #1 1'b0; // keep SDA low |
end |
|
stop_c: |
begin |
scl_oen <= #1 1'b1; // keep SCL high |
sda_oen <= #1 1'b0; // keep SDA low |
end |
stop_c: |
begin |
c_state <= #1 stop_d; |
scl_oen <= #1 1'b1; // keep SCL high |
sda_oen <= #1 1'b0; // keep SDA low |
end |
|
stop_d: |
begin |
scl_oen <= #1 1'b1; // keep SCL high |
sda_oen <= #1 1'b1; // set SDA high |
end |
stop_d: |
begin |
c_state <= #1 idle; |
cmd_ack <= #1 clk_en; |
scl_oen <= #1 1'b1; // keep SCL high |
sda_oen <= #1 1'b1; // set SDA high |
end |
|
//write |
wr_a: |
begin |
scl_oen <= #1 1'b0; // keep SCL low |
sda_oen <= #1 din; // set SDA |
end |
// read |
rd_a: |
begin |
c_state <= #1 rd_b; |
scl_oen <= #1 1'b0; // keep SCL low |
sda_oen <= #1 1'b1; // tri-state SDA |
end |
|
wr_b: |
begin |
scl_oen <= #1 1'b1; // set SCL high |
sda_oen <= #1 din; // keep SDA |
end |
rd_b: |
begin |
c_state <= #1 rd_c; |
scl_oen <= #1 1'b1; // set SCL high |
sda_oen <= #1 1'b1; // keep SDA tri-stated |
end |
|
wr_c: |
begin |
scl_oen <= #1 1'b1; // keep SCL high |
sda_oen <= #1 din; |
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; |
end |
|
wr_d: |
begin |
scl_oen <= #1 1'b0; // set SCL low |
sda_oen <= #1 din; |
end |
rd_d: |
begin |
c_state <= #1 idle; |
cmd_ack <= #1 clk_en; |
scl_oen <= #1 1'b0; // set SCL low |
sda_oen <= #1 1'b1; |
end |
|
// read |
rd_a: |
begin |
scl_oen <= #1 1'b0; // keep SCL low |
sda_oen <= #1 1'b1; // tri-state SDA |
end |
// write |
wr_a: |
begin |
c_state <= #1 wr_b; |
scl_oen <= #1 1'b0; // keep SCL low |
sda_oen <= #1 din; // set SDA |
end |
|
rd_b: |
begin |
scl_oen <= #1 1'b1; // set SCL high |
sda_oen <= #1 1'b1; // keep SDA tri-stated |
end |
wr_b: |
begin |
c_state <= #1 wr_c; |
scl_oen <= #1 1'b1; // set SCL high |
sda_oen <= #1 din; // keep SDA |
end |
|
rd_c: |
begin |
scl_oen <= #1 1'b1; // keep SCL high |
sda_oen <= #1 1'b1; |
end |
wr_c: |
begin |
c_state <= #1 wr_d; |
scl_oen <= #1 1'b1; // keep SCL high |
sda_oen <= #1 din; |
end |
|
rd_d: |
begin |
scl_oen <= #1 1'b0; // set SCL low |
sda_oen <= #1 1'b1; |
end |
wr_d: |
begin |
c_state <= #1 idle; |
cmd_ack <= #1 1'b1; |
scl_oen <= #1 1'b0; // set SCL low |
sda_oen <= #1 din; |
end |
|
endcase |
endcase |
end |
|
|
// assign scl and sda output (always gnd) |
assign scl_o = 1'b0; |
assign sda_o = 1'b0; |
|
endmodule |
/trunk/rtl/verilog/i2c_master_top.v
1,6 → 1,6
///////////////////////////////////////////////////////////////////// |
//// //// |
//// WISHBONE rev.B2 compliant I2C Master controller Top-level //// |
//// WISHBONE revB.2 compliant I2C Master controller Top-level //// |
//// //// |
//// //// |
//// Author: Richard Herveille //// |
37,10 → 37,10
|
// CVS Log |
// |
// $Id: i2c_master_top.v,v 1.5 2001-11-10 10:52:55 rherveille Exp $ |
// $Id: i2c_master_top.v,v 1.6 2002-11-30 22:24:40 rherveille Exp $ |
// |
// $Date: 2001-11-10 10:52:55 $ |
// $Revision: 1.5 $ |
// $Date: 2002-11-30 22:24:40 $ |
// $Revision: 1.6 $ |
// $Author: rherveille $ |
// $Locker: $ |
// $State: Exp $ |
47,8 → 47,14
// |
// Change History: |
// $Log: not supported by cvs2svn $ |
// Revision 1.5 2001/11/10 10:52:55 rherveille |
// Changed PRER reset value from 0x0000 to 0xffff, conform specs. |
// |
|
// synopsys translate_off |
`include "timescale.v" |
// synopsys translate_on |
|
`include "i2c_master_defines.v" |
|
module i2c_master_top( |
70,12 → 76,14
input [2:0] wb_adr_i; // lower address bits |
input [7:0] wb_dat_i; // databus input |
output [7:0] wb_dat_o; // databus output |
reg [7:0] wb_dat_o; |
input wb_we_i; // write enable input |
input wb_stb_i; // stobe/core select signal |
input wb_cyc_i; // valid bus cycle input |
output wb_ack_o; // bus cycle acknowledge output |
output wb_inta_o; // interrupt request signal output |
|
reg [7:0] wb_dat_o; |
reg wb_ack_o; |
reg wb_inta_o; |
|
// I2C signals |
83,6 → 91,7
input scl_pad_i; // SCL-line input |
output scl_pad_o; // SCL-line output (always 1'b0) |
output scl_padoen_o; // SCL-line output enable (active low) |
|
// i2c data line |
input sda_pad_i; // SDA-line input |
output sda_pad_o; // SDA-line output (always 1'b0) |
121,64 → 130,65
|
// generate internal reset |
wire rst_i = arst_i ^ ARST_LVL; |
|
|
// generate acknowledge output signal |
assign wb_ack_o = wb_cyc_i && wb_stb_i; // because timing is always honored |
always @(posedge wb_clk_i) |
wb_ack_o <= #1 wb_cyc_i & wb_stb_i & ~wb_ack_o; // because timing is always honored |
|
// assign DAT_O |
always@(wb_adr_i or prer or ctr or txr or cr or rxr or sr) |
always @(posedge wb_clk_i) |
begin |
case (wb_adr_i) // synopsis full_case parallel_case |
3'b000: wb_dat_o = prer[ 7:0]; |
3'b001: wb_dat_o = prer[15:8]; |
3'b010: wb_dat_o = ctr; |
3'b011: wb_dat_o = rxr; // write is transmit register (txr) |
3'b100: wb_dat_o = sr; // write is command register (cr) |
3'b101: wb_dat_o = txr; |
3'b110: wb_dat_o = cr; |
3'b111: wb_dat_o = 0; // reserved |
endcase |
case (wb_adr_i) // synopsis full_case parallel_case |
3'b000: wb_dat_o = prer[ 7:0]; |
3'b001: wb_dat_o = prer[15:8]; |
3'b010: wb_dat_o = ctr; |
3'b011: wb_dat_o = rxr; // write is transmit register (txr) |
3'b100: wb_dat_o = sr; // write is command register (cr) |
3'b101: wb_dat_o = txr; |
3'b110: wb_dat_o = cr; |
3'b111: wb_dat_o = 0; // reserved |
endcase |
end |
|
|
// generate registers |
always@(posedge wb_clk_i or negedge rst_i) |
if (!rst_i) |
begin |
prer <= #1 16'hffff; |
ctr <= #1 8'h0; |
txr <= #1 8'h0; |
cr <= #1 8'h0; |
end |
else if (wb_rst_i) |
begin |
prer <= #1 16'hffff; |
ctr <= #1 8'h0; |
txr <= #1 8'h0; |
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 |
always @(posedge wb_clk_i or negedge rst_i) |
if (!rst_i) |
begin |
prer <= #1 16'hffff; |
ctr <= #1 8'h0; |
txr <= #1 8'h0; |
cr <= #1 8'h0; |
end |
else if (wb_rst_i) |
begin |
prer <= #1 16'hffff; |
ctr <= #1 8'h0; |
txr <= #1 8'h0; |
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 |
|
cr[2:1] <= #1 2'b00; // reserved bits |
cr[0] <= #1 cr[0] && irq_flag; // clear when irq_flag 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 |
195,75 → 205,65
|
// hookup byte controller block |
i2c_master_byte_ctrl byte_controller ( |
.clk(wb_clk_i), |
.rst(wb_rst_i), |
.nReset(rst_i), |
.ena(core_en), |
.clk_cnt(prer), |
.start(sta), |
.stop(sto), |
.read(rd), |
.write(wr), |
.ack_in(ack), |
.din(txr), |
.cmd_ack(done), |
.ack_out(irxack), |
.dout(rxr), |
.i2c_busy(i2c_busy), |
.scl_i(scl_pad_i), |
.scl_o(scl_pad_o), |
.scl_oen(scl_padoen_o), |
.sda_i(sda_pad_i), |
.sda_o(sda_pad_o), |
.sda_oen(sda_padoen_o) |
.clk ( wb_clk_i ), |
.rst ( wb_rst_i ), |
.nReset ( rst_i ), |
.ena ( core_en ), |
.clk_cnt ( prer ), |
.start ( sta ), |
.stop ( sto ), |
.read ( rd ), |
.write ( wr ), |
.ack_in ( ack ), |
.din ( txr ), |
.cmd_ack ( done ), |
.ack_out ( irxack ), |
.dout ( rxr ), |
.i2c_busy ( i2c_busy ), |
.scl_i ( scl_pad_i ), |
.scl_o ( scl_pad_o ), |
.scl_oen ( scl_padoen_o ), |
.sda_i ( sda_pad_i ), |
.sda_o ( sda_pad_o ), |
.sda_oen ( sda_padoen_o ) |
); |
|
|
// status register block + interrupt request signal |
always@(posedge wb_clk_i or negedge rst_i) |
if (!rst_i) |
begin |
rxack <= #1 1'b0; |
tip <= #1 1'b0; |
irq_flag <= #1 1'b0; |
end |
else if (wb_rst_i) |
begin |
rxack <= #1 1'b0; |
tip <= #1 1'b0; |
irq_flag <= #1 1'b0; |
end |
else |
begin |
rxack <= #1 irxack; |
tip <= #1 (rd || wr); |
irq_flag <= #1 (done || irq_flag) && !iack; // interrupt request flag is always generated |
end |
always @(posedge wb_clk_i or negedge rst_i) |
if (!rst_i) |
begin |
rxack <= #1 1'b0; |
tip <= #1 1'b0; |
irq_flag <= #1 1'b0; |
end |
else if (wb_rst_i) |
begin |
rxack <= #1 1'b0; |
tip <= #1 1'b0; |
irq_flag <= #1 1'b0; |
end |
else |
begin |
rxack <= #1 irxack; |
tip <= #1 (rd | wr); |
irq_flag <= #1 (done | irq_flag) & ~iack; // interrupt request flag is always generated |
end |
|
// generate interrupt request signals |
always@(posedge wb_clk_i or negedge rst_i) |
if (!rst_i) |
wb_inta_o <= #1 1'b0; |
else if (wb_rst_i) |
wb_inta_o <= #1 1'b0; |
else |
wb_inta_o <= #1 irq_flag && ien; // interrupt signal is only generated when IEN (interrupt enable bit is set) |
// generate interrupt request signals |
always @(posedge wb_clk_i or negedge rst_i) |
if (!rst_i) |
wb_inta_o <= #1 1'b0; |
else if (wb_rst_i) |
wb_inta_o <= #1 1'b0; |
else |
wb_inta_o <= #1 irq_flag && ien; // interrupt signal is only generated when IEN (interrupt enable bit is set) |
|
// assign status register bits |
assign sr[7] = rxack; |
assign sr[6] = i2c_busy; |
assign sr[5:2] = 4'h0; // reserved |
assign sr[1] = tip; |
assign sr[0] = irq_flag; |
// assign status register bits |
assign sr[7] = rxack; |
assign sr[6] = i2c_busy; |
assign sr[5:2] = 4'h0; // reserved |
assign sr[1] = tip; |
assign sr[0] = irq_flag; |
|
endmodule |
|
|
|
|
|
|
|
|
|
|
/trunk/rtl/vhdl/i2c_master_byte_ctrl.vhd
37,10 → 37,10
|
-- CVS Log |
-- |
-- $Id: i2c_master_byte_ctrl.vhd,v 1.1 2001-11-05 12:02:33 rherveille Exp $ |
-- $Id: i2c_master_byte_ctrl.vhd,v 1.2 2002-11-30 22:24:37 rherveille Exp $ |
-- |
-- $Date: 2001-11-05 12:02:33 $ |
-- $Revision: 1.1 $ |
-- $Date: 2002-11-30 22:24:37 $ |
-- $Revision: 1.2 $ |
-- $Author: rherveille $ |
-- $Locker: $ |
-- $State: Exp $ |
47,6 → 47,11
-- |
-- Change History: |
-- $Log: not supported by cvs2svn $ |
-- Revision 1.1 2001/11/05 12:02:33 rherveille |
-- Split i2c_master_core.vhd into separate files for each entity; same layout as verilog version. |
-- Code updated, is now up-to-date to doc. rev.0.4. |
-- Added headers. |
-- |
|
|
|
61,9 → 66,6
use ieee.std_logic_arith.all; |
|
entity i2c_master_byte_ctrl is |
generic( |
Tcq : time := 1 ns |
); |
port ( |
clk : in std_logic; |
rst : in std_logic; -- synchronous active high reset (WISHBONE compatible) |
70,7 → 72,7
nReset : in std_logic; -- asynchornous active low reset (FPGA compatible) |
ena : in std_logic; -- core enable signal |
|
clk_cnt : in unsigned(15 downto 0); -- 4x SCL |
clk_cnt : in unsigned(15 downto 0); -- 4x SCL |
|
-- input signals |
start, |
98,32 → 100,29
|
architecture structural of i2c_master_byte_ctrl is |
component i2c_master_bit_ctrl is |
generic( |
Tcq : time := Tcq |
); |
port ( |
clk : in std_logic; |
rst : in std_logic; |
nReset : in std_logic; |
ena : in std_logic; -- core enable signal |
port ( |
clk : in std_logic; |
rst : in std_logic; |
nReset : in std_logic; |
ena : in std_logic; -- core enable signal |
|
clk_cnt : in unsigned(15 downto 0); -- clock prescale value |
clk_cnt : in unsigned(15 downto 0); -- clock prescale value |
|
cmd : in std_logic_vector(3 downto 0); |
cmd_ack : out std_logic; |
busy : out std_logic; |
cmd : in std_logic_vector(3 downto 0); |
cmd_ack : out std_logic; |
busy : out std_logic; |
|
din : in std_logic; |
dout : out std_logic; |
din : in std_logic; |
dout : out std_logic; |
|
-- i2c lines |
scl_i : in std_logic; -- i2c clock line input |
scl_o : out std_logic; -- i2c clock line output |
scl_oen : out std_logic; -- i2c clock line output enable, active low |
sda_i : in std_logic; -- i2c data line input |
sda_o : out std_logic; -- i2c data line output |
sda_oen : out std_logic -- i2c data line output enable, active low |
); |
-- i2c lines |
scl_i : in std_logic; -- i2c clock line input |
scl_o : out std_logic; -- i2c clock line output |
scl_oen : out std_logic; -- i2c clock line output enable, active low |
sda_i : in std_logic; -- i2c data line input |
sda_o : out std_logic; -- i2c data line output |
sda_oen : out std_logic -- i2c data line output enable, active low |
); |
end component i2c_master_bit_ctrl; |
|
-- commands for bit_controller block |
169,7 → 168,7
|
-- generate host-command-acknowledge |
cmd_ack <= host_ack; |
|
|
-- generate go-signal |
go <= (read or write or stop) and not host_ack; |
|
179,33 → 178,33
-- generate shift register |
shift_register: process(clk, nReset) |
begin |
if (nReset = '0') then |
sr <= (others => '0') after Tcq; |
elsif (clk'event and clk = '1') then |
if (rst = '1') then |
sr <= (others => '0') after Tcq; |
elsif (ld = '1') then |
sr <= din after Tcq; |
elsif (shift = '1') then |
sr <= (sr(6 downto 0) & core_rxd) after Tcq; |
end if; |
end if; |
if (nReset = '0') then |
sr <= (others => '0'); |
elsif (clk'event and clk = '1') then |
if (rst = '1') then |
sr <= (others => '0'); |
elsif (ld = '1') then |
sr <= din; |
elsif (shift = '1') then |
sr <= (sr(6 downto 0) & core_rxd); |
end if; |
end if; |
end process shift_register; |
|
-- generate data-counter |
data_cnt: process(clk, nReset) |
begin |
if (nReset = '0') then |
dcnt <= (others => '0') after Tcq; |
elsif (clk'event and clk = '1') then |
if (rst = '1') then |
dcnt <= (others => '0') after Tcq; |
elsif (ld = '1') then |
dcnt <= (others => '1') after Tcq; -- load counter with 7 |
elsif (shift = '1') then |
dcnt <= dcnt -1 after Tcq; |
end if; |
end if; |
if (nReset = '0') then |
dcnt <= (others => '0'); |
elsif (clk'event and clk = '1') then |
if (rst = '1') then |
dcnt <= (others => '0'); |
elsif (ld = '1') then |
dcnt <= (others => '1'); -- load counter with 7 |
elsif (shift = '1') then |
dcnt <= dcnt -1; |
end if; |
end if; |
end process data_cnt; |
|
cnt_done <= '1' when (dcnt = 0) else '0'; |
214,147 → 213,137
-- state machine |
-- |
statemachine : block |
type states is (st_idle, st_start, st_read, st_write, st_ack, st_stop); |
signal c_state : states; |
type states is (st_idle, st_start, st_read, st_write, st_ack, st_stop); |
signal c_state : states; |
begin |
-- |
-- command interpreter, translate complex commands into simpler I2C commands |
-- |
nxt_state_decoder: process(clk, nReset) |
begin |
if (nReset = '0') then |
core_cmd <= I2C_CMD_NOP after Tcq; |
core_txd <= '0' after Tcq; |
|
shift <= '0' after Tcq; |
ld <= '0' after Tcq; |
-- |
-- command interpreter, translate complex commands into simpler I2C commands |
-- |
nxt_state_decoder: process(clk, nReset) |
begin |
if (nReset = '0') then |
core_cmd <= I2C_CMD_NOP; |
core_txd <= '0'; |
shift <= '0'; |
ld <= '0'; |
host_ack <= '0'; |
c_state <= st_idle; |
ack_out <= '0'; |
elsif (clk'event and clk = '1') then |
if (rst = '1') then |
core_cmd <= I2C_CMD_NOP; |
core_txd <= '0'; |
shift <= '0'; |
ld <= '0'; |
host_ack <= '0'; |
c_state <= st_idle; |
ack_out <= '0'; |
else |
-- initialy reset all signal |
core_txd <= sr(7); |
shift <= '0'; |
ld <= '0'; |
host_ack <= '0'; |
|
host_ack <= '0' after Tcq; |
c_state <= st_idle after Tcq; |
case c_state is |
when st_idle => |
if (go = '1') then |
if (start = '1') then |
c_state <= st_start; |
core_cmd <= I2C_CMD_START; |
elsif (read = '1') then |
c_state <= st_read; |
core_cmd <= I2C_CMD_READ; |
elsif (write = '1') then |
c_state <= st_write; |
core_cmd <= I2C_CMD_WRITE; |
else -- stop |
c_state <= st_stop; |
core_cmd <= I2C_CMD_STOP; |
host_ack <= '1'; -- generate acknowledge signal |
end if; |
|
ack_out <= '0' after Tcq; |
elsif (clk'event and clk = '1') then |
if (rst = '1') then |
core_cmd <= I2C_CMD_NOP after Tcq; |
core_txd <= '0' after Tcq; |
|
shift <= '0' after Tcq; |
ld <= '0' after Tcq; |
ld <= '1'; |
end if; |
|
host_ack <= '0' after Tcq; |
c_state <= st_idle after Tcq; |
when st_start => |
if (core_ack = '1') then |
if (read = '1') then |
c_state <= st_read; |
core_cmd <= I2C_CMD_READ; |
else |
c_state <= st_write; |
core_cmd <= I2C_CMD_WRITE; |
end if; |
|
ack_out <= '0' after Tcq; |
else |
-- initialy reset all signal |
core_txd <= sr(7) after Tcq; |
ld <= '1'; |
end if; |
|
shift <= '0' after Tcq; |
ld <= '0' after Tcq; |
when st_write => |
if (core_ack = '1') then |
if (cnt_done = '1') then |
c_state <= st_ack; |
core_cmd <= I2C_CMD_READ; |
else |
c_state <= st_write; -- stay in same state |
core_cmd <= I2C_CMD_WRITE; -- write next bit |
shift <= '1'; |
end if; |
end if; |
|
host_ack <= '0' after Tcq; |
when st_read => |
if (core_ack = '1') then |
if (cnt_done = '1') then |
c_state <= st_ack; |
core_cmd <= I2C_CMD_WRITE; |
else |
c_state <= st_read; -- stay in same state |
core_cmd <= I2C_CMD_READ; -- read next bit |
end if; |
|
case c_state is |
when st_idle => |
if (go = '1') then |
if (start = '1') then |
c_state <= st_start after Tcq; |
core_cmd <= I2C_CMD_START after Tcq; |
elsif (read = '1') then |
c_state <= st_read after Tcq; |
core_cmd <= I2C_CMD_READ after Tcq; |
elsif (write = '1') then |
c_state <= st_write after Tcq; |
core_cmd <= I2C_CMD_WRITE after Tcq; |
else -- stop |
c_state <= st_stop after Tcq; |
core_cmd <= I2C_CMD_STOP after Tcq; |
shift <= '1'; |
core_txd <= ack_in; |
end if; |
|
host_ack <= '1' after Tcq; -- generate acknowledge signal |
end if; |
when st_ack => |
if (core_ack = '1') then |
-- check for stop; Should a STOP command be generated ? |
if (stop = '1') then |
c_state <= st_stop; |
core_cmd <= I2C_CMD_STOP; |
else |
c_state <= st_idle; |
core_cmd <= I2C_CMD_NOP; |
end if; |
|
ld <= '1' after Tcq; |
end if; |
-- assign ack_out output to core_rxd (contains last received bit) |
ack_out <= core_rxd; |
|
when st_start => |
if (core_ack = '1') then |
if (read = '1') then |
c_state <= st_read after Tcq; |
core_cmd <= I2C_CMD_READ after Tcq; |
else |
c_state <= st_write after Tcq; |
core_cmd <= I2C_CMD_WRITE after Tcq; |
end if; |
-- generate command acknowledge signal |
host_ack <= '1'; |
|
ld <= '1' after Tcq; |
end if; |
core_txd <= '1'; |
else |
core_txd <= ack_in; |
end if; |
|
when st_write => |
if (core_ack = '1') then |
if (cnt_done = '1') then |
c_state <= st_ack after Tcq; |
core_cmd <= I2C_CMD_READ after Tcq; |
else |
c_state <= st_write after Tcq; -- stay in same state |
core_cmd <= I2C_CMD_WRITE after Tcq; -- write next bit |
when st_stop => |
if (core_ack = '1') then |
c_state <= st_idle; |
core_cmd <= I2C_CMD_NOP; |
end if; |
|
shift <= '1' after Tcq; |
end if; |
end if; |
when others => -- illegal states |
c_state <= st_idle; |
core_cmd <= I2C_CMD_NOP; |
report ("Byte controller entered illegal state."); |
|
when st_read => |
if (core_ack = '1') then |
if (cnt_done = '1') then |
c_state <= st_ack after Tcq; |
core_cmd <= I2C_CMD_WRITE after Tcq; |
else |
c_state <= st_read after Tcq; -- stay in same state |
core_cmd <= I2C_CMD_READ after Tcq; -- read next bit |
end if; |
end case; |
|
shift <= '1' after Tcq; |
core_txd <= ack_in after Tcq; |
end if; |
end if; |
end if; |
end process nxt_state_decoder; |
|
when st_ack => |
if (core_ack = '1') then |
-- check for stop; Should a STOP command be generated ? |
if (stop = '1') then |
c_state <= st_stop after Tcq; |
core_cmd <= I2C_CMD_STOP after Tcq; |
else |
c_state <= st_idle after Tcq; |
core_cmd <= I2C_CMD_NOP after Tcq; |
end if; |
|
-- assign ack_out output to core_rxd (contains last received bit) |
ack_out <= core_rxd after Tcq; |
|
-- generate command acknowledge signal |
host_ack <= '1' after Tcq; |
|
core_txd <= '1' after Tcq; |
else |
core_txd <= ack_in after Tcq; |
end if; |
|
when st_stop => |
if (core_ack = '1') then |
c_state <= st_idle after Tcq; |
core_cmd <= I2C_CMD_NOP after Tcq; |
end if; |
|
when others => -- illegal states |
c_state <= st_idle after Tcq; |
core_cmd <= I2C_CMD_NOP after Tcq; |
report ("Byte controller entered illegal state."); |
|
end case; |
|
end if; |
end if; |
end process nxt_state_decoder; |
|
end block statemachine; |
|
end architecture structural; |
/trunk/rtl/vhdl/i2c_master_bit_ctrl.vhd
1,6 → 1,6
--------------------------------------------------------------------- |
---- ---- |
---- WISHBONE revB2 compl. I2C Master Core; bit-controller ---- |
---- WISHBONE revB2 I2C Master Core; bit-controller ---- |
---- ---- |
---- ---- |
---- Author: Richard Herveille ---- |
37,10 → 37,10
|
-- CVS Log |
-- |
-- $Id: i2c_master_bit_ctrl.vhd,v 1.3 2002-10-30 18:09:53 rherveille Exp $ |
-- $Id: i2c_master_bit_ctrl.vhd,v 1.4 2002-11-30 22:24:37 rherveille Exp $ |
-- |
-- $Date: 2002-10-30 18:09:53 $ |
-- $Revision: 1.3 $ |
-- $Date: 2002-11-30 22:24:37 $ |
-- $Revision: 1.4 $ |
-- $Author: rherveille $ |
-- $Locker: $ |
-- $State: Exp $ |
47,6 → 47,9
-- |
-- Change History: |
-- $Log: not supported by cvs2svn $ |
-- Revision 1.3 2002/10/30 18:09:53 rherveille |
-- Fixed some reported minor start/stop generation timing issuess. |
-- |
-- Revision 1.2 2002/06/15 07:37:04 rherveille |
-- Fixed a small timing bug in the bit controller.\nAdded verilog simulation environment. |
-- |
101,9 → 104,6
use ieee.std_logic_arith.all; |
|
entity i2c_master_bit_ctrl is |
generic( |
Tcq : time := 1 ns |
); |
port ( |
clk : in std_logic; |
rst : in std_logic; |
136,7 → 136,7
constant I2C_CMD_READ : std_logic_vector(3 downto 0) := "0100"; |
constant I2C_CMD_WRITE : std_logic_vector(3 downto 0) := "1000"; |
|
type states is (idle, start_a, start_b, start_c, start_d, start_e, |
type states is (idle, start_a, start_b, start_c, start_d, start_e, |
stop_a, stop_b, stop_c, stop_d, rd_a, rd_b, rd_c, rd_d, wr_a, wr_b, wr_c, wr_d); |
signal c_state : states; |
|
153,8 → 153,8
synch_scl_sda: process(clk) |
begin |
if (clk'event and clk = '1') then |
sSCL <= scl_i after Tcq; |
sSDA <= sda_i after Tcq; |
sSCL <= scl_i; |
sSDA <= sda_i; |
end if; |
end process synch_SCL_SDA; |
|
162,7 → 162,7
process (clk) |
begin |
if (clk'event and clk = '1') then |
dscl_oen <= iscl_oen after Tcq; |
dscl_oen <= iscl_oen; |
end if; |
end process; |
|
173,21 → 173,21
gen_clken: process(clk, nReset) |
begin |
if (nReset = '0') then |
cnt <= (others => '0') after Tcq; |
clk_en <= '1' after Tcq; |
cnt <= (others => '0'); |
clk_en <= '1'; |
elsif (clk'event and clk = '1') then |
if (rst = '1') then |
cnt <= (others => '0') after Tcq; |
clk_en <= '1' after Tcq; |
cnt <= (others => '0'); |
clk_en <= '1'; |
else |
if ( (cnt = 0) or (ena = '0') ) then |
clk_en <= '1' after Tcq; |
cnt <= clk_cnt after Tcq; |
clk_en <= '1'; |
cnt <= clk_cnt; |
else |
if (slave_wait = '0') then |
cnt <= cnt -1 after Tcq; |
cnt <= cnt -1; |
end if; |
clk_en <= '0' after Tcq; |
clk_en <= '0'; |
end if; |
end if; |
end if; |
218,12 → 218,12
gen_busy: process(clk, nReset) |
begin |
if (nReset = '0') then |
ibusy <= '0' after Tcq; |
ibusy <= '0'; |
elsif (clk'event and clk = '1') then |
if (rst = '1') then |
ibusy <= '0' after Tcq; |
ibusy <= '0'; |
else |
ibusy <= (sta_condition or ibusy) and not sto_condition after Tcq; |
ibusy <= (sta_condition or ibusy) and not sto_condition; |
end if; |
end if; |
end process gen_busy; |
235,219 → 235,141
|
-- generate statemachine |
nxt_state_decoder : process (clk, nReset, c_state, cmd) |
variable nxt_state : states; |
variable icmd_ack, store_sda : std_logic; |
begin |
nxt_state := c_state; |
if (nReset = '0') then |
c_state <= idle; |
cmd_ack <= '0'; |
dout <= '0'; |
iscl_oen <= '1'; |
isda_oen <= '1'; |
elsif (clk'event and clk = '1') then |
if (rst = '1') then |
c_state <= idle; |
cmd_ack <= '0'; |
dout <= '0'; |
iscl_oen <= '1'; |
isda_oen <= '1'; |
else |
cmd_ack <= '0'; -- default no acknowledge |
|
icmd_ack := '0'; -- default no acknowledge |
if (clk_en = '1') then |
case (c_state) is |
-- idle |
when idle => |
case cmd is |
when I2C_CMD_START => c_state <= start_a; |
when I2C_CMD_STOP => c_state <= stop_a; |
when I2C_CMD_WRITE => c_state <= wr_a; |
when I2C_CMD_READ => c_state <= rd_a; |
when others => c_state <= idle; -- NOP command |
end case; |
|
store_sda := '0'; |
iscl_oen <= iscl_oen; -- keep SCL in same state |
isda_oen <= isda_oen; -- keep SDA in same state |
|
case (c_state) is |
-- idle |
when idle => |
case cmd is |
when I2C_CMD_START => |
nxt_state := start_a; |
-- start |
when start_a => |
c_state <= start_b; |
iscl_oen <= iscl_oen; -- keep SCL in same state (for repeated start) |
isda_oen <= '1'; -- set SDA high |
|
when I2C_CMD_STOP => |
nxt_state := stop_a; |
when start_b => |
c_state <= start_c; |
iscl_oen <= '1'; -- set SCL high |
isda_oen <= '1'; -- keep SDA high |
|
when I2C_CMD_WRITE => |
nxt_state := wr_a; |
when start_c => |
c_state <= start_d; |
iscl_oen <= '1'; -- keep SCL high |
isda_oen <= '0'; -- set SDA low |
|
when I2C_CMD_READ => |
nxt_state := rd_a; |
when start_d => |
c_state <= start_e; |
iscl_oen <= '1'; -- keep SCL high |
isda_oen <= '0'; -- keep SDA low |
|
when others => -- NOP command |
nxt_state := idle; |
end case; |
when start_e => |
c_state <= idle; |
cmd_ack <= '1'; -- command completed |
iscl_oen <= '0'; -- set SCL low |
isda_oen <= '0'; -- keep SDA low |
|
-- start |
when start_a => |
nxt_state := start_b; |
-- stop |
when stop_a => |
c_state <= stop_b; |
iscl_oen <= '0'; -- keep SCL disabled |
isda_oen <= '0'; -- set SDA low |
|
when start_b => |
nxt_state := start_c; |
when stop_b => |
c_state <= stop_c; |
iscl_oen <= '1'; -- set SCL high |
isda_oen <= '0'; -- keep SDA low |
|
when start_c => |
nxt_state := start_d; |
when stop_c => |
c_state <= stop_d; |
iscl_oen <= '1'; -- keep SCL high |
isda_oen <= '0'; -- keep SDA low |
|
when start_d => |
nxt_state := start_e; |
when stop_d => |
c_state <= idle; |
cmd_ack <= '1'; -- command completed |
iscl_oen <= '1'; -- keep SCL high |
isda_oen <= '1'; -- set SDA high |
|
when start_e => |
nxt_state := idle; |
icmd_ack := '1'; -- command completed |
-- read |
when rd_a => |
c_state <= rd_b; |
iscl_oen <= '0'; -- keep SCL low |
isda_oen <= '1'; -- tri-state SDA |
|
-- stop |
when stop_a => |
nxt_state := stop_b; |
when rd_b => |
c_state <= rd_c; |
iscl_oen <= '1'; -- set SCL high |
isda_oen <= '1'; -- tri-state SDA |
|
when stop_b => |
nxt_state := stop_c; |
when rd_c => |
c_state <= rd_d; |
dout <= sSDA; |
iscl_oen <= '1'; -- keep SCL high |
isda_oen <= '1'; -- tri-state SDA |
|
when stop_c => |
nxt_state := stop_d; |
when rd_d => |
c_state <= idle; |
cmd_ack <= '1'; -- command completed |
iscl_oen <= '0'; -- set SCL low |
isda_oen <= '1'; -- tri-state SDA |
|
when stop_d => |
nxt_state := idle; |
icmd_ack := '1'; -- command completed |
-- write |
when wr_a => |
c_state <= wr_b; |
iscl_oen <= '0'; -- keep SCL low |
isda_oen <= din; -- set SDA |
|
-- read |
when rd_a => |
nxt_state := rd_b; |
when wr_b => |
c_state <= wr_c; |
iscl_oen <= '1'; -- set SCL high |
isda_oen <= din; -- keep SDA |
|
when rd_b => |
nxt_state := rd_c; |
when wr_c => |
c_state <= wr_d; |
iscl_oen <= '1'; -- keep SCL high |
isda_oen <= din; -- keep SDA |
|
when rd_c => |
nxt_state := rd_d; |
store_sda := '1'; |
when wr_d => |
c_state <= idle; |
cmd_ack <= '1'; -- command completed |
iscl_oen <= '0'; -- set SCL low |
isda_oen <= din; -- keep SDA |
|
when rd_d => |
nxt_state := idle; |
icmd_ack := '1'; -- command completed |
when others => |
|
-- write |
when wr_a => |
nxt_state := wr_b; |
|
when wr_b => |
nxt_state := wr_c; |
|
when wr_c => |
nxt_state := wr_d; |
|
when wr_d => |
nxt_state := idle; |
icmd_ack := '1'; -- command completed |
|
end case; |
|
-- generate regs |
if (nReset = '0') then |
c_state <= idle after Tcq; |
cmd_ack <= '0' after Tcq; |
Dout <= '0' after Tcq; |
elsif (clk'event and clk = '1') then |
if (rst = '1') then |
c_state <= idle after Tcq; |
cmd_ack <= '0' after Tcq; |
Dout <= '0' after Tcq; |
elsif (clk_en = '1') then |
c_state <= nxt_state after Tcq; |
|
if (store_sda = '1') then |
dout <= sSDA after Tcq; |
end case; |
end if; |
end if; |
|
cmd_ack <= icmd_ack and clk_en; |
end if; |
end process nxt_state_decoder; |
|
-- |
-- convert states to SCL and SDA signals |
-- |
output_decoder: process (clk, nReset, c_state, iscl_oen, isda_oen, din) |
variable iscl, isda : std_logic; |
begin |
case (c_state) is |
-- idle |
when idle => |
iscl := iscl_oen; -- keep SCL in same state |
isda := isda_oen; -- keep SDA in same state |
|
-- start |
when start_a => |
iscl := iscl_oen; -- keep SCL in same state (for repeated start) |
isda := '1'; -- set SDA high |
|
when start_b => |
iscl := '1'; -- set SCL high |
isda := '1'; -- keep SDA high |
|
when start_c => |
iscl := '1'; -- keep SCL high |
isda := '0'; -- set SDA low |
|
when start_d => |
iscl := '1'; -- keep SCL high |
isda := '0'; -- keep SDA low |
|
when start_e => |
iscl := '0'; -- set SCL low |
isda := '0'; -- keep SDA low |
|
-- stop |
when stop_a => |
iscl := '0'; -- keep SCL disabled |
isda := '0'; -- set SDA low |
|
when stop_b => |
iscl := '1'; -- set SCL high |
isda := '0'; -- keep SDA low |
|
when stop_c => |
iscl := '1'; -- keep SCL high |
isda := '0'; -- keep SDA low |
|
when stop_d => |
iscl := '1'; -- keep SCL high |
isda := '1'; -- set SDA high |
|
-- write |
when wr_a => |
iscl := '0'; -- keep SCL low |
isda := din; -- set SDA |
|
when wr_b => |
iscl := '1'; -- set SCL high |
isda := din; -- keep SDA |
|
when wr_c => |
iscl := '1'; -- keep SCL high |
isda := din; -- keep SDA |
|
when wr_d => |
iscl := '0'; -- set SCL low |
isda := din; -- keep SDA |
|
-- read |
when rd_a => |
iscl := '0'; -- keep SCL low |
isda := '1'; -- tri-state SDA |
|
when rd_b => |
iscl := '1'; -- set SCL high |
isda := '1'; -- tri-state SDA |
|
when rd_c => |
iscl := '1'; -- keep SCL high |
isda := '1'; -- tri-state SDA |
|
when rd_d => |
iscl := '0'; -- set SCL low |
isda := '1'; -- tri-state SDA |
end case; |
|
-- generate registers |
if (nReset = '0') then |
iscl_oen <= '1' after Tcq; |
isda_oen <= '1' after Tcq; |
elsif (clk'event and clk = '1') then |
if (rst = '1') then |
iscl_oen <= '1' after Tcq; |
isda_oen <= '1' after Tcq; |
elsif (clk_en = '1') then |
iscl_oen <= iscl after Tcq; |
isda_oen <= isda after Tcq; |
end if; |
end if; |
end process output_decoder; |
|
-- assign outputs |
scl_o <= '0'; |
scl_oen <= iscl_oen; |
/trunk/rtl/vhdl/i2c_master_top.vhd
37,10 → 37,10
|
-- CVS Log |
-- |
-- $Id: i2c_master_top.vhd,v 1.2 2001-11-10 10:52:44 rherveille Exp $ |
-- $Id: i2c_master_top.vhd,v 1.3 2002-11-30 22:24:37 rherveille Exp $ |
-- |
-- $Date: 2001-11-10 10:52:44 $ |
-- $Revision: 1.2 $ |
-- $Date: 2002-11-30 22:24:37 $ |
-- $Revision: 1.3 $ |
-- $Author: rherveille $ |
-- $Locker: $ |
-- $State: Exp $ |
47,6 → 47,9
-- |
-- Change History: |
-- $Log: not supported by cvs2svn $ |
-- Revision 1.2 2001/11/10 10:52:44 rherveille |
-- Changed PRER reset value from 0x0000 to 0xffff, conform specs. |
-- |
|
|
library ieee; |
55,26 → 58,21
|
entity i2c_master_top is |
generic( |
ARST_LVL : std_logic := '0'; -- asynchronous reset level |
|
-- Register timing parameters. |
-- Last parameters in list for |
-- verilog compatibility |
Tcq : time := 1 ns -- Clock to output delay |
ARST_LVL : std_logic := '0' -- asynchronous reset level |
); |
port ( |
-- wishbone signals |
wb_clk_i : in std_logic; -- master clock input |
wb_rst_i : in std_logic := '0'; -- synchronous active high reset |
arst_i : in std_logic := not ARST_LVL; -- asynchronous reset |
wb_adr_i : in unsigned(2 downto 0); -- lower address bits |
wb_dat_i : in std_logic_vector(7 downto 0); -- Databus input |
wb_dat_o : out std_logic_vector(7 downto 0); -- Databus output |
wb_we_i : in std_logic; -- Write enable input |
wb_stb_i : in std_logic; -- Strobe signals / core select signal |
wb_cyc_i : in std_logic; -- Valid bus cycle input |
wb_ack_o : out std_logic; -- Bus cycle acknowledge output |
wb_inta_o : out std_logic; -- interrupt request output signal |
wb_clk_i : in std_logic; -- master clock input |
wb_rst_i : in std_logic := '0'; -- synchronous active high reset |
arst_i : in std_logic := not ARST_LVL; -- asynchronous reset |
wb_adr_i : in unsigned(2 downto 0); -- lower address bits |
wb_dat_i : in std_logic_vector(7 downto 0); -- Databus input |
wb_dat_o : out std_logic_vector(7 downto 0); -- Databus output |
wb_we_i : in std_logic; -- Write enable input |
wb_stb_i : in std_logic; -- Strobe signals / core select signal |
wb_cyc_i : in std_logic; -- Valid bus cycle input |
wb_ack_o : out std_logic; -- Bus cycle acknowledge output |
wb_inta_o : out std_logic; -- interrupt request output signal |
|
-- i2c lines |
scl_pad_i : in std_logic; -- i2c clock line input |
88,52 → 86,52
|
architecture structural of i2c_master_top is |
component i2c_master_byte_ctrl is |
generic( |
Tcq : time := Tcq |
); |
port ( |
clk : in std_logic; |
rst : in std_logic; -- synchronous active high reset (WISHBONE compatible) |
nReset : in std_logic; -- asynchornous active low reset (FPGA compatible) |
ena : in std_logic; -- core enable signal |
port ( |
clk : in std_logic; |
rst : in std_logic; -- synchronous active high reset (WISHBONE compatible) |
nReset : in std_logic; -- asynchornous active low reset (FPGA compatible) |
ena : in std_logic; -- core enable signal |
|
clk_cnt : in unsigned(15 downto 0); -- 4x SCL |
clk_cnt : in unsigned(15 downto 0); -- 4x SCL |
|
-- input signals |
start, |
stop, |
read, |
write, |
ack_in : std_logic; |
din : in std_logic_vector(7 downto 0); |
-- input signals |
start, |
stop, |
read, |
write, |
ack_in : std_logic; |
din : in std_logic_vector(7 downto 0); |
|
-- output signals |
cmd_ack : out std_logic; |
ack_out : out std_logic; |
i2c_busy : out std_logic; |
dout : out std_logic_vector(7 downto 0); |
-- output signals |
cmd_ack : out std_logic; |
ack_out : out std_logic; |
i2c_busy : out std_logic; |
dout : out std_logic_vector(7 downto 0); |
|
-- i2c lines |
scl_i : in std_logic; -- i2c clock line input |
scl_o : out std_logic; -- i2c clock line output |
scl_oen : out std_logic; -- i2c clock line output enable, active low |
sda_i : in std_logic; -- i2c data line input |
sda_o : out std_logic; -- i2c data line output |
sda_oen : out std_logic -- i2c data line output enable, active low |
); |
-- i2c lines |
scl_i : in std_logic; -- i2c clock line input |
scl_o : out std_logic; -- i2c clock line output |
scl_oen : out std_logic; -- i2c clock line output enable, active low |
sda_i : in std_logic; -- i2c data line input |
sda_o : out std_logic; -- i2c data line output |
sda_oen : out std_logic -- i2c data line output enable, active low |
); |
end component i2c_master_byte_ctrl; |
|
-- registers |
signal prer : unsigned(15 downto 0); -- clock prescale register |
signal ctr : std_logic_vector(7 downto 0); -- control register |
signal txr : std_logic_vector(7 downto 0); -- transmit register |
signal rxr : std_logic_vector(7 downto 0); -- receive register |
signal cr : std_logic_vector(7 downto 0); -- command register |
signal sr : std_logic_vector(7 downto 0); -- status register |
signal prer : unsigned(15 downto 0); -- clock prescale register |
signal ctr : std_logic_vector(7 downto 0); -- control register |
signal txr : std_logic_vector(7 downto 0); -- transmit register |
signal rxr : std_logic_vector(7 downto 0); -- receive register |
signal cr : std_logic_vector(7 downto 0); -- command register |
signal sr : std_logic_vector(7 downto 0); -- status register |
|
-- internal reset signal |
signal rst_i : std_logic; |
|
-- internal acknowledge signal |
signal iack_o : std_logic; |
|
-- done signal: command completed, clear command register |
signal done : std_logic; |
|
145,10 → 143,10
signal ien : std_logic; |
|
-- status register signals |
signal irxack, rxack : std_logic; -- received aknowledge from slave |
signal tip : std_logic; -- transfer in progress |
signal irq_flag : std_logic; -- interrupt pending flag |
signal i2c_busy : std_logic; -- bus busy (start signal detected) |
signal irxack, rxack : std_logic; -- received aknowledge from slave |
signal tip : std_logic; -- transfer in progress |
signal irq_flag : std_logic; -- interrupt pending flag |
signal i2c_busy : std_logic; -- bus busy (start signal detected) |
|
begin |
-- generate internal reset signal |
155,44 → 153,36
rst_i <= arst_i xor ARST_LVL; |
|
-- generate acknowledge output signal |
wb_ack_o <= wb_cyc_i and wb_stb_i; -- because timing is always honored |
|
-- assign wb_dat_o |
assign_dato : process(wb_adr_i, prer, ctr, txr, cr, rxr, sr) |
gen_ack_o : process(wb_clk_i) |
begin |
case wb_adr_i is |
when "000" => |
wb_dat_o <= std_logic_vector(prer( 7 downto 0)); |
if (wb_clk_i'event and wb_clk_i = '1') then |
iack_o <= wb_cyc_i and wb_stb_i and not iack_o; -- because timing is always honored |
end if; |
end process gen_ack_o; |
|
when "001" => |
wb_dat_o <= std_logic_vector(prer(15 downto 8)); |
wb_ack_o <= iack_o; |
|
when "010" => |
wb_dat_o <= ctr; |
|
when "011" => |
wb_dat_o <= rxr; -- write is transmit register TxR |
-- assign wb_dat_o |
assign_dato : process(wb_clk_i) |
begin |
if (wb_clk_i'event and wb_clk_i = '1') then |
case wb_adr_i is |
when "000" => wb_dat_o <= std_logic_vector(prer( 7 downto 0)); |
when "001" => wb_dat_o <= std_logic_vector(prer(15 downto 8)); |
when "010" => wb_dat_o <= ctr; |
when "011" => wb_dat_o <= rxr; -- write is transmit register TxR |
when "100" => wb_dat_o <= sr; -- write is command register CR |
|
when "100" => |
wb_dat_o <= sr; -- write is command register CR |
|
-- Debugging registers: |
-- These registers are not documented. |
-- Functionality could change in future releases |
|
when "101" => |
wb_dat_o <= txr; |
|
when "110" => |
wb_dat_o <= cr; |
|
when "111" => |
wb_dat_o <= (others => '0'); |
|
when others => |
wb_dat_o <= (others => 'X'); -- for simulation only |
|
end case; |
-- Debugging registers: |
-- These registers are not documented. |
-- Functionality could change in future releases |
when "101" => wb_dat_o <= txr; |
when "110" => wb_dat_o <= cr; |
when "111" => wb_dat_o <= (others => '0'); |
when others => wb_dat_o <= (others => 'X'); -- for simulation only |
end case; |
end if; |
end process assign_dato; |
|
|
199,54 → 189,55
-- registers block |
regs_block: process(rst_i, wb_clk_i) |
begin |
if (rst_i = '0') then |
prer <= (others => '1') after Tcq; |
ctr <= (others => '0') after Tcq; |
txr <= (others => '0') after Tcq; |
cr <= (others => '0') after Tcq; |
elsif (wb_clk_i'event and wb_clk_i = '1') then |
if (wb_rst_i = '1') then |
prer <= (others => '1') after Tcq; |
ctr <= (others => '0') after Tcq; |
txr <= (others => '0') after Tcq; |
cr <= (others => '0') after Tcq; |
else |
if (wb_cyc_i = '1' and wb_stb_i = '1' and wb_we_i = '1') then |
if (wb_adr_i(2) = '0') then |
case wb_adr_i(1 downto 0) is |
when "00" => prer( 7 downto 0) <= unsigned(wb_dat_i) after Tcq; |
when "01" => prer(15 downto 8) <= unsigned(wb_dat_i) after Tcq; |
when "10" => ctr <= wb_dat_i after Tcq; |
when "11" => txr <= wb_dat_i after Tcq; |
if (rst_i = '0') then |
prer <= (others => '1'); |
ctr <= (others => '0'); |
txr <= (others => '0'); |
cr <= (others => '0'); |
elsif (wb_clk_i'event and wb_clk_i = '1') then |
if (wb_rst_i = '1') then |
prer <= (others => '1'); |
ctr <= (others => '0'); |
txr <= (others => '0'); |
cr <= (others => '0'); |
else |
if (wb_cyc_i = '1' and wb_stb_i = '1' and wb_we_i = '1') then |
if (wb_adr_i(2) = '0') then |
case wb_adr_i(1 downto 0) is |
when "00" => prer( 7 downto 0) <= unsigned(wb_dat_i); |
when "01" => prer(15 downto 8) <= unsigned(wb_dat_i); |
when "10" => ctr <= wb_dat_i; |
when "11" => txr <= wb_dat_i; |
|
-- illegal cases, for simulation only |
when others => |
report ("Illegal write address, setting all registers to unknown."); |
prer <= (others => 'X'); |
ctr <= (others => 'X'); |
txr <= (others => 'X'); |
end case; |
elsif ( (core_en = '1') and (wb_adr_i(1 downto 0) = 0) ) then |
-- only take new commands when i2c ore enabled |
-- pending commands are finished |
cr <= wb_dat_i after Tcq; |
end if; |
else |
-- clear command bits when done |
if (done = '1') then |
cr(7 downto 4) <= (others => '0') after Tcq; |
end if; |
-- illegal cases, for simulation only |
when others => |
report ("Illegal write address, setting all registers to unknown."); |
prer <= (others => 'X'); |
ctr <= (others => 'X'); |
txr <= (others => 'X'); |
end case; |
elsif ( (core_en = '1') and (wb_adr_i(1 downto 0) = 0) ) then |
-- only take new commands when i2c ore enabled |
-- pending commands are finished |
cr <= wb_dat_i; |
end if; |
else |
-- clear command bits when done |
if (done = '1') then |
cr(7 downto 4) <= (others => '0'); |
end if; |
|
-- reserved bits |
cr(2 downto 1) <= (others => '0') after Tcq; |
-- reserved bits |
cr(2 downto 1) <= (others => '0'); |
|
-- clear iack when irq_flag cleared |
cr(0) <= cr(0) and irq_flag; |
end if; |
end if; |
end if; |
-- clear iack when irq_flag cleared |
cr(0) <= cr(0) and irq_flag; |
end if; |
end if; |
end if; |
end process regs_block; |
|
|
|
-- decode command register |
sta <= cr(7); |
sto <= cr(6); |
264,7 → 255,7
clk => wb_clk_i, |
rst => wb_rst_i, |
nReset => rst_i, |
ena => core_en, |
ena => core_en, |
clk_cnt => prer, |
start => sta, |
stop => sto, |
288,50 → 279,49
-- status register block + interrupt request signal |
st_irq_block : block |
begin |
-- generate status register bits |
gen_sr_bits: process (wb_clk_i, rst_i) |
begin |
if (rst_i = '0') then |
rxack <= '0' after Tcq; |
tip <= '0' after Tcq; |
irq_flag <= '0' after Tcq; |
elsif (wb_clk_i'event and wb_clk_i = '1') then |
if (wb_rst_i = '1') then |
rxack <= '0' after Tcq; |
tip <= '0' after Tcq; |
irq_flag <= '0' after Tcq; |
else |
rxack <= irxack after Tcq; |
tip <= (rd or wr) after Tcq; |
-- generate status register bits |
gen_sr_bits: process (wb_clk_i, rst_i) |
begin |
if (rst_i = '0') then |
rxack <= '0'; |
tip <= '0'; |
irq_flag <= '0'; |
elsif (wb_clk_i'event and wb_clk_i = '1') then |
if (wb_rst_i = '1') then |
rxack <= '0'; |
tip <= '0'; |
irq_flag <= '0'; |
else |
rxack <= irxack; |
tip <= (rd or wr); |
|
-- interrupt request flag is always generated |
irq_flag <= (done or irq_flag) and not iack after Tcq; |
end if; |
end if; |
end process gen_sr_bits; |
-- interrupt request flag is always generated |
irq_flag <= (done or irq_flag) and not iack; |
end if; |
end if; |
end process gen_sr_bits; |
|
-- generate interrupt request signals |
gen_irq: process (wb_clk_i, rst_i) |
begin |
if (rst_i = '0') then |
wb_inta_o <= '0' after Tcq; |
elsif (wb_clk_i'event and wb_clk_i = '1') then |
if (wb_rst_i = '1') then |
wb_inta_o <= '0' after Tcq; |
else |
-- interrupt signal is only generated when IEN (interrupt enable bit) is set |
wb_inta_o <= irq_flag and ien after Tcq; |
end if; |
end if; |
end process gen_irq; |
-- generate interrupt request signals |
gen_irq: process (wb_clk_i, rst_i) |
begin |
if (rst_i = '0') then |
wb_inta_o <= '0'; |
elsif (wb_clk_i'event and wb_clk_i = '1') then |
if (wb_rst_i = '1') then |
wb_inta_o <= '0'; |
else |
-- interrupt signal is only generated when IEN (interrupt enable bit) is set |
wb_inta_o <= irq_flag and ien; |
end if; |
end if; |
end process gen_irq; |
|
-- assign status register bits |
sr(7) <= rxack; |
sr(6) <= i2c_busy; |
sr(5 downto 2) <= (others => '0'); -- reserved |
sr(1) <= tip; |
sr(0) <= irq_flag; |
-- assign status register bits |
sr(7) <= rxack; |
sr(6) <= i2c_busy; |
sr(5 downto 2) <= (others => '0'); -- reserved |
sr(1) <= tip; |
sr(0) <= irq_flag; |
end block; |
|
end architecture structural; |
|