我正在尝试在verilog中创建I2C协议以从传感器(TMP007)读取数据,然后显示使用led接收的数据,但无济于事。我一直试图将LED(例如LED_GREEN [2] = 1;)置于状态以测试状态的流动。只有LED_GREEN 1和LED_GREEN [0]才会变亮。所以我猜这个问题确实发生在STATE_WACK2中。有人可以帮忙吗?
module tmpi2c(
input wire clk,
input wire reset,
inout reg i2c_sda,
output wire i2c_scl,
output reg [17:0] LED_RED, // LED Red[17:0]
output reg [7:0] LED_GREEN
);
// write to device address 0x40, 0x01h
localparam STATE_IDLE = 0;
localparam STATE_START = 1;
localparam STATE_ADDR = 2;
localparam STATE_RW = 3;
localparam STATE_WACK = 4;
localparam STATE_DATA = 5;
localparam STATE_WACK2 = 6;
localparam STATE_ADDR2 = 7;
localparam STATE_RW2 = 8;
localparam STATE_WACK3 = 9;
localparam STATE_READ = 10;
localparam STATE_WACK4 = 11;
localparam STATE_READ2 = 12;
localparam STATE_WACK5 = 13;
localparam STATE_STOP = 14;
localparam STATE_DISPLAY = 15;
reg enable; //(r=1, w=0)
reg clki2c = 0;
reg [9:0]counter = 0; // 10-bit counter size
reg [9:0] timer = 0;
reg [7:0] state;
reg [6:0] addr;
reg [7:0] data;
reg [7:0] count;
reg [15:0] value =0;
reg [4:0] ge,shi,bai;
reg i2c_scl_enable =0;
assign i2c_scl = (i2c_scl_enable == 0) ? 1 : ~clki2c;
reg i2c_sda_en;
wire i2c_sda_in = i2c_sda ;
// counter size calculation according to input and output frequencies
parameter sys_clk = 50000000; // 50 MHz system clock
//parameter clk_out = 400000; // 0.4 MHz clock output
parameter clk_out = 200000; // 0.2 MHz clock output
//parameter clk_out = 1; // 1Hz clock output
parameter max = sys_clk / (2*clk_out); // max-counter size
//clock divider from 50Mhz to 0.4Mhz
always@(posedge clk or posedge reset)
begin
if(reset) begin
counter <=0;
clki2c <= 0;
end
else begin
if (counter < max) begin
counter <= counter + 1'd1;
end
else begin
counter <= 0;
clki2c <= ~clki2c;
end
end
end
//end clock divider
always@(posedge clki2c) begin
if (!i2c_sda_en) begin i2c_sda = i2c_sda ;
end else begin
i2c_sda = 1'bz;
end
if (reset == 1)
begin
state <= 0;
//i2c_sda <= 1;
//i2c_scl <= 1;
i2c_sda_en <= 1;// i2c_sda ==z;
addr <= 7'h40;
count <= 8'd0;
data <= 8'h01;
LED_RED[17:0] = 0;
LED_GREEN[7:0] = 0;
end
else begin
case(state)
STATE_IDLE: begin //idle
state <= STATE_START;
end
STATE_START: begin //start
i2c_sda_en <= 0;
state <=STATE_ADDR;
count <= 6;
end
STATE_ADDR: begin //msb address bit
LED_GREEN[0] =1;
i2c_sda <= addr[count];
if (count ==0) state <= STATE_RW;
else count <= count -1;
end
STATE_RW: begin
i2c_sda <=0; //write here
state <=STATE_WACK;
end
STATE_WACK: begin
i2c_sda_en <= 1;
if(i2c_sda_in==1)
begin
state <= STATE_WACK;
end
else
begin
state <= STATE_DATA;
end
count <= 7 ;
i2c_sda_en <= 0;
end
STATE_DATA: begin
LED_GREEN[1] =1;
i2c_sda <= data[count];
if (count == 0) state <= STATE_WACK2;
else count <= count -1;
end
STATE_WACK2: begin
i2c_sda_en <= 1;
if(i2c_sda_in==1)
begin
state <= STATE_WACK2;
end
else
begin
state <= STATE_ADDR2;
//LED_GREEN[1] =1;
end
count <= 6;
i2c_sda_en <= 0;
end
STATE_ADDR2: begin
LED_GREEN[2] =1;
i2c_sda <= addr[count];
if (count ==0) state <= STATE_RW2;
else count <= count -1;
end
STATE_RW2: begin
i2c_sda <=1; //read here
state <=STATE_WACK3;
end
STATE_WACK3: begin
i2c_sda_en <= 1;
if(i2c_sda_in==1)
begin
state <= STATE_WACK2;
end
else
begin
state <= STATE_READ;
end
count <= 15;
//i2c_sda_en <= 0;
end
STATE_READ: begin
LED_GREEN[3] =1;
value[count] <= i2c_sda_in;
if (count == 8) state<= STATE_WACK4;
else count <= count -1;
end
STATE_WACK4: begin
i2c_sda_en <= 0;
i2c_sda <=1; //Master should leave SDA high to terminate a single-byte read operation.
state <= STATE_READ2;
count <= 7;
i2c_sda_en <= 1;
end
STATE_READ2: begin
LED_GREEN[4] =1;
value[count] <= i2c_sda_in;
if (count == 0) state<= STATE_WACK5;
else count <= count -1;
end
STATE_WACK5: begin
i2c_sda_en <= 0;
i2c_sda <=1; //Master should leave SDA high to terminate a two-byte read operation.
state <= STATE_STOP;
end
STATE_STOP: begin
//i2c_sda <=1;
state <= STATE_DISPLAY;
end
STATE_DISPLAY: begin
LED_RED[17] = value[15];
LED_RED[16] = value[14];
LED_RED[15] = value[13];
LED_RED[14] = value[12];
LED_RED[13] = value[11];
LED_RED[12] = value[10];
LED_RED[11] = value[9];
LED_RED[10] = value[8];
LED_RED[9] = value[7];
LED_RED[8] = value[6];
LED_RED[7] = value[5];
LED_RED[6] = value[4];
LED_RED[5] = value[3];
LED_RED[4] = value[2];
LED_RED[2] = value[0];
LED_RED[3] = value[1];
//display delay
if (timer < 100000) timer <= timer+1;
else timer <= 0;
state <= STATE_IDLE;
end
endcase
end
end
endmodule