SURF  1.0
SaciSlaveOld.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 -- File : SaciSlaveOld.vhd
3 -- Company : SLAC National Accelerator Laboratory
4 -- Created : 2012-07-12
5 -- Last update: 2016-06-17
6 -------------------------------------------------------------------------------
7 -- Description: Slave module for SACI interface. Legacy (bloated) version.
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 
23 --! @see entity
24  --! @ingroup protocols_saci
25 entity SaciSlaveOld is
26 
27  generic (
28  TPD_G : time := 1 ns);
29 
30  port (
31  rstL : in sl; -- ASIC global reset
32 
33  -- Serial Interface
34  saciClk : in sl;
35  saciSelL : in sl; -- chipSelect
36  saciCmd : in sl;
37  saciRsp : out sl;
38 
39  -- Silly reset hack to get saciSelL | rst onto dedicated reset bar
40  rstOutL : out sl;
41  rstInL : in sl;
42 
43  -- Detector (Parallel) Interface
44  exec : out sl;
45  ack : in sl;
46  readL : out sl;
47  cmd : out slv(6 downto 0);
48  addr : out slv(11 downto 0);
49  wrData : out slv(31 downto 0);
50  rdData : in slv(31 downto 0));
51 
52 end entity SaciSlaveOld;
53 
54 architecture rtl of SaciSlaveOld is
55 
56  type StateType is (IDLE_S,
57  SHIFT_HEADER_IN_S,
58  SHIFT_DATA_IN_S,
59  EXEC_S,
60  SHIFT_HEADER_OUT_S,
61  SHIFT_DATA_OUT_S);
62 
63  type RegType is record
64  headerShiftReg : slv(20 downto 0);
65  dataShiftReg : slv(31 downto 0);
66  shiftCount : unsigned(5 downto 0);
67  state : StateType;
68  exec : sl;
69  writeFlag : sl;
70  saciRsp : sl;
71  end record RegType;
72 
73  signal r, rin : RegType;
74  signal saciCmdFall : sl;
75 
76  procedure shiftInLeft (
77  i : in sl;
78  r : in slv;
79  v : out slv) is
80  begin
81  if (r'ascending) then
82  v := r(r'low+1 to r'high) & i;
83  else
84  v := r(r'high-1 downto r'low) & i;
85  end if;
86  end procedure shiftInLeft;
87 
88 begin
89 
90  -- Chip select also functions as async reset
91  rstOutL <= rstL and not saciSelL;
92 
93 
94  -- Clock in serial input on falling edge
95  fall : process (saciClk, rstInL) is
96  begin
97  if (rstInL = '0') then
98  saciCmdFall <= '0' after TPD_G;
99  elsif (falling_edge(saciClk)) then
100  saciCmdFall <= saciCmd after TPD_G;
101  end if;
102  end process fall;
103 
104 
105  seq : process (saciClk, rstInL) is
106  begin
107  if (rstInL = '0') then
108  r.headerShiftReg <= (others => '0') after TPD_G;
109  r.dataShiftReg <= (others => '0') after TPD_G;
110  r.shiftCount <= (others => '0') after TPD_G;
111  r.state <= IDLE_S after TPD_G;
112  r.exec <= '0' after TPD_G;
113  r.writeFlag <= '0' after TPD_G;
114  r.saciRsp <= '0' after TPD_G;
115  elsif (rising_edge(saciClk)) then
116  r <= rin after TPD_G;
117  end if;
118  end process seq;
119 
120  comb : process (r, saciCmdFall, ack, rdData, saciSelL) is
121  variable rVar : RegType;
122  begin
123  rVar := r;
124 
125  -- Defualt values
126  -- Overridden in some states
127  rVar.exec := '0';
128  rVar.saciRsp := '0';
129 
130  -- Main state machine
131  case (r.state) is
132 
133  when IDLE_S =>
134  -- Shift in bits until a start bit is seen
135  shiftInLeft(saciCmdFall, r.headerShiftReg, rVar.headerShiftReg);
136  rVar.shiftCount := (others => '0');
137  rVar.dataShiftReg := (others => '0');
138  if (saciCmdFall = '1') then
139  rVar.state := SHIFT_HEADER_IN_S;
140  end if;
141 
142  when SHIFT_HEADER_IN_S =>
143  -- Shift in the header
144  shiftInLeft(saciCmdFall, r.headerShiftReg, rVar.headerShiftReg);
145  rVar.shiftCount := r.shiftCount + 1;
146  if (r.shiftCount = 19) then
147  -- Header rx'd, check r/w bit
148  rVar.writeFlag := r.headerShiftReg(18);
149  rVar.shiftCount := (others => '0');
150  if (r.headerShiftReg(18) = '1') then -- r/w bit will be at index 19 when frozen
151  -- Write
152  rVar.state := SHIFT_DATA_IN_S;
153  else
154  -- Read
155  rVar.state := EXEC_S;
156  end if;
157  end if;
158 
159  when SHIFT_DATA_IN_S =>
160  -- Write being performed, shift in write data
161  shiftInLeft(saciCmdFall, r.dataShiftReg, rVar.dataShiftReg);
162  rVar.shiftCount := r.shiftCount + 1;
163  if (r.shiftCount = 31) then
164  rVar.state := EXEC_S;
165  end if;
166 
167  when EXEC_S =>
168  -- Do exec/ack cycle
169  rVar.exec := '1';
170  rVar.shiftCount := (others => '0');
171  if (ack = '1') then
172  rVar.dataShiftReg := rdData;
173  rVar.state := SHIFT_HEADER_OUT_S;
174  end if;
175 
176  when SHIFT_HEADER_OUT_S =>
177  -- Always send back the header, even on writes, as an ack to the other side
178  rVar.shiftCount := r.shiftCount + 1;
179  rVar.saciRsp := r.headerShiftReg(20);
180  -- Technically shifting out but its the same
181  -- Any saciCmd data shifted in here will be ignored (but there shouldn't be any)
182  shiftInLeft(saciCmdFall, r.headerShiftReg, rVar.headerShiftReg);
183  if (r.shiftCount = 20) then
184  rVar.shiftCount := (others => '0');
185  if (r.writeFlag = '1') then
186  -- Done
187  rVar.state := IDLE_S;
188  else
189  -- Must now send read data back
190  rVar.state := SHIFT_DATA_OUT_S;
191  end if;
192 
193  end if;
194 
195  when SHIFT_DATA_OUT_S =>
196  -- Read being performed, the read data obtained during EXEC_S
197  rVar.shiftCount := r.shiftCount + 1;
198  rVar.saciRsp := r.dataShiftReg(31);
199  shiftInLeft(saciCmdFall, r.dataShiftReg, rVar.dataShiftReg);
200  if (r.shiftCount = 32) then
201  rVar.state := IDLE_S;
202  end if;
203 
204  when others =>
205  rVar.headerShiftReg := (others => '0');
206  rVar.dataShiftReg := (others => '0');
207  rVar.shiftCount := (others => '0');
208  rVar.state := IDLE_S;
209  rVar.exec := '0';
210  rVar.writeFlag := '0';
211  rVar.saciRsp := '0';
212 
213  end case;
214 
215 
216  rin <= rVar;
217 
218  -- Assign outputs from registers
219  exec <= r.exec;
220  readL <= r.writeFlag;
221  cmd <= r.headerShiftReg(18 downto 12);
222  addr <= r.headerShiftReg(11 downto 0);
223  wrData <= r.dataShiftReg;
224  saciRsp <= r.saciRsp;
225 
226  end process comb;
227 
228 -- data <= r.dataShiftReg when r.writeFlag = '1' else (others => 'Z');
229 -- saciRsp <= r.saciRsp when saciSelL = '0' else 'Z';
230 
231 end architecture rtl;
232 
out rstOutLsl
out addrslv( 11 downto 0)
std_logic sl
Definition: StdRtlPkg.vhd:28
out cmdslv( 6 downto 0)
out saciRspsl
_library_ IEEEIEEE
Definition: SaciSlave.vhd:18
TPD_Gtime := 1 ns
in rdDataslv( 31 downto 0)
out wrDataslv( 31 downto 0)
std_logic_vector slv
Definition: StdRtlPkg.vhd:29