Example: Video
Video.VHD
------------------------------------------------------- -- A Video Frame Grabber. -- -- This circuit was first described in "Practical Design -- Using Programmable Logic" by David Pellerin and Michael -- Holley (Prentice Hall, 1990). A slightly modified form -- of the circuit also appears in the ATMEL Configurable -- Logic Design and Application Book, 1993-1994 edition. -- -- The circuit described is a simple freeze-frame unit that -- 'grabs' and holds a single frame of NTSC color video -- image. This design description includes the frame detection -- and capture logic. The complete circuit requires an 8-bit -- D-A/A-D converter and a 256K X 8 static RAM. -- Library ieee; Use ieee.std_logic_1164.all; Use ieee.numeric_std.all; Entity CONTROL Is Port ( Reset: in std_logic; Clk: in std_logic; Mode: in std_logic; Data: in std_logic_vector(7 downto 0); TestLoad: in std_logic; Addr: out std_logic_vector(17 downto 0); RAMWE: out std_logic; RAMOE: out std_logic; ADOE: out std_logic ); End CONTROL; Architecture CONTROL_A of CONTROL Is constant FRAMESIZE: integer := 253243; constant TESTADDR: integer := 253000; signal ENDFR: std_logic; signal INCAD: std_logic; signal VS: std_logic; signal Sync: unsigned (7 downto 0); type states is (StateLive,StateWait,StateSample,StateDisplay); signal current_state, next_state: states; Begin -- Address counter. This counter increments until we reach the end of -- the frame (address 253243), or until the input INCAD goes low. ADDRCTR: process(Clk) variable cnt: unsigned (17 downto 0); begin if rising_edge(Clk) then if TestLoad = '1' then cnt := to_unsigned(TESTADDR,18); ENDFR <= '0'; else if INCAD = '0' or cnt = to_unsigned(FRAMESIZE,18) then cnt := (others => '0'); else cnt := cnt + 1; end if; if cnt = FRAMESIZE then ENDFR <= '1'; else ENDFR <= '0'; end if; end if; end if; Addr <= std_logic_vector(cnt); end process; -- Vertical sync detector. Here we look for 128 bits of zero, which -- indicates the vertical sync blanking interval. SYNCCTR: process(Reset,Clk) begin if Reset = '1' then Sync <= (others => '0'); elsif rising_edge(Clk) then if Data /= "00000000" or Sync = to_unsigned(127,7) then Sync <= (others => '0'); else Sync <= Sync + 1; end if; end if; end process; VS <= '1' when Sync = to_unsigned(127,7) else '0'; -- State register process: STREG: process(Reset,Clk) begin if Reset = '1' then current_state <= StateLive; elsif rising_edge(Clk) then current_state <= next_state; end if; end process; -- State transitions: STTRANS: process(current_state,Mode,VS,ENDFR) begin case current_state is when StateLive => -- Display live video on the output RAMWE <= '1'; RAMOE <= '1'; ADOE <= '0'; INCAD <= '0'; if Mode = '1' then next_state <= StateWait; end if; when StateWait => -- Wait for vertical sync RAMWE <= '1'; RAMOE <= '1'; ADOE <= '0'; INCAD <= '0'; if VS = '1' then next_state <= StateSample; end if; when StateSample => -- Sample one frame of video RAMWE <= '0'; RAMOE <= '1'; ADOE <= '0'; INCAD <= '1'; if ENDFR = '1' then next_state <= StateDisplay; end if; when StateDisplay => -- Display the stored frame RAMWE <= '1'; RAMOE <= '0'; ADOE <= '1'; INCAD <= '1'; if Mode = '1' then next_state <= StateLive; end if; end case; end process; End CONTROL_A;
Vtest.VHD
----------------------------------------------------------- -- Video frame grabber test bench -- library ieee; Use ieee.std_logic_1164.all; Use ieee.numeric_std.all; Use std.textio.all; use work.all; Entity T_CONTROL Is End Entity T_CONTROL; Architecture stimulus of T_CONTROL Is Component CONTROL is Port ( Reset: in std_logic; Clk: in std_logic; Mode: in std_logic; Data: in std_logic_vector(7 downto 0); TestLoad: in std_logic; Addr: out std_logic_vector(17 downto 0); RAMWE: out std_logic; RAMOE: out std_logic; ADOE: out std_logic ); End Component CONTROL; Constant PERIOD: time := 100 ns; -- Top level signals go here... Signal Reset: std_logic; Signal Clk: std_logic; Signal Mode: std_logic; Signal Data: std_logic_vector(7 downto 0); Signal TestLoad: std_logic; Signal Addr: std_logic_vector(17 downto 0); Signal RAMWE: std_logic; Signal RAMOE: std_logic; Signal ADOE: std_logic; Signal done: boolean := false; Begin DUT: CONTROL Port Map ( Reset => Reset, Clk => Clk, Mode => Mode, Data => Data, TestLoad => TestLoad, Addr => Addr, RAMWE => RAMWE, RAMOE => RAMOE, ADOE => ADOE ); Clock1: process variable clktmp: std_logic := '0'; begin wait for PERIOD/2; clktmp := not clktmp; Clk <= clktmp; -- Attach your clock here if done = true then wait; end if; end process Clock1; Stimulus1: Process Begin -- Sequential stimulus goes here... Reset <= '1'; Mode <= '0'; Data <= "00000000"; TestLoad <= '0'; wait for PERIOD; Reset <= '0'; wait for PERIOD; Data <= "00000001"; wait for PERIOD; Mode <= '1'; -- Check to make sure we detect the vertical sync... Data <= "00000000"; for i in 0 to 127 loop wait for PERIOD; end loop; -- Now sample data to make sure the frame counter works... Data <= "01010101"; for i in 0 to 100000 loop wait for PERIOD; end loop; -- Load in the test value to check the end of frame detection... TestLoad <= '1'; wait for PERIOD; TestLoad <= '0'; for i in 0 to 300 loop wait for PERIOD; end loop; done <= true; End Process Stimulus1; End architecture stimulus;