首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >入站verilog协议I2C

入站verilog协议I2C
EN

Stack Overflow用户
提问于 2015-12-07 03:23:48
回答 1查看 2.8K关注 0票数 1

我正在用verilog创建I2C协议,以便从传感器(BMP180)读取数据,正如您所知道的,传感器会向我发送一些确认识别。如何使用inout i2c_sda端口发送和接收。

如果我的变量声明为inout类型,则发送和接收i2c_sda为同一行。

代码语言:javascript
复制
module stepPrueba( 
    input wire      clk1,
    input wire  reset,
     input wire     start,
    inout           i2c_sda,
    inout           i2c_scl,
     output wire    ready,
     output reg led1,
     output reg led2
    );



    reg i2c_scl_out;
    assign i2c_scl1= (i2c_scl_out == 1'b0) ? 1'b0 : 1'bz;
     wire i2c_scl_in = i2c_scl;

     assign i2c_scl = (i2c_scl_enable == 0) ? i2c_scl1 : clk1;  
    reg clk;


     assign clk1 = (clk == 1)? 1'bz:1'b0;

    reg i2c_sda_out;
    assign i2c_sda = (i2c_sda_out == 1'b0) ? 1'b0 : 1'bz;
    wire i2c_sda_in = i2c_sda ;




     reg    [6:0] addr;
     reg    [7:0] data;
     reg enable; //(read=1, write=0)
    reg datas;
     reg enable2; //(read=1, write = 0)
     reg [7:0] state;
     reg [7:0] count;
     reg i2c_scl_enable = 0;
     reg [6:0] saved_addr;
     reg [7:0] saved_data;





//goal es escribir al dispositivo direccion 0X55, 0Xaa
    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_STOP = 7;  


always@(posedge clk) 
    begin
      //enable2 <= 0; //i2c_scl==zetas & c_lectura=z;
      if(reset == 1) 
         begin
           i2c_scl_out<=1; 
           i2c_scl_enable <= 0; 
         end
        else 
          begin
             if((state == STATE_IDLE) || (state == STATE_START) ) 
              begin
                //i2c_scl_enable <= 0; //dats == 1 --> ztas == z
                 i2c_scl_out<=1; 
               i2c_scl_enable <= 0; 
              end
            else 
              begin
                i2c_scl_enable <= 1; // dats==clk;
                 clk<=clk1;
             end
         end 
    end


always@(posedge clk) 
    begin
       if(reset == 1) 
          begin
            led1 <=0;
            led2 <=0;
            state <=0;
             i2c_sda_out <= 1;// i2c_sda ==z;
            addr <= 7'b1110111; // direccion del sensor
            count <= 8'd0;
            data <= 8'b11110100; //direccion interna PRESION
         end
       else //reset ==0
          begin

            case (state)

             STATE_IDLE: 
                begin //idle
                   //datas <= 1;  //zetas==z
                    i2c_scl_out<=1; 
                 i2c_scl_enable <= 0; 

                    i2c_sda_out <= 1;
                   if(start) 
                     begin
                        state <= STATE_START;
                        saved_addr <= addr;
                        saved_data <= data;



                 // reg i2c_scl_out;
              // assign i2c_scl1= (i2c_scl_out == 1'b0) ? 1'b0 : 1'bz;
               // wire i2c_scl_in = i2c_scl;
               // assign i2c_scl = (i2c_scl_enable == 0) ? i2c_scl1 : ~clk;  


                     end
                   else 
                     begin
                       state <= STATE_IDLE;
                     end
                end

            STATE_START: 
               begin // start
                  //enable <= 0; // lectura==z; --> i2c_sda==zetas
                  i2c_sda_out <= 0;
                  //datas <= 0; // zetas==0 
                  state<= STATE_ADDR;
                  count <= 6;               
               end

            STATE_ADDR: 
               begin //msb addres bit
                  //enable <= 0; // lectura==z; --> i2c_sda==zetas
                  i2c_sda_out <= saved_addr[count]; // datas ==0 --> zetas==0 || datas==1 --> zetas==z
                  if (count == 0) 
                    begin
                       state <= STATE_RW;
                     end
                  else 
                    begin
                       count <= count - 1;
                     end
               end

            STATE_RW: 
               begin
                  //enable <= 0; //enable==0 --> i2c_sda==zetas
                  i2c_sda_out <= 0;//datas <= 0;
                  state <= STATE_WACK;
               end

            STATE_WACK: 
               begin
                  //enable <= 1; //enable==1 lee  i2c_sda==z & lectura==i2c_sda

                   //enable <= 0; 
                   //if(APA)
                  if(i2c_sda_in==1)
                    begin
                       state <= STATE_IDLE;
                    end 
                  else 
                    begin
                   state <= STATE_DATA;
                       led1 <= 1;
                   end
                  count <= 7;
               end

            STATE_DATA: 
               begin
                  //enable <= 0;
                  i2c_sda_out <= saved_data[count];
                  if(count ==0) 
                    begin
                      state <= STATE_WACK2;
                    end
                  else 
                    begin 
                      count <= count - 1;
                end                  
               end

            STATE_WACK2: 
               begin
                  //enable <= 1;
                  if(i2c_sda_in ==1)
                    begin
                       state <= STATE_IDLE;
                     end 
                  else 
                    begin
                       state <= STATE_STOP;
                       led2 <= 1;
                     end
               end

            STATE_STOP: 
               begin
                  //enable <= 0;
                  i2c_sda_out <= 0;
                  state <= STATE_IDLE;
               end
       endcase
   end
end
endmodule
EN

回答 1

Stack Overflow用户

发布于 2015-12-07 04:20:16

如果你有一个模块引脚定义为

代码语言:javascript
复制
inout wire pin

然后,您可以像这样访问它

代码语言:javascript
复制
wire pin_input = pin;
assign pin = pin_oe ? pin_output : 1'bz;

这应该推断出一个三态缓冲区。

但是,在这样做时我会很小心,因为如果你过早地推断出一个三态缓冲区,它可能会限制你对模块所能做的事情。例如,可以将多个内部I2C组件连接在一起,例如允许FPGA内部的多个主设备访问相同的引脚。但是,三态信号不能在FPGA内部路由,因此如果您在I2C主模块中实现三态,这就变得不可能了。相反,您可以考虑将每个管脚实现为三个模块管脚:输入、输出和输出使能/三态。这允许多个模块通过仿真三态总线连接,并允许它们共享芯片上实际I/O引脚的一组三态缓冲器。

有关其工作原理的一个很好的示例,请参阅https://github.com/alexforencich/verilog-i2c/blob/master/rtl/i2c_master.v中的注释。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34121625

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档