Results 1 to 7 of 7

Thread: Using a SPI module.

  1. #1
    Join Date
    Jan 2009
    Posts
    72
    Rep Power
    1

    Default Using a SPI module.

    I have a SPI module.
    Code:
    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;
    But how do I actually use it?
    In order to write to it I should load some data to SPI_Wr_Data and apply high signal to SPI_Wr_Start_Trig.
    When the trigger applied the data shifted out on SPI_MasterOut pin.
    SPI_Wr_Data <= "10010000";
    triger <= '1';
    SPI_Wr_Start_Trig<= triger ;
    The question is - when I clear SPI_Wr_Start_Trig? i.e triger=0; SPI_Wr_Start_Trig <= triger.
    Or let me paraphrase how I write several bytes?

  2. #2
    Tricky is offline Moderator **Forum Master**
    Join Date
    Oct 2008
    Posts
    5,651
    Rep Power
    1

    Default Re: Using a SPI module.

    You should read the documentation provided with the core.
    If you dont have documentation, then find another core, or investigate how this one works.
    Where did you get this code from?

  3. #3
    Join Date
    Jan 2009
    Posts
    72
    Rep Power
    1

    Default Re: Using a SPI module.

    Hi Tricky,
    Let me put it this way - do you have any working SPI module? If so - can you provide a practical example how to use it?
    I don't know the origin of SPI core I provided but I know for sure it's a working code cause it was used before. No I can't look at the previous use of the module - i don't have it.

  4. #4
    Join Date
    Jan 2009
    Posts
    72
    Rep Power
    1

    Default Re: Using a SPI module.

    Suppose I have an SPI module. SPI_Wr_Data is a byte to send (8 bit). SPI_Wr_Start_Trig is a trigger to start byte transfer. How should I implement user logic to send several bytes?

  5. #5
    Tricky is offline Moderator **Forum Master**
    Join Date
    Oct 2008
    Posts
    5,651
    Rep Power
    1

    Default Re: Using a SPI module.

    Quote Originally Posted by john7 View Post
    Suppose I have an SPI module. SPI_Wr_Data is a byte to send (8 bit). SPI_Wr_Start_Trig is a trigger to start byte transfer. How should I implement user logic to send several bytes?
    If you have no documentation - I suggest finding a core that does have documentation and probably a testbench.
    From a brief look at this code, wr_start_trig starts sending a single byte. So for several bytes you just assert wr_start_trig at the start of every byte.

  6. #6
    Join Date
    Jan 2009
    Posts
    72
    Rep Power
    1

    Default Re: Using a SPI module.

    I see. Thank you. I thought so. Is it right to do so?

    --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...

  7. #7
    Tricky is offline Moderator **Forum Master**
    Join Date
    Oct 2008
    Posts
    5,651
    Rep Power
    1

    Default Re: Using a SPI module.

    Steps for success:
    1. Write your user logic
    2. Write a testbench containing your user logic and the SPI module
    3. test and debug
    4. ????
    5. Profit!!

Similar Threads

  1. Replies: 1
    Last Post: January 14th, 2017, 06:17 AM
  2. Instantiation of one module disturbing other module functionality
    By madhu.mami60 in forum Verilog and System Verilog
    Replies: 1
    Last Post: March 17th, 2015, 12:55 AM
  3. Zero total logic elements for top module instantiate lower module
    By jasonjinct in forum Quartus II and EDA Tools Discussion
    Replies: 4
    Last Post: March 11th, 2014, 12:28 AM
  4. How to carryout the data from one module to other module within the project
    By prasanna_37 in forum Verilog and System Verilog
    Replies: 0
    Last Post: January 21st, 2014, 03:58 AM
  5. Mercury CA1 module enclustra Altera Cyclone IV E FPGA Module
    By _franz in forum General Altera Discussion
    Replies: 4
    Last Post: July 4th, 2011, 03:56 AM

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •