用于tmp007传感器模块的I2C主控制器

时间:2016-03-20 18:32:14

标签: verilog fpga i2c

我正在尝试在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

Two-Wire Timing Diagram for Read Word Format

0 个答案:

没有答案