147 lines
5.2 KiB
VHDL
147 lines
5.2 KiB
VHDL
---------- DEFAULT LIBRARIES -------
|
|
LIBRARY IEEE;
|
|
USE IEEE.STD_LOGIC_1164.ALL;
|
|
USE IEEE.NUMERIC_STD.ALL;
|
|
------------------------------------
|
|
|
|
ENTITY rgb2gray IS
|
|
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 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;
|
|
|
|
TYPE state_type IS (IDLE, ACCUMULATE, WAIT_DIV, SEND);
|
|
SIGNAL state : state_type := IDLE;
|
|
|
|
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 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 last_seen : STD_LOGIC := '0';
|
|
|
|
BEGIN
|
|
|
|
-- Connect internal signals to output ports
|
|
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: divides the sum of RGB by 3 to obtain grayscale value
|
|
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
|
|
-- Asynchronous reset: initialize all signals and state
|
|
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 for each clock cycle
|
|
m_axis_tlast_int <= '0';
|
|
|
|
CASE state IS
|
|
WHEN IDLE =>
|
|
-- Wait for the first valid input sample
|
|
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;
|
|
|
|
WHEN ACCUMULATE =>
|
|
-- Accumulate the next two color components (expecting 3 total: R, G, B)
|
|
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;
|
|
|
|
WHEN WAIT_DIV =>
|
|
-- Now gray is valid (output from divider)
|
|
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;
|
|
|
|
WHEN SEND =>
|
|
-- Hold the data until it is accepted by the downstream module
|
|
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 CASE;
|
|
END IF;
|
|
END IF;
|
|
END PROCESS;
|
|
|
|
END ARCHITECTURE; |