------------------------------------------------------------------------------- -- -- File : rgb3sx8_to_gs.vhd -- Related files : -- -- Author(s) : stephane Domas (sdomas@univ-fcomte.fr) -- -- Creation Date : 2017/10/16 -- -- Description : This IP does a conversion from rgb24 (8 bits/serial) to grayscale -- -- Note : rgb24 (8 bits/serial) pixels are composed of three 8 bits -- values that are consumed on port rgb_in, in the following -- order : blue, green, red. -- output value on gs_out is computed with (red+green+blue)/3 -- ------------------------------------------------------------------------------- library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; entity rgb3sx8_to_gs is generic( dsp_in_width : natural := 18; dsp_out_width : natural := 36 ); port( clk : in std_logic; reset : in std_logic; rgb_in : in std_logic_vector(7 downto 0); rgb_in_enb : in std_logic; gs_out : out std_logic_vector(7 downto 0); gs_out_enb : out std_logic ); end rgb3sx8_to_gs; architecture rtl of rgb3sx8_to_gs is -- Signals signal do_mult : std_logic; signal do_out : std_logic; signal count : unsigned (2 downto 0); signal accum : unsigned(dsp_in_width-1 downto 0); signal result : unsigned(dsp_out_width-1 downto 0); signal cst_mult : unsigned(dsp_in_width-1 downto 0); -- eq. 87382 to do /3 begin cst_mult <= to_unsigned(87382, 18); accum_process : process (clk, reset) begin if reset = '1' then count <= to_unsigned(0, 3); accum <= to_unsigned(0, dsp_in_width); do_mult <= '0'; elsif rising_edge(clk) then do_mult <= '0'; if rgb_in_enb = '1' then if count = 0 then accum <= resize(unsigned(rgb_in), dsp_in_width); count <= to_unsigned(1, 3); elsif count = 1 then accum <= accum + resize(unsigned(rgb_in), dsp_in_width); count <= to_unsigned(2, 3); elsif count = 2 then accum <= accum + resize(unsigned(rgb_in), dsp_in_width); count <= to_unsigned(0, 3); do_mult <= '1'; end if; end if; end if; end process accum_process; mult_process : process (clk, reset) begin if reset = '1' then result <= to_unsigned(0, dsp_out_width); do_out <= '0'; elsif rising_edge(clk) then do_out <= '0'; if do_mult = '1' then result <= accum * cst_mult; do_out <= '1'; end if; end if; end process mult_process; gs_out <= std_logic_vector(result(dsp_in_width+7 downto dsp_in_width)); gs_out_enb <= do_out; end rtl;