Refactor rgb2gray and divider_by_3: update signal handling, enhance state management, and improve stimulus memory for better functionality and clarity

This commit is contained in:
2025-04-24 11:25:39 +02:00
parent 5995a532f5
commit 75fb66e531
3 changed files with 126 additions and 120 deletions

View File

@@ -43,15 +43,15 @@ ARCHITECTURE Behavioral OF rgb2gray_tb IS
-- Stimulus memory for RGB triplets (R, G, B) -- 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); 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 := ( SIGNAL rgb_mem : rgb_mem_type := (
(x"10", x"20", x"30"), (x"1A", x"2F", x"7C"),
(x"40", x"50", x"60"), (x"05", x"7F", x"3B"),
(x"70", x"80", x"90"), (x"4D", x"12", x"6E"),
(x"A0", x"B0", x"C0"), (x"7E", x"01", x"23"),
(x"D0", x"E0", x"F0"), (x"3C", x"55", x"7A"),
(x"01", x"02", x"03"), (x"2B", x"0F", x"6D"),
(x"04", x"05", x"06"), (x"7B", x"7D", x"7C"),
(x"07", x"08", x"09"), (x"6A", x"3E", x"27"),
(x"0A", x"0B", x"0C") (x"0C", x"5A", x"7F")
); );
SIGNAL tready_block_req : STD_LOGIC := '0'; SIGNAL tready_block_req : STD_LOGIC := '0';

View File

@@ -36,6 +36,9 @@ BEGIN
-- 4. The final grayscale value is extracted from the result and converted back to a std_logic_vector. -- 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 -- 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); sum_extended <= dividend + TO_UNSIGNED(2, BIT_DEPTH + 2);
-- Multiply the sum by the precomputed multiplier -- Multiply the sum by the precomputed multiplier

View File

@@ -31,23 +31,27 @@ ARCHITECTURE Behavioral OF rgb2gray IS
); );
END COMPONENT; END COMPONENT;
TYPE state_type IS (WAIT_R, WAIT_G, WAIT_B); TYPE state_type IS (IDLE, ACCUMULATE, WAIT_DIV, SEND);
SIGNAL state : state_type := WAIT_R; SIGNAL state : state_type := IDLE;
SIGNAL r_val, g_val : UNSIGNED(7 DOWNTO 0); SIGNAL sum : UNSIGNED(8 DOWNTO 0) := (OTHERS => '0');
SIGNAL sum : UNSIGNED(8 DOWNTO 0); SIGNAL rgb_sum : UNSIGNED(8 DOWNTO 0) := (OTHERS => '0');
SIGNAL gray : UNSIGNED(6 DOWNTO 0); SIGNAL gray : UNSIGNED(6 DOWNTO 0);
SIGNAL count : INTEGER RANGE 0 TO 2 := 0;
SIGNAL m_axis_tvalid_int : STD_LOGIC := '0'; SIGNAL m_axis_tvalid_int : STD_LOGIC := '0';
SIGNAL s_axis_tready_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 BEGIN
s_axis_tready <= s_axis_tready_int; s_axis_tready <= s_axis_tready_int;
m_axis_tvalid <= m_axis_tvalid_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 instance
DIVIDER : divider_by_3 DIVIDER : divider_by_3
@@ -55,7 +59,7 @@ BEGIN
BIT_DEPTH => 7 BIT_DEPTH => 7
) )
PORT MAP( PORT MAP(
dividend => sum, dividend => rgb_sum,
result => gray result => gray
); );
@@ -63,73 +67,72 @@ BEGIN
BEGIN BEGIN
IF rising_edge(clk) THEN IF rising_edge(clk) THEN
IF resetn = '0' THEN IF resetn = '0' THEN
-- Reset all signals state <= IDLE;
state <= WAIT_R;
s_axis_tready_int <= '0';
m_axis_tvalid_int <= '0';
m_axis_tdata <= (OTHERS => '0');
m_axis_tlast <= '0';
r_val <= (OTHERS => '0');
g_val <= (OTHERS => '0');
sum <= (OTHERS => '0'); sum <= (OTHERS => '0');
rgb_sum <= (OTHERS => '0');
trigger <= '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 ELSE
-- Default assignments
m_axis_tlast_int <= '0';
-- Input data - slave CASE state IS
s_axis_tready_int <= m_axis_tready; 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 IF s_axis_tlast = '1' THEN
last_seen <= '1'; last_seen <= '1';
END IF;
state <= ACCUMULATE;
END IF;
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 ELSE
m_axis_tlast <= '0'; count <= count + 1;
IF s_axis_tlast = '1' THEN
last_seen <= '1';
END IF;
END IF;
END IF; END IF;
-- Output data - master WHEN WAIT_DIV =>
IF m_axis_tready = '1' THEN -- Ora gray <20> valido
m_axis_tvalid_int <= '0'; m_axis_tdata_int <= '0' & STD_LOGIC_VECTOR(gray);
END IF;
IF trigger = '1' AND (m_axis_tvalid_int = '0' OR m_axis_tready = '1') THEN
m_axis_tvalid_int <= '1'; m_axis_tvalid_int <= '1';
m_axis_tdata <= '0' & STD_LOGIC_VECTOR(gray); -- MSB zero + 7bit gray s_axis_tready_int <= '0';
IF last_seen = '1' THEN IF last_seen = '1' THEN
m_axis_tlast <= '1'; m_axis_tlast_int <= '1';
last_seen <= '0'; last_seen <= '0';
END IF; END IF;
state <= SEND;
trigger <= '0'; WHEN SEND =>
-- Mantieni il dato finch<63> 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; 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 CASE;
END IF; END IF;
END IF; END IF;