📄 i2cmaster.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 + -