------------------------------------------------------------------------------- -- -- File : rgb3sx8_to_ycbcr_3DSP.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 YCrCb -- -- 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 values on ycrcb_out are produced in the following -- order: cb, cr, y -- They are computed using ITU-R BT.601 conversion principles, -- assuming that RGB component are digital and thus rangin -- from 0 to 255. Formulas are: -- Y = 16 + 65.738R/256 + 129.057G/256 + 25.064B/256 -- Cb = 128 - 37.945R/256 - 74.494G/256 + 112.439B/256 -- Cr = 128 + 112.439R/256 - 94.154G/256 - 18.285B/256 -- ------------------------------------------------------------------------------- library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; entity rgb3sx8_to_ycbcr_3DSP is port( clk : in std_logic; reset : in std_logic; rgb_in : in std_logic_vector(7 downto 0); rgb_in_enb : in std_logic; ycbcr_out : out std_logic_vector(7 downto 0); ycbcr_out_enb : out std_logic ); end rgb3sx8_to_ycbcr_3DSP; architecture rtl of rgb3sx8_to_ycbcr_3DSP is component mult_accum port ( clk : in std_logic; ce : in std_logic; sclr : in std_logic; bypass : in std_logic; a : in std_logic_vector(17 downto 0); b : in std_logic_vector(17 downto 0); s : out std_logic_vector(47 downto 0) ); end component; -- Signals signal do_sum_y : std_logic; signal do_sum_y_dly : std_logic; signal do_sum_cr : std_logic; signal do_sum_cr_dly : std_logic; signal do_sum_cb : std_logic; signal do_sum_cb_dly : std_logic; signal do_out : std_logic; signal do_out_cr : std_logic; signal do_out_cb : std_logic; signal do_out_y : std_logic; signal count_y : unsigned (2 downto 0); signal count_cr : unsigned (2 downto 0); signal count_cb : unsigned (2 downto 0); signal y : signed(8 downto 0); signal y_dly1 : signed(8 downto 0); signal y_dly2 : signed(8 downto 0); signal cb : signed(8 downto 0); signal cb_dly1 : signed(8 downto 0); signal cr : signed(8 downto 0); signal cst_y_r : signed(17 downto 0); signal cst_y_g : signed(17 downto 0); signal cst_y_b : signed(17 downto 0); signal cst_cb_r : signed(17 downto 0); signal cst_cb_g : signed(17 downto 0); signal cst_cb_b : signed(17 downto 0); signal cst_cr_r : signed(17 downto 0); signal cst_cr_g : signed(17 downto 0); signal cst_cr_b : signed(17 downto 0); signal bypass_y : std_logic; signal a_y : std_logic_vector(17 downto 0); signal b_y : std_logic_vector(17 downto 0); signal s_y : std_logic_vector(47 downto 0); signal bypass_cr : std_logic; signal a_cr : std_logic_vector(17 downto 0); signal b_cr : std_logic_vector(17 downto 0); signal s_cr : std_logic_vector(47 downto 0); signal bypass_cb : std_logic; signal a_cb : std_logic_vector(17 downto 0); signal b_cb : std_logic_vector(17 downto 0); signal s_cb : std_logic_vector(47 downto 0); signal compo_out : std_logic_vector(7 downto 0); begin y_multiplier : mult_accum port map ( clk => clk, ce => '1', sclr => '0', bypass => bypass_y, a => a_y, b => b_y, s => s_y ); cr_multiplier : mult_accum port map ( clk => clk, ce => '1', sclr => '0', bypass => bypass_cr, a => a_cr, b => b_cr, s => s_cr ); cb_multiplier : mult_accum port map ( clk => clk, ce => '1', sclr => '0', bypass => bypass_cb, a => a_cb, b => b_cb, s => s_cb ); cst_y_r <= to_signed(33658, 18); cst_y_g <= to_signed(66077, 18); cst_y_b <= to_signed(12833, 18); cst_cb_r <= to_signed(-19428, 18); cst_cb_g <= to_signed(-38141, 18); cst_cb_b <= to_signed(57569, 18); cst_cr_r <= to_signed(57569, 18); cst_cr_g <= to_signed(-48207, 18); cst_cr_b <= to_signed(-9362, 18); multy_process : process (clk, reset) begin if reset = '1' then a_y <= (others => '0'); b_y <= (others => '0'); count_y <= to_unsigned(0, 3); do_sum_y <= '0'; elsif rising_edge(clk) then do_sum_y <= '0'; a_y <= (others => '0'); b_y <= (others => '0'); if rgb_in_enb = '1' then a_y <= "0000000000" & rgb_in; if count_y = 0 then b_y <= std_logic_vector(cst_y_b); count_y <= to_unsigned(1, 3); elsif count_y = 1 then b_y <= std_logic_vector(cst_y_g); count_y <= to_unsigned(2, 3); elsif count_y = 2 then b_y <= std_logic_vector(cst_y_r); count_y <= to_unsigned(0, 3); do_sum_y <= '1'; end if; end if; end if; end process multy_process; sumy_process : process (clk, reset) begin if reset = '1' then bypass_y <= '0'; y <= to_signed(0, 9); y_dly1 <= to_signed(0, 9); y_dly2 <= to_signed(0, 9); elsif rising_edge(clk) then bypass_y <= do_sum_y; do_sum_y_dly <= do_sum_y; y_dly1 <= y; y_dly2 <= y_dly1; if do_sum_y_dly = '1' then y <= to_signed(16, 9) + signed(s_y(25 downto 17)); end if; end if; end process sumy_process; multcb_process : process (clk, reset) begin if reset = '1' then a_cb <= (others => '0'); b_cb <= (others => '0'); count_cb <= to_unsigned(0, 3); do_sum_cb <= '0'; elsif rising_edge(clk) then do_sum_cb <= '0'; a_cb <= (others => '0'); b_cb <= (others => '0'); if rgb_in_enb = '1' then a_cb <= "0000000000" & rgb_in; if count_cb = 0 then b_cb <= std_logic_vector(cst_cb_b); count_cb <= to_unsigned(1, 3); elsif count_cb = 1 then b_cb <= std_logic_vector(cst_cb_g); count_cb <= to_unsigned(2, 3); elsif count_cb = 2 then b_cb <= std_logic_vector(cst_cb_r); count_cb <= to_unsigned(0, 3); do_sum_cb <= '1'; end if; end if; end if; end process multcb_process; sumcb_process : process (clk, reset) begin if reset = '1' then bypass_cb <= '0'; cb <= to_signed(0, 9); cb_dly1 <= to_signed(0, 9); elsif rising_edge(clk) then bypass_cb <= do_sum_cb; do_sum_cb_dly <= do_sum_cb; cb_dly1 <= cb; if do_sum_cb_dly = '1' then cb <= to_signed(128, 9) + signed(s_cb(25 downto 17)); end if; end if; end process sumcb_process; multcr_process : process (clk, reset) begin if reset = '1' then a_cr <= (others => '0'); b_cr <= (others => '0'); count_cr <= to_unsigned(0, 3); do_sum_cr <= '0'; elsif rising_edge(clk) then do_sum_cr <= '0'; a_cr <= (others => '0'); b_cr <= (others => '0'); if rgb_in_enb = '1' then a_cr <= "0000000000" & rgb_in; if count_cr = 0 then b_cr <= std_logic_vector(cst_cr_b); count_cr <= to_unsigned(1, 3); elsif count_cr = 1 then b_cr <= std_logic_vector(cst_cr_g); count_cr <= to_unsigned(2, 3); elsif count_cr = 2 then b_cr <= std_logic_vector(cst_cr_r); count_cr <= to_unsigned(0, 3); do_sum_cr <= '1'; end if; end if; end if; end process multcr_process; sumcr_process : process (clk, reset) begin if reset = '1' then bypass_cr <= '0'; cr <= to_signed(0, 9); do_out_cr <= '0'; elsif rising_edge(clk) then bypass_cr <= do_sum_cr; do_sum_cr_dly <= do_sum_cr; do_out_cr <= '0'; if do_sum_cr_dly = '1' then do_out_cr <= '1'; cr <= to_signed(128, 9) + signed(s_cr(25 downto 17)); end if; end if; end process sumcr_process; out_process : process (clk, reset) begin if reset = '1' then do_out_y <= '0'; do_out_cb <= '0'; elsif rising_edge(clk) then do_out_cb <= do_out_cr; do_out_y <= do_out_cb; end if; end process out_process; ycbcr_out <= std_logic_vector(y_dly2(7 downto 0)) when do_out_y = '1' else std_logic_vector(cb_dly1(7 downto 0)) when do_out_cb = '1' else std_logic_vector(cr(7 downto 0)) when do_out_cr = '1' else (others => '0'); ycbcr_out_enb <= do_out_y or do_out_cb or do_out_cr; end rtl;