660 likes | 725 Views
This tutorial explores Chroma-Key Blending, Sprite Generation, Pointer Sprite RAM, and blending methods for video enhancement in FPGA. Learn about blending modes, color conversion, and block diagrams for efficient design.
E N D
ECE 448 Lecture 13 FPro Video Subsystem:Sprite Core ECE 448 – FPGA and ASIC Design with VHDL
Required Reading • P. Chu, FPGA Prototyping by VHDL Examples • Chapter 21.2, FPro Video IP Core • Chapter 22, Sprite Core • Source Code of Examples • http://academic.csuohio.edu/chu_p/rtl/fpga_mcs_vhdl.html • Basys 3 FPGA Board Reference Manual7. VGA Port ECE 448 – FPGA and ASIC Design with VHDL
FPro System Memory Map 22-bit word space, 24-bit byte space 0x xxxxxxxxxmmmmmmaaaaa 64 MMIO Cores, each with 25-word address space 11 aaaaaaaaaaaaaaaaaaaa 1 Frame Buffer Core, with 220-word address space 10 xxxv vvaa aaaaaaaaaaaa 8 Video Cores, each with 214-word address space ECE 448 – FPGA and ASIC Design with VHDL
Two Types of FPro Video Cores e.g.. color-to-grayscale conversion ECE 448 – FPGA and ASIC Design with VHDL
Blending • A process to combine two video frames into a single frame • Two frames are treated as two vertical layers • Bottom layer: background frame • Top layer: foreground frame ECE 448 – FPGA and ASIC Design with VHDL
Chroma-Key Blending Foreground Frame Background Frame ECE 448 – FPGA and ASIC Design with VHDL
Chroma-Key Blending • A technique to display a selective region of foreground frame on top of the background frame • A special preselected color is defined as the chroma key • The chroma key is used as the “background color”of a foreground frame • When two frames are blended, the pixels with thewith the chroma key of the foreground frame are replaced by the corresponding pixels of the background frame ECE 448 – FPGA and ASIC Design with VHDL
Chroma-Key Blending • r = f if f ≠ CK • = b otherwise r – blended result f – color of a foreground pixel b – color of a background pixel CK – chroma key ECE 448 – FPGA and ASIC Design with VHDL
Chroma-Key Blending Foreground Frame Background Frame ECE 448 – FPGA and ASIC Design with VHDL
𝛼 Blending • r = 𝛼 ・ f + (1 - 𝛼) ・ b r – blended result f – color of a foreground pixel b – color of a background pixel 𝛼 – “opacity level” of the foreground frame 0.0 ≤ 𝛼 ≤ 1.0 1.0 opacity = only foreground color displayed 0.0 opacity = only background color displayed ECE 448 – FPGA and ASIC Design with VHDL
Chroma-Key 𝛼 Blending • r = 𝛼 ・ f + (1 - 𝛼) ・ b if f ≠ CK • = b otherwise r – blended result f – color of a foreground pixel b – color of a background pixel CK – chroma key 𝛼 – “opacity level” of the foreground frame 0.0 ≤ 𝛼 ≤ 1.0 1.0 opacity = only foreground color displayed 0.0 opacity = only background color displayed ECE 448 – FPGA and ASIC Design with VHDL
Mouse Pointer Sprite 12 pixels by 20 pixels ECE 448 – FPGA and ASIC Design with VHDL
Sprite • In computer graphics, a sprite is a small bitmap image that is integrated into a larger scene • A bitmap defines a rectangular area and the colorfor each pixel in the display area • A sprite is a small bitmap, for which a display areais a tiny fraction of the frame ECE 448 – FPGA and ASIC Design with VHDL
Block Diagram of a Sprite Generation Circuit ECE 448 – FPGA and ASIC Design with VHDL
Sprite RAM • Stores the pixel data of the bitmap • Memory word width = color depth • One dimensional array • address (xr, yr) = yr * Hs + xr • where the dimensions of the bitmap are Hs and Vs • Typically, Hs = 2h and Vs= 2v, and then • address (xr, yr) = yr << h + xr = yr || xr ECE 448 – FPGA and ASIC Design with VHDL
In-Region Comparison Screen x, y. : current x- and y- coordinates of the scan point x0, y0: the x- and y- coordinates of the top-left corner of the sprite xr, yr: the relative coordinates Hs, Vs: the horizontal and vertical dimensions of the sprite ECE 448 – FPGA and ASIC Design with VHDL
Pointer Sprite RAM To make the core more flexible, and facilitate future expansion, a larger 32-by-32 RAM is selected for construction. The unused portions are filled with the chroma-key color. For a color encoded using 12 bits 210 x 12 bit memory is used. ECE 448 – FPGA and ASIC Design with VHDL
Pointer Sprite RAM (1) library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity mouse_ram_lut is generic( ADDR_WIDTH: integer:=10; DATA_WIDTH:integer:=12 ); port( clk: in std_logic; we: in std_logic; addr_w: in std_logic_vector(ADDR_WIDTH-1 downto 0); addr_r: in std_logic_vector(ADDR_WIDTH-1 downto 0); din: in std_logic_vector(DATA_WIDTH-1 downto 0); dout: out std_logic_vector(DATA_WIDTH-1 downto 0) ); end mouse_ram_lut; ECE 448 – FPGA and ASIC Design with VHDL
Pointer Sprite RAM (2) architecture beh_arch of mouse_ram_lut is type ram_type is array (0 to 2**ADDR_WIDTH-1) of std_logic_vector (DATA_WIDTH-1 downto 0); -- pointer pattern constant INIT_MOUSE_LUT: ram_type:= ( x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"fff", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"fff", x"444", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", x"000", ……. ); ECE 448 – FPGA and ASIC Design with VHDL
Pointer Sprite RAM (3) signal ram: ram_type:=INIT_MOUSE_LUT; begin process(clk) begin if (clk'event and clk = '1') then if (we = '1') then ram(to_integer(unsigned(addr_w))) <= din; end if; dout <= ram(to_integer(unsigned(addr_r))); end if; end process; end beh_arch; ECE 448 – FPGA and ASIC Design with VHDL
Mouse Pixel Generation Circuit (1) library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity mouse_src is generic( CD : integer := 12; ADDR : integer := 10; KEY_COLOR : std_logic_vector(11 downto 0) := (others => '0') ); port( clk : std_logic; x, y : in std_logic_vector(10 downto 0); x0, y0 : in std_logic_vector(10 downto 0); we : in std_logic; addr_w : in std_logic_vector(9 downto 0); pixel_in : in std_logic_vector(CD - 1 downto 0); mouse_rgb : out std_logic_vector(CD - 1 downto 0) ); end mouse_src; ECE 448 – FPGA and ASIC Design with VHDL
Mouse Pixel Generation Circuit (2) architecture arch of mouse_src is -- sprite size constant H_SIZE : integer := 32; -- horizontal size of sprite constant V_SIZE : integer := 32; -- vertical size of sprite signal xr : signed(11 downto 0); -- relative x position signal yr : signed(11 downto 0); -- relative y position signal in_region : std_logic; signal addr_r : std_logic_vector(9 downto 0); signal full_rgb : std_logic_vector(CD - 1 downto 0); signal out_rgb : std_logic_vector(CD - 1 downto 0); signal out_rgb_d1_reg : std_logic_vector(CD - 1 downto 0); ECE 448 – FPGA and ASIC Design with VHDL
Mouse Pixel Generation Circuit (3) begin -- instantiate sprite RAM slot_ram_unit : entity work.mouse_ram_lut generic map( ADDR_WIDTH => ADDR, DATA_WIDTH => CD ) port map( clk => clk, we => we, addr_w => addr_w, din => pixel_in, addr_r => addr_r, dout => full_rgb ); ECE 448 – FPGA and ASIC Design with VHDL
Mouse Pixel Generation Circuit (4) addr_r <= std_logic_vector(yr(4 downto 0) & xr(4 downto 0)); xr <= signed('0' & x) - signed('0' & x0); yr <= signed('0' & y) - signed('0' & y0); in_region <= '1' when (0 <= xr) and (xr < H_SIZE) and (0 <= yr) and (yr < V_SIZE) else '0'; out_rgb <= full_rgb when in_region = '1' else KEY_COLOR; process(clk) begin if (clk'event and clk = '1') then out_rgb_d1_reg <= out_rgb; end if; end process; mouse_rgb <= out_rgb_d1_reg; end arch; ECE 448 – FPGA and ASIC Design with VHDL
Mouse Pointer Core – Register Map 0x xxaaaaaaaaaa 210 x 12 Sprite RAM 1x xxxxxxxx xx00 bit 0: bypass bit 1x xxxxxxxx xx01 bits 9 downto 0: x0 register 1x xxxxxxxx xx01 bits 9 downto 0: y0 register ECE 448 – FPGA and ASIC Design with VHDL
Mouse Pointer Core (1) library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity chu_vga_slot_mouse_core is generic( CD : integer := 12; ADDR_WIDTH : integer := 10; KEY_COLOR : std_logic_vector(11 downto 0) := (others => '0') ); ECE 448 – FPGA and ASIC Design with VHDL
Mouse Pointer Core (2) port( clk : in std_logic; reset : in std_logic; x : in std_logic_vector(10 downto 0); y : in std_logic_vector(10 downto 0); cs : in std_logic; write : in std_logic; addr : in std_logic_vector(13 downto 0); wr_data : in std_logic_vector(31 downto 0); si_rgb : in std_logic_vector(CD - 1 downto 0); so_rgb : out std_logic_vector(CD - 1 downto 0) ); end chu_vga_slot_mouse_core; ECE 448 – FPGA and ASIC Design with VHDL
Mouse Pointer Core (3) architecture arch of chu_vga_slot_mouse_core is signal wr_en : std_logic; signal wr_ram : std_logic; signal wr_reg : std_logic; signal wr_bypass : std_logic; signal wr_x0 : std_logic; signal wr_y0 : std_logic; signal x0_reg : std_logic_vector(10 downto 0); signal y0_reg : std_logic_vector(10 downto 0); signal bypass_reg : std_logic; signal mouse_rgb : std_logic_vector(CD - 1 downto 0); signal chrom_rgb : std_logic_vector(CD - 1 downto 0); ECE 448 – FPGA and ASIC Design with VHDL
Mouse Pointer Core (4) begin slot_unit : entity work.mouse_src generic map( CD => 12, KEY_COLOR => (others => '0') ) port map( clk => clk, x => x, y => y, x0 => x0_reg, y0 => y0_reg, we => wr_ram, addr_w => addr(ADDR_WIDTH - 1 downto 0), pixel_in => wr_data(CD - 1 downto 0), mouse_rgb => mouse_rgb ); ECE 448 – FPGA and ASIC Design with VHDL
Mouse Pointer Core (5) -- registers and decoding process(clk, reset) begin if reset = '1' then x0_reg <= (others => '0'); y0_reg <= (others => '0'); elsif (clk'event and clk = '1') then if wr_x0 = '1' then x0_reg <= wr_data(10 downto 0); end if; if wr_y0 = '1' then y0_reg <= wr_data(10 downto 0); end if; if wr_bypass = '1' then bypass_reg <= wr_data(0); end if; end if; end process; ECE 448 – FPGA and ASIC Design with VHDL
Mouse Pointer Core (6) wr_en <= '1' when write = '1' and cs = '1' else '0'; wr_ram <= '1' when addr(13) = '0' and wr_en = '1' else '0'; wr_reg <= '1' when addr(13) = '1' and wr_en = '1' else '0'; wr_bypass <= '1' when wr_reg='1' and addr(1 downto 0)="00" else '0'; wr_x0 <= '1' when wr_reg='1' and addr(1 downto 0)="01" else '0'; wr_y0 <= '1' when wr_reg='1' and addr(1 downto 0)="10" else '0'; -- chroma-key blending and multiplexing chrom_rgb <= mouse_rgb when mouse_rgb /= KEY_COLOR else si_rgb; so_rgb <= si_rgb when bypass_reg = '1' else chrom_rgb; end arch; ECE 448 – FPGA and ASIC Design with VHDL
Mouse Pointer Core – Register Map 0x xxaaaaaaaaaa 210 x 12 Sprite RAM 1x xxxxxxxx xx00 bit 0: bypass bit 1x xxxxxxxx xx01 bits 9 downto 0: x0 register 1x xxxxxxxx xx01 bits 9 downto 0: y0 register ECE 448 – FPGA and ASIC Design with VHDL
Animation • Process to make the illusion of motion by rapidlypresenting a sequence of slightly modified images • Frame rate specifies the speed with which the images are to be presented, expressed as the number of images (frames) per second • 10 frames per second is a good starting point ECE 448 – FPGA and ASIC Design with VHDL
Ghost Sprites 16 pixels by 64 pixels ECE 448 – FPGA and ASIC Design with VHDL
Palette Coding of the Ghost Images 210 by 12 RAM can be replaced by 210 x 2 RAM ECE 448 – FPGA and ASIC Design with VHDL
Ghost RAM (1) library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity ghost_ram_lut is generic( ADDR_WIDTH : integer := 10; DATA_WIDTH : integer := 2 ); port( clk : in std_logic; we : in std_logic; addr_w : in std_logic_vector(ADDR_WIDTH - 1 downto 0); addr_r : in std_logic_vector(ADDR_WIDTH - 1 downto 0); din : in std_logic_vector(DATA_WIDTH - 1 downto 0); dout : out std_logic_vector(DATA_WIDTH - 1 downto 0) ); end ghost_ram_lut; ECE 448 – FPGA and ASIC Design with VHDL
Ghost RAM (2) architecture beh_arch of ghost_ram_lut is type ram_type is array (0 to 2 ** ADDR_WIDTH - 1) of std_logic_vector(DATA_WIDTH - 1 downto 0); constant INIT_GHOST_LUT : ram_type := ( -- ghost sprite #0 "00", "00", "00", "00", "00", "00", "00", "00", "00", "00", "00", "00", "00", "00", "00", "00", "00", "00", "00", "00", "00", "00", "10", "10", "10", "10", "00", "00", "00", "00", "00", "00", "00", "00", "00", "00", "10", "10", "10", "10", "10", "10", "10", "10", "00", "00", "00", "00", "00", "00", "00", "10", "10", "10", "10", "10", "10", "10", "10", "10", "10", "00", "00", "00", …. -- ghost sprite #1 …. -- ghost sprite #2 …. -- ghost sprite #3 …. ); ECE 448 – FPGA and ASIC Design with VHDL
Ghost RAM (3) signal ram : ram_type := INIT_GHOST_LUT; begin process(clk) begin if (clk'event and clk = '1') then if (we = '1') then ram(to_integer(unsigned(addr_w))) <= din; end if; dout <= ram(to_integer(unsigned(addr_r))); end if; end process; end beh_arch; ECE 448 – FPGA and ASIC Design with VHDL
Ghost Pixel Generation Circuit (1) library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity ghost_src is generic( CD : integer := 12; ADDR : integer := 10; KEY_COLOR : std_logic_vector(11 downto 0) := (others => '0') ); port( clk : std_logic; x, y, x0, y0 : in std_logic_vector(10 downto 0); ctrl : in std_logic_vector(4 downto 0); we : in std_logic; addr_w : in std_logic_vector(9 downto 0); pixel_in : in std_logic_vector(1 downto 0); sprite_rgb : out std_logic_vector(CD - 1 downto 0) ); end ghost_src; ECE 448 – FPGA and ASIC Design with VHDL
Ghost Pixel Generation Circuit (2) architecture arch of ghost_src is constant H_SIZE : integer := 16; -- horizontal size of sprite constant V_SIZE : integer := 16; -- vertical size of sprite signal addr_r : std_logic_vector(9 downto 0); signal sid : std_logic_vector(1 downto 0); -- sprite id signal xr : signed(11 downto 0); -- sprite x position signal yr : signed(11 downto 0); -- sprite y position signal in_region : std_logic; signal plt_code : std_logic_vector(1 downto 0); signal frame_tick : std_logic; signal ani_tick : std_logic; signal c_reg : unsigned(3 downto 0); signal c_next : unsigned(3 downto 0); ECE 448 – FPGA and ASIC Design with VHDL
Ghost Pixel Generation Circuit (3) signal ani_reg : unsigned(1 downto 0); signal ani_next : unsigned(1 downto 0); signal x_d1_reg : std_logic_vector(10 downto 0); signal full_rgb : std_logic_vector(CD - 1 downto 0); signal ghost_rgb : std_logic_vector(CD - 1 downto 0); signal out_rgb : std_logic_vector(CD - 1 downto 0); signal out_d1_reg : std_logic_vector(CD - 1 downto 0); alias gc_color_sel : std_logic_vector(1 downto 0) is ctrl(4 downto 3); alias auto : std_logic is ctrl(2); alias gc_id_sel : std_logic_vector(1 downto 0) is ctrl(1 downto 0); ECE 448 – FPGA and ASIC Design with VHDL
Ghost Pixel Generation Circuit (4) begin -- sprite RAM slot_ram_unit : entity work.ghost_ram_lut generic map( ADDR_WIDTH => ADDR, DATA_WIDTH => 2 ) port map( clk => clk, we => we, addr_w => addr_w, din => pixel_in, addr_r => addr_r, dout => plt_code ); addr_r <= sid & std_logic_vector(yr(3 downto 0) & xr(3 downto 0)); ECE 448 – FPGA and ASIC Design with VHDL
Ghost Pixel Generation Circuit (5) -- ghost color control with gc_color_sel select ghost_rgb <= x"f00" when "00", -- red x"f8b" when "01", -- pink x"fa0" when "10", -- orange x"0ff" when others; -- cyan -- palette table with plt_code select full_rgb <= x"000" when "00", -- chrome key x"111" when "01", -- dark gray ghost_rgb when "10", -- ghost body color x"fff" when others; -- white ECE 448 – FPGA and ASIC Design with VHDL
Palette Coding of the Ghost Images 210 by 12 RAM can be replaced by 210 x 2 RAM ECE 448 – FPGA and ASIC Design with VHDL
Ghost Pointer Core – Register Map 1x xxxxxxxx xx11 bits 4 downto 3: selection of the ghost color bit 2: selection of mode; 1 – animation mode, 0 - still mode bits 1 downto 0: selection of specific sprite in still mode ECE 448 – FPGA and ASIC Design with VHDL
Ghost Pixel Generation Circuit (6) -- in-region circuit xr <= signed('0' & x) - signed('0' & x0); yr <= signed('0' & y) - signed('0' & y0); in_region <= '1' when (0 <= xr) and (xr < H_SIZE) and (0 <= yr) and (yr < V_SIZE) else '0'; out_rgb <= full_rgb when in_region = '1' else KEY_COLOR; -- animation timing control process(clk) begin if (clk'event and clk = '1') then x_d1_reg <= x; c_reg <= c_next; ani_reg <= ani_next; end if; end process; ECE 448 – FPGA and ASIC Design with VHDL
Ghost Pixel Generation Circuit (7) c_next <= (others => '0') when frame_tick='1' and c_reg=9 else c_reg +1 when frame_tick='1' else c_reg; ani_next <= ani_reg + 1 when ani_tick='1' else ani_reg; -- 60-Hz tick from from counter frame_tick <= '1' when signed(x_d1_reg) = 0 and signed(x) = 1 and signed(y) = 0 else '0'; -- sprite animation id tick ani_tick <= '1' when frame_tick = '1' and c_reg = 0 else '0'; -- sprite id selection sid <= std_logic_vector(ani_reg) when auto = '1' else gc_id_sel; ECE 448 – FPGA and ASIC Design with VHDL
Ghost Pixel Generation Circuit (8) -- delay line (one clock) process(clk) begin if (clk'event and clk = '1') then out_d1_reg <= out_rgb; end if; end process; sprite_rgb <= out_d1_reg; end arch; ECE 448 – FPGA and ASIC Design with VHDL