⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i2cslave.vhd

📁 DesignWave 2005 8 Verilog Example
💻 VHD
字号:
--------------------------------------------------------------------------------
-- i2cSlave (i2c Slave Unit)
-- Takashi Kohno (DigiCat)
-- Rev. 0.5.0c  / 20, Jun., 2005
--
----------------------------------------
--
-- Copyright (c)   2005   Takashi Kohno
-- This design is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- as published by the Free Software Foundation; either version 2
-- of the License, or any later version.
--
-- This design is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to the Free Software
-- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
--
--------------------------------------------------------------------------------
library IEEE ;
use IEEE.std_logic_1164.all ;
use IEEE.std_logic_arith.all ;

use WORK.i2cBasics.all ;

entity i2cSlave is
	port(	CLK, nRST, syncRST	: in std_logic ;
			CKE					: in std_logic ;  -- CLK enable for sampling clock
			
			-- i2c bus
			SCL, SDA			: in std_logic ;
			slvSCL, slvSDA		: out std_logic ;

			-- Local bus for slave functions
			-- Transaction detection
			SReq				: out std_logic ;
			Si2cAdrs			: out std_logic_vector(6 downto 0) ;
			SRnW				: out std_logic ;
			SAck				: in std_logic ;
			
			-- Slave write stream
			SwrDReq				: out std_logic ;
			SwrData				: out std_logic_vector(7 downto 0) ;
			SwrTerm				: in std_logic ;
			SwrDRdy				: in std_logic ;
			
			-- Slave read stream
			SrdDReq				: out std_logic ;
			SrdData				: in std_logic_vector(7 downto 0) ;
			SrdDRdy				: in std_logic ;

			-- Status Reports
			srpTerm				: out std_logic ;
			srpAbort			: out std_logic ;
			srpBFree			: out std_logic ;
			srpBObsc			: out std_logic ;

			-- Timing Parameters
			Dsup				: in std_logic_vector(1 downto 0)
			) ;
end i2cSlave ;



architecture RTL of i2cSlave is

-- component I/F signals
-- for i2cStDec
signal BSQ				: i2cBusState ;
signal BoSCH			: std_logic ;
signal EoSCH			: std_logic ;
signal STAC				: std_logic ;
signal STPC				: std_logic ;
signal ReceivedData		: std_logic_vector(7 downto 0) ;
signal FirstSBit		: std_logic ;
signal LastSBit			: std_logic ;
signal vSCL, vSDA		: std_logic ;
signal BFree, BObsc		: std_logic ;


-- Signals for i2cSlave
type SlaveFunctionState is (slvIdle, slvQuery, slvTr) ;
signal SQ				: SlaveFunctionState ;

type SlaveDTrState is (slvDTrIdle, slvDTrReq, slvDTrWait, slvDTrSetup, slvLoadSDA) ;
signal SDTQ				: SlaveDTrState ;

type SlaveDRcState is (slvDRcIdle, slvDRcReq0, slvDRcReq1, slvDRcWait) ;
signal SDRQ				: SlaveDRcState ;

signal regSRnW			: std_logic ;
signal slvDTR			: std_logic_vector(7 downto 0) ; -- Shift Reg. for Data Transmitter
signal slvDsupCntr		: std_logic_vector(1 downto 0) ; -- setup timer counter for delayed data
signal iSrdDReq			: std_logic ;  -- SrdDReq for internal reference
signal regSwrTerm		: std_logic ;  -- checks SWrTerm while 2clocks after rising_edge(SwrDReq)


begin

-- Component instantiations:
	slvStDecUnit: i2cStDec
		port map(	CLK => CLK, nRST => nRST, syncRST => syncRST,
					CKE => CKE,
					SCL => SCL, SDA => SDA,
					BSQ => BSQ,
					BoSCH => BoSCH,
					EoSCH => EoSCH,
					STAC => STAC,
					STPC => STPC,
					ReceivedData => ReceivedData,
					FirstSBit => FirstSBit,
					LastSBit => LastSBit,
					vSCL => vSCL, vSDA => vSDA,
					BFree => BFree, BObsc => BObsc
					) ;




---------------------------------------------------------------------------------------------------
-- Transaction detector
---------------------------------------------------------------------------------------------------
	-- Root sequencer for slave functions
	SlaveFuncitionRootSeq: process(CLK, nRST)
	begin
		if nRST = '0' then
			SQ <= slvIdle ;
		elsif rising_edge(CLK) then
			if syncRST = '1' then
				SQ <= slvIdle ;
			else
				case SQ is
					when slvIdle =>
						if BSQ = ATR and LastSBit = '1' then
							if BoSCH = '1' then
								SQ <= slvQuery ;
							end if ;
						end if ;
					when slvQuery =>
						if SAck = '1' then
							SQ <= slvTr ;
						elsif EoSCH = '1' then
							SQ <= slvIdle ;
						end if ;
					when slvTr =>
						if STPC = '1' or STAC = '1' then
							SQ <= slvIdle ;
						end if ;
					when others =>
						SQ <= slvIdle ;
				end case ;
			end if ;
		end if ;
	end process ;

	-- Holds the direction of current transaction
	SlaveTrDirHolder: process(CLK, nRST)
	begin
		if nRST = '0' then
			regSRnW <= '0' ;
		elsif rising_edge(CLK) then
			if syncRST = '1' then
				regSRnW <= '0' ;
			elsif SQ /= slvTr then
				regSRnW <= ReceivedData(0) ;
			end if ;
		end if ;
	end process ;

	-- Slave query I/F
	SReq <= '1' when SQ = slvQuery else
			'0' ;
	Si2cAdrs <= ReceivedData(7 downto 1) ;
	SRnW <= ReceivedData(0) ;


---------------------------------------------------------------------------------------------------
-- SCL and SDA driver
---------------------------------------------------------------------------------------------------
	slvSCL <= '0' when SDTQ = slvDTrWait or SDTQ = slvDTrSetup or SDTQ = slvLoadSDA or SDRQ = slvDRcWait else
			  '1' ;

	SlaveSDADriver: process(CLK, nRST)
	begin
		if nRST = '0' then
			slvSDA <= '1' ;
		elsif rising_edge(CLK) then
			if syncRST = '1' then
				slvSDA <= '1' ;
			elsif SQ = slvTr then
				case BSQ is
					when ATR =>  			-- Generates Ack
						if LastSBit = '1' and EoSCH = '1' then
							slvSDA <= '0' ;
						end if ;
					when ACK =>
						if EoSCH = '1' then
							if regSRnW = '1' and iSrdDReq = '0' then
								slvSDA <= slvDTR(7) ;
							else
								slvSDA <= '1' ;
							end if ;
						end if ;
					when DTR =>
						if SDTQ = slvLoadSDA then
							slvSDA <= slvDTR(7) ;
						else
							if EoSCH = '1' then
								if regSRnW = '1' then  -- Slave Read
									slvSDA <= slvDTR(7) ;
								else  	-- Slave Write
									if LastSBit = '1' then
										slvSDA <= regSwrTerm ;
									else
										slvSDA <= '1' ;
									end if ;
								end if ;
							end if ;
						end if ;
					when others =>
						slvSDA <= '1' ;
				end case ;
			else
				slvSDA <= '1' ;
			end if ;
		end if ;
	end process ;


---------------------------------------------------------------------------------------------------
-- Data Transmitter (for Slave-Read transaction)
---------------------------------------------------------------------------------------------------
	-- SrdDxxx I/F (Generates SrdDReq and Convert SrdData to SDA)
	SrdDIF: process(CLK, nRST)
	begin
		if nRST = '0' then
			SDTQ <= slvDTrIdle ;
		elsif rising_edge(CLK) then
			if syncRST = '1' then
				SDTQ <= slvDTrIdle ;
			else
				case SDTQ is
					when slvDTrIdle =>
						if SQ = slvTr and regSRnW = '1' and BSQ = ACK and BoSCH = '1' then
							if vSDA = '0' then  -- not EoStr
								SDTQ <= slvDTrReq ;
							end if ;
						end if ;
					when slvDTrReq =>
						if SrdDRdy = '1' then
							if EoSCH = '0' then
								SDTQ <= slvDTrIdle ;
							else
								SDTQ <= slvLoadSDA ;
							end if ;
						else
							if EoSCH = '1' then
								SDTQ <= slvDTrWait ;
							end if ;
						end if ;
					when slvDTrWait =>
						if SrdDRdy = '1' then
							SDTQ <= slvLoadSDA ;
						end if ;
					when slvLoadSDA =>
						SDTQ <= slvDTrSetup ;
					when slvDTrSetup =>
						if slvDsupCntr = "00" and CKE = '1' then
							SDTQ <= slvDTrIdle ;
						end if ;
					when others =>
						SDTQ <= slvDTrIdle ;
				end case ;
			end if ;
		end if ;
	end process ;

	iSrdDReq <= '1' when SDTQ = slvDTrReq or SDTQ = slvDTrWait else
				'0' ;
	SrdDReq <= iSrdDReq ;

	-- Acquires data setup time for delayed data
	DataSetupTimeCounter: process(CLK, nRST)
	begin
		if nRST = '0' then
			slvDsupCntr <= (others => '0') ;
		elsif rising_edge(CLK) then
			if syncRST = '1' then
				slvDsupCntr <= (others => '0') ;
			elsif SDTQ = slvDTrSetup then
				if CKE = '1' then
					slvDsupCntr <= unsigned(slvDsupCntr) - 1 ;
				end if ;
			else
				slvDsupCntr <= Dsup ;
			end if ;
		end if ;
	end process ;

	-- Shift Reg. (SrdData -> SDA)
	SlaveDTR: process(CLK, nRST)
	begin
		if nRST = '0' then
			slvDTR <= (others => '0') ;
		elsif rising_edge(CLK) then
			if syncRST = '1' then
				slvDTR <= (others => '0') ;
			elsif iSrdDReq = '1' and SrdDRdy = '1' then
				slvDTr <= SrdData ;
			elsif SDTQ = slvLoadSDA or EoSCH = '1' then
				slvDTr(7 downto 1) <= slvDTr(6 downto 0) ;
				slvDTr(0) <= '1' ;
			end if ;
		end if ;
	end process ;


---------------------------------------------------------------------------------------------------
-- Data Receiver (for Slave-Write transaction)
---------------------------------------------------------------------------------------------------
	-- SwrDxxx I/F (Generates SwrDReq)
	SwrDIF: process(CLK, nRST)
	begin
		if nRST = '0' then
			SDRQ <= slvDRcIdle ;
		elsif rising_edge(CLK) then
			if syncRST = '1' then
				SDRQ <= slvDRcIdle ;
			else
				case SDRQ is
					when slvDRcIdle =>
						if SQ = slvTr and regSRnW = '0' and BSQ = DTR and LastSBit = '1' and BoSCH = '1' then
							SDRQ <= slvDRcReq0 ;
						end if ;
					when slvDRcReq0 =>
						if SwrDRdy = '1' then
							SDRQ <= slvDRcIdle ;
						else
							if EoSCH = '1' then
								SDRQ <= slvDRcReq1 ;
							end if ;
						end if ;
					when slvDRcReq1 =>
						if SwrDRdy = '1' then
							SDRQ <= slvDRcIdle ;
						elsif EoSCH = '1' then
							SDRQ <= slvDRcWait ;
						end if ;
					when slvDRcWait =>
						if SwrDRdy = '1' then
							SDRQ <= slvDRcIdle ;
						end if ;
					when others =>
						SDRQ <= slvDRcIdle ;
				end case ;
			end if ;
		end if ;
	end process ;

	SwrDReq <= '1' when SDRQ = slvDRcReq0 or SDRQ = slvDRcReq1 or SDRQ = slvDRcWait else
			   '0' ;

	SwrData <= ReceivedData ;

	-- SwrTerm detector (regSwrTerm <= '1' if SwrTerm = '1' while SDRQ = slvDRcReq0)
	--  SwrTerm can be activeted ('0' -> '1') only while SwrDReq = '0' and the first clock of
	--  SwrDReq = '1'
	DetectSwrTerm: process(CLK ,nRST)
	begin
		if nRST = '0' then
			regSwrTerm <= '0' ;
		elsif rising_edge(CLK) then
			if syncRST = '1' then
				regSwrTerm <= '0' ;
			elsif EoSCH = '1' then
				regSwrTerm <= '0' ;
			elsif SDRQ = slvDRcReq0 then
				if SwrTerm = '1' then
					regSwrTerm <= '1' ;
				end if ;
			end if ;
		end if ;
	end process ;


---------------------------------------------------------------------------------------------------
-- Status Report Holder
---------------------------------------------------------------------------------------------------
	SrpHolder: process(CLK, nRST)
	begin
		if nRST = '0' then
			srpTerm <= '0' ;
			srpAbort <= '0' ;
		elsif rising_edge(CLK) then
			if syncRST = '1' or SAck = '1' then
				srpTerm <= '0' ;
				srpAbort <= '0' ;
			elsif SQ = slvTr and (STAC = '1' or STPC = '1') then
				case BSQ is
					when STP =>
						srpTerm <= '1' ;
						srpAbort <= '0' ;
					when DTR =>
						if FirstSBit = '1' then
							srpTerm <= '1' ;
							srpAbort <= '0' ;
						else
							srpTerm <= '0' ;
							srpAbort <= '1' ;
						end if ;
					when STR | ATR | ACK =>
						srpTerm <= '0' ;
						srpAbort <= '1' ;
					when others =>
				end case ;
			end if ;
		end if ;
	end process ;

	srpBFree <= BFree ;
	srpBObsc <= BObsc ;



end RTL ;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -