Refactor image processing components: update bit depth in rgb2gray and divider_by_3, enhance img_conv architecture, and adjust simulation settings
This commit is contained in:
@@ -45,35 +45,89 @@ ARCHITECTURE Behavioral OF rgb2gray_tb IS
|
||||
|
||||
BEGIN
|
||||
|
||||
m_axis_tready<='1';
|
||||
|
||||
clk <= not clk AFTER clk_period / 2; -- Clock generation
|
||||
clk <= NOT clk AFTER clk_period / 2; -- Clock generation
|
||||
|
||||
-- Instantiate the Device Under Test (DUT)
|
||||
DUT: rgb2gray
|
||||
PORT MAP (
|
||||
clk => clk,
|
||||
resetn => resetn,
|
||||
m_axis_tvalid => m_axis_tvalid,
|
||||
m_axis_tdata => m_axis_tdata,
|
||||
m_axis_tready => m_axis_tready,
|
||||
m_axis_tlast => m_axis_tlast,
|
||||
s_axis_tvalid => s_axis_tvalid,
|
||||
s_axis_tdata => s_axis_tdata,
|
||||
s_axis_tready => s_axis_tready,
|
||||
s_axis_tlast => s_axis_tlast
|
||||
);
|
||||
DUT : rgb2gray
|
||||
PORT MAP(
|
||||
clk => clk,
|
||||
resetn => resetn,
|
||||
m_axis_tvalid => m_axis_tvalid,
|
||||
m_axis_tdata => m_axis_tdata,
|
||||
m_axis_tready => m_axis_tready,
|
||||
m_axis_tlast => m_axis_tlast,
|
||||
s_axis_tvalid => s_axis_tvalid,
|
||||
s_axis_tdata => s_axis_tdata,
|
||||
s_axis_tready => s_axis_tready,
|
||||
s_axis_tlast => s_axis_tlast
|
||||
);
|
||||
|
||||
-- Stimulus process
|
||||
stimulus_process : PROCESS
|
||||
VARIABLE pixel_value : INTEGER := 1; -- Variable to increment pixel values
|
||||
BEGIN
|
||||
wait for 10 ns;
|
||||
resetn<='1';
|
||||
WAIT FOR 10 ns;
|
||||
resetn <= '1';
|
||||
s_axis_tvalid <= '1';
|
||||
|
||||
-- Send multiple RGB pixels with incrementing values
|
||||
FOR i IN 0 TO 10 LOOP -- Send 10 pixels
|
||||
FOR i IN 0 TO 5 LOOP -- Send 10 pixels
|
||||
-- R component
|
||||
s_axis_tdata <= STD_LOGIC_VECTOR(TO_UNSIGNED(pixel_value, 8));
|
||||
WAIT FOR clk_period;
|
||||
|
||||
-- G component
|
||||
pixel_value := pixel_value + 5;
|
||||
s_axis_tdata <= STD_LOGIC_VECTOR(TO_UNSIGNED(pixel_value, 8));
|
||||
WAIT FOR clk_period;
|
||||
|
||||
-- B component
|
||||
pixel_value := pixel_value + 1;
|
||||
s_axis_tdata <= STD_LOGIC_VECTOR(TO_UNSIGNED(pixel_value, 8));
|
||||
WAIT FOR clk_period;
|
||||
|
||||
-- Reset last signal
|
||||
pixel_value := pixel_value + 1;
|
||||
END LOOP;
|
||||
|
||||
m_axis_tready <= '0';
|
||||
|
||||
-- R component
|
||||
s_axis_tdata <= STD_LOGIC_VECTOR(TO_UNSIGNED(pixel_value, 8));
|
||||
WAIT FOR clk_period;
|
||||
|
||||
-- G component
|
||||
pixel_value := pixel_value + 5;
|
||||
s_axis_tdata <= STD_LOGIC_VECTOR(TO_UNSIGNED(pixel_value, 8));
|
||||
WAIT FOR clk_period;
|
||||
|
||||
-- B component
|
||||
pixel_value := pixel_value + 1;
|
||||
s_axis_tdata <= STD_LOGIC_VECTOR(TO_UNSIGNED(pixel_value, 8));
|
||||
WAIT FOR clk_period;
|
||||
|
||||
FOR i IN 0 TO 3 LOOP -- Send 10 pixels
|
||||
-- R component
|
||||
s_axis_tdata <= STD_LOGIC_VECTOR(TO_UNSIGNED(pixel_value, 8));
|
||||
WAIT FOR clk_period;
|
||||
|
||||
-- G component
|
||||
pixel_value := pixel_value + 5;
|
||||
s_axis_tdata <= STD_LOGIC_VECTOR(TO_UNSIGNED(pixel_value, 8));
|
||||
WAIT FOR clk_period;
|
||||
|
||||
-- B component
|
||||
pixel_value := pixel_value + 1;
|
||||
s_axis_tdata <= STD_LOGIC_VECTOR(TO_UNSIGNED(pixel_value, 8));
|
||||
WAIT FOR clk_period;
|
||||
|
||||
-- Reset last signal
|
||||
pixel_value := pixel_value + 1;
|
||||
END LOOP;
|
||||
|
||||
m_axis_tready <= '1';
|
||||
|
||||
FOR i IN 0 TO 3 LOOP -- Send 10 pixels
|
||||
-- R component
|
||||
s_axis_tdata <= STD_LOGIC_VECTOR(TO_UNSIGNED(pixel_value, 8));
|
||||
WAIT FOR clk_period;
|
||||
|
||||
@@ -1,99 +1,94 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
|
||||
entity depacketizer is
|
||||
generic (
|
||||
HEADER: INTEGER :=16#FF#;
|
||||
FOOTER: INTEGER :=16#F1#
|
||||
LIBRARY ieee;
|
||||
USE ieee.std_logic_1164.ALL;
|
||||
USE ieee.numeric_std.ALL;
|
||||
ENTITY depacketizer IS
|
||||
GENERIC (
|
||||
HEADER : INTEGER := 16#FF#;
|
||||
FOOTER : INTEGER := 16#F1#
|
||||
);
|
||||
port (
|
||||
clk : in std_logic;
|
||||
aresetn : in std_logic;
|
||||
PORT (
|
||||
clk : IN STD_LOGIC;
|
||||
aresetn : IN STD_LOGIC;
|
||||
|
||||
s_axis_tdata : in std_logic_vector(7 downto 0);
|
||||
s_axis_tvalid : in std_logic;
|
||||
s_axis_tready : out std_logic;
|
||||
s_axis_tdata : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
|
||||
s_axis_tvalid : IN STD_LOGIC;
|
||||
s_axis_tready : OUT STD_LOGIC;
|
||||
|
||||
m_axis_tdata : out std_logic_vector(7 downto 0);
|
||||
m_axis_tvalid : out std_logic;
|
||||
m_axis_tready : in std_logic;
|
||||
m_axis_tlast : out std_logic
|
||||
m_axis_tdata : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
|
||||
m_axis_tvalid : OUT STD_LOGIC;
|
||||
m_axis_tready : IN STD_LOGIC;
|
||||
m_axis_tlast : OUT STD_LOGIC
|
||||
);
|
||||
end entity depacketizer;
|
||||
END ENTITY depacketizer;
|
||||
|
||||
architecture rtl of depacketizer is
|
||||
ARCHITECTURE rtl OF depacketizer IS
|
||||
|
||||
-- Enumeration for the state machine
|
||||
-- IDLE: Waiting for the start of a new packet
|
||||
-- STREAMING: Actively processing and forwarding packet data
|
||||
type state_type is (IDLE, STREAMING);
|
||||
signal state : state_type := IDLE;
|
||||
TYPE state_type IS (IDLE, STREAMING);
|
||||
SIGNAL state : state_type := IDLE;
|
||||
|
||||
-- Buffer to handle backpressure
|
||||
signal buffer_in : std_logic_vector(7 downto 0) := (others => '0');
|
||||
signal buffer_valid : std_logic := '0'; -- Indicates if buffer_in contains valid data
|
||||
begin
|
||||
SIGNAL buffer_in : STD_LOGIC_VECTOR(7 DOWNTO 0) := (OTHERS => '0');
|
||||
SIGNAL buffer_valid : STD_LOGIC := '0'; -- Indicates if buffer_in contains valid data
|
||||
BEGIN
|
||||
|
||||
depacketizer_fsm: process(clk)
|
||||
begin
|
||||
if rising_edge(clk) then
|
||||
if aresetn = '0' then
|
||||
depacketizer_fsm : PROCESS (clk)
|
||||
BEGIN
|
||||
IF rising_edge(clk) THEN
|
||||
IF aresetn = '0' THEN
|
||||
-- Reset: back to idle and clear everything
|
||||
state <= IDLE;
|
||||
state <= IDLE;
|
||||
s_axis_tready <= '0';
|
||||
m_axis_tvalid <= '0';
|
||||
m_axis_tlast <= '0';
|
||||
m_axis_tdata <= (others => '0');
|
||||
buffer_in <= (others => '0');
|
||||
buffer_valid <= '0';
|
||||
m_axis_tlast <= '0';
|
||||
m_axis_tdata <= (OTHERS => '0');
|
||||
buffer_in <= (OTHERS => '0');
|
||||
buffer_valid <= '0';
|
||||
|
||||
else
|
||||
ELSE
|
||||
-- Defaults for each clock cycle
|
||||
s_axis_tready <= '1';
|
||||
m_axis_tvalid <= '0';
|
||||
m_axis_tlast <= '0';
|
||||
m_axis_tlast <= '0';
|
||||
|
||||
case state is
|
||||
CASE state IS
|
||||
|
||||
when IDLE =>
|
||||
WHEN IDLE =>
|
||||
-- Wait for start of a new packet
|
||||
if s_axis_tvalid = '1' then
|
||||
if s_axis_tdata = std_logic_vector(to_unsigned(HEADER, 8)) then
|
||||
IF s_axis_tvalid = '1' THEN
|
||||
m_axis_tvalid <= '0';
|
||||
IF s_axis_tdata = STD_LOGIC_VECTOR(to_unsigned(HEADER, 8)) THEN
|
||||
state <= STREAMING;
|
||||
end if;
|
||||
end if;
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
WHEN STREAMING =>
|
||||
IF s_axis_tvalid = '1' THEN
|
||||
|
||||
when STREAMING =>
|
||||
if s_axis_tvalid = '1' then
|
||||
-- End of packet detected
|
||||
if s_axis_tdata = std_logic_vector(to_unsigned(FOOTER, 8)) then
|
||||
state <= IDLE;
|
||||
m_axis_tlast <= '1'; -- Let receiver know packet ends
|
||||
else
|
||||
IF s_axis_tdata = STD_LOGIC_VECTOR(to_unsigned(FOOTER, 8)) THEN
|
||||
-- Send the last data and transition to IDLE
|
||||
m_axis_tdata <= buffer_in; -- Send the last buffered data
|
||||
state <= IDLE;
|
||||
m_axis_tlast <= '1'; -- Let receiver know packet ends
|
||||
ELSE
|
||||
-- Valid payload: send to output
|
||||
if buffer_valid = '1' then
|
||||
if m_axis_tready = '1' then
|
||||
m_axis_tdata <= buffer_in;
|
||||
m_axis_tvalid <= '1';
|
||||
buffer_valid <= '0'; -- Clear the buffer
|
||||
end if;
|
||||
else
|
||||
if m_axis_tready = '1' then
|
||||
m_axis_tdata <= s_axis_tdata;
|
||||
m_axis_tvalid <= '1';
|
||||
else
|
||||
buffer_in <= s_axis_tdata;
|
||||
buffer_valid <= '1'; -- Mark buffer as valid
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
IF buffer_valid = '1' AND m_axis_tready = '1' THEN
|
||||
m_axis_tdata <= buffer_in;
|
||||
m_axis_tvalid <= '1';
|
||||
buffer_valid <= '0'; -- Clear the buffer
|
||||
END IF;
|
||||
|
||||
end case;
|
||||
end if;
|
||||
end if;
|
||||
end process;
|
||||
buffer_in <= s_axis_tdata;
|
||||
buffer_valid <= '1';
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
end architecture;
|
||||
END CASE;
|
||||
END IF;
|
||||
END IF;
|
||||
END PROCESS;
|
||||
|
||||
END ARCHITECTURE;
|
||||
@@ -7,11 +7,11 @@ USE IEEE.MATH_REAL.ALL;
|
||||
|
||||
ENTITY divider_by_3 IS
|
||||
GENERIC (
|
||||
BIT_DEPTH : INTEGER := 8
|
||||
BIT_DEPTH : INTEGER := 7
|
||||
);
|
||||
PORT (
|
||||
dividend : IN UNSIGNED(BIT_DEPTH + 1 DOWNTO 0);
|
||||
gray : OUT UNSIGNED(BIT_DEPTH - 1 DOWNTO 0)
|
||||
result : OUT UNSIGNED(BIT_DEPTH - 1 DOWNTO 0)
|
||||
);
|
||||
END divider_by_3;
|
||||
|
||||
@@ -20,12 +20,11 @@ ARCHITECTURE Behavioral OF divider_by_3 IS
|
||||
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;
|
||||
CONSTANT RESULT_WIDTH : INTEGER := (2 * BIT_DEPTH) + 2; -- 16 bit
|
||||
|
||||
-- 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 DOWNTO 0) := (OTHERS => '0');
|
||||
SIGNAL grayscale_value : UNSIGNED(BIT_DEPTH - 1 DOWNTO 0) := (OTHERS => '0');
|
||||
SIGNAL sum_extended : UNSIGNED(BIT_DEPTH + 1 DOWNTO 0) := (OTHERS => '0');
|
||||
SIGNAL scaled_result : UNSIGNED(RESULT_WIDTH - 1 DOWNTO 0) := (OTHERS => '0');
|
||||
BEGIN
|
||||
|
||||
-- Explanation of how the division by 3 is performed:
|
||||
@@ -37,15 +36,12 @@ 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
|
||||
rgb_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
|
||||
scaled_result <= rgb_sum_extended * TO_UNSIGNED(DIVISION_MULTIPLIER, BIT_DEPTH + 1);
|
||||
scaled_result <= RESIZE(sum_extended * TO_UNSIGNED(DIVISION_MULTIPLIER, BIT_DEPTH + 1), 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);
|
||||
|
||||
-- Assign the grayscale value to the output
|
||||
gray <= grayscale_value;
|
||||
result <= scaled_result(RESULT_WIDTH - 1 DOWNTO RESULT_WIDTH - BIT_DEPTH);
|
||||
|
||||
END Behavioral;
|
||||
@@ -1,41 +1,177 @@
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
LIBRARY ieee;
|
||||
USE ieee.std_logic_1164.ALL;
|
||||
USE ieee.numeric_std.ALL;
|
||||
|
||||
entity img_conv is
|
||||
generic(
|
||||
LOG2_N_COLS: POSITIVE :=8;
|
||||
LOG2_N_ROWS: POSITIVE :=8
|
||||
ENTITY img_conv IS
|
||||
GENERIC (
|
||||
LOG2_N_COLS : POSITIVE := 8;
|
||||
LOG2_N_ROWS : POSITIVE := 8
|
||||
);
|
||||
port (
|
||||
PORT (
|
||||
|
||||
clk : in std_logic;
|
||||
aresetn : in std_logic;
|
||||
clk : IN STD_LOGIC;
|
||||
aresetn : IN STD_LOGIC;
|
||||
|
||||
m_axis_tdata : out std_logic_vector(7 downto 0);
|
||||
m_axis_tvalid : out std_logic;
|
||||
m_axis_tready : in std_logic;
|
||||
m_axis_tlast : out std_logic;
|
||||
|
||||
conv_addr: out std_logic_vector(LOG2_N_COLS+LOG2_N_ROWS-1 downto 0);
|
||||
conv_data: in std_logic_vector(6 downto 0);
|
||||
m_axis_tdata : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
|
||||
m_axis_tvalid : OUT STD_LOGIC;
|
||||
m_axis_tready : IN STD_LOGIC;
|
||||
m_axis_tlast : OUT STD_LOGIC;
|
||||
|
||||
conv_addr : OUT STD_LOGIC_VECTOR(LOG2_N_COLS + LOG2_N_ROWS - 1 DOWNTO 0);
|
||||
conv_data : IN STD_LOGIC_VECTOR(6 DOWNTO 0);
|
||||
|
||||
start_conv : IN STD_LOGIC;
|
||||
done_conv : OUT STD_LOGIC
|
||||
|
||||
start_conv: in std_logic;
|
||||
done_conv: out std_logic
|
||||
|
||||
);
|
||||
end entity img_conv;
|
||||
END ENTITY img_conv;
|
||||
|
||||
architecture rtl of img_conv is
|
||||
ARCHITECTURE rtl OF img_conv IS
|
||||
|
||||
TYPE conv_mat_type IS ARRAY(0 TO 2, 0 TO 2) OF INTEGER;
|
||||
CONSTANT conv_mat : conv_mat_type := ((-1, -1, -1),(-1, 8, -1),(-1, -1, -1));
|
||||
|
||||
type conv_mat_type is array(0 to 2, 0 to 2) of integer;
|
||||
constant conv_mat : conv_mat_type := ((-1,-1,-1),(-1,8,-1),(-1,-1,-1));
|
||||
-- Definizione della finestra 3x3; ogni pixel <20> rappresentato da 8 bit
|
||||
TYPE window_array IS ARRAY(0 TO 2, 0 TO 2) OF STD_LOGIC_VECTOR(7 DOWNTO 0);
|
||||
SIGNAL window : window_array := (OTHERS => (OTHERS => (OTHERS => '0')));
|
||||
|
||||
|
||||
-- Parametri immagine
|
||||
CONSTANT IMG_WIDTH : INTEGER := 2 ** LOG2_N_COLS; -- Larghezza dell'immagine
|
||||
CONSTANT IMG_HEIGHT : INTEGER := 2 ** LOG2_N_ROWS; -- Altezza dell'immagine
|
||||
|
||||
begin
|
||||
-- Indirizzo corrente per la lettura dei pixel
|
||||
SIGNAL current_addr : STD_LOGIC_VECTOR(LOG2_N_COLS + LOG2_N_ROWS - 1 DOWNTO 0);
|
||||
|
||||
-- Variabili per il calcolo della convoluzione
|
||||
SIGNAL conv_sum : INTEGER := 0; -- Somma dei prodotti
|
||||
SIGNAL conv_out : STD_LOGIC_VECTOR(7 DOWNTO 0); -- Risultato della convoluzione
|
||||
|
||||
-- Stato della macchina a stati
|
||||
TYPE state_type IS (IDLE, LOAD_PIXEL, COMPUTE, OUTPUT);
|
||||
SIGNAL state : state_type := IDLE;
|
||||
|
||||
end architecture;
|
||||
-- Contatori per riga e colonna
|
||||
SIGNAL row, col : INTEGER RANGE 0 TO IMG_HEIGHT - 1 := 0;
|
||||
|
||||
BEGIN
|
||||
|
||||
-- Aggiornamento dell'indirizzo di lettura (mapping riga-colonna)
|
||||
conv_addr <= STD_LOGIC_VECTOR(to_unsigned(row * IMG_WIDTH + col, conv_addr'length));
|
||||
|
||||
-- Processo principale: macchina a stati per la gestione della convoluzione
|
||||
PROCESS (clk, aresetn)
|
||||
BEGIN
|
||||
IF aresetn = '0' THEN
|
||||
-- Reset asincrono: inizializza tutti i segnali
|
||||
state <= IDLE;
|
||||
row <= 0;
|
||||
col <= 0;
|
||||
window <= (OTHERS => (OTHERS => (OTHERS => '0')));
|
||||
conv_sum <= 0;
|
||||
conv_out <= (OTHERS => '0');
|
||||
m_axis_tdata <= (OTHERS => '0');
|
||||
m_axis_tvalid <= '0';
|
||||
m_axis_tlast <= '0';
|
||||
done_conv <= '0';
|
||||
current_addr <= (OTHERS => '0');
|
||||
ELSIF rising_edge(clk) THEN
|
||||
CASE state IS
|
||||
|
||||
-- Stato IDLE: attende il segnale di start per iniziare la convoluzione
|
||||
WHEN IDLE =>
|
||||
m_axis_tvalid <= '0';
|
||||
m_axis_tlast <= '0';
|
||||
IF start_conv = '1' THEN
|
||||
row <= 0;
|
||||
col <= 0;
|
||||
done_conv <= '0';
|
||||
-- Inizializza la finestra a zero per gestire il padding superiore
|
||||
window <= (OTHERS => (OTHERS => (OTHERS => '0')));
|
||||
state <= LOAD_PIXEL;
|
||||
END IF;
|
||||
|
||||
-- Stato LOAD_PIXEL: carica un nuovo pixel e aggiorna la finestra
|
||||
WHEN LOAD_PIXEL =>
|
||||
-- Aggiorna la finestra con il nuovo pixel (conv_data)
|
||||
-- Lo shifting viene realizzato per spostare i dati verso sinistra
|
||||
IF col = 0 THEN
|
||||
-- Per ogni riga della finestra si forza la colonna sinistra a zero
|
||||
FOR i IN 0 TO 2 LOOP
|
||||
window(i)(0) <= (OTHERS => '0');
|
||||
END LOOP;
|
||||
ELSE
|
||||
FOR i IN 0 TO 2 LOOP
|
||||
window(i)(0) <= window(i)(1);
|
||||
window(i)(1) <= window(i)(2);
|
||||
END LOOP;
|
||||
END IF;
|
||||
|
||||
-- Aggiorna la colonna destra della finestra con il nuovo pixel
|
||||
FOR i IN 0 TO 2 LOOP
|
||||
window(i)(2) <= conv_data;
|
||||
END LOOP;
|
||||
|
||||
-- Aggiorna i contatori per scorrere l'immagine
|
||||
IF col = IMG_WIDTH - 1 THEN
|
||||
col <= 0;
|
||||
IF row = IMG_HEIGHT - 1 THEN
|
||||
state <= COMPUTE;
|
||||
ELSE
|
||||
row <= row + 1;
|
||||
END IF;
|
||||
ELSE
|
||||
col <= col + 1;
|
||||
END IF;
|
||||
|
||||
state <= COMPUTE;
|
||||
|
||||
-- Stato COMPUTE: esegue il calcolo della convoluzione
|
||||
WHEN COMPUTE =>
|
||||
-- Gestione dei bordi: imposta il risultato a zero se la finestra non <20> completa
|
||||
IF (row = 0) OR (row = IMG_HEIGHT - 1) OR (col = 0) OR (col = IMG_WIDTH - 1) THEN
|
||||
conv_sum <= 0;
|
||||
ELSE
|
||||
conv_sum <= 0;
|
||||
-- Moltiplica cella per cella e somma i prodotti
|
||||
FOR i IN 0 TO 2 LOOP
|
||||
FOR j IN 0 TO 2 LOOP
|
||||
conv_sum <= conv_sum + conv_mat(i, j) * to_integer(unsigned(window(i)(j)));
|
||||
END LOOP;
|
||||
END LOOP;
|
||||
END IF;
|
||||
|
||||
-- Saturazione del risultato
|
||||
IF conv_sum < 0 THEN
|
||||
conv_out <= STD_LOGIC_VECTOR(to_unsigned(0, 8));
|
||||
ELSIF conv_sum >= 256 THEN
|
||||
conv_out <= STD_LOGIC_VECTOR(to_unsigned(255, 8));
|
||||
ELSE
|
||||
conv_out <= STD_LOGIC_VECTOR(to_unsigned(conv_sum, 8));
|
||||
END IF;
|
||||
|
||||
state <= OUTPUT;
|
||||
|
||||
-- Stato OUTPUT: invia il risultato tramite l'interfaccia AXIS
|
||||
WHEN OUTPUT =>
|
||||
IF m_axis_tready = '1' THEN
|
||||
m_axis_tdata <= conv_out;
|
||||
m_axis_tvalid <= '1';
|
||||
-- Se siamo sull'ultimo pixel dell'immagine, segnaliamo TLAST e il completamento
|
||||
IF (row = IMG_HEIGHT - 1) AND (col = IMG_WIDTH - 1) THEN
|
||||
m_axis_tlast <= '1';
|
||||
done_conv <= '1';
|
||||
state <= IDLE;
|
||||
ELSE
|
||||
m_axis_tlast <= '0';
|
||||
state <= LOAD_PIXEL;
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
-- Stato di default: ritorna a IDLE
|
||||
WHEN OTHERS =>
|
||||
state <= IDLE;
|
||||
END CASE;
|
||||
END IF;
|
||||
END PROCESS;
|
||||
|
||||
END ARCHITECTURE;
|
||||
@@ -30,29 +30,30 @@ ARCHITECTURE Behavioral OF rgb2gray IS
|
||||
|
||||
COMPONENT divider_by_3
|
||||
GENERIC (
|
||||
BIT_DEPTH : INTEGER := 8
|
||||
BIT_DEPTH : INTEGER := 7
|
||||
);
|
||||
PORT (
|
||||
dividend : IN UNSIGNED(BIT_DEPTH + 1 DOWNTO 0);
|
||||
gray : OUT UNSIGNED(BIT_DEPTH - 1 DOWNTO 0));
|
||||
result : OUT UNSIGNED(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;
|
||||
|
||||
SIGNAL r_val, g_val : unsigned(7 DOWNTO 0);
|
||||
SIGNAL sum : unsigned(9 DOWNTO 0);
|
||||
SIGNAL gray : UNSIGNED(7 DOWNTO 0);
|
||||
SIGNAL sum : unsigned(8 DOWNTO 0);
|
||||
SIGNAL gray : UNSIGNED(6 DOWNTO 0);
|
||||
SIGNAL send_data : STD_LOGIC := '0';
|
||||
|
||||
BEGIN
|
||||
|
||||
DIVIDER : divider_by_3
|
||||
GENERIC MAP(
|
||||
BIT_DEPTH => 8
|
||||
BIT_DEPTH => 7
|
||||
)
|
||||
PORT MAP(
|
||||
dividend => sum,
|
||||
gray => gray
|
||||
result => gray
|
||||
);
|
||||
|
||||
PROCESS (clk)
|
||||
@@ -70,32 +71,43 @@ BEGIN
|
||||
sum <= (OTHERS => '0');
|
||||
ELSE
|
||||
-- Default control signals
|
||||
s_axis_tready <= '1';
|
||||
m_axis_tlast <= '0';
|
||||
m_axis_tlast <= s_axis_tlast;
|
||||
m_axis_tvalid <= '0';
|
||||
|
||||
-- If downstream is ready, send the grayscale pixel
|
||||
IF m_axis_tready = '1' THEN
|
||||
m_axis_tdata <= STD_LOGIC_VECTOR(gray);
|
||||
m_axis_tlast <= s_axis_tlast;
|
||||
IF m_axis_tready = '1' AND send_data = '1' THEN
|
||||
m_axis_tdata <= STD_LOGIC_VECTOR('0' & gray);
|
||||
m_axis_tvalid <= '1';
|
||||
send_data <= '0';
|
||||
END IF;
|
||||
|
||||
CASE state IS
|
||||
WHEN WAIT_R =>
|
||||
IF s_axis_tvalid = '1' THEN
|
||||
r_val <= unsigned(s_axis_tdata);
|
||||
|
||||
IF m_axis_tready = '0' THEN
|
||||
s_axis_tready <= '0';
|
||||
END IF;
|
||||
|
||||
state <= WAIT_G;
|
||||
END IF;
|
||||
|
||||
WHEN WAIT_G =>
|
||||
IF s_axis_tvalid = '1' THEN
|
||||
g_val <= unsigned(s_axis_tdata);
|
||||
state <= WAIT_B;
|
||||
|
||||
IF m_axis_tready = '1' THEN
|
||||
s_axis_tready <= '1';
|
||||
state <= WAIT_B;
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
WHEN WAIT_B =>
|
||||
IF s_axis_tvalid = '1' THEN
|
||||
sum <= ('0' & '0' & r_val) + ('0' & '0' & g_val) + ('0' & '0' & unsigned(s_axis_tdata));
|
||||
m_axis_tvalid <= '1';
|
||||
sum <= RESIZE(r_val + g_val + unsigned(s_axis_tdata), 9);
|
||||
send_data <= '1';
|
||||
|
||||
state <= WAIT_R;
|
||||
END IF;
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
<Option Name="IPStaticSourceDir" Val="$PIPUSERFILESDIR/ipstatic"/>
|
||||
<Option Name="EnableBDX" Val="FALSE"/>
|
||||
<Option Name="DSABoardId" Val="basys3"/>
|
||||
<Option Name="WTXSimLaunchSim" Val="50"/>
|
||||
<Option Name="WTXSimLaunchSim" Val="84"/>
|
||||
<Option Name="WTModelSimLaunchSim" Val="0"/>
|
||||
<Option Name="WTQuestaLaunchSim" Val="0"/>
|
||||
<Option Name="WTIesLaunchSim" Val="0"/>
|
||||
|
||||
Reference in New Issue
Block a user