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:
53
LAB2/src/divider_by_3.vhd
Normal file
53
LAB2/src/divider_by_3.vhd
Normal 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
@@ -1,36 +1,111 @@
|
||||
---------- DEFAULT LIBRARIES -------
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.all;
|
||||
use IEEE.NUMERIC_STD.ALL;
|
||||
use IEEE.MATH_REAL.all; -- For LOG **FOR A CONSTANT!!**
|
||||
LIBRARY IEEE;
|
||||
USE IEEE.STD_LOGIC_1164.ALL;
|
||||
USE IEEE.NUMERIC_STD.ALL;
|
||||
USE IEEE.MATH_REAL.ALL; -- For logarithmic calculations (used for a constant)
|
||||
------------------------------------
|
||||
|
||||
---------- OTHER LIBRARIES ---------
|
||||
-- NONE
|
||||
------------------------------------
|
||||
|
||||
entity rgb2gray is
|
||||
Port (
|
||||
clk : in std_logic;
|
||||
resetn : in std_logic;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
@@ -95,6 +95,12 @@
|
||||
<Attr Name="UsedIn" Val="simulation"/>
|
||||
</FileInfo>
|
||||
</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">
|
||||
<FileInfo>
|
||||
<Attr Name="UsedIn" Val="synthesis"/>
|
||||
@@ -196,9 +202,7 @@
|
||||
<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">
|
||||
<Strategy Version="1" Minor="2">
|
||||
<StratHandle Name="Vivado Synthesis Defaults" Flow="Vivado Synthesis 2020">
|
||||
<Desc>Vivado Synthesis Defaults</Desc>
|
||||
</StratHandle>
|
||||
<StratHandle Name="Vivado Synthesis Defaults" Flow="Vivado Synthesis 2020"/>
|
||||
<Step Id="synth_design"/>
|
||||
</Strategy>
|
||||
<ReportStrategy Name="Vivado Synthesis Default Reports" Flow="Vivado Synthesis 2020"/>
|
||||
@@ -207,9 +211,7 @@
|
||||
</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">
|
||||
<Strategy Version="1" Minor="2">
|
||||
<StratHandle Name="Vivado Implementation Defaults" Flow="Vivado Implementation 2020">
|
||||
<Desc>Default settings for Implementation.</Desc>
|
||||
</StratHandle>
|
||||
<StratHandle Name="Vivado Implementation Defaults" Flow="Vivado Implementation 2020"/>
|
||||
<Step Id="init_design"/>
|
||||
<Step Id="opt_design"/>
|
||||
<Step Id="power_opt_design"/>
|
||||
|
||||
@@ -11,7 +11,7 @@ lab1_lib.files = [
|
||||
]
|
||||
|
||||
lab2_lib.files = [
|
||||
"LAB2/src/**/*.vhd",
|
||||
"LAB2/src/*.vhd",
|
||||
"LAB2/sim/**/*.vhd"
|
||||
]
|
||||
|
||||
@@ -24,3 +24,8 @@ xpm.files = [
|
||||
"C:/Xilinx/Vivado/2020.2/data/ip/xpm/xpm_VCOMP.vhd"
|
||||
]
|
||||
xpm.is_third_party = true
|
||||
|
||||
unisim.files = [
|
||||
"C:/Xilinx/Vivado/2020.2/data/vhdl/src/unisims/**/*.vhd"
|
||||
]
|
||||
unisim.is_third_party = true
|
||||
Reference in New Issue
Block a user