OpenCores
URL https://opencores.org/ocsvn/mpeg2fpga/mpeg2fpga/trunk

Subversion Repositories mpeg2fpga

[/] [mpeg2fpga/] [trunk/] [rtl/] [mpeg2/] [yuv2rgb.v] - Blame information for rev 2

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 kdv
/*
2
 * yuv2rgb.v
3
 *
4
 * Copyright (c) 2006 - 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
 * yuv2rgb - conversion from y, u, v, to r, g, b.
21
 */
22
 
23
`include "timescale.v"
24
 
25
`undef DEBUG
26
//`define DEBUG 1
27
 
28
module yuv2rgb (clk, clk_en, rst,
29
                matrix_coefficients, y, u, v, h_sync_in, v_sync_in, pixel_en_in,
30
                r, g, b, y_out, u_out, v_out, h_sync_out, v_sync_out, c_sync_out, pixel_en_out
31
                );
32
  input  clk;
33
  input  clk_en;
34
  input  rst;
35
 
36
  input [7:0] matrix_coefficients; /* extracted from mpeg2 bitstream. Determines yuv -> rgb conversion factors. ISO/IEC 13818-2, par. 6.3.6 */
37
 
38
  input [7:0]y;
39
  input [7:0]u;
40
  input [7:0]v;
41
 
42
  output reg [7:0]r;
43
  output reg [7:0]g;
44
  output reg [7:0]b;
45
  output reg [7:0]y_out;
46
  output reg [7:0]u_out;
47
  output reg [7:0]v_out;
48
 
49
  /*
50
   * pixel_en_out, h_sync_out, v_sync_out are pixel_en_in, h_sync_in and v_sync_in, delayed so as to balance the delay from yuv -> rgb.
51
   * Typical use is to connect r, g, b to the 24-bit data-in of the dvi transmitter,
52
   * pixel_en_out, h_sync_out and video_out to de (data enable), h_sync and v_sync of the dvi transmitter.
53
   */
54
 
55
  input pixel_en_in;
56
  input h_sync_in;
57
  input v_sync_in;
58
  output reg pixel_en_out;
59
  output reg h_sync_out;
60
  output reg v_sync_out;
61
  output reg c_sync_out;
62
 
63
  reg signed [26:0]cy_y;
64
  reg signed [26:0]crv_v;
65
  reg signed [26:0]cbu_u;
66
  reg signed [26:0]cgu_u;
67
  reg signed [26:0]cgv_v;
68
 
69
  reg signed [17:0]crv;
70
  reg signed [17:0]cbu;
71
  reg signed [17:0]cgu;
72
  reg signed [17:0]cgv;
73
 
74
  reg signed [8:0]y_offset;
75
  reg signed [8:0]u_offset;
76
  reg signed [8:0]v_offset;
77
 
78
  reg signed [29:0]r_0;
79
  reg signed [29:0]g1_0;
80
  reg signed [29:0]g2_0;
81
  reg signed [29:0]b_0;
82
 
83
  reg signed [29:0]r_1;
84
  reg signed [29:0]g_1;
85
  reg signed [29:0]b_1;
86
 
87
  reg pixel_en_0;
88
  reg h_sync_0;
89
  reg v_sync_0;
90
  reg [7:0]y_0;
91
  reg [7:0]u_0;
92
  reg [7:0]v_0;
93
 
94
  reg pixel_en_1;
95
  reg h_sync_1;
96
  reg v_sync_1;
97
  reg [7:0]y_1;
98
  reg [7:0]u_1;
99
  reg [7:0]v_1;
100
 
101
  reg pixel_en_2;
102
  reg h_sync_2;
103
  reg v_sync_2;
104
  reg [7:0]y_2;
105
  reg [7:0]u_2;
106
  reg [7:0]v_2;
107
 
108
  /*
109
   * Simplify matrix_coefficients: values 8..255 are reserved and should not occur.
110
   * If value of matrix_coefficients outside 0..7 range, replace with 0.
111
   */
112
 
113
  reg         [2:0]mat_coeff;
114
  always @(posedge clk)
115
    if (~rst) mat_coeff <= 0;
116
    else if (clk_en && (matrix_coefficients[7:3] == 5'b0)) mat_coeff <= matrix_coefficients[2:0];
117
    else mat_coeff <= 0;
118
 
119
  /*
120
   *
121
   * Table 6-9 inverted.
122
   *
123
   * y        = cr * r + cg * g + cb * b
124
   * cr + cg + cb = 1
125
   *
126
   * cy       = (255/219) * 32768
127
   * crv      = (255/224) * 32768 * (1-cr) / 0.5
128
   * cbu      = (255/224) * 32768 * (1-cb) / 0.5
129
   * cgu      = (255/224) * 32768 * (cb/cg) * (1 - cb) / 0.5
130
   * cgv      = (255/224) * 32768 * (cr/cg) * (1 - cr) / 0.5
131
   * r        = ( cy * (y - 16)                   + crv * (v - 128) + 16384) >> 15;
132
   * g        = ( cy * (y - 16) - cgu * (u - 128) + crv * (v - 128) + 16384) >> 15;
133
   * b        = ( cy * (y - 16) - cbu * (u - 128)                   + 16384) >> 15;
134
   */
135
 
136
  parameter signed [17:0]
137
    cy = 18'sd38155;
138
 
139
  always @(posedge clk)
140
    if (clk_en)
141
      case (mat_coeff)
142
        3'd0, /* default value, no sequence_display_extension */
143
        3'd1: /* ITU-R Rec. 709 (1990) */
144
              begin
145
                crv <= 18'sd58752;
146
                cbu <= 18'sd69227;
147
                cgu <= 18'sd6977;
148
                cgv <= 18'sd17452;
149
              end
150
        3'd2, /* unspecified */
151
        3'd3, /* reserved */
152
        3'd5, /* ITU-R Rec. 624-4 System B, G */
153
        3'd6: /* SMPTE 170M */
154
              begin
155
                crv <= 18'sd52299;
156
                cbu <= 18'sd66101;
157
                cgu <= 18'sd12838;
158
                cgv <= 18'sd26640;
159
              end
160
        3'd4: /* FCC */
161
              begin
162
                crv <= 18'sd52224;
163
                cbu <= 18'sd66399;
164
                cgu <= 18'sd12380;
165
                cgv <= 18'sd26555;
166
              end
167
        3'd7: /* SMPTE 240M (1987) */
168
              begin
169
                crv <= 18'sd58790;
170
                cbu <= 18'sd68115;
171
                cgu <= 18'sd8454;
172
                cgv <= 18'sd17780;
173
              end
174
     endcase
175
 
176
  /* conversion */
177
  always @(posedge clk)
178
    if (~rst)
179
      begin
180
        y_offset <= 0;
181
        u_offset <= 0;
182
        v_offset <= 0;
183
 
184
        cy_y  <= 0;
185
        crv_v <= 0;
186
        cgv_v <= 0;
187
        cgu_u <= 0;
188
        cbu_u <= 0;
189
 
190
        r_0   <= 0;
191
        g1_0  <= 0;
192
        g2_0  <= 0;
193
        b_0   <= 0;
194
 
195
        r_1   <= 0;
196
        g_1   <= 0;
197
        b_1   <= 0;
198
      end
199
    else if (clk_en)
200
      begin
201
        y_offset <= {1'b0, y} - 9'sd16;
202
        u_offset <= {1'b0, u} - 9'sd128;
203
        v_offset <= {1'b0, v} - 9'sd128;
204
 
205
        cy_y  <= cy  * y_offset;
206
        cgu_u <= cgu * u_offset;
207
        cbu_u <= cbu * u_offset;
208
        crv_v <= crv * v_offset;
209
        cgv_v <= cgv * v_offset;
210
 
211
        r_0   <=   {{3{cy_y[26]}}, cy_y}  + {{3{crv_v[26]}}, crv_v};
212
        g1_0  <=   {{3{cy_y[26]}}, cy_y}  - {{3{cgu_u[26]}}, cgu_u};
213
        g2_0  <=                          - {{3{cgv_v[26]}}, cgv_v} + 30'sd16384;
214
        b_0   <=   {{3{cy_y[26]}}, cy_y}  + {{3{cbu_u[26]}}, cbu_u};
215
 
216
        r_1   <= (r_0 + 30'sd16384) >>> 15;
217
        g_1   <= (g1_0 + g2_0) >>> 15;
218
        b_1   <= (b_0 + 30'sd16384) >>> 15;
219
      end
220
    else
221
      begin
222
        y_offset <= y_offset;
223
        u_offset <= u_offset;
224
        v_offset <= v_offset;
225
 
226
        cy_y  <= cy_y;
227
        cgu_u <= cgu_u;
228
        cbu_u <= cbu_u;
229
        crv_v <= crv_v;
230
        cgv_v <= cgv_v;
231
 
232
        r_0   <= r_0;
233
        g1_0  <= g1_0;
234
        g2_0  <= g2_0;
235
        b_0   <= b_0;
236
 
237
        r_1   <= r_1;
238
        g_1   <= r_1;
239
        b_1   <= r_1;
240
      end
241
 
242
  /* clipping */
243
  always @(posedge clk)
244
    if (~rst) r <= 8'd0;
245
    else if (clk_en && r_1[29]) r <= 8'd0; /* negative, clip to 0 */
246
    else if (clk_en && (r_1[29:8] != 22'b0)) r <= 8'd255; /* 256 or more, clip to 255 */
247
    else if (clk_en) r <= r_1[7:0]; /* between 0 and 255, copy */
248
    else r <= r;
249
 
250
  always @(posedge clk)
251
    if (~rst) g <= 8'd0;
252
    else if (clk_en && g_1[29]) g <= 8'd0;
253
    else if (clk_en && (g_1[29:8] != 22'b0)) g <= 8'd255;
254
    else if (clk_en) g <= g_1[7:0];
255
    else g <= g;
256
 
257
  always @(posedge clk)
258
    if (~rst) b <= 8'd0;
259
    else if (clk_en && b_1[29]) b <= 8'd0;
260
    else if (clk_en && (b_1[29:8] != 22'b0)) b <= 8'd255;
261
    else if (clk_en) b <= b_1[7:0];
262
    else b <= b;
263
 
264
 /* delay pixel_en, h_sync and v_sync so they are balanced with r, g, b */
265
 
266
  always @(posedge clk)
267
    if (~rst)
268
      begin
269
        pixel_en_0 <= 1'b0;
270
        pixel_en_1 <= 1'b0;
271
        pixel_en_2 <= 1'b0;
272
        pixel_en_out <= 1'b0;
273
     end
274
   else if (clk_en)
275
     begin
276
        pixel_en_0 <= pixel_en_in;
277
        pixel_en_1 <= pixel_en_0;
278
        pixel_en_2 <= pixel_en_1;
279
        pixel_en_out <= pixel_en_2;
280
     end
281
   else
282
     begin
283
        pixel_en_0 <= pixel_en_0;
284
        pixel_en_1 <= pixel_en_1;
285
        pixel_en_2 <= pixel_en_2;
286
        pixel_en_out <= pixel_en_out;
287
     end
288
 
289
  always @(posedge clk)
290
    if (~rst)
291
      begin
292
        h_sync_0 <= 1'b0;
293
        h_sync_1 <= 1'b0;
294
        h_sync_2 <= 1'b0;
295
        h_sync_out <= 1'b0;
296
     end
297
   else if (clk_en)
298
     begin
299
        h_sync_0 <= h_sync_in;
300
        h_sync_1 <= h_sync_0;
301
        h_sync_2 <= h_sync_1;
302
        h_sync_out <= h_sync_2;
303
     end
304
   else
305
     begin
306
        h_sync_0 <= h_sync_0;
307
        h_sync_1 <= h_sync_1;
308
        h_sync_2 <= h_sync_2;
309
        h_sync_out <= h_sync_out;
310
     end
311
 
312
  always @(posedge clk)
313
    if (~rst)
314
      begin
315
        v_sync_0 <= 1'b0;
316
        v_sync_1 <= 1'b0;
317
        v_sync_2 <= 1'b0;
318
        v_sync_out <= 1'b0;
319
     end
320
   else if (clk_en)
321
     begin
322
        v_sync_0 <= v_sync_in;
323
        v_sync_1 <= v_sync_0;
324
        v_sync_2 <= v_sync_1;
325
        v_sync_out <= v_sync_2;
326
     end
327
   else
328
     begin
329
        v_sync_0 <= v_sync_0;
330
        v_sync_1 <= v_sync_1;
331
        v_sync_2 <= v_sync_2;
332
        v_sync_out <= v_sync_out;
333
     end
334
  /*
335
   * composite sync
336
   */
337
 
338
  always @(posedge clk)
339
    if (~rst) c_sync_out <= 1'b0;
340
    else if (clk_en) c_sync_out <= ~(h_sync_2 ^ v_sync_2);
341
    else c_sync_out <= c_sync_out;
342
 
343
  /*
344
   * yuv
345
   */
346
 
347
  always @(posedge clk)
348
    if (~rst)
349
      begin
350
        y_0 <= 8'd0;
351
        y_1 <= 8'd0;
352
        y_2 <= 8'd0;
353
        y_out <= 8'd0;
354
     end
355
   else if (clk_en)
356
     begin
357
        y_0 <= y;
358
        y_1 <= y_0;
359
        y_2 <= y_1;
360
        y_out <= y_2;
361
     end
362
   else
363
     begin
364
        y_0 <= y_0;
365
        y_1 <= y_1;
366
        y_2 <= y_2;
367
        y_out <= y_out;
368
     end
369
 
370
  always @(posedge clk)
371
    if (~rst)
372
      begin
373
        u_0 <= 8'd0;
374
        u_1 <= 8'd0;
375
        u_2 <= 8'd0;
376
        u_out <= 8'd0;
377
     end
378
   else if (clk_en)
379
     begin
380
        u_0 <= u;
381
        u_1 <= u_0;
382
        u_2 <= u_1;
383
        u_out <= u_2;
384
     end
385
   else
386
     begin
387
        u_0 <= u_0;
388
        u_1 <= u_1;
389
        u_2 <= u_2;
390
        u_out <= u_out;
391
     end
392
 
393
  always @(posedge clk)
394
    if (~rst)
395
      begin
396
        v_0 <= 8'd0;
397
        v_1 <= 8'd0;
398
        v_2 <= 8'd0;
399
        v_out <= 8'd0;
400
     end
401
   else if (clk_en)
402
     begin
403
        v_0 <= v;
404
        v_1 <= v_0;
405
        v_2 <= v_1;
406
        v_out <= v_2;
407
     end
408
   else
409
     begin
410
        v_0 <= v_0;
411
        v_1 <= v_1;
412
        v_2 <= v_2;
413
        v_out <= v_out;
414
     end
415
 
416
`ifdef DEBUG
417
  always @(posedge clk)
418
    begin
419
      $strobe("%m\tyuv: %0d %0d %0d pixel_en_in: %0d rgb: %0d %0d %0d pixel_en_out: %0d", y, u, v, pixel_en_in, r, g, b, pixel_en_out);
420
      $strobe("%m\tmatrix_coefficients: %4d y: %4d u: %4d v: %d y_offset: %d u_offset: %d v_offset: %d cy_y: %d crv_v: %d cgv_v: %d cgu_u: %d cbu_u: %d r_0: %d g1_0: %d g2_0: %d b_0: %d r_1: %d g_1: %d b_1: %d r: %4d g: %4d b: %4d ",
421
                   matrix_coefficients,     y,     u,     v,    y_offset,    u_offset,    v_offset,    cy_y,    crv_v,    cgv_v,    cgu_u,    cbu_u,    r_0,    g1_0,    g2_0,    b_0,    r_1,    g_1,    b_1,    r,     g,     b);
422
    end
423
`endif
424
endmodule
425
/* not truncated */

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.