📄 rif_i2cmaster.vhd
字号:
--------------------------------------------------------------------------------
-- rif_i2cMaster (Register I/F for i2cMaster)
-- Takashi Kohno (DigiCat)
-- Rev. 0.5.0c / 27, May., 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 ;
entity rif_i2cMaster is
port( CLK, nRST : in std_logic ;
CKE : in std_logic ; -- CLK enable for sampling clock
-- Register I/F
WrEn, RdEn : in std_logic ;
Usel : in std_logic ; -- Unit select
Uadrs : in std_logic_vector(2 downto 0) ;
Din : in std_logic_vector(7 downto 0) ;
Dout : out std_logic_vector(7 downto 0) ;
Int : out std_logic ;
-- Local bus for slave functions
syncRST : out std_logic ;
-- Transaction query
MReq : out std_logic ;
Mi2cAdrs : out std_logic_vector(6 downto 0) ;
MRnW : out std_logic ;
MCont : out std_logic ;
MStb : out std_logic ;
MBusy : in std_logic ;
-- Master write stream
MwrDReq : in std_logic ;
MwrData : out std_logic_vector(7 downto 0) ;
MwrTerm : out std_logic ;
MwrDRdy : out std_logic ;
-- Master read stream
MrdDReq : in std_logic ;
MrdData : in std_logic_vector(7 downto 0) ;
MrdTerm : out std_logic ;
MrdDRdy : out std_logic ;
-- Status Reports
srpBFree : in std_logic ;
srpBObsc : in std_logic ;
srpAdrs : in std_logic ;
srpWrite : in std_logic ;
srpArbt : in std_logic ;
srpAbort : in std_logic ;
-- Timing parameters
Spre : out std_logic_vector(3 downto 0) ;
Spos : out std_logic_vector(3 downto 0) ;
Tlow : out std_logic_vector(3 downto 0) ;
Thig : out std_logic_vector(3 downto 0) ;
Dhol : out std_logic_vector(1 downto 0)
) ;
end rif_i2cMaster ;
architecture RTL of rif_i2cMaster is
-- Register addresses
constant ADRS_CMDSTS : std_logic_vector(2 downto 0) := "000" ;
constant ADRS_I2CADRS : std_logic_vector(2 downto 0) := "001" ;
constant ADRS_MRDATA : std_logic_vector(2 downto 0) := "010" ;
constant ADRS_MWDATA : std_logic_vector(2 downto 0) := "011" ;
constant ADRS_MCFGS : std_logic_vector(2 downto 0) := "100" ;
constant ADRS_MCFGT : std_logic_vector(2 downto 0) := "101" ;
constant ADRS_MCFGD : std_logic_vector(2 downto 0) := "110" ;
constant ADRS_MTRNS : std_logic_vector(2 downto 0) := "111" ;
-- Register select signals
signal rselCmdSts : std_logic ;
signal rseli2cAdrs : std_logic ;
signal rselMrdData : std_logic ;
signal rselMwrData : std_logic ;
signal rselMCfgS : std_logic ;
signal rselMCfgT : std_logic ;
signal rselMCfgD : std_logic ;
signal rselMTrns : std_logic ;
-- Registers
signal regSts : std_logic_vector(7 downto 0) ;
signal regi2cAdrs : std_logic_vector(7 downto 0) ;
signal regMwrData : std_logic_vector(7 downto 0) ;
signal regMCfgS : std_logic_vector(7 downto 0) ;
signal regMCfgT : std_logic_vector(7 downto 0) ;
signal regMCfgD : std_logic_vector(7 downto 0) ;
signal regMTrns : std_logic_vector(7 downto 0) ;
signal regINTen : std_logic ;
signal regMStB : std_logic ;
signal regMCont : std_logic ;
signal regMRnW : std_logic ;
alias regSpre : std_logic_vector(3 downto 0) is regMCfgS(3 downto 0) ;
alias regSpos : std_logic_vector(3 downto 0) is regMCfgS(7 downto 4) ;
alias regTlow : std_logic_vector(3 downto 0) is regMCfgT(3 downto 0) ;
alias regThig : std_logic_vector(3 downto 0) is regMCfgT(7 downto 4) ;
alias regDhol : std_logic_vector(1 downto 0) is regMCfgD(1 downto 0) ;
-- Status
signal stsPCmnd : std_logic ;
type QueryBusState is (QrEmpty, QrFull) ;
signal QQr : QueryBusState ;
signal MwrDFull : std_logic ;
signal msgs : std_logic ;
signal IntMsg : std_logic ;
signal IntCmd : std_logic ;
signal IntMwr : std_logic ;
signal IntMrd : std_logic ;
signal dmsgs : std_logic ; -- msgs delayed for 1 clock
signal dMBusy : std_logic ; -- MBusy delayed for 1 clock
signal dMwrDReq : std_logic ; -- MwrDReq delayed for 1 clock
signal dMrdDReq : std_logic ; -- MrdDReq delayed for 1 clock
begin
-- Register select signals
rselCmdSts <= Usel when Uadrs = ADRS_CMDSTS else
'0' ;
rseli2cAdrs <= Usel when Uadrs = ADRS_I2CADRS else
'0' ;
rselMrdData <= Usel when Uadrs = ADRS_MRDATA else
'0' ;
rselMwrData <= Usel when Uadrs = ADRS_MWDATA else
'0' ;
rselMCfgS <= Usel when Uadrs = ADRS_MCFGS else
'0' ;
rselMCfgT <= Usel when Uadrs = ADRS_MCFGT else
'0' ;
rselMCfgD <= Usel when Uadrs = ADRS_MCFGD else
'0' ;
rselMTrns <= Usel when Uadrs = ADRS_MTRNS else
'0' ;
-- Register I/F output
with Uadrs select
Dout <= regSts when ADRS_CMDSTS,
regi2cAdrs when ADRS_I2CADRS,
MrdData when ADRS_MRDATA,
regMwrData when ADRS_MWDATA,
regMCfgS when ADRS_MCFGS,
regMCfgT when ADRS_MCFGT,
regMCfgD when ADRS_MCFGD,
regMTrns when ADRS_MTRNS,
(others => '0') when others ;
Int <= regINTen when (IntMsg or IntCmd or IntMwr or IntMrd) = '1' else
'0' ;
---------------------------------------------------------------------------------------------------
-- Command I/F
---------------------------------------------------------------------------------------------------
QueryBusRegs: process(CLK, nRST)
begin
if nRST = '0' then
regMStB <= '0' ;
regMCont <= '0' ;
regMRnW <= '0' ;
regi2cAdrs <= (others => '0') ;
elsif rising_edge(CLK) then
if WrEn = '1' then
if rselCmdSts = '1' and QQr = QrEmpty then
regMStB <= Din(2) ;
regMCont <= Din(1) ;
regMRnW <= Din(0) ;
end if ;
if rseli2cAdrs = '1' then
regi2cAdrs <= Din ;
end if ;
end if ;
end if ;
end process ;
QueryBusSeq: process(CLK, nRST)
begin
if nRST = '0' then
QQr <= QrEmpty ;
elsif rising_edge(CLK) then
case QQr is
when QrEmpty =>
if MBusy = '1' and (WrEn and rselCmdSts) = '1' then
QQr <= QrFull ;
end if ;
when QrFull =>
if msgs = '1' or MBusy = '0' then
QQr <= QrEmpty ;
end if ;
when others =>
end case ;
end if ;
end process ;
-- Query bus signals
MReq <= '0' when QQr = QrEmpty and (WrEn and rselCmdSts) = '0' else
'1' ;
Mi2cAdrs <= regi2cAdrs(6 downto 0) ;
MRnW <= Din(0) when QQr = QrEmpty else
regMRnW ;
MCont <= Din(1) when QQr = QrEmpty else
regMCont ;
MStB <= Din(2) when QQr = QrEmpty else
regMStB ;
-- Status register output
stsPCmnd <= '1' when QQr = QrFull else
'0' ;
regSts <= (MBusy, stsPCmnd, srpBFree, srpBObsc, srpAdrs, srpWrite, srpArbt, srpAbort) ;
---------------------------------------------------------------------------------------------------
-- Master-Read Data I/F
---------------------------------------------------------------------------------------------------
-- Master-Read bus signals
MrdDataBus: process(CLK, nRST)
begin
if nRST = '0' then
MrdTerm <= '0' ;
elsif rising_edge(CLK) then
if (WrEn and rselMrdData) = '1' then
MrdTerm <= '1' ;
elsif MrdDReq = '1' then
MrdTerm <= '0' ;
end if ;
end if ;
end process ;
MrdDRdy <= '1' when (RdEn and rselMrdData) = '1' else
'0' ;
---------------------------------------------------------------------------------------------------
-- Master-Write Data I/F
---------------------------------------------------------------------------------------------------
MwrDataBusSeq: process(CLK, nRST)
begin
if nRST = '0' then
regMwrData <= (others => '0') ;
MwrDFull <= '0' ;
elsif rising_edge(CLK) then
if MwrDFull = '0' then
if MwrDReq = '0' and (WrEn and rselMwrData) = '1' then
MwrDFull <= '1' ;
regMwrData <= Din ;
end if ;
else
if MwrDReq = '1' or msgs = '1' then
MwrDFull <= '0' ;
end if ;
end if ;
end if ;
end process ;
--Master-Write bus signals
MwrDataBus: process(CLK, nRST)
begin
if nRST = '0' then
MwrTerm <= '0' ;
elsif rising_edge(CLK) then
if (RdEn and rselMwrData) = '1' and MwrDFull = '0' then
MwrTerm <= '1' ;
elsif (MwrDReq = '1' and ((WrEn and rselMwrData) = '1' or MwrDFull = '1')) or
msgs = '1' then
MwrTerm <= '0' ;
end if ;
end if ;
end process ;
MwrDRdy <= '0' when MwrDFull = '0' and (WrEn and rselMwrData) = '0' else
'1' ;
MwrData <= Din when MwrDFull = '0' else
regMwrData ;
---------------------------------------------------------------------------------------------------
-- Interruption generator
---------------------------------------------------------------------------------------------------
-- Transaction register
TrReg: process(CLK, nRST)
begin
if nRST = '0' then
regINTen <= '0' ;
elsif rising_edge(CLK) then
if WrEn = '1' and rselMTrns = '1' then
regINTen <= Din(0) ;
end if ;
end if ;
end process ;
syncRST <= Din(7) when WrEn = '1' and rselMTrns = '1' else
'0' ;
-- Transaction register output
regMTrns <= (IntMsg, IntCmd, IntMwr, IntMrd, MwrDFull, MwrDReq, MrdDReq, regINTen) ;
-- Interruption generator
StsDelayers: process(CLK, nRST)
begin
if nRST = '0' then
dmsgs <= '0' ;
dMBusy <= '0' ;
dMwrDReq <= '0' ;
dMrdDReq <= '0' ;
elsif rising_edge(CLK) then
dmsgs <= msgs ;
dMBusy <= MBusy ;
dMwrDReq <= MwrDReq ;
dMrdDReq <= MrdDReq ;
end if ;
end process ;
IntMsgGen: process(CLK, nRST)
begin
if nRST = '0' then
IntMsg <= '0' ;
elsif rising_edge(CLK) then
if dmsgs = '0' and msgs = '1' then
IntMsg <= '1' ;
elsif RdEn = '1' and rselMTrns = '1' then
IntMsg <= '0' ;
end if ;
end if ;
end process ;
IntCmdGen: process(CLK, nRST)
begin
if nRST = '0' then
IntCmd <= '0' ;
elsif rising_edge(CLK) then
if dMBusy = '1' and MBusy = '0' then
IntCmd <= '1' ;
elsif RdEn = '1' and rselMTrns = '1' then
IntCmd <= '0' ;
end if ;
end if ;
end process ;
IntMwrGen: process(CLK, nRST)
begin
if nRST = '0' then
IntMwr <= '0' ;
elsif rising_edge(CLK) then
if dMwrDReq = '0' and MwrDReq = '1' then
IntMwr <= '1' ;
elsif RdEn = '1' and rselMTrns = '1' then
IntMwr <= '0' ;
end if ;
end if ;
end process ;
IntMrdGen: process(CLK, nRST)
begin
if nRST = '0' then
IntMrd <= '0' ;
elsif rising_edge(CLK) then
if dMrdDReq = '0' and MrdDReq = '1' then
IntMrd <= '1' ;
elsif RdEn = '1' and rselMTrns = '1' then
IntMrd <= '0' ;
end if ;
end if ;
end process ;
msgs <= srpAdrs or srpWrite or srpArbt or srpAbort ;
---------------------------------------------------------------------------------------------------
-- Configuration Registers
---------------------------------------------------------------------------------------------------
CRegs: process(CLK, nRST)
begin
if nRST = '0' then
regMCfgS <= (others => '0') ;
regMCfgT <= (others => '0') ;
regMCfgD <= (others => '0') ;
elsif rising_edge(CLK) then
if WrEn = '1' then
if rselMCfgS = '1' then
regMCfgS <= Din ;
end if ;
if rselMCfgT = '1' then
regMCfgT <= Din ;
end if ;
if rselMCfgD = '1' then
regMCfgD <= Din ;
end if ;
end if ;
end if ;
end process ;
-- for i2cMaster
Spre <= regSpre ;
Spos <= regSpos ;
Tlow <= regTlow ;
Thig <= regThig ;
Dhol <= regDhol ;
end RTL ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -