1 ------------------------------------------------------------------------------- 2 -- File : I2cRegSlave.vhd 3 -- Company : SLAC National Accelerator Laboratory 4 -- Created : 2013-01-16 5 -- Last update: 2014-03-13 6 ------------------------------------------------------------------------------- 7 -- Description: Implements an I2C slave attached to a generic RAM interface. 8 -- Protocol is simple: Address of configurable size, followed by data of 10 ------------------------------------------------------------------------------- 11 -- This file is part of 'SLAC Firmware Standard Library'. 12 -- It is subject to the license terms in the LICENSE.txt file found in the 13 -- top-level directory of this distribution and at: 14 -- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. 15 -- No part of 'SLAC Firmware Standard Library', including this file, 16 -- may be copied, modified, propagated, or distributed except according to 17 -- the terms contained in the LICENSE.txt file. 18 ------------------------------------------------------------------------------- 21 use ieee.std_logic_1164.
all;
28 --! @ingroup protocols_i2c 32 -- Generics passed down to I2cSlave 45 -- Front End Ram Interface 54 end entity I2cRegSlave;
58 type StateType is (IDLE_S, ADDR_S, WRITE_DATA_S, READ_DATA_S);
60 type RegType is record 71 constant REG_INIT_C : RegType := ( 73 byteCnt => (others => '0'), 74 addr => (others => '0'), 80 signal r : RegType := REG_INIT_C;
87 totalBytes : positive)
92 return to_integer(byteCount)*8;
95 return (totalBytes-1-to_integer(byteCount))*8;
97 end function getIndex;
118 comb :
process (
rdData, r, i2cSlaveOut,
sRst)
is 119 variable v : RegType;
120 variable byteCntVar : ;
121 variable addrIndexVar : ;
122 variable dataIndexVar : ;
126 byteCntVar := to_integer(r.byteCnt);
130 -- Enable the i2cSlave after reset 131 v.i2cSlaveIn.enable := '1';
133 -- Read and Write enables are pulsed, defualt to 0 137 -- Pulse rxAck or wait until rxValid drops? 138 -- Can get away with pulsing. 139 v.i2cSlaveIn.rxAck := '0';
141 -- Auto increment the address after each read or write 142 -- This enables bursts. 143 if (r.wrEn = '1' or r.rdEn = '1') then 147 -- Tx Data always valid, assigned based on byte cnt 152 v.byteCnt := (others => '0');
153 -- Get txData ready in case a read occurs. 154 v.i2cSlaveIn.txData := rdData(dataIndexVar+7 downto dataIndexVar);
156 -- Wait here for slave to be addressed 157 if (i2cSlaveOut.rxActive = '1') then 158 -- Slave has been addressed for a write on the i2c bus 159 -- This write will consist of the ram address 161 v.addr := (others => '0');
163 elsif (i2cSlaveOut.txActive = '1') then 164 v.state := READ_DATA_S;
168 if (i2cSlaveOut.rxValid = '1') then 169 -- Received a byte of the address 170 v.addr(addrIndexVar+7 downto addrIndexVar) := (i2cSlaveOut.rxData);
171 v.byteCnt := r.byteCnt + 1;
173 v.byteCnt := (others => '0');
174 v.state := WRITE_DATA_S;
178 if (i2cSlaveOut.rxActive = '0') then 179 -- Didn't get enough bytes, go back to idle 181 v.byteCnt := (others => '0');
185 if (i2cSlaveOut.rxValid = '1') then 186 -- Received another byte 187 v.wrData(dataIndexVar+7 downto dataIndexVar) := i2cSlaveOut.rxData;
188 v.byteCnt := r.byteCnt + 1;
189 -- v.i2cSlaveIn.rxAck := '1'; 191 -- Received a whole word. Increment addr, reset byteCnt 193 v.byteCnt := (others => '0');
197 if (i2cSlaveOut.rxActive = '0') then 202 v.i2cSlaveIn.txData := rdData(dataIndexVar+7 downto dataIndexVar);
203 if (i2cSlaveOut.txAck = '1') then 205 v.byteCnt := r.byteCnt + 1;
207 -- Word was sent. Increment addr to get next word, reset byteCnt 209 v.byteCnt := (others => '0');
213 if (i2cSlaveOut.txActive = '0') then 221 ------------------------------------------------------------------------------------------------ 223 ------------------------------------------------------------------------------------------------ 226 -- v.state := IDLE_S; 227 -- v.byteCnt := (others => '0'); 228 -- v.addr := (others => '0'); 230 -- v.wrData := (others => '0'); 232 -- v.i2cSlaveIn.enable := '0'; 233 -- v.i2cSlaveIn.txValid := '0'; 234 -- v.i2cSlaveIn.txData := (others => '0'); 235 -- v.i2cSlaveIn.rxAck := '0'; 238 ------------------------------------------------------------------------------------------------ 239 -- Signal Assignments 240 ------------------------------------------------------------------------------------------------ 245 i2cSlaveIn <= r.i2cSlaveIn;
259 r <= REG_INIT_C after TPD_G;
260 -- r.state <= IDLE_S after TPD_G; 261 -- r.byteCnt <= (others => '0') after TPD_G; 262 -- r.addr <= (others => '0') after TPD_G; 263 -- r.wrEn <= '0' after TPD_G; 264 -- r.wrData <= (others => '0') after TPD_G; 265 -- r.rdEn <= '0' after TPD_G; 266 -- r.i2cSlaveIn.enable <= '0' after TPD_G; 267 -- r.i2cSlaveIn.txValid <= '0' after TPD_G; 268 -- r.i2cSlaveIn.txData <= (others => '0') after TPD_G; 269 -- r.i2cSlaveIn.rxAck <= '0' after TPD_G; 270 elsif (rising_edge(clk)) then 271 r <= rin after TPD_G;
275 end architecture rtl;
I2C_ADDR_Ginteger range 0 to 1023:= 0
OUTPUT_EN_POLARITY_Ginteger range 0 to 1:= 0
RMODE_Ginteger range 0 to 1:= 0
TMODE_Ginteger range 0 to 1:= 0
FILTER_Ginteger range 2 to 512:= 4
FILTER_Ginteger range 2 to 512:= 4
out wrDataslv(( 8* DATA_SIZE_G)- 1 downto 0)
OUTPUT_EN_POLARITY_Ginteger range 0 to 1:= 0
I2C_ADDR_Ginteger range 0 to 1023:= 0
TENBIT_Ginteger range 0 to 1:= 0
in rdDataslv(( 8* DATA_SIZE_G)- 1 downto 0)
I2cSlaveInType :=(enable => '0',txValid => '0',txData =>( others => '0'),rxAck => '0') I2C_SLAVE_IN_INIT_C
in i2cSlaveInI2cSlaveInType
out addrslv(( 8* ADDR_SIZE_G)- 1 downto 0)
ENDIANNESS_Ginteger range 0 to 1:= 0
TENBIT_Ginteger range 0 to 1:= 0
out i2cSlaveOutI2cSlaveOutType