- //傳輸頻率為400k Hz
- module I2C(
- clk,
- rst,
- w_ctrl, //control byte
- w_h_addr, //address high byte
- w_l_addr, //address low byte
- w_data, //write data
- r_ctrl, //control byte
- r_h_addr, //address high byte
- r_l_addr, //address low byte
- r_data, //read data
- scl,
- sda
- );
- input clk,rst;
- input [6:0] w_ctrl;
- input [7:0] w_h_addr;
- input [7:0] w_l_addr;
- input [7:0] w_data;
- input [6:0] r_ctrl;
- input [7:0] r_h_addr;
- input [7:0] r_l_addr;
- output [7:0] r_data;
- output scl;
- inout sda;
- reg [6:0] div_cnt;
- reg [3:0] bps_cnt;
- reg [7:0] reg_d;
- reg [7:0] in_d;
- reg [7:0] r_data;
- reg reg_sda;
- reg div_en;
- reg bps_en;
- reg sda_en;
- reg buf_sda;
- reg scl;
- //=====================================================
- // 狀態機
- //=====================================================
- parameter [4:0] W_START = 5'd0,
- W_CTRL_B = 5'd1,
- W_ACK0 = 5'd2,
- W_ADDR_H_B = 5'd3,
- W_ACK1 = 5'd4,
- W_ADDR_L_B = 5'd5,
- W_ACK2 = 5'd6,
- W_DATA = 5'd7,
- W_ACK3 = 5'd8,
- W_STOP = 5'd9,
- W_IDLE = 5'd10,
- R_START0 = 5'd11,
- R_CTRL_B0 = 5'd12,
- R_ACK0 = 5'd13,
- R_ADDR_H_B = 5'd14,
- R_ACK1 = 5'd15,
- R_ADDR_L_B = 5'd16,
- R_ACK2 = 5'd17,
- R_START1 = 5'd18,
- R_CTRL_B1 = 5'd19,
- R_ACK3 = 5'd20,
- R_DATA = 5'd21,
- R_NO_ACK = 5'd22,
- R_STOP = 5'd23,
- R_IDLE = 5'd24;
- reg [4:0] present_state, next_state;
- always@(posedge clk or negedge rst)
- begin
- if(!rst) present_state <= W_START;
- else present_state <= next_state;
- end
- always@(div_cnt or bps_cnt or present_state)
- begin
- case(present_state)
- W_START : if(div_cnt == 7'd124 && bps_cnt == 4'd0)
- next_state = W_CTRL_B;
- else
- next_state = W_START;
- W_CTRL_B : if(div_cnt == 7'd124 && bps_cnt == 4'd8)
- next_state = W_ACK0;
- else
- next_state = W_CTRL_B;
- W_ACK0 : if(div_cnt == 7'd124 && bps_cnt == 4'd0)
- next_state = W_ADDR_H_B;
- else
- next_state = W_ACK0;
- W_ADDR_H_B : if(div_cnt == 7'd124 && bps_cnt == 4'd8)
- next_state = W_ACK1;
- else
- next_state = W_ADDR_H_B;
- W_ACK1 : if(div_cnt == 7'd124 && bps_cnt == 4'd0)
- next_state = W_ADDR_L_B;
- else
- next_state = W_ACK1;
- W_ADDR_L_B : if(div_cnt == 7'd124 && bps_cnt == 4'd8)
- next_state = W_ACK2;
- else
- next_state = W_ADDR_L_B;
- W_ACK2 : if(div_cnt == 7'd124 && bps_cnt == 4'd0)
- next_state = W_DATA;
- else
- next_state = W_ACK2;
- W_DATA : if(div_cnt == 7'd124 && bps_cnt == 4'd8)
- next_state = W_ACK3;
- else
- next_state = W_DATA;
- W_ACK3 : if(div_cnt == 7'd124 && bps_cnt == 4'd0)
- next_state = W_STOP;
- else
- next_state = W_ACK3;
- W_STOP : if(div_cnt == 7'd124 && bps_cnt == 4'd1)
- next_state = W_IDLE;
- else
- next_state = W_STOP;
- W_IDLE : if(div_cnt == 7'd124 && bps_cnt == 4'd8)
- next_state = R_START0;
- else
- next_state = W_IDLE;
- R_START0 : if(div_cnt == 7'd124 && bps_cnt == 4'd0)
- next_state = R_CTRL_B0;
- else
- next_state = R_START0;
- R_CTRL_B0 : if(div_cnt == 7'd124 && bps_cnt == 4'd8)