SURF  1.0
I2cRegMaster.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 -- File : I2cRegMaster.vhd
3 -- Company : SLAC National Accelerator Laboratory
4 -- Created : 2013-01-22
5 -- Last update: 2016-07-11
6 -------------------------------------------------------------------------------
7 -- Description:
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 -------------------------------------------------------------------------------
19 
20 library ieee;
21 use ieee.std_logic_1164.all;
22 use ieee.numeric_std.all;
23 
24 use work.StdRtlPkg.all;
25 use work.I2cPkg.all;
26 
27 --! @see entity
28  --! @ingroup protocols_i2c
29 entity I2cRegMaster is
30 
31  generic (
32  TPD_G : time := 1 ns;
33  OUTPUT_EN_POLARITY_G : integer range 0 to 1 := 0;
34  FILTER_G : integer range 2 to 512 := 8;
35  PRESCALE_G : integer range 0 to 655535 := 62);
36  port (
37  clk : in sl;
38  srst : in sl := '0';
39  arst : in sl := '0';
40  regIn : in I2cRegMasterInType;
41  regOut : out I2cRegMasterOutType;
44 
45 end entity I2cRegMaster;
46 
47 architecture rtl of I2cRegMaster is
48 
49  type StateType is (
50  WAIT_REQ_S,
51  ADDR_S,
52  WRITE_S,
53  READ_TXN_S,
54  READ_S,
55  BUS_ACK_S,
56  REG_ACK_S);
57 
58  type RegType is record
59  state : StateType;
60  byteCount : unsigned(1 downto 0);
61  regOut : I2cRegMasterOutType;
62  i2cMasterIn : I2cMasterInType;
63  end record RegType;
64 
65  constant REG_INIT_C : RegType := (
66  state => WAIT_REQ_S,
67  byteCount => (others => '0'),
68  regOut => (
69  regAck => '0',
70  regFail => '0',
71  regFailCode => (others => '0'),
72  regRdData => (others => '0')),
73  i2cMasterIn => (
74  enable => '0',
75  prescale => (others => '0'),
76  filter => (others => '0'),
77  txnReq => '0',
78  stop => '0',
79  op => '0',
80  busReq => '0',
81  addr => (others => '0'),
82  tenbit => '0',
83  wrValid => '0',
84  wrData => (others => '0'),
85  rdAck => '0'));
86 
87  signal r : RegType := REG_INIT_C;
88  signal rin : RegType;
89  signal i2cMasterIn : I2cMasterInType;
90  signal i2cMasterOut : I2cMasterOutType;
91 
92  function getIndex (
93  endianness : sl;
94  byteCount : unsigned;
95  totalBytes : unsigned)
96  return integer is
97  begin
98  if (endianness = '0') then
99  -- little endian
100  return to_integer(byteCount)*8;
101  else
102  -- big endian
103  return (to_integer(totalBytes)-to_integer(byteCount))*8;
104  end if;
105  end function getIndex;
106 
107 begin
108 
109  i2cMaster_1 : entity work.I2cMaster
110  generic map (
111  TPD_G => TPD_G,
113  FILTER_G => FILTER_G,
114  DYNAMIC_FILTER_G => 0)
115  port map (
116  clk => clk,
117  srst => srst,
118  arst => arst,
119  i2cMasterIn => i2cMasterIn,
120  i2cMasterOut => i2cMasterOut,
121  i2ci => i2ci,
122  i2co => i2co);
123 
124  comb : process (regIn, i2cMasterOut, r, srst) is
125  variable v : RegType;
126  variable addrIndexVar : integer;
127  variable dataIndexVar : integer;
128  begin
129  v := r;
130 
131  addrIndexVar := getIndex(regIn.endianness, r.byteCount, unsigned(regIn.regAddrSize));
132  dataIndexVar := getIndex(regIn.endianness, r.byteCount, unsigned(regIn.regDataSize));
133 
134  v.regOut.regAck := '0';
135  v.regOut.regFail := '0';
136 
137  v.i2cMasterIn.rdAck := '0';
138 
139  case r.state is
140  when WAIT_REQ_S =>
141  v.byteCount := (others => '0');
142  if (regIn.regReq = '1') then
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
148  v.i2cMasterIn.stop := ite(regIn.regOp = '0' and regIn.repeatStart = '1', '0', '1');
149  v.i2cMasterIn.busReq := regIn.busReq;
150  v.state := ADDR_S;
151  if regIn.busReq = '1' then
152  v.state := BUS_ACK_S;
153  elsif (regIn.regAddrSkip = '1') then
154  if (regIn.regOp = '1') then
155  v.state := WRITE_S;
156  else
157  v.i2cMasterIn.op := '0';
158  v.state := READ_S;
159  end if;
160  end if;
161  end if;
162 
163  when ADDR_S =>
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
167  v.i2cMasterIn.wrData := regIn.regAddr(addrIndexVar+7 downto addrIndexVar);
168  v.i2cMasterIn.wrValid := '1';
169  -- Must drop txnReq as last byte is sent if reading
170  v.i2cMasterIn.txnReq := not toSl(slv(r.byteCount) = regIn.regAddrSize and regIn.regOp = '0');
171 
172  if (i2cMasterOut.wrAck = '1') then
173  v.byteCount := r.byteCount + 1;
174  v.i2cMasterIn.wrValid := '0';
175  if (slv(r.byteCount) = regIn.regAddrSize) then
176  -- Done sending addr
177  v.byteCount := (others => '0');
178  if (regIn.regOp = '1') then
179  v.state := WRITE_S;
180  else
181  v.state := READ_TXN_S;
182  end if;
183  end if;
184  end if;
185 
186  when WRITE_S =>
187  -- Txn started in WAIT_REQ_S still active
188  -- Put wrData on the bus one byte at a time
189  v.i2cMasterIn.wrData := regIn.regWrData(dataIndexVar+7 downto dataIndexVar);
190  v.i2cMasterIn.wrValid := '1';
191  v.i2cMasterIn.txnReq := not toSl(slv(r.byteCount) = regIn.regDataSize);
192  v.i2cMasterIn.stop := '1'; -- Send stop when done writing all bytes
193  if (i2cMasterOut.wrAck = '1') then
194  v.byteCount := r.byteCount + 1;
195  v.i2cMasterIn.wrValid := '0';
196  if (slv(r.byteCount) = regIn.regDataSize) then -- could use rxnReq = 0
197  v.state := REG_ACK_S;
198  end if;
199  end if;
200 
201 
202  when READ_TXN_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
207  v.state := READ_S;
208 
209  when READ_S =>
210  -- Drop txnReq on last byte
211  v.i2cMasterIn.txnReq := not toSl(slv(r.byteCount) = regIn.regDataSize);
212  -- Read data bytes as they arrive
213  if (i2cMasterOut.rdValid = '1' and r.i2cMasterIn.rdAck = '0') then
214  v.byteCount := r.byteCount + 1;
215  v.regOut.regRdData(dataIndexVar+7 downto dataIndexVar) := i2cMasterOut.rdData;
216  v.i2cMasterIn.rdAck := '1';
217  if (slv(r.byteCount) = regIn.regDataSize) then
218  -- Done
219  v.state := REG_ACK_S;
220  end if;
221  end if;
222 
223  when BUS_ACK_S =>
224  if i2cMasterOut.busAck = '1' then
225  v.i2cMasterIn.txnReq := '0';
226  v.state := REG_ACK_S;
227  end if;
228 
229  when REG_ACK_S =>
230  -- Req done. Ack the req.
231  -- Might have failed so hold regFail (would be set to 0 otherwise).
232  v.regOut.regAck := '1';
233  v.regOut.regFail := r.regOut.regFail;
234  if (regIn.regReq = '0') then
235 -- v.regOut.regAck := '0'; Might want this back.
236  v.state := WAIT_REQ_S;
237  end if;
238 
239  end case;
240 
241  -- Always check for errors an cancel the txn if they happen
242  if (i2cMasterOut.txnError = '1' and i2cMasterOut.rdValid = '1') then
243  v.regOut.regFail := '1';
244  v.regOut.regFailCode := i2cMasterOut.rdData;
245  v.i2cMasterIn.txnReq := '0';
246  v.i2cMasterIn.rdAck := '1';
247  v.state := REG_ACK_S;
248  end if;
249 
250  ------------------------------------------------------------------------------------------------
251  -- Synchronous Reset
252  ------------------------------------------------------------------------------------------------
253  if (srst = '1') then
254  v := REG_INIT_C;
255  end if;
256 
257  ------------------------------------------------------------------------------------------------
258  -- Signal Assignments
259  ------------------------------------------------------------------------------------------------
260  -- Update registers
261  rin <= v;
262 
263  -- Internal signals
264  i2cMasterIn.enable <= '1';
265  i2cMasterIn.prescale <= slv(to_unsigned(PRESCALE_G, 16));
266  i2cMasterIn.filter <= (others => '0'); -- Not using dynamic filtering
267  i2cMasterIn.addr <= regIn.i2cAddr;
268  i2cMasterIn.tenbit <= regIn.tenbit;
269  i2cMasterIn.txnReq <= r.i2cMasterIn.txnReq;
270  i2cMasterIn.stop <= r.i2cMasterIn.stop;
271  i2cMasterIn.op <= r.i2cMasterIn.op;
272  i2cMasterIn.wrValid <= r.i2cMasterIn.wrValid;
273  i2cMasterIn.wrData <= r.i2cMasterIn.wrData;
274  i2cMasterIn.rdAck <= r.i2cMasterIn.rdAck;
275  i2cMasterIn.busReq <= r.i2cMasterIn.busReq;
276 
277  -- Outputs
278  regOut <= r.regOut;
279 
280  end process comb;
281 
282  seq : process (clk, arst) is
283  begin
284  if (arst = '1') then
285  r <= REG_INIT_C after TPD_G;
286  elsif (rising_edge(clk)) then
287  r <= rin after TPD_G;
288  end if;
289  end process seq;
290 
291 
292 
293 end architecture rtl;
in regInI2cRegMasterInType
sl op
Definition: I2cPkg.vhd:62
I2cMasterInType
Definition: I2cPkg.vhd:56
slv( 1 downto 0) regAddrSize
Definition: I2cPkg.vhd:86
sl rdValid
Definition: I2cPkg.vhd:75
slv( 7 downto 0) rdData
Definition: I2cPkg.vhd:76
in clksl
Definition: I2cMaster.vhd:55
in i2cii2c_in_type
OUTPUT_EN_POLARITY_Ginteger range 0 to 1:= 0
Definition: I2cMaster.vhd:51
i2c_in_type
Definition: I2cPkg.vhd:34
slv( 31 downto 0) regAddr
Definition: I2cPkg.vhd:82
std_logic sl
Definition: StdRtlPkg.vhd:28
sl txnReq
Definition: I2cPkg.vhd:60
sl stop
Definition: I2cPkg.vhd:61
out i2coi2c_out_type
Definition: I2cMaster.vhd:65
in arstsl := '0'
Definition: I2cMaster.vhd:57
slv( 15 downto 0) prescale
Definition: I2cPkg.vhd:58
sl endianness
Definition: I2cPkg.vhd:90
TPD_Gtime := 1 ns
Definition: I2cMaster.vhd:50
in srstsl := '0'
sl regOp
Definition: I2cPkg.vhd:84
I2cMasterOutType
Definition: I2cPkg.vhd:71
DYNAMIC_FILTER_Ginteger range 0 to 1:= 0
Definition: I2cMaster.vhd:53
FILTER_Ginteger range 2 to 512:= 126
Definition: I2cMaster.vhd:52
OUTPUT_EN_POLARITY_Ginteger range 0 to 1:= 0
slv( 7 downto 0) regFailCode
Definition: I2cPkg.vhd:113
slv( 1 downto 0) regDataSize
Definition: I2cPkg.vhd:87
TPD_Gtime := 1 ns
sl regAddrSkip
Definition: I2cPkg.vhd:85
in i2cMasterInI2cMasterInType
Definition: I2cMaster.vhd:59
slv( 7 downto 0) wrData
Definition: I2cPkg.vhd:67
i2c_out_type
Definition: I2cPkg.vhd:41
sl rdAck
Definition: I2cPkg.vhd:68
slv( 15 downto 0) filter
Definition: I2cPkg.vhd:59
sl txnError
Definition: I2cPkg.vhd:73
sl tenbit
Definition: I2cPkg.vhd:65
sl regReq
Definition: I2cPkg.vhd:88
in i2cii2c_in_type
Definition: I2cMaster.vhd:63
slv( 9 downto 0) i2cAddr
Definition: I2cPkg.vhd:80
sl busAck
Definition: I2cPkg.vhd:72
in srstsl := '0'
Definition: I2cMaster.vhd:56
slv( 9 downto 0) addr
Definition: I2cPkg.vhd:64
_library_ ieeeieee
Definition: I2cPkg.vhd:28
slv( 31 downto 0) regRdData
Definition: I2cPkg.vhd:114
sl busReq
Definition: I2cPkg.vhd:63
out i2coi2c_out_type
sl wrValid
Definition: I2cPkg.vhd:66
out i2cMasterOutI2cMasterOutType
Definition: I2cMaster.vhd:60
FILTER_Ginteger range 2 to 512:= 8
out regOutI2cRegMasterOutType
std_ulogic enable
Definition: I2cPkg.vhd:46
sl regAck
Definition: I2cPkg.vhd:111
sl repeatStart
Definition: I2cPkg.vhd:91
sl regFail
Definition: I2cPkg.vhd:112
sl wrAck
Definition: I2cPkg.vhd:74
in arstsl := '0'
PRESCALE_Ginteger range 0 to 655535:= 62
slv( 31 downto 0) regWrData
Definition: I2cPkg.vhd:83
std_logic_vector slv
Definition: StdRtlPkg.vhd:29