SURF  1.0
SaciMaster2.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 -- File : SaciMaster2.vhd
3 -- Company : SLAC National Accelerator Laboratory
4 -- Created : 2012-08-10
5 -- Last update: 2016-06-17
6 -------------------------------------------------------------------------------
7 -- Description: New and improved version of the SaciMaster.
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.std_logic_unsigned.all;
21 use ieee.std_logic_arith.all;
22 
23 use work.StdRtlPkg.all;
24 
25 --! @see entity
26  --! @ingroup protocols_saci
27 entity SaciMaster2 is
28 
29  generic (
30  TPD_G : time := 1 ns;
31  SYS_CLK_PERIOD_G : real := 8.0e-9;
32  SACI_CLK_PERIOD_G : real := 1.0e-6;
33  SACI_CLK_FREERUN_G : boolean := false;
34  SACI_NUM_CHIPS_G : positive := 1;
35  SACI_RSP_BUSSED_G : boolean := false);
36  port (
37  sysClk : in sl; -- Main clock
38  sysRst : in sl;
39 
40  -- Request interface
41  req : in sl;
42  ack : out sl;
43  fail : out sl;
44  chip : in slv(log2(SACI_NUM_CHIPS_G)-1 downto 0);
45  op : in sl;
46  cmd : in slv(6 downto 0);
47  addr : in slv(11 downto 0);
48  wrData : in slv(31 downto 0);
49  rdData : out slv(31 downto 0);
50 
51  -- Serial interface
52  saciClk : out sl;
53  saciSelL : out slv(SACI_NUM_CHIPS_G-1 downto 0);
54  saciCmd : out sl;
55  saciRsp : in slv(ite(SACI_RSP_BUSSED_G, 0, SACI_NUM_CHIPS_G-1) downto 0));
56 
57 
58 end entity SaciMaster2;
59 
60 architecture rtl of SaciMaster2 is
61 
62  constant SACI_CLK_HALF_PERIOD_C : integer := integer(SACI_CLK_PERIOD_G / (2.0*SYS_CLK_PERIOD_G))-1;
63  constant SACI_CLK_COUNTER_SIZE_C : integer := log2(SACI_CLK_HALF_PERIOD_C);
64 
65  type StateType is (IDLE_S, TX_S, RX_START_S, RX_HEADER_S, RX_DATA_S, ACK_S);
66 
67  type RegType is record
68  state : StateType;
69  shiftReg : slv(52 downto 0);
70  shiftCount : slv(5 downto 0);
71 
72  --Saci clk gen
73  clkCount : slv(SACI_CLK_COUNTER_SIZE_C-1 downto 0);
74  saciClkRising : sl;
75  saciClkFalling : sl;
76 
77  -- System Outputs
78  ack : sl;
79  fail : sl;
80  rdData : slv(31 downto 0);
81 
82  -- SACI Outputs
83  saciClk : sl;
84  saciSelL : slv(SACI_NUM_CHIPS_G-1 downto 0);
85  saciCmd : sl;
86  end record RegType;
87 
88  constant REG_INIT_C : RegType := (
89  state => IDLE_S,
90  shiftReg => (others => '0'),
91  shiftCount => (others => '0'),
92  clkCount => (others => '0'),
93  saciClkRising => '0',
94  saciClkFalling => '0',
95  ack => '0',
96  fail => '0',
97  rdData => (others => '0'),
98  saciClk => '0',
99  saciSelL => (others => '1'),
100  saciCmd => '0');
101 
102  signal r : RegType := REG_INIT_C;
103  signal rin : RegType;
104 
105  signal saciRspSync : slv(saciRsp'range);
106 
107 begin
108 
109  -------------------------------------------------------------------------------------------------
110  -- Synchronize saciRsp to sysClk
111  -------------------------------------------------------------------------------------------------
112  RSP_SYNC : for i in saciRsp'range generate
113  U_Synchronizer_1 : entity work.Synchronizer
114  generic map (
115  TPD_G => TPD_G)
116  port map (
117  clk => sysClk, -- [in]
118  rst => sysRst, -- [in]
119  dataIn => saciRsp(i), -- [in]
120  dataOut => saciRspSync(i)); -- [out]
121  end generate RSP_SYNC;
122 
123  -------------------------------------------------------------------------------------------------
124  -- Main logic
125  -------------------------------------------------------------------------------------------------
126  comb : process (addr, chip, cmd, op, r, req, saciRspSync, sysRst, wrData) is
127  variable v : RegType;
128  variable rspIndex : integer;
129  begin
130  v := r;
131 
132  -- Default values
133  v.ack := '0';
134  rspIndex := ite(SACI_RSP_BUSSED_G, 0, conv_integer(chip));
135 
136  -- Run the saciClk
137  v.clkCount := r.clkCount + 1;
138  if (r.clkCount = SACI_CLK_HALF_PERIOD_C) then
139  v.saciClk := not r.saciClk;
140  v.clkCount := (others => '0');
141  end if;
142 
143  -- Create saciClk edge strobes
144  v.saciClkRising := '0';
145  v.saciClkFalling := '0';
146  if (r.clkCount = SACI_CLK_HALF_PERIOD_C-1) then
147  if (r.saciClk = '0') then
148  v.saciClkRising := '1';
149  end if;
150  if (r.saciClk = '1') then
151  v.saciClkFalling := '1';
152  end if;
153  end if;
154 
155  case (r.state) is
156  when IDLE_S =>
157  v.fail := '0';
158  v.shiftReg := (others => '0');
159  v.shiftCount := (others => '0');
160  v.saciSelL := (others => '1');
161  -- Hold clock inactive while idle
162  -- Make this configurable?
163  if (not SACI_CLK_FREERUN_G) then
164  v.saciClk := '0';
165  v.clkCount := (others => '0');
166  end if;
167 
168  -- Start new command on the falling edge of saciClk
169  -- If clock is not freerunning then start right away
170  if (req = '1' and r.saciClk = '0' and r.clkCount = 0) then
171  -- New command, load shift reg
172  v.shiftReg(52) := '1'; -- Start bit
173  v.shiftReg(51) := op;
174  v.shiftReg(50 downto 44) := cmd;
175  v.shiftReg(43 downto 32) := addr;
176  if (op = '1') then
177  v.shiftReg(31 downto 0) := wrData;
178  else
179  v.shiftReg(31 downto 0) := (others => '0');
180  end if;
181  -- Assert saciSelL line
182  v.saciSelL := not decode(chip)(SACI_NUM_CHIPS_G-1 downto 0);
183  v.state := TX_S;
184  end if;
185 
186  when TX_S =>
187  -- Shift out data on rising edge of saciClk
188  if r.saciClkRising = '1' then
189  v.saciCmd := r.shiftReg(52);
190  v.shiftReg := r.shiftReg(51 downto 0) & '0';
191  v.shiftCount := r.shiftCount + 1;
192  end if;
193 
194  if (op = '0' and r.shiftCount = 21) then -- Read
195  v.state := RX_START_S;
196  elsif (op = '1' and r.shiftCount = 53) then -- Write
197  v.state := RX_START_S;
198  end if;
199 
200 
201  when RX_START_S =>
202  -- Clear last saciCmd on rising edge of saciCLk
203  if (r.saciClkRising = '1') then
204  v.saciCmd := '0';
205  end if;
206 
207  -- Wait for saciRsp start bit
208  v.shiftCount := (others => '0');
209  if (saciRspSync(rspIndex) = '1' and r.saciClkFalling = '1') then
210  v.state := RX_HEADER_S;
211  end if;
212 
213  when RX_HEADER_S =>
214  -- Shift data in and check that header is correct
215  if (r.saciClkFalling = '1') then
216  v.shiftCount := r.shiftCount + 1;
217  v.shiftReg := r.shiftReg(r.shiftReg'high-1 downto r.shiftReg'low) & saciRspSync(rspIndex);
218  end if;
219 
220  if (r.shiftCount = 20) then
221  -- Check that op, cmd and addr in response are correct
222  if (r.shiftReg(19) /= op or
223  r.shiftReg(18 downto 12) /= cmd or
224  r.shiftReg(11 downto 0) /= addr) then
225  v.fail := '1';
226  end if;
227 
228  if (op = '0') then
229  v.state := RX_DATA_S;
230  else
231  v.state := ACK_S;
232  end if;
233  end if;
234 
235  when RX_DATA_S =>
236  if (r.saciClkFalling = '1') then
237  v.shiftCount := r.shiftCount + 1;
238  v.shiftReg := r.shiftReg(r.shiftReg'high-1 downto r.shiftReg'low) & saciRspSync(rspIndex);
239  if (r.shiftCount = 51) then
240  v.state := ACK_S;
241  end if;
242  end if;
243 
244 
245  when ACK_S =>
246  v.ack := '1';
247  v.rdData := r.shiftReg(31 downto 0);
248  if (req = '0') then
249  v.ack := '0';
250  v.fail := '0';
251  v.state := IDLE_S;
252  end if;
253 
254  end case;
255 
256  if (sysRst = '1') then
257  v := REG_INIT_C;
258  end if;
259 
260  rin <= v;
261 
262  saciSelL <= r.saciSelL;
263  saciCmd <= r.saciCmd;
264  saciClk <= r.saciClk;
265  ack <= r.ack;
266  fail <= r.fail;
267  rdData <= r.rdData;
268 
269  end process comb;
270 
271  seq : process (sysClk) is
272  begin
273  if (rising_edge(sysClk)) then
274  r <= rin after TPD_G;
275  end if;
276  end process seq;
277 
278 
279 end architecture rtl;
TPD_Gtime := 1 ns
Definition: SaciMaster2.vhd:30
SYS_CLK_PERIOD_Greal := 8.0e-9
Definition: SaciMaster2.vhd:31
std_logic sl
Definition: StdRtlPkg.vhd:28
in rstsl :=not RST_POLARITY_G
in saciRspslv( ite( SACI_RSP_BUSSED_G, 0, SACI_NUM_CHIPS_G- 1) downto 0)
Definition: SaciMaster2.vhd:55
out saciCmdsl
Definition: SaciMaster2.vhd:54
in sysRstsl
Definition: SaciMaster2.vhd:38
in addrslv( 11 downto 0)
Definition: SaciMaster2.vhd:47
in sysClksl
Definition: SaciMaster2.vhd:37
out dataOutsl
out rdDataslv( 31 downto 0)
Definition: SaciMaster2.vhd:49
SACI_RSP_BUSSED_Gboolean := false
Definition: SaciMaster2.vhd:35
in chipslv( log2(SACI_NUM_CHIPS_G )- 1 downto 0)
Definition: SaciMaster2.vhd:44
TPD_Gtime := 1 ns
in wrDataslv( 31 downto 0)
Definition: SaciMaster2.vhd:48
out saciClksl
Definition: SaciMaster2.vhd:52
_library_ IEEEIEEE
Definition: SaciMaster.vhd:18
SACI_CLK_FREERUN_Gboolean := false
Definition: SaciMaster2.vhd:33
in cmdslv( 6 downto 0)
Definition: SaciMaster2.vhd:46
out failsl
Definition: SaciMaster2.vhd:43
SACI_NUM_CHIPS_Gpositive := 1
Definition: SaciMaster2.vhd:34
out acksl
Definition: SaciMaster2.vhd:42
out saciSelLslv( SACI_NUM_CHIPS_G- 1 downto 0)
Definition: SaciMaster2.vhd:53
SACI_CLK_PERIOD_Greal := 1.0e-6
Definition: SaciMaster2.vhd:32
std_logic_vector slv
Definition: StdRtlPkg.vhd:29