1 |
2 |
kdv |
/*
|
2 |
|
|
* motcomp_addrgen.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 |
|
|
`include "timescale.v"
|
20 |
|
|
|
21 |
|
|
`undef DEBUG
|
22 |
|
|
//`define DEBUG 1
|
23 |
|
|
|
24 |
|
|
/*
|
25 |
|
|
* motcomp_addrgen - Motion compensation address generator. Handles 4:2:0 only.
|
26 |
|
|
*/
|
27 |
|
|
|
28 |
|
|
/*
|
29 |
|
|
par. 7.6.4, Forming Predictions:
|
30 |
|
|
A positive value of the horizontal component of a motion vector indicates that the prediction is made from samples (in the reference field/frame) that lie to the right of the samples being predicted.
|
31 |
|
|
A positive value of the vertical component of a motion vector indicates that the prediction is made from samples (in the reference field/frame) that lie below the samples being predicted.
|
32 |
|
|
All motion vectors are specified to an accuracy of one half sample.
|
33 |
|
|
Thus, if a component of the motion vector is odd, the samples will be read from mid-way between the actual samples in the reference field/frame.
|
34 |
|
|
These half-samples are calculated by simple linear interpolation from the actual samples.
|
35 |
|
|
*/
|
36 |
|
|
|
37 |
|
|
module motcomp_addrgen(
|
38 |
|
|
clk, clk_en, rst,
|
39 |
|
|
mvec_rd_en, mvec_rd_valid,
|
40 |
|
|
picture_coding_type, picture_structure, motion_type, dct_type,
|
41 |
|
|
macroblock_address, macroblock_motion_forward, macroblock_motion_backward, macroblock_intra,
|
42 |
|
|
mb_width, mb_height, horizontal_size, vertical_size, chroma_format,
|
43 |
|
|
pmv_0_0_0, pmv_0_0_1, pmv_1_0_0, pmv_1_0_1, pmv_0_1_0, pmv_0_1_1, pmv_1_1_0, pmv_1_1_1,
|
44 |
|
|
dmv_0_0, dmv_0_1, dmv_1_0, dmv_1_1,
|
45 |
|
|
motion_vert_field_select_0_0, motion_vert_field_select_0_1, motion_vert_field_select_1_0, motion_vert_field_select_1_1,
|
46 |
|
|
second_field, progressive_sequence, progressive_frame, top_field_first, repeat_first_field, last_frame, update_picture_buffers, motion_vector_valid,
|
47 |
|
|
source_select,
|
48 |
|
|
fwd_wr_addr_en, fwd_wr_addr, fwd_wr_addr_almost_full,
|
49 |
|
|
bwd_wr_addr_en, bwd_wr_addr, bwd_wr_addr_almost_full,
|
50 |
|
|
dst_wr_en, dst_wr_write_recon, dst_wr_write_address, dst_wr_almost_full,
|
51 |
|
|
dst_wr_motion_forward, dst_wr_fwd_hor_offset, dst_wr_fwd_hor_halfpixel, dst_wr_fwd_ver_halfpixel,
|
52 |
|
|
dst_wr_motion_backward, dst_wr_bwd_hor_offset, dst_wr_bwd_hor_halfpixel, dst_wr_bwd_ver_halfpixel,
|
53 |
|
|
output_frame, output_frame_valid, output_frame_rd, output_progressive_sequence, output_progressive_frame, output_top_field_first, output_repeat_first_field, picbuf_busy,
|
54 |
|
|
dct_block_cmd, dct_block_en, dct_block_wr_almost_full
|
55 |
|
|
);
|
56 |
|
|
|
57 |
|
|
`include "motcomp_dctcodes.v"
|
58 |
|
|
|
59 |
|
|
input clk; // clock
|
60 |
|
|
input clk_en; // clock enable
|
61 |
|
|
input rst; // synchronous active low reset
|
62 |
|
|
output reg mvec_rd_en; // motion vector fifo read enable
|
63 |
|
|
input mvec_rd_valid; // motion vector fifo read valid
|
64 |
|
|
|
65 |
|
|
input [2:0]picture_coding_type; // identifies whether a picture is an I, P or B picture.
|
66 |
|
|
input [1:0]picture_structure; // one of FRAME_PICTURE, TOP_FIELD or BOTTOM_FIELD
|
67 |
|
|
input [1:0]motion_type; // one of MC_FIELD, MC_FRAME, MC_16X8 or MC_DMV
|
68 |
|
|
input dct_type; // dct_type == 1 : field dct coded; dct_type == 0 : frame dct coded
|
69 |
|
|
input [12:0]macroblock_address; // absolute position of the current macroblock. top-left macroblock has macroblock_address zero.
|
70 |
|
|
input macroblock_motion_forward;
|
71 |
|
|
input macroblock_motion_backward;
|
72 |
|
|
input macroblock_intra;
|
73 |
|
|
input [7:0]mb_width; // par. 6.3.3. width of the encoded luminance component of pictures in macroblocks
|
74 |
|
|
input [7:0]mb_height; // par. 6.3.3. height of the encoded luminance component of frame pictures in macroblocks
|
75 |
|
|
input [13:0]horizontal_size; // par. 6.2.2.1, par. 6.3.3
|
76 |
|
|
input [13:0]vertical_size; // par. 6.2.2.1, par. 6.3.3
|
77 |
|
|
input [1:0]chroma_format;
|
78 |
|
|
input motion_vert_field_select_0_0; // motion_vertical_field_select. Indicates which reference field shall be used to form the prediction.
|
79 |
|
|
// If motion_vertical_field_select[r][s] is zero, then the top reference field shall be used,
|
80 |
|
|
// if it is one then the bottom reference field shall be used.
|
81 |
|
|
input motion_vert_field_select_0_1;
|
82 |
|
|
input motion_vert_field_select_1_0;
|
83 |
|
|
input motion_vert_field_select_1_1;
|
84 |
|
|
input second_field;
|
85 |
|
|
input signed [12:0]pmv_0_0_0; // predicted motion vector
|
86 |
|
|
input signed [12:0]pmv_0_0_1; // predicted motion vector
|
87 |
|
|
input signed [12:0]pmv_1_0_0; // predicted motion vector
|
88 |
|
|
input signed [12:0]pmv_1_0_1; // predicted motion vector
|
89 |
|
|
input signed [12:0]pmv_0_1_0; // predicted motion vector
|
90 |
|
|
input signed [12:0]pmv_0_1_1; // predicted motion vector
|
91 |
|
|
input signed [12:0]pmv_1_1_0; // predicted motion vector
|
92 |
|
|
input signed [12:0]pmv_1_1_1; // predicted motion vector
|
93 |
|
|
input signed [12:0]dmv_0_0; // dual-prime motion vector.
|
94 |
|
|
input signed [12:0]dmv_0_1; // dual-prime motion vector.
|
95 |
|
|
input signed [12:0]dmv_1_0; // dual-prime motion vector.
|
96 |
|
|
input signed [12:0]dmv_1_1; // dual-prime motion vector.
|
97 |
|
|
input progressive_sequence;
|
98 |
|
|
input progressive_frame;
|
99 |
|
|
input top_field_first;
|
100 |
|
|
input repeat_first_field;
|
101 |
|
|
|
102 |
|
|
input last_frame;
|
103 |
|
|
input update_picture_buffers;
|
104 |
|
|
input motion_vector_valid;
|
105 |
|
|
/* trick modes */
|
106 |
|
|
input [2:0]source_select; /* select video out source */
|
107 |
|
|
|
108 |
|
|
`include "mem_codes.v"
|
109 |
|
|
`include "vld_codes.v"
|
110 |
|
|
|
111 |
|
|
/* picture buffers */
|
112 |
|
|
reg do_update_picture_buffers;
|
113 |
|
|
wire [2:0]forward_reference_frame; /* forward reference frame. Has value 2'd0 or 2'd1 */
|
114 |
|
|
wire [2:0]backward_reference_frame; /* backward reference frame. Has value 2'd0 or 2'd1 */
|
115 |
|
|
wire [2:0]current_frame; /* current frame */
|
116 |
|
|
output [2:0]output_frame; /* frame to be displayed */
|
117 |
|
|
output output_frame_valid; /* asserted when output_frame valid */
|
118 |
|
|
input output_frame_rd; /* asserted to read next output_frame */
|
119 |
|
|
output output_progressive_sequence;
|
120 |
|
|
output output_progressive_frame;
|
121 |
|
|
output output_top_field_first;
|
122 |
|
|
output output_repeat_first_field;
|
123 |
|
|
output picbuf_busy;
|
124 |
|
|
|
125 |
|
|
/* reading forward reference frame: writing address */
|
126 |
|
|
input fwd_wr_addr_almost_full;
|
127 |
|
|
output fwd_wr_addr_en;
|
128 |
|
|
output [21:0]fwd_wr_addr;
|
129 |
|
|
|
130 |
|
|
/* reading backward reference frame: writing address */
|
131 |
|
|
input bwd_wr_addr_almost_full;
|
132 |
|
|
output bwd_wr_addr_en;
|
133 |
|
|
output [21:0]bwd_wr_addr;
|
134 |
|
|
|
135 |
|
|
/* writing block reconstruction fifo */
|
136 |
|
|
input dst_wr_almost_full;
|
137 |
|
|
output dst_wr_en;
|
138 |
|
|
output dst_wr_write_recon;
|
139 |
|
|
output [21:0]dst_wr_write_address;
|
140 |
|
|
output dst_wr_motion_forward;
|
141 |
|
|
output [2:0]dst_wr_fwd_hor_offset;
|
142 |
|
|
output dst_wr_fwd_hor_halfpixel;
|
143 |
|
|
output dst_wr_fwd_ver_halfpixel;
|
144 |
|
|
output dst_wr_motion_backward;
|
145 |
|
|
output [2:0]dst_wr_bwd_hor_offset;
|
146 |
|
|
output dst_wr_bwd_hor_halfpixel;
|
147 |
|
|
output dst_wr_bwd_ver_halfpixel;
|
148 |
|
|
|
149 |
|
|
/* field/frame dct decoding */
|
150 |
|
|
input dct_block_wr_almost_full;
|
151 |
|
|
output [2:0]dct_block_cmd;
|
152 |
|
|
output dct_block_en;
|
153 |
|
|
|
154 |
|
|
/* motvec output */
|
155 |
|
|
wire frame_picture_0;
|
156 |
|
|
wire field_in_frame_0;
|
157 |
|
|
wire [12:0]macroblock_address_0;
|
158 |
|
|
wire [1:0]comp_0;
|
159 |
|
|
wire signed [12:0]delta_x_0;
|
160 |
|
|
wire signed [12:0]delta_y_0;
|
161 |
|
|
wire [2:0]fwd_src_frame_0;
|
162 |
|
|
wire fwd_src_field_0;
|
163 |
|
|
wire signed [12:0]fwd_mv_x_0;
|
164 |
|
|
wire signed [12:0]fwd_mv_y_0;
|
165 |
|
|
wire fwd_valid_0;
|
166 |
|
|
wire [2:0]bwd_src_frame_0;
|
167 |
|
|
wire bwd_src_field_0;
|
168 |
|
|
wire signed [12:0]bwd_mv_x_0;
|
169 |
|
|
wire signed [12:0]bwd_mv_y_0;
|
170 |
|
|
wire bwd_valid_0;
|
171 |
|
|
wire [2:0]recon_dst_frame_0;
|
172 |
|
|
wire recon_dst_field_0;
|
173 |
|
|
wire signed [12:0]recon_delta_x_0;
|
174 |
|
|
wire signed [12:0]recon_delta_y_0;
|
175 |
|
|
wire write_recon_0;
|
176 |
|
|
wire recon_valid_0;
|
177 |
|
|
|
178 |
|
|
/* ripple counter */
|
179 |
|
|
reg column;
|
180 |
|
|
reg signed [3:0]row;
|
181 |
|
|
reg signed [3:0]last_row;
|
182 |
|
|
reg [1:0]block;
|
183 |
|
|
reg [1:0]comp; /* COMP_Y, COMP_CR or COMP_CB */
|
184 |
|
|
reg mb_end;
|
185 |
|
|
reg motvec_update;
|
186 |
|
|
reg next_column;
|
187 |
|
|
reg signed [3:0]next_row;
|
188 |
|
|
reg [1:0]next_block;
|
189 |
|
|
reg [1:0]next_comp;
|
190 |
|
|
reg next_mb_end;
|
191 |
|
|
|
192 |
|
|
/* basic motion compensation state machine */
|
193 |
|
|
|
194 |
|
|
parameter [2:0]
|
195 |
|
|
STATE_INIT = 4'h0,
|
196 |
|
|
STATE_READ = 4'h1,
|
197 |
|
|
STATE_UPDATE = 4'h2,
|
198 |
|
|
STATE_MOTVEC = 4'h3,
|
199 |
|
|
STATE_NEXT = 4'h4;
|
200 |
|
|
|
201 |
|
|
reg [2:0]state;
|
202 |
|
|
reg [2:0]next;
|
203 |
|
|
|
204 |
|
|
/* next state logic */
|
205 |
|
|
always @*
|
206 |
|
|
case (state)
|
207 |
|
|
STATE_INIT: if (~mvec_rd_valid || fwd_wr_addr_almost_full || bwd_wr_addr_almost_full || dst_wr_almost_full || dct_block_wr_almost_full) next = STATE_INIT; // wait until mvec_rd_valid
|
208 |
|
|
else next = STATE_READ;
|
209 |
|
|
|
210 |
|
|
STATE_READ: if (mvec_rd_valid && update_picture_buffers) next = STATE_UPDATE; // update picture buffers
|
211 |
|
|
else if (mvec_rd_valid && motion_vector_valid) next = STATE_MOTVEC; // motion vector valid: process macroblock
|
212 |
|
|
else next = STATE_INIT;
|
213 |
|
|
|
214 |
|
|
STATE_MOTVEC: if (mb_end) next = STATE_NEXT;
|
215 |
|
|
else next = STATE_MOTVEC; // reconstruct pixels from predictions
|
216 |
|
|
|
217 |
|
|
STATE_UPDATE: next = STATE_NEXT; // perform picture buffer update
|
218 |
|
|
|
219 |
|
|
STATE_NEXT: next = STATE_INIT; // wait for clk_en;
|
220 |
|
|
|
221 |
|
|
default next = STATE_INIT;
|
222 |
|
|
|
223 |
|
|
endcase
|
224 |
|
|
|
225 |
|
|
/* state */
|
226 |
|
|
always @(posedge clk)
|
227 |
|
|
if(~rst) state <= STATE_INIT;
|
228 |
|
|
else if (clk_en) state <= next;
|
229 |
|
|
else state <= state;
|
230 |
|
|
|
231 |
|
|
always @(posedge clk)
|
232 |
|
|
if (~rst) mvec_rd_en <= 1'b0;
|
233 |
|
|
else if (clk_en && (state == STATE_NEXT)) mvec_rd_en <= 1'b1;
|
234 |
|
|
else if (clk_en) mvec_rd_en <= 1'b0;
|
235 |
|
|
else mvec_rd_en <= 1'b0;
|
236 |
|
|
|
237 |
|
|
always @(posedge clk)
|
238 |
|
|
if(~rst) motvec_update <= 1'b0;
|
239 |
|
|
else if (clk_en) motvec_update <= (next == STATE_MOTVEC);
|
240 |
|
|
else motvec_update <= motvec_update;
|
241 |
|
|
|
242 |
|
|
/*
|
243 |
|
|
This represents a "ripple counter" which cycles through all possible component/block/row/column combinations.
|
244 |
|
|
|
245 |
|
|
4:2:0
|
246 |
|
|
Component Block Row Column
|
247 |
|
|
Y 0..3 -1..7 0..1
|
248 |
|
|
Cr 0..1 -1..3 0..1
|
249 |
|
|
Cb 0..1 -1..3 0..1
|
250 |
|
|
|
251 |
|
|
Luminance is reconstructed in blocks of 8x8 pixels.
|
252 |
|
|
|
253 |
|
|
For horizontal halfpixel calculations, we need the pixel to the right of the current pixel.
|
254 |
|
|
For vertical halfpixel calculations, we need the pixel below the current pixel.
|
255 |
|
|
Hence, for reconstructing a 8x8 pixel block we need 9x9 pixels.
|
256 |
|
|
As we retrieve pixels from memory 8 at a time, this means we need to retrieve 9x16 pixels from memory.
|
257 |
|
|
|
258 |
|
|
| column 0 | column 1
|
259 |
|
|
-------|------------------------+------------------------
|
260 |
|
|
row -1| 0 1 2 3 4 5 6 7 | 0 1 2 3 4 5 6 7 dst_wr_write_recon <= 1'b0. block: 0..3
|
261 |
|
|
row 0 | 0 1 2 3 4 5 6 7 | 0 1 2 3 4 5 6 7 dst_wr_write_recon <= 1'b1.
|
262 |
|
|
row 1 | 0 1 2 3 4 5 6 7 | 0 1 2 3 4 5 6 7 dst_wr_write_recon <= 1'b1.
|
263 |
|
|
row 2 | 0 1 2 3 4 5 6 7 | 0 1 2 3 4 5 6 7 dst_wr_write_recon <= 1'b1.
|
264 |
|
|
row 3 | 0 1 2 3 4 5 6 7 | 0 1 2 3 4 5 6 7 dst_wr_write_recon <= 1'b1.
|
265 |
|
|
row 4 | 0 1 2 3 4 5 6 7 | 0 1 2 3 4 5 6 7 dst_wr_write_recon <= 1'b1.
|
266 |
|
|
row 5 | 0 1 2 3 4 5 6 7 | 0 1 2 3 4 5 6 7 dst_wr_write_recon <= 1'b1.
|
267 |
|
|
row 6 | 0 1 2 3 4 5 6 7 | 0 1 2 3 4 5 6 7 dst_wr_write_recon <= 1'b1.
|
268 |
|
|
row 7 | 0 1 2 3 4 5 6 7 | 0 1 2 3 4 5 6 7 dst_wr_write_recon <= 1'b1.
|
269 |
|
|
-------|------------------------+------------------------
|
270 |
|
|
|
271 |
|
|
The first row (16 pixels) is sent to motcomp_recon with dst_wr_write_recon <= 1'b0;
|
272 |
|
|
causing recon to just load the row but not to write any reconstructed pixels to memory.
|
273 |
|
|
The remaining 8 rows are sent to motcomp_recon with dst_wr_write_recon <= 1'b1.
|
274 |
|
|
This causes recon not only to load the row, but also to write the reconstructed pixels to memory.
|
275 |
|
|
|
276 |
|
|
For chrominance, reconstruction happens in "blocks" of 8x4 pixels.
|
277 |
|
|
|
278 |
|
|
| column 0 | column 1
|
279 |
|
|
-------|------------------------+------------------------
|
280 |
|
|
row -1| 0 1 2 3 4 5 6 7 | 0 1 2 3 4 5 6 7 dst_wr_write_recon <= 1'b0. block: 0..1
|
281 |
|
|
row 0 | 0 1 2 3 4 5 6 7 | 0 1 2 3 4 5 6 7 dst_wr_write_recon <= 1'b1.
|
282 |
|
|
row 1 | 0 1 2 3 4 5 6 7 | 0 1 2 3 4 5 6 7 dst_wr_write_recon <= 1'b1.
|
283 |
|
|
row 2 | 0 1 2 3 4 5 6 7 | 0 1 2 3 4 5 6 7 dst_wr_write_recon <= 1'b1.
|
284 |
|
|
row 3 | 0 1 2 3 4 5 6 7 | 0 1 2 3 4 5 6 7 dst_wr_write_recon <= 1'b1.
|
285 |
|
|
-------|------------------------+------------------------
|
286 |
|
|
*/
|
287 |
|
|
|
288 |
|
|
always @(posedge clk)
|
289 |
|
|
if (~rst) last_row <= 4'd0;
|
290 |
|
|
else if (clk_en && (state == STATE_INIT)) last_row <= 4'sd7;
|
291 |
|
|
else if (clk_en && (state == STATE_MOTVEC) && (comp == COMP_Y)) last_row <= 4'sd7;
|
292 |
|
|
else if (clk_en && (state == STATE_MOTVEC)) last_row <= 4'sd3;
|
293 |
|
|
else last_row <= last_row;
|
294 |
|
|
|
295 |
|
|
always @*
|
296 |
|
|
next_column = ~column;
|
297 |
|
|
|
298 |
|
|
always @*
|
299 |
|
|
if ((row == last_row) && (column == 1'd1)) next_row = -4'sd1;
|
300 |
|
|
else if (column == 1'd1) next_row = row + 4'sd1;
|
301 |
|
|
else next_row = row;
|
302 |
|
|
|
303 |
|
|
always @*
|
304 |
|
|
if ((row == last_row) && (column == 1'd1) && (comp == COMP_Y)) next_block = block + 2'd1; // COMP_Y: 0 1 2 3 0
|
305 |
|
|
else if ((row == last_row) && (column == 1'd1) && (block == 2'd0)) next_block = block + 2'd1; // COMP_CR/CB: 0 1 0
|
306 |
|
|
else if ((row == last_row) && (column == 1'd1)) next_block = 2'd0;
|
307 |
|
|
else next_block = block;
|
308 |
|
|
|
309 |
|
|
always @*
|
310 |
|
|
if ((row == last_row) && (column == 1'd1))
|
311 |
|
|
case (comp)
|
312 |
|
|
COMP_Y: if (block == 2'd3) next_comp = COMP_CR;
|
313 |
|
|
else next_comp = COMP_Y;
|
314 |
|
|
COMP_CR: if (block == 2'd1) next_comp = COMP_CB;
|
315 |
|
|
else next_comp = COMP_CR;
|
316 |
|
|
COMP_CB: if (block == 2'd1) next_comp = COMP_Y;
|
317 |
|
|
else next_comp = COMP_CB;
|
318 |
|
|
default next_comp = COMP_Y;
|
319 |
|
|
endcase
|
320 |
|
|
else next_comp = comp;
|
321 |
|
|
|
322 |
|
|
always @*
|
323 |
|
|
if ((block == 2'd1) && (row == last_row) && (column == 1'd0) && (next_comp == COMP_CB)) next_mb_end = 1'b1;
|
324 |
|
|
else next_mb_end = 1'b0;
|
325 |
|
|
|
326 |
|
|
always @(posedge clk)
|
327 |
|
|
if (~rst) column <= 1'b0;
|
328 |
|
|
else if (clk_en && (state == STATE_INIT)) column <= 1'b0;
|
329 |
|
|
else if (clk_en && (state == STATE_MOTVEC)) column <= next_column;
|
330 |
|
|
else column <= column;
|
331 |
|
|
|
332 |
|
|
always @(posedge clk)
|
333 |
|
|
if (~rst) row <= -4'sd1;
|
334 |
|
|
else if (clk_en && (state == STATE_INIT)) row <= -4'sd1;
|
335 |
|
|
else if (clk_en && (state == STATE_MOTVEC)) row <= next_row;
|
336 |
|
|
else row <= row;
|
337 |
|
|
|
338 |
|
|
always @(posedge clk)
|
339 |
|
|
if (~rst) block <= 2'b0;
|
340 |
|
|
else if (clk_en && (state == STATE_INIT)) block <= 2'b0;
|
341 |
|
|
else if (clk_en && (state == STATE_MOTVEC)) block <= next_block;
|
342 |
|
|
else block <= block;
|
343 |
|
|
|
344 |
|
|
always @(posedge clk)
|
345 |
|
|
if (~rst) comp <= COMP_Y;
|
346 |
|
|
else if (clk_en && (state == STATE_INIT)) comp <= COMP_Y;
|
347 |
|
|
else if (clk_en && (state == STATE_MOTVEC)) comp <= next_comp;
|
348 |
|
|
else comp <= comp;
|
349 |
|
|
|
350 |
|
|
always @(posedge clk)
|
351 |
|
|
if (~rst) mb_end <= 1'b0;
|
352 |
|
|
else if (clk_en && (state == STATE_INIT)) mb_end <= 1'b0;
|
353 |
|
|
else if (clk_en && (state == STATE_MOTVEC)) mb_end <= next_mb_end;
|
354 |
|
|
else mb_end <= mb_end;
|
355 |
|
|
|
356 |
|
|
/* picture buffers */
|
357 |
|
|
always @(posedge clk)
|
358 |
|
|
if (~rst) do_update_picture_buffers <= 1'b0;
|
359 |
|
|
else if (clk_en) do_update_picture_buffers <= (next == STATE_UPDATE);
|
360 |
|
|
else do_update_picture_buffers <= do_update_picture_buffers;
|
361 |
|
|
|
362 |
|
|
motcomp_picbuf picbuf (
|
363 |
|
|
.clk(clk),
|
364 |
|
|
.clk_en(clk_en),
|
365 |
|
|
.rst(rst),
|
366 |
|
|
.source_select(source_select), // from regfile
|
367 |
|
|
.picture_coding_type(picture_coding_type),
|
368 |
|
|
.progressive_sequence(progressive_sequence), // from vld
|
369 |
|
|
.progressive_frame(progressive_frame), // from vld
|
370 |
|
|
.top_field_first(top_field_first), // from vld
|
371 |
|
|
.repeat_first_field(repeat_first_field), // from vld
|
372 |
|
|
.last_frame(last_frame),
|
373 |
|
|
.update_picture_buffers(do_update_picture_buffers),
|
374 |
|
|
.forward_reference_frame(forward_reference_frame),
|
375 |
|
|
.backward_reference_frame(backward_reference_frame),
|
376 |
|
|
.current_frame(current_frame),
|
377 |
|
|
.output_frame(output_frame),
|
378 |
|
|
.output_frame_valid(output_frame_valid),
|
379 |
|
|
.output_frame_rd(output_frame_rd),
|
380 |
|
|
.output_progressive_sequence(output_progressive_sequence),// to resample
|
381 |
|
|
.output_progressive_frame(output_progressive_frame), // to resample
|
382 |
|
|
.output_top_field_first(output_top_field_first), // to resample
|
383 |
|
|
.output_repeat_first_field(output_repeat_first_field), // to resample
|
384 |
|
|
.picbuf_busy(picbuf_busy)
|
385 |
|
|
);
|
386 |
|
|
|
387 |
|
|
/* motion vector selection */
|
388 |
|
|
/*
|
389 |
|
|
Note motion vector is not constant for a macroblock.
|
390 |
|
|
Some motion types have different motion vectors for the upper two blocks and the lower two blocks.
|
391 |
|
|
*/
|
392 |
|
|
motcomp_motvec motvec (
|
393 |
|
|
.clk(clk),
|
394 |
|
|
.clk_en(clk_en),
|
395 |
|
|
.rst(rst),
|
396 |
|
|
/* in */
|
397 |
|
|
.picture_coding_type(picture_coding_type),
|
398 |
|
|
.picture_structure(picture_structure),
|
399 |
|
|
.motion_type(motion_type),
|
400 |
|
|
.dct_type(dct_type),
|
401 |
|
|
.macroblock_motion_forward(macroblock_motion_forward),
|
402 |
|
|
.macroblock_motion_backward(macroblock_motion_backward),
|
403 |
|
|
.macroblock_intra(macroblock_intra),
|
404 |
|
|
.macroblock_address_in(macroblock_address),
|
405 |
|
|
.pmv_0_0_0(pmv_0_0_0),
|
406 |
|
|
.pmv_0_0_1(pmv_0_0_1),
|
407 |
|
|
.pmv_1_0_0(pmv_1_0_0),
|
408 |
|
|
.pmv_1_0_1(pmv_1_0_1),
|
409 |
|
|
.pmv_0_1_0(pmv_0_1_0),
|
410 |
|
|
.pmv_0_1_1(pmv_0_1_1),
|
411 |
|
|
.pmv_1_1_0(pmv_1_1_0),
|
412 |
|
|
.pmv_1_1_1(pmv_1_1_1),
|
413 |
|
|
.dmv_0_0(dmv_0_0),
|
414 |
|
|
.dmv_0_1(dmv_0_1),
|
415 |
|
|
.dmv_1_0(dmv_1_0),
|
416 |
|
|
.dmv_1_1(dmv_1_1),
|
417 |
|
|
.motion_vert_field_select_0_0(motion_vert_field_select_0_0),
|
418 |
|
|
.motion_vert_field_select_0_1(motion_vert_field_select_0_1),
|
419 |
|
|
.motion_vert_field_select_1_0(motion_vert_field_select_1_0),
|
420 |
|
|
.motion_vert_field_select_1_1(motion_vert_field_select_1_1),
|
421 |
|
|
.second_field(second_field),
|
422 |
|
|
.forward_reference_frame(forward_reference_frame),
|
423 |
|
|
.backward_reference_frame(backward_reference_frame),
|
424 |
|
|
.current_frame(current_frame),
|
425 |
|
|
.column(column),
|
426 |
|
|
.row(row),
|
427 |
|
|
.block(block),
|
428 |
|
|
.comp(comp),
|
429 |
|
|
.motvec_update(motvec_update),
|
430 |
|
|
/* out */
|
431 |
|
|
.frame_picture(frame_picture_0),
|
432 |
|
|
.field_in_frame(field_in_frame_0),
|
433 |
|
|
.comp_out(comp_0),
|
434 |
|
|
.macroblock_address_out(macroblock_address_0),
|
435 |
|
|
.delta_x(delta_x_0),
|
436 |
|
|
.delta_y(delta_y_0),
|
437 |
|
|
.fwd_src_frame(fwd_src_frame_0),
|
438 |
|
|
.fwd_src_field(fwd_src_field_0),
|
439 |
|
|
.fwd_mv_x(fwd_mv_x_0),
|
440 |
|
|
.fwd_mv_y(fwd_mv_y_0),
|
441 |
|
|
.fwd_valid(fwd_valid_0),
|
442 |
|
|
.bwd_src_frame(bwd_src_frame_0),
|
443 |
|
|
.bwd_src_field(bwd_src_field_0),
|
444 |
|
|
.bwd_mv_x(bwd_mv_x_0),
|
445 |
|
|
.bwd_mv_y(bwd_mv_y_0),
|
446 |
|
|
.bwd_valid(bwd_valid_0),
|
447 |
|
|
.write_recon(write_recon_0),
|
448 |
|
|
.recon_delta_x(recon_delta_x_0),
|
449 |
|
|
.recon_delta_y(recon_delta_y_0),
|
450 |
|
|
.recon_valid(recon_valid_0),
|
451 |
|
|
.recon_dst_frame(recon_dst_frame_0),
|
452 |
|
|
.recon_dst_field(recon_dst_field_0),
|
453 |
|
|
.dct_block_cmd(dct_block_cmd),
|
454 |
|
|
.dct_block_en(dct_block_en)
|
455 |
|
|
);
|
456 |
|
|
|
457 |
|
|
/* forward */
|
458 |
|
|
memory_address
|
459 |
|
|
#(.dta_width(1))
|
460 |
|
|
fwd_mem_addr (
|
461 |
|
|
.clk(clk),
|
462 |
|
|
.clk_en(clk_en),
|
463 |
|
|
.rst(rst),
|
464 |
|
|
/* in */
|
465 |
|
|
.frame(fwd_src_frame_0),
|
466 |
|
|
.frame_picture(frame_picture_0),
|
467 |
|
|
.field_in_frame(field_in_frame_0),
|
468 |
|
|
.field(fwd_src_field_0),
|
469 |
|
|
.component(comp_0),
|
470 |
|
|
.mb_width(mb_width),
|
471 |
|
|
.horizontal_size(horizontal_size),
|
472 |
|
|
.vertical_size(vertical_size),
|
473 |
|
|
.macroblock_address(macroblock_address_0),
|
474 |
|
|
.delta_x(delta_x_0),
|
475 |
|
|
.delta_y(delta_y_0),
|
476 |
|
|
.mv_x(fwd_mv_x_0),
|
477 |
|
|
.mv_y(fwd_mv_y_0),
|
478 |
|
|
.dta_in(1'b0),
|
479 |
|
|
.valid_in(fwd_valid_0),
|
480 |
|
|
/* out */
|
481 |
|
|
.address(fwd_wr_addr),
|
482 |
|
|
.offset_x(dst_wr_fwd_hor_offset),
|
483 |
|
|
.halfpixel_x(dst_wr_fwd_hor_halfpixel),
|
484 |
|
|
.halfpixel_y(dst_wr_fwd_ver_halfpixel),
|
485 |
|
|
.dta_out(),
|
486 |
|
|
.valid_out(fwd_wr_addr_en)
|
487 |
|
|
);
|
488 |
|
|
|
489 |
|
|
/* backward */
|
490 |
|
|
memory_address
|
491 |
|
|
#(.dta_width(1))
|
492 |
|
|
bwd_mem_addr (
|
493 |
|
|
.clk(clk),
|
494 |
|
|
.clk_en(clk_en),
|
495 |
|
|
.rst(rst),
|
496 |
|
|
/* in */
|
497 |
|
|
.frame(bwd_src_frame_0),
|
498 |
|
|
.frame_picture(frame_picture_0),
|
499 |
|
|
.field_in_frame(field_in_frame_0),
|
500 |
|
|
.field(bwd_src_field_0),
|
501 |
|
|
.component(comp_0),
|
502 |
|
|
.mb_width(mb_width),
|
503 |
|
|
.horizontal_size(horizontal_size),
|
504 |
|
|
.vertical_size(vertical_size),
|
505 |
|
|
.macroblock_address(macroblock_address_0),
|
506 |
|
|
.delta_x(delta_x_0),
|
507 |
|
|
.delta_y(delta_y_0),
|
508 |
|
|
.mv_x(bwd_mv_x_0),
|
509 |
|
|
.mv_y(bwd_mv_y_0),
|
510 |
|
|
.dta_in(1'b0),
|
511 |
|
|
.valid_in(bwd_valid_0),
|
512 |
|
|
/* out */
|
513 |
|
|
.address(bwd_wr_addr),
|
514 |
|
|
.offset_x(dst_wr_bwd_hor_offset),
|
515 |
|
|
.halfpixel_x(dst_wr_bwd_hor_halfpixel),
|
516 |
|
|
.halfpixel_y(dst_wr_bwd_ver_halfpixel),
|
517 |
|
|
.dta_out(),
|
518 |
|
|
.valid_out(bwd_wr_addr_en)
|
519 |
|
|
);
|
520 |
|
|
|
521 |
|
|
/* reconstruction */
|
522 |
|
|
memory_address
|
523 |
|
|
#(.dta_width(3))
|
524 |
|
|
recon_mem_addr (
|
525 |
|
|
.clk(clk),
|
526 |
|
|
.clk_en(clk_en),
|
527 |
|
|
.rst(rst),
|
528 |
|
|
/* in */
|
529 |
|
|
.frame(recon_dst_frame_0),
|
530 |
|
|
.frame_picture(frame_picture_0),
|
531 |
|
|
.field_in_frame(field_in_frame_0),
|
532 |
|
|
.field(recon_dst_field_0),
|
533 |
|
|
.component(comp_0),
|
534 |
|
|
.mb_width(mb_width),
|
535 |
|
|
.horizontal_size(horizontal_size),
|
536 |
|
|
.vertical_size(vertical_size),
|
537 |
|
|
.macroblock_address(macroblock_address_0),
|
538 |
|
|
.delta_x(recon_delta_x_0),
|
539 |
|
|
.delta_y(recon_delta_y_0),
|
540 |
|
|
.mv_x(13'sd0),
|
541 |
|
|
.mv_y(13'sd0),
|
542 |
|
|
.dta_in({fwd_valid_0, bwd_valid_0, write_recon_0}),
|
543 |
|
|
.valid_in(recon_valid_0),
|
544 |
|
|
/* out */
|
545 |
|
|
.address(dst_wr_write_address),
|
546 |
|
|
.offset_x(),
|
547 |
|
|
.halfpixel_x(),
|
548 |
|
|
.halfpixel_y(),
|
549 |
|
|
.dta_out({dst_wr_motion_forward, dst_wr_motion_backward, dst_wr_write_recon}),
|
550 |
|
|
.valid_out(dst_wr_en)
|
551 |
|
|
);
|
552 |
|
|
|
553 |
|
|
`ifdef DEBUG
|
554 |
|
|
/* debugging */
|
555 |
|
|
|
556 |
|
|
always @(posedge clk)
|
557 |
|
|
if (clk_en && (state == STATE_READ) && motion_vector_valid)
|
558 |
|
|
begin
|
559 |
|
|
case (chroma_format)
|
560 |
|
|
CHROMA420: #0 $display("%m CHROMA420");
|
561 |
|
|
CHROMA422: #0 $display("%m CHROMA422");
|
562 |
|
|
CHROMA444: #0 $display("%m CHROMA444");
|
563 |
|
|
default #0 $display("%m chroma_format %h", chroma_format);
|
564 |
|
|
endcase
|
565 |
|
|
case (picture_coding_type)
|
566 |
|
|
P_TYPE: #0 $display("%m P_TYPE");
|
567 |
|
|
I_TYPE: #0 $display("%m I_TYPE");
|
568 |
|
|
B_TYPE: #0 $display("%m B_TYPE");
|
569 |
|
|
D_TYPE: #0 $display("%m D_TYPE"); // mpeg1 only; mpeg2 does not have D pictures
|
570 |
|
|
endcase
|
571 |
|
|
case (picture_structure)
|
572 |
|
|
FRAME_PICTURE: #0 $display("%m FRAME_PICTURE");
|
573 |
|
|
TOP_FIELD: #0 $display("%m TOP_FIELD");
|
574 |
|
|
BOTTOM_FIELD: #0 $display("%m BOTTOM_FIELD");
|
575 |
|
|
default #0 $display("%m picture_structure %h", picture_structure);
|
576 |
|
|
endcase
|
577 |
|
|
|
578 |
|
|
/*
|
579 |
|
|
MC_FRAME and MC_16X8 share the same code; which one is used depends upon picture_structure.
|
580 |
|
|
In a FRAME_PICTURE you can have MC_FRAME, but never MC_16X8.
|
581 |
|
|
In a field picture (TOP_FIELD, BOTTOM_FIELD) you can have MC_16X8, but never MC_FRAME.
|
582 |
|
|
*/
|
583 |
|
|
case (picture_structure)
|
584 |
|
|
FRAME_PICTURE:
|
585 |
|
|
case (motion_type)
|
586 |
|
|
MC_FIELD: #0 $display("%m MC_FIELD");
|
587 |
|
|
MC_FRAME: #0 $display("%m MC_FRAME");
|
588 |
|
|
MC_DMV: #0 $display("%m MC_DMV");
|
589 |
|
|
MC_NONE: #0 $display("%m MC_NONE");
|
590 |
|
|
default #0 $display("%m *** unknown motion_type %h ***", motion_type);
|
591 |
|
|
endcase
|
592 |
|
|
TOP_FIELD,
|
593 |
|
|
BOTTOM_FIELD:
|
594 |
|
|
case (motion_type)
|
595 |
|
|
MC_FIELD: #0 $display("%m MC_FIELD");
|
596 |
|
|
MC_16X8: #0 $display("%m MC_16X8");
|
597 |
|
|
MC_DMV: #0 $display("%m MC_DMV");
|
598 |
|
|
MC_NONE: #0 $display("%m MC_NONE");
|
599 |
|
|
default #0 $display("%m *** unknown motion_type %h ***", motion_type);
|
600 |
|
|
endcase
|
601 |
|
|
endcase
|
602 |
|
|
#0 $display("%m macroblock_address: %d", macroblock_address);
|
603 |
|
|
if (macroblock_intra) #0 $display("%m macroblock_intra");
|
604 |
|
|
if (macroblock_motion_forward && macroblock_motion_backward) #0 $display("%m macroblock_motion_forward, macroblock_motion_backward");
|
605 |
|
|
else if (macroblock_motion_forward) #0 $display("%m macroblock_motion_forward");
|
606 |
|
|
else if (macroblock_motion_backward) #0 $display("%m macroblock_motion_backward");
|
607 |
|
|
else #0 $display("%m no macroblock_motion_forward, no macroblock_motion_backward");
|
608 |
|
|
if (dct_type) #0 $display("%m dct_type field");
|
609 |
|
|
else #0 $display("%m dct_type frame");
|
610 |
|
|
#0 $display("%m\tpmv_0_0_0: %d pmv_0_0_1: %d pmv_1_0_0: %d pmv_1_0_1: %d pmv_0_1_0: %d pmv_0_1_1: %d pmv_1_1_0: %d pmv_1_1_1: %d", pmv_0_0_0, pmv_0_0_1, pmv_1_0_0, pmv_1_0_1, pmv_0_1_0, pmv_0_1_1, pmv_1_1_0, pmv_1_1_1);
|
611 |
|
|
#0 $display("%m\tdmv_0_0: %d dmv_0_1: %d dmv_1_0: %d dmv_1_1: %d", dmv_0_0, dmv_0_1, dmv_1_0, dmv_1_1);
|
612 |
|
|
#0 $display("%m\tmotion_vert_field_select_0_0: %d motion_vert_field_select_0_1: %d motion_vert_field_select_1_0: %d motion_vert_field_select_1_1: %d", motion_vert_field_select_0_0, motion_vert_field_select_0_1, motion_vert_field_select_1_0, motion_vert_field_select_1_1);
|
613 |
|
|
end
|
614 |
|
|
|
615 |
|
|
always @(posedge clk)
|
616 |
|
|
if (clk_en && (state == STATE_READ) && update_picture_buffers)
|
617 |
|
|
begin
|
618 |
|
|
#0 $display("%m\tupdate picture buffers");
|
619 |
|
|
end
|
620 |
|
|
|
621 |
|
|
always @(posedge clk)
|
622 |
|
|
if (clk_en)
|
623 |
|
|
case (state)
|
624 |
|
|
STATE_INIT: #0 $display("%m STATE_INIT");
|
625 |
|
|
STATE_READ: #0 $display("%m STATE_READ");
|
626 |
|
|
STATE_UPDATE: #0 $display("%m STATE_UPDATE");
|
627 |
|
|
STATE_MOTVEC: #0 $display("%m STATE_MOTVEC");
|
628 |
|
|
STATE_NEXT: #0 $display("%m STATE_NEXT");
|
629 |
|
|
default #0 $display("%m *** Error: unknown state %d", state);
|
630 |
|
|
endcase
|
631 |
|
|
|
632 |
|
|
always @(posedge clk)
|
633 |
|
|
begin
|
634 |
|
|
$strobe("%m\tclk_en: %d mvec_rd_en: %d mvec_rd_valid: %d", clk_en, mvec_rd_en, mvec_rd_valid);
|
635 |
|
|
$strobe("%m\tclk_en: %d mb_end: %d last_row: %d comp: %d block: %d row: %d col:%d motvec_update: %d", clk_en, mb_end, last_row, comp, block, row, column, motvec_update);
|
636 |
|
|
|
637 |
|
|
$strobe("%m\tclk_en: %d fwd_src_frame_0: %d frame_picture_0: %d field_in_frame_0: %d fwd_src_field_0: %d comp_0: %d macroblock_address_0: %d delta_x_0: %d delta_y_0: %d fwd_mv_x_0: %d fwd_mv_y_0: %d fwd_valid_0: %d",
|
638 |
|
|
clk_en, fwd_src_frame_0, frame_picture_0, field_in_frame_0, fwd_src_field_0, comp_0, macroblock_address_0, delta_x_0, delta_y_0, fwd_mv_x_0, fwd_mv_y_0, fwd_valid_0);
|
639 |
|
|
|
640 |
|
|
$strobe("%m\tclk_en: %d bwd_src_frame_0: %d frame_picture_0: %d field_in_frame_0: %d bwd_src_field_0: %d comp_0: %d macroblock_address_0: %d delta_x_0: %d delta_y_0: %d bwd_mv_x_0: %d bwd_mv_y_0: %d bwd_valid_0: %d",
|
641 |
|
|
clk_en, bwd_src_frame_0, frame_picture_0, field_in_frame_0, bwd_src_field_0, comp_0, macroblock_address_0, delta_x_0, delta_y_0, bwd_mv_x_0, bwd_mv_y_0, bwd_valid_0);
|
642 |
|
|
|
643 |
|
|
$strobe("%m\tclk_en: %d recon_dst_frame_0: %d frame_picture_0: %d field_in_frame_0: %d recon_dst_field_0: %d comp_0: %d macroblock_address_0: %d recon_delta_x_0: %d recon_delta_y_0: %d recon_valid_0: %d write_recon_0: %d",
|
644 |
|
|
clk_en, recon_dst_frame_0, frame_picture_0, field_in_frame_0, recon_dst_field_0, comp_0, macroblock_address_0, recon_delta_x_0, recon_delta_y_0, recon_valid_0, write_recon_0);
|
645 |
|
|
$strobe("%m\tclk_en: %d dst_wr_en: %d dst_wr_write_recon: %d dst_wr_write_address: %h dst_wr_motion_forward: %d dst_wr_motion_backward: %d ",
|
646 |
|
|
clk_en, dst_wr_en, dst_wr_write_recon, dst_wr_write_address, dst_wr_motion_forward, dst_wr_motion_backward);
|
647 |
|
|
$strobe("%m\tclk_en: %d dst_wr_en: %d dst_wr_fwd_hor_offset: %d dst_wr_fwd_hor_halfpixel: %d dst_wr_fwd_ver_halfpixel: %d dst_wr_bwd_hor_offset: %d dst_wr_bwd_hor_halfpixel: %d dst_wr_bwd_ver_halfpixel: %d",
|
648 |
|
|
clk_en, dst_wr_en, dst_wr_fwd_hor_offset, dst_wr_fwd_hor_halfpixel, dst_wr_fwd_ver_halfpixel, dst_wr_bwd_hor_offset, dst_wr_bwd_hor_halfpixel, dst_wr_bwd_ver_halfpixel);
|
649 |
|
|
|
650 |
|
|
$strobe("%m\tclk_en: %d dct_block_cmd: %d dct_block_en: %d",
|
651 |
|
|
clk_en, dct_block_cmd, dct_block_en);
|
652 |
|
|
end
|
653 |
|
|
|
654 |
|
|
`endif
|
655 |
|
|
|
656 |
|
|
endmodule
|
657 |
|
|
/* not truncated */
|