Jump to content
    

Непонятки с модулем 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 но почему он затыкается то мне не понятно.

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

Спасибо.

 

 

 

 

 

 

 

 

 

 

Share this post


Link to post
Share on other sites

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

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

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

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

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

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

 

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

Share this post


Link to post
Share on other sites

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

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

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

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

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

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

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

Share this post


Link to post
Share on other sites

В 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

Edited by Worldmaster

Share this post


Link to post
Share on other sites

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

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

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

Share this post


Link to post
Share on other sites

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

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

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

 

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

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

А например? 

Share this post


Link to post
Share on other sites

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

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

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

 

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

Share this post


Link to post
Share on other sites

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

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

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

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

Share this post


Link to post
Share on other sites

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

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

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

 

Share this post


Link to post
Share on other sites

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

Share this post


Link to post
Share on other sites

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

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

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

 

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

Share this post


Link to post
Share on other sites

19 minutes ago, Worldmaster said:

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

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

https://github.com/tirfil/VhdI2CSlave

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

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

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

Share this post


Link to post
Share on other sites

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

 

 

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

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

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

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

Share this post


Link to post
Share on other sites

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

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

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

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

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

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

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

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

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...