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

Скомутировать два вывода наружу.

Есть два мастер SPI которые пользуются общими пинами в TOP ENTITY

NewProject-1.png.cb82349ff41fe9d82ec054097aee86d5.png

Я могу сделать так

entity TOP is
port
(
    ADC_SS1    : out std_logic;
    ADC_SS2    : out std_logic;
    ADCS_SCLK  : out std_logic;
    ADCS_MOSI  : out std_logic;
    ADCS_MISO  : in std_logic 
);
end TOP;

U_ADC_1 : ADC 
port map
(	 
    CS    => ADC_SS1, 
    SCLK  => s_adc1_clk,
    MOSI  => s_mosi1_clk,
    MISO  => ADCS_MISO,	 
);

U_ADC_2 : ADC 
port map
(
    CS    => ADC_SS2, 
    SCLK  => s_adc2_clk,
    MOSI  => s_mosi2_clk,
    MISO  => ADCS_MISO
);


ADCS_SCLK <= s_adc1_clk or s_adc2_clk;
ADCS_MOSI <= s_mosi1_clk or s_mosi2_clk;

Но вот гложет меня сомнение правильно комутирировать с OR или есть более правильное решение?

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


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

Только что, jenya7 сказал:

Есть два мастер SPI которые пользуются общими пинами в TOP ENTITY

NewProject-1.png.cb82349ff41fe9d82ec054097aee86d5.png

Я могу сделать так


entity TOP is
port
(
    ADC_SS1    : out std_logic;
    ADC_SS2    : out std_logic;
    ADCS_SCLK  : out std_logic;
    ADCS_MOSI  : out std_logic;
    ADCS_MISO  : in std_logic 
);
end TOP;

U_ADC_1 : ADC 
port map
(	 
    CS    => ADC_SS1, 
    SCLK  => s_adc1_clk,
    MOSI  => s_mosi1_clk,
    MISO  => ADCS_MISO,	 
);

U_ADC_2 : ADC 
port map
(
    CS    => ADC_SS2, 
    SCLK  => s_adc2_clk,
    MOSI  => s_mosi2_clk,
    MISO  => ADCS_MISO
);


ADCS_SCLK <= s_adc1_clk or s_adc2_clk;
ADCS_MOSI <= s_mosi1_clk or s_mosi2_clk;

Но вот гложет меня сомнение правильно комутирировать с OR или есть более правильное решение?

Арбитр доступа которой рулит коллизиями, когда оба мастера хотят поиметь слейва.

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


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

9 minutes ago, Flip-fl0p said:

Арбитр доступа которой рулит коллизиями, когда оба мастера хотят поиметь слейва.

а как его сделать правильно?

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

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

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


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

35 minutes ago, jenya7 said:

Но вот гложет меня сомнение правильно комутирировать с OR или есть более правильное решение?

AND-OR мультиплексор вещь обычная и довольно часто используемая, но, т.к. тут есть два канала управления (которые маски), требуется обеспечить режим, чтобы оба мастера не могли быть активными. Если вы делаете это на административном уровне и у вас всегда, у выключенного мастера сигналы падают в 0, то вы все сделали верно. 

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


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

16 minutes ago, des00 said:

AND-OR мультиплексор вещь обычная и довольно часто используемая, но, т.к. тут есть два канала управления (которые маски), требуется обеспечить режим, что оба мастера не могут быть активными. 

что то вроде?

chip_sel <= ADC_SS2 & ADC_SS1;

case chip_sel is
  when "01" => ADCS_SCLK <= s_adc1_clk;
  when "10" => ADCS_SCLK <= s_adc2_clk;
  default =>
end case;  

 

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

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


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

35 minutes ago, jenya7 said:

что то вроде?


chip_sel <= ADC_SS2 & ADC_SS1;

case chip_sel is
  when "01" => ADCS_SCLK <= s_adc1_clk;
  when "10" => ADCS_SCLK <= s_adc2_clk;
  default =>
end case;  

 

ADCS_SCLK <= (s_adc1_clk and adc_ss1) or (s_adc2_clk and adc_ss2); - ложится в один LUT4, за это, в свое время, эту схему любили для широких мультиплексоров. 

(adc_ss1 =1) & (adc_ss2 = 1) естественно запрещенная ситуация. 

Если маски есть у вас внутри блоков ADC, то снаружи достаточно просто or 

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


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

4 minutes ago, des00 said:

ADCS_SCLK <= (s_adc1_clk and adc_ss1) or (s_adc2_clk and adc_ss2); - ложится в один LUT4, за это, в свое время, эту схему любили для широких мультиплексоров. 

(adc_ss1 =1) & (adc_ss2 = 1) естественно запрещенная ситуация. 

Если маски есть у вас внутри блоков ADC, то снаружи достаточно просто or 

тогда наверно так?

ADCS_SCLK <= (s_adc1_clk and not adc_ss1) or (not s_adc2_clk and adc_ss2);

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


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

2 minutes ago, jenya7 said:

тогда наверно так?

ADCS_SCLK <= (s_adc1_clk and not adc_ss1) or (not s_adc2_clk and adc_ss2);

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

но вот зачем инвертировать вторую тактовую я не понял) 

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


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

1 minute ago, des00 said:

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

но это всё равно не блокирует. я же могу оба CS опустить.

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


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

10 minutes ago, jenya7 said:

но это всё равно не блокирует. я же могу оба CS опустить.

эмм. Вы вообще не читаете мои ответы? 

Quote

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

(adc_ss1 =1) & (adc_ss2 = 1) естественно запрещенная ситуация. 

Если они у вас работают асинхронно, тогда ставьте арбитр включения модулей, любого типа: каруселька, раундробин, приоритетный. 

UPD. Именно арбитр включения модуля, а не мультиплексирования транзакции SPI. Т.к. SPI транзакцию рвать нельзя. Самое простое сделать сигнал Enable в модулях и уже ими управлять исходя из поступающих запросов на доступ к SPI. А для мультиплексирования, сделать все сигналы в пассивном состоянии 0. на верхнем уровне простой OR.

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


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

спасибо. буду думать над арбитром.

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

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

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


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

5 minutes ago, jenya7 said:

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

я бы сделал один SPI модуль и к нему приделал многоканальный арбитр доступа. Ну а сами источники транзакций пусть работают по простому valid & ready интерфейсу) А если ready не подразумевается в источниках транзакций, сами транзакции редкие, а запрос - импульс длительностью 1 такт, то просто захватываете его, на арбитр, как он получил доступ, сбрасываете его.  

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


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

1 hour ago, des00 said:

я бы сделал один SPI модуль и к нему приделал многоканальный арбитр доступа. Ну а сами источники транзакций пусть работают по простому valid & ready интерфейсу) А если ready не подразумевается в источниках транзакций, сами транзакции редкие, а запрос - импульс длительностью 1 такт, то просто захватываете его, на арбитр, как он получил доступ, сбрасываете его.  

спасибо. это идея. всё придется переделывать. :)

 

ну вот как то так получается

Spoiler

entity TOP is
port
(
     TOP_CLK    : in std_logic;
	 TOP_RST    : in std_logic := '0';
	  
	 ----------ADC SPI-----------
	 ADC_SS1    : out std_logic;
	 ADC_SS2    : out std_logic;
	 ADC_SS3    : out std_logic;
	 ADC_SS4    : out std_logic;
	 
	 ADCS_SCLK  : out std_logic;
	 ADCS_MOSI  : out std_logic;
	 ADCS_MISO  : in std_logic;
	 
	 LED_TEST   : out std_logic
);
end TOP;

architecture behavior of TOP is

  ------------------ADC---------------------------------
signal s_adc_cs_mask : std_logic_vector(3 downto 0);

signal s_adc_trig : std_logic;
signal s_adc_chan : std_logic_vector(2 downto 0);
signal s_adc_val  : std_logic_vector(15 downto 0);
signal s_rd_data : std_logic_vector(15 downto 0); 
signal s_wr_data : std_logic_vector(15 downto 0); 
signal s_wr_start_trig : std_logic;
signal s_wr_done : std_logic;
signal s_wr_done_clr : std_logic;

signal s_adc1_cs : std_logic;
signal s_adc1_trig : std_logic;
signal s_adc1_chan : std_logic_vector(2 downto 0);
signal s_adc1_val  : std_logic_vector(15 downto 0);
signal s_rd_data1 : std_logic_vector(15 downto 0); 
signal s_wr_data1 : std_logic_vector(15 downto 0); 
signal s_wr_start_trig1 : std_logic;
signal s_wr_done1 : std_logic;
signal s_wr_done_clr1 : std_logic;

signal s_adc2_cs : std_logic;
signal s_adc2_trig : std_logic;
signal s_adc2_chan : std_logic_vector(2 downto 0);
signal s_adc2_val  : std_logic_vector(15 downto 0);
signal s_rd_data2 : std_logic_vector(15 downto 0); 
signal s_wr_data2 : std_logic_vector(15 downto 0); 
signal s_wr_start_trig2 : std_logic;
signal s_wr_done2 : std_logic;
signal s_wr_done_clr2 : std_logic;

signal s_adc3_cs : std_logic;
signal s_adc3_trig : std_logic;
signal s_adc3_chan : std_logic_vector(2 downto 0);
signal s_adc3_val  : std_logic_vector(15 downto 0);
signal s_rd_data3 : std_logic_vector(15 downto 0); 
signal s_wr_data3 : std_logic_vector(15 downto 0); 
signal s_wr_start_trig3 : std_logic;
signal s_wr_done3 : std_logic;
signal s_wr_done_clr3 : std_logic;

signal s_adc4_cs : std_logic;
signal s_adc4_trig : std_logic;
signal s_adc4_chan : std_logic_vector(2 downto 0);
signal s_adc4_val  : std_logic_vector(15 downto 0);
signal s_rd_data4 : std_logic_vector(15 downto 0); 
signal s_wr_data4 : std_logic_vector(15 downto 0); 
signal s_wr_start_trig4 : std_logic;
signal s_wr_done4 : std_logic;
signal s_wr_done_clr4 : std_logic;

begin
  
s_adc_cs_mask <= s_adc4_cs & s_adc3_cs & s_adc2_cs & s_adc1_cs;

U_ADC_SPI_MASTER : GENERIC_SPI 
port map
(	 
    RST	    => '0',
    CLK     => TOP_CLK,
	 
    SPI_nCS       => '0',
    SPI_CLK       => ADCS_SCLK,
    SPI_MasterOut => ADCS_MOSI,
    SPI_MasterIn  => ADCS_MISO, 
		
    SPI_CTRL_REG   => "000", --bit0  = CPHA bit1  = CPOL bit2 = MSBnLSB_FIRST
    SPI_BAUD_DIV   => X"000C",  --120Mhz
    SPI_DATA_LENGTH   => '1', --0 = length of 8 bits --1 = 16 bit

    SPI_Wr_Data       => s_wr_data,
    SPI_Rd_Data       => s_rd_data, 
    SPI_Wr_Start_Trig => s_wr_start_trig,  
		
    SPI_Rd_Start_Trig  => '0',   
    SPI_Data_Ready	   => open,
    SPI_Data_Ready_Clear => '0', 
		
    SPI_Wr_DONE		  => s_wr_done,
    SPI_Wr_DONE_Clear => s_wr_done_clr,
		
    SPI_WR_En		 => open,		
    SPI_Data_Count   => open	                                           
);	

U_ADC_1 : ADC 
port map
(
    ADC_CLK  => TOP_CLK,
    ADC_RST  => TOP_RST,
	 
     CS          => s_adc1_cs, 
	 WR_DONE_CLR => s_wr_done_clr1,
	 WR_START    => s_wr_start_trig1, 
	 WR_DONE     => s_wr_done1,
	 
	 WR_DATA  => s_wr_data1,
	 RD_DATA  => s_rd_data1, 
	 
	 TRIG     => s_adc1_trig,
	 
	 CHAN     => s_adc_chan,
	
	 ADC_VAL  => s_adc1_val
);

U_ADC_2 : ADC 
port map
(
    ADC_CLK  => TOP_CLK,
	ADC_RST  => TOP_RST,
	 
	 CS           => s_adc2_cs,
	 WR_DONE_CLR  => s_wr_done_clr2,
	 WR_START     => s_wr_start_trig2, 
	 WR_DONE      => s_wr_done2,
	 
	 WR_DATA      => s_wr_data2,
	 RD_DATA      => s_rd_data2, 
	 
	 TRIG         => s_adc2_trig,
	 
	 CHAN         => s_adc_chan,
	
	 ADC_VAL     => s_adc2_val
);

U_ADC_3 : ADC 
port map
(
    ADC_CLK  => TOP_CLK,
	 ADC_RST  => TOP_RST,
	 
	 CS           => s_adc3_cs,
	 WR_DONE_CLR  => s_wr_done_clr3,
	 WR_START     => s_wr_start_trig3, 
	 WR_DONE      => s_wr_done3,
	 
	 WR_DATA      => s_wr_data3,
	 RD_DATA      => s_rd_data3, 
	 
	 TRIG         => s_adc3_trig,
	 
	 CHAN         => s_adc_chan,
	
	 ADC_VAL     => s_adc3_val
);

U_ADC_4 : ADC 
port map
(
    ADC_CLK  => TOP_CLK,
	 ADC_RST  => TOP_RST,
	 
	 CS           => s_adc4_cs,
	 WR_DONE_CLR  => s_wr_done_clr4,
	 WR_START     => s_wr_start_trig4, 
	 WR_DONE      => s_wr_done4,
	 
	 WR_DATA      => s_wr_data4,
	 RD_DATA      => s_rd_data4, 
	 
	 TRIG         => s_adc4_trig,
	 
	 CHAN         => s_adc_chan,
	
	 ADC_VAL     => s_adc4_val
);


process (TOP_CLK)
begin

    if (rising_edge(TOP_CLK)) then
	     
        case s_adc_cs_mask is
		  
            when "1110" =>
		       ADC_SS1 <= s_adc1_cs;
			   s_wr_data <= s_wr_data1;
			   s_rd_data <= s_rd_data1;
			   s_wr_start_trig <= s_wr_start_trig1;
			   s_wr_done <= s_wr_done1;
			   s_wr_done_clr <= s_wr_done_clr1;
					 
			when "1101" =>
				ADC_SS2 <= s_adc2_cs;
				s_wr_data <= s_wr_data2;
				s_rd_data <= s_rd_data2;
				s_wr_start_trig <= s_wr_start_trig2;
				s_wr_done <= s_wr_done2;
				s_wr_done_clr <= s_wr_done_clr2;
				
		     when "1011" =>
				ADC_SS3 <= s_adc3_cs;
				s_wr_data <= s_wr_data3;
				s_rd_data <= s_rd_data3;
				s_wr_start_trig <= s_wr_start_trig3;
				s_wr_done <= s_wr_done3;
				s_wr_done_clr <= s_wr_done_clr3;
					 
			  when "0111" =>
				  ADC_SS4 <= s_adc4_cs;
				  s_wr_data <= s_wr_data4;
				  s_rd_data <= s_rd_data4;
				  s_wr_start_trig <= s_wr_start_trig4;
				  s_wr_done <= s_wr_done4;
				  s_wr_done_clr <= s_wr_done_clr4;
					 
			   when others =>
				   ADC_SS1 <= '1';
					ADC_SS2 <= '1';
					ADC_SS3 <= '1';
					ADC_SS4 <= '1';
				    s_wr_start_trig <= '0';
					 
		  end case;
		  
		   
	 end if;

end process;

end behavior;  
  
  

 

 

Так нормально?

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

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


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

Я возможно странный вопрос задам, однако : Чем обусловлено наличие двух независимых мастеров в ПЛИС, которые даже не знают о существовании друг друга, то есть не могут договориться об очередности доступа к слейву программно?

Может тут надо на системном уровне в начале проблемы порешать?

 

З Ы Вы конечно можете реализовать честный арбитр, который реализует данную схему доступа, но при этом вам придется добавить интерфейс между мастерами и арбитром (добавить сигналы REQ и GNT в каждый инстанс мастера и "научить" мастера начинать транзакцию только после получения ответа от арбитра. Не такая уж сложная штука вроде бы, но об этом надо помнить.

 

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


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

4 hours ago, Bad0512 said:

Я возможно странный вопрос задам, однако : Чем обусловлено наличие двух независимых мастеров в ПЛИС, которые даже не знают о существовании друг друга, то есть не могут договориться об очередности доступа к слейву программно?

Может тут надо на системном уровне в начале проблемы порешать?

 

З Ы Вы конечно можете реализовать честный арбитр, который реализует данную схему доступа, но при этом вам придется добавить интерфейс между мастерами и арбитром (добавить сигналы REQ и GNT в каждый инстанс мастера и "научить" мастера начинать транзакцию только после получения ответа от арбитра. Не такая уж сложная штука вроде бы, но об этом надо помнить.

 

 действительно. что то я погнал не в ту степь.  опустил CS слейва и общайся с ним. весь арбитраж - общий enable который активный при условии что только один CS опущен.

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

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


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

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

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

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

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

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

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

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

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

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