SURF  1.0
AxiI2cEepromCore.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 -- File : AxiI2cEepromCore.vhd
3 -- Company : SLAC National Accelerator Laboratory
4 -- Created : 2016-07-11
5 -- Last update: 2016-09-20
6 -------------------------------------------------------------------------------
7 -- Description: AXI-Lite Read/ModifyWrite for standard EEPROM Module
8 --
9 -- Supported Devices:
10 -- 24AA01F/24LC01F/24FC01F (1kb: ADDR_WIDTH_G = 7)
11 -- 24AA02F/24LC02F/24FC02F (2kb: ADDR_WIDTH_G = 8)
12 -- 24AA04F/24LC04F/24FC04F (4kb: ADDR_WIDTH_G = 9)
13 -- 24AA08F/24LC08F/24FC08F (8kb: ADDR_WIDTH_G = 10)
14 -- 24AA16F/24LC16F/24FC16F (16kb: ADDR_WIDTH_G = 11)
15 -- 24AA32F/24LC32F/24FC32F (32kb: ADDR_WIDTH_G = 12)
16 -- 24AA64F/24LC64F/24FC64F (64kb: ADDR_WIDTH_G = 13)
17 -- 24AA128F/24LC128F/24FC128F (128kb: ADDR_WIDTH_G = 14)
18 -- 24AA256F/24LC256F/24FC256F (256kb: ADDR_WIDTH_G = 15)
19 -- 24AA512F/24LC512F/24FC512F (512kb: ADDR_WIDTH_G = 16)
20 -------------------------------------------------------------------------------
21 -- This file is part of 'SLAC Firmware Standard Library'.
22 -- It is subject to the license terms in the LICENSE.txt file found in the
23 -- top-level directory of this distribution and at:
24 -- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html.
25 -- No part of 'SLAC Firmware Standard Library', including this file,
26 -- may be copied, modified, propagated, or distributed except according to
27 -- the terms contained in the LICENSE.txt file.
28 -------------------------------------------------------------------------------
29 
30 library ieee;
31 use ieee.std_logic_1164.all;
32 use ieee.std_logic_unsigned.all;
33 use ieee.std_logic_arith.all;
34 
35 use work.StdRtlPkg.all;
36 use work.AxiLitePkg.all;
37 use work.I2cPkg.all;
38 
39 library unisim;
40 use unisim.vcomponents.all;
41 
42 --! @see entity
43  --! @ingroup protocols_i2c
45  generic (
46  TPD_G : time := 1 ns;
47  ADDR_WIDTH_G : positive := 16;
48  POLL_TIMEOUT_G : positive := 16;
49  I2C_ADDR_G : slv(6 downto 0) := "1010000";
50  I2C_SCL_FREQ_G : real := 100.0E+3; -- units of Hz
51  I2C_MIN_PULSE_G : real := 100.0E-9; -- units of seconds
52  AXI_CLK_FREQ_G : real := 156.25E+6; -- units of Hz
54  port (
55  -- I2C Ports
58  -- AXI-Lite Register Interface
63  -- Clocks and Resets
64  axilClk : in sl;
65  axilRst : in sl);
66 end AxiI2cEepromCore;
67 
68 architecture rtl of AxiI2cEepromCore is
69 
70  -- Note: PRESCALE_G = (clk_freq / (5 * i2c_freq)) - 1
71  -- FILTER_G = (min_pulse_time / clk_period) + 1
72  constant I2C_SCL_5xFREQ_C : real := 5.0 * I2C_SCL_FREQ_G;
73  constant PRESCALE_C : natural := (getTimeRatio(AXI_CLK_FREQ_G, I2C_SCL_5xFREQ_C)) - 1;
74  constant FILTER_C : natural := natural(AXI_CLK_FREQ_G * I2C_MIN_PULSE_G) + 1;
75 
76  constant ADDR_SIZE_C : slv(1 downto 0) := toSlv(wordCount(ADDR_WIDTH_G, 8) - 1, 2);
77  constant DATA_SIZE_C : slv(1 downto 0) := toSlv(wordCount(32, 8) - 1, 2);
78  constant I2C_ADDR_C : slv(9 downto 0) := ("000" & I2C_ADDR_G);
79  constant TIMEOUT_C : natural := (getTimeRatio(AXI_CLK_FREQ_G, 200.0)) - 1; -- 5 ms timeout
80 
81  constant MY_I2C_REG_MASTER_IN_INIT_C : I2cRegMasterInType := (
82  i2cAddr => I2C_ADDR_C,
83  tenbit => '0',
84  regAddr => (others => '0'),
85  regWrData => (others => '0'),
86  regOp => '0', -- 1 for write, 0 for read
87  regAddrSkip => '0',
88  regAddrSize => ADDR_SIZE_C,
89  regDataSize => DATA_SIZE_C,
90  regReq => '0',
91  busReq => '0',
92  endianness => '1', -- Big endian
93  repeatStart => '0');
94 
95  type StateType is (
96  IDLE_S,
97  READ_ACK_S,
98  READ_DONE_S,
99  WRITE_REQ_S,
100  WRITE_ACK_S,
101  WRITE_DONE_S,
102  WAIT_S);
103 
104  type RegType is record
105  timer : natural range 0 to TIMEOUT_C;
106  RnW : sl;
109  regIn : I2cRegMasterInType;
110  state : StateType;
111  end record;
112 
113  constant REG_INIT_C : RegType := (
114  timer => 0,
115  RnW => '0',
118  regIn => MY_I2C_REG_MASTER_IN_INIT_C,
119  state => IDLE_S);
120 
121  signal r : RegType := REG_INIT_C;
122  signal rin : RegType;
123 
124  signal regOut : I2cRegMasterOutType;
125 
126  -- attribute dont_touch : string;
127  -- attribute dont_touch of r : signal is "TRUE";
128  -- attribute dont_touch of regOut : signal is "TRUE";
129 
130 begin
131 
132  U_I2cRegMaster : entity work.I2cRegMaster
133  generic map(
134  TPD_G => TPD_G,
136  FILTER_G => FILTER_C,
137  PRESCALE_G => PRESCALE_C)
138  port map (
139  -- I2C Port Interface
140  i2ci => i2ci,
141  i2co => i2co,
142  -- I2C Register Interface
143  regIn => r.regIn,
144  regOut => regOut,
145  -- Clock and Reset
146  clk => axilClk,
147  srst => axilRst);
148 
149  comb : process (axilReadMaster, axilRst, axilWriteMaster, r, regOut) is
150  variable v : regType;
151  variable axilStatus : AxiLiteStatusType;
152  variable axilResp : slv(1 downto 0);
153  begin
154  -- Latch the current value
155  v := r;
156 
157  -- Determine the transaction type
158  axiSlaveWaitTxn(axilWriteMaster, axilReadMaster, v.axilWriteSlave, v.axilReadSlave, axilStatus);
159 
160  -- Update the AXI-Lite response
161  axilResp := ite(regOut.regFail = '1', AXI_ERROR_RESP_G, AXI_RESP_OK_C);
162 
163  -- State Machine
164  case (r.state) is
165  ----------------------------------------------------------------------
166  when IDLE_S =>
167  if regOut.regAck = '0' then
168  -- Check for a write request
169  if (axilStatus.writeEnable = '1') then
170  -- Set the flag
171  v.RnW := '0';
172  -- Send read transaction to I2cRegMaster
173  v.regIn.regReq := '1';
174  v.regIn.regOp := '0'; -- Read (then modify write) operation
175  v.regIn.regAddr(ADDR_WIDTH_G-1 downto 0) := axilWriteMaster.awaddr(ADDR_WIDTH_G-1 downto 0);
176  -- Next state
177  v.state := READ_ACK_S;
178  -- Check for a read request
179  elsif (axilStatus.readEnable = '1') then
180  -- Set the flag
181  v.RnW := '1';
182  -- Send read transaction to I2cRegMaster
183  v.regIn.regReq := '1';
184  v.regIn.regOp := '0'; -- Read operation
185  v.regIn.regAddr(ADDR_WIDTH_G-1 downto 0) := axilReadMaster.araddr(ADDR_WIDTH_G-1 downto 0);
186  -- Next state
187  v.state := READ_ACK_S;
188  end if;
189  end if;
190  ----------------------------------------------------------------------
191  when READ_ACK_S =>
192  -- Wait for completion
193  if regOut.regAck = '1' then
194  -- Reset the flag
195  v.regIn.regReq := '0';
196  -- Check for write operation
197  if r.RnW = '0' then
198  -- Check for I2C failure
199  if regOut.regFail = '1' then
200  -- Send AXI-Lite response
201  axiSlaveWriteResponse(v.axilWriteSlave, axilResp);
202  -- Next state
203  v.state := WAIT_S;
204  -- Check if not modification required
205  elsif axilWriteMaster.wData = regOut.regRdData then
206  -- Send AXI-Lite response
207  axiSlaveWriteResponse(v.axilWriteSlave, axilResp);
208  -- Next state
209  v.state := IDLE_S;
210  else
211  -- Next state
212  v.state := READ_DONE_S;
213  end if;
214  -- Else read operation
215  else
216  -- Check for I2C failure
217  if regOut.regFail = '1' then
218  -- Next state
219  v.state := WAIT_S;
220  -- Forward error code on the data bus for debugging
221  v.axilReadSlave.rdata := X"000000" & regOut.regFailCode;
222  else
223  -- Forward the readout data
224  v.axilReadSlave.rdata := regOut.regRdData;
225  -- Next state
226  v.state := IDLE_S;
227  end if;
228  -- Send AXI-Lite response
229  axiSlaveReadResponse(v.axilReadSlave, axilResp);
230  end if;
231  end if;
232  ----------------------------------------------------------------------
233  when READ_DONE_S =>
234  if regOut.regAck = '0' then
235  -- Next state
236  v.state := WRITE_REQ_S;
237  end if;
238  ----------------------------------------------------------------------
239  when WRITE_REQ_S =>
240  -- Send write transaction to I2cRegMaster
241  v.regIn.regReq := '1';
242  v.regIn.regOp := '1'; -- Write operation
243  v.regIn.regWrData := axilWriteMaster.wData;
244  -- Next state
245  v.state := WRITE_ACK_S;
246  ----------------------------------------------------------------------
247  when WRITE_ACK_S =>
248  -- Wait for completion
249  if regOut.regAck = '1' then
250  -- Reset the flag
251  v.regIn.regReq := '0';
252  -- Send AXI-Lite response
253  axiSlaveWriteResponse(v.axilWriteSlave, axilResp);
254  -- Check for I2C failure
255  if regOut.regFail = '1' then
256  -- Next state
257  v.state := IDLE_S;
258  else
259  -- Next state
260  v.state := WRITE_DONE_S;
261  end if;
262  end if;
263  ----------------------------------------------------------------------
264  when WRITE_DONE_S =>
265  if regOut.regAck = '0' then
266  -- Next state
267  v.state := WAIT_S;
268  end if;
269  ----------------------------------------------------------------------
270  when WAIT_S =>
271  -- Increment the counter
272  v.timer := r.timer + 1;
273  -- Check counter
274  if (r.timer = TIMEOUT_C) then
275  -- Reset the counter
276  v.timer := 0;
277  -- Next state
278  v.state := IDLE_S;
279  end if;
280  ----------------------------------------------------------------------
281  end case;
282 
283  -- Synchronous Reset
284  if (axilRst = '1') then
285  v := REG_INIT_C;
286  end if;
287 
288  -- Register the variable for next clock cycle
289  rin <= v;
290 
291  -- Outputs
294 
295  end process comb;
296 
297  seq : process (axilClk) is
298  begin
299  if (rising_edge(axilClk)) then
300  r <= rin after TPD_G;
301  end if;
302  end process seq;
303 
304 end rtl;
in regInI2cRegMasterInType
in axilWriteMasterAxiLiteWriteMasterType
_library_ unisimunisim
in i2cii2c_in_type
i2c_in_type
Definition: I2cPkg.vhd:34
slv( 31 downto 0) regAddr
Definition: I2cPkg.vhd:82
AxiLiteWriteMasterType
Definition: AxiLitePkg.vhd:111
std_logic sl
Definition: StdRtlPkg.vhd:28
sl endianness
Definition: I2cPkg.vhd:90
slv( 31 downto 0) rdata
Definition: AxiLitePkg.vhd:89
in srstsl := '0'
sl regOp
Definition: I2cPkg.vhd:84
in i2cii2c_in_type
AXI_CLK_FREQ_Greal := 156.25E+6
OUTPUT_EN_POLARITY_Ginteger range 0 to 1:= 0
slv( 7 downto 0) regFailCode
Definition: I2cPkg.vhd:113
TPD_Gtime := 1 ns
I2C_MIN_PULSE_Greal := 100.0E-9
slv( 1 downto 0) := "10" AXI_RESP_SLVERR_C
Definition: AxiLitePkg.vhd:36
I2cRegMasterOutType
Definition: I2cPkg.vhd:110
I2C_SCL_FREQ_Greal := 100.0E+3
AXI_ERROR_RESP_Gslv( 1 downto 0) := AXI_RESP_SLVERR_C
i2c_out_type
Definition: I2cPkg.vhd:41
AxiLiteReadMasterType
Definition: AxiLitePkg.vhd:59
sl tenbit
Definition: I2cPkg.vhd:65
sl regReq
Definition: I2cPkg.vhd:88
POLL_TIMEOUT_Gpositive := 16
slv( 31 downto 0) awaddr
Definition: AxiLitePkg.vhd:113
I2C_ADDR_Gslv( 6 downto 0) := "1010000"
_library_ ieeeieee
AxiLiteReadSlaveType :=(arready => '0',rdata =>( others => '0'),rresp =>( others => '0'),rvalid => '0') AXI_LITE_READ_SLAVE_INIT_C
Definition: AxiLitePkg.vhd:95
slv( 9 downto 0) i2cAddr
Definition: I2cPkg.vhd:80
I2cRegMasterInType
Definition: I2cPkg.vhd:79
out i2coi2c_out_type
AxiLiteReadSlaveType
Definition: AxiLitePkg.vhd:85
slv( 31 downto 0) regRdData
Definition: I2cPkg.vhd:114
in axilReadMasterAxiLiteReadMasterType
slv( 1 downto 0) := "00" AXI_RESP_OK_C
Definition: AxiLitePkg.vhd:31
out axilReadSlaveAxiLiteReadSlaveType
slv( 31 downto 0) araddr
Definition: AxiLitePkg.vhd:61
sl busReq
Definition: I2cPkg.vhd:63
out i2coi2c_out_type
ADDR_WIDTH_Gpositive := 16
out axilWriteSlaveAxiLiteWriteSlaveType
FILTER_Ginteger range 2 to 512:= 8
out regOutI2cRegMasterOutType
sl regAck
Definition: I2cPkg.vhd:111
sl repeatStart
Definition: I2cPkg.vhd:91
sl regFail
Definition: I2cPkg.vhd:112
AxiLiteWriteSlaveType :=(awready => '0',wready => '0',bresp =>( others => '0'),bvalid => '0') AXI_LITE_WRITE_SLAVE_INIT_C
Definition: AxiLitePkg.vhd:156
PRESCALE_Ginteger range 0 to 655535:= 62
slv( 31 downto 0) regWrData
Definition: I2cPkg.vhd:83
std_logic_vector slv
Definition: StdRtlPkg.vhd:29