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

📄 i2cmaster.vhd

📁 DesignWave 2005 8 Verilog Example
💻 VHD
字号:
--------------------------------------------------------------------------------
-- i2cMaster (i2c main Master Sequencers)
-- Takashi Kohno (DigiCat)
-- Rev. 0.5.1c  / 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 i2cMaster is
	port(	CLK, nRST, syncRST	: in std_logic ;
			CKE					: in std_logic ;  -- CLK enable for sampling clock
			
			-- i2c bus
			SCL, SDA			: in std_logic ;
			mstSCL, mstSDA		: out std_logic ;

			-- Local bus for slave functions
			-- Transaction detection
			MReq				: in std_logic ;
			Mi2cAdrs			: in std_logic_vector(6 downto 0) ;
			MRnW				: in std_logic ;
			MCont				: in std_logic ;
			MStb				: in std_logic ;
			MBusy				: out std_logic ;
			
			-- Master write stream
			MwrDReq				: out std_logic ;
			MwrData				: in std_logic_vector(7 downto 0) ;
			MwrTerm				: in std_logic ;
			MwrDRdy				: in std_logic ;
			
			-- Master read stream
			MrdDReq				: out std_logic ;
			MrdData				: out std_logic_vector(7 downto 0) ;
			MrdTerm				: in std_logic ;
			MrdDRdy				: in std_logic ;

			-- Status Reports
			srpBFree			: out std_logic ;
			srpBObsc			: out std_logic ;
			srpAdrs				: out std_logic ;
			srpWrite			: out std_logic ;
			srpArbt				: out std_logic ;
			srpAbort			: out std_logic ;

			-- Timing parameters
			Spre				: in std_logic_vector(3 downto 0) ;
			Spos				: in std_logic_vector(3 downto 0) ;
			Tlow				: in std_logic_vector(3 downto 0) ;
			Thig				: in std_logic_vector(3 downto 0) ;
			Dhol				: in std_logic_vector(1 downto 0)
			) ;
end i2cMaster ;



architecture RTL of i2cMaster 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 LastSBit			: std_logic ;
signal vSCL, vSDA		: std_logic ;
signal BFree, BObsc		: std_logic ;

-- for i2cDrv
signal imstSDA			: std_logic ;
signal drvBusy			: std_logic ;
signal gSTR				: std_logic ;
signal gDTR				: std_logic ;
signal gSTP				: std_logic ;
signal gRSR				: std_logic ;
signal Data				: std_logic ;
signal ABT				: std_logic ;
signal gDTW				: std_logic ;


-- Signals for i2cMaster
type MasterFunctionState is (mstIdle, mstStart, mstDRc, mstDRcReq0, mstDRcReq1, mstDRcGAck, mstDTr, mstDTrReq0, mstDTrReq1, mstDRcFin, mstDTrFin, mstDisc, mstArbt, mstAbort) ;
signal MQ				: MasterFunctionState ;

signal regMi2cAdrs		: std_logic_vector(6 downto 0) ;
signal regMRnW			: std_logic ;
signal regMCont			: std_logic ;
signal regMStB			: std_logic ;

signal regMrdTerm		: std_logic ;
signal regMwrTerm		: std_logic ;

signal mstDTreg			: std_logic_vector(7 downto 0) ;

signal adrsAck			: std_logic ;
signal busexr			: std_logic ;
signal confSDA			: std_logic ;  	-- when SDA has conflict
signal busconflict		: std_logic ;


begin

-- Component instantiations:
	mstStDecUnit: 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 => open,
					LastSBit => LastSBit,
					vSCL => vSCL, vSDA => vSDA,
					BFree => BFree, BObsc => BObsc
					) ;

	DrvUnit: i2cDrv
		port map(	CLK => CLK, nRST => nRST, syncRST => syncRST,
					CKE => CKE,
					SCLout => mstSCL, SDAout => imstSDA,
					rcvSCL => vSCL, rcvSDA => vSDA,
					BSY => drvBusy,
					gSTR => gSTR,
					gDTR => gDTR,
					gSTP => gSTP,
					gRSR => gRSR,
					Data => Data,
					ABT => ABT,
					gDTW => gDTW,
					Spre => Spre,
					Spos => Spos,
					Tlow => Tlow,
					Thig => Thig,
					Dhol => Dhol
					) ;

	mstSDA <= imstSDA ;



---------------------------------------------------------------------------------------------------
-- Transaction sequence generator
---------------------------------------------------------------------------------------------------
	-- Root sequencer for master functions
	MasterFuncitionRootSeq: process(CLK, nRST)
	begin
		if nRST = '0' then
			MQ <= mstIdle ;
			busexr <= '0' ;
		elsif rising_edge(CLK) then
			if syncRST = '1' then
				MQ <= mstIdle ;
			elsif busconflict = '1' then
				MQ <= mstAbort ;
			else
				case MQ is
					when mstIdle =>
						if MReq = '1' then
							MQ <= mstStart ;
						end if ;
					when mstStart =>
						if BSQ = STR then
							busexr <= '1' ;
							if regMRnW = '1' then  -- Master read
								MQ <= mstDRc ;
							else  			-- Master write
								MQ <= mstDTr ;
							end if ;
						end if ;
					when mstDRc =>  		-- Root of master read
						if BoSCH = '1' then
							case BSQ is
								when ACK =>
									if regMStB = '1' then
										MQ <= mstDRcFin ;
									elsif vSDA = '1' then
										MQ <= mstDisc ;
									end if ;
								when DTR =>
									if LastSBit = '1' then
										MQ <= mstDRcReq0 ;
									end if ;
								when ATR =>  -- Arbitration
									if confSDA = '1' then
										MQ <= mstArbt ;
									end if ;
								when others =>
							end case ;
						end if ;
					when mstDRcReq0 =>  	-- wait for MrdDRdy while preparing for ACK state
						if MrdDRdy = '1' then  -- when MrdDRdy is given before generating ACK state
							MQ <= mstDRcGAck ;
						elsif drvBusy = '0' then  -- ACK state has been generated
							MQ <= mstDRcReq1 ;
						end if ;
					when mstDRcReq1 =>  	-- waits for MrdDRdy after bus transfers to ACK state
						if MrdDRdy = '1' then
							if regMrdTerm = '1' then
								MQ <= mstDRcFin ;  -- ends reading
							else
								MQ <= mstDrc ;  -- contiunes another byte
							end if ;
						end if ;
					when mstDRcGAck =>  	-- generates ACK state after MrdDRdy is given
						if EoSCH = '1' then
							if regMrdTerm = '1' then
								MQ <= mstDRcFin ;  -- ends reading
							else
								MQ <= mstDrc ;  -- continues another byte
							end if ;
						end if ;
					when mstDTr =>
						if BoSCH = '1' then
							case BSQ is
								when ACK =>
									if regMStB = '1' then
										MQ <= mstDTrFin ;
									elsif vSDA = '1' then
										MQ <= mstDisc ;
									else
										if regMwrTerm = '0' then
											MQ <= mstDTrReq0 ;
										else
											MQ <= mstDTrFin ;
										end if ;
									end if ;
								when ATR | DTR =>  -- Arbitration
									if confSDA = '1' then
										MQ <= mstArbt ;
									end if ;
								when others =>
							end case ;
						end if ;
					when mstDTrReq0 =>
						if MwrDRdy = '1' then
							MQ <= mstDTr ;
						end if ;
					when mstDRcFin =>		-- terminates a transferration
						if BoSCH = '1' and confSDA = '1' then  -- Arbitration
							MQ <= mstArbt ;
						elsif drvBusy = '0' then
							MQ <= mstIdle ;
							if regMCont = '0' then
								busexr <= '0' ;
							end if ;
						end if ;
					when mstDTrFin =>		-- terminates a transferration
						if EoSCH = '1' then
							MQ <= mstIdle ;
							if regMCont = '0' then
								busexr <= '0' ;
							end if ;
						end if ;
					when mstDisc | mstArbt =>	-- terminates a transferration
						if EoSCH = '1' then
							MQ <= mstIdle ;
							busexr <= '0' ;
						end if ;
					when mstAbort =>
						if drvBusy = '0' then
							MQ <= mstIdle ;
							busexr <= '0' ;
						end if ;
					when others =>
						MQ <= mstIdle ;
				end case ;
			end if ;
		end if ;
	end process ;

	-- Holds the Master Transaction Request
	MReqHolder: process(CLK, nRST)
	begin
		if nRST = '0' then
			regMi2cAdrs <= (others => '0') ;
			regMRnW <= '0' ;
			regMCont <= '0' ;
			regMStB <= '0' ;
		elsif rising_edge(CLK) then
			if syncRST = '1' then
				regMi2cAdrs <= (others => '0') ;
				regMRnW <= '0' ;
				regMCont <= '0' ;
			elsif MQ = mstIdle then
				if MStB = '1' then
					regMi2cAdrs <= (others => '0') ;
					regMRnW <= '1' ;
					regMCont <= '1' ;
				else
					regMi2cAdrs <= Mi2cAdrs ;
					regMRnW <= MRnW ;
					regMCont <= MCont ;
				end if ;
				regMStB <= MStB ;
			end if ;
		end if ;
	end process ;

	-- Holds the Address Acknowledge status
	AdrsAckHolder: process(CLK, nRST)
	begin
		if nRST = '0' then
			adrsAck <= '0' ;
		elsif rising_edge(CLK) then
			if syncRST = '1' then
				adrsAck <= '0' ;
			else
				case MQ is
					when mstDTr | mstDRc =>
						if BSQ = ACK and BoSCH = '1' and adrsAck = '0' then
							adrsAck <= not vSDA ;
						end if ;
					when mstIdle =>
						adrsAck <= '0' ;
					when others =>
				end case ;
			end if ;
		end if ;
	end process ;
				
	-- Samples MrdTerm
	MrdTermSampler: process(CLK, nRST)
	begin
		if nRST = '0' then
			regMrdTerm <= '0' ;
		elsif rising_edge(CLK) then
			if syncRST = '1' then
				regMrdTerm <= '0' ;
			elsif MQ = mstDRc then
				regMrdTerm <= MrdTerm ;
			end if ;
		end if ;
	end process ;

	-- Samples MwrTerm
	MwrTermSampler: process(CLK, nRST)
	begin
		if nRST = '0' then
			regMwrTerm <= '0' ;
		elsif rising_edge(CLK) then
			if syncRST = '1' then
				regMwrTerm <= '0' ;
			elsif MQ = mstDTrReq0 and MwrDRdy = '1' then
				regMwrTerm <= MwrTerm ;
			elsif MQ = mstIdle then
				regMwrTerm <= '0' ;
			end if ;
		end if ;
	end process ;

	-- Master query I/F
	MBusy <= '1' when MQ /= mstIdle else
			 '0' ;

	-- Arbitration detector
	confSDA <= imstSDA xor vSDA ;

	busconflict <= '1' when (MQ /= mstIdle and MQ /= mstStart) and (STAC = '1' or STPC = '1') else
				   '0' ;


---------------------------------------------------------------------------------------------------
-- SCL and SDA driver (drives i2cDrv)
---------------------------------------------------------------------------------------------------
	gDTRgen: process(MQ, BSQ, regMCont)
	begin
		case MQ is
			when mstDRc | mstDTr =>
				if BSQ = STR or BSQ = DTR or BSQ = ATR or BSQ = ACK then
					gDTR <= '1' ;
				else
					gDTR <= '0' ;
				end if ;
			when mstDRcReq0 | mstDRcGAck =>
				gDTR <= '1' ;
			when mstDTrFin | mstDRcFin =>
				if regMCont = '1' then
					gDTR <= '1' ;
				else
					gDTR <= '0' ;
				end if ;
			when others =>
				gDTR <= '0' ;
		end case ;
	end process ;
				
	gSTR <= '1' when MQ = mstStart and (BSQ = Free or busexr = '1') else
			'0' ;
	gSTP <= '1' when ((MQ = mstDTrFin or MQ = mstDRcFin) and regMCont = '0') or MQ = mstDisc else
			'0' ;
	gDTW <= '1' when (MQ = mstDRcReq1 and MrdDRdy = '0') or (MQ = mstDTrReq0 and MwrDRdy = '0') else
			'0' ;
	gRSR <= '0' ;
	ABT <= '0' ;

	Datagen: process(MQ, BSQ, regMCont, regMrdTerm, mstDTreg(7))
	begin
		case MQ is
			when mstDRcReq0 | mstDRcGAck =>
				if regMrdTerm = '0' then  -- generates Ack
					Data <= '0' ;
				else
					Data <= '1' ;
				end if ;
			when mstDRcReq1 =>
				if regMrdTerm = '1' and regMCont = '0' then  -- prepare for STOP condition
					Data <= '0' ;
				else
					Data <= '1' ;
				end if ;
			when mstDRc =>
				if BSQ = STR or BSQ = ATR then
					Data <= mstDTreg(7) ;
				else
					Data <= '1' ;
				end if ;
			when mstDTrReq0 =>
				Data <= '0' ;
			when mstDTr =>
				if BSQ = STR or BSQ = ATR or BSQ = DTR or BSQ = ACK then
					Data <= mstDTreg(7) ;
				else
					Data <= '1' ;
				end if ;
			when others =>
				Data <= '1' ;
		end case ;
	end process ;
							

---------------------------------------------------------------------------------------------------
-- Data Receiver (for Master-Read tarnsactions)
---------------------------------------------------------------------------------------------------
	MrdDReq <= '1' when MQ = mstDRcReq0 or MQ = mstDRcReq1 else
			   '0' ;
	MrdData <= ReceivedData ;


---------------------------------------------------------------------------------------------------
-- Data Transmitter (for Address phases and Master-Write transactions)
---------------------------------------------------------------------------------------------------
	MwrDReq <= '1' when MQ = mstDTrReq0 else
			   '0' ;

	-- Shift Reg. (SrdData -> SDA)
	MasterDTR: process(CLK, nRST)
	begin
		if nRST = '0' then
			mstDTreg <= (others => '0') ;
		elsif rising_edge(CLK) then
			if syncRST = '1' then
				mstDTreg <= (others => '0') ;
			elsif MQ = mstStart then
				mstDTreg(7 downto 1) <= regMi2cAdrs ;
				mstDTreg(0) <= regMRnW ;
			elsif MQ = mstDTrReq0 and MwrDRdy = '1' then
				mstDTreg <= MwrData ;
			elsif (BSQ = DTR or BSQ = ATR or BSQ = STR or BSQ = ACK) and drvBusy = '0' then
				mstDTreg(7 downto 1) <= mstDTreg(6 downto 0) ;
				mstDTreg(0) <= '1' ;
			end if ;
		end if ;
	end process ;


---------------------------------------------------------------------------------------------------
-- Status Report Holder
---------------------------------------------------------------------------------------------------
	StatusReportHolder: process(CLK, nRST)
	begin
		if nRST = '0' then
			srpAdrs <= '0' ;
			srpWrite <= '0' ;
			srpArbt <= '0' ;
			srpAbort <= '0' ;
		elsif rising_edge(CLK) then
			if syncRST = '1' then
				srpAdrs <= '0' ;
				srpWrite <= '0' ;
				srpArbt <= '0' ;
				srpAbort <= '0' ;
			else
				case MQ is
					when mstDisc =>
						if adrsAck = '0' then
							srpAdrs <= '1' ;
						else
							srpWrite <= '1' ;
						end if ;
					when mstArbt =>
						srpArbt <= '1' ;
					when mstAbort =>
						srpAbort <= '1' ;
					when mstIdle =>
						if MReq = '1' then
							srpAdrs <= '0' ;
							srpWrite <= '0' ;
							srpArbt <= '0' ;
							srpAbort <= '0' ;
						end if ;
					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 + -