1 |
2 |
kdv |
/*
|
2 |
|
|
* syncgen.v
|
3 |
|
|
*
|
4 |
|
|
* Copyright (c) 2007 Koen De Vleeschauwer.
|
5 |
|
|
*
|
6 |
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
7 |
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
8 |
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
9 |
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
10 |
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
11 |
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
12 |
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
13 |
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
14 |
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
15 |
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
16 |
|
|
* SUCH DAMAGE.
|
17 |
|
|
*/
|
18 |
|
|
|
19 |
|
|
/*
|
20 |
|
|
* sync_gen - Sync generator.
|
21 |
|
|
*/
|
22 |
|
|
|
23 |
|
|
`include "timescale.v"
|
24 |
|
|
|
25 |
|
|
`undef DEBUG
|
26 |
|
|
//`define DEBUG 1
|
27 |
|
|
|
28 |
|
|
/*
|
29 |
|
|
* Generates horizontal and vertical synchronisation and timing.
|
30 |
|
|
*
|
31 |
|
|
* Inputs:
|
32 |
|
|
*
|
33 |
|
|
* horizontal_size, vertical_size, display_horizontal_size, and display_vertical_size
|
34 |
|
|
* are parameters extracted from the MPEG2 bitstream.
|
35 |
|
|
* horizontal_size and vertical_size determine the size of the reconstructed bitmap in frame memory;
|
36 |
|
|
* display_horizontal_size and display_vertical_size - if non-zero - are the displayable part of this bitmap.
|
37 |
|
|
*
|
38 |
|
|
* horizontal_resolution, horizontal_sync_start, horizontal_sync_end, horizontal_length,
|
39 |
|
|
* vertical_resolution, vertical_sync_start, vertical_sync_end, horizontal_halfline and vertical_length determine video timing.
|
40 |
|
|
*
|
41 |
|
|
* The timing parameters can be deduced from the X11 modeline for the display.
|
42 |
|
|
* See "XFree86 Video Timings HOWTO".
|
43 |
|
|
*
|
44 |
|
|
* Note vertical_resolution, vertical_sync_start, vertical_sync_end and vertical_length refer to a frame if
|
45 |
|
|
* progressive, and to a field if interlaced.
|
46 |
|
|
*
|
47 |
|
|
* For instance, vertical_resolution is number of visible lines per frame if progressive,
|
48 |
|
|
* and number of visible lines per field if interlaced.
|
49 |
|
|
*
|
50 |
|
|
* If 'interlaced' is asserted, vertical sync is delayed one-half scan line at the end of odd frames.
|
51 |
|
|
* This is similar to "interlace sync and video mode" of the mc6845 crtc.
|
52 |
|
|
*
|
53 |
|
|
* Outputs:
|
54 |
|
|
* h_pos and v_pos are the coordinates of the current pixel.
|
55 |
|
|
* pixel_en is not asserted if blanking is required.
|
56 |
|
|
* h_sync and v_sync are horizontal and vertical synchronisation,
|
57 |
|
|
* respectively.
|
58 |
|
|
*
|
59 |
|
|
*/
|
60 |
|
|
|
61 |
|
|
module sync_gen (clk, clk_en, rst,
|
62 |
|
|
horizontal_size, vertical_size, display_horizontal_size, display_vertical_size,
|
63 |
|
|
horizontal_resolution, horizontal_sync_start, horizontal_sync_end, horizontal_length,
|
64 |
|
|
vertical_resolution, vertical_sync_start, vertical_sync_end, horizontal_halfline, vertical_length,
|
65 |
|
|
interlaced, clip_display_size,
|
66 |
|
|
h_pos, v_pos, pixel_en, h_sync, v_sync, c_sync, h_blank, v_blank);
|
67 |
|
|
|
68 |
|
|
input clk;
|
69 |
|
|
input clk_en;
|
70 |
|
|
input rst;
|
71 |
|
|
|
72 |
|
|
input [13:0]horizontal_size; /* par. 6.2.2.1, par. 6.3.3 */
|
73 |
|
|
input [13:0]vertical_size; /* par. 6.2.2.1, par. 6.3.3 */
|
74 |
|
|
input [13:0]display_horizontal_size; /* par. 6.2.2.4, par. 6.3.6 */
|
75 |
|
|
input [13:0]display_vertical_size; /* par. 6.2.2.4, par. 6.3.6 */
|
76 |
|
|
|
77 |
|
|
input [11:0]horizontal_resolution; /* horizontal resolution. number of dots per line */
|
78 |
|
|
input [11:0]horizontal_sync_start; /* the dot the horizontal sync pulse begins. */
|
79 |
|
|
input [11:0]horizontal_sync_end; /* the dot the horizontal sync pulse ends. */
|
80 |
|
|
input [11:0]horizontal_length; /* total horizontal length */
|
81 |
|
|
input [11:0]vertical_resolution; /* vertical resolution. number of visible lines per frame (progressive) or field (interlaced) */
|
82 |
|
|
input [11:0]vertical_sync_start; /* the line number within the frame (progressive) or field (interlaced) the vertical sync pulse begins. */
|
83 |
|
|
input [11:0]vertical_sync_end; /* the line number within the frame (progressive) or field (interlaced) the vertical sync pulse ends. */
|
84 |
|
|
input [11:0]horizontal_halfline; /* the dot the vertical sync begins on odd frames of interlaced video. Not used in progressive mode. */
|
85 |
|
|
input [11:0]vertical_length; /* total number of lines of a vertical frame (progressive) or field (interlaced) */
|
86 |
|
|
input interlaced; /* asserted if interlaced output required. */
|
87 |
|
|
input clip_display_size; /* assert to clip image to (display_horizontal_size, display_vertical_size) */
|
88 |
|
|
|
89 |
|
|
output reg [11:0]h_pos; /* horizontal position */
|
90 |
|
|
output reg [11:0]v_pos; /* vertical position */
|
91 |
|
|
output reg pixel_en; /* pixel enable, asserted when pixel drawn */
|
92 |
|
|
output reg h_sync; /* horizontal sync */
|
93 |
|
|
output reg v_sync; /* vertical sync */
|
94 |
|
|
output reg c_sync; /* complex sync */
|
95 |
|
|
output reg h_blank; /* horizontal blanking */
|
96 |
|
|
output reg v_blank; /* vertical blanking */
|
97 |
|
|
|
98 |
|
|
/*
|
99 |
|
|
* general registers
|
100 |
|
|
*/
|
101 |
|
|
|
102 |
|
|
reg [11:0]h_size;
|
103 |
|
|
reg [11:0]h_display_size;
|
104 |
|
|
reg [11:0]v_size;
|
105 |
|
|
reg [11:0]v_display_size;
|
106 |
|
|
reg [11:0]v_sync_h_pos;
|
107 |
|
|
reg odd_field;
|
108 |
|
|
|
109 |
|
|
/*
|
110 |
|
|
* v_sync_h_pos: horizontal position of vertical sync.
|
111 |
|
|
* In progressive video, the vertical sync begins at horizontal position 0,
|
112 |
|
|
* In interlaced video:
|
113 |
|
|
* - in even fields, vertical sync begins at horizontal position 0
|
114 |
|
|
* - in odd fields, vertical sync is delayed horizontal_halfline dots.
|
115 |
|
|
* A common value for horizontal_halfline is horizontal_length/2.
|
116 |
|
|
*/
|
117 |
|
|
|
118 |
|
|
always @(posedge clk)
|
119 |
|
|
if (~rst) v_sync_h_pos <= 12'd0;
|
120 |
|
|
else if (clk_en) v_sync_h_pos <= (interlaced && odd_field) ? horizontal_halfline : 12'd0;
|
121 |
|
|
else v_sync_h_pos <= v_sync_h_pos;
|
122 |
|
|
|
123 |
|
|
/*
|
124 |
|
|
* for h_display_size and v_display_size:
|
125 |
|
|
* display_horizontal_size and display_vertical_size are optional mpeg2 parameters.
|
126 |
|
|
* If display_horizontal_size and display_vertical_size are zero, the whole frame is displayable; use horizontal_size and vertical_size instead.
|
127 |
|
|
* If display_horizontal_size and display_vertical_size are non-zero, only display_horizontal_size by display_vertical_size of the frame is displayable.
|
128 |
|
|
*/
|
129 |
|
|
|
130 |
|
|
always @(posedge clk)
|
131 |
|
|
if (~rst) h_display_size <= 12'd0;
|
132 |
|
|
else if (clk_en) h_display_size <= ((display_horizontal_size != 0) && clip_display_size) ? display_horizontal_size[11:0] : ((horizontal_size != 0) ? horizontal_size[11:0] : horizontal_resolution);
|
133 |
|
|
else h_display_size <= h_display_size;
|
134 |
|
|
|
135 |
|
|
always @(posedge clk)
|
136 |
|
|
if (~rst) v_display_size <= 12'd0;
|
137 |
|
|
else if (clk_en && interlaced) v_display_size <= ((display_vertical_size != 0) && clip_display_size) ? display_vertical_size[11:1] : ((vertical_size != 0) ? vertical_size[11:1] : vertical_resolution[11:1]); // interlacing; one field contains half the visible lines.
|
138 |
|
|
else if (clk_en) v_display_size <= ((display_vertical_size != 0) && clip_display_size) ? display_vertical_size[11:0] : ((vertical_size != 0) ? vertical_size[11:0] : vertical_resolution); // no interlacing; one frame contains all visible lines.
|
139 |
|
|
else v_display_size <= v_display_size;
|
140 |
|
|
|
141 |
|
|
always @(posedge clk)
|
142 |
|
|
if (~rst) h_size <= 12'd0;
|
143 |
|
|
else if (clk_en) h_size <= (horizontal_size != 0) ? horizontal_size[11:0] : horizontal_resolution;
|
144 |
|
|
else h_size <= h_size;
|
145 |
|
|
|
146 |
|
|
always @(posedge clk)
|
147 |
|
|
if (~rst) v_size <= 12'd0;
|
148 |
|
|
else if (clk_en && interlaced) v_size <= (vertical_size != 0) ? vertical_size[11:1] : vertical_resolution[11:1];
|
149 |
|
|
else if (clk_en) v_size <= (vertical_size != 0) ? vertical_size[11:0] : vertical_resolution;
|
150 |
|
|
else v_size <= v_size;
|
151 |
|
|
|
152 |
|
|
/*
|
153 |
|
|
* Stage 0
|
154 |
|
|
*/
|
155 |
|
|
|
156 |
|
|
reg [11:0]h_cntr;
|
157 |
|
|
reg [11:0]v_cntr;
|
158 |
|
|
|
159 |
|
|
/* horizontal counter */
|
160 |
|
|
always @(posedge clk)
|
161 |
|
|
if (~rst) h_cntr <= 12'd0;
|
162 |
|
|
else if (clk_en) h_cntr <= (h_cntr >= horizontal_length) ? 12'd0 : (h_cntr + 1);
|
163 |
|
|
else h_cntr <= h_cntr;
|
164 |
|
|
|
165 |
|
|
/* vertical counter */
|
166 |
|
|
always @(posedge clk)
|
167 |
|
|
if (~rst) v_cntr <= 12'd0;
|
168 |
|
|
else if (clk_en && (h_cntr >= horizontal_length)) v_cntr <= (v_cntr >= vertical_length) ? 12'd0 : (v_cntr + 1);
|
169 |
|
|
else v_cntr <= v_cntr;
|
170 |
|
|
|
171 |
|
|
/*
|
172 |
|
|
* Stage 1
|
173 |
|
|
*/
|
174 |
|
|
|
175 |
|
|
reg [11:0]h_cntr_1;
|
176 |
|
|
reg [11:0]v_cntr_1;
|
177 |
|
|
reg h_blank_1;
|
178 |
|
|
reg v_blank_1;
|
179 |
|
|
reg h_sync_1;
|
180 |
|
|
reg v_sync_1;
|
181 |
|
|
|
182 |
|
|
always @(posedge clk)
|
183 |
|
|
if (~rst) h_cntr_1 <= 12'd0;
|
184 |
|
|
else if (clk_en) h_cntr_1 <= h_cntr;
|
185 |
|
|
else h_cntr_1 <= h_cntr_1;
|
186 |
|
|
|
187 |
|
|
always @(posedge clk)
|
188 |
|
|
if (~rst) v_cntr_1 <= 12'd0;
|
189 |
|
|
else if (clk_en) v_cntr_1 <= v_cntr;
|
190 |
|
|
else v_cntr_1 <= v_cntr_1;
|
191 |
|
|
|
192 |
|
|
/* horizontal synchronisation */
|
193 |
|
|
always @(posedge clk)
|
194 |
|
|
if (~rst) h_sync_1 <= 1'b0;
|
195 |
|
|
else if (clk_en) h_sync_1 <= (h_cntr >= horizontal_sync_start) && (h_cntr <= horizontal_sync_end);
|
196 |
|
|
else h_sync_1 <= h_sync_1;
|
197 |
|
|
|
198 |
|
|
/* horizontal blanking */
|
199 |
|
|
always @(posedge clk)
|
200 |
|
|
if (~rst) h_blank_1 <= 1'b1;
|
201 |
|
|
else if (clk_en) h_blank_1 <= (h_cntr >= horizontal_resolution) || (h_cntr >= h_size) || (h_cntr >= h_display_size);
|
202 |
|
|
else h_blank_1 <= h_blank_1;
|
203 |
|
|
|
204 |
|
|
/* vertical synchronisation */
|
205 |
|
|
always @(posedge clk)
|
206 |
|
|
if (~rst) v_sync_1 <= 1'b0;
|
207 |
|
|
else if (clk_en) v_sync_1 <= ((v_cntr == vertical_sync_start) && (h_cntr >= v_sync_h_pos))
|
208 |
|
|
|| ((v_cntr > vertical_sync_start) && (v_cntr < vertical_sync_end))
|
209 |
|
|
|| ((v_cntr == vertical_sync_end) && (h_cntr < v_sync_h_pos));
|
210 |
|
|
else v_sync_1 <= v_sync_1;
|
211 |
|
|
|
212 |
|
|
/* vertical blanking */
|
213 |
|
|
always @(posedge clk)
|
214 |
|
|
if (~rst) v_blank_1 <= 1'b1;
|
215 |
|
|
else if (clk_en) v_blank_1 <= (v_cntr >= vertical_resolution) || (v_cntr >= v_size) || (v_cntr >= v_display_size);
|
216 |
|
|
else v_blank_1 <= v_blank_1;
|
217 |
|
|
|
218 |
|
|
/*
|
219 |
|
|
* odd_field is asserted during odd fields of interlaced pictures.
|
220 |
|
|
* odd_field is not asserted when video is not interlaced.
|
221 |
|
|
*/
|
222 |
|
|
|
223 |
|
|
always @(posedge clk)
|
224 |
|
|
if (~rst) odd_field <= 1'b0;
|
225 |
|
|
else if (clk_en && ~interlaced) odd_field <= 1'b0;
|
226 |
|
|
else if (clk_en && interlaced && (h_cntr == 12'b0) && (v_cntr == 12'b0)) odd_field <= ~odd_field; // when interlaced, toggle
|
227 |
|
|
else odd_field <= odd_field;
|
228 |
|
|
|
229 |
|
|
/*
|
230 |
|
|
* Stage 2
|
231 |
|
|
*/
|
232 |
|
|
|
233 |
|
|
reg [11:0]h_cntr_2;
|
234 |
|
|
reg [11:0]v_cntr_2;
|
235 |
|
|
reg h_blank_2;
|
236 |
|
|
reg v_blank_2;
|
237 |
|
|
reg h_sync_2;
|
238 |
|
|
reg v_sync_2;
|
239 |
|
|
|
240 |
|
|
always @(posedge clk)
|
241 |
|
|
if (~rst) h_cntr_2 <= 12'd0;
|
242 |
|
|
else if (clk_en) h_cntr_2 <= h_cntr_1;
|
243 |
|
|
else h_cntr_2 <= h_cntr_2;
|
244 |
|
|
|
245 |
|
|
always @(posedge clk)
|
246 |
|
|
if (~rst) v_cntr_2 <= 12'd0;
|
247 |
|
|
else if (clk_en) v_cntr_2 <= v_cntr_1;
|
248 |
|
|
else v_cntr_2 <= v_cntr_2;
|
249 |
|
|
|
250 |
|
|
always @(posedge clk)
|
251 |
|
|
if (~rst) h_blank_2 <= 1'b1;
|
252 |
|
|
else if (clk_en) h_blank_2 <= h_blank_1;
|
253 |
|
|
else h_blank_2 <= h_blank_2;
|
254 |
|
|
|
255 |
|
|
always @(posedge clk)
|
256 |
|
|
if (~rst) v_blank_2 <= 1'b1;
|
257 |
|
|
else if (clk_en) v_blank_2 <= v_blank_1;
|
258 |
|
|
else v_blank_2 <= v_blank_2;
|
259 |
|
|
|
260 |
|
|
always @(posedge clk)
|
261 |
|
|
if (~rst) h_sync_2 <= 1'b0;
|
262 |
|
|
else if (clk_en) h_sync_2 <= h_sync_1;
|
263 |
|
|
else h_sync_2 <= h_sync_2;
|
264 |
|
|
|
265 |
|
|
always @(posedge clk)
|
266 |
|
|
if (~rst) v_sync_2 <= 1'b0;
|
267 |
|
|
else if (clk_en) v_sync_2 <= v_sync_1;
|
268 |
|
|
else v_sync_2 <= v_sync_2;
|
269 |
|
|
|
270 |
|
|
/*
|
271 |
|
|
* horizontal coordinate
|
272 |
|
|
*/
|
273 |
|
|
|
274 |
|
|
always @(posedge clk)
|
275 |
|
|
if (~rst) h_pos <= 12'd0;
|
276 |
|
|
else if (clk_en) h_pos <= h_cntr_2;
|
277 |
|
|
else h_pos <= h_pos;
|
278 |
|
|
|
279 |
|
|
/*
|
280 |
|
|
* vertical coordinate: line number.
|
281 |
|
|
* If progressive, v_pos sequences through the line number 0, 1, 2, 3, 4, 5, ...
|
282 |
|
|
* If interlaced, v_pos sequences through even numbers on odd fields 0, 2, 4, ...
|
283 |
|
|
* and through odd numbers on even fields 1, 3, 5, ...
|
284 |
|
|
* (This is because tv people start counting from 1, not 0.)
|
285 |
|
|
*/
|
286 |
|
|
|
287 |
|
|
always @(posedge clk)
|
288 |
|
|
if (~rst) v_pos <= 12'd0;
|
289 |
|
|
else if (clk_en) v_pos <= interlaced ? { v_cntr_2[10:0], ~odd_field } : v_cntr_2;
|
290 |
|
|
else v_pos <= v_pos;
|
291 |
|
|
|
292 |
|
|
always @(posedge clk)
|
293 |
|
|
if (~rst) h_sync <= 1'b0;
|
294 |
|
|
else if (clk_en) h_sync <= h_sync_2;
|
295 |
|
|
else h_sync <= h_sync;
|
296 |
|
|
|
297 |
|
|
always @(posedge clk)
|
298 |
|
|
if (~rst) v_sync <= 1'b0;
|
299 |
|
|
else if (clk_en) v_sync <= v_sync_2;
|
300 |
|
|
else v_sync <= v_sync;
|
301 |
|
|
|
302 |
|
|
always @(posedge clk)
|
303 |
|
|
if (~rst) h_blank <= 1'b1;
|
304 |
|
|
else if (clk_en) h_blank <= h_blank_2;
|
305 |
|
|
else h_blank <= h_blank;
|
306 |
|
|
|
307 |
|
|
always @(posedge clk)
|
308 |
|
|
if (~rst) v_blank <= 1'b1;
|
309 |
|
|
else if (clk_en) v_blank <= v_blank_2;
|
310 |
|
|
else v_blank <= v_blank;
|
311 |
|
|
|
312 |
|
|
/*
|
313 |
|
|
* pixel enable
|
314 |
|
|
*/
|
315 |
|
|
|
316 |
|
|
always @(posedge clk)
|
317 |
|
|
if (~rst) pixel_en <= 1'd0;
|
318 |
|
|
else if (clk_en) pixel_en <= ~h_blank_2 && ~v_blank_2;
|
319 |
|
|
else pixel_en <= pixel_en;
|
320 |
|
|
|
321 |
|
|
/*
|
322 |
|
|
* composite sync
|
323 |
|
|
*/
|
324 |
|
|
|
325 |
|
|
always @(posedge clk)
|
326 |
|
|
if (~rst) c_sync <= 1'b0;
|
327 |
|
|
else if (clk_en) c_sync <= ~(h_sync_2 ^ v_sync_2);
|
328 |
|
|
else c_sync <= c_sync;
|
329 |
|
|
|
330 |
|
|
`ifdef DEBUG
|
331 |
|
|
always @(posedge clk)
|
332 |
|
|
begin
|
333 |
|
|
$strobe("%m\th_pos: %4d v_pos: %4d h_cntr: %4d v_cntr: %4d h_sync: %d v_sync: %d h_blank: %d v_blank: %d pixel_en: %d odd_field: %d v_sync_h_pos: %d h_display_size: %d v_display_size: %d h_size: %d v_size: %d",
|
334 |
|
|
h_pos, v_pos, h_cntr, v_cntr, h_sync, v_sync, h_blank, v_blank, pixel_en, odd_field, v_sync_h_pos, h_display_size, v_display_size, h_size, v_size);
|
335 |
|
|
|
336 |
|
|
$strobe("%m\thorizontal_size: %d vertical_size: %d display_horizontal_size: %d display_vertical_size: %d horizontal_resolution: %d horizontal_sync_start: %d horizontal_sync_end: %d horizontal_length: %d",
|
337 |
|
|
horizontal_size, vertical_size, display_horizontal_size, display_vertical_size, horizontal_resolution, horizontal_sync_start, horizontal_sync_end, horizontal_length);
|
338 |
|
|
|
339 |
|
|
$strobe("%m\tvertical_resolution: %d vertical_sync_start: %d vertical_sync_end: %d horizontal_halfline: %d vertical_length: %d interlaced: %d",
|
340 |
|
|
vertical_resolution, vertical_sync_start, vertical_sync_end, horizontal_halfline, vertical_length, interlaced);
|
341 |
|
|
|
342 |
|
|
$strobe("%m\t%4d.%4d h_sync: %0d v_sync: %0d h_blank: %0d v_blank: %0d pixel_en: %0d", h_pos, v_pos, h_sync, v_sync, h_blank, v_blank, pixel_en);
|
343 |
|
|
|
344 |
|
|
$strobe("sync2graph %0d %0d %d %d %d", h_pos, v_pos, h_sync, v_sync, pixel_en); // for sync2graph testbench
|
345 |
|
|
end
|
346 |
|
|
`endif
|
347 |
|
|
endmodule
|
348 |
|
|
/* not truncated */
|