银杏科技有限公司旗下技术文档发布平台 | |||
技术支持电话 | 0379-69926675-801 | ||
技术支持邮件 | Gingko@vip.163.com | ||
版本 | 日期 | 作者 | 修改内容 |
---|---|---|---|
V1.0 | 2020-03-14 | gingko | 初次建立 |
1、正常情况下,数据的变化都发生在SCL的低电平,只有起始标志时,SDA的变化发生在SCL的高电平。根据这个特点,提取每次命令交互的开始标志,其代码如下:
always@(negedge i2c_sda or negedge rst_n or posedge cmd_over) begin if(!rst_n) begin rx_start_r <= 1'd0; end else if(cmd_over) begin rx_start_r <= 1'd0; end else if(i2c_scl) begin rx_start_r <= 1'd1; end end
2、在每个SDL的上升沿锁存数据并将数据拼接成完整的字节,其代码如下:
always@(posedge i2c_scl or negedge rst_n or posedge rx_start) begin if((!rst_n)||(rx_start)) begin receive_byte_r <= 8'd0; rx_state <= 8'd0; rx_over <= 1'd0; data_over <= 1'd0; end else begin case(rx_state) 8'd0:begin rx_state <= rx_state + 1'd1; receive_byte_r[7] <= i2c_sda; end 8'd1:begin rx_state <= rx_state + 1'd1; receive_byte_r[6] <= i2c_sda; end 8'd2:begin rx_state <= rx_state + 1'd1; receive_byte_r[5] <= i2c_sda; end 8'd3:begin rx_over <= 1'd0; rx_state <= rx_state + 1'd1; receive_byte_r[4] <= i2c_sda; end 8'd4:begin rx_state <= rx_state + 1'd1; receive_byte_r[3] <= i2c_sda; end 8'd5:begin rx_state <= rx_state + 1'd1; receive_byte_r[2] <= i2c_sda; end 8'd6:begin rx_state <= rx_state + 1'd1; receive_byte_r[1] <= i2c_sda; end 8'd7:begin rx_state <= rx_state + 1'd1; receive_byte_r[0] <= i2c_sda; // rx_over <= 1'd1; data_over <= 1'd1; end 8'd8:begin rx_state <= 8'd0; rx_over <= 1'd1; data_over <= 1'd0; end default:begin end endcase end end
3、在给个数据拼接完成后,对该数据进行二级存储,并根据接收的自己数目产生RAM的读写时钟信号和命令完成标志,其代码下:
always@(posedge rx_over or negedge rst_n or posedge rx_start) begin if(!rst_n) begin ack_state <= 4'd0; address_r <= 8'd0; rx_data <= 8'd0; wr_clk_r <= 1'd0; rd_clk_r <= 1'd0; cmd_over_r <= 1'd1; end else if(rx_start) begin ack_state <= 4'd0; wr_clk_r <= 1'd0; cmd_over_r <= 1'd0; end else begin case(ack_state) 4'd0:begin if(receive_byte_r==8'ha0) begin ack_state <= ack_state + 1'd1; end else if(receive_byte_r==8'ha1) begin rd_clk_r <= 1'd1; ack_state <= 4'd3; end else begin ack_state <= ack_state; end end 4'd1:begin//锁存地址信息 address_r <= receive_byte_r; ack_state <= ack_state + 1'd1; cmd_over_r <= 1'd1; end 4'd2:begin//接收写入RAM的数据 rx_data <= receive_byte_r; wr_clk_r <= 1'd1; end 4'd3:begin rd_clk_r <= 1'd0; cmd_over_r <= 1'd1; end default:begin end endcase end end
4、在每个读命令到来时发送,读取的数据,其代码如下:
always@(negedge i2c_scl or negedge rst_n or posedge rx_start) begin if((!rst_n)||(rx_start)) begin sda_r <= 1'hz; send_state <= 8'd0; end else begin case(send_state) 8'd0:begin if(data_over) begin if(receive_byte_r==8'ha0) begin sda_r <= 1'd0; send_state <= send_state + 1'd1; end else if(receive_byte_r==8'ha1) begin sda_r <= 1'd0; send_state <= 8'd3; end else begin sda_r <= 1'hz; end end else begin send_state <= send_state; end end 8'd1:begin if(data_over) begin sda_r <= 1'd0; send_state <= send_state + 1'd1; end else begin sda_r <= 1'hz; end end 8'd2:begin if(data_over) begin sda_r <= 1'd0; end else begin sda_r <= 1'hz; end end 8'd3:begin {sda_r,send_data[7:1]} <= data_out; send_state <= send_state + 1'd1; end 8'd4,8'd5,8'd6,8'd7,8'd8,8'd9,8'd10,:begin {sda_r,send_data[7:1]} <= send_data; send_state <= send_state + 1'd1; end 8'd11:begin sda_r <= 1'hz; end default:begin end endcase end end
1.通过Signaltap观察I2C通信时序是否和参考时序一致。