source: firmware/FAD/FACT_FAD_20MHz_VAR_PS/FACT_FAD_lib/hdl/phase_shifter.vhd @ 10149

Last change on this file since 10149 was 10149, checked in by neise, 9 years ago
REFCLK counter asserts alarm outputs at first place. phase shifter generates correct phaseshift output.
File size: 5.7 KB
Line 
1--
2-- phase_shifter.vhd
3--
4-- implements interface between w5300_modul.vhd
5-- and clock_generator_variable_PS_struct.vhd
6--
7library ieee;
8use ieee.std_logic_1164.all;
9use IEEE.NUMERIC_STD.all;
10
11library FACT_FAD_lib;
12use FACT_FAD_lib.fad_definitions.all;
13
14
15ENTITY phase_shifter IS
16
17        PORT(
18                CLK : IN std_logic;
19                rst : out std_logic := '0'; --asynch in of DCM
20               
21                -- interface to: clock_generator_variable_PS_struct.vhd
22                PSCLK : OUT std_logic;
23                PSEN : OUT std_logic := '0'; 
24                PSINCDEC : OUT std_logic := '1'; -- default is 'incrementing'
25                PSDONE : IN std_logic; -- will pulse once, if phase shifting was done.
26                LOCKED : IN std_logic; -- when is this going high?
27               
28               
29                -- interface to: w5300_modul.vhd
30                shift_phase : IN std_logic;
31                direction : IN std_logic; -- corresponds to 'PSINCDEC'
32                reset_DCM : in std_logic; -- asynch in: orders us, to reset the DCM
33               
34                -- status:
35                shifting : OUT std_logic := '0';
36                ready : OUT std_logic := '0';
37                offset : OUT std_logic_vector (7 DOWNTO 0) := (OTHERS => '0');
38                DCM_locked : OUT std_logic
39               
40        );
41END phase_shifter;
42
43-- usage:
44-- w5300_modul will set 'direction' to desired direction and pulse 'shift_phase' once
45-- to initiate a phase shifting process.
46-- while phase shifting, 'shifting' will show '1' and further pulses will be discarded.
47-- 'offset' shows the number of phase_shift steps that have been performed.
48-- ready is high, when DCM is LOCKED and not phase_shifting.
49-- DCM_status is a copy, of the STATUS input.
50-- DCM_locked is a copy of LOCKED
51--
52-- how it works internally:
53-- PSCLK is connected to clk, always.
54--
55-- main FSM goes from init to ready, when LOCKED is high.
56-- main FSM goes from ready to shifting, when shift_phase goes high.
57--              when in shifting:
58--                      PSINCDEC is set to 'direction'
59--                      PSEN is set high
60--                      shifting is set high
61--                      next state waiting-for-done is entered
62--
63--              when in waiting-for-done:
64--                      PSEN is set low
65--                      if PSDONE is found to be high.
66--                      shifting is set low and state ready is entered.
67--
68--      whenever LOCKED goes low FSM enters 'init' state
69--              when in init state:
70--                      'ready' is set low
71
72architecture first_behave of phase_shifter is
73  constant OFFS_MIN : integer := -51;
74  constant OFFS_MAX : integer := 51;
75   
76        type states is (INIT, READY_STATE, PRE_SHIFTING_STATE, SHIFTING_STATE, WAITINGFORDONE, RESET_STATE); 
77        signal state,next_state : states := INIT;
78       
79        signal local_direction : std_logic;
80        signal offset_int : integer range OFFS_MIN to OFFS_MAX := 0;
81        signal lower_limit_reached : std_logic := '0';
82        signal upper_limit_reached : std_logic := '0';
83               
84        signal reset_dcm_sr : std_logic_vector(1 downto 0) := "00";
85        signal shift_phase_sr : std_logic_vector(1 downto 0) := "00";
86        signal ready_int : std_logic := '0';
87begin
88
89-- concurrent statements:
90DCM_locked <= LOCKED;
91ready <= ready_int;
92PSCLK <= CLK;
93offset <= LOCKED & ready_int & std_logic_vector(to_signed(offset_int,6));
94
95  -- MAIN FSM: go to next state if rising edge, or to INIT if LOCKED not high.
96  -- is this really coorect?
97 
98  FSM_Registers: process(CLK, LOCKED, rst)
99  begin
100    if LOCKED = '0' then
101      state <= INIT;
102    elsif Rising_edge(CLK) then
103      state <= next_state;
104    end if;
105  end process;
106
107  -- MAIN FSM
108  FSM_logic: process(state, PSDONE, LOCKED, shift_phase, direction, local_direction)
109  begin
110    next_state <= state;
111        reset_dcm_sr <= reset_dcm_sr(1) & reset_DCM;  --synch in
112        shift_phase_sr <= shift_phase_sr(1) & shift_phase; --synch in
113    case state is
114                -- INIT state: here the FSM is idling, when LOCKED is not HIGH.
115                when INIT =>
116                        rst <= '0';
117                        ready_int <= '0';
118                        shifting <= '0';
119                        PSEN <= '0';
120                        offset_int <= 0;
121                        if (LOCKED = '1') then
122                                next_state <= READY_STATE;
123                        else 
124                                next_state <= INIT;
125                        end if;
126                -- RESET state: when ordered to do so: DCM is reseted and FSM send back to INIT.
127                when RESET_STATE =>
128                        rst <= '1';
129                        ready_int <= '0';
130                        shifting <= '0';
131                        PSEN <= '0';
132                        next_state <= INIT;
133                       
134                -- READY_STATE state: here FSM is waiting for the 'shift_phase' to go high, or
135                -- if reset_DCM goes high, we will reset the DCM and go back to init.
136                when READY_STATE =>
137                        ready_int <= '1';
138                        shifting <= '0';
139                        PSEN <= '0';
140
141                        lower_limit_reached <='0';
142                        upper_limit_reached <='0';
143                        if (offset_int = OFFS_MIN) then 
144                                lower_limit_reached <= '1';
145                        elsif (offset_int = OFFS_MAX) then
146                                upper_limit_reached <= '1';
147                        end if;
148                       
149                        if (shift_phase_sr = "01") then
150                                local_direction <= direction; -- direction is sampled, once 'shift_phase' goes high
151                                next_state <= PRE_SHIFTING_STATE;
152                        else
153                                next_state <= READY_STATE;
154                        end if;
155                       
156                        if (reset_dcm_sr = "01") then
157                                next_state <= RESET_STATE;
158                        end if;
159               
160                -- checks if possible to shift in asked direction. If not ... back to READY.
161                when PRE_SHIFTING_STATE =>
162                ready_int <= '0';
163                        if (local_direction = '1' and upper_limit_reached = '1') or
164                                (local_direction = '0' and lower_limit_reached = '1') then
165                                next_state <= READY_STATE;
166                        else
167                                next_state <= SHIFTING_STATE;
168                        end if;
169               
170               
171                -- SHIFTING_STATE state: PSENC is set HIGH here and set low in the next state.
172                when SHIFTING_STATE =>
173                        ready_int <= '0';
174                        shifting <= '1';
175                        PSEN <= '1';
176                        PSINCDEC <= local_direction; -- this is the value of 'direction', when 'shift_phase' went up.
177                        next_state <= WAITINGFORDONE;
178               
179                -- WAITINGFORDONE state: PSENC is set LOW, ensuring that is was high only one clock cycle.
180                when WAITINGFORDONE =>
181                        ready_int <= '0';
182                        shifting <= '1';
183                        PSEN <= '0';
184                        if (PSDONE = '1') then
185                                next_state <= READY_STATE;
186                                if (local_direction = '1') then
187                                        offset_int <= offset_int + 1;
188                                else
189                                        offset_int <= offset_int - 1;
190                                end if;
191                        else
192                                next_state <= WAITINGFORDONE;
193                        end if;
194                       
195                -- does this work????
196                when others =>
197                        next_state <= RESET_STATE;
198               
199    end case;
200  end process;
201
202end first_behave;
Note: See TracBrowser for help on using the repository browser.