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

Непонятки с модулем I2C

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

Помогите разобраться что может быть.

Есть чип GW2AR-LV18EQ144C8/I7 с коркой i2c.

 

Сделал модуль:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;
use IEEE.numeric_std.all;



entity I2C_MODULE is 
 
port (    
    rst_n : in std_logic;    
    I_clk : in std_logic;   

	SCL_io : inout std_logic;   
	SDA_io : inout std_logic;   
    
	transmit_en : in std_logic;   					-- флаг начала передачи
	
    Dev_adr: in std_logic_vector(6 downto 0);  		-- адрес устройства
    Reg_adr: in std_logic_vector(15 downto 0); 		-- адрес регистра
	RW: in std_logic;   							-- чтение или запись
	Data_count: in std_logic_vector(7 downto 0); 	-- количество данных для чтения или записи
    
	Is16BitAddres: in std_logic;    -- для камеры нужно 16 битный адрес
	
    IsDataReady: out std_logic;   						-- флаг готовности данных
    IsReady: out std_logic;   						-- флаг готовности модуля
    ReadData: out std_logic_vector(7 downto 0); 	-- данные для чтения
    WriteData: in std_logic_vector(7 downto 0); 	-- данные для записи

	CompleteTransaction: out std_logic;
	ErrorCode: out std_logic_vector(7 downto 0);	-- код ошибки при передаче
	LastStatusCode: out std_logic_vector(7 downto 0)	-- Последнее состояние статусного регистра модуля
); 
end I2C_MODULE;

architecture rtl of I2C_MODULE is 

-- локальные сигналы
signal i2c_wr_adr: std_logic_vector(2 downto 0):=(others=>'0');       
signal i2c_wr_data: std_logic_vector(7 downto 0):=(others=>'0');       
signal i2c_rd: std_logic:='0';                           
signal i2c_wr: std_logic:='0';    
signal i2c_rd_adr: std_logic_vector(2 downto 0):=(others=>'0');       
signal i2c_rd_data: std_logic_vector(7 downto 0):=(others=>'Z');              
signal i2c_int: std_logic:='0';                         

signal i2c_complete: std_logic:='0';   

----------------------------------------------------------------------- 
component I2C_MASTER_Top
	port (
		I_CLK: in std_logic;
		I_RESETN: in std_logic;
		I_TX_EN: in std_logic;
		I_WADDR: in std_logic_vector(2 downto 0);
		I_WDATA: in std_logic_vector(7 downto 0);
		I_RX_EN: in std_logic;
		I_RADDR: in std_logic_vector(2 downto 0);
		O_RDATA: out std_logic_vector(7 downto 0);
		O_IIC_INT: out std_logic;
		SCL: inout std_logic;
		SDA: inout std_logic
	);
end component; 

begin

 MyI2C: I2C_MASTER_Top
	port map (
		I_CLK =>  I_clk,
		I_RESETN => rst_n,
		I_TX_EN => i2c_wr,
		I_WADDR => i2c_wr_adr,
		I_WDATA => i2c_wr_data,
		I_RX_EN => i2c_rd,
		I_RADDR => i2c_rd_adr,
		O_RDATA => i2c_rd_data,
		O_IIC_INT => i2c_int,
		SCL => SCL_io,
		SDA => SDA_io
	); 

 
-- основной процесс для отправки команды
i2c_module_main: process (I_clk, rst_n, transmit_en)
-- коды регистров
constant 	TX_REG: std_logic_vector(2 downto 0) := "011"; 
constant 	RX_REG: std_logic_vector(2 downto 0) := "011"; 
constant 	CMD_REG: std_logic_vector(2 downto 0) := "100"; 
constant 	ST_REG: std_logic_vector(2 downto 0) := "100";
 
-- биты проверки статуса
constant TIP: integer:=1;
constant RX_ACK: integer:=7;

-- команды
constant 	STA_WR_CR	: std_logic_vector(7 downto 0) := "10010001"; --start+write_ack
constant 	WR_CR		: std_logic_vector(7 downto 0) := "00010001"; --write+ack
constant	STP_WR_CR	: std_logic_vector(7 downto 0) := "01010001"; --stop+write+ack
constant	STP_CR		: std_logic_vector(7 downto 0) := "01000001"; --stop+write+ack
constant 	STA_RD_CR	: std_logic_vector(7 downto 0) := "10100001"; --8'hC0;//start+read+ack     C0--->A0?
constant 	RD_CR		: std_logic_vector(7 downto 0) := "00100001"; --read+ack
constant 	RD_NACKCR	: std_logic_vector(7 downto 0) := "00101001"; --read+nack
constant 	STP_NCR	    : std_logic_vector(7 downto 0) := "01001001"; --stop+nack
constant 	STP_RD_NCR	: std_logic_vector(7 downto 0) := "01101001"; --stop+read+nack
constant 	STP_IACR	: std_logic_vector(7 downto 0) := "01000001"; --stop+IACK
constant 	READ      	: std_logic := '1';
constant    WRITE     	: std_logic := '0';

-- состояния 
type fsm_state is(init, idle, send_cmd_1, send_cmd_2, send_cmd_3,send_cmd_4,  ReadData_init,ReadData_process, ReadData_complete,ReadData_complete_2 ,WriteData_init, WriteData_process, complete, nop); 

variable state: fsm_state:=init ;
variable next_state: fsm_state:=init;
variable bytes_counter: integer:=0;
--variable reg_value:std_logic_vector(7 downto 0):=x"00";

variable Task_reg_value:std_logic_vector(7 downto 0):= x"00";	-- значение которое запишется в регистр при очередном цикле
variable Task_cmd_value:std_logic_vector(7 downto 0):= x"00";	-- команда которая запишется в модуль при очередном цикле
variable SubTask_mode_value:integer:=0;					-- номер обработки задач чтения или записи

-- параметры настройки модуля
type SRAM_STATIC_ARR is array (2 downto 0) of std_logic_vector(7 downto 0);
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"27",x"0f");
--constant SRAM_INIT_CFG_DATA : SRAM_STATIC_ARR := (x"80",x"00",x"63"); -- for 50Mhz clock 100 000 hz
constant SRAM_INIT_CFG_DATA : SRAM_STATIC_ARR := (x"80",x"61",x"a7");  -- 1000 hz

--constant SRAM_INIT_CFG_DATA : SRAM_STATIC_ARR := (x"80",x"00",x"fa");

variable init_state : std_logic := '0';	
variable byte_cnt: integer:=0; 
variable error_timeout: integer:=0;
variable AddrSended: std_logic:='0';
Variable LocErrorCode: std_logic_vector(7 downto 0);	-- код ошибки при передаче
begin


if rst_n = '0' then 
	i2c_wr_adr <= (others => '0');
	i2c_wr_data <=(others => '0'); 
	i2c_rd_adr <=(others => '0'); 
    ReadData <= (others => '0');
	LastStatusCode <= (others => '0');
    init_state := '0';
	i2c_wr  <= '0';            
	i2c_rd <= '0';     
    IsReady <= '0';        
	IsDataReady <= '0';
    byte_cnt := 0;
    state := init;
	ErrorCode <= x"00";
	LocErrorCode := x"00";
	AddrSended := '0';
	i2c_complete <= '1';
	CompleteTransaction <= '0';
else if rising_edge(I_clk) then  
	case state is
        when init =>
			if init_state = '0' then
				-- инициирование регистров модуля 
				i2c_wr_adr <=  SRAM_INIT_CFG_REGS(byte_cnt)(2 downto 0);   
				i2c_wr_data <= SRAM_INIT_CFG_DATA(byte_cnt);
				i2c_wr <= '1';
				init_state := '1'; 
			else 
				i2c_wr <= '0';
				i2c_wr_adr <= (others => '0');
				i2c_wr_data <= (others => '0');
				init_state := '0';
				-- отправляем следующий байт
				if byte_cnt >= 2 then  
					state := idle;	    
				else  
					byte_cnt := byte_cnt + 1;
				end if; 
			end if;
		when idle=>
			AddrSended := not Is16BitAddres;
			IsReady <= '1';
            IsDataReady <= '0';
			i2c_wr_adr <= (others => '0');
			i2c_wr_data <=(others => '0'); 
			i2c_rd_adr <=(others => '0'); 
			i2c_wr  <= '0';            
			i2c_rd <= '0';  
			error_timeout := 0;				
			CompleteTransaction <= '1';	 		
			ErrorCode <= x"00";
			LocErrorCode := x"00";
				
			if transmit_en = '1' then
				i2c_complete <= '0';
				CompleteTransaction <= '0';
				ErrorCode <= x"00";
				LocErrorCode := x"00";
                bytes_counter := to_integer(unsigned(Data_count));  
				Task_reg_value := (Dev_adr & WRITE);
				Task_cmd_value := STA_WR_CR;
				SubTask_mode_value := 0;
				state := send_cmd_1;				
			end if;						
----------------------------------------------------
-- стандартный блок взаимодействия с модулем i2c		 
		when send_cmd_1=>
            IsDataReady <= '0';
			IsReady <= '0'; 
			i2c_wr_adr <= TX_REG;  
			i2c_wr_data <= Task_reg_value ;     
			i2c_wr <= '1'; 	
			state := nop; 	
			next_state := send_cmd_2;			
		when send_cmd_2=>     
			i2c_wr_adr <= CMD_REG;  
			i2c_wr_data <= Task_cmd_value;     
			i2c_wr <= '1'; 		
			state := nop; 	
			next_state := send_cmd_3;
		when send_cmd_3 =>             
			i2c_rd_adr <= ST_REG;  
			i2c_rd <= '1';  
			state := nop; 	
			next_state := send_cmd_4;
			-- error_timeout := 0;	-- надо чтобы было актуальное значение задержки если обнулять то смысл теряется
        when send_cmd_4 =>    
            --reg_value :=  i2c_rd_data; 
			if i2c_rd_data(TIP) = '0' then  -- ждем пока модуль закончит свои операции
				error_timeout := 0;
				LastStatusCode <= i2c_rd_data;
				
				if i2c_complete = '1' then
					state := complete; 	
				else			
					-- если есть АСК значит устрйоство на шине и можем продолжать операции
					-- надо определить следующее действие 				 			
					case SubTask_mode_value is
						when 0 =>						
							if i2c_rd_data(RX_ACK) = '0' then															
								-- инициация начала чтения регистраё
								if AddrSended = '0' then
									Task_reg_value := Reg_adr(15 downto 8);
									AddrSended  := '1';
								else
									Task_reg_value := Reg_adr(7 downto 0);
									SubTask_mode_value := SubTask_mode_value + 1 ;	
								end if;
                                state := send_cmd_1;
								Task_cmd_value := WR_CR;								
							else
								--ErrorCode <= x"f1"; -- NO ACK ERROR
								LocErrorCode :=x"f1";
								i2c_complete <= '1';
								Task_cmd_value := STP_IACR;
								state := send_cmd_2;
								--state := complete;
							end if;							
						when 1 =>
							if RW = READ then	
								-- продоление чтение регистра
								Task_reg_value := (Dev_adr & READ);
								Task_cmd_value := STA_WR_CR;
								SubTask_mode_value := SubTask_mode_value + 1 ;
								state := send_cmd_1;			
							else					
								-- инициация записи
								state := WriteData_init;
								IsDataReady <= '1';	
							end if;
						when 2 =>
							if RW = READ then	
								-- продоление чтение и завершение чтения регистра	 					
								state := ReadData_init;
								SubTask_mode_value := SubTask_mode_value + 1 ; 		
							else					
								i2c_complete <= '1';
								Task_cmd_value := STP_IACR;
								state := send_cmd_2;
							end if;							 
						when 3 =>
							 if RW = READ then	
								state := ReadData_process;		
							else					
								i2c_complete <= '1';
								Task_cmd_value := STP_IACR;
								state := send_cmd_2;
							end if;			
						when others =>
								i2c_complete <= '1';
								Task_cmd_value := STP_IACR;
								state := send_cmd_2;
					end case; 
				end if;
            else
                state := send_cmd_3; 
				error_timeout := error_timeout + 1;
				if error_timeout > 100_000_000 then
					--ErrorCode <= x"f0";
					LocErrorCode :=  x"f0";
					i2c_complete <= '1';
					Task_cmd_value := STP_IACR;
					state := send_cmd_2;	
				end if;
            end if;
----------------------------------------------------
		 when ReadData_init =>
			IsDataReady <= '0';		
		 	if bytes_counter <= 1 then
				Task_cmd_value := STP_RD_NCR;   			
			else 								
				Task_cmd_value := RD_CR; 									
			end if; 
				
			state := send_cmd_2;
		 when ReadData_process => 				
			i2c_rd_adr <= RX_REG;  
            i2c_rd <= '1';			
			next_state := ReadData_complete;		
			state := nop;	
		 when ReadData_complete=> 				
			-- данные готовы можно считывать	
			IsDataReady <= '1';				
			ReadData <= i2c_rd_data; 
			state := ReadData_complete_2;	
		when ReadData_complete_2=> 						
			if bytes_counter <= 1 then 
				-- транзакия завершена штатно с выходов STOP
				i2c_complete <= '1'; 
				state := complete;
			else 	
				IsDataReady <= '0'; 			
				state := ReadData_init;		 					
			end if;
			if bytes_counter > 0 then			
				bytes_counter := bytes_counter - 1;	
			end if;
----------------------------------------------------
-- блок записи в шину
		 when WriteData_init =>
			IsDataReady <= '0'; 
			if bytes_counter < 1 then 
				-- транзакия завершена штатно с выходов STOP
				i2c_complete <= '1'; 
				state := complete;
			else 
				state := WriteData_process;
			end if;
			
		 when WriteData_process=>            
			Task_reg_value := WriteData; 			
			if bytes_counter <= 1 then
				Task_cmd_value := STP_WR_CR;   			
			else
				Task_cmd_value := WR_CR; 									
			end if; 	
			if bytes_counter > 0 then			
				bytes_counter := bytes_counter - 1;	
			end if;
			state := send_cmd_1;			
----------------------------------------------------
		
		when nop=>
			i2c_wr <= '0';
			i2c_rd <= '0';			 
			i2c_rd_adr <=(others => '0'); 
            i2c_wr_adr <= (others => '0');
            i2c_wr_data <= (others => '0');
            state := next_state; 				 
            --if transmit_en = '0' then
            --    state := idle;
            --end if; 
		when complete =>
			i2c_wr <= '0';
			i2c_rd <= '0';			 
			i2c_rd_adr <=(others => '0'); 
            i2c_wr_adr <= (others => '0');
            i2c_wr_data <= (others => '0');
			CompleteTransaction <= '1';
			ErrorCode <= LocErrorCode;
			if transmit_en = '0' then
                state := idle;
            end if; 
		when others =>
	end case;
end if;
end if;
end process i2c_module_main;

 

Сделал для него в главной архитектуре процесс:

I2c_cam1_Exchange_Process: process (InClock_50, I2c_Bus_2_Start_Transaction, cam1_Ready, cam1_Data_Ready)
type LOC_FSM_STATE is (Init, Idle,  Processing);
variable loc_state: loc_fsm_state:=init;

begin 
if i2c_bus_2_Start_Transaction = '0'  then
	loc_state := init;   
	cam1_en <= '0';
else 
	if rising_edge(InClock_50) then
		case loc_state is			
			when init =>
				if cam1_ready = '1' then 
					if i2c_bus_2_tx_data_buffer(REG_ADDR16_BIT) = x"00" then
							cam1_reg_adr16 <= '0'; 
						else
							cam1_reg_adr16 <= '1'; 
						end if;
					
						cam1_dev_adr <= i2c_bus_2_tx_data_buffer(DEV_ADDR_BIT)(6 downto 0) ; -- адрес устройства
						cam1_reg_adr <= i2c_bus_2_tx_data_buffer(REG_ADDR_HI) & i2c_bus_2_tx_data_buffer(REG_ADDR_LOW); -- адрес регистра
						if i2c_bus_2_tx_data_buffer(RW_BIT) = x"00" then
							cam1_rw <= '0'; -- WRITE: std_logic := '0';  
						else
							cam1_rw <= '1'; -- READ: std_logic := '1';
					end if;
					cam1_data_count <= i2c_bus_2_tx_data_buffer(BYTES_COUNT_BIT);  -- количество 
					cam1_ptr <= 0;
					cam1_en <= '1';
					loc_state := processing;  
				end if;          
			when processing=>
				if cam1_errCode /= x"00" then
					i2c_bus_2_rx_data_buffer(0) <= cam1_errCode;
					i2c_bus_2_rx_data_buffer(1) <= cam1_LastStatusCode;
					loc_state := idle;     
				else
					if cam1_data_ready = '1' then  	
						-- на последнем байте перейдем в ожидание завершения
						if cam1_ptr >= cam1_data_count then
							loc_state := idle;  					
						else
							if i2c_bus_2_tx_data_buffer(RW_BIT) = x"00" then	 
								cam1_writeData <= i2c_bus_2_tx_data_buffer(DATA_PTR_BIT + cam1_ptr);
							else 
								i2c_bus_2_rx_data_buffer(cam1_ptr) <= cam1_readData;  				
							end if;      
							cam1_ptr <= cam1_ptr + 1;
						end if;
					end if;  
				end if;
			when idle=>
				-- ожидаем пока головной процесс выключит модуль 
                if i2c_bus_2_Complete_Transaction = '1' then
                    cam1_en <= '0';
                end if;
		end case;	
	end if;
end if;
end process I2c_cam1_Exchange_Process;

 

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

И вроде бы все отлично.

Подпаял анализатор, смотрю что на шине.

image.thumb.png.d442e41e9e2219dd7bba6c3f0312649f.png

 

Но через какое то рандомное время модуль просто перестает работать.

В коде i2c сделал обработку ошибок и вывод состояния наверх в комп.

--ErrorCode <= x"f1"; -- NO ACK ERROR
LocErrorCode :=x"f1";
i2c_complete <= '1';
Task_cmd_value := STP_IACR;
state := send_cmd_2;
--state := complete;

И когда все падает то я получаю ошибку что нет ACK но судя по анализатору там даже на линию и не выдается никаких сигналов.

Изначально статусный регистр выкидывал флаг if.

image.thumb.png.d2281846d73da09a973ee1e0ea3f5621.png

Я думал что это из за него и просто вставил во все команды бит IACK

image.thumb.png.57dd579a4b186786fe97512db13ef4c8.png

 

-- команды
constant 	STA_WR_CR	: std_logic_vector(7 downto 0) := "10010001"; --start+write_ack
constant 	WR_CR		: std_logic_vector(7 downto 0) := "00010001"; --write+ack
constant	STP_WR_CR	: std_logic_vector(7 downto 0) := "01010001"; --stop+write+ack
constant	STP_CR		: std_logic_vector(7 downto 0) := "01000001"; --stop+write+ack
constant 	STA_RD_CR	: std_logic_vector(7 downto 0) := "10100001"; --8'hC0;//start+read+ack     C0--->A0?
constant 	RD_CR		: std_logic_vector(7 downto 0) := "00100001"; --read+ack
constant 	RD_NACKCR	: std_logic_vector(7 downto 0) := "00101001"; --read+nack
constant 	STP_NCR	    : std_logic_vector(7 downto 0) := "01001001"; --stop+nack
constant 	STP_RD_NCR	: std_logic_vector(7 downto 0) := "01101001"; --stop+read+nack
constant 	STP_IACR	: std_logic_vector(7 downto 0) := "01000001"; --stop+IACK
constant 	READ      	: std_logic := '1';
constant    WRITE     	: std_logic := '0';

 

Однако это не стало прям конкретным решением (((.

Сейчас сразу начнут говорить про тестбенч. Так вот в нем я отладил только общий алгоритм подачи команд и возврата и по тестбенчу это все работает. Да и в железе тоже.

К тому же в тестбенче невозможно проверить действительное состояние линий SDA SCL. Ну или я чего то не знаю.

Сейчас статус при ошибке возвращается как 0x80 но почему он затыкается то мне не понятно.

В общем буду благодарен за любую помощью или хоть какие нибудь методы чтобы понять в чем косячина.

Спасибо.

 

 

 

 

 

 

 

 

 

 

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


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

В общем я так и понял что много кода и всем лень читать и вникать.

Но С кодом видимо все в порядке. Стопудово косяк в самой корке.

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

Сейчас вот уже двое суток работает .. захожу по удаленке и смотрю на показания анализатора. Пропуски конечно есть .. но они уровня 1 на 1000 запросов. 

Очень странное поведение модуля. У микрочипа или стм на их чипах никогда подобных косяков даже близко не встречал. Если уж модуль запустился то он может работать нормально на всем протяжении работы чипа.

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

 

В общем как то так. Относитесь к коркам с осторожностью. 

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


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

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

Решение сделать все жутким костылем.

В общем как то так. Относитесь к коркам с осторожностью. 

Разве это решение. Поставить костыль. Иметь пропуски. Наверно правильное решение - отказаться от корки (при этом промоделировать ее и предупредить всех о ее несоответствии стандарту).

Непонятно, почему  в тестбенче невозможно проверить действительное состояние линий SDA SCL.  Нет ведь проблем в моделировании двунаправленной линии с  буфером с открытым стоком (два состояния на выходе : 0, z: два состояния на входе : 0, 1).

z состояние синим цветом нарисуют.

Посмотрите, какие частотные ограничения в корке накладываются на I_clk : in std_logic;SCL_io : inout std_logic; С трудом вериться, что корка не работает.

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


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

В 27.01.2024 в 23:53, sazh сказал:

Наверно правильное решение - отказаться от корки (при этом промоделировать ее и предупредить всех о ее несоответствии стандарту).

Ну может и так. Только кого уведомлять то?? Gowin дела до этого нет. Все запросы они игнорят.

В 27.01.2024 в 23:53, sazh сказал:

Непонятно, почему  в тестбенче невозможно проверить действительное состояние линий SDA SCL. 

Мне тоже не особо понятно. Вот сигнал из корки i2c_rd_data. Как только отправляется команда на работу этот сигнал помечается как XX. Это вроде бы значит что производится запись из разных процессов. Но у меня запись в него не производиться вообще. 

И даже когда я формированно выставляю нужные сигналы то на линиях SDA SCL ни за какое время никаких изменений не происходит. Вроде бы я даже по этому поводу тему заводил. Если есть желание то могу тему поднять и выложить тестбенч может я там действительно чего то не усмотрел. 

В 27.01.2024 в 23:53, sazh сказал:

С трудом вериться, что корка не работает.

Так вот мне тоже с трудом в это верится. Но как показала практика то у китайцев не все так просто. Например с модулем SDRAM (тоже есть отдельная тема). Там только опытным путем стало понятно что корка работает в ограниченном функционале. Но в даташитах нигде об этом ни слова. Возможно что и тут тоже есть какая то мелочь о которой в даташите ни сказано.

 

Прикладываю даташит. Никаких особых ограничений я не увидел. 

image.thumb.png.e2ddd93f8462927dfecc146aca9312c8.png

 

image.thumb.png.12cd22a26b4d69f00d883a98d4bd8a71.png

 

Я строил свой алгоритм в основном отталкиваясь от примера который на сайте выложен. Там на вход подается 50 мегагерц. Также и у меня. 

 

 

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

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

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


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

On 1/25/2024 at 2:55 PM, Worldmaster said:

К тому же в тестбенче невозможно проверить действительное состояние линий SDA SCL. Ну или я чего то не знаю.

Как невозможно? Давайте делать, попробую подсказать. Надо поставить что то посерединке. Так то если цеплять напрямую, тогда конечно, не увидеть что же задрайвило линию в текущее состояние. Ну и в тестбенче я бы помучил модуль какими то нештатными ситуациями и реакцией на них - сразу вылезет тонна.

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


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

В 15.02.2024 в 02:13, 1891ВМ12Я сказал:

Надо поставить что то посерединке.

А можно конкретнее?? Посерединке это куда?

 

В 15.02.2024 в 02:13, 1891ВМ12Я сказал:

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

А например? 

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


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

On 2/20/2024 at 8:23 AM, Worldmaster said:

А можно конкретнее?? Посерединке это куда?

Некий промежуточный модуль, у которого две и более пары SDA/SCL, и вручную явно управлять этими значениями, как одна линия влияет на другую. Еще вот можно встретить что SDA линию разбивают на in/out и на третий сигнал enable, то есть внешний буфер. С целью отладки и для гибкости.

 

Пример нештатный ситуаций, например внезапный обрыв пакета, внезапный repeated start, неверный уход в состояние sda=1 scl=1 не похожее на stop. Как пример.

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


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

В 29.02.2024 в 19:11, 1891ВМ12Я сказал:

Некий промежуточный модуль, у которого две и более пары SDA/SCL, и вручную явно управлять этими значениями, как одна линия влияет на другую.

Вы имеете ввиду модель? Я таких не нашел. Хотел по быстрому собрать i2c slave но такой корки не нашлось.

Если у вас есть такие модели то поделитесь пожалуйста

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


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

В 01.03.2024 в 16:57, Maverick_ сказал:

И первый и второй вариант пробовал но мне нужен slave. Чтобы отладить работу корки. 

Причем корка позволяет использовать адрес и 8 и 16 битный. И длину считывания тоже. А тут надо эти модули еще допиливать под себя. 

 

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


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

В 01.03.2024 в 21:56, Maverick_ сказал:

Возьмите плату на stm32 и организуйте обмен для отладки

Так я же писал уже что есть готовая плата где все работает. И подключенный анализатор сигналов. Когда модуль замыкается то в анализаторе пусто. Все сигналы старт и стоп соответствует. Данные также приходят. 

 

Стм то что тут решит. В идеале конечно и2ц слецв модель и в моделсим можно было бы покрутить. 

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


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

19 minutes ago, Worldmaster said:

Стм то что тут решит. В идеале конечно и2ц слецв модель и в моделсим можно было бы покрутить. 

тогда работа с описаниями по ссилкам

https://github.com/tirfil/VhdI2CSlave

https://github.com/murattcan/FPGA-I2C-Slave

можно поискать еще и включить в поиск модули на verilog кроме vhdl - уверен их много, просто я потратил на поиск 2 мин

PS возможна дополнительная работа напильником

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


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

В 02.03.2024 в 12:49, Worldmaster сказал:

 

 

Стм то что тут решит. В идеале конечно и2ц слецв модель и в моделсим можно было бы покрутить. 

Нет смысла i2c искать. Ничего приличного я не увидел. По мне или IP или свое. И корка тут скорее всего рабочая.

Проверить ведь просто. В тестбенче создать две сущности корки мастер и слеф и замкнуть друг на друга. Наверняка будут работать.

Особенность этого интерфейса в том, что сигналы на линии sda должны изменяться в момент времени когда на линии scl стоит ноль (в том числе с учетом арбитража), иначе корка уйдет в состояние старт или стоп. На Вашей осциллограме вроде бы ack выдается некорректно (фронтами  scl с sda бъются).

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


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

On 1/25/2024 at 2:55 PM, Worldmaster said:

Сделал модуль:

А чем Вас готовый и отлаженный модуль не устраивает?

Вот, например:

https://github.com/alexforencich/verilog-i2c

Сам я не любитель использовать чужой код, но этот модуль написан на мой взгляд весьма неплохо.

Использую его уже третий год в своих проектах - пока никаких проблем не было.

Да и документирован он довольно неплохо.

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


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

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

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

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

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

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

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

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

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

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