1 |
2 |
eejlny |
----------------------------------------------------------------------------
|
2 |
|
|
-- This file is a part of the LM VHDL IP LIBRARY
|
3 |
|
|
-- Copyright (C) 2009 Jose Nunez-Yanez
|
4 |
|
|
--
|
5 |
|
|
-- This program is free software; you can redistribute it and/or modify
|
6 |
|
|
-- it under the terms of the GNU General Public License as published by
|
7 |
|
|
-- the Free Software Foundation; either version 2 of the License, or
|
8 |
|
|
-- (at your option) any later version.
|
9 |
|
|
--
|
10 |
|
|
-- See the file COPYING for the full details of the license.
|
11 |
|
|
--
|
12 |
|
|
-- The license allows free and unlimited use of the library and tools for research and education purposes.
|
13 |
|
|
-- The full LM core supports many more advanced motion estimation features and it is available under a
|
14 |
|
|
-- low-cost commercial license. See the readme file to learn more or contact us at
|
15 |
|
|
-- eejlny@byacom.co.uk or www.byacom.co.uk
|
16 |
|
|
--------------------------------------
|
17 |
|
|
-- entity = me_control_unit --
|
18 |
|
|
-- version = 1.0 --
|
19 |
|
|
-- last update = 20/07/09 --
|
20 |
|
|
-- author = Jose Nunez --
|
21 |
|
|
--------------------------------------
|
22 |
|
|
|
23 |
|
|
|
24 |
|
|
-- main control unit for the motion estimation process
|
25 |
|
|
|
26 |
|
|
library IEEE;
|
27 |
|
|
use IEEE.std_logic_1164.all;
|
28 |
|
|
use IEEE.std_logic_unsigned."+";
|
29 |
|
|
use IEEE.std_logic_unsigned."-";
|
30 |
|
|
use IEEE.std_logic_unsigned."=";
|
31 |
|
|
use IEEE.std_logic_unsigned.">";
|
32 |
|
|
use IEEE.std_logic_unsigned."<";
|
33 |
|
|
use IEEE.std_logic_unsigned.">=";
|
34 |
|
|
use IEEE.Numeric_STD.all;
|
35 |
|
|
use work.config.all;
|
36 |
|
|
|
37 |
|
|
|
38 |
|
|
entity me_control_unit is
|
39 |
|
|
generic ( integer_pipeline_count : integer := 1);
|
40 |
|
|
port ( clk : in std_logic;
|
41 |
|
|
clear : in std_logic;
|
42 |
|
|
reset : in std_logic;
|
43 |
|
|
start : in std_logic;
|
44 |
|
|
range_ok : in std_logic; --keep track of the mv range
|
45 |
|
|
best_sad_in : in std_logic_vector(15 downto 0); -- to make SAD-based decisions
|
46 |
|
|
mv_length_in : in std_logic_vector(15 downto 0); -- to make LENGTH-based decisions
|
47 |
|
|
mode_in : in mode_type;
|
48 |
|
|
qp_on : in std_logic; -- qp on
|
49 |
|
|
mvc_done : in std_logic; -- all motion vector candidates evaluated
|
50 |
|
|
mvc_to_do : in std_logic_vector(3 downto 0);
|
51 |
|
|
partition_count_out : out std_logic_vector(3 downto 0); --identify the partition active
|
52 |
|
|
start_pipelines : out std_logic_vector((integer_pipeline_count-1) downto 0);
|
53 |
|
|
active_pipelines : out std_logic_vector((integer_pipeline_count-1) downto 0); -- so sad selector ignores the non active ones
|
54 |
|
|
shift_concatenate_valid : in std_logic; -- valid output from the concantenate unit
|
55 |
|
|
interpolation_done : in std_logic; -- interpolation completes
|
56 |
|
|
interpolate_data_request : in std_logic; -- interpolator requests data
|
57 |
|
|
instruction_address : out std_logic_vector(7 downto 0); -- address to fetch next instruction
|
58 |
|
|
instruction_opcode : in std_logic_vector(3 downto 0); -- opcode
|
59 |
|
|
point_count : in std_logic_vector(7 downto 0); -- how many points to test
|
60 |
|
|
point_address : in std_logic_vector(7 downto 0); -- which is the first point to test
|
61 |
|
|
calculate_sad_done : in std_logic; -- signals when the distance engine has finished
|
62 |
|
|
distance_engine_active : in std_logic; -- signals when distance engine is not running
|
63 |
|
|
next_point : out std_logic_vector(7 downto 0); -- next point address to ROM
|
64 |
|
|
line_offset : out std_logic_vector(5 downto 0); -- multiple line reading
|
65 |
|
|
enable_concatenate_unit : out std_logic;
|
66 |
|
|
-- enable_dist_engine : out std_logic;
|
67 |
|
|
write_register : out std_logic;
|
68 |
|
|
best_eu : in std_logic_vector(3 downto 0); -- best execution unit
|
69 |
|
|
load_mv : out std_logic;
|
70 |
|
|
update : out std_logic;
|
71 |
|
|
instruction_zero : out std_logic; -- program completes after hitting instruction zero points
|
72 |
|
|
all_done : out std_logic; -- fp part completes or program completes
|
73 |
|
|
partition_done : out std_logic;
|
74 |
|
|
qpel_loc_x : in std_logic_vector(1 downto 0); -- detect qp mode
|
75 |
|
|
qpel_loc_y : in std_logic_vector(1 downto 0);
|
76 |
|
|
start_qp : out std_logic;
|
77 |
|
|
enable_hp_inter : out std_logic; -- start the interpolation core
|
78 |
|
|
-- write_block1 : out std_logic;
|
79 |
|
|
-- next_rm_address_ready : in std_logic;
|
80 |
|
|
next_rm_addresss : in std_logic_vector(13 downto 0); --physical address for reference (macroblock upper left corner
|
81 |
|
|
rm_address : out std_logic_vector(13 downto 0) -- reference memory read from address
|
82 |
|
|
--cm_address : out std_logic_vector(4 downto 0); -- address to extract 4x4 blocks from current macroblock
|
83 |
|
|
-- rma_address : out std_logic_vector(4 downto 0); -- reference macroblock write to address
|
84 |
|
|
-- rma_we : out std_logic
|
85 |
|
|
);
|
86 |
|
|
end;
|
87 |
|
|
|
88 |
|
|
architecture struct of me_control_unit is
|
89 |
|
|
|
90 |
|
|
|
91 |
|
|
|
92 |
|
|
type state_type is (terminate,idle,fetch_instruction,access_point_memory,next_phy_address_ready,update_mv,wait_for_distance_engine,wait_for_distance_engine2,enable_concatenate_2,enable_concatenate,wait_for_phy_address,wait_for_phy_address2); -- me control unit states
|
93 |
|
|
|
94 |
|
|
type state_register_type is record
|
95 |
|
|
|
96 |
|
|
state : state_type;
|
97 |
|
|
partition_count : std_logic_vector(3 downto 0); -- to keep track of the sub-partitions
|
98 |
|
|
best_eu : std_logic_vector(3 downto 0); -- for jump conditions
|
99 |
|
|
qp_mode : std_logic; -- processing a fraction instruction
|
100 |
|
|
invalidate : std_logic; -- flag to invalidate instructions that follow jumps
|
101 |
|
|
enable_concatenate_unit : std_logic;
|
102 |
|
|
data_block : std_logic_vector(1 downto 0); --9 data blocks of 8 rows and 8 pixels for interpolation
|
103 |
|
|
enable_hp_inter : std_logic;
|
104 |
|
|
instruction_address : std_logic_vector(7 downto 0); --counter keeps track of next instruction to execute
|
105 |
|
|
instruction_opcode : std_logic_vector(3 downto 0);
|
106 |
|
|
point_count : std_logic_vector(7 downto 0); --register stores the number of points to test
|
107 |
|
|
point_address : std_logic_vector(7 downto 0); -- register stores the first address of the points to test
|
108 |
|
|
points_tested : std_logic_vector(7 downto 0); -- counter that keeps track of the number of points tested
|
109 |
|
|
phy_address : std_logic_vector(13 downto 0); -- address for the reference memory
|
110 |
|
|
phy_address_ready : std_logic_vector(13 downto 0); -- stores a ready copy of the next reference memory address
|
111 |
|
|
--rma_address : std_logic_vector(4 downto 0); -- address for the reference macroblock memory
|
112 |
|
|
line_offset : std_logic_vector(5 downto 0); -- reading of multiple lines control
|
113 |
|
|
line_count : std_logic_vector(4 downto 0); -- counter to keep track of the number of lines loaded in reference macroblock
|
114 |
|
|
interpolation_done : std_logic; -- remember when interpolation has been done so not to do it again
|
115 |
|
|
active_pipelines_r : std_logic_vector((integer_pipeline_count-1) downto 0);
|
116 |
|
|
condition_bit : std_logic; -- condition bit for jump instructions
|
117 |
|
|
-- calculate_sad_done : std_logic;
|
118 |
|
|
--write_block1 : std_logic; -- flag
|
119 |
|
|
end record;
|
120 |
|
|
|
121 |
|
|
signal r, r_in: state_register_type; -- state register
|
122 |
|
|
signal finish : std_logic;
|
123 |
|
|
|
124 |
|
|
|
125 |
|
|
begin
|
126 |
|
|
|
127 |
|
|
|
128 |
|
|
--rma_address <= (others => '0'); -- reference macroblock write to address
|
129 |
|
|
--cm_address <= (others => '0'); -- address to extract 4x4 blocks from current macroblock
|
130 |
|
|
all_done <= finish;
|
131 |
|
|
|
132 |
|
|
control: process(mvc_done,mvc_to_do,range_ok,instruction_opcode,best_eu,mode_in,r,qpel_loc_x,qpel_loc_y,interpolation_done,interpolate_data_request,start,next_rm_addresss,shift_concatenate_valid,calculate_sad_done,point_address,point_count)
|
133 |
|
|
|
134 |
|
|
variable v : state_register_type;
|
135 |
|
|
variable vfinish,vstart,vrma_we,vload_mv,vupdate,vstart_qp,vpartition_done,vinstruction_zero : std_logic;
|
136 |
|
|
variable vwrite_register,venable_dist_engine : std_logic;
|
137 |
|
|
variable vrm_address : std_logic_vector(13 downto 0); -- generate rm address as soon as possible
|
138 |
|
|
variable vstart_pipelines : std_logic_vector((integer_pipeline_count-1) downto 0);
|
139 |
|
|
|
140 |
|
|
begin
|
141 |
|
|
|
142 |
|
|
--v.calculate_sad_done := calculate_sad_done;
|
143 |
|
|
vstart_qp := '0';
|
144 |
|
|
vpartition_done := '0';
|
145 |
|
|
vfinish := '0';
|
146 |
|
|
vinstruction_zero := '0'; --instruction zero points hit
|
147 |
|
|
v.qp_mode := r.qp_mode;
|
148 |
|
|
v.partition_count := r.partition_count;
|
149 |
|
|
v.data_block := r.data_block;
|
150 |
|
|
v.invalidate := r.invalidate;
|
151 |
|
|
v.best_eu := r.best_eu;
|
152 |
|
|
v.points_tested := r.points_tested;
|
153 |
|
|
v.instruction_address := r.instruction_address;
|
154 |
|
|
v.phy_address_ready := next_rm_addresss;
|
155 |
|
|
v.line_offset := r.line_offset;
|
156 |
|
|
v.point_count := r.point_count;
|
157 |
|
|
v.point_address := r.point_address;
|
158 |
|
|
v.phy_address := r.phy_address;
|
159 |
|
|
v.line_count := r.line_count;
|
160 |
|
|
v.enable_concatenate_unit := r.enable_concatenate_unit;
|
161 |
|
|
v.enable_hp_inter := r.enable_hp_inter;
|
162 |
|
|
v.instruction_opcode := (others =>'0');
|
163 |
|
|
--vnext_rm_address_ready := next_rm_address_ready;
|
164 |
|
|
v.state := r.state;
|
165 |
|
|
v.interpolation_done := r.interpolation_done;
|
166 |
|
|
vstart := start;
|
167 |
|
|
vload_mv := '0';
|
168 |
|
|
vrma_we := '0';
|
169 |
|
|
vupdate := '0';
|
170 |
|
|
vwrite_register := '0';
|
171 |
|
|
venable_dist_engine := '0';
|
172 |
|
|
vrm_address := r.phy_address;
|
173 |
|
|
vstart_pipelines := (others => '0'); -- all pipelines disable
|
174 |
|
|
v.active_pipelines_r := r.active_pipelines_r;
|
175 |
|
|
v.condition_bit := r.condition_bit;
|
176 |
|
|
|
177 |
|
|
-- std_logic_vector(to_unsigned(,integer_pipeline_count));
|
178 |
|
|
|
179 |
|
|
|
180 |
|
|
|
181 |
|
|
case v.state is
|
182 |
|
|
|
183 |
|
|
when idle => -- first state, waiting for command register bit 31 to go high
|
184 |
|
|
if (vstart = '1') then
|
185 |
|
|
v.state := fetch_instruction;
|
186 |
|
|
v.interpolation_done := '0';
|
187 |
|
|
--if (mvc_done = '1') then -- first evaluate all the mvcs
|
188 |
|
|
v.instruction_address := v.instruction_address + x"01";
|
189 |
|
|
--end if;
|
190 |
|
|
end if;
|
191 |
|
|
|
192 |
|
|
when fetch_instruction => -- execute instructions in the program firmware memory
|
193 |
|
|
--v.instruction_address := v.instruction_address + x"01";
|
194 |
|
|
v.point_count := point_count;
|
195 |
|
|
v.point_address := point_address;
|
196 |
|
|
v.instruction_opcode := instruction_opcode;
|
197 |
|
|
case v.instruction_opcode is
|
198 |
|
|
when "0000" => --full pel pattern instruction
|
199 |
|
|
if (v.invalidate = '0') then
|
200 |
|
|
if (v.point_count = x"00") then -- finish => all instructions executed
|
201 |
|
|
v.state := terminate;
|
202 |
|
|
v.instruction_address := (others => '0');
|
203 |
|
|
v.condition_bit := '0'; -- reset condition bit
|
204 |
|
|
--vfinish := '1'; -- clear the state when completing program
|
205 |
|
|
else
|
206 |
|
|
v.state := access_point_memory;
|
207 |
|
|
end if;
|
208 |
|
|
else
|
209 |
|
|
v.invalidate := '0'; -- clear flag
|
210 |
|
|
v.instruction_address := v.instruction_address + x"01";
|
211 |
|
|
end if;
|
212 |
|
|
when "0001" => -- fractional pel pattern instruction
|
213 |
|
|
if CFG_PIPELINE_COUNT_QP = 1 then
|
214 |
|
|
if (v.invalidate = '0') then
|
215 |
|
|
v.state := access_point_memory;
|
216 |
|
|
v.qp_mode := '1';
|
217 |
|
|
else
|
218 |
|
|
v.invalidate := '0'; -- clear flag
|
219 |
|
|
v.instruction_address := v.instruction_address + x"01";
|
220 |
|
|
end if;
|
221 |
|
|
end if;
|
222 |
|
|
when "0010" => -- condional jump instruction (if best_eu == field A in instruction (point count) jumpp to point_address
|
223 |
|
|
if (v.best_eu = point_count(3 downto 0)) then
|
224 |
|
|
v.instruction_address := point_address;
|
225 |
|
|
v.invalidate := '1'; -- invalidate the next instruction so it does not execute
|
226 |
|
|
else
|
227 |
|
|
v.instruction_address := v.instruction_address + x"01";
|
228 |
|
|
v.invalidate := '0';
|
229 |
|
|
end if;
|
230 |
|
|
when "0100" => -- conditional jump to label (if condition bit set jump to label)
|
231 |
|
|
if (v.condition_bit = '1') then
|
232 |
|
|
v.instruction_address := point_address;
|
233 |
|
|
v.invalidate := '1'; -- invalidate the next instruction so it does not execute
|
234 |
|
|
else
|
235 |
|
|
v.instruction_address := v.instruction_address + x"01";
|
236 |
|
|
v.invalidate := '0';
|
237 |
|
|
end if;
|
238 |
|
|
v.condition_bit := '0'; -- reset condition bit
|
239 |
|
|
when "0101" => -- compare (if less than set condition bit)
|
240 |
|
|
if (point_count(7 downto 6) = "00") then -- reg field
|
241 |
|
|
if (best_sad_in < point_count(5 downto 0) & point_address(7 downto 0)) then
|
242 |
|
|
v.condition_bit := '1'; -- set condition bit
|
243 |
|
|
end if;
|
244 |
|
|
else
|
245 |
|
|
if (mv_length_in(14 downto 7) & mv_length_in(6 downto 0)) < (point_count(5 downto 0) & point_address(7 downto 0)) then
|
246 |
|
|
v.condition_bit := '1'; -- set condition bit
|
247 |
|
|
end if;
|
248 |
|
|
end if;
|
249 |
|
|
v.instruction_address := v.instruction_address + x"01";
|
250 |
|
|
when "0110" => -- compare (if greater than set condition bit)
|
251 |
|
|
if (point_count(7 downto 6) = "00") then -- reg field
|
252 |
|
|
if (best_sad_in > point_count(5 downto 0) & point_address(7 downto 0)) then
|
253 |
|
|
v.condition_bit := '1'; -- set condition bit
|
254 |
|
|
end if;
|
255 |
|
|
else
|
256 |
|
|
if (mv_length_in(14 downto 7) & mv_length_in(6 downto 0)) > (point_count(5 downto 0) & point_address(7 downto 0)) then
|
257 |
|
|
v.condition_bit := '1'; -- set condition bit
|
258 |
|
|
end if;
|
259 |
|
|
end if;
|
260 |
|
|
v.instruction_address := v.instruction_address + x"01";
|
261 |
|
|
when others => null;
|
262 |
|
|
end case;
|
263 |
|
|
-- unconditional jump
|
264 |
|
|
-- conditional jump if condition bit
|
265 |
|
|
-- compare instruction (less than)
|
266 |
|
|
when access_point_memory =>
|
267 |
|
|
v.enable_concatenate_unit := '0';
|
268 |
|
|
v.state := wait_for_phy_address;
|
269 |
|
|
if (r.qp_mode = '0') then --only use slave fp pipelines if not qp mode
|
270 |
|
|
v.active_pipelines_r(0) := '1';
|
271 |
|
|
vstart_pipelines(0) := '1';
|
272 |
|
|
for i in 1 to integer_pipeline_count-1 loop
|
273 |
|
|
if (v.point_count-v.points_tested > i) then
|
274 |
|
|
vstart_pipelines(i) := '1';
|
275 |
|
|
v.active_pipelines_r(i) := '1';
|
276 |
|
|
else
|
277 |
|
|
vstart_pipelines(i) := '0';
|
278 |
|
|
v.active_pipelines_r(i) := '0';
|
279 |
|
|
end if;
|
280 |
|
|
end loop;
|
281 |
|
|
end if;
|
282 |
|
|
when wait_for_phy_address =>-- waiting for translation to finish
|
283 |
|
|
if (range_ok = '1')then
|
284 |
|
|
v.state := wait_for_phy_address2;
|
285 |
|
|
if CFG_PIPELINE_COUNT_QP = 1 then
|
286 |
|
|
if (r.qp_mode = '1' and r.interpolation_done = '0') then -- jump if mvx or mvy qp instruction are qp fractional
|
287 |
|
|
v.enable_hp_inter := '1';
|
288 |
|
|
v.instruction_address := v.instruction_address + x"FF"; -- -1
|
289 |
|
|
--v.qp_mode := '1';
|
290 |
|
|
-- v.state := inter_wait_for_phy_address2;
|
291 |
|
|
end if;
|
292 |
|
|
end if;
|
293 |
|
|
else --bypass point calculation if range is not good
|
294 |
|
|
v.point_address := v.point_address + std_logic_vector(to_unsigned(integer_pipeline_count,8)); -- next point memory position
|
295 |
|
|
v.points_tested := v.points_tested + std_logic_vector(to_unsigned(integer_pipeline_count,8)); -- new point ajusted depending of the number of integer pipelines
|
296 |
|
|
if (v.points_tested >= r.point_count) then -- current instruction completes
|
297 |
|
|
v.state := wait_for_distance_engine2;
|
298 |
|
|
v.points_tested := (others => '0');
|
299 |
|
|
else
|
300 |
|
|
v.state := access_point_memory;
|
301 |
|
|
end if;
|
302 |
|
|
end if;
|
303 |
|
|
when wait_for_phy_address2 => -- two cycles to get phy address
|
304 |
|
|
v.phy_address := next_rm_addresss; -- store phy address in register
|
305 |
|
|
v.line_offset := v.line_offset + "000001"; -- +1 to increase the y component
|
306 |
|
|
v.state := next_phy_address_ready;
|
307 |
|
|
-- v.point_address := v.point_address + std_logic_vector(to_unsigned(integer_pipeline_count,8)); -- next
|
308 |
|
|
|
309 |
|
|
|
310 |
|
|
|
311 |
|
|
when next_phy_address_ready => -- start accessing reference memory
|
312 |
|
|
v.enable_concatenate_unit := '0';
|
313 |
|
|
v.phy_address := (v.phy_address(13 downto 3) + "00000000001") & next_rm_addresss(2 downto 0); -- plus 1 to read again part of the data (simple alignment)
|
314 |
|
|
v.state := enable_concatenate;
|
315 |
|
|
|
316 |
|
|
--v.point_address := v.point_address + std_logic_vector(to_unsigned(integer_pipeline_count,8)); -- next point memory position
|
317 |
|
|
--vload_mv := '1'; -- load mv candidate in distance engine for future use
|
318 |
|
|
when enable_concatenate =>
|
319 |
|
|
v.phy_address := v.phy_address + "00000000001000";
|
320 |
|
|
v.enable_concatenate_unit := '1';
|
321 |
|
|
-- if (shift_concatenate_valid = '1') then -- first part of line
|
322 |
|
|
v.state := enable_concatenate_2;
|
323 |
|
|
v.line_offset := v.line_offset + "000001"; -- +1 to increase the y componenent
|
324 |
|
|
if (r.line_count = "01111") then
|
325 |
|
|
|
326 |
|
|
|
327 |
|
|
v.line_offset := (others => '0');
|
328 |
|
|
end if;
|
329 |
|
|
if (r.line_count = "01110") then
|
330 |
|
|
vload_mv := '1'; -- load mv candidate in distance engine for future use
|
331 |
|
|
v.point_address := v.point_address + std_logic_vector(to_unsigned(integer_pipeline_count,8)); -- next
|
332 |
|
|
end if;
|
333 |
|
|
|
334 |
|
|
-- end if;
|
335 |
|
|
when enable_concatenate_2 =>
|
336 |
|
|
-- if (r.line_offset = "10000") then
|
337 |
|
|
-- v.line_offset := (others => '0');
|
338 |
|
|
-- end if;
|
339 |
|
|
-- v.phy_address := (v.phy_address(13 downto 3) + "00000000010") & "000";
|
340 |
|
|
-- v.enable_concatenate_unit := '1';
|
341 |
|
|
-- if (shift_concatenate_valid = '1') then -- second part of line
|
342 |
|
|
v.enable_concatenate_unit := '1';
|
343 |
|
|
--v.state := enable_interpolate;
|
344 |
|
|
v.line_count := v.line_count + "00001";
|
345 |
|
|
--vrm_address := next_rm_addresss(12 downto 3) & "000"; -- set to "000" so the first new access does not interfere with the concatenation of the last bytes in the previous access
|
346 |
|
|
vrm_address := r.phy_address_ready;
|
347 |
|
|
v.phy_address := next_rm_addresss + "00000000001000"; -- (plus 1 as well?) store phy address in register
|
348 |
|
|
--v.phy_address := (v.phy_address(11 downto 3) + "000000001") & next_rm_addresss(2 downto 0)
|
349 |
|
|
v.state := enable_concatenate; -- next line
|
350 |
|
|
-- end if;
|
351 |
|
|
if (r.line_count = "01110") then
|
352 |
|
|
v.line_offset := (others => '0');
|
353 |
|
|
--v.point_address := v.point_address + std_logic_vector(to_unsigned(integer_pipeline_count,8)); -- next
|
354 |
|
|
end if;
|
355 |
|
|
if (r.line_count = "01111") then -- all the lines done
|
356 |
|
|
--v.enable_concatenate_unit := '0';
|
357 |
|
|
--v.point_address := v.point_address + std_logic_vector(to_unsigned(integer_pipeline_count,8)); -- next point memory position
|
358 |
|
|
v.points_tested := v.points_tested + std_logic_vector(to_unsigned(integer_pipeline_count,8)); -- new point ajusted depending of the number of integer pipelines
|
359 |
|
|
v.line_count := (others=>'0');
|
360 |
|
|
v.phy_address := next_rm_addresss; -- store phy address in register
|
361 |
|
|
v.line_offset := v.line_offset + "000001"; -- +1 to increase the y component
|
362 |
|
|
if (v.points_tested >= r.point_count) then -- current instruction completes
|
363 |
|
|
v.state := wait_for_distance_engine;
|
364 |
|
|
v.points_tested := (others => '0');
|
365 |
|
|
v.line_offset := (others => '0');
|
366 |
|
|
-- v.point_address := point_address; -- start accesing point memory earlier
|
367 |
|
|
else
|
368 |
|
|
v.state := next_phy_address_ready; -- access should be ready;
|
369 |
|
|
if (r.qp_mode = '0') then --only use slave fp pipelines if not qp mode
|
370 |
|
|
v.active_pipelines_r(0) := '1';
|
371 |
|
|
vstart_pipelines(0) := '1';
|
372 |
|
|
for i in 1 to integer_pipeline_count-1 loop
|
373 |
|
|
if (v.point_count-v.points_tested > i) then
|
374 |
|
|
vstart_pipelines(i) := '1';
|
375 |
|
|
v.active_pipelines_r(i) := '1';
|
376 |
|
|
else
|
377 |
|
|
vstart_pipelines(i) := '0';
|
378 |
|
|
v.active_pipelines_r(i) := '0';
|
379 |
|
|
end if;
|
380 |
|
|
end loop;
|
381 |
|
|
end if;
|
382 |
|
|
end if;
|
383 |
|
|
-- v.line_offset := (others => '0');
|
384 |
|
|
end if;
|
385 |
|
|
when wait_for_distance_engine=>
|
386 |
|
|
v.enable_concatenate_unit := '0';
|
387 |
|
|
if (calculate_sad_done= '1') then
|
388 |
|
|
v.state := update_mv;
|
389 |
|
|
end if;
|
390 |
|
|
when wait_for_distance_engine2 =>
|
391 |
|
|
v.enable_concatenate_unit := '0';
|
392 |
|
|
if (distance_engine_active = '0') then
|
393 |
|
|
v.state := update_mv;
|
394 |
|
|
end if;
|
395 |
|
|
when update_mv =>
|
396 |
|
|
vupdate := '1';
|
397 |
|
|
v.best_eu := best_eu; --update the condition bit
|
398 |
|
|
v.state := fetch_instruction;
|
399 |
|
|
--if (mvc_done = '1') then -- first evaluate all the mvcs
|
400 |
|
|
v.instruction_address := v.instruction_address + x"01"; -- start reading the next instruction when arriving in fetch instruction state
|
401 |
|
|
--end if;
|
402 |
|
|
when terminate =>
|
403 |
|
|
if (qp_on = '0') then -- qp must have finished
|
404 |
|
|
-- if (mode_in = m16x16) then
|
405 |
|
|
vfinish := '1';
|
406 |
|
|
vinstruction_zero := '1';
|
407 |
|
|
v.state := idle;
|
408 |
|
|
vpartition_done := '1';
|
409 |
|
|
end if;
|
410 |
|
|
--v.state := idle;
|
411 |
|
|
when others => null;
|
412 |
|
|
|
413 |
|
|
end case;
|
414 |
|
|
|
415 |
|
|
if (interpolation_done = '1') then
|
416 |
|
|
v.interpolation_done := '1';
|
417 |
|
|
end if;
|
418 |
|
|
|
419 |
|
|
r_in <= v;
|
420 |
|
|
partition_count_out <= r.partition_count;
|
421 |
|
|
write_register <= vwrite_register;
|
422 |
|
|
load_mv <= vload_mv;
|
423 |
|
|
update <= vupdate;
|
424 |
|
|
rm_address <= vrm_address;
|
425 |
|
|
finish <= vfinish;
|
426 |
|
|
start_qp <= vstart_qp;
|
427 |
|
|
start_pipelines <= vstart_pipelines; --enable extra pipelines as required
|
428 |
|
|
partition_done <= vpartition_done;
|
429 |
|
|
instruction_zero <= vinstruction_zero;
|
430 |
|
|
|
431 |
|
|
end process control;
|
432 |
|
|
|
433 |
|
|
instruction_address <= r.instruction_address;
|
434 |
|
|
next_point <= r.point_address;
|
435 |
|
|
line_offset <= r.line_offset;
|
436 |
|
|
enable_hp_inter <= r.enable_hp_inter;
|
437 |
|
|
enable_concatenate_unit <= r_in.enable_concatenate_unit when r.enable_hp_inter = '0' else r.enable_concatenate_unit;
|
438 |
|
|
active_pipelines <= r.active_pipelines_r;
|
439 |
|
|
|
440 |
|
|
|
441 |
|
|
-- sequential part
|
442 |
|
|
|
443 |
|
|
regs: process (clk,clear)
|
444 |
|
|
|
445 |
|
|
begin
|
446 |
|
|
|
447 |
|
|
if (clear = '1') then
|
448 |
|
|
r.partition_count <= (others => '0');
|
449 |
|
|
r.state <= idle;
|
450 |
|
|
r.qp_mode <= '0';
|
451 |
|
|
r.instruction_address <= (others => '0');
|
452 |
|
|
r.point_count <= (others => '0');
|
453 |
|
|
r.point_address <= (others => '0');
|
454 |
|
|
r.phy_address <= (others => '0');
|
455 |
|
|
r.phy_address_ready <= (others => '0');
|
456 |
|
|
r.line_count <= (others => '0');
|
457 |
|
|
r.line_offset <= (others => '0');
|
458 |
|
|
r.points_tested <= (others => '0');
|
459 |
|
|
r.enable_hp_inter <= '0';
|
460 |
|
|
r.data_block <= (others => '0');
|
461 |
|
|
r.interpolation_done <= '0';
|
462 |
|
|
r.invalidate <= '0';
|
463 |
|
|
r.enable_concatenate_unit <= '0';
|
464 |
|
|
r.best_eu <= (others => '0');
|
465 |
|
|
r.active_pipelines_r <= (others => '0');
|
466 |
|
|
r.condition_bit <= '0';
|
467 |
|
|
-- r.calculate_sad_done <= '0';
|
468 |
|
|
elsif rising_edge(clk) then
|
469 |
|
|
if (reset = '1') then
|
470 |
|
|
r.partition_count <= (others => '0');
|
471 |
|
|
r.state <= idle;
|
472 |
|
|
r.invalidate <= '0';
|
473 |
|
|
r.qp_mode <= '0';
|
474 |
|
|
r.instruction_address <= (others => '0');
|
475 |
|
|
r.point_count <= (others => '0');
|
476 |
|
|
r.point_address <= (others => '0');
|
477 |
|
|
r.phy_address <= (others => '0');
|
478 |
|
|
r.best_eu <= (others => '0');
|
479 |
|
|
r.phy_address_ready <= (others => '0');
|
480 |
|
|
r.line_count <= (others => '0');
|
481 |
|
|
r.line_offset <= (others => '0');
|
482 |
|
|
r.points_tested <= (others => '0');
|
483 |
|
|
r.enable_hp_inter <= '0';
|
484 |
|
|
r.data_block <= (others => '0');
|
485 |
|
|
r.interpolation_done <= '0';
|
486 |
|
|
r.enable_concatenate_unit <= '0';
|
487 |
|
|
r.active_pipelines_r <= (others => '0');
|
488 |
|
|
r.condition_bit <= '0';
|
489 |
|
|
-- r.calculate_sad_done <= '0';
|
490 |
|
|
else
|
491 |
|
|
r <= r_in;
|
492 |
|
|
end if;
|
493 |
|
|
end if;
|
494 |
|
|
|
495 |
|
|
end process regs;
|
496 |
|
|
|
497 |
|
|
end;
|
498 |
|
|
|
499 |
|
|
|
500 |
|
|
|
501 |
|
|
|
502 |
|
|
|
503 |
|
|
|
504 |
|
|
|
505 |
|
|
|
506 |
|
|
|
507 |
|
|
|