SURF  1.0
SaciMasterSync.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 -- File : SaciMasterSync.vhd
3 -- Company : SLAC National Accelerator Laboratory
4 -- Created : 2012-08-10
5 -- Last update: 2017-05-10
6 -------------------------------------------------------------------------------
7 -- Description: Saci Master Synchronization Wrapper
8 -------------------------------------------------------------------------------
9 -- This file is part of 'SLAC Firmware Standard Library'.
10 -- It is subject to the license terms in the LICENSE.txt file found in the
11 -- top-level directory of this distribution and at:
12 -- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html.
13 -- No part of 'SLAC Firmware Standard Library', including this file,
14 -- may be copied, modified, propagated, or distributed except according to
15 -- the terms contained in the LICENSE.txt file.
16 -------------------------------------------------------------------------------
17 
18 library IEEE;
19 use IEEE.std_logic_1164.all;
20 use ieee.numeric_std.all;
21 use work.StdRtlPkg.all;
22 -- use work.SynchronizePkg.all;
23 use work.SaciMasterPkg.all;
24 
25 --! @see entity
26  --! @ingroup protocols_saci
27 entity SaciMasterSync is
28 
29  generic (
30  TPD_G : time := 1 ns;
31  SYNCHRONIZE_CONTROL_G : boolean := true
32  );
33 
34  port (
35  clk : in sl; -- Main clock
36  rst : in sl;
37 
38  -- Serial interface
39  saciClk : out sl;
40  saciSelL : out slv(SACI_NUM_SLAVES_C-1 downto 0);
41  saciCmd : out sl;
42  saciRsp : in sl;
43 
44  saciHalfClk : in slv(7 downto 0);
45 
46  -- Parallel interface
49 
50 end entity SaciMasterSync;
51 
52 architecture rtl of SaciMasterSync is
53 
54  type SynchronizerType is record
55  tmp : sl;
56  sync : sl;
57  last : sl;
58  end record;
59  constant SYNCHRONIZER_INIT_0_C : SynchronizerType := (tmp => '0', sync => '0', last => '0');
60  constant SYNCHRONIZER_INIT_1_C : SynchronizerType := (tmp => '1', sync => '1', last => '1');
61  procedure synchronize (
62  input : in sl;
63  current : in SynchronizerType;
64  nextOut : out SynchronizerType) is
65  begin
66  nextOut.tmp := input;
67  nextOut.sync := current.tmp;
68  nextOut.last := current.sync;
69  end procedure;
70 
71  type StateType is (IDLE_S, CHIP_SELECT_S, TX_S, RX_START_S, RX_HEADER_S, RX_DATA_S, ACK_S);
72 
73  type RegType is record
74  reqSync : SynchronizerType;
75  resetSync : SynchronizerType;
76  state : StateType;
77  shiftReg : slv(52 downto 0);
78  shiftCount : unsigned(5 downto 0);
79 
80  saciSelL : slv(SACI_NUM_SLAVES_C-1 downto 0);
81  saciCmd : sl;
83  end record RegType;
84 
85  signal r, rin : RegType;
86  signal saciRspFall : sl;
87 
88  signal saciClkCnt : unsigned(31 downto 0);
89  signal saciClkCntRst : std_logic;
90  signal saciClkRising : std_logic;
91  signal saciClkFalling : std_logic;
92  signal iSaciClk : std_logic;
93  signal iSaciClkD : std_logic;
94 
95 begin
96 
97  --------------------------------------------------------------------------------------------------
98  -- Saci clock counter
99  --------------------------------------------------------------------------------------------------
100  saci_clk_p : process (clk, rst) is
101  begin
102  if rising_edge(clk) then
103 
104  if rst = '1' or saciClkCntRst = '1' then
105  saciClkCnt <= (others=>'0') after TPD_G;
106  elsif saciClkCnt = to_integer(unsigned(saciHalfClk)) then
107  saciClkCnt <= (others=>'0') after TPD_G;
108  else
109  saciClkCnt <= saciClkCnt + 1 after TPD_G;
110  end if;
111 
112  if rst = '1' or saciClkCntRst = '1' then
113  iSaciClk <= '0' after TPD_G;
114  elsif saciClkCnt = to_integer(unsigned(saciHalfClk)) then
115  iSaciClk <= not iSaciClk after TPD_G;
116  end if;
117 
118  if rst = '1' or saciClkCntRst = '1' then
119  iSaciClkD <= '0' after TPD_G;
120  else
121  iSaciClkD <= iSaciClk after TPD_G;
122  end if;
123 
124  end if;
125  end process;
126 
127  saciClk <= iSaciClk;
128  saciClkRising <= iSaciClk and not iSaciClkD;
129  saciClkFalling <= iSaciClkD and not iSaciClk;
130 
131 
132  --------------------------------------------------------------------------------------------------
133  -- Capture serial input
134  --------------------------------------------------------------------------------------------------
135  fall : process (clk, rst) is
136  begin
137  if (rst = '1') then
138  saciRspFall <= '0' after TPD_G;
139  elsif (rising_edge(clk)) then
140  saciRspFall <= saciRsp after TPD_G;
141  end if;
142  end process fall;
143 
144  seq : process (clk, rst) is
145  begin
146  if (rst = '1') then
147  r.reqSync <= SYNCHRONIZER_INIT_0_C after TPD_G;
148  r.resetSync <= SYNCHRONIZER_INIT_0_C after TPD_G;
149  r.state <= IDLE_S after TPD_G;
150  r.shiftReg <= (others => '0') after TPD_G;
151  r.shiftCount <= (others => '0') after TPD_G;
152  r.saciSelL <= (others => '1') after TPD_G;
153  r.saciCmd <= '0' after TPD_G;
154  r.saciMasterOut.ack <= '0' after TPD_G;
155  r.saciMasterOut.fail <= '0' after TPD_G;
156  r.saciMasterOut.rdData <= (others => '0') after TPD_G;
157  elsif (rising_edge(clk)) then
158  r <= rin after TPD_G;
159  end if;
160  end process seq;
161 
162  comb : process (r, saciRspFall, saciMasterIn, saciClkRising) is
163  variable rVar : RegType;
164  variable reqVar : sl;
165  variable resetVar : sl;
166  begin
167  rVar := r;
168 
169  -- Synchronize control inputs to serial clock
170  synchronize(saciMasterIn.req, r.reqSync, rVar.reqSync);
171  synchronize(saciMasterIn.reset, r.resetSync, rVar.resetSync);
172  if (SYNCHRONIZE_CONTROL_G) then
173  reqVar := r.reqSync.sync;
174  resetVar := r.resetSync.sync;
175  else
176  reqVar := saciMasterIn.req;
177  resetVar := saciMasterIn.reset;
178  end if;
179 
180  rVar.shiftCount := (others => '0');
181  rVar.saciMasterOut.ack := '0';
182 
183  saciClkCntRst <= '0';
184 
185  if (resetVar = '1') then
186  rVar.saciSelL := (others => '1');
187  rVar.shiftReg := (others => '0');
188  rVar.shiftCount := (others => '0');
189  rVar.state := IDLE_S;
190  rVar.saciMasterOut.ack := '1';
191  else
192 
193  case (r.state) is
194  when IDLE_S =>
195  saciClkCntRst <= '1';
196  rVar.saciMasterOut.fail := '0';
197  rVar.saciSelL := (others => '1');
198  rVar.shiftReg := (others => '0');
199  rVar.shiftCount := (others => '0');
200  if (reqVar = '1') then
201  saciClkCntRst <= '0';
202  -- New command, load shift reg
203  rVar.shiftReg(52) := '1'; -- Start bit
204  rVar.shiftReg(51) := saciMasterIn.op;
205  rVar.shiftReg(50 downto 44) := saciMasterIn.cmd;
206  rVar.shiftReg(43 downto 32) := saciMasterIn.addr;
207  if (saciMasterIn.op = '1') then
208  rVar.shiftReg(31 downto 0) := saciMasterIn.wrData;
209  else
210  rVar.shiftReg(31 downto 0) := (others => '0');
211  end if;
212  rVar.state := CHIP_SELECT_S;
213  end if;
214 
215  when CHIP_SELECT_S =>
216  rVar.saciSelL := (others => '1');
217  rVar.saciSelL(to_integer(unsigned(saciMasterIn.chip))) := '0';
218  if saciClkRising = '1' then
219  rVar.state := TX_S;
220  else
221  rVar.state := CHIP_SELECT_S;
222  end if;
223 
224  when TX_S =>
225  -- Shift out data on saciCmd
226  rVar.saciCmd := r.shiftReg(52);
227  if saciClkRising = '1' then
228  rVar.shiftReg := r.shiftReg(51 downto 0) & '0';
229  rVar.shiftCount := r.shiftCount + 1;
230  else
231  rVar.shiftReg := r.shiftReg;
232  rVar.shiftCount := r.shiftCount;
233  end if;
234 
235  if (saciMasterIn.op = '0' and r.shiftCount = 21) then -- Read
236  rVar.state := RX_START_S;
237  elsif (saciMasterIn.op = '1' and r.shiftCount = 53) then -- Write
238  rVar.state := RX_START_S;
239  end if;
240 
241 
242  when RX_START_S =>
243  -- Wait for saciRsp start bit
244  rVar.shiftCount := (others => '0');
245  if (saciRspFall = '1' and saciClkRising = '1') then
246  rVar.state := RX_HEADER_S;
247  else
248  rVar.state := RX_START_S;
249  end if;
250 
251  when RX_HEADER_S =>
252  -- Shift data in and check that header is correct
253  if saciClkRising = '1' then
254  rVar.shiftCount := r.shiftCount + 1;
255  --shiftInLeft(saciRspFall, r.shiftReg, rVar.shiftReg);
256  rVar.shiftReg := r.shiftReg(r.shiftReg'high-1 downto r.shiftReg'low) & saciRspFall;
257  else
258  rVar.shiftCount := r.shiftCount;
259  rVar.shiftReg := r.shiftReg;
260  end if;
261  if (r.shiftCount = 20) then
262  if (r.shiftReg(19) /= saciMasterIn.op or
263  r.shiftReg(18 downto 12) /= saciMasterIn.cmd or
264  r.shiftReg(11 downto 0) /= saciMasterIn.addr) then
265  rVar.saciMasterOut.fail := '1';
266  end if;
267  if (saciMasterIn.op = '0') then
268  rVar.state := RX_DATA_S;
269  else
270  rVar.state := ACK_S;
271  end if;
272  end if;
273 
274  when RX_DATA_S =>
275  if saciClkRising = '1' then
276  rVar.shiftCount := r.shiftCount + 1;
277  --shiftInLeft(saciRspFall, r.shiftReg, rVar.shiftReg);
278  rVar.shiftReg := r.shiftReg(r.shiftReg'high-1 downto r.shiftReg'low) & saciRspFall;
279  if (r.shiftCount = 51) then
280  rVar.state := ACK_S;
281  end if;
282  else
283  rVar.shiftCount := r.shiftCount;
284  rVar.shiftReg := r.shiftReg;
285  end if;
286 
287 
288 
289  when ACK_S =>
290  rVar.saciMasterOut.ack := '1';
291  rVar.saciMasterOut.rdData := r.shiftReg(31 downto 0);
292  if (reqVar = '0') then
293  rVar.saciMasterOut.ack := '0';
294  rVar.saciMasterOut.fail := '0';
295  rVar.state := IDLE_S;
296  end if;
297 
298  when others => null;
299  end case;
300 
301  end if;
302 
303  rin <= rVar;
304 
305  saciSelL <= r.saciSelL;
306  saciCmd <= r.saciCmd;
308 
309  end process comb;
310 
311 end architecture rtl;
SYNCHRONIZE_CONTROL_Gboolean := true
out saciMasterOutSaciMasterOutType
slv( 11 downto 0) addr
std_logic sl
Definition: StdRtlPkg.vhd:28
slv( 31 downto 0) wrData
slv( 6 downto 0) cmd
out saciSelLslv( SACI_NUM_SLAVES_C- 1 downto 0)
positive := 4 SACI_NUM_SLAVES_C
_library_ IEEEIEEE
TPD_Gtime := 1 ns
in saciHalfClkslv( 7 downto 0)
slv( 31 downto 0) rdData
in saciMasterInSaciMasterInType
slv( SACI_CHIP_WIDTH_C- 1 downto 0) chip
std_logic_vector slv
Definition: StdRtlPkg.vhd:29