diff --git a/doc/~$$配置0x00波形图.~vsdx b/doc/~$$配置0x00波形图.~vsdx deleted file mode 100644 index c771ab5..0000000 Binary files a/doc/~$$配置0x00波形图.~vsdx and /dev/null differ diff --git a/doc/唤醒状态机.vsdx b/doc/唤醒状态机.vsdx index 4ad4893..391d9db 100644 Binary files a/doc/唤醒状态机.vsdx and b/doc/唤醒状态机.vsdx differ diff --git a/doc/读取0x00波形图.vsdx b/doc/读取0x00波形图.vsdx new file mode 100644 index 0000000..f814eb3 Binary files /dev/null and b/doc/读取0x00波形图.vsdx differ diff --git a/doc/读取0x00状态机.vsdx b/doc/读取0x00状态机.vsdx new file mode 100644 index 0000000..b0744b2 Binary files /dev/null and b/doc/读取0x00状态机.vsdx differ diff --git a/doc/配置0x00状态机.vsdx b/doc/配置0x00状态机.vsdx index 653879b..3779d14 100644 Binary files a/doc/配置0x00状态机.vsdx and b/doc/配置0x00状态机.vsdx differ diff --git a/rtl/i2c_ctrl.v b/rtl/i2c_ctrl.v index 976f5c1..6db3e55 100644 --- a/rtl/i2c_ctrl.v +++ b/rtl/i2c_ctrl.v @@ -19,7 +19,8 @@ parameter IDLE = 4'd0, DEVICE_ADDR = 4'd6, DATA = 4'd7, WAIT = 4'd8, - STOP = 4'd9; + NACK = 4'd9, + STOP = 4'd10; reg [3: 0] state_c; reg [3: 0] state_n; //// @@ -34,6 +35,7 @@ reg [9: 0] cnt_wait ;//1000us reg skip_en_1 ;//步骤1跳转信号 reg skip_en_2 ;//步骤2跳转信号 reg skip_en_3 ;//步骤3跳转信号 +reg skip_en_4 ;//步骤4跳转信号 reg [2: 0] step ;//步骤 reg [1: 0] cnt_i2c_clk ;//i2c计数器 reg [2: 0] cnt_bit ;//bit计数器 @@ -45,9 +47,11 @@ reg i2c_scl ; reg [7: 0] slave_addr ; reg [7: 0] device_addr ; reg [7: 0] wr_data ; +reg [7: 0] recv_data ;//接受0x20寄存器 reg ack ;//接受信号 +reg err_en ;//接受到0x20有误 //三态门 -assign sda_en = ((state_c == ACK_1) || (state_c == ACK_2) || (state_c == ACK_3)) ? 1'b0: 1'b1;//发送主机控制从机,接受主机释放 +assign sda_en = ((state_c == ACK_1) || (state_c == ACK_2) || (state_c == ACK_3) || (state_c == DATA && step == 3'd3)) ? 1'b0: 1'b1;//发送主机控制从机,接受主机释放 assign sda_in = sda; assign sda = (sda_en == 1'b1)? i2c_sda : 1'bz; //i2c驱动时钟设计 @@ -87,13 +91,13 @@ end //状态机第二段 always @(*)begin case(state_c) - IDLE: if((skip_en_1 == 1'b1) || (skip_en_2 == 1'b1) || (skip_en_3 == 1'b1))begin + IDLE: if((skip_en_1 == 1'b1) || (skip_en_2 == 1'b1) || (skip_en_3 == 1'b1) || (skip_en_4 == 1'b1))begin state_n = START; end else begin state_n = IDLE; end - START: if((skip_en_1 == 1'b1) || (skip_en_2 == 1'b1) || (skip_en_3 == 1'b1))begin + START: if((skip_en_1 == 1'b1) || (skip_en_2 == 1'b1) || (skip_en_3 == 1'b1) || (skip_en_4 == 1'b1))begin state_n = SLAVE_ADDR; end else begin @@ -102,7 +106,7 @@ always @(*)begin SLAVE_ADDR: if(skip_en_1 == 1'b1)begin state_n = WAIT; end - else if((skip_en_2 == 1'b1) || (skip_en_3 == 1'b1))begin + else if((skip_en_2 == 1'b1) || (skip_en_3 == 1'b1) || (skip_en_4 == 1'b1))begin state_n = ACK_1; end else begin @@ -111,6 +115,9 @@ always @(*)begin ACK_1: if((skip_en_2 == 1'b1) || (skip_en_3 == 1'b1))begin state_n = DEVICE_ADDR; end + else if(skip_en_4 == 1'b1)begin + state_n = DATA; + end else begin state_n = ACK_1; end @@ -132,9 +139,21 @@ always @(*)begin DATA: if(skip_en_2 == 1'b1)begin state_n = ACK_3; end + else if(skip_en_4 == 1'b1)begin + state_n = NACK; + end + else if(err_en == 1'b1)begin + state_n = IDLE; + end else begin state_n = DATA; end + NACK: if(skip_en_4 == 1'b1)begin + state_n = STOP; + end + else begin + state_n = NACK; + end ACK_3: if(skip_en_2 == 1'b1)begin state_n = STOP; end @@ -147,7 +166,7 @@ always @(*)begin else begin state_n = WAIT; end - STOP: if((skip_en_1 == 1'b1) || (skip_en_2 == 1'b1) || (skip_en_3 == 1'b1))begin + STOP: if((skip_en_1 == 1'b1) || (skip_en_2 == 1'b1) || (skip_en_3 == 1'b1) || (skip_en_4 == 1'b1))begin state_n = IDLE; end else begin @@ -165,7 +184,9 @@ always @(posedge i2c_clk or negedge sys_rst_n)begin skip_en_1 <= 1'b0;//步骤1跳转信号 skip_en_2 <= 1'b0;//步骤2跳转信号 skip_en_3 <= 1'b0;//步骤3跳转信号 + skip_en_4 <= 1'b0;//步骤4跳转信号 step <= 3'd0; + err_en <= 1'b0; cnt_i2c_clk <= 2'd0; cnt_bit <= 3'd0; i2c_end <= 1'b0; @@ -197,6 +218,12 @@ always @(posedge i2c_clk or negedge sys_rst_n)begin else begin skip_en_3 <= 1'b0; end + if((cnt_wait == MAX - 2'd2) && (step == 3'd3))begin + skip_en_4 <= 1'b1; + end + else begin + skip_en_4 <= 1'b0; + end end START: begin cnt_i2c_clk <= cnt_i2c_clk + 1'd1; @@ -218,6 +245,12 @@ always @(posedge i2c_clk or negedge sys_rst_n)begin else begin skip_en_3 <= 1'b0; end + if((cnt_i2c_clk == 2'd2) && (step == 3'd3))begin + skip_en_4 <= 1'b1; + end + else begin + skip_en_4 <= 1'b0; + end end SLAVE_ADDR: begin cnt_i2c_clk <= cnt_i2c_clk + 1'd1; @@ -239,6 +272,12 @@ always @(posedge i2c_clk or negedge sys_rst_n)begin else begin skip_en_3 <= 1'b0; end + if((cnt_i2c_clk == 2'd2) && (step == 3'd3) && (cnt_bit == 3'd7))begin + skip_en_4 <= 1'b1; + end + else begin + skip_en_4 <= 1'b0; + end if((cnt_bit == 3'd7) && (cnt_i2c_clk == 2'd3))begin cnt_bit <= 3'd0; end @@ -263,6 +302,12 @@ always @(posedge i2c_clk or negedge sys_rst_n)begin else begin skip_en_3 <= 1'b0; end + if((ack == 1'b1) && (cnt_i2c_clk == 2'd2) && (step == 3'd3))begin + skip_en_4 <= 1'b1; + end + else begin + skip_en_4 <= 1'b0; + end end DEVICE_ADDR:begin cnt_i2c_clk <= cnt_i2c_clk + 1'b1; @@ -320,6 +365,33 @@ always @(posedge i2c_clk or negedge sys_rst_n)begin else begin skip_en_2 <= 1'b0; end + if((cnt_i2c_clk == 2'd2) && (cnt_bit == 3'd7) && (step == 3'd3) && (recv_data == 8'h20))begin + skip_en_4 <= 1'b1; + end + else begin + skip_en_4 <= 1'b0; + end + if((cnt_i2c_clk == 2'd2) && (cnt_bit == 3'd7) && (step == 3'd3) && (recv_data != 8'h20))begin + begin + err_en <= 1'b1; + step <= 3'd0; + end + end + else begin + begin + err_en <= 1'b0; + step <= step; + end + end + end + NACK: begin + cnt_i2c_clk <= cnt_i2c_clk + 1; + if((ack == 1'b1) && (cnt_i2c_clk == 2'd2) && (step == 3'd3))begin + skip_en_4 <= 1'b1; + end + else begin + skip_en_4 <= 1'b0; + end end ACK_3: begin cnt_i2c_clk <= cnt_i2c_clk + 1; @@ -364,6 +436,12 @@ always @(posedge i2c_clk or negedge sys_rst_n)begin else begin skip_en_3 <= 1'b0; end + if((cnt_i2c_clk == 2'd2) && (step == 3'd3))begin + skip_en_4 <= 1'b1; + end + else begin + skip_en_4 <= 1'b0; + end if(cnt_i2c_clk == 2'd2)begin i2c_end <= 1'b1; end @@ -382,6 +460,8 @@ always @(posedge i2c_clk or negedge sys_rst_n)begin skip_en_1 <= 1'b0; skip_en_2 <= 1'b0; skip_en_3 <= 1'b0; + skip_en_4 <= 1'b0; + err_en <= 1'b0; step <= step; cnt_i2c_clk <= 2'd0; cnt_bit <= 3'd0; @@ -390,10 +470,30 @@ always @(posedge i2c_clk or negedge sys_rst_n)begin endcase end end +//recv_data +always @(posedge i2c_clk or negedge sys_rst_n)begin + if(!sys_rst_n)begin + recv_data <= 8'h0; + end + else begin + case(state_c) + DATA: begin + if((cnt_i2c_clk == 2'd1) && (step == 3'd3))begin + recv_data <= {recv_data[6:0], sda_in}; + end + else begin + recv_data <= recv_data; + end + end + default: recv_data <= recv_data; + endcase + end +end //ack always @(*)begin case(state_c) ACK_1, ACK_2, ACK_3: ack = ~sda_in; + NACK: ack = i2c_sda;//主机发送NACK default: ack = 1'b0; endcase end @@ -412,7 +512,12 @@ always @(*)begin end 3'd2: begin slave_addr = {SLAVE_ID, 1'b0}; - device_addr= {8'hef}; + device_addr= {8'h00}; + wr_data = {8'h00}; + end + 3'd3: begin + slave_addr = {SLAVE_ID, 1'b1};//读取 + device_addr= {8'h00}; wr_data = {8'h00}; end default:begin @@ -427,7 +532,7 @@ always @(*)begin case(state_c) IDLE: i2c_scl = 1'b1; START: i2c_scl = (cnt_i2c_clk <= 2'd2) ? 1'b1 : 1'b0; - SLAVE_ADDR, DEVICE_ADDR, DATA, ACK_1, ACK_2, ACK_3: + SLAVE_ADDR, DEVICE_ADDR, DATA, ACK_1, ACK_2, ACK_3, NACK: i2c_scl = ((cnt_i2c_clk == 2'd1) || (cnt_i2c_clk == 2'd2)) ? 1'b1 : 1'b0; WAIT: i2c_scl = 1'b0; STOP: i2c_scl = (cnt_i2c_clk >= 2'd1) ? 1'b1 : 1'b0; @@ -440,10 +545,16 @@ always @(*)begin START: i2c_sda = (cnt_i2c_clk > 2'd1) ? 1'b0 : 1'b1; SLAVE_ADDR: i2c_sda = slave_addr[7 - cnt_bit]; DEVICE_ADDR:i2c_sda = device_addr[7 - cnt_bit]; - DATA: i2c_sda = wr_data[7 - cnt_bit]; + DATA: if(step == 3'd3)begin + i2c_sda = sda_in; + end + else begin + i2c_sda = wr_data[7 - cnt_bit]; + end ACK_1, ACK_2, ACK_3: i2c_sda = 1'b0; WAIT: i2c_sda = 1'b0; + NACK: i2c_sda = 1'b1;//主机给从机发1 STOP: i2c_sda = (cnt_i2c_clk >= 2'd2) ? 1'b1 : 1'b0; default: i2c_sda = 1'b1; endcase