Перейти к содержанию
    

1 минуту назад, vladec сказал:

В честном I2C сделать "короткое замыкание" нельзя принципиально, поскольку ноль там активный, а единица слабая через подтяжку, тип выходов "открытый коллектор или сток".

Ну а если у нас одновременно одно устройство выдает лог.1 а другое устройство придавливает линию к нулю ? Такая ситуация вполне возможна... Например ошибка в прошивке FPGA. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 минуту назад, Flip-fl0p сказал:

Ну а если у нас одновременно одно устройство выдает лог.1 а другое устройство придавливает линию к нулю ? Такая ситуация вполне возможна... Например ошибка в прошивке FPGA.

Тогда на шине будет обычный стандартный ноль. В "правильной" I2C устройства выдают на шину только нули, а единица формируется исключительно резистивной подтяжкой шины к плюсу питания.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 минуту назад, vladec сказал:

Тогда на шине будет обычный стандартный ноль. В "правильной" I2C устройства выдают на шину только нули, а единица формируется исключительно резистивной подтяжкой шины к плюсу питания.

Именно так. В "правильной" i2c шине все происходит именно так. Но у создателя темы i2c контроллер скачан на просторах интернета. Контроллер не проверен. Я лишь предупреждаю ТС, что если контроллер содержит ошибку - то крайне рискованно запускать тестирование в железе. Тем более в том коде сходу в глаза бросаются некоторые ошибки....

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

3 минуты назад, Flip-fl0p сказал:

Именно так. В "правильной" i2c шине все происходит именно так. Но у создателя темы i2c контроллер скачан на просторах интернета. Контроллер не проверен. Я лишь предупреждаю ТС, что если контроллер содержит ошибку - то крайне рискованно запускать тестирование в железе. Тем более в том коде сходу в глаза бросаются некоторые ошибки.... 

 

Ну это если у него неправильно заданы типы выходов шины на ПЛИС, как push-pull. По другому закоротить никак не получится, вот "завесить" или сбить, это элементарно.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот на intel взял исходник:

/************************************************************************************************************
I2C to GPIO Port expander. Date: December 21, 2006.
************************************************************************************************************/
`timescale 1us/10ns

/* Top module */

module I2C_to_GPIO ( sda, sclk, GPIO_input, GPIO_output);

inout sda;                        // Bidirectional SDA
input sclk;                       // Bidirectional SCLK
input [7:0] GPIO_input;
output [7:0] GPIO_output;                                         
parameter slave_address = 7'h0;   // can be changed as per the protocol это для адреса slave?
parameter n = 8;

reg start_stop;        // Indicated if the device has detected a start and is busy in some operation
reg start, stop;       // Goes high temperarily when a start or stop is detectd
reg some_other_device; // to reset start_stop, when the adress on the bus is different from the device address;
reg repeat_start;      // to reset everything if repeat start is detected.
reg write_flag;        // to set when write oper begins
reg reset;             // Used to reset the start , stop registers     
reg sda_out;           // To force the SDA output Low. Remains tristated for sending High Logic.
reg done;              // To Indicate data transfer done
reg [3:0]count;                          // Down Counter ( 7 to 0 + ack bit )
reg [n-1:0] GPIO_output;                 // parallel store
reg [n-1:0] GPIO_input_reg;              // Stores the Values at the input pins before sending to master.
reg data_or_address;                     // high for data, low for address
reg read_oper, add_is_matching;          // high for master read; high for address matching


/********************************************************************************************************/

/* Detecting STOP Condition on the SDA Bus */
always @ (posedge sda or posedge reset)
if (reset) begin
    stop <= 0;
end else if (sclk) begin
    stop <= 1;
end


/* Detecting START Condition on the SDA Bus */
always @ (negedge sda or posedge reset)
if (reset) begin
    start <= 0;
end else if (sclk) begin
    start <= 1;
end


/* Tracking START_STOP related status of the device */
always @ (negedge sclk)
 if (start_stop & start) begin
     repeat_start <= 1;
     reset <= 1;
 end else if (start) begin
     start_stop <= 1;
     reset <= 1;
     repeat_start <= 0;
 end else if (stop) begin
     start_stop <= 0;
     reset <= 1;
     repeat_start <= 0;
 end else if (some_other_device) begin
     start_stop <= 0;
     repeat_start <= 1;
 end else begin
     reset <= 0;
     repeat_start <= 0;  
 end

/***********************************************************************************************************/   

/* Counting of bits. First eight bits are data and the last one is ack. */
wire sda_is_ack = count[3] & count [2];  // High for ack , count = 1111

/* Down Counter, 1111 is ack */
always @ (negedge sclk)
if (start) begin
    count <= 4'h7;               // it would decreae to 7 on the first pos edge of sclk.
end
else if (start_stop) begin
         if (sda_is_ack) begin   // count is restored to 7
            count <= 4'h7;
         end else begin
         count <= count - 4'h1;  // count is decremented until zero.
         end
end


/***********************************************************************************************************/
/* Taking the Inputs from SDA line and Comparing with Address */это чтение?

always @(posedge sclk)
   if (start_stop) begin
      if (~sda_is_ack) begin
          if (~data_or_address | repeat_start) begin
              if (repeat_start) begin
              add_is_matching <= 1;               // high means matching
              data_or_address <= 0;               // default is address
              some_other_device <= 0;             // High means that device address does not match with SDA data
              write_flag <= 0;                    
              done <= 0;                          // Low means Transfer is pending
              end
              if (count == 7 & sda != slave_address[6]) add_is_matching <= 0;  
              if (count == 6 & sda != slave_address[5]) add_is_matching <= 0;  
              if (count == 5 & sda != slave_address[4]) add_is_matching <= 0;  
              if (count == 4 & sda != slave_address[3]) add_is_matching <= 0;  
              if (count == 3 & sda != slave_address[2]) add_is_matching <= 0;  
              if (count == 2 & sda != slave_address[1]) add_is_matching <= 0;  
              if (count == 1 & sda != slave_address[0]) add_is_matching <= 0;  
              if (count == 0 & ~sda )begin
              read_oper <= 0;
              data_or_address <= 1;
              end else if (count == 0) begin
              read_oper <= 1;
              data_or_address <= 1;              
              end
           
          end else if (~read_oper & ~done) begin               
               if (count == 7) GPIO_output[7] <= sda;
               if (count == 6) GPIO_output[6] <= sda;
               if (count == 5) GPIO_output[5] <= sda;
               if (count == 4) GPIO_output[4] <= sda;
               if (count == 3) GPIO_output[3] <= sda;
               if (count == 2) GPIO_output[2] <= sda;
               if (count == 1) GPIO_output[1] <= sda;
               if (count == 0) begin
                   GPIO_output[0] <= sda;
                   done <= 1;    
               end
          end else begin
               if (count == 0) done <= 1;
          end   

       end else begin
          if (add_is_matching) begin
              if (read_oper) write_flag <= 1;   
          end else begin
              data_or_address <= 0;
              some_other_device <= 1;
          end
             
       end   
    
    end else begin
    add_is_matching <= 1;  // high means matching
    data_or_address <= 0;  // default is address
    some_other_device <= 0;
    write_flag <= 0;
    done <= 0;
    end

/***********************************************************************************************************/

/* Writing ACK and DATA on the SDA Line*/

wire ack_flag = (count[3]|count[2]|count[1]|count[0]); //becomes low when count is 0

always@(negedge sclk)
    if (start_stop) begin
        if (~ack_flag) begin                              
            if ( add_is_matching  & ~write_flag)begin sda_out <= 1'b0;
            end else begin sda_out <= 1'bz;
            end
            if (read_oper & ~done) GPIO_input_reg <= GPIO_input;
        end else if (read_oper & data_or_address & ~done) begin
             if (ack_flag) begin
                 if (~GPIO_input_reg[7]) begin
                     sda_out <= 1'b0;
                 end else begin
                     sda_out <= 1'bz;
                 end
                 GPIO_input_reg <= GPIO_input_reg << 1;                    
             end
        end else begin
             sda_out <= 1'bz;
        end
    end

wire sda;

assign sda = sda_out;

endmodule

...................................................................

как с помощью этого кода можно записывать (адрес slave 7'h50) и почему здесь нет тактовой частоты?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

6 часов назад, Alexey87 сказал:

почему здесь нет тактовой частоты

Потому что это ведомое (slave) устройство?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

16 часов назад, Alexey87 сказал:

Вот на intel взял исходник:

как с помощью этого кода можно записывать (адрес slave 7'h50) и почему здесь нет тактовой частоты?

Вы привели отличный пример, каким не должен быть проект на FPGA... Может он и будет работать. Но сбои и ошибки ему гарантированны.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

On 11/10/2018 at 1:22 AM, Alexey87 said:

 

как с помощью этого кода можно записывать (адрес slave 7'h50) и почему здесь нет тактовой частоты?

Вам хочется разбираться с чужими кодами, а не писать свое, как рекомендовали?
Взгляните и на мой самописный код, которым я успешно работал с cat24wc256.
Но я всё-равно присоединяюсь к вышесказанному и советую вам самому разобраться в вопросе ни на кого, кроме стандартов и datasheet-ов, не глядя.

i2c.zip

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

to: AnatolySh.

Спасибо за код, на данный момент я уже не пытаюсь разобраться с протоколом i2c, а приступил к базовым основам цифровой схемотехники и уже потом наверное буду пробовать свои силы.

С уважением, Алексей.

Изменено пользователем Alexey87

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

9 часов назад, Alexey87 сказал:

to: AnatolySh.

Спасибо за код, на данный момент я уже не пытаюсь разобраться с протоколом i2c, а приступил к базовым основам цифровой схемотехники и уже потом наверное буду пробовать свои силы.

С уважением, Алексей.

 

Очень хорошая книга, которая может Вам помочь: Уэйкерли Дж.Ф. Проектирование цифровых устройств.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

6 hours ago, Flip-fl0p said:

Очень хорошая книга, которая может Вам помочь: Уэйкерли Дж.Ф. Проектирование цифровых устройств.

Благодарю Вас, сейчас ещё жду: Токхейм Р. Основы цифровой электроники.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я свои исходники кастомные более менее обобщил, если будет актуально, отпишитесь, помогу чем смогу. Но лучше конечно самому разобраться, лучше задавайте вопросы по протоколу.

Изменено пользователем new123

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Здравствуйте, попробовал описать запись по протоколу I2C для EEPROM 24C04 (как я понял реализацию). В архиве, то что получилось.

test.rar

У меня возникли вопросы:

1. Как правильно инкрементировать значение регистра reg

reg[7:0]data = 0;

data <= data + 1 или data <= data + 1'b1?

2. Как правильно обнулять значение регистра reg

data <= 0 или data <= 8'b0 или data <= 8'b00000000?

С уважением, Алексей.

p.s. Интересуют варианты реализации для 1 и 2 вопроса.

Изменено пользователем Alexey87

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 час назад, Alexey87 сказал:

1. Как правильно инкрементировать значение регистра reg

reg[7:0]data = 0;

data <= data + 1 или data <= data + ?

Поздравляю вас с выбором Верилога. Можно так и так, но из-за того, что целые числа являются 32-разрядными, то, если вы будете просто писать <= 0 или <= 1, вас будет спамить варнингами о несовпадении разрядностей левой и правой части. Поэтому лучше писать data <= data + 1'b1. Меня, испорченного VHDL'ем, эта лишняя писанина из-за варнинга на пустом месте сильно достаёт.

1 час назад, Alexey87 сказал:

data <= 0 или data <= 8'b0 или data <= 8'b00000000?

Всё то же самое.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...