source: firmware/FAD/FACT_FAD_lib/hdl/phase_shifter.vhd@ 12559

Last change on this file since 12559 was 11755, checked in by neise, 13 years ago
reinit of this svn repos .... it was all too messy deleted the old folders and restarted with FACT_FAD_lib only. (well and the testbenches)
File size: 5.4 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
38 locked_status_o : OUT std_logic;
39 ready_status_o : OUT std_logic;
40 offset : OUT std_logic_vector (7 DOWNTO 0) := (OTHERS => '0')
41
42
43 );
44END phase_shifter;
45
46-- usage:
47-- w5300_modul will set 'direction' to desired direction and pulse 'shift_phase' once
48-- to initiate a phase shifting process.
49-- while phase shifting, 'shifting' will show '1' and further pulses will be discarded.
50-- 'offset' shows the number of phase_shift steps that have been performed.
51-- ready is high, when DCM is LOCKED and not phase_shifting.
52-- DCM_status is a copy, of the STATUS input.
53-- DCM_locked is a copy of LOCKED
54--
55-- how it works internally:
56-- PSCLK is connected to clk, always.
57--
58-- main FSM goes from init to ready, when LOCKED is high.
59-- main FSM goes from ready to shifting, when shift_phase goes high.
60-- when in shifting:
61-- PSINCDEC is set to 'direction'
62-- PSEN is set high
63-- shifting is set high
64-- next state waiting-for-done is entered
65--
66-- when in waiting-for-done:
67-- PSEN is set low
68-- if PSDONE is found to be high.
69-- shifting is set low and state ready is entered.
70--
71-- whenever LOCKED goes low FSM enters 'init' state
72-- when in init state:
73-- 'ready' is set low
74
75architecture first_behave of phase_shifter is
76 constant OFFS_MIN : integer := -51;
77 constant OFFS_MAX : integer := 51;
78
79 type states is (INIT, READY_STATE, PRE_SHIFTING_STATE, SHIFTING_STATE, WAITINGFORDONE, RESET_STATE);
80 signal state : states := INIT;
81
82 signal local_direction : std_logic;
83 signal offset_int : integer range OFFS_MIN to OFFS_MAX := 0;
84 signal lower_limit_reached : std_logic := '0';
85 signal upper_limit_reached : std_logic := '0';
86
87 signal reset_dcm_sr : std_logic_vector(1 downto 0) := "00";
88 signal shift_phase_sr : std_logic_vector(1 downto 0) := "00";
89 signal ready_int : std_logic := '0';
90begin
91
92-- concurrent statements:
93ready <= ready_int;
94PSCLK <= CLK;
95offset <= std_logic_vector(to_signed(offset_int,8));
96locked_status_o <= LOCKED;
97ready_status_o <= ready_int;
98
99 -- MAIN FSM
100 FSM: process(CLK)
101 begin
102
103 if rising_edge(CLK) then
104 reset_dcm_sr <= reset_dcm_sr(1) & reset_DCM; --synch in
105 shift_phase_sr <= shift_phase_sr(1) & shift_phase; --synch in
106
107 case state is
108 -- INIT state: here the FSM is idling, when LOCKED is not HIGH.
109 when INIT =>
110 rst <= '0';
111 ready_int <= '0';
112 shifting <= '0';
113 PSEN <= '0';
114 offset_int <= 0;
115 if (LOCKED = '1') then
116 state <= READY_STATE;
117 else
118 state <= INIT;
119 end if;
120
121 -- RESET state: when ordered to do so: DCM is reseted and FSM send back to INIT.
122 when RESET_STATE =>
123 rst <= '1';
124 ready_int <= '0';
125 shifting <= '0';
126 PSEN <= '0';
127 state <= INIT;
128
129 -- READY_STATE state: here FSM is waiting for the 'shift_phase' to go high, or
130 -- if reset_DCM goes high, we will reset the DCM and go back to init.
131 when READY_STATE =>
132 ready_int <= '1';
133 shifting <= '0';
134 PSEN <= '0';
135
136 lower_limit_reached <='0';
137 upper_limit_reached <='0';
138 if (offset_int = OFFS_MIN) then
139 lower_limit_reached <= '1';
140 elsif (offset_int = OFFS_MAX) then
141 upper_limit_reached <= '1';
142 end if;
143
144 if (shift_phase_sr = "01") then
145 local_direction <= direction; -- direction is sampled, once 'shift_phase' goes high
146 state <= PRE_SHIFTING_STATE;
147 else
148 state <= READY_STATE;
149 end if;
150
151 if (reset_dcm_sr = "01") then
152 state <= RESET_STATE;
153 end if;
154
155 -- checks if possible to shift in asked direction. If not ... back to READY.
156 when PRE_SHIFTING_STATE =>
157 ready_int <= '0';
158 if (local_direction = '1' and upper_limit_reached = '1') or
159 (local_direction = '0' and lower_limit_reached = '1') then
160 state <= READY_STATE;
161 else
162 state <= SHIFTING_STATE;
163 end if;
164
165
166 -- SHIFTING_STATE state: PSENC is set HIGH here and set low in the next state.
167 when SHIFTING_STATE =>
168 ready_int <= '0';
169 shifting <= '1';
170 PSEN <= '1';
171 PSINCDEC <= local_direction; -- this is the value of 'direction', when 'shift_phase' went up.
172 state <= WAITINGFORDONE;
173
174 -- WAITINGFORDONE state: PSENC is set LOW, ensuring that is was high only one clock cycle.
175 when WAITINGFORDONE =>
176 ready_int <= '0';
177 shifting <= '1';
178 PSEN <= '0';
179 if (PSDONE = '1') then
180 state <= READY_STATE;
181 if (local_direction = '1') then
182 offset_int <= offset_int + 1;
183 else
184 offset_int <= offset_int - 1;
185 end if;
186 else
187 state <= WAITINGFORDONE;
188 end if;
189
190 -- does this work????
191 when others =>
192 state <= RESET_STATE;
193
194 end case;
195 end if;
196 end process;
197
198end first_behave;
Note: See TracBrowser for help on using the repository browser.