From c712b160cc694606c47b93ece22fc4ba8658c0ae Mon Sep 17 00:00:00 2001 From: Davide Date: Fri, 11 Apr 2025 13:00:46 +0200 Subject: [PATCH] Refactor RGB to Grayscale conversion: update divider component and add testbench --- LAB2/sim/tb_rgb2gray.vhd | 102 ++++++++++ LAB2/src/divider_by_3.vhd | 16 +- LAB2/src/rgb2gray.vhd | 36 ++-- LAB2/vivado/rgb2grey_test/rgb2grey_test.xpr | 211 ++++++++++++++++++++ 4 files changed, 336 insertions(+), 29 deletions(-) create mode 100644 LAB2/sim/tb_rgb2gray.vhd create mode 100644 LAB2/vivado/rgb2grey_test/rgb2grey_test.xpr diff --git a/LAB2/sim/tb_rgb2gray.vhd b/LAB2/sim/tb_rgb2gray.vhd new file mode 100644 index 0000000..f742af1 --- /dev/null +++ b/LAB2/sim/tb_rgb2gray.vhd @@ -0,0 +1,102 @@ +-- Testbench for rgb2gray +LIBRARY IEEE; +USE IEEE.STD_LOGIC_1164.ALL; +USE IEEE.NUMERIC_STD.ALL; + +ENTITY rgb2gray_tb IS +END rgb2gray_tb; + +ARCHITECTURE Behavioral OF rgb2gray_tb IS + + -- Component Declaration + COMPONENT rgb2gray + PORT ( + clk : IN STD_LOGIC; + resetn : IN STD_LOGIC; + + m_axis_tvalid : OUT STD_LOGIC; + m_axis_tdata : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); + m_axis_tready : IN STD_LOGIC; + m_axis_tlast : OUT STD_LOGIC; + + s_axis_tvalid : IN STD_LOGIC; + s_axis_tdata : IN STD_LOGIC_VECTOR(7 DOWNTO 0); + s_axis_tready : OUT STD_LOGIC; + s_axis_tlast : IN STD_LOGIC + ); + END COMPONENT; + + -- Signals + SIGNAL clk : STD_LOGIC := '0'; + SIGNAL resetn : STD_LOGIC := '0'; + + SIGNAL m_axis_tvalid : STD_LOGIC; + SIGNAL m_axis_tdata : STD_LOGIC_VECTOR(7 DOWNTO 0); + SIGNAL m_axis_tready : STD_LOGIC := '1'; + SIGNAL m_axis_tlast : STD_LOGIC; + + SIGNAL s_axis_tvalid : STD_LOGIC := '0'; + SIGNAL s_axis_tdata : STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS => '0'); + SIGNAL s_axis_tready : STD_LOGIC; + SIGNAL s_axis_tlast : STD_LOGIC := '0'; + + -- Clock generation + CONSTANT clk_period : TIME := 10 ns; + +BEGIN + + m_axis_tready<='1'; + + clk <= not clk AFTER clk_period / 2; -- Clock generation + + -- Instantiate the Device Under Test (DUT) + DUT: rgb2gray + PORT MAP ( + clk => clk, + resetn => resetn, + m_axis_tvalid => m_axis_tvalid, + m_axis_tdata => m_axis_tdata, + m_axis_tready => m_axis_tready, + m_axis_tlast => m_axis_tlast, + s_axis_tvalid => s_axis_tvalid, + s_axis_tdata => s_axis_tdata, + s_axis_tready => s_axis_tready, + s_axis_tlast => s_axis_tlast + ); + + -- Stimulus process + stimulus_process : PROCESS + VARIABLE pixel_value : INTEGER := 1; -- Variable to increment pixel values + BEGIN + wait for 10 ns; + resetn<='1'; + s_axis_tvalid <= '1'; + + -- Send multiple RGB pixels with incrementing values + FOR i IN 0 TO 10 LOOP -- Send 10 pixels + -- R component + s_axis_tdata <= STD_LOGIC_VECTOR(TO_UNSIGNED(pixel_value, 8)); + WAIT FOR clk_period; + + -- G component + pixel_value := pixel_value + 5; + s_axis_tdata <= STD_LOGIC_VECTOR(TO_UNSIGNED(pixel_value, 8)); + WAIT FOR clk_period; + + -- B component + pixel_value := pixel_value + 1; + s_axis_tdata <= STD_LOGIC_VECTOR(TO_UNSIGNED(pixel_value, 8)); + WAIT FOR clk_period; + + -- Reset last signal + pixel_value := pixel_value + 1; + END LOOP; + + -- Deassert valid signal + s_axis_tlast <= '1'; -- Indicate end of pixel + s_axis_tvalid <= '0'; + + WAIT; + END PROCESS; + +END Behavioral; \ No newline at end of file diff --git a/LAB2/src/divider_by_3.vhd b/LAB2/src/divider_by_3.vhd index 9665824..27a37eb 100644 --- a/LAB2/src/divider_by_3.vhd +++ b/LAB2/src/divider_by_3.vhd @@ -10,10 +10,8 @@ ENTITY divider_by_3 IS BIT_DEPTH : INTEGER := 8 ); PORT ( - R : IN STD_LOGIC_VECTOR(BIT_DEPTH - 1 DOWNTO 0); - G : IN STD_LOGIC_VECTOR(BIT_DEPTH - 1 DOWNTO 0); - B : IN STD_LOGIC_VECTOR(BIT_DEPTH - 1 DOWNTO 0); - grey : OUT STD_LOGIC_VECTOR(BIT_DEPTH - 1 DOWNTO 0) + dividend : IN UNSIGNED(BIT_DEPTH + 1 DOWNTO 0); + gray : OUT UNSIGNED(BIT_DEPTH - 1 DOWNTO 0) ); END divider_by_3; @@ -26,7 +24,7 @@ ARCHITECTURE Behavioral OF divider_by_3 IS -- Signals to hold the sum of the RGB channels and the intermediate results SIGNAL rgb_sum_extended : UNSIGNED(BIT_DEPTH + 1 DOWNTO 0) := (OTHERS => '0'); - SIGNAL scaled_result : UNSIGNED(RESULT_WIDTH - 1 DOWNTO 0) := (OTHERS => '0'); + SIGNAL scaled_result : UNSIGNED(RESULT_WIDTH DOWNTO 0) := (OTHERS => '0'); SIGNAL grayscale_value : UNSIGNED(BIT_DEPTH - 1 DOWNTO 0) := (OTHERS => '0'); BEGIN @@ -39,15 +37,15 @@ BEGIN -- 4. The final grayscale value is extracted from the result and converted back to a std_logic_vector. -- Calculate the sum of the RGB channels - rgb_sum_extended <= UNSIGNED(R) + UNSIGNED(G) + UNSIGNED(B) + TO_UNSIGNED(2, BIT_DEPTH + 2); + rgb_sum_extended <= dividend + TO_UNSIGNED(2, BIT_DEPTH + 2); -- Multiply the sum by the precomputed multiplier - scaled_result <= rgb_sum_extended * TO_UNSIGNED(DIVISION_MULTIPLIER, RESULT_WIDTH); + scaled_result <= rgb_sum_extended * TO_UNSIGNED(DIVISION_MULTIPLIER, BIT_DEPTH + 1); -- Extract the grayscale value from the scaled result by right-shifting - grayscale_value <= scaled_result(RESULT_WIDTH - 1 DOWNTO RESULT_WIDTH - BIT_DEPTH - 1); + grayscale_value <= scaled_result(RESULT_WIDTH - 1 DOWNTO RESULT_WIDTH - BIT_DEPTH); -- Assign the grayscale value to the output - grey <= STD_LOGIC_VECTOR(grayscale_value); + gray <= grayscale_value; END Behavioral; \ No newline at end of file diff --git a/LAB2/src/rgb2gray.vhd b/LAB2/src/rgb2gray.vhd index 87b6458..19718ec 100644 --- a/LAB2/src/rgb2gray.vhd +++ b/LAB2/src/rgb2gray.vhd @@ -33,17 +33,16 @@ ARCHITECTURE Behavioral OF rgb2gray IS BIT_DEPTH : INTEGER := 8 ); PORT ( - R : IN STD_LOGIC_VECTOR(BIT_DEPTH - 1 DOWNTO 0); - G : IN STD_LOGIC_VECTOR(BIT_DEPTH - 1 DOWNTO 0); - B : IN STD_LOGIC_VECTOR(BIT_DEPTH - 1 DOWNTO 0); - grey : OUT STD_LOGIC_VECTOR(BIT_DEPTH - 1 DOWNTO 0)); + dividend : IN UNSIGNED(BIT_DEPTH + 1 DOWNTO 0); + gray : OUT UNSIGNED(BIT_DEPTH - 1 DOWNTO 0)); END COMPONENT divider_by_3; TYPE state_type IS (WAIT_R, WAIT_G, WAIT_B); SIGNAL state : state_type := WAIT_R; - SIGNAL r_val, g_val, b_val : unsigned(7 DOWNTO 0); - SIGNAL gray : unsigned(7 DOWNTO 0); + SIGNAL r_val, g_val : unsigned(7 DOWNTO 0); + SIGNAL sum : unsigned(9 DOWNTO 0); + SIGNAL gray : UNSIGNED(7 DOWNTO 0); BEGIN @@ -52,10 +51,8 @@ BEGIN BIT_DEPTH => 8 ) PORT MAP( - R => STD_LOGIC_VECTOR(r_val), - G => STD_LOGIC_VECTOR(g_val), - B => STD_LOGIC_VECTOR(b_val), - grey => STD_LOGIC_VECTOR(gray) + dividend => sum, + gray => gray ); PROCESS (clk) @@ -70,14 +67,18 @@ BEGIN m_axis_tdata <= (OTHERS => '0'); r_val <= (OTHERS => '0'); g_val <= (OTHERS => '0'); - b_val <= (OTHERS => '0'); - gray <= (OTHERS => '0'); + sum <= (OTHERS => '0'); ELSE -- Default control signals s_axis_tready <= '1'; - m_axis_tvalid <= '0'; m_axis_tlast <= '0'; + -- If downstream is ready, send the grayscale pixel + IF m_axis_tready = '1' THEN + m_axis_tdata <= STD_LOGIC_VECTOR(gray); + m_axis_tlast <= s_axis_tlast; + END IF; + CASE state IS WHEN WAIT_R => IF s_axis_tvalid = '1' THEN @@ -93,16 +94,11 @@ BEGIN WHEN WAIT_B => IF s_axis_tvalid = '1' THEN - b_val <= unsigned(s_axis_tdata); - END IF; - - -- If downstream is ready, send the grayscale pixel - IF m_axis_tready = '1' THEN - m_axis_tdata <= STD_LOGIC_VECTOR(gray); + sum <= ('0' & '0' & r_val) + ('0' & '0' & g_val) + ('0' & '0' & unsigned(s_axis_tdata)); m_axis_tvalid <= '1'; - m_axis_tlast <= s_axis_tlast; state <= WAIT_R; END IF; + END CASE; END IF; END IF; diff --git a/LAB2/vivado/rgb2grey_test/rgb2grey_test.xpr b/LAB2/vivado/rgb2grey_test/rgb2grey_test.xpr new file mode 100644 index 0000000..5326766 --- /dev/null +++ b/LAB2/vivado/rgb2grey_test/rgb2grey_test.xpr @@ -0,0 +1,211 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + default_dashboard + + +