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

VHDL. Использование SPI модуля.

Что то я запутался. У меня есть SPI модуль.

entity GENERIC_SPI is
port(
	RST			:In Std_logic                     ; --Main DSP system reset.
	CLK                 :In Std_logic                 	; --DSP MAin Clock to be divided.

	SPI_nCS            :In   Std_logic ;
	SPI_CLK            :Out  Std_logic;
	SPI_MasterOut	:Out  Std_logic;
	SPI_MasterIn	 :In  Std_logic;

	SPI_CTRL_REG      :In   Std_logic_vector(2 downto 0) ;--bit0  = CPHA bit1  = CPOL bit2  = MSBnLSB_FIRST
	SPI_BAUD_DIV       :In   Std_logic_vector(15 downto 0) ;
	SPI_DATA_LENGTH    :In   Std_logic ;

	SPI_Wr_Data        :In  Std_logic_vector(15 downto 0)  ;   --Signal coming from REG_FILE SMI_Wr_Data_Reg
	SPI_Rd_Data        :Out  Std_logic_vector(15 downto 0) ;   --Signal going to REG_FILE
	SPI_Wr_Start_Trig  :In Std_logic  ;   --DSP MAin Clock to be divided.

	SPI_Rd_Start_Trig  	:In Std_logic            ;   --DSP MAin Clock to be divided.
	SPI_Data_Ready	:Out   Std_logic ;
	SPI_Data_Ready_Clear:In   Std_logic ;

	SPI_Wr_DONE		:Out   Std_logic ;
	SPI_Wr_DONE_Clear	:In   Std_logic ;

	SPI_WR_En		:Out   Std_logic 	;	
	SPI_Data_Count        :Out  Std_logic_vector(15 downto 0)  

	--SPI_Counter_Reset   :In   Std_logic                                              
 );
end GENERIC_SPI;

architecture STRUCTURE of GENERIC_SPI is

Signal CLK_DIV     :Std_logic_vector(15 downto 0) := (others=>'0');
Signal CLK_RISE    :Std_logic := '0';
Signal CLK_FALL    :Std_logic := '0';

Signal CLK_EN    :Std_logic := '0';
Signal CLK_EN_ACTIVE_Trig    :Std_logic := '0';
Signal CLK_EN_FALL_COUNTER   :Std_logic_vector(3 downto 0)  := (others=>'0');

Signal ShiftCount  :Std_logic_vector(3 downto 0)  := (others=>'0');

Signal SPI_CLK_reg :Std_logic := '0';  
Signal SPI_RdnWr     :Std_logic := '0';
Signal SPI_Z_Out     :Std_logic := '0';
Signal SPI_Start_Trig_d     :Std_logic := '0';

Signal SPI_SIO_out     :Std_logic := '0';

Signal SPI_Wr_Data_ShiftReg         :Std_logic_vector(15 downto 0)  ;   --Shift Reg for parallel2Serial COnversion of  Data(MSB First)
Signal SPI_Rd_Data_ShiftReg          :Std_logic_vector(15 downto 0) ;   --Shift Reg for Serial2parallel COnversion of  Data recived from switchdevice(MSB First)

Signal SPI_Data_Count_reg        : Std_logic_vector(15 downto 0)  := (others=>'0');

Signal SPI_nCS_reg     :Std_logic := '0';  
Signal Next_Clk_FALL_nRAISE :Std_logic := '0';

Signal CPHA     :Std_logic := '0';  
Signal CPOL     :Std_logic := '0';  
Signal MSBnLSB_FIRST     :Std_logic := '0';  
Signal Pos_Clk_Out      :Std_logic := '0';  
Signal Neg_Clk_Out      :Std_logic := '0';  

       Signal SPI_DATA_LENGTH_DEF     :Std_logic_vector(3 downto 0) := (others=>'0');

Type StateType is (ST_Idle,ST_WAIT_FOR_FALL,ST_FIRST_LOAD,ST_WAIT_FOR_LOAD,ST_WAIT_FOR_SAMP,ST_END
_SAMP_REG);
Signal State   :StateType;

begin

CPHA			<=	SPI_CTRL_REG(0)		;
CPOL			<=	SPI_CTRL_REG(1)		;
MSBnLSB_FIRST	<=	SPI_CTRL_REG(2)		;
SPI_Data_Count 	<= SPI_Data_Count_reg	;
SPI_WR_En		<= '0'					;--Not in use yet 
SPI_Data_Ready  <= '0'					;--Not in use yet 

   process (SPI_DATA_LENGTH,SPI_Wr_Data_ShiftReg) begin 
     if (SPI_DATA_LENGTH='0') then 
	SPI_DATA_LENGTH_DEF <=X"7" ;
     	SPI_MasterOut <= SPI_Wr_Data_ShiftReg(7);			
     else 
	SPI_DATA_LENGTH_DEF <=X"F" ; 
     	SPI_MasterOut <= SPI_Wr_Data_ShiftReg(15);
     end if;
   end process;

process (CLK,RST) begin 
	if (RST='1') then 		         
		Pos_Clk_Out <='0' ; 
		Neg_Clk_Out <='1' ; 
	elsif (CLK'event and CLK='1') then
		if (CLK_EN='1') then 
			Pos_Clk_Out <=SPI_CLK_reg ;
			Neg_Clk_Out <=not(SPI_CLK_reg) ;
		else 
			Pos_Clk_Out <='0' ; 
			Neg_Clk_Out <='1' ; 
		end if;
	end if;
end process;

process (CPOL,Pos_Clk_Out,Neg_Clk_Out) begin 
	if (CPOL='0') then 
     		SPI_CLK <=Pos_Clk_Out ;
	else 
     		SPI_CLK <=Neg_Clk_Out ; 
	end if;
   end process;    

 process (CLK,RST) begin
if (RST='1') then 		   
 		CLK_EN <= '0';
 		CLK_EN_FALL_COUNTER <= (others=>'0');
elsif (CLK'event and CLK='1') then
       if (CLK_EN_ACTIVE_Trig = '1'	)then
       	CLK_EN <= '1';
       	CLK_EN_FALL_COUNTER <= X"0";
 		end if;
 		if ( (CLK_FALL = '1')and (CLK_EN = '1') )then
  		CLK_EN_FALL_COUNTER <= (CLK_EN_FALL_COUNTER +1);
 			if (CLK_EN_FALL_COUNTER = SPI_DATA_LENGTH_DEF	)then
  			CLK_EN <= '0';
  			CLK_EN_FALL_COUNTER <= (others=>'0');
		end if;			
 		end if;			      	
end if;
 end process;   

 ----------------------------------------------------------
-- Clock Divider, Generates CLK_RISE,CLK_FALL signals
process (CLK,RST) begin--reset changed to be asynchronus not like in a2d module.
	if (RST='1') then
		CLK_DIV 	<= (others=>'0'); --reset changed to be asynchronus not like in a2d module.
    	    SPI_CLK_reg	<= '0'; -- Keep CLK = '0'---might changed not like d2a	
    		CLK_RISE 	<= '0';
    		CLK_FALL 	<= '0';
    		Next_Clk_FALL_nRAISE <= '0';
	elsif (CLK'event and CLK='1') then
		CLK_DIV <= CLK_DIV + 1;
	if (CLK_DIV = SPI_BAUD_DIV	) then 
		CLK_DIV 				<= (others=>'0');
      		SPI_CLK_reg <= not(SPI_CLK_reg);
      		Next_Clk_FALL_nRAISE <= not(Next_Clk_FALL_nRAISE);
		if (Next_Clk_FALL_nRAISE  = '0') then 
			CLK_RISE <= '1';
		elsif  (Next_Clk_FALL_nRAISE  = '1')	then 
			CLK_FALL <= '1';
		end if;
	else 	
      		CLK_RISE <= '0';
      		CLK_FALL <= '0'; 
	end if;
 end if;
 end process;

 ----------------------------------------------------------

process (CLK,RST) begin 
	if (RST='1') then
		State <= ST_Idle;
		CLK_EN_ACTIVE_Trig	<= '0';
		SPI_Rd_Data		<= (others=>'0') ;-- update output when idle 
		ShiftCount   	<= (others=>'0');--Load value of 15 to hiftCount because address word to send is 14 bit (without TA)
		SPI_Wr_Data_ShiftReg <= (others=>'0');
		SPI_Rd_Data_ShiftReg <= (others=>'0');
		SPI_Wr_DONE 	<= '0';
		SPI_Data_Count_reg	<= (others=>'0') ;
	   -- SPI_MasterOut	   <= '0'	;
	elsif (CLK'event and CLK='1') then

       case State is
          --------------------------------
	     When ST_Idle =>
			CLK_EN_ACTIVE_Trig	<= '0';
			--SPI_Rd_Data<=SPI_Rd_Data_ShiftReg ;-- update output when idle 
			ShiftCount   <= (others=>'0');--Load value of 15 to hiftCount because address word to send is 14 bit (without TA)
			SPI_Rd_Data_ShiftReg	<= (others=>'0');
			SPI_Wr_Data_ShiftReg	<= (others=>'0');

			if (SPI_Wr_Start_Trig = '1') then
				State <= ST_WAIT_FOR_FALL;
				SPI_Wr_Data_ShiftReg<=SPI_Wr_Data;--//load data
				--Counter <= 0XXXX000	
			end if;  

			if (SPI_Wr_DONE_Clear = '1') then
				SPI_Wr_DONE 	<= '0';
				--Counter <= 0XXXX000	
			end if;  

			 When ST_WAIT_FOR_FALL =>
			 	CLK_EN_ACTIVE_Trig	<= '0';
	    	if(CLK_FALL = '1') then
	    		CLK_EN_ACTIVE_Trig	<= '1';	
	    		if(CPHA = '0')then
					State   <= ST_WAIT_FOR_SAMP;
					SPI_Wr_Data_ShiftReg <= SPI_Wr_Data;
					ShiftCount  <= (others=>'0');
					State <= ST_FIRST_LOAD;    
			   		end if;
			   	end if;	

			 When ST_FIRST_LOAD =>
			 	CLK_EN_ACTIVE_Trig	<= '0';
	    	if(((CPHA = '1') and (CLK_RISE = '1'))) then   		
				State   <= ST_WAIT_FOR_SAMP;	
				SPI_Wr_Data_ShiftReg <= SPI_Wr_Data;

				ShiftCount  <= (others=>'0');
			   	end if;
			if	(CLK_FALL = '1')then
			   		CLK_EN_ACTIVE_Trig	<= '1';	
			end if;		

	    When ST_WAIT_FOR_LOAD =>
	    	CLK_EN_ACTIVE_Trig	<= '0';
	    	if( ((CPHA = '0') and (CLK_FALL = '1')) or ((CPHA = '1') and (CLK_RISE = '1')) ) then		   		
			State   <= ST_WAIT_FOR_SAMP;
			SPI_Wr_Data_ShiftReg <= SPI_Wr_Data_ShiftReg(14 downto 0) & '0';--//--if 8 bit the output would be from bit 7 

			 end if;

     		When ST_WAIT_FOR_SAMP =>
     			CLK_EN_ACTIVE_Trig	<= '0';
     			if( ((CPHA = '0') and ( CLK_RISE= '1')) or   ((CPHA = '1') and (CLK_FALL = '1')) )    then
     				State  <= ST_WAIT_FOR_LOAD;
     				SPI_Rd_Data_ShiftReg <=SPI_Rd_Data_ShiftReg (14 downto 0) & SPI_MasterIn ; --insted of 0ne would be data.

     				if (ShiftCount  = SPI_DATA_LENGTH_DEF)then	
     					State   <= ST_END_SAMP_REG;
     				else  
     					ShiftCount  <= ShiftCount + 1;	
     				end if;	
     				--read data
         		end if; 	

		When ST_END_SAMP_REG =>
     			CLK_EN_ACTIVE_Trig	<= '0';
     			State   <= ST_Idle;
     			SPI_Rd_Data<=SPI_Rd_Data_ShiftReg ;-- update data 
     			SPI_Data_Count_reg <= SPI_Data_Count_reg +1;
     			SPI_Wr_DONE <= '1';

        end case;
      end if;

 end process;
end STRUCTURE;

Я хочу к нему подключиться и говорить с внешним прибором.

Я создал еще один модуль для реализации логики.

 entity SPI_CAN is
port(
	SPI_CAN_RST		 :In Std_logic;  --Main DSP system reset.
	SPI_CAN_GCLK     :In Std_logic; --DSP MAin Clock to be divided.

	SPI_CAN_WR_DATA   :out  Std_logic_vector(15 downto 0);  --write data to SPI
	SPI_CAN_RD_DATA   :in Std_logic_vector(15 downto 0);    --read data from SPI
	SPI_CAN_WR_START_TRIG :in  Std_logic;  

	SPI_CAN_WR_DONE :out Std_logic;
	SPI_CAN_WR_DONE_CLEAR :in Std_logic
 );
end SPI_CAN;

И делаю мап между модулями.

U_GENERIC_SPI : GENERIC_SPI port map(
    -------------------------------------------
    RST        =>     SPI_CAN_RST,
    CLK               =>   SPI_CAN_GCLK,
                  
    SPI_nCS             =>   CAN_CS,
    SPI_CLK             =>   CAN_CLK,
    SPI_MasterOut    =>   CAN_SDO,
    SPI_MasterIn         =>   CAN_SDI,
                            
    SPI_CTRL_REG               => "000",           --SPI_CTRL_REG <= "000";    --bit0  = CPHA bit1  = CPOL bit2  = MSBnLSB_FIRST
    SPI_BAUD_DIV            => X"000F",
    SPI_DATA_LENGTH         => '0',             --SPI_DATA_LENGTH , 0 = length of 8 bits
                    
    SPI_Wr_Data            =>  SPI_CAN_WR_DATA,
    SPI_Rd_Data             =>  SPI_CAN_RD_DATA,
    SPI_Wr_Start_Trig       =>  SPI_CAN_WR_START_TRIG,
                      
    SPI_Rd_Start_Trig          =>    '0',  --not in use read wsing write
    SPI_Data_Ready            =>    open, --not in use yet 
    SPI_Data_Ready_Clear    =>    '0',  --not in use yet 
                     
    SPI_Wr_DONE        =>    SPI_CAN_WR_DONE, 
    SPI_Wr_DONE_Clear    =>    SPI_CAN_WR_DONE_CLEAR, 
                    
    SPI_WR_En        =>     open,    --not in use yet 
    SPI_Data_Count      =>   open                                                             
  );

Получаю ошибку

actual port "SPI_CAN_WR_DATA" of mode "out" cannot be associated with formal port "SPI_Wr_Data" of mode "in"

В чем криминал? Соединяю выход на вход, все честно.

post-71075-1486280170_thumb.png

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

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


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

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

Сделайте например так для каждого соединения:

...
architecture ...
...
signal SPI_CAN_WR_DATA_s:std_logic_vector(15 downto 0);
....
begin
COMPONENT1:NAME
port map
(
   ...
   SPI_Wr_Data            =>  SPI_CAN_WR_DATA_s,
   ...
);


component2:name
port map
(
...
SPI_CAN_WR_DATA =>  SPI_CAN_WR_DATA_s,
);

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


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

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

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

 

у меня есть пример.

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
ENTITY arthur IS
PORT(
clk : IN STD_LOGIC; --clock input
enbl : IN STD_LOGIC; --enable for arthur
adv : IN STD_LOGIC; --advance the state
pulse : OUT STD_LOGIC; --pulse the dog collar
open_door : OUT STD_LOGIC --output to door driver
);
END arthur;

ARCHITECTURE struct OF arthur IS
SIGNAL ask_me : STD_LOGIC; --barney asks elmo
SIGNAL clear : STD_LOGIC; --elmo clears request to ask
COMPONENT barney PORT(clk : IN STD_LOGIC;
enable : IN STD_LOGIC;
adv : IN STD_LOGIC;
clear : IN STD_LOGIC;
outa : OUT STD_LOGIC;
ask_me : OUT STD_LOGIC
);
END COMPONENT;
COMPONENT elmo PORT(ask_me : IN STD_LOGIC;
go : OUT STD_LOGIC;
clear : OUT STD_LOGIC
);
END COMPONENT;
BEGIN
U1 : barney PORT MAP(clk => clk,
enable => enbl,
adv => adv,
clear => clear,
outa => pulse,
ask_me => ask_me
);
U2 : elmo PORT MAP(ask_me => ask_me,
go => open_door,
clear => clear
);
END struct;

как мы видим выход ask_me от barney одключается напрямую ко входу ask_me от elmo.

post-71075-1486288308_thumb.png

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

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


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

Для "внутренних" соединений используются сигналы. Если у компонента порт выходит сразу наружу (неважно вход, выход или двунаправленный) то его можно сразу назначать в карте соединений.

как мы видим выход ask_me от barney одключается напрямую ко входу ask_me от elmo.

А то что этим выходам назначены и одноименные сигналы Вы не наблюдаете?

SIGNAL ask_me : STD_LOGIC; --barney asks elmo

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


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

Для "внутренних" соединений используются сигналы. Если у компонента порт выходит сразу наружу (неважно вход, выход или двунаправленный) то его можно сразу назначать в карте соединений.

 

А то что этим выходам назначены и одноименные сигналы Вы не наблюдаете?

SIGNAL ask_me : STD_LOGIC; --barney asks elmo

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

то есть если я правильно понял то соединение двух компонентов такое?

(component 1 ) PIN/PORT OUT -> signal -> PIN/PORT IN (component 2)

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

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


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

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

Тут конечно можно о стиле долго рассуждать.

У себя в проектах всегда добавляю "суффиксы":_v - переменная, _s - сигнал, _с - константа.

то есть если я правильно понял то соединение двух компонентов такое?

(component 1 ) PIN/PORT OUT -> signal -> PIN/PORT IN (component 2)

Да правильно.

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


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

Тут конечно можно о стиле долго рассуждать.

У себя в проектах всегда добавляю "суффиксы":_v - переменная, _s - сигнал, _с - константа.

 

Да правильно.

спасибо.

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


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

честно говоря я не очень понимаю как использовать SPI модуль.

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

то есть нужно сделать что то вроде

SPI_Wr_Data <= "10010000";

triger <= '1';

SPI_Wr_Start_Trig<= triger ;

вопрос когда опустить тригер? или другими словами - как послать несколько байт?

 

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


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

Сделайте конечный автомат, который будет "дергать" нужные выводы Ваших компонентов.

Для начала можете задействовать простой счетчик с дешифратором: совпал код - формируем сигнал записи.

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


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

Сделайте конечный автомат, который будет "дергать" нужные выводы Ваших компонентов.

Для начала можете задействовать простой счетчик с дешифратором: совпал код - формируем сигнал записи.

Я не понимаю когда сигнал записи рисетовать. В каком кейсе автомата. Я не очень искушен в VHDL. Не понимаю еще как правильно.

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


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

Я не понимаю когда сигнал записи рисетовать. В каком кейсе автомата. Я не очень искушен в VHDL. Не понимаю еще как правильно.

Могу рассказать "Как"...

 

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


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

Я не понимаю когда сигнал записи рисетовать. В каком кейсе автомата. Я не очень искушен в VHDL. Не понимаю еще как правильно.

Тут многое от построения зависит, но в общих чертах:

делаем счетчик от 0 до 15 (или другого значения);

пишем "дешифратор" который будет каждое состояние счетчика сравнивать с константами, например счетчик досчитал до 3, проводим действие (установили сигнал), дошел счетчик до 5 - сбросили сигнал. И так далее.

 

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


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

Могу рассказать "Как"...

был бы очень признателен.

 

Тут многое от построения зависит, но в общих чертах:

делаем счетчик от 0 до 15 (или другого значения);

пишем "дешифратор" который будет каждое состояние счетчика сравнивать с константами, например счетчик досчитал до 3, проводим действие (установили сигнал), дошел счетчик до 5 - сбросили сигнал. И так далее.

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

 

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

--first byte
SPI_Wr_Data <= "00000001";
trigger <= '1';
SPI_Wr_Start_Trig <= trigger;
--??? delay?
trigger <= '0';
SPI_Wr_Start_Trig <= trigger;
--second byte
SPI_Wr_Data <= "00000011";
trigger <= '1';
SPI_Wr_Start_Trig <= trigger;
trigger <= '0';
SPI_Wr_Start_Trig <= trigger;
--and so on...

но это конечно не по-vhdl-овски.

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


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

был бы очень признателен.

Ну так пообщайтесь в скайпе - Вам уже руку помощи предложили, неужто надо этой рукой Вас за шиворот к монитору притянуть?

 

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

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

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


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

Ну так пообщайтесь в скайпе - Вам уже руку помощи предложили, неужто надо этой рукой Вас за шиворот к монитору притянуть?

 

 

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

понял. ModelSim я уже качаю.

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


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

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

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

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

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

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

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

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

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

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