23-05-2011, 10:29 AM
(This post was last modified: 23-05-2011, 10:34 AM by ppppenguin.)
It's a bit garbled by the formatting in the forum but here's a fragment of VHDL from a current project. It's all synchronous, with a clock enable (CE) covering everything so that it will run from a common 148.5MHz clock for all digital TV standards, whether they need 148.5MHz, 74.25MHz or 13.5MHz. I haven't put in all the declarations for signals, IO etc. I've put in some extra bold comments for illustration. If you are coming to this from a software background remember that all statements on the same clock execute concurrently, not sequentially as you would expect in C, Basic etc. The order of statements in many cases is irrelevant in VHDL. The VHDL compiler does a lot of optimising to give efficient usage. If your VHDL style is good, this helps the compiler to get a nice looking answer. Poor VHDL style can use more logic than needed, low maximum clokc speeds and other woes even if the logic is actually technically correct.
Code:
process (CK) begin
if rising_edge(CK) then
if CE='1' then
[b]-- This is a JK (strictly RS) flipflop[/b]
-- Define H inner window (1 pixel wide), H outer window (variable) and half line
-- Probable HLOCK_POINT is 26, probable outer window 24/27 to give 3 pix wide around lock point
if HBLANK_END(HLOCK_OUTER_WINDOW_START) = '1' then OUTER_H_WINDOW <= true;
elsif HBLANK_END(HLOCK_OUTER_WINDOW_END) = '1' then OUTER_H_WINDOW <= false;
else OUTER_H_WINDOW <= OUTER_H_WINDOW;
end if;
INNER_H_WINDOW <= HBLANK_END(HLOCK_POINT) = '1'; -- Not really a window, just 1 pixel wide
-- Half line goes low at lock point, goes high halfway through line
if HBLANK_END(HLOCK_POINT) = '1' then HALF_LINE <= false;
elsif (HCOUNT = HLOCK_MID_LINE) then HALF_LINE <= true;
else HALF_LINE <= HALF_LINE;
end if;
-- Some operations happen at the timing reference. Windows etc are sampled, decisions about HMAX/VMAX are made.
if DELAYED_SELECTED_TIMING_REF then
-- Determine H lock status by sampling inner and outer H windows
if INNER_H_WINDOW then H_LOCKED <= true; -- Within inner window hence locked
elsif H_LOCKED and OUTER_H_WINDOW then H_LOCKED <= true; -- Already locked but strayed into outer window so stay locked
else H_LOCKED <= false; -- Outside windows so not locked
end if;
-- H_ALMOST_LOCKED occurs when approaching lock
if OUTER_H_WINDOW and not H_LOCKED then H_ALMOST_LOCKED <= true; -- Within outer window but not locked
else H_ALMOST_LOCKED <= false; -- Totally unlocked
end if;
-- Determine V lock status by sampling V window which is exactly one line long
if V_WINDOW then V_LOCKED <= true; -- Within window hence locked
else V_LOCKED <= false; -- Outside window so not locked
end if;
end if; --DELAYED_SELECTED_TIMING_REF
[b]-- A load of "random" logic, expressed in a comprehensible way[/b]
-- Determine H lock direction and speed
if MANUAL_H_LOCK_UP then HMAX_OFFSET <= H_LOCK_RATE;
elsif MANUAL_H_LOCK_DOWN then HMAX_OFFSET <= - H_LOCK_RATE;
elsif LOCK_ENABLE and H_LOCK_ENABLE and not H_LOCKED and H_ALMOST_LOCKED and not HALF_LINE then HMAX_OFFSET <= 1; -- Slow approach when almost locked
elsif LOCK_ENABLE and H_LOCK_ENABLE and not H_LOCKED and H_ALMOST_LOCKED and HALF_LINE then HMAX_OFFSET <= -1;
elsif LOCK_ENABLE and H_LOCK_ENABLE and not H_LOCKED and not H_ALMOST_LOCKED and not HALF_LINE then HMAX_OFFSET <= H_LOCK_RATE; -- Otherwise fast approach
elsif LOCK_ENABLE and H_LOCK_ENABLE and not H_LOCKED and not H_ALMOST_LOCKED and HALF_LINE then HMAX_OFFSET <= - H_LOCK_RATE;
else HMAX_OFFSET <= 0;
end if;
-- Only do H correction on specified line
if VERT_CE then -- These run with vertical CE
if (VCOUNT = HLOCK_CORRECTION_LINE) then OFFSET_HMAX_VALUE <= HMAX_VALUE + HMAX_OFFSET mod 8192;
else OFFSET_HMAX_VALUE <= HMAX_VALUE;
end if;
end if; -- VERT_CE
-- Determine V lock direction
if MANUAL_V_LOCK_UP then VMAX_OFFSET <= 1;
elsif MANUAL_V_LOCK_DOWN then VMAX_OFFSET <= -1;
elsif LOCK_ENABLE and V_LOCK_ENABLE and not V_LOCKED and not HALF_FRAME then VMAX_OFFSET <= 1;
elsif LOCK_ENABLE and V_LOCK_ENABLE and not V_LOCKED and HALF_FRAME then VMAX_OFFSET <= -1;
else VMAX_OFFSET <= 0;
end if;
OFFSET_VMAX_VALUE <= VMAX_VALUE + VMAX_OFFSET mod 2048;
end if; --CE
end if; --CK
end process;
--====================================================================================================================
------------------------------------ Horizontal count ----------------------------------------------------------------
process (CK) begin
if rising_edge(CK) then
if CE='1' then --These run with standard CE (13.5MHz/74.25MHz/1)
[b]-- A 13 bit counter with sync reset [/b]
--Central horizontal 13 bit counter. Line length up to 4125 pixels
if HRESET then HCOUNT <= 0; -- Reset at terminal count
else HCOUNT <= HCOUNT + 1 MOD 8192; -- MOD not essential for symthesis but vital for simulation
end if;
-- H counter reset with double pipeline
EARLY_HRESET <= (HCOUNT = OFFSET_HMAX_VALUE); -- EARLY_HRESET used for 3GHz VERT_CE
HRESET <= EARLY_HRESET; -- HRESET used for SD/HD VERT_CE
www.borinsky.co.uk Jeffrey Borinsky www.becg.tv







