1 | --=======================================================================================
|
---|
2 | -- TITLE : Interface synchronization on the 50MHz clock
|
---|
3 | -- DESCRIPTION : Manage interface between 250MHz clock domain and 50MHz clock domain
|
---|
4 | -- FILE : interface_sync_50MHz.vhd
|
---|
5 | -- COMPANY : Micro-Cameras & Space Exploration SA
|
---|
6 | --=======================================================================================
|
---|
7 | -- CREATION
|
---|
8 | -- DATE AUTHOR PROJECT REVISION
|
---|
9 | -- 25/03/2011 JGi 110325a
|
---|
10 | --=======================================================================================
|
---|
11 | -- MODIFICATION HISTORY
|
---|
12 | -- DATE AUTHOR PROJECT REVISION COMMENTS
|
---|
13 | -- 25/03/2011 JGi 110325a Description
|
---|
14 | --=======================================================================================
|
---|
15 | -- Library Definition
|
---|
16 | library ieee;
|
---|
17 | use ieee.std_logic_1164.all;
|
---|
18 | use ieee.numeric_std.all;
|
---|
19 |
|
---|
20 | -- Entity Definition
|
---|
21 | entity interface_sync_50MHz is
|
---|
22 | port( --clock
|
---|
23 | clk_50MHz : in std_logic;
|
---|
24 | clk_250MHz : in std_logic;
|
---|
25 | --250MHz inputs
|
---|
26 | config_done : in std_logic;
|
---|
27 | trigger_active : in std_logic;
|
---|
28 | trigger_ID_done : in std_logic;
|
---|
29 | trigger_ID : in std_logic_vector(55 downto 0);
|
---|
30 | --50MHz inputs
|
---|
31 | trigger_ID_read : in std_logic;
|
---|
32 | trigger_cnt_read : in std_logic;
|
---|
33 | --outputs
|
---|
34 | sync_config_done : out std_logic;
|
---|
35 | sync_trigger_active : out std_logic;
|
---|
36 | sync_trigger_ID_ready : out std_logic;
|
---|
37 | sync_trigger_ID : out std_logic_vector(55 downto 0);
|
---|
38 | trigger_cnt_valid : out std_logic;
|
---|
39 | trigger_cnt_copy : out std_logic_vector(31 downto 0));
|
---|
40 | end interface_sync_50MHz;
|
---|
41 |
|
---|
42 | -- Architecture Definition
|
---|
43 | architecture RTL of interface_sync_50MHz is
|
---|
44 |
|
---|
45 | type t_reg_50 is record
|
---|
46 | -- Ouput register declaration
|
---|
47 | sync_config_done : std_logic_vector(3 downto 0);
|
---|
48 | sync_trigger_active : std_logic_vector(3 downto 0);
|
---|
49 | sync_trigger_ID_ready : std_logic_vector(3 downto 0);
|
---|
50 | sync_trigger_ID : std_logic_vector(111 downto 0);
|
---|
51 | trigger_cnt_valid : std_logic;
|
---|
52 | trigger_cnt_copy : std_logic_vector(31 downto 0);
|
---|
53 | end record;
|
---|
54 |
|
---|
55 | type t_reg_250 is record
|
---|
56 | -- Internal register declaration
|
---|
57 | config_done : std_logic;
|
---|
58 | sync_config_done : std_logic_vector(1 downto 0);
|
---|
59 | trigger_active : std_logic;
|
---|
60 | sync_trigger_active : std_logic_vector(1 downto 0);
|
---|
61 | trigger_ID_done : std_logic;
|
---|
62 | sync_trigger_ID_done : std_logic_vector(1 downto 0);
|
---|
63 | end record;
|
---|
64 |
|
---|
65 | signal i_next_reg_250 : t_reg_250 := (config_done => '0',
|
---|
66 | sync_config_done => (others => '0'),
|
---|
67 | trigger_active => '0',
|
---|
68 | sync_trigger_active => (others => '0'),
|
---|
69 | trigger_ID_done => '0',
|
---|
70 | sync_trigger_ID_done => (others => '0'));
|
---|
71 | signal i_reg_250 : t_reg_250 := (config_done => '0',
|
---|
72 | sync_config_done => (others => '0'),
|
---|
73 | trigger_active => '0',
|
---|
74 | sync_trigger_active => (others => '0'),
|
---|
75 | trigger_ID_done => '0',
|
---|
76 | sync_trigger_ID_done => (others => '0'));
|
---|
77 | signal i_next_reg_50 : t_reg_50 := (sync_config_done => (others => '0'),
|
---|
78 | sync_trigger_active => (others => '0'),
|
---|
79 | sync_trigger_ID_ready => (others => '0'),
|
---|
80 | sync_trigger_ID => (others => '0'),
|
---|
81 | trigger_cnt_valid => '0',
|
---|
82 | trigger_cnt_copy => (others => '0'));
|
---|
83 | signal i_reg_50 : t_reg_50 := (sync_config_done => (others => '0'),
|
---|
84 | sync_trigger_active => (others => '0'),
|
---|
85 | sync_trigger_ID_ready => (others => '0'),
|
---|
86 | sync_trigger_ID => (others => '0'),
|
---|
87 | trigger_cnt_valid => '0',
|
---|
88 | trigger_cnt_copy => (others => '0'));
|
---|
89 |
|
---|
90 | begin
|
---|
91 |
|
---|
92 | -- Combinatorial logic
|
---|
93 | -- Manage signals on the 250MHz side
|
---|
94 | process(config_done, trigger_active, trigger_ID_done, i_reg_50, i_reg_250)
|
---|
95 | variable v_reg : t_reg_250 := (config_done => '0',
|
---|
96 | sync_config_done => (others => '0'),
|
---|
97 | trigger_active => '0',
|
---|
98 | sync_trigger_active => (others => '0'),
|
---|
99 | trigger_ID_done => '0',
|
---|
100 | sync_trigger_ID_done => (others => '0'));
|
---|
101 | begin
|
---|
102 | v_reg := i_reg_250;
|
---|
103 | --===================================================================================
|
---|
104 |
|
---|
105 | --===================================================================================
|
---|
106 | -- Generate signals until they have been received by the 50MHz interface
|
---|
107 | --===================================================================================
|
---|
108 | -- Synchronized config done from 50MHz interface
|
---|
109 | v_reg.sync_config_done(0) := i_reg_50.sync_config_done(1);
|
---|
110 | v_reg.sync_config_done(1) := i_reg_250.sync_config_done(0);
|
---|
111 |
|
---|
112 | -- Set config done high when detected at input
|
---|
113 | if config_done = '1' then
|
---|
114 | v_reg.config_done := '1';
|
---|
115 | -- Reset config done when set high by the 50MHz part
|
---|
116 | elsif i_reg_250.sync_config_done(1) = '1' then
|
---|
117 | v_reg.config_done := '0';
|
---|
118 | end if;
|
---|
119 |
|
---|
120 | -- Synchronized trigger active from 50MHz interface
|
---|
121 | v_reg.sync_trigger_active(0) := i_reg_50.sync_trigger_active(1);
|
---|
122 | v_reg.sync_trigger_active(1) := i_reg_250.sync_trigger_active(0);
|
---|
123 |
|
---|
124 | -- Set trigger active high when detected at input
|
---|
125 | if trigger_active = '1' then
|
---|
126 | v_reg.trigger_active := '1';
|
---|
127 | -- Reset trigger active when set high by the 50MHz part
|
---|
128 | elsif i_reg_250.sync_trigger_active(1) = '1' then
|
---|
129 | v_reg.trigger_active := '0';
|
---|
130 | end if;
|
---|
131 |
|
---|
132 | -- Detect rising edge on trigger ID ready from 50MHz interface
|
---|
133 | if i_reg_50.sync_trigger_ID_ready(1) = '1' and
|
---|
134 | i_reg_50.sync_trigger_ID_ready(2) = '0' then
|
---|
135 | v_reg.sync_trigger_ID_done(0) := '1';
|
---|
136 | else
|
---|
137 | v_reg.sync_trigger_ID_done(0) := '0';
|
---|
138 | end if;
|
---|
139 | v_reg.sync_trigger_ID_done(1) := i_reg_250.sync_trigger_ID_done(0);
|
---|
140 |
|
---|
141 | -- Set trigger ID done high when detected at input
|
---|
142 | if trigger_ID_done = '1' then
|
---|
143 | v_reg.trigger_ID_done := '1';
|
---|
144 | -- Reset trigger ID done when set high by the 50MHz part
|
---|
145 | elsif i_reg_250.sync_trigger_ID_done(1) = '1' then
|
---|
146 | v_reg.trigger_ID_done := '0';
|
---|
147 | end if;
|
---|
148 | --===================================================================================
|
---|
149 |
|
---|
150 | --===================================================================================
|
---|
151 | -- Drive register input
|
---|
152 | i_next_reg_250 <= v_reg;
|
---|
153 | --===================================================================================
|
---|
154 | end process;
|
---|
155 |
|
---|
156 | -- Manage signals on the 50MHz side
|
---|
157 | process(trigger_ID_read, trigger_ID, trigger_cnt_read, i_reg_250, i_reg_50)
|
---|
158 | variable v_reg : t_reg_50 := (sync_config_done => (others => '0'),
|
---|
159 | sync_trigger_active => (others => '0'),
|
---|
160 | sync_trigger_ID_ready => (others => '0'),
|
---|
161 | sync_trigger_ID => (others => '0'),
|
---|
162 | trigger_cnt_valid => '0',
|
---|
163 | trigger_cnt_copy => (others => '0'));
|
---|
164 | begin
|
---|
165 | v_reg := i_reg_50;
|
---|
166 | --===================================================================================
|
---|
167 |
|
---|
168 | --===================================================================================
|
---|
169 | -- Synchronize signals from the 250MHz side
|
---|
170 | --===================================================================================
|
---|
171 | -- Synchronize config done from the 250MHz interface
|
---|
172 | v_reg.sync_config_done(0) := i_reg_250.config_done;
|
---|
173 | v_reg.sync_config_done(1) := i_reg_50.sync_config_done(0);
|
---|
174 | v_reg.sync_config_done(2) := i_reg_50.sync_config_done(1);
|
---|
175 |
|
---|
176 | -- Set config done on 50MHz when set by 250MHz interface
|
---|
177 | if i_reg_50.sync_config_done(1) = '1' and i_reg_50.sync_config_done(2) = '0' and
|
---|
178 | i_reg_50.sync_config_done(3) = '0' then
|
---|
179 | v_reg.sync_config_done(3) := '1';
|
---|
180 | else
|
---|
181 | v_reg.sync_config_done(3) := '0';
|
---|
182 | end if;
|
---|
183 |
|
---|
184 | -- Synchronize trigger active from the 250MHz interface
|
---|
185 | v_reg.sync_trigger_active(0) := i_reg_250.trigger_active;
|
---|
186 | v_reg.sync_trigger_active(1) := i_reg_50.sync_trigger_active(0);
|
---|
187 |
|
---|
188 | -- Synchronize trigger ID ready from the 250MHz interface
|
---|
189 | v_reg.sync_trigger_ID_ready(0) := i_reg_250.trigger_ID_done;
|
---|
190 | v_reg.sync_trigger_ID_ready(1) := i_reg_50.sync_trigger_ID_ready(0);
|
---|
191 | v_reg.sync_trigger_ID_ready(2) := i_reg_50.sync_trigger_ID_ready(1);
|
---|
192 |
|
---|
193 | -- Set trigger ready when set on the 250MHz side and release it
|
---|
194 | -- when read by the 50MHz side
|
---|
195 | if trigger_ID_read = '1' then
|
---|
196 | v_reg.sync_trigger_ID_ready(3) := '0';
|
---|
197 | elsif i_reg_50.sync_trigger_ID_ready(1) = '1' and
|
---|
198 | i_reg_50.sync_trigger_ID_ready(2) = '0' then
|
---|
199 | v_reg.sync_trigger_ID_ready(3) := '1';
|
---|
200 | end if;
|
---|
201 |
|
---|
202 | -- Simply synchronize trigger ID
|
---|
203 | v_reg.sync_trigger_ID(55 downto 0) := trigger_ID;
|
---|
204 | v_reg.sync_trigger_ID(111 downto 56) := i_reg_50.sync_trigger_ID(55 downto 0);
|
---|
205 |
|
---|
206 | -- Counter is a simple copy of the counter of the synchronized trigger ID
|
---|
207 | v_reg.trigger_cnt_valid := trigger_cnt_read;
|
---|
208 | if trigger_cnt_read = '1' then
|
---|
209 | v_reg.trigger_cnt_copy := i_reg_50.sync_trigger_ID(87 downto 56);
|
---|
210 | end if;
|
---|
211 | --===================================================================================
|
---|
212 |
|
---|
213 | --===================================================================================
|
---|
214 | -- Drive register input
|
---|
215 | i_next_reg_50 <= v_reg;
|
---|
216 |
|
---|
217 | --===================================================================================
|
---|
218 | -- Output assignation
|
---|
219 | sync_config_done <= i_reg_50.sync_config_done(3);
|
---|
220 | sync_trigger_active <= i_reg_50.sync_trigger_active(1);
|
---|
221 | sync_trigger_ID_ready <= i_reg_50.sync_trigger_ID_ready(3);
|
---|
222 | sync_trigger_ID <= i_reg_50.sync_trigger_ID(111 downto 56);
|
---|
223 | trigger_cnt_valid <= i_reg_50.trigger_cnt_valid;
|
---|
224 | trigger_cnt_copy <= i_reg_50.trigger_cnt_copy;
|
---|
225 | --===================================================================================
|
---|
226 | end process;
|
---|
227 |
|
---|
228 | -- Sequential logic
|
---|
229 | process(clk_250MHz)
|
---|
230 | begin
|
---|
231 | if rising_edge(clk_250MHz) then
|
---|
232 | i_reg_250 <= i_next_reg_250;
|
---|
233 | end if;
|
---|
234 | end process;
|
---|
235 |
|
---|
236 | process(clk_50MHz)
|
---|
237 | begin
|
---|
238 | if rising_edge(clk_50MHz) then
|
---|
239 | i_reg_50 <= i_next_reg_50;
|
---|
240 | end if;
|
---|
241 | end process;
|
---|
242 |
|
---|
243 | end RTL; |
---|