Refactor RGB to Grayscale Converter and Add Divider Component

- Updated the rgb2gray.vhd file to improve readability and structure, including consistent casing for keywords and signals.
- Implemented a new divider_by_3 component to calculate the grayscale value by dividing the sum of RGB channels by 3.
- Enhanced the state machine in rgb2gray to handle RGB input and output grayscale values correctly.
- Updated the Vivado project file to include the new divider_by_3.vhd for synthesis and simulation.
- Modified vhdl_ls.toml to include unisim files for third-party library support.
This commit is contained in:
2025-04-11 01:50:19 +02:00
parent 0912887822
commit 0d805b93b6
5 changed files with 643 additions and 633 deletions

53
LAB2/src/divider_by_3.vhd Normal file
View File

@@ -0,0 +1,53 @@
---------- DEFAULT LIBRARIES -------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
USE IEEE.MATH_REAL.ALL;
------------------------------------
ENTITY divider_by_3 IS
GENERIC (
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)
);
END divider_by_3;
ARCHITECTURE Behavioral OF divider_by_3 IS
-- Constant to calculate the multiplier for approximating division by 3
CONSTANT DIVISION_MULTIPLIER : INTEGER := INTEGER(floor(real(2 ** (BIT_DEPTH + 2)) / 3.0));
-- Constant to calculate the length of the result signal
CONSTANT RESULT_WIDTH : INTEGER := (2 * BIT_DEPTH) + 2;
-- 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 grayscale_value : UNSIGNED(BIT_DEPTH - 1 DOWNTO 0) := (OTHERS => '0');
BEGIN
-- Explanation of how the division by 3 is performed:
-- 1. The sum of the RGB channels (R + G + B) is calculated and extended to avoid overflow.
-- 2. The sum is multiplied by a precomputed constant (DIVISION_MULTIPLIER), which is approximately equal to (2^(BIT_DEPTH + 2)) / 3.
-- This scales the value up to prepare for the division.
-- 3. The result of the multiplication is then right-shifted by a specific number of bits.
-- This operation effectively scales the value back down, approximating the division by 3.
-- 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);
-- Multiply the sum by the precomputed multiplier
scaled_result <= rgb_sum_extended * TO_UNSIGNED(DIVISION_MULTIPLIER, RESULT_WIDTH);
-- Extract the grayscale value from the scaled result by right-shifting
grayscale_value <= scaled_result(RESULT_WIDTH - 1 DOWNTO RESULT_WIDTH - BIT_DEPTH - 1);
-- Assign the grayscale value to the output
grey <= STD_LOGIC_VECTOR(grayscale_value);
END Behavioral;

File diff suppressed because it is too large Load Diff

View File

@@ -1,36 +1,111 @@
---------- DEFAULT LIBRARIES ------- ---------- DEFAULT LIBRARIES -------
library IEEE; LIBRARY IEEE;
use IEEE.STD_LOGIC_1164.all; USE IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL; USE IEEE.NUMERIC_STD.ALL;
use IEEE.MATH_REAL.all; -- For LOG **FOR A CONSTANT!!** USE IEEE.MATH_REAL.ALL; -- For logarithmic calculations (used for a constant)
------------------------------------ ------------------------------------
---------- OTHER LIBRARIES --------- ---------- OTHER LIBRARIES ---------
-- NONE -- NONE
------------------------------------ ------------------------------------
entity rgb2gray is ENTITY rgb2gray IS
Port ( PORT (
clk : in std_logic; clk : IN STD_LOGIC;
resetn : in std_logic; resetn : IN STD_LOGIC;
m_axis_tvalid : out std_logic; m_axis_tvalid : OUT STD_LOGIC;
m_axis_tdata : out std_logic_vector(7 downto 0); m_axis_tdata : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
m_axis_tready : in std_logic; m_axis_tready : IN STD_LOGIC;
m_axis_tlast : out std_logic; m_axis_tlast : OUT STD_LOGIC;
s_axis_tvalid : in std_logic; s_axis_tvalid : IN STD_LOGIC;
s_axis_tdata : in std_logic_vector(7 downto 0); s_axis_tdata : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
s_axis_tready : out std_logic; s_axis_tready : OUT STD_LOGIC;
s_axis_tlast : in std_logic s_axis_tlast : IN STD_LOGIC
); );
end rgb2gray; END rgb2gray;
architecture Behavioral of rgb2gray is ARCHITECTURE Behavioral OF rgb2gray IS
COMPONENT divider_by_3
GENERIC (
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));
END COMPONENT divider_by_3;
TYPE state_type IS (WAIT_R, WAIT_G, WAIT_B);
SIGNAL state : state_type := WAIT_R;
begin SIGNAL r_val, g_val, b_val : unsigned(7 DOWNTO 0);
SIGNAL gray : unsigned(7 DOWNTO 0);
BEGIN
end Behavioral; DIVIDER : divider_by_3
GENERIC MAP(
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)
);
PROCESS (clk)
BEGIN
IF rising_edge(clk) THEN
IF resetn = '0' THEN
-- Reset all signals
state <= WAIT_R;
s_axis_tready <= '1';
m_axis_tvalid <= '0';
m_axis_tlast <= '0';
m_axis_tdata <= (OTHERS => '0');
r_val <= (OTHERS => '0');
g_val <= (OTHERS => '0');
b_val <= (OTHERS => '0');
gray <= (OTHERS => '0');
ELSE
-- Default control signals
s_axis_tready <= '1';
m_axis_tvalid <= '0';
m_axis_tlast <= '0';
CASE state IS
WHEN WAIT_R =>
IF s_axis_tvalid = '1' THEN
r_val <= unsigned(s_axis_tdata);
state <= WAIT_G;
END IF;
WHEN WAIT_G =>
IF s_axis_tvalid = '1' THEN
g_val <= unsigned(s_axis_tdata);
state <= WAIT_B;
END IF;
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);
m_axis_tvalid <= '1';
m_axis_tlast <= s_axis_tlast;
state <= WAIT_R;
END IF;
END CASE;
END IF;
END IF;
END PROCESS;
END ARCHITECTURE;

View File

@@ -95,6 +95,12 @@
<Attr Name="UsedIn" Val="simulation"/> <Attr Name="UsedIn" Val="simulation"/>
</FileInfo> </FileInfo>
</File> </File>
<File Path="$PPRDIR/../../src/divider_by_3.vhd">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<File Path="$PPRDIR/../../src/rgb2gray.vhd"> <File Path="$PPRDIR/../../src/rgb2gray.vhd">
<FileInfo> <FileInfo>
<Attr Name="UsedIn" Val="synthesis"/> <Attr Name="UsedIn" Val="synthesis"/>
@@ -196,9 +202,7 @@
<Runs Version="1" Minor="15"> <Runs Version="1" Minor="15">
<Run Id="synth_1" Type="Ft3:Synth" SrcSet="sources_1" Part="xc7a35tcpg236-1" ConstrsSet="constrs_1" Description="Vivado Synthesis Defaults" AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" State="current" IncludeInArchive="true" AutoIncrementalDir="$PPRDIR/../../lab2/lab2.srcs/utils_1/imports/synth_1"> <Run Id="synth_1" Type="Ft3:Synth" SrcSet="sources_1" Part="xc7a35tcpg236-1" ConstrsSet="constrs_1" Description="Vivado Synthesis Defaults" AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" State="current" IncludeInArchive="true" AutoIncrementalDir="$PPRDIR/../../lab2/lab2.srcs/utils_1/imports/synth_1">
<Strategy Version="1" Minor="2"> <Strategy Version="1" Minor="2">
<StratHandle Name="Vivado Synthesis Defaults" Flow="Vivado Synthesis 2020"> <StratHandle Name="Vivado Synthesis Defaults" Flow="Vivado Synthesis 2020"/>
<Desc>Vivado Synthesis Defaults</Desc>
</StratHandle>
<Step Id="synth_design"/> <Step Id="synth_design"/>
</Strategy> </Strategy>
<ReportStrategy Name="Vivado Synthesis Default Reports" Flow="Vivado Synthesis 2020"/> <ReportStrategy Name="Vivado Synthesis Default Reports" Flow="Vivado Synthesis 2020"/>
@@ -207,9 +211,7 @@
</Run> </Run>
<Run Id="impl_1" Type="Ft2:EntireDesign" Part="xc7a35tcpg236-1" ConstrsSet="constrs_1" Description="Default settings for Implementation." AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" State="current" SynthRun="synth_1" IncludeInArchive="true" GenFullBitstream="true" AutoIncrementalDir="$PPRDIR/../../lab2/lab2.srcs/utils_1/imports/impl_1"> <Run Id="impl_1" Type="Ft2:EntireDesign" Part="xc7a35tcpg236-1" ConstrsSet="constrs_1" Description="Default settings for Implementation." AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" State="current" SynthRun="synth_1" IncludeInArchive="true" GenFullBitstream="true" AutoIncrementalDir="$PPRDIR/../../lab2/lab2.srcs/utils_1/imports/impl_1">
<Strategy Version="1" Minor="2"> <Strategy Version="1" Minor="2">
<StratHandle Name="Vivado Implementation Defaults" Flow="Vivado Implementation 2020"> <StratHandle Name="Vivado Implementation Defaults" Flow="Vivado Implementation 2020"/>
<Desc>Default settings for Implementation.</Desc>
</StratHandle>
<Step Id="init_design"/> <Step Id="init_design"/>
<Step Id="opt_design"/> <Step Id="opt_design"/>
<Step Id="power_opt_design"/> <Step Id="power_opt_design"/>

View File

@@ -11,7 +11,7 @@ lab1_lib.files = [
] ]
lab2_lib.files = [ lab2_lib.files = [
"LAB2/src/**/*.vhd", "LAB2/src/*.vhd",
"LAB2/sim/**/*.vhd" "LAB2/sim/**/*.vhd"
] ]
@@ -24,3 +24,8 @@ xpm.files = [
"C:/Xilinx/Vivado/2020.2/data/ip/xpm/xpm_VCOMP.vhd" "C:/Xilinx/Vivado/2020.2/data/ip/xpm/xpm_VCOMP.vhd"
] ]
xpm.is_third_party = true xpm.is_third_party = true
unisim.files = [
"C:/Xilinx/Vivado/2020.2/data/vhdl/src/unisims/**/*.vhd"
]
unisim.is_third_party = true