1 ------------------------------------------------------------------------------- 2 -- File : I2cRegMaster.vhd 3 -- Company : SLAC National Accelerator Laboratory 4 -- Created : 2013-01-22 5 -- Last update: 2016-07-11 6 ------------------------------------------------------------------------------- 8 -- PRESCALE_G = (clk_freq / (5 * i2c_freq)) - 1 9 -- FILTER_G = (min_pulse_time / clk_period) + 1 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 40 regIn :
in I2cRegMasterInType;
41 regOut :
out I2cRegMasterOutType;
45 end entity I2cRegMaster;
58 type RegType is record 60 byteCount : (1 downto 0);
61 regOut : I2cRegMasterOutType;
65 constant REG_INIT_C : RegType := ( 67 byteCount => (others => '0'), 71 regFailCode => (
others => '0'),
72 regRdData => (
others => '0')),
81 addr => (others => '0'), 87 signal r : RegType := REG_INIT_C;
100 return to_integer(byteCount)*8;
103 return (to_integer(totalBytes)-to_integer(byteCount))*8;
105 end function getIndex;
124 comb :
process (
regIn, i2cMasterOut, r,
srst)
is 125 variable v : RegType;
126 variable addrIndexVar : ;
127 variable dataIndexVar : ;
137 v.i2cMasterIn.rdAck := '0';
141 v.byteCount := (others => '0');
143 v.i2cMasterIn.txnReq := '1';
144 v.i2cMasterIn.op := '1';
145 -- Use a repeated start for reads when directed to do so 146 -- This is done by setting stop to 0 for the regAddr write txn 147 -- Then the following read txn will be issued with repeated start 152 v.state := BUS_ACK_S;
157 v.i2cMasterIn.op := '0';
164 -- When a new register access request is seen, 165 -- Write the register address out on the bus first 166 -- One byte at a time, order determined by endianness input 169 -- Must drop txnReq as last byte is sent if reading 172 if (i2cMasterOut.wrAck = '1') then 173 v.byteCount := r.byteCount + 1;
177 v.byteCount := (others => '0');
181 v.state := READ_TXN_S;
187 -- Txn started in WAIT_REQ_S still active 188 -- Put wrData on the bus one byte at a time 192 v.i2cMasterIn.stop := '1';
-- Send stop when done writing all bytes 193 if (i2cMasterOut.wrAck = '1') then 194 v.byteCount := r.byteCount + 1;
197 v.state := REG_ACK_S;
203 -- Start new txn to read data bytes 204 v.i2cMasterIn.txnReq := '1';
205 v.i2cMasterIn.op := '0';
206 v.i2cMasterIn.stop := '1';
-- i2c stop after all bytes are read 210 -- Drop txnReq on last byte 212 -- Read data bytes as they arrive 213 if (i2cMasterOut.rdValid = '1' and r.i2cMasterIn.rdAck = '0') then 214 v.byteCount := r.byteCount + 1;
216 v.i2cMasterIn.rdAck := '1';
219 v.state := REG_ACK_S;
224 if i2cMasterOut.busAck = '1' then 225 v.i2cMasterIn.txnReq := '0';
226 v.state := REG_ACK_S;
230 -- Req done. Ack the req. 231 -- Might have failed so hold regFail (would be set to 0 otherwise). 235 -- v.regOut.regAck := '0'; Might want this back. 236 v.state := WAIT_REQ_S;
241 -- Always check for errors an cancel the txn if they happen 245 v.i2cMasterIn.txnReq := '0';
246 v.i2cMasterIn.rdAck := '1';
247 v.state := REG_ACK_S;
250 ------------------------------------------------------------------------------------------------ 252 ------------------------------------------------------------------------------------------------ 257 ------------------------------------------------------------------------------------------------ 258 -- Signal Assignments 259 ------------------------------------------------------------------------------------------------ 264 i2cMasterIn.enable <= '1';
266 i2cMasterIn.filter <= (others => '0');
-- Not using dynamic filtering 270 i2cMasterIn.stop <= r.i2cMasterIn.stop;
271 i2cMasterIn.op <= r.i2cMasterIn.op;
285 r <= REG_INIT_C after TPD_G;
286 elsif (rising_edge(clk)) then 287 r <= rin after TPD_G;
293 end architecture rtl;
in regInI2cRegMasterInType
slv( 1 downto 0) regAddrSize
OUTPUT_EN_POLARITY_Ginteger range 0 to 1:= 0
slv( 31 downto 0) regAddr
slv( 15 downto 0) prescale
DYNAMIC_FILTER_Ginteger range 0 to 1:= 0
FILTER_Ginteger range 2 to 512:= 126
OUTPUT_EN_POLARITY_Ginteger range 0 to 1:= 0
slv( 7 downto 0) regFailCode
slv( 1 downto 0) regDataSize
in i2cMasterInI2cMasterInType
slv( 31 downto 0) regRdData
out i2cMasterOutI2cMasterOutType
FILTER_Ginteger range 2 to 512:= 8
out regOutI2cRegMasterOutType
PRESCALE_Ginteger range 0 to 655535:= 62
slv( 31 downto 0) regWrData