2015-12-06 2 views
0

Я создаю протокол I2C в verilog для считывания данных с датчика (BMP180), как вы знаете, датчик посылает мне немного признания. Как использовать порт inout i2c_sda для отправки и как я могу получить.inout verilog protocol I2C

В качестве доставки и получения i2c_sda той же строки, если моя переменная объявлена ​​типа inout.

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; 


[email protected](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 


[email protected](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 

ответ

0

Если у вас есть модуль контактный определяется как

inout wire pin 

, то вы можете получить доступ к нему, как так

wire pin_input = pin; 
assign pin = pin_oe ? pin_output : 1'bz; 

этого следует заключить с тремя состояниями буфера.

Тем не менее, я был бы осторожен при выполнении этого, как если бы вы слишком рано вводили тристатный буфер, это может ограничить то, что вы можете сделать с модулем. Например, можно было бы подключить несколько внутренних компонентов I2C вместе, например, разрешить нескольким мастерам внутри доступа FPGA к тем же контактам. Однако, тристатные сигналы не могут быть проложены внутри FPGA, поэтому, если вы реализуете tristate внутри основного модуля I2C, это становится невозможным. Вместо этого вы можете рассмотреть каждый вывод в виде трех модулей: вход, выход и выход enable/tristate. Это позволяет подключать несколько модулей с эмулируемой тристатной шиной и позволяет им делиться одним набором тристатных буферов с фактическим выводом ввода-вывода на микросхеме.

Для хорошего примера того, как это работает, см. Комментарии в https://github.com/alexforencich/verilog-i2c/blob/master/rtl/i2c_master.v.

Смежные вопросы