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

GOWIN I2C VHDL

Здравствуйте.

А кто нибудь работал с i2c у ПЛИС GOWIN?

Добавил корку в проект, настройки вроде бы самые простые.

image.thumb.png.e3f17bec5c7ffb538b03e4b3e3cffb18.png

 

Он формирует вот такой вот компонент:

your_instance_name: I2C_MASTER_Top
	port map (
		I_CLK => I_CLK_i,
		I_RESETN => I_RESETN_i,
		I_TX_EN => I_TX_EN_i,
		I_WADDR => I_WADDR_i,
		I_WDATA => I_WDATA_i,
		I_RX_EN => I_RX_EN_i,
		I_RADDR => I_RADDR_i,
		O_RDATA => O_RDATA_o,
		O_IIC_INT => O_IIC_INT_o,
		SCL => SCL_io,
		SDA => SDA_io
	);

 

Скачал доку по описанию работы i2c

И судя по ней взаимосвязь с модулем i2c необходимо реализовать через какие то встроенные регистры SRAM.

image.thumb.png.f9b50ff905d9a0c5fcad523b944f3b2c.png

 

А как получить доступ то к этим регистрам?? 

Может у кого есть примерчик работы этого модуля?? 

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

Спасибо.

 

 

IPUG504-1.5E_Gowin I2C Master and Slave User Guide.pdf

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


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

Блин. Отбой. Я вначале не понял а потом как понял. ))

Но остается вопрос по примерам. В даташите вроде ссылаются на пример но почему то у меня в их IDE такого нет. Может я чего то не установил или где то есть комплект примеров??

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


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

I2C Master RefDesign: https://www.gowinsemi.com/en/document/chkLogin/?a=upload%2Fdatabase_doc%2F2018%2Fdocument%2F63bf270e8d5c3.zip

I2C Slave RefDesign : https://www.gowinsemi.com/en/document/chkLogin/?a=upload%2Fdatabase_doc%2F2019%2Fdocument%2F626a064198725.rar

 

Но для скачивания нужно на сайте зарегистрироваться.

 

На всякий случай прилагаю:

Gowin_I2C_Slave_refDesign.rar Gowin_I2C_Master_RefDesign.zip

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


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

В 08.08.2023 в 13:25, StewartLittle сказал:

Но для скачивания нужно на сайте зарегистрироваться.

Спасибо. Это документы я скачал. 

 

По аналогии с примером на verilog сделал свой код, но у меня какая то странная фигня. 

 

Вот кусок кода. Вроде бы все идеально.

 case i2c_mode_cnt is
        when 0 =>
            i2c_reset_n <= '0';
            i2c_wr_adr <= (others => '0');
            i2c_wr_data <=(others => '0'); 
            i2c_rd_adr <=(others => '0'); 
            i2c_wr  <= '0';            
            i2c_rd <= '0';
            byte_cnt := 0;
            inb_cnt:=0;
            i2c_delay_cnt <= i2c_delay_cnt + 1;
            if i2c_delay_cnt > 125_000_000 then
                i2c_mode_cnt <= i2c_mode_cnt + 1;
                i2c_reset_n <= '1';
                i2c_request_counter <= i2c_request_counter + 1;
                if i2c_request_counter>255 then
                    i2c_request_counter <= 0;
                end if;
                i2c_delay_cnt <= 0;                
            end if;
        when 1 =>
            
            -- записать в прескаллер 250 - это 100 000 при частоте 125мгц
            i2c_wr_adr <= SRAM_INIT_CFG_REGS(byte_cnt)(2 downto 0);   
            i2c_wr_data <=SRAM_INIT_CFG_DATA(byte_cnt);
            i2c_wr <= '1';
            i2c_mode_cnt <= i2c_mode_cnt + 1; 
            
        when 2 =>
            i2c_wr <= '0';
            i2c_wr_adr <= (others => '0');
            i2c_wr_data <= (others => '0');

            if byte_cnt >= 2 then  
                i2c_mode_cnt <= 3;           
            else 
                i2c_mode_cnt <= 1;
                byte_cnt := byte_cnt + 1;
            end if;
---------------------------------------------------------------------------------------------------------
        when 3 =>  
            -- Set the value of transmit register: Slave address + Write bit.
            i2c_wr_adr <= TX_REG; -- 03 transmit reg
            i2c_wr_data <= "11010100";  --(LSM6DS3_ADDR & WRITE);
            i2c_wr <= '1';
            i2c_mode_cnt <= i2c_mode_cnt + 1;
        when 4 =>
            i2c_wr <= '0';
            i2c_wr_adr <= (others => '0');
            i2c_wr_data <= (others => '0');
            i2c_mode_cnt <= i2c_mode_cnt + 1;
---------------------------------------------------------------------------------------------------------

        when 5 =>
            -- Set the value of the command register as 8h90 to enable the START and WRITE command. This starts the transmission on the IIC bus.
            i2c_wr_adr <= CMD_REG; -- 04 command
            i2c_wr_data <= STA_WR_CR; -- START and WRITE command
            i2c_wr <= '1';
            i2c_mode_cnt <= i2c_mode_cnt + 1;
        when 6 =>
            i2c_wr <= '0';
            i2c_wr_adr <= (others => '0');
            i2c_wr_data <= (others => '0');
            i2c_mode_cnt <= i2c_mode_cnt + 1;
---------------------------------------------------------------------------------------------------------
       
        when 7 =>             
            i2c_rd_adr <= ST_REG;  
            i2c_rd <= '1';
            i2c_mode_cnt <= i2c_mode_cnt + 1;
        when 8 =>
            i2c_rd_adr <=(others => '0'); 
            i2c_rd <= '0';
            i2c_mode_cnt <= i2c_mode_cnt + 1;
        when 9 =>    
            regVal :=  i2c_rd_data;
            i2c_inbuffer(inb_cnt) <= i2c_rd_data;
            if regVal(TIP) = '0' then                       
                i2c_mode_cnt <= 10;  
                inb_cnt := 2;
                -- goto next
            else
                i2c_mode_cnt <= 7;
                inb_cnt := 1;
            end if;
---------------------------------------------------------------------------------------------------------
        
        when 10 =>           
            i2c_wr_adr <= TX_REG;   
            i2c_wr_data <= LSM6DS3_WHO_AM_I_REG;  
            i2c_wr <= '1';
            i2c_mode_cnt <= i2c_mode_cnt + 1;
        when 11 =>
            i2c_wr <= '0';
            i2c_wr_adr <= (others => '0');
            i2c_wr_data <= (others => '0');
            i2c_mode_cnt <= i2c_mode_cnt + 1;
---------------------------------------------------------------------------------------------------------

         when 12 =>            
            i2c_wr_adr <= CMD_REG; 
            i2c_wr_data <= WR_CR;  
            i2c_wr <= '1';
            i2c_mode_cnt <= i2c_mode_cnt + 1;
         when 13 => 
            i2c_wr <= '0';
            i2c_wr_adr <= (others => '0');
            i2c_wr_data <= (others => '0');
            i2c_mode_cnt <= i2c_mode_cnt + 1;
---------------------------------------------------------------------------------------------------------

        when 14 =>
            i2c_rd_adr <= ST_REG;  
            i2c_rd <= '1';
            i2c_mode_cnt <= i2c_mode_cnt + 1;
        when 15 =>
            i2c_rd_adr <=(others => '0'); 
            i2c_rd <= '0';
            i2c_mode_cnt <= i2c_mode_cnt + 1;
        when 16 =>     
            regVal :=  i2c_rd_data;
            i2c_inbuffer(inb_cnt) <= i2c_rd_data;
            if regVal(TIP) = '0' then
                i2c_inbuffer(3) <= regVal;
                i2c_mode_cnt <= 17;
                inb_cnt := 4;
                -- goto next
            else
                i2c_mode_cnt <= 14;
                inb_cnt := 3;
            end if;
---------------------------------------------------------------------------------------------------------
        
        when 17 =>  
            -- Set the value of transmit register: Slave address + Write bit.
            i2c_wr_adr <= TX_REG; -- 03 transmit reg
            i2c_wr_data <= LSM6DS3_ADDR & READ;
            i2c_wr <= '1';
            i2c_mode_cnt <= i2c_mode_cnt + 1;
        when 18 =>
            i2c_wr <= '0';
            i2c_wr_adr <= (others => '0');
            i2c_wr_data <= (others => '0');
            i2c_mode_cnt <= i2c_mode_cnt + 1;
---------------------------------------------------------------------------------------------------------

        when 19 =>
            -- Set the value of the command register as 8h90 to enable the START and WRITE command. This starts the transmission on the IIC bus.
            i2c_wr_adr <= CMD_REG;  
            i2c_wr_data <= STA_WR_CR; 
            i2c_wr <= '1';
            i2c_mode_cnt <= i2c_mode_cnt + 1;
        when 20 => 
            i2c_wr <= '0';
            i2c_wr_adr <= (others => '0');
            i2c_wr_data <= (others => '0');
            i2c_mode_cnt <= i2c_mode_cnt + 1;
---------------------------------------------------------------------------------------------------------

        when 21 => 
            i2c_rd_adr <= ST_REG;  
            i2c_rd <= '1';
            i2c_mode_cnt <= i2c_mode_cnt + 1;
        when 22 =>
            i2c_rd_adr <=(others => '0'); 
            i2c_rd <= '0';
            i2c_mode_cnt <= i2c_mode_cnt + 1;
        when 23 =>     
            regVal :=  i2c_rd_data;
            i2c_inbuffer(inb_cnt) <= i2c_rd_data;

            if regVal(TIP) = '0' then
                i2c_inbuffer(5) <= regVal;
                i2c_mode_cnt <= 24;
                inb_cnt := 6;
                -- goto next
            else
                i2c_mode_cnt <= 21;
                inb_cnt := 5;
            end if;
---------------------------------------------------------------------------------------------------------
         
        when 24 =>
            i2c_wr_adr <= CMD_REG; -- 04 command
            i2c_wr_data <= RD_CR; -- START and WRITE command
            i2c_wr <= '1';
            i2c_mode_cnt <= i2c_mode_cnt + 1;
        when 25 => 
            i2c_wr <= '0';
            i2c_wr_adr <= (others => '0');
            i2c_wr_data <= (others => '0');
            i2c_mode_cnt <= i2c_mode_cnt + 1;
---------------------------------------------------------------------------------------------------------

        when 26 => 
            i2c_rd_adr <= ST_REG;  
            i2c_rd <= '1';
            i2c_mode_cnt <= i2c_mode_cnt + 1;
        when 27 =>
            i2c_rd_adr <=(others => '0'); 
            i2c_rd <= '0';
            i2c_mode_cnt <= i2c_mode_cnt + 1;
        when 28 =>     
            regVal :=  i2c_rd_data;
            i2c_inbuffer(inb_cnt) <= i2c_rd_data;

            if regVal(TIP) = '0' then
                i2c_inbuffer(7) <= regVal; 
                i2c_mode_cnt <= 29;
                inb_cnt := 8;
                -- goto next
            else
                i2c_mode_cnt <= 26;
                inb_cnt := 7;
            end if;
---------------------------------------------------------------------------------------------------------

        when 29 => 
            i2c_rd_adr <= RX_REG;  
            i2c_rd <= '1';
            i2c_mode_cnt <= i2c_mode_cnt + 1;
        when 30 =>
            i2c_rd_adr <=(others => '0'); 
            i2c_rd <= '0';
            i2c_mode_cnt <= i2c_mode_cnt + 1;
        when 31 =>
            i2c_inbuffer(inb_cnt)<= i2c_rd_data;         
            i2c_mode_cnt <= i2c_mode_cnt + 1;            
---------------------------------------------------------------------------------------------------------

        when 32 => 
            i2c_wr_adr <= CMD_REG; 
            i2c_wr_data <= STP_RD_NCR; 
            i2c_wr <= '1'; 
            i2c_mode_cnt <= i2c_mode_cnt + 1;
        when 33 =>
            i2c_wr <= '0';
            i2c_wr_adr <= (others => '0');
            i2c_wr_data <= (others => '0');
            i2c_mode_cnt <= i2c_mode_cnt + 1;
            byte_cnt :=0;
---------------------------------------------------------------------------------------------------------

 

Частота 50 мхз. делитель для 100кгц сделал.

constant SRAM_INIT_CFG_REGS : SRAM_STATIC_ARR := (x"02",x"01",x"00");
constant SRAM_INIT_CFG_DATA : SRAM_STATIC_ARR := (x"80",x"00",x"63"); -- for 50Mhz clock 100 000 hz

 

Записал все в регистр и считал обратно данные соответствуют.

Вот что показывает анализатор на линии:

image.thumb.png.96394a553879e07c5d99bf3af32fe083.png

 

Устройство это LSM6DSO. адрес 1101010

image.thumb.png.1b78d7e0b5ffc281193b5586fda1eeca.png

 

Ну ни в какую не работает. В чем может быть проблема??

 

Причем почему то адрес показывается 6A хотя должен быть D4 (1101010-0)

 

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

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


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

5 часов назад, Worldmaster сказал:

Причем почему то адрес показывается 6A хотя должен быть D4

В I2C встречается два варианта прочтения адреса слэйв устройства:
1. Восьмибитный. В вашем случае 0xD4 - адрес записи, 0xD5 - адрес чтения
2. Семибитный. В вашем случае 0x6A. Запись или чтение указываются текстом. У вас на картинке написаны Setup Write to [0x6A] и Setup Read to [0x6A]

Логический анализатор можно настроить на показ того и другого варианта.

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


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

В 09.08.2023 в 17:39, Zig сказал:

Логический анализатор можно настроить на показ того и другого варианта.

 

Ну да. Спасибо. Нашел.

А по поводу того что гироскоп недоступен то это все таки проблема гироскопа?? или что то все таки не так сделал?

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


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

Для будущих поколений оставлю решение:

Проверяйте к каким банкам подключены линии взаимодействия.

image.thumb.png.326c726f847fef216e8fbf4643ecb518.png

1,8 не хватало для определения уровня и периодически анализатор указывал на ошибку Missing Ack.

Изменил на 3.3 и заработало. Однако надо учитывать подобные вещи на этапе планировки оборудования так как можете подключить разное оборудование на несовместимые банки.

 

 

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


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

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

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

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

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

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

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

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

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

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