SURF  1.0
AdiConfigSlave.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 -- File : AdiConfigSlave.vhd
3 -- Company : SLAC National Accelerator Laboratory
4 -- Created : 2014-01-14
5 -- Last update: 2016-11-14
6 -------------------------------------------------------------------------------
7 -- Description: An implementation of the common SPI configuration interface
8 -- use by many AnalogDevices chips.
9 -------------------------------------------------------------------------------
10 -- This file is part of 'SLAC Firmware Standard Library'.
11 -- It is subject to the license terms in the LICENSE.txt file found in the
12 -- top-level directory of this distribution and at:
13 -- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html.
14 -- No part of 'SLAC Firmware Standard Library', including this file,
15 -- may be copied, modified, propagated, or distributed except according to
16 -- the terms contained in the LICENSE.txt file.
17 -------------------------------------------------------------------------------
18 
19 library ieee;
20 use ieee.std_logic_1164.all;
21 use ieee.std_logic_unsigned.all;
22 use ieee.std_logic_arith.all;
23 use work.StdRtlPkg.all;
24 
25 --! @see entity
26  --! @ingroup devices_AnalogDevices_general
27 entity AdiConfigSlave is
28 
29  generic (
30  TPD_G : time := 1 ns);
31 
32  port (
33  clk : in sl;
34 
35  sclk : in sl;
36  sdio : inout sl;
37  csb : in sl;
38 
39  wrEn : out sl;
40  rdEn : out sl;
41  addr : out slv(12 downto 0);
42  wrData : out slv(31 downto 0);
43  byteValid : out slv(3 downto 0);
44  rdData : in slv(31 downto 0));
45 
46 end entity AdiConfigSlave;
47 
48 architecture behavioral of AdiConfigSlave is
49 
50  type StateType is (
51  WAIT_CSB_FALL_S,
52  SHIFT_HEADER_S,
53  LATCH_HEADER_S,
54  WRITE_S,
55  LATCH_WRITE_BYTE_S,
56  READ_WAIT_S,
57  LATCH_READ_BYTE_S,
58  READ_S,
59  WAIT_SCLK_RISE_S);
60 
61  type RegType is record
63  count : slv(3 downto 0);
64  shift : slv(15 downto 0);
65  bytes : slv(1 downto 0);
66  wrEn : sl;
67  rdEn : sl;
68  addr : slv(12 downto 0);
69  wrData : slv(31 downto 0);
70  byteValid : slv(3 downto 0);
72  end record RegType;
73 
74  constant REG_INIT_C : RegType := (
75  state => WAIT_CSB_FALL_S,
76  count => (others => '0'),
77  shift => (others => '0'),
78  bytes => (others => '0'),
79  wrEn => '0',
80  rdEn => '0',
81  addr => (others => '0'),
82  wrData => (others => '0'),
83  byteValid => (others => '0'),
84  dataOut => '1');
85 
86  signal r : RegType := REG_INIT_C;
87  signal rin : RegType;
88 
89  signal sdioRes : sl;
90  signal sdioSync : sl;
91  signal sdioRise : sl;
92  signal sdioFall : sl;
93  signal sclkRes : sl;
94  signal sclkSync : sl;
95  signal sclkRise : sl;
96  signal sclkFall : sl;
97  signal csbRes : sl;
98  signal csbSync : sl;
99  signal csbRise : sl;
100  signal csbFall : sl;
101 
102 begin
103 
104  sdio <= '0' when r.dataOut = '0' else 'Z';
105 
106  sdioRes <= to_x01z(sdio);
107  sclkRes <= to_x01z(sclk);
108  csbRes <= to_x01z(csb);
109 
110  SynchronizerEdge_SDIO : entity work.SynchronizerEdge
111  generic map (
112  TPD_G => TPD_G)
113  port map (
114  clk => clk,
115  rst => '0',
116  dataIn => sdioRes,
117  dataOut => sdioSync,
118  risingEdge => sdioRise,
119  fallingEdge => sdioFall);
120 
121  SynchronizerEdge_SCLK : entity work.SynchronizerEdge
122  generic map (
123  TPD_G => TPD_G)
124  port map (
125  clk => clk,
126  rst => '0',
127  dataIn => sclkRes,
128  dataOut => sclkSync,
129  risingEdge => sclkRise,
130  fallingEdge => sclkFall);
131 
132  SynchronizerEdge_CSB : entity work.SynchronizerEdge
133  generic map (
134  TPD_G => TPD_G)
135  port map (
136  clk => clk,
137  rst => '0',
138  dataIn => csbRes,
139  dataOut => csbSync,
140  risingEdge => csbRise,
141  fallingEdge => csbFall);
142 
143  comb : process (csbFall, r, rdData, sclkFall, sclkRise, sdioSync) is
144  variable v : RegType;
145  begin
146  v := r;
147  v.wrEn := '0';
148  v.dataOut := '1';
149  case (r.state) is
150  when WAIT_CSB_FALL_S =>
151  v.rdEn := '0';
152  v.shift := (others => '0');
153  v.count := (others => '0');
154  if (csbFall = '1') then
155  v.state := SHIFT_HEADER_S;
156  end if;
157 
158  when SHIFT_HEADER_S =>
159  if (sclkRise = '1') then
160  v.shift := r.shift(14 downto 0) & sdioSync;
161  v.count := r.count + 1;
162  if (r.count = 15) then
163  v.state := LATCH_HEADER_S;
164  end if;
165  end if;
166 
167  when LATCH_HEADER_S =>
168  v.addr := r.shift(12 downto 0);
169  case (r.shift(14 downto 13)) is
170  when "00" =>
171  v.byteValid := "0001";
172  when "01" =>
173  v.byteValid := "0011";
174  when "10" =>
175  v.byteValid := "0111";
176  when "11" =>
177  v.byteValid := "1111"; -- No support yet for streaming
178  when others =>
179  v.byteValid := "0000";
180  end case;
181  v.bytes := r.shift(14 downto 13);
182 
183  if (r.shift(15) = '0') then
184  v.state := WRITE_S;
185  else
186  v.state := READ_WAIT_S;
187  v.rdEn := '1';
188  end if;
189 
190  when WRITE_S =>
191  if (sclkRise = '1') then
192  v.shift := v.shift(14 downto 0) & sdioSync;
193  v.count := r.count + 1;
194  if (r.count = 7) then
195  v.state := LATCH_WRITE_BYTE_S;
196  end if;
197  end if;
198 
199  when LATCH_WRITE_BYTE_S =>
200  v.wrData(conv_integer(r.bytes)*8+7 downto conv_integer(r.bytes)*8) := r.shift(7 downto 0);
201 
202  v.count := (others => '0');
203  if (r.bytes = 0) then
204  v.wrEn := '1';
205  v.state := WAIT_CSB_FALL_S;
206  else
207  v.bytes := r.bytes - 1;
208  v.state := WRITE_S;
209  end if;
210 
211  when READ_WAIT_S =>
212  v.dataOut := r.dataOut;
213  v.state := LATCH_READ_BYTE_S;
214 
215  when LATCH_READ_BYTE_S =>
216  v.dataOut := r.dataOut;
217  v.shift(7 downto 0) := rdData(conv_integer(r.bytes)*8+7 downto conv_integer(r.bytes)*8);
218  v.count := (others => '0');
219  v.state := READ_S;
220 
221  when READ_S =>
222  v.dataOut := r.dataOut;
223  if (sclkFall = '1') then
224  v.dataOut := v.shift(7);
225  v.shift := v.shift(14 downto 0) & '0';
226  v.count := r.count + 1;
227  if (r.count = 7) then
228  v.bytes := r.bytes - 1;
229  if(r.bytes = 0) then
230  v.state := WAIT_SCLK_RISE_S;
231  else
232  v.state := LATCH_READ_BYTE_S;
233  end if;
234  end if;
235  end if;
236 
237  when WAIT_SCLK_RISE_S =>
238  -- Hold last rd data until it has been sampled and txn is over
239  v.dataOut := r.dataOut;
240  if (sclkRise = '1') then
241  v.state := WAIT_CSB_FALL_S;
242  end if;
243 
244  end case;
245 
246 
247  rin <= v;
248  wrData <= r.wrData;
249  wrEn <= r.wrEn;
250  rdEn <= r.rdEn;
251  addr <= r.addr;
252  byteValid <= r.byteValid;
253 
254 
255  end process comb;
256 
257  seq : process (clk) is
258  begin
259  if (rising_edge(clk)) then
260  r <= rin after TPD_G;
261  end if;
262  end process seq;
263 
264 
265 
266 
267 end architecture behavioral;
out byteValidslv( 3 downto 0)
RegType := REG_INIT_C r
std_logic sl
Definition: StdRtlPkg.vhd:28
slv( 31 downto 0) wrData
out addrslv( 12 downto 0)
slv( 3 downto 0) byteValid
out wrDataslv( 31 downto 0)
in rstsl :=not RST_POLARITY_G
_library_ ieeeieee
slv( 15 downto 0) shift
RegType :=(state => WAIT_CSB_FALL_S,count =>( others => '0'),shift =>( others => '0'),bytes =>( others => '0'),wrEn => '0',rdEn => '0',addr =>( others => '0'),wrData =>( others => '0'),byteValid =>( others => '0'),dataOut => '1') REG_INIT_C
(WAIT_CSB_FALL_S,SHIFT_HEADER_S,LATCH_HEADER_S,WRITE_S,LATCH_WRITE_BYTE_S,READ_WAIT_S,LATCH_READ_BYTE_S,READ_S,WAIT_SCLK_RISE_S) StateType
in rdDataslv( 31 downto 0)
slv( 12 downto 0) addr
TPD_Gtime := 1 ns
std_logic_vector slv
Definition: StdRtlPkg.vhd:29