1 |
2 |
kdv |
/*
|
2 |
|
|
* resample_bilinear.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 |
|
|
* resample_bilinear - chroma resampling: bilinear interpolation. Doesn't increase sharpness, but doesn't "ring" either.
|
21 |
|
|
*/
|
22 |
|
|
|
23 |
|
|
`include "timescale.v"
|
24 |
|
|
|
25 |
|
|
`undef DEBUG
|
26 |
|
|
//`define DEBUG 1
|
27 |
|
|
|
28 |
|
|
module resample_bilinear (
|
29 |
|
|
clk, clk_en, rst,
|
30 |
|
|
fifo_read, fifo_valid,
|
31 |
|
|
fifo_osd, fifo_y, fifo_u_upper, fifo_u_lower, fifo_v_upper, fifo_v_lower, fifo_position,
|
32 |
|
|
y, u, v, osd_out, position_out, pixel_wr_en, pixel_wr_almost_full
|
33 |
|
|
);
|
34 |
|
|
|
35 |
|
|
input clk; // clock
|
36 |
|
|
input clk_en; // clock enable
|
37 |
|
|
input rst; // synchronous active low reset
|
38 |
|
|
|
39 |
|
|
output reg fifo_read;
|
40 |
|
|
input fifo_valid;
|
41 |
|
|
|
42 |
|
|
/* chroma resampling: writing pixels and osd */
|
43 |
|
|
output reg [7:0]y;
|
44 |
|
|
output reg [7:0]u;
|
45 |
|
|
output reg [7:0]v;
|
46 |
|
|
output reg [7:0]osd_out;
|
47 |
|
|
output reg [2:0]position_out;
|
48 |
|
|
output reg pixel_wr_en;
|
49 |
|
|
input pixel_wr_almost_full;
|
50 |
|
|
|
51 |
|
|
/* pixel data from resample_dta */
|
52 |
|
|
input [127:0]fifo_osd; /* osd data */
|
53 |
|
|
input [127:0]fifo_y; /* lumi */
|
54 |
|
|
input [63:0]fifo_u_upper; /* chromi, upper row */
|
55 |
|
|
input [63:0]fifo_u_lower; /* chromi, lower row */
|
56 |
|
|
input [63:0]fifo_v_upper; /* chromi, upper row */
|
57 |
|
|
input [63:0]fifo_v_lower; /* chromi, lower row */
|
58 |
|
|
input [2:0]fifo_position; /* position code */
|
59 |
|
|
|
60 |
|
|
`include "resample_codes.v"
|
61 |
|
|
|
62 |
|
|
parameter [2:0]
|
63 |
|
|
STATE_INIT = 3'h0,
|
64 |
|
|
STATE_MACROBLOCK = 3'h1,
|
65 |
|
|
STATE_PIXEL = 3'h2;
|
66 |
|
|
|
67 |
|
|
reg [2:0]state;
|
68 |
|
|
reg [2:0]next;
|
69 |
|
|
|
70 |
|
|
reg [15:0]loop;
|
71 |
|
|
|
72 |
|
|
/* next state logic */
|
73 |
|
|
always @*
|
74 |
|
|
case (state)
|
75 |
|
|
STATE_INIT: if (~pixel_wr_almost_full && fifo_valid) next = STATE_MACROBLOCK;
|
76 |
|
|
else next = STATE_INIT;
|
77 |
|
|
|
78 |
|
|
STATE_MACROBLOCK: next = STATE_PIXEL;
|
79 |
|
|
|
80 |
|
|
STATE_PIXEL: if (loop[15] == 1'b0) next = STATE_INIT;
|
81 |
|
|
else next = STATE_PIXEL;
|
82 |
|
|
|
83 |
|
|
default next = STATE_INIT;
|
84 |
|
|
endcase
|
85 |
|
|
|
86 |
|
|
/* state */
|
87 |
|
|
always @(posedge clk)
|
88 |
|
|
if(~rst) state <= STATE_INIT;
|
89 |
|
|
else if (clk_en) state <= next;
|
90 |
|
|
else state <= state;
|
91 |
|
|
|
92 |
|
|
always @(posedge clk)
|
93 |
|
|
if(~rst) loop <= 16'b0;
|
94 |
|
|
else if (clk_en)
|
95 |
|
|
case (state)
|
96 |
|
|
STATE_INIT:
|
97 |
|
|
if (fifo_valid)
|
98 |
|
|
begin
|
99 |
|
|
case (fifo_position)
|
100 |
|
|
ROW_0_COL_0,
|
101 |
|
|
ROW_1_COL_0,
|
102 |
|
|
ROW_X_COL_0: loop <= 16'b1111111111111000; // output 15 pixels for first macroblock of a row of pixels
|
103 |
|
|
ROW_X_COL_X: loop <= 16'b1111111111111100; // output 16 pixels for in-between macroblocks
|
104 |
|
|
ROW_X_COL_LAST: loop <= 16'b1111111111111110; // output 17 pixels for last macroblock of a row of pixels
|
105 |
|
|
default loop <= 16'b0;
|
106 |
|
|
endcase
|
107 |
|
|
end
|
108 |
|
|
else
|
109 |
|
|
loop <= loop;
|
110 |
|
|
STATE_MACROBLOCK: loop <= loop;
|
111 |
|
|
STATE_PIXEL: loop <= {loop[14:0], 1'b0};
|
112 |
|
|
default loop <= loop;
|
113 |
|
|
endcase
|
114 |
|
|
else loop <= loop;
|
115 |
|
|
|
116 |
|
|
always @(posedge clk)
|
117 |
|
|
if(~rst) fifo_read <= 1'b0;
|
118 |
|
|
else if (clk_en) fifo_read <= (state == STATE_MACROBLOCK);
|
119 |
|
|
else fifo_read <= fifo_read;
|
120 |
|
|
|
121 |
|
|
/*
|
122 |
|
|
What "bilinear upsampling" boils down to is this:
|
123 |
|
|
- pass luminance on unchanged
|
124 |
|
|
- if chroma horizontal position coincides with luma horizontal position, interpolate chroma vertically:
|
125 |
|
|
chroma_out = 0.75 * chroma_upper + 0.25 * chroma_lower
|
126 |
|
|
- if chroma horizontal position does not coincide with luma horizontal position, interpolate chroma both horizontally and vertically:
|
127 |
|
|
chroma_out = 0.375 * chroma_upper_left + 0.125 * chroma_lower_left + 0.375 * chroma_upper_right + 0.125 * chroma_lower_right
|
128 |
|
|
It's the responsibility of the chroma resampling address generator to make sure "upper" and "lower" row correspond to whatever is suitable for frame. top or bottom picture.
|
129 |
|
|
resample_bilinear just does the math.
|
130 |
|
|
*/
|
131 |
|
|
|
132 |
|
|
/* stage 0 */
|
133 |
|
|
|
134 |
|
|
/* registers to read fifo_* in.
|
135 |
|
|
16 pixels - a macroblock - wide.
|
136 |
|
|
Two rows of chrominance information are stored, as we will have to interpolate between these two rows. */
|
137 |
|
|
reg [127:0]osd_0; /* osd data */
|
138 |
|
|
reg [127:0]y_0; /* lumi */
|
139 |
|
|
reg [63:0]u_upper_0; /* chromi, upper row */
|
140 |
|
|
reg [63:0]u_lower_0; /* chromi, lower row */
|
141 |
|
|
reg [63:0]v_upper_0; /* chromi, upper row */
|
142 |
|
|
reg [63:0]v_lower_0; /* chromi, lower row */
|
143 |
|
|
reg [2:0]position_0; /* position code */
|
144 |
|
|
|
145 |
|
|
always @(posedge clk)
|
146 |
|
|
if (~rst)
|
147 |
|
|
begin
|
148 |
|
|
osd_0 <= 8'b0;
|
149 |
|
|
y_0 <= 8'b0;
|
150 |
|
|
u_upper_0 <= 12'sd0;
|
151 |
|
|
u_lower_0 <= 12'sd0;
|
152 |
|
|
v_upper_0 <= 12'sd0;
|
153 |
|
|
v_lower_0 <= 12'sd0;
|
154 |
|
|
position_0 <= 3'b0;
|
155 |
|
|
end
|
156 |
|
|
else if (clk_en && (state == STATE_INIT) && fifo_valid)
|
157 |
|
|
begin
|
158 |
|
|
osd_0 <= fifo_osd;
|
159 |
|
|
y_0 <= fifo_y;
|
160 |
|
|
u_upper_0 <= fifo_u_upper;
|
161 |
|
|
u_lower_0 <= fifo_u_lower;
|
162 |
|
|
v_upper_0 <= fifo_v_upper;
|
163 |
|
|
v_lower_0 <= fifo_v_lower;
|
164 |
|
|
position_0 <= fifo_position;
|
165 |
|
|
end
|
166 |
|
|
else
|
167 |
|
|
begin
|
168 |
|
|
osd_0 <= osd_0;
|
169 |
|
|
y_0 <= y_0;
|
170 |
|
|
u_upper_0 <= u_upper_0;
|
171 |
|
|
u_lower_0 <= u_lower_0;
|
172 |
|
|
v_upper_0 <= v_upper_0;
|
173 |
|
|
v_lower_0 <= v_lower_0;
|
174 |
|
|
position_0 <= position_0;
|
175 |
|
|
end
|
176 |
|
|
|
177 |
|
|
/* stage 1 */
|
178 |
|
|
reg [135:0]osd_1;
|
179 |
|
|
reg [135:0]y_1;
|
180 |
|
|
reg [135:0]u_upper_1;
|
181 |
|
|
reg [135:0]u_lower_1;
|
182 |
|
|
reg [135:0]v_upper_1;
|
183 |
|
|
reg [135:0]v_lower_1;
|
184 |
|
|
reg [2:0]position_1;
|
185 |
|
|
reg pixel_wr_en_1;
|
186 |
|
|
reg [2:0]position_0_saved;
|
187 |
|
|
|
188 |
|
|
always @(posedge clk)
|
189 |
|
|
if (~rst)
|
190 |
|
|
begin
|
191 |
|
|
osd_1 <= 135'b0;
|
192 |
|
|
y_1 <= 135'b0;
|
193 |
|
|
u_upper_1 <= 135'b0;
|
194 |
|
|
u_lower_1 <= 135'b0;
|
195 |
|
|
v_upper_1 <= 135'b0;
|
196 |
|
|
v_lower_1 <= 135'b0;
|
197 |
|
|
position_1 <= 3'b0;
|
198 |
|
|
position_0_saved <= 3'b0;
|
199 |
|
|
pixel_wr_en_1 <= 1'b0;
|
200 |
|
|
end
|
201 |
|
|
else if (clk_en && (state == STATE_INIT))
|
202 |
|
|
begin
|
203 |
|
|
osd_1 <= osd_1;
|
204 |
|
|
y_1 <= y_1;
|
205 |
|
|
u_upper_1 <= u_upper_1;
|
206 |
|
|
u_lower_1 <= u_lower_1;
|
207 |
|
|
v_upper_1 <= v_upper_1;
|
208 |
|
|
v_lower_1 <= v_lower_1;
|
209 |
|
|
position_1 <= position_1;
|
210 |
|
|
position_0_saved <= position_0_saved;
|
211 |
|
|
pixel_wr_en_1 <= 1'b0;
|
212 |
|
|
end
|
213 |
|
|
else if (clk_en && (state == STATE_MACROBLOCK) && ((position_0 == ROW_0_COL_0) || (position_0 == ROW_1_COL_0) || (position_0 == ROW_X_COL_0)))
|
214 |
|
|
begin
|
215 |
|
|
osd_1 <= {osd_0, 8'b0};
|
216 |
|
|
y_1 <= {y_0, 8'b0};
|
217 |
|
|
u_upper_1 <= {duplicate_pixel(u_upper_0), 8'b0};
|
218 |
|
|
u_lower_1 <= {duplicate_pixel(u_lower_0), 8'b0};
|
219 |
|
|
v_upper_1 <= {duplicate_pixel(v_upper_0), 8'b0};
|
220 |
|
|
v_lower_1 <= {duplicate_pixel(v_lower_0), 8'b0};
|
221 |
|
|
position_1 <= position_0;
|
222 |
|
|
position_0_saved <= ROW_X_COL_X;
|
223 |
|
|
pixel_wr_en_1 <= 1'b1;
|
224 |
|
|
end
|
225 |
|
|
else if (clk_en && (state == STATE_MACROBLOCK) && ((position_0 == ROW_X_COL_LAST) || (position_0 == ROW_X_COL_X)))
|
226 |
|
|
begin
|
227 |
|
|
osd_1 <= {osd_1[127:120], osd_0};
|
228 |
|
|
y_1 <= {y_1[127:120], y_0};
|
229 |
|
|
u_upper_1 <= {u_upper_1[127:120], duplicate_pixel(u_upper_0)};
|
230 |
|
|
u_lower_1 <= {u_lower_1[127:120], duplicate_pixel(u_lower_0)};
|
231 |
|
|
v_upper_1 <= {v_upper_1[127:120], duplicate_pixel(v_upper_0)};
|
232 |
|
|
v_lower_1 <= {v_lower_1[127:120], duplicate_pixel(v_lower_0)};
|
233 |
|
|
position_1 <= ROW_X_COL_X;
|
234 |
|
|
position_0_saved <= position_0;
|
235 |
|
|
pixel_wr_en_1 <= 1'b1;
|
236 |
|
|
end
|
237 |
|
|
else if (clk_en && (state == STATE_MACROBLOCK))
|
238 |
|
|
begin
|
239 |
|
|
osd_1 <= osd_1;
|
240 |
|
|
y_1 <= y_1;
|
241 |
|
|
u_upper_1 <= u_upper_1;
|
242 |
|
|
u_lower_1 <= u_lower_1;
|
243 |
|
|
v_upper_1 <= v_upper_1;
|
244 |
|
|
v_lower_1 <= v_lower_1;
|
245 |
|
|
position_1 <= position_1;
|
246 |
|
|
position_0_saved <= position_0_saved;
|
247 |
|
|
pixel_wr_en_1 <= 1'b0;
|
248 |
|
|
end
|
249 |
|
|
else if (clk_en && (state == STATE_PIXEL))
|
250 |
|
|
begin
|
251 |
|
|
osd_1 <= {osd_1[127:0], osd_1[7:0]};
|
252 |
|
|
y_1 <= {y_1[127:0], y_1[7:0]};
|
253 |
|
|
u_upper_1 <= {u_upper_1[127:0], u_upper_1[7:0]};
|
254 |
|
|
u_lower_1 <= {u_lower_1[127:0], u_lower_1[7:0]};
|
255 |
|
|
v_upper_1 <= {v_upper_1[127:0], v_upper_1[7:0]};
|
256 |
|
|
v_lower_1 <= {v_lower_1[127:0], v_lower_1[7:0]};
|
257 |
|
|
position_1 <= (loop[15] == 1'b0) ? position_0_saved : ROW_X_COL_X;
|
258 |
|
|
position_0_saved <= position_0_saved;
|
259 |
|
|
pixel_wr_en_1 <= 1'b1;
|
260 |
|
|
end
|
261 |
|
|
else
|
262 |
|
|
begin
|
263 |
|
|
osd_1 <= osd_1;
|
264 |
|
|
y_1 <= y_1;
|
265 |
|
|
u_upper_1 <= u_upper_1;
|
266 |
|
|
u_lower_1 <= u_lower_1;
|
267 |
|
|
v_upper_1 <= v_upper_1;
|
268 |
|
|
v_lower_1 <= v_lower_1;
|
269 |
|
|
position_1 <= position_1;
|
270 |
|
|
position_0_saved <= position_0_saved;
|
271 |
|
|
pixel_wr_en_1 <= pixel_wr_en_1;
|
272 |
|
|
end
|
273 |
|
|
|
274 |
|
|
/* helper function. given a row of 8 pixels, repeat every pixel once, producing a row of 16 pixels */
|
275 |
|
|
function [127:0]duplicate_pixel;
|
276 |
|
|
input [63:0]u;
|
277 |
|
|
begin
|
278 |
|
|
duplicate_pixel = {u[63:56], u[63:56], u[55:48], u[55:48], u[47:40], u[47:40], u[39:32], u[39:32], u[31:24], u[31:24], u[23:16], u[23:16], u[15:8], u[15:8], u[7:0], u[7:0]};
|
279 |
|
|
end
|
280 |
|
|
endfunction
|
281 |
|
|
|
282 |
|
|
/* For luminance, pick the leftmost. For chrominance, pick the leftmost two pixels - we'll need them to interpolate. */
|
283 |
|
|
|
284 |
|
|
wire [7:0]osd_pixel_1 = osd_1[135:128];
|
285 |
|
|
wire signed [7:0]y_pixel_1 = y_1[135:128];
|
286 |
|
|
wire signed [11:0]u_upper_left_pixel_1 = {{4{u_upper_1[135]}}, u_upper_1[135:128]}; // sign extend
|
287 |
|
|
wire signed [11:0]u_lower_left_pixel_1 = {{4{u_lower_1[135]}}, u_lower_1[135:128]}; // sign extend
|
288 |
|
|
wire signed [11:0]u_upper_right_pixel_1 = {{4{u_upper_1[127]}}, u_upper_1[127:120]}; // sign extend
|
289 |
|
|
wire signed [11:0]u_lower_right_pixel_1 = {{4{u_lower_1[127]}}, u_lower_1[127:120]}; // sign extend
|
290 |
|
|
wire signed [11:0]v_upper_left_pixel_1 = {{4{v_upper_1[135]}}, v_upper_1[135:128]}; // sign extend
|
291 |
|
|
wire signed [11:0]v_lower_left_pixel_1 = {{4{v_lower_1[135]}}, v_lower_1[135:128]}; // sign extend
|
292 |
|
|
wire signed [11:0]v_upper_right_pixel_1 = {{4{v_upper_1[127]}}, v_upper_1[127:120]}; // sign extend
|
293 |
|
|
wire signed [11:0]v_lower_right_pixel_1 = {{4{v_lower_1[127]}}, v_lower_1[127:120]}; // sign extend
|
294 |
|
|
|
295 |
|
|
/* stage 2 */
|
296 |
|
|
reg [7:0]osd_pixel_2;
|
297 |
|
|
reg signed [7:0]y_pixel_2;
|
298 |
|
|
reg signed [11:0]u_upper_sum_2;
|
299 |
|
|
reg signed [11:0]u_lower_sum_2;
|
300 |
|
|
reg signed [11:0]v_upper_sum_2;
|
301 |
|
|
reg signed [11:0]v_lower_sum_2;
|
302 |
|
|
reg [2:0]position_2;
|
303 |
|
|
reg pixel_wr_en_2;
|
304 |
|
|
|
305 |
|
|
always @(posedge clk)
|
306 |
|
|
if (~rst)
|
307 |
|
|
begin
|
308 |
|
|
osd_pixel_2 <= 8'b0;
|
309 |
|
|
y_pixel_2 <= 8'b0;
|
310 |
|
|
u_upper_sum_2 <= 12'sd0;
|
311 |
|
|
u_lower_sum_2 <= 12'sd0;
|
312 |
|
|
v_upper_sum_2 <= 12'sd0;
|
313 |
|
|
v_lower_sum_2 <= 12'sd0;
|
314 |
|
|
position_2 <= 3'b0;
|
315 |
|
|
pixel_wr_en_2 <= 1'b0;
|
316 |
|
|
end
|
317 |
|
|
else if (clk_en)
|
318 |
|
|
begin
|
319 |
|
|
osd_pixel_2 <= osd_pixel_1;
|
320 |
|
|
y_pixel_2 <= y_pixel_1;
|
321 |
|
|
u_upper_sum_2 <= u_upper_left_pixel_1 + u_upper_right_pixel_1;
|
322 |
|
|
u_lower_sum_2 <= u_lower_left_pixel_1 + u_lower_right_pixel_1;
|
323 |
|
|
v_upper_sum_2 <= v_upper_left_pixel_1 + v_upper_right_pixel_1;
|
324 |
|
|
v_lower_sum_2 <= v_lower_left_pixel_1 + v_lower_right_pixel_1;
|
325 |
|
|
position_2 <= position_1;
|
326 |
|
|
pixel_wr_en_2 <= pixel_wr_en_1;
|
327 |
|
|
end
|
328 |
|
|
else
|
329 |
|
|
begin
|
330 |
|
|
osd_pixel_2 <= osd_pixel_2;
|
331 |
|
|
y_pixel_2 <= y_pixel_2;
|
332 |
|
|
u_upper_sum_2 <= u_upper_sum_2;
|
333 |
|
|
u_lower_sum_2 <= u_lower_sum_2;
|
334 |
|
|
v_upper_sum_2 <= v_upper_sum_2;
|
335 |
|
|
v_lower_sum_2 <= v_lower_sum_2;
|
336 |
|
|
position_2 <= position_2;
|
337 |
|
|
pixel_wr_en_2 <= pixel_wr_en_2;
|
338 |
|
|
end
|
339 |
|
|
|
340 |
|
|
/* stage 3 */
|
341 |
|
|
reg [7:0]osd_pixel_3;
|
342 |
|
|
reg signed [7:0]y_pixel_3;
|
343 |
|
|
reg signed [11:0]u_upper_sum_3;
|
344 |
|
|
reg signed [11:0]u_lower_sum_3;
|
345 |
|
|
reg signed [11:0]v_upper_sum_3;
|
346 |
|
|
reg signed [11:0]v_lower_sum_3;
|
347 |
|
|
reg [2:0]position_3;
|
348 |
|
|
reg pixel_wr_en_3;
|
349 |
|
|
|
350 |
|
|
wire signed [11:0]double_u_upper_sum_2 = u_upper_sum_2 <<< 1;
|
351 |
|
|
wire signed [11:0]double_v_upper_sum_2 = v_upper_sum_2 <<< 1;
|
352 |
|
|
|
353 |
|
|
always @(posedge clk)
|
354 |
|
|
if (~rst)
|
355 |
|
|
begin
|
356 |
|
|
osd_pixel_3 <= 8'b0;
|
357 |
|
|
y_pixel_3 <= 8'b0;
|
358 |
|
|
u_upper_sum_3 <= 12'sd0;
|
359 |
|
|
u_lower_sum_3 <= 12'sd0;
|
360 |
|
|
v_upper_sum_3 <= 12'sd0;
|
361 |
|
|
v_lower_sum_3 <= 12'sd0;
|
362 |
|
|
position_3 <= 3'b0;
|
363 |
|
|
pixel_wr_en_3 <= 1'b0;
|
364 |
|
|
end
|
365 |
|
|
else if (clk_en)
|
366 |
|
|
begin
|
367 |
|
|
osd_pixel_3 <= osd_pixel_2;
|
368 |
|
|
y_pixel_3 <= y_pixel_2;
|
369 |
|
|
u_upper_sum_3 <= u_upper_sum_2 + double_u_upper_sum_2; // multiply by 3
|
370 |
|
|
u_lower_sum_3 <= u_lower_sum_2;
|
371 |
|
|
v_upper_sum_3 <= v_upper_sum_2 + double_v_upper_sum_2; // multiply by 3
|
372 |
|
|
v_lower_sum_3 <= v_lower_sum_2;
|
373 |
|
|
position_3 <= position_2;
|
374 |
|
|
pixel_wr_en_3 <= pixel_wr_en_2;
|
375 |
|
|
end
|
376 |
|
|
else
|
377 |
|
|
begin
|
378 |
|
|
osd_pixel_3 <= osd_pixel_3;
|
379 |
|
|
y_pixel_3 <= y_pixel_3;
|
380 |
|
|
u_upper_sum_3 <= u_upper_sum_3;
|
381 |
|
|
u_lower_sum_3 <= u_lower_sum_3;
|
382 |
|
|
v_upper_sum_3 <= v_upper_sum_3;
|
383 |
|
|
v_lower_sum_3 <= v_lower_sum_3;
|
384 |
|
|
position_3 <= position_3;
|
385 |
|
|
pixel_wr_en_3 <= pixel_wr_en_3;
|
386 |
|
|
end
|
387 |
|
|
|
388 |
|
|
/* stage 4 */
|
389 |
|
|
reg [7:0]osd_pixel_4;
|
390 |
|
|
reg signed [7:0]y_pixel_4;
|
391 |
|
|
reg signed [11:0]u_pixel_4;
|
392 |
|
|
reg signed [11:0]v_pixel_4;
|
393 |
|
|
reg [2:0]position_4;
|
394 |
|
|
reg pixel_wr_en_4;
|
395 |
|
|
|
396 |
|
|
always @(posedge clk)
|
397 |
|
|
if (~rst)
|
398 |
|
|
begin
|
399 |
|
|
osd_pixel_4 <= 8'b0;
|
400 |
|
|
y_pixel_4 <= 8'b0;
|
401 |
|
|
u_pixel_4 <= 12'sd0;
|
402 |
|
|
v_pixel_4 <= 12'sd0;
|
403 |
|
|
position_4 <= 3'b0;
|
404 |
|
|
pixel_wr_en_4 <= 1'b0;
|
405 |
|
|
end
|
406 |
|
|
else if (clk_en)
|
407 |
|
|
begin
|
408 |
|
|
osd_pixel_4 <= osd_pixel_3;
|
409 |
|
|
y_pixel_4 <= y_pixel_3;
|
410 |
|
|
u_pixel_4 <= (u_upper_sum_3 + u_lower_sum_3 + 12'sd7) >>> 3;
|
411 |
|
|
v_pixel_4 <= (v_upper_sum_3 + v_lower_sum_3 + 12'sd7) >>> 3;
|
412 |
|
|
position_4 <= position_3;
|
413 |
|
|
pixel_wr_en_4 <= pixel_wr_en_3;
|
414 |
|
|
end
|
415 |
|
|
else
|
416 |
|
|
begin
|
417 |
|
|
osd_pixel_4 <= osd_pixel_4;
|
418 |
|
|
y_pixel_4 <= y_pixel_4;
|
419 |
|
|
u_pixel_4 <= u_pixel_4;
|
420 |
|
|
v_pixel_4 <= v_pixel_4;
|
421 |
|
|
position_4 <= position_4;
|
422 |
|
|
pixel_wr_en_4 <= pixel_wr_en_4;
|
423 |
|
|
end
|
424 |
|
|
|
425 |
|
|
/* stage 5, clip to -128..127 */
|
426 |
|
|
reg [7:0]osd_pixel_5;
|
427 |
|
|
reg signed [7:0]y_pixel_5;
|
428 |
|
|
reg signed [7:0]u_pixel_5;
|
429 |
|
|
reg signed [7:0]v_pixel_5;
|
430 |
|
|
reg [2:0]position_5;
|
431 |
|
|
reg pixel_wr_en_5;
|
432 |
|
|
|
433 |
|
|
always @(posedge clk)
|
434 |
|
|
if (~rst)
|
435 |
|
|
begin
|
436 |
|
|
osd_pixel_5 <= 8'b0;
|
437 |
|
|
y_pixel_5 <= 8'sd0;
|
438 |
|
|
u_pixel_5 <= 8'sd0;
|
439 |
|
|
v_pixel_5 <= 8'sd0;
|
440 |
|
|
position_5 <= 3'b0;
|
441 |
|
|
pixel_wr_en_5 <= 1'b0;
|
442 |
|
|
end
|
443 |
|
|
else if (clk_en)
|
444 |
|
|
begin
|
445 |
|
|
osd_pixel_5 <= osd_pixel_4;
|
446 |
|
|
y_pixel_5 <= y_pixel_4;
|
447 |
|
|
if ((u_pixel_4[11:8] == 4'b0000) || (u_pixel_4[11:8] == 4'b1111)) u_pixel_5 <= u_pixel_4[7:0];
|
448 |
|
|
else u_pixel_5 <= {u_pixel_4[11], {7{~u_pixel_4[11]}}};
|
449 |
|
|
if ((v_pixel_4[11:8] == 4'b0000) || (v_pixel_4[11:8] == 4'b1111)) v_pixel_5 <= v_pixel_4[7:0];
|
450 |
|
|
else v_pixel_5 <= {v_pixel_4[11], {7{~v_pixel_4[11]}}};
|
451 |
|
|
position_5 <= position_4;
|
452 |
|
|
pixel_wr_en_5 <= pixel_wr_en_4;
|
453 |
|
|
end
|
454 |
|
|
else
|
455 |
|
|
begin
|
456 |
|
|
osd_pixel_5 <= osd_pixel_5;
|
457 |
|
|
y_pixel_5 <= y_pixel_5;
|
458 |
|
|
u_pixel_5 <= u_pixel_5;
|
459 |
|
|
v_pixel_5 <= v_pixel_5;
|
460 |
|
|
position_5 <= position_5;
|
461 |
|
|
pixel_wr_en_5 <= pixel_wr_en_5;
|
462 |
|
|
end
|
463 |
|
|
|
464 |
|
|
/* stage 6, add offset of 128 to convert range to 0..255 and output */
|
465 |
|
|
|
466 |
|
|
always @(posedge clk)
|
467 |
|
|
if (~rst)
|
468 |
|
|
begin
|
469 |
|
|
osd_out <= 8'b0;
|
470 |
|
|
y <= 8'b0;
|
471 |
|
|
u <= 8'b0;
|
472 |
|
|
v <= 8'b0;
|
473 |
|
|
position_out <= 3'b0;
|
474 |
|
|
pixel_wr_en <= 1'b0;
|
475 |
|
|
end
|
476 |
|
|
else if (clk_en)
|
477 |
|
|
begin
|
478 |
|
|
osd_out <= osd_pixel_5;
|
479 |
|
|
y <= y_pixel_5 + 8'd128;
|
480 |
|
|
u <= u_pixel_5 + 8'd128;
|
481 |
|
|
v <= v_pixel_5 + 8'd128;
|
482 |
|
|
position_out <= position_5;
|
483 |
|
|
pixel_wr_en <= pixel_wr_en_5;
|
484 |
|
|
end
|
485 |
|
|
else
|
486 |
|
|
begin
|
487 |
|
|
osd_out <= osd_out;
|
488 |
|
|
y <= y;
|
489 |
|
|
u <= u;
|
490 |
|
|
v <= v;
|
491 |
|
|
position_out <= position_out;
|
492 |
|
|
pixel_wr_en <= pixel_wr_en;
|
493 |
|
|
end
|
494 |
|
|
|
495 |
|
|
`ifdef DEBUG
|
496 |
|
|
always @(posedge clk)
|
497 |
|
|
case (state)
|
498 |
|
|
STATE_INIT: #0 $display("%m STATE_INIT");
|
499 |
|
|
STATE_MACROBLOCK: #0 $display("%m STATE_MACROBLOCK");
|
500 |
|
|
STATE_PIXEL: #0 $display("%m STATE_PIXEL");
|
501 |
|
|
default #0 $display("%m *** Error: unknown state %d", state);
|
502 |
|
|
endcase
|
503 |
|
|
|
504 |
|
|
always @(posedge clk)
|
505 |
|
|
$strobe("%m\tloop: %18b", loop);
|
506 |
|
|
|
507 |
|
|
always @(posedge clk)
|
508 |
|
|
begin
|
509 |
|
|
$strobe("%m\tosd_0: %32h y_0: %32h u_upper_0: %16h u_lower_0: %16h v_upper_0: %16h v_lower_0: %16h position_0: %d fifo_valid: %d", osd_0, y_0, u_upper_0, u_lower_0, v_upper_0, v_lower_0, position_0, fifo_valid);
|
510 |
|
|
$strobe("%m\tosd_1: %32h y_1: %32h u_upper_1: %34h u_lower_1: %34h v_upper_1: %34h v_lower_1: %34h position_1: %d pixel_wr_en_1: %d", osd_1, y_1, u_upper_1, u_lower_1, v_upper_1, v_lower_1, position_1, pixel_wr_en_1);
|
511 |
|
|
$strobe("%m\tosd_pixel_2: %h y_pixel_2: %h u_upper_sum_2: %h u_lower_sum_2: %h v_upper_sum_2: %h v_lower_sum_2: %h position_2: %d pixel_wr_en_2: %d", osd_pixel_2, y_pixel_2, u_upper_sum_2, u_lower_sum_2, v_upper_sum_2, v_lower_sum_2, position_2, pixel_wr_en_2);
|
512 |
|
|
$strobe("%m\tosd_pixel_3: %h y_pixel_3: %h u_upper_sum_3: %h u_lower_sum_3: %h v_upper_sum_3: %h v_lower_sum_3: %h position_3: %d pixel_wr_en_3: %d", osd_pixel_3, y_pixel_3, u_upper_sum_3, u_lower_sum_3, v_upper_sum_3, v_lower_sum_3, position_3, pixel_wr_en_3);
|
513 |
|
|
$strobe("%m\tosd_pixel_4: %h y_pixel_4: %h u_pixel_4: %h v_pixel_4: %h position_4: %d pixel_wr_en_4: %d", osd_pixel_4, y_pixel_4, u_pixel_4, v_pixel_4, position_4, pixel_wr_en_4);
|
514 |
|
|
$strobe("%m\tosd_pixel_5: %h y_pixel_5: %h u_pixel_5: %h v_pixel_5: %h position_5: %d pixel_wr_en_5: %d", osd_pixel_5, y_pixel_5, u_pixel_5, v_pixel_5, position_5, pixel_wr_en_5);
|
515 |
|
|
$strobe("%m\tosd_out: %h y: %h u: %h v: %h position_out: %d pixel_wr_en: %d", osd_out, y, u, v, position_out, pixel_wr_en);
|
516 |
|
|
end
|
517 |
|
|
|
518 |
|
|
`endif
|
519 |
|
|
|
520 |
|
|
`ifdef STOP_IF_UNDEFINED_PIXEL
|
521 |
|
|
/*
|
522 |
|
|
Note not all undefined pixels indicate a decoder error;
|
523 |
|
|
if a stream begins with a P or B image pixels may be undefined as well.
|
524 |
|
|
*/
|
525 |
|
|
always @(posedge clk)
|
526 |
|
|
if (pixel_wr_en && ((^y === 1'bx) || (^u === 1'bx) || (^v === 1'bx)))
|
527 |
|
|
begin
|
528 |
|
|
$finish;
|
529 |
|
|
end
|
530 |
|
|
`endif
|
531 |
|
|
|
532 |
|
|
endmodule
|
533 |
|
|
/* not truncated */
|