1 ------------------------------------------------------------------------------- 2 -- File : SaciMaster.vhd 3 -- Company : SLAC National Accelerator Laboratory 4 -- Created : 2012-08-10 5 -- Last update: 2013-03-01 6 ------------------------------------------------------------------------------- 7 -- Description: Saci Master Module 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 ------------------------------------------------------------------------------- 19 use IEEE.std_logic_1164.
all;
26 --! @ingroup protocols_saci 47 end entity SaciMaster;
51 type SynchronizerType is record 57 type SynchronizerArray is array ( range <>) of SynchronizerType;
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');
62 procedure synchronize (
64 current :
in SynchronizerType;
65 nextOut :
out SynchronizerType)
is 68 nextOut.sync := current.tmp;
69 nextOut.last := current.sync;
72 -- Simplified. Can be used when v := r has already been called. 73 procedure synchronize (
74 var :
inout SynchronizerType;
80 end procedure synchronize;
82 procedure synchronize (
84 current :
in SynchronizerArray;
85 nextOut :
out SynchronizerArray)
is 87 for i in input'range loop 88 synchronize(input(i), current(i), nextOut(i));
92 -- Simplified. Can be used when v := r has already been called. 93 procedure synchronize (
94 var :
inout SynchronizerArray;
97 for i in input'range loop 98 synchronize(var(i), input(i));
100 end procedure synchronize;
102 procedure shiftInLeft (
107 if (r'ascending) then 108 v := r(r'low+1 to r'high) & i;
110 v := r(r'high-1 downto r'low) & i;
112 end procedure shiftInLeft;
114 type StateType is (IDLE_S, CHIP_SELECT_S, TX_S, RX_START_S, RX_HEADER_S, RX_DATA_S, ACK_S);
116 type RegType is record 117 reqSync : SynchronizerType;
118 resetSync : SynchronizerType;
120 shiftReg : slv(52 downto 0);
121 shiftCount : (5 downto 0);
128 signal r, rin : RegType;
129 signal saciRspFall : sl;
133 saciClk <= '0' when r.state = IDLE_S and r.reqSync.sync = '0' else 136 -------------------------------------------------------------------------------------------------- 137 -- Capture serial input on falling edge of clock 138 -------------------------------------------------------------------------------------------------- 139 fall :
process (
clk,
rst)
is 142 saciRspFall <= '0' after TPD_G;
143 elsif (falling_edge(clk)) then 148 seq :
process (
clk,
rst)
is 151 r.reqSync <= SYNCHRONIZER_INIT_0_C after TPD_G;
152 r.resetSync <= SYNCHRONIZER_INIT_0_C after TPD_G;
153 r.state <= IDLE_S after TPD_G;
154 r.shiftReg <= (others => '0') after TPD_G;
155 r.shiftCount <= (others => '0') after TPD_G;
161 elsif (rising_edge(clk)) then 162 r <= rin after TPD_G;
167 variable rVar : RegType;
168 variable reqVar : sl;
169 variable resetVar : sl;
174 -- Synchronize control inputs to serial clock 178 reqVar := r.reqSync.sync;
179 resetVar := r.resetSync.sync;
185 rVar.shiftCount := (others => '0');
188 if (resetVar = '1') then 190 rVar.shiftReg := (others => '0');
191 rVar.shiftCount := (others => '0');
192 rVar.state := IDLE_S;
200 rVar.shiftReg := (others => '0');
201 rVar.shiftCount := (others => '0');
202 if (reqVar = '1') then 203 -- New command, load shift reg 204 rVar.shiftReg(52) := '1';
-- Start bit 211 rVar.shiftReg(31 downto 0) := (others => '0');
213 rVar.state := CHIP_SELECT_S;
216 when CHIP_SELECT_S => 222 -- Shift out data on saciCmd 223 rVar.saciCmd := r.shiftReg(52);
224 rVar.shiftReg := r.shiftReg(51 downto 0) & '0';
225 rVar.shiftCount := r.shiftCount + 1;
227 rVar.state := RX_START_S;
229 rVar.state := RX_START_S;
233 -- Wait for saciRsp start bit 234 rVar.shiftCount := (others => '0');
235 if (saciRspFall = '1') then 236 rVar.state := RX_HEADER_S;
240 -- Shift data in and check that header is correct 241 rVar.shiftCount := r.shiftCount + 1;
242 shiftInLeft(saciRspFall, r.shiftReg, rVar.shiftReg);
243 if (r.shiftCount = 20) then 250 rVar.state := RX_DATA_S;
257 rVar.shiftCount := r.shiftCount + 1;
258 shiftInLeft(saciRspFall, r.shiftReg, rVar.shiftReg);
259 if (r.shiftCount = 51) then 266 if (reqVar = '0') then 269 rVar.state := IDLE_S;
285 end architecture rtl;
out saciMasterOutSaciMasterOutType
out saciSelLslv( SACI_NUM_SLAVES_C- 1 downto 0)
positive := 4 SACI_NUM_SLAVES_C
SYNCHRONIZE_CONTROL_Gboolean := true
slv( SACI_CHIP_WIDTH_C- 1 downto 0) chip
in saciMasterInSaciMasterInType