From 75fb66e5311af517a638ff825465c1322f88b456 Mon Sep 17 00:00:00 2001 From: Davide Date: Thu, 24 Apr 2025 11:25:39 +0200 Subject: [PATCH] Refactor rgb2gray and divider_by_3: update signal handling, enhance state management, and improve stimulus memory for better functionality and clarity --- LAB2/sim/tb_rgb2gray.vhd | 18 +-- LAB2/src/divider_by_3.vhd | 3 + LAB2/src/rgb2gray.vhd | 225 +++++++++++++++++++------------------- 3 files changed, 126 insertions(+), 120 deletions(-) diff --git a/LAB2/sim/tb_rgb2gray.vhd b/LAB2/sim/tb_rgb2gray.vhd index 38b1350..945919b 100644 --- a/LAB2/sim/tb_rgb2gray.vhd +++ b/LAB2/sim/tb_rgb2gray.vhd @@ -43,15 +43,15 @@ ARCHITECTURE Behavioral OF rgb2gray_tb IS -- Stimulus memory for RGB triplets (R, G, B) TYPE rgb_mem_type IS ARRAY(0 TO 8, 0 TO 2) OF STD_LOGIC_VECTOR(7 DOWNTO 0); SIGNAL rgb_mem : rgb_mem_type := ( - (x"10", x"20", x"30"), - (x"40", x"50", x"60"), - (x"70", x"80", x"90"), - (x"A0", x"B0", x"C0"), - (x"D0", x"E0", x"F0"), - (x"01", x"02", x"03"), - (x"04", x"05", x"06"), - (x"07", x"08", x"09"), - (x"0A", x"0B", x"0C") + (x"1A", x"2F", x"7C"), + (x"05", x"7F", x"3B"), + (x"4D", x"12", x"6E"), + (x"7E", x"01", x"23"), + (x"3C", x"55", x"7A"), + (x"2B", x"0F", x"6D"), + (x"7B", x"7D", x"7C"), + (x"6A", x"3E", x"27"), + (x"0C", x"5A", x"7F") ); SIGNAL tready_block_req : STD_LOGIC := '0'; diff --git a/LAB2/src/divider_by_3.vhd b/LAB2/src/divider_by_3.vhd index b96076e..4f7181c 100644 --- a/LAB2/src/divider_by_3.vhd +++ b/LAB2/src/divider_by_3.vhd @@ -36,6 +36,9 @@ 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 + -- The addition of 2 is used to implement rounding when dividing by 3. + -- This is a common technique: adding half of the divisor (3/2 ? 2) before division + -- ensures that the result is rounded to the nearest integer instead of truncated. sum_extended <= dividend + TO_UNSIGNED(2, BIT_DEPTH + 2); -- Multiply the sum by the precomputed multiplier diff --git a/LAB2/src/rgb2gray.vhd b/LAB2/src/rgb2gray.vhd index f610e2c..d35bd1e 100644 --- a/LAB2/src/rgb2gray.vhd +++ b/LAB2/src/rgb2gray.vhd @@ -3,136 +3,139 @@ USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.NUMERIC_STD.ALL; ENTITY rgb2gray IS - PORT ( - clk : IN STD_LOGIC; - resetn : IN STD_LOGIC; + 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; + 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 - ); + 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 rgb2gray; ARCHITECTURE Behavioral OF rgb2gray IS - COMPONENT divider_by_3 - GENERIC ( - BIT_DEPTH : INTEGER := 7 - ); - PORT ( - dividend : IN UNSIGNED(BIT_DEPTH + 1 DOWNTO 0); - result : OUT UNSIGNED(BIT_DEPTH - 1 DOWNTO 0) - ); - END COMPONENT; + COMPONENT divider_by_3 + GENERIC ( + BIT_DEPTH : INTEGER := 7 + ); + PORT ( + dividend : IN UNSIGNED(BIT_DEPTH + 1 DOWNTO 0); + result : OUT UNSIGNED(BIT_DEPTH - 1 DOWNTO 0) + ); + END COMPONENT; - TYPE state_type IS (WAIT_R, WAIT_G, WAIT_B); - SIGNAL state : state_type := WAIT_R; + TYPE state_type IS (IDLE, ACCUMULATE, WAIT_DIV, SEND); + SIGNAL state : state_type := IDLE; - SIGNAL r_val, g_val : UNSIGNED(7 DOWNTO 0); - SIGNAL sum : UNSIGNED(8 DOWNTO 0); - SIGNAL gray : UNSIGNED(6 DOWNTO 0); + SIGNAL sum : UNSIGNED(8 DOWNTO 0) := (OTHERS => '0'); + SIGNAL rgb_sum : UNSIGNED(8 DOWNTO 0) := (OTHERS => '0'); + SIGNAL gray : UNSIGNED(6 DOWNTO 0); + SIGNAL count : INTEGER RANGE 0 TO 2 := 0; - SIGNAL m_axis_tvalid_int : STD_LOGIC := '0'; - SIGNAL s_axis_tready_int : STD_LOGIC := '0'; + SIGNAL m_axis_tvalid_int : STD_LOGIC := '0'; + SIGNAL m_axis_tdata_int : STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS => '0'); + SIGNAL m_axis_tlast_int : STD_LOGIC := '0'; + SIGNAL s_axis_tready_int : STD_LOGIC := '1'; - SIGNAL trigger : STD_LOGIC := '0'; - SIGNAL last_seen : STD_LOGIC := '0'; + SIGNAL last_seen : STD_LOGIC := '0'; BEGIN - s_axis_tready <= s_axis_tready_int; - m_axis_tvalid <= m_axis_tvalid_int; + s_axis_tready <= s_axis_tready_int; + m_axis_tvalid <= m_axis_tvalid_int; + m_axis_tdata <= m_axis_tdata_int; + m_axis_tlast <= m_axis_tlast_int; - -- Divider instance - DIVIDER : divider_by_3 - GENERIC MAP( - BIT_DEPTH => 7 - ) - PORT MAP( - dividend => sum, - result => gray - ); + -- Divider instance + DIVIDER : divider_by_3 + GENERIC MAP( + BIT_DEPTH => 7 + ) + PORT MAP( + dividend => rgb_sum, + result => gray + ); - PROCESS (clk) - BEGIN - IF rising_edge(clk) THEN - IF resetn = '0' THEN - -- Reset all signals - state <= WAIT_R; + PROCESS (clk) + BEGIN + IF rising_edge(clk) THEN + IF resetn = '0' THEN + state <= IDLE; + sum <= (OTHERS => '0'); + rgb_sum <= (OTHERS => '0'); + count <= 0; + m_axis_tvalid_int <= '0'; + m_axis_tdata_int <= (OTHERS => '0'); + m_axis_tlast_int <= '0'; + s_axis_tready_int <= '1'; + last_seen <= '0'; + ELSE + -- Default assignments + m_axis_tlast_int <= '0'; - s_axis_tready_int <= '0'; - m_axis_tvalid_int <= '0'; + CASE state IS + WHEN IDLE => + m_axis_tdata_int <= (OTHERS => '0'); + sum <= (OTHERS => '0'); + count <= 0; + m_axis_tvalid_int <= '0'; + s_axis_tready_int <= '1'; + IF s_axis_tvalid = '1' AND s_axis_tready_int = '1' THEN + sum <= unsigned('0' & s_axis_tdata); + count <= 1; + IF s_axis_tlast = '1' THEN + last_seen <= '1'; + END IF; + state <= ACCUMULATE; + END IF; - m_axis_tdata <= (OTHERS => '0'); - m_axis_tlast <= '0'; + WHEN ACCUMULATE => + IF s_axis_tvalid = '1' AND s_axis_tready_int = '1' THEN + sum <= sum + unsigned(s_axis_tdata); + IF count = 2 THEN + rgb_sum <= sum + unsigned(s_axis_tdata); + s_axis_tready_int <= '0'; + IF s_axis_tlast = '1' THEN + last_seen <= '1'; + END IF; + state <= WAIT_DIV; + ELSE + count <= count + 1; + IF s_axis_tlast = '1' THEN + last_seen <= '1'; + END IF; + END IF; + END IF; - r_val <= (OTHERS => '0'); - g_val <= (OTHERS => '0'); + WHEN WAIT_DIV => + -- Ora gray è valido + m_axis_tdata_int <= '0' & STD_LOGIC_VECTOR(gray); + m_axis_tvalid_int <= '1'; + s_axis_tready_int <= '0'; + IF last_seen = '1' THEN + m_axis_tlast_int <= '1'; + last_seen <= '0'; + END IF; + state <= SEND; - sum <= (OTHERS => '0'); + WHEN SEND => + -- Mantieni il dato finché non viene accettato + IF m_axis_tvalid_int = '1' AND m_axis_tready = '1' THEN + m_axis_tvalid_int <= '0'; + s_axis_tready_int <= '1'; + state <= IDLE; + END IF; - trigger <= '0'; - - ELSE - - -- Input data - slave - s_axis_tready_int <= m_axis_tready; - - IF s_axis_tlast = '1' THEN - last_seen <= '1'; - ELSE - m_axis_tlast <= '0'; - END IF; - - -- Output data - master - IF m_axis_tready = '1' THEN - m_axis_tvalid_int <= '0'; - END IF; - - IF trigger = '1' AND (m_axis_tvalid_int = '0' OR m_axis_tready = '1') THEN - m_axis_tvalid_int <= '1'; - m_axis_tdata <= '0' & STD_LOGIC_VECTOR(gray); -- MSB zero + 7bit gray - - IF last_seen = '1' THEN - m_axis_tlast <= '1'; - last_seen <= '0'; - END IF; - - trigger <= '0'; - END IF; - - -- State machine for R, G, B values buffering - CASE state IS - WHEN WAIT_R => - IF s_axis_tvalid = '1' AND s_axis_tready_int = '1' THEN - r_val <= unsigned(s_axis_tdata); - - state <= WAIT_G; - END IF; - - WHEN WAIT_G => - IF s_axis_tvalid = '1' AND s_axis_tready_int = '1' THEN - g_val <= unsigned(s_axis_tdata); - - state <= WAIT_B; - END IF; - - WHEN WAIT_B => - IF s_axis_tvalid = '1' AND s_axis_tready_int = '1' THEN - sum <= RESIZE(r_val + g_val + unsigned(s_axis_tdata), sum'length); - trigger <= '1'; - - state <= WAIT_R; - END IF; - END CASE; - END IF; - END IF; - END PROCESS; + END CASE; + END IF; + END IF; + END PROCESS; END ARCHITECTURE; \ No newline at end of file