萌新请教问题,关于Sparten6开发板教程中的问题。
源码贴上来吧。感觉代码少了一部分。而且字体看着好奇怪。
大概意思就是C1在“数据写”的模式下。
每一次时钟上升沿C1+1。
当C1计算到100的时候。SDA就变为低电平。
当C1计算到200的时候。SCL就变为低电平。
当C1计算到249的时候,C1就会变为0,同时i加上1.
至于前面的C1等于0的情况应该是SDA和SCL的复位
module iic_com
(
input CLK,
input RSTn,
input [1:0] Start_Sig, //read or write command
input [7:0] Addr_Sig, //eeprom words address
input [7:0] Wr Data,
output [7:0] Rd Data,
output Done_Sig,
output SCL,
inout SDA
);
parameter F100K = 9'd200;
reg [4:0] i;
reg [4:0] Go;
reg [8:0] C1;
reg [7:0] r Data;
reg r SCL;
reg r SDA;
reg is Ack;
reg is Done;
reg is Out;
assign Done_Sig = is Done;
assign Rd Data = r Data;
assign SCL = r SCL;
assign SDA = is Out ? r SDA : 1'bz;
//****************************************//
//* I2C 读写处理程序 *//
//****************************************//
always @ ( posedge CLK or negedge RSTn )
if( !RSTn ) begin
i <= 5'd0;
Go <= 5'd0;
C1 <= 9'd0;
r Data <= 8'd0;
r SCL <= 1'b1;
r SDA <= 1'b1;
is Ack <= 1'b1;
is Done <= 1'b0;
is Out <= 1'b1;
end
else if( Start_Sig[0] ) //I2C 数据写
case( i )
0: // Start
begin
is Out <= 1; //SDA 端口输出
if( C1 == 0 ) r SCL <= 1'b1;
else if( C1 == 200 ) r SCL <= 1'b0; //SCL 由高变低
if( C1 == 0 ) r SDA <= 1'b1;
else if( C1 == 100 ) r SDA <= 1'b0; //SDA 先由高变低
if( C1 == 250 -1) begin C1 <= 9'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end
1: // Write Device Addr
begin r Data <= {4'b1010, 3'b000, 1'b0}; i <= 5'd7; Go <= i + 1'b1; end
2: // Wirte Word Addr
reg r SDA;
reg is Ack;
reg is Done;
reg is Out;
assign Done_Sig = is Done;
assign Rd Data = r Data;
assign SCL = r SCL;
assign SDA = is Out ? r SDA : 1'bz;
//****************************************//
//* I2C 读写处理程序 *//
//****************************************//
always @ ( posedge CLK or negedge RSTn )
if( !RSTn ) begin
i <= 5'd0;
Go <= 5'd0;
C1 <= 9'd0;
r Data <= 8'd0;
r SCL <= 1'b1;
r SDA <= 1'b1;
is Ack <= 1'b1;
is Done <= 1'b0;
is Out <= 1'b1;
end
else if( Start_Sig[0] ) //I2C 数据写
case( i )
0: // Start
begin
is Out <= 1; //SDA 端口输出
if( C1 == 0 ) r SCL <= 1'b1;
else if( C1 == 200 ) r SCL <= 1'b0; //SCL 由高变低
if( C1 == 0 ) r SDA <= 1'b1;
else if( C1 == 100 ) r SDA <= 1'b0; //SDA 先由高变低
if( C1 == 250 -1) begin C1 <= 9'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end
1: // Write Device Addr
begin r Data <= {4'b1010, 3'b000, 1'b0}; i <= 5'd7; Go <= i + 1'b1; end
2: // Wirte Word Addr
else if( C1 == 150 ) r SCL <= 1'b0;
if( C1 == F100K -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end
16:
if( is Ack != 0 ) i <= 5'd0;
else i <= Go;
endcase
else if( Start_Sig[1] ) //I2C 数据读
case( i )
0: // Start
begin
is Out <= 1; //SDA 端口输出
if( C1 == 0 ) r SCL <= 1'b1;
else if( C1 == 200 ) r SCL <= 1'b0; //SCL 由高变低
if( C1 == 0 ) r SDA <= 1'b1;
else if( C1 == 100 ) r SDA <= 1'b0; //SDA 先由高变低
if( C1 == 250 -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end
1: // Write Device Addr
begin r Data <= {4'b1010, 3'b000, 1'b0}; i <= 5'd9; Go <= i + 1'b1; end
2: // Wirte Word Addr
begin r Data <= Addr_Sig; i <= 5'd9; Go <= i + 1'b1; end
3: // Start again
begin
is Out <= 1'b1;
if( C1 == 0 ) r SCL <= 1'b0;
else if( C1 == 50 ) r SCL <= 1'b1;
else if( C1 == 250 ) r SCL <= 1'b0;
if( C1 == 0 ) r SDA <= 1'b0;
else if( C1 == 50 ) r SDA <= 1'b1;
else if( C1 == 150 ) r SDA <= 1'b0;
if( C1 == 300 -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end
4: // Write Device Addr ( Read )
begin r Data <= {4'b1010, 3'b000, 1'b1}; i <= 5'd9; Go <= i + 1'b1; end
5: // Read Data
begin r Data <= 8'd0; i <= 5'd19; Go <= i + 1'b1; end
6: // Stop
begin
is Out <= 1'b1;
if( C1 == 0 ) r SCL <= 1'b0;
else if( C1 == 50 ) r SCL <= 1'b1;
if( C1 == 0 ) r SDA <= 1'b0;
else if( C1 == 150 ) r SDA <= 1'b1;
if( C1 == 250 -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end
7: //写 I2C 结束
begin is Done <= 1'b1; i <= i + 1'b1; end
8:
begin is Done <= 1'b0; i <= 5'd0; end
9,10,11,12,13,14,15,16: //发送 Device Addr(write)/Word Addr/Device Addr(read)
begin
is Out <= 1'b1;
r SDA <= r Data[16-i];
if( C1 == 0 ) r SCL <= 1'b0;
else if( C1 == 50 ) r SCL <= 1'b1;
else if( C1 == 150 ) r SCL <= 1'b0;
if( C1 == F100K -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end
17: // waiting for acknowledge
begin
is Out <= 1'b0; //SDA 端口改为输入
if( C1 == 100 ) is Ack <= SDA;
if( C1 == 0 ) r SCL <= 1'b0;
else if( C1 == 50 ) r SCL <= 1'b1;
else if( C1 == 150 ) r SCL <= 1'b0;
if( C1 == F100K -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end
18:
if( is Ack != 0 ) i <= 5'd0;
else i <= Go;
19,20,21,22,23,24,25,26: // Read data
begin
is Out <= 1'b0;
if( C1 == 100 ) r Data[26-i] <= SDA;
if( C1 == 0 ) r SCL <= 1'b0;
else if( C1 == 50 ) r SCL <= 1'b1;
else if( C1 == 150 ) r SCL <= 1'b0;
if( C1 == F100K -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end
27: // no acknowledge
begin
is Out <= 1'b1;
if( C1 == 0 ) r SCL <= 1'b0;
else if( C1 == 50 ) r SCL <= 1'b1;
else if( C1 == 150 ) r SCL <= 1'b0;
if( C1 == F100K -1 ) begin C1 <= 9'd0; i <= Go; end
else C1 <= C1 + 1'b1;
end
endcase
endmodule
这是原码,谢谢你回答我的问题,我主要的疑问是为什么这个C1在200的时候变成电平改变,我能理解这是一个启动写的过程,但是我就有时候纠结在具体数字上。
module iic_com
(
input CLK,
input RSTn,
input [1:0] Start_Sig, //read or write command
input [7:0] Addr_Sig, //eeprom words address
input [7:0] Wr Data,
output [7:0] Rd Data,
output Done_Sig,
output SCL,
inout SDA
);
parameter F100K = 9'd200;
reg [4:0] i;
reg [4:0] Go;
reg [8:0] C1;
reg [7:0] r Data;
reg r SCL;
reg r SDA;
reg is Ack;
reg is Done;
reg is Out;
assign Done_Sig = is Done;
assign Rd Data = r Data;
assign SCL = r SCL;
assign SDA = is Out ? r SDA : 1'bz;
//****************************************//
//* I2C 读写处理程序 *//
//****************************************//
always @ ( posedge CLK or negedge RSTn )
if( !RSTn ) begin
i <= 5'd0;
Go <= 5'd0;
C1 <= 9'd0;
r Data <= 8'd0;
r SCL <= 1'b1;
r SDA <= 1'b1;
is Ack <= 1'b1;
is Done <= 1'b0;
is Out <= 1'b1;
end
else if( Start_Sig[0] ) //I2C 数据写
case( i )
0: // Start
begin
is Out <= 1; //SDA 端口输出
if( C1 == 0 ) r SCL <= 1'b1;
else if( C1 == 200 ) r SCL <= 1'b0; //SCL 由高变低
if( C1 == 0 ) r SDA <= 1'b1;
else if( C1 == 100 ) r SDA <= 1'b0; //SDA 先由高变低
if( C1 == 250 -1) begin C1 <= 9'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end
1: // Write Device Addr
begin r Data <= {4'b1010, 3'b000, 1'b0}; i <= 5'd7; Go <= i + 1'b1; end
2: // Wirte Word Addr
reg r SDA;
reg is Ack;
reg is Done;
reg is Out;
assign Done_Sig = is Done;
assign Rd Data = r Data;
assign SCL = r SCL;
assign SDA = is Out ? r SDA : 1'bz;
//****************************************//
//* I2C 读写处理程序 *//
//****************************************//
always @ ( posedge CLK or negedge RSTn )
if( !RSTn ) begin
i <= 5'd0;
Go <= 5'd0;
C1 <= 9'd0;
r Data <= 8'd0;
r SCL <= 1'b1;
r SDA <= 1'b1;
is Ack <= 1'b1;
is Done <= 1'b0;
is Out <= 1'b1;
end
else if( Start_Sig[0] ) //I2C 数据写
case( i )
0: // Start
begin
is Out <= 1; //SDA 端口输出
if( C1 == 0 ) r SCL <= 1'b1;
else if( C1 == 200 ) r SCL <= 1'b0; //SCL 由高变低
if( C1 == 0 ) r SDA <= 1'b1;
else if( C1 == 100 ) r SDA <= 1'b0; //SDA 先由高变低
if( C1 == 250 -1) begin C1 <= 9'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end
1: // Write Device Addr
begin r Data <= {4'b1010, 3'b000, 1'b0}; i <= 5'd7; Go <= i + 1'b1; end
2: // Wirte Word Addr
else if( C1 == 150 ) r SCL <= 1'b0;
if( C1 == F100K -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end
16:
if( is Ack != 0 ) i <= 5'd0;
else i <= Go;
endcase
else if( Start_Sig[1] ) //I2C 数据读
case( i )
0: // Start
begin
is Out <= 1; //SDA 端口输出
if( C1 == 0 ) r SCL <= 1'b1;
else if( C1 == 200 ) r SCL <= 1'b0; //SCL 由高变低
if( C1 == 0 ) r SDA <= 1'b1;
else if( C1 == 100 ) r SDA <= 1'b0; //SDA 先由高变低
if( C1 == 250 -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end
1: // Write Device Addr
begin r Data <= {4'b1010, 3'b000, 1'b0}; i <= 5'd9; Go <= i + 1'b1; end
2: // Wirte Word Addr
begin r Data <= Addr_Sig; i <= 5'd9; Go <= i + 1'b1; end
3: // Start again
begin
is Out <= 1'b1;
if( C1 == 0 ) r SCL <= 1'b0;
else if( C1 == 50 ) r SCL <= 1'b1;
else if( C1 == 250 ) r SCL <= 1'b0;
if( C1 == 0 ) r SDA <= 1'b0;
else if( C1 == 50 ) r SDA <= 1'b1;
else if( C1 == 150 ) r SDA <= 1'b0;
if( C1 == 300 -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end
4: // Write Device Addr ( Read )
begin r Data <= {4'b1010, 3'b000, 1'b1}; i <= 5'd9; Go <= i + 1'b1; end
5: // Read Data
begin r Data <= 8'd0; i <= 5'd19; Go <= i + 1'b1; end
6: // Stop
begin
is Out <= 1'b1;
if( C1 == 0 ) r SCL <= 1'b0;
else if( C1 == 50 ) r SCL <= 1'b1;
if( C1 == 0 ) r SDA <= 1'b0;
else if( C1 == 150 ) r SDA <= 1'b1;
if( C1 == 250 -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end
7: //写 I2C 结束
begin is Done <= 1'b1; i <= i + 1'b1; end
8:
begin is Done <= 1'b0; i <= 5'd0; end
9,10,11,12,13,14,15,16: //发送 Device Addr(write)/Word Addr/Device Addr(read)
begin
is Out <= 1'b1;
r SDA <= r Data[16-i];
if( C1 == 0 ) r SCL <= 1'b0;
else if( C1 == 50 ) r SCL <= 1'b1;
else if( C1 == 150 ) r SCL <= 1'b0;
if( C1 == F100K -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end
17: // waiting for acknowledge
begin
is Out <= 1'b0; //SDA 端口改为输入
if( C1 == 100 ) is Ack <= SDA;
if( C1 == 0 ) r SCL <= 1'b0;
else if( C1 == 50 ) r SCL <= 1'b1;
else if( C1 == 150 ) r SCL <= 1'b0;
if( C1 == F100K -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end
18:
if( is Ack != 0 ) i <= 5'd0;
else i <= Go;
19,20,21,22,23,24,25,26: // Read data
begin
is Out <= 1'b0;
if( C1 == 100 ) r Data[26-i] <= SDA;
if( C1 == 0 ) r SCL <= 1'b0;
else if( C1 == 50 ) r SCL <= 1'b1;
else if( C1 == 150 ) r SCL <= 1'b0;
if( C1 == F100K -1 ) begin C1 <= 9'd0; i <= i + 1'b1; end
else C1 <= C1 + 1'b1;
end
27: // no acknowledge
begin
is Out <= 1'b1;
if( C1 == 0 ) r SCL <= 1'b0;
else if( C1 == 50 ) r SCL <= 1'b1;
else if( C1 == 150 ) r SCL <= 1'b0;
if( C1 == F100K -1 ) begin C1 <= 9'd0; i <= Go; end
else C1 <= C1 + 1'b1;
end
endcase
endmodule
这是原码,谢谢你回答我的问题,我主要的疑问是为什么这个C1在200的时候变成电平改变,我能理解这是一个启动写的过程,但是我就有时候纠结在具体数字上。
这个我也不太懂,看看有没有解答吧