Refactor and update various components in LAB2 design

- Updated node connections in lab_2.bda and pak_depak.bda to correct source and target references.
- Modified pak_depak_wrapper.vhd to reflect the correct timestamp.
- Rearranged the order of components in pak_depak.bd for clarity and consistency.
- Adjusted BRAM writer logic in bram_writer.vhd for improved data handling and comments for clarity.
- Enhanced depacketizer.vhd with additional comments and logic adjustments for better data reception.
- Refined divider_by_3.vhd to optimize division calculations and improve clarity in comments.
- Improved img_conv.vhd with better state management and comments for the convolution process.
- Updated led_blinker.vhd to enhance readability and maintainability with clearer comments.
- Enhanced packetizer.vhd to improve data handling and added comments for better understanding.
- Adjusted rgb2gray.vhd to include standard library comments for consistency.
- Updated test.py to improve image processing logic and added visualization for differences.
- Added new binary files for test_nopath.exe and archived project files for lab2 and pak_depak.
- Updated Vivado project files to ensure correct paths and settings for synthesis and implementation.
This commit is contained in:
2025-04-25 00:43:10 +02:00
parent 5cabb20fdd
commit 835b4d0ab8
21 changed files with 535 additions and 470 deletions

View File

@@ -1,6 +1,8 @@
---------- DEFAULT LIBRARIES -------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
------------------------------------
ENTITY bram_writer IS
GENERIC (
@@ -79,7 +81,7 @@ BEGIN
-- Assign AXIS ready signal
s_axis_tready <= s_axis_tready_int;
-- Binding BRAM data to output
-- Output only the lower 7 bits of BRAM data
conv_data <= bram_data_out(6 DOWNTO 0);
-- Select BRAM address based on state
@@ -116,9 +118,8 @@ BEGIN
-- State machine for data handling
CASE state IS
WHEN IDLE =>
-- Wait for valid input data
-- Wait for valid input data to start writing
IF s_axis_tvalid = '1' AND s_axis_tready_int = '1' THEN
-- valid data received, start receiving
wr_addr <= (OTHERS => '0');
bram_we <= '1'; -- Enable write to BRAM
bram_data_in <= s_axis_tdata; -- Write data to BRAM
@@ -145,7 +146,7 @@ BEGIN
END IF;
WHEN CHECK_DATA =>
-- Check for overflow/underflow
-- Check for overflow/underflow after data reception
IF overflow_flag = '1' THEN
overflow <= '1';
overflow_flag <= '0';
@@ -156,7 +157,6 @@ BEGIN
ELSE
-- Data reception complete, start convolution
write_ok <= '1';
s_axis_tready_int <= '0';
start_conv <= '1';
state <= CONVOLUTION;

View File

@@ -1,6 +1,8 @@
---------- DEFAULT LIBRARIES -------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
------------------------------------
ENTITY depacketizer IS
@@ -21,7 +23,7 @@ ENTITY depacketizer IS
m_axis_tready : IN STD_LOGIC;
m_axis_tlast : OUT STD_LOGIC
);
END ENTITY depacketizer;
ARCHITECTURE rtl OF depacketizer IS
@@ -51,7 +53,7 @@ BEGIN
state <= WAITING_HEADER;
m_axis_tdata_int <= (OTHERS => '0');
m_axis_tlast_int <= '0';
s_axis_tready_int <= '1';
s_axis_tready_int <= '0';
m_axis_tvalid_int <= '0';
data_buffer <= (OTHERS => '0');
data_ready <= '0';
@@ -63,6 +65,7 @@ BEGIN
s_axis_tready_int <= '1';
m_axis_tvalid_int <= '0';
data_ready <= '0';
-- Wait for header value to start receiving data
IF s_axis_tvalid = '1' AND s_axis_tready_int = '1' THEN
IF s_axis_tdata = STD_LOGIC_VECTOR(to_unsigned(HEADER, 8)) THEN
state <= RECEIVING;
@@ -75,6 +78,7 @@ BEGIN
m_axis_tdata_int <= data_buffer;
m_axis_tvalid_int <= '1';
-- Check for footer value to signal end of packet
IF s_axis_tdata = STD_LOGIC_VECTOR(to_unsigned(FOOTER, 8)) THEN
m_axis_tlast_int <= '1';
state <= WAITING_HEADER;

View File

@@ -16,35 +16,22 @@ ENTITY divider_by_3 IS
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 N : INTEGER := BIT_DEPTH + 3;
CONSTANT DIVISION_MULTIPLIER : INTEGER := INTEGER(round(real(2 ** N) / 3.0));
CONSTANT OFFSET : INTEGER := 2 ** (N - 1);
-- Constant to calculate the length of the result signal
CONSTANT RESULT_WIDTH : INTEGER := (2 * BIT_DEPTH) + 2; -- 16 bit
CONSTANT MULT_WIDTH : INTEGER := BIT_DEPTH + 1 + N;
-- Signals to hold the sum of the RGB channels and the intermediate results
SIGNAL sum_extended : UNSIGNED(BIT_DEPTH + 1 DOWNTO 0) := (OTHERS => '0');
SIGNAL scaled_result : UNSIGNED(RESULT_WIDTH - 1 DOWNTO 0) := (OTHERS => '0');
SIGNAL mult_result : UNSIGNED(MULT_WIDTH - 1 DOWNTO 0);
SIGNAL sum_with_offset : UNSIGNED(MULT_WIDTH - 1 DOWNTO 0);
BEGIN
-- Moltiplicazione senza perdita di bit
mult_result <= dividend * TO_UNSIGNED(DIVISION_MULTIPLIER, N - 1);
-- 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
-- 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);
-- Multiply the sum by the precomputed multiplier
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
result <= scaled_result(RESULT_WIDTH - 1 DOWNTO RESULT_WIDTH - BIT_DEPTH);
-- Somma con offset senza perdita di bit
sum_with_offset <= mult_result + TO_UNSIGNED(OFFSET, MULT_WIDTH);
-- Estrazione risultato arrotondato
result <= sum_with_offset(MULT_WIDTH - 2 DOWNTO MULT_WIDTH - BIT_DEPTH -1);
END Behavioral;

View File

@@ -1,6 +1,8 @@
---------- DEFAULT LIBRARIES -------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
------------------------------------
ENTITY img_conv IS
GENERIC (
@@ -27,18 +29,23 @@ ENTITY img_conv IS
END ENTITY img_conv;
ARCHITECTURE rtl OF img_conv IS
-- 3x3 convolution matrix (kernel)
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));
-- Offset arrays for kernel position relative to current pixel
TYPE offset_array IS ARRAY(0 TO 2) OF INTEGER;
CONSTANT offset : offset_array := (-1, 0, 1);
-- State machine for convolution process
TYPE state_type IS (IDLE, START_CONVOLUTING, CONVOLUTING, WAIT_READY);
SIGNAL state : state_type := IDLE;
-- Current column and row in the image
SIGNAL col : UNSIGNED(LOG2_N_COLS - 1 DOWNTO 0) := (OTHERS => '0');
SIGNAL row : UNSIGNED(LOG2_N_ROWS - 1 DOWNTO 0) := (OTHERS => '0');
-- Indices for kernel matrix position (previous, current, next)
SIGNAL col_mat_idx_prv : INTEGER := 0;
SIGNAL row_mat_idx_prv : INTEGER := 0;
@@ -48,10 +55,12 @@ ARCHITECTURE rtl OF img_conv IS
SIGNAL col_mat_idx_nxt : INTEGER := 0;
SIGNAL row_mat_idx_nxt : INTEGER := 0;
-- Accumulators for convolution result
SIGNAL conv_data_out, conv_data_int, conv_data_mul : SIGNED(10 DOWNTO 0) := (OTHERS => '0');
SIGNAL m_axis_tvalid_int : STD_LOGIC;
-- Control signals for data flow and pipelining
SIGNAL trigger, prepare_data, ready_data, send_data : STD_LOGIC := '0';
SIGNAL tlast : STD_LOGIC := '0';
SIGNAL save_data : STD_LOGIC := '0';
@@ -65,7 +74,7 @@ BEGIN
IF rising_edge(clk) THEN
IF aresetn = '0' THEN
-- Reset all signals
-- Reset all signals and state
state <= IDLE;
col <= (OTHERS => '0');
@@ -100,13 +109,13 @@ BEGIN
conv_addr <= (OTHERS => '0');
ELSE
-- Default values for signals
-- Default values for signals at each clock
done_conv <= '0';
m_axis_tlast <= '0';
CASE state IS
WHEN IDLE =>
-- Default values in IDLE
-- Wait for start_conv signal to begin convolution
done_conv <= '0';
m_axis_tlast <= '0';
m_axis_tvalid_int <= '0';
@@ -125,7 +134,7 @@ BEGIN
IF start_conv = '1' THEN
state <= START_CONVOLUTING;
-- Reset the convolution matrix position
-- Reset image pointers
row <= (OTHERS => '0');
col <= (OTHERS => '0');
@@ -156,6 +165,7 @@ BEGIN
END IF;
WHEN START_CONVOLUTING =>
-- Start the convolution process or resume from the previous state
conv_addr <= STD_LOGIC_VECTOR(
TO_UNSIGNED(
(TO_INTEGER(col) + offset(col_mat_idx_nxt)) +
@@ -167,7 +177,7 @@ BEGIN
state <= CONVOLUTING;
WHEN CONVOLUTING =>
-- Convolution operation: accumulate the result of current pixel and kernel coefficient
-- Perform convolution: multiply input by kernel coefficient and accumulate
conv_addr <= STD_LOGIC_VECTOR(
TO_UNSIGNED(
(TO_INTEGER(col) + offset(col_mat_idx_nxt)) +
@@ -191,7 +201,7 @@ BEGIN
trigger <= '0';
WHEN WAIT_READY =>
-- Wait for m_axis_tready signal to be asserted before sending data and continue convolution
-- Wait for m_axis_tready signal before sending data and continuing
IF m_axis_tready = '1' THEN
conv_addr <= STD_LOGIC_VECTOR(
TO_UNSIGNED(
@@ -205,6 +215,7 @@ BEGIN
state <= CONVOLUTING;
END IF;
-- Save convolution result only once per WAIT_READY state
IF save_data = '0' THEN
conv_data_mul <= RESIZE(
SIGNED('0' & conv_data) * TO_SIGNED(conv_mat(col_mat_idx_prv, row_mat_idx_prv), 5),
@@ -228,11 +239,12 @@ BEGIN
m_axis_tvalid_int <= '0';
END IF;
-- Wait for m_axis_tready signal to be asserted before continuing convolution
-- If output not ready, wait before continuing
IF m_axis_tready = '0' AND m_axis_tvalid_int = '1' THEN
state <= WAIT_READY;
END IF;
-- Send data when ready and output interface is available
IF send_data = '1' AND (m_axis_tvalid_int = '0' OR m_axis_tready = '1') THEN
m_axis_tvalid_int <= '1';
@@ -243,6 +255,7 @@ BEGIN
tlast <= '0';
END IF;
-- Clamp output to 0..127 range
IF conv_data_out < 0 THEN
m_axis_tdata <= STD_LOGIC_VECTOR(TO_UNSIGNED(0, m_axis_tdata'length));
ELSIF conv_data_out > 127 THEN
@@ -256,8 +269,9 @@ BEGIN
send_data <= '0';
END IF;
-- Main kernel/image sweep logic
IF state = CONVOLUTING OR state = START_CONVOLUTING OR (state = WAIT_READY AND m_axis_tready = '1') THEN
-- Update convolution matrix position, image position and check for zero padding
-- Update kernel and image indices, handle zero padding and end conditions
IF col_mat_idx_nxt = 1 AND col = (2 ** LOG2_N_COLS - 1) THEN
IF row_mat_idx_nxt = 1 AND row = (2 ** LOG2_N_ROWS - 1) THEN
-- Last pixel and last kernel position: finish convolution
@@ -323,10 +337,12 @@ BEGIN
END IF;
prepare_data <= trigger; -- Pipeline trigger for data output waiting for last data
-- Pipeline control for output data
prepare_data <= trigger;
ready_data <= prepare_data;
send_data <= ready_data;
-- Update previous and current kernel indices
row_mat_idx_prv <= row_mat_idx;
col_mat_idx_prv <= col_mat_idx;

View File

@@ -1,78 +1,86 @@
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
---------- DEFAULT LIBRARIES -------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
USE ieee.math_real.ALL;
------------------------------------
entity led_blinker is
generic (
CLK_PERIOD_NS : positive := 10;
BLINK_PERIOD_MS : positive := 1000;
N_BLINKS : positive := 4
ENTITY led_blinker IS
GENERIC (
CLK_PERIOD_NS : POSITIVE := 10;
BLINK_PERIOD_MS : POSITIVE := 1000;
N_BLINKS : POSITIVE := 4
);
port (
clk : in std_logic;
aresetn : in std_logic;
start_blink : in std_logic;
led : out std_logic
PORT (
clk : IN STD_LOGIC;
aresetn : IN STD_LOGIC;
start_blink : IN STD_LOGIC;
led : OUT STD_LOGIC
);
end entity;
END ENTITY;
architecture rtl of led_blinker is
-- Calcoli per larghezze e valori massimi
constant CLK_PER_MS : integer := 1_000_000 / CLK_PERIOD_NS;
constant MAX_COUNT : integer := CLK_PER_MS * BLINK_PERIOD_MS;
constant CNT_WIDTH : integer := integer(ceil(log2(real(MAX_COUNT))));
constant BLINK_WIDTH : integer := integer(ceil(log2(real(N_BLINKS + 1))));
ARCHITECTURE rtl OF led_blinker IS
-- Calculations for widths and maximum values
CONSTANT CLK_PER_MS : INTEGER := 1_000_000 / CLK_PERIOD_NS; -- Clock cycles per millisecond
CONSTANT MAX_COUNT : INTEGER := CLK_PER_MS * BLINK_PERIOD_MS; -- Counter max value for one blink period
CONSTANT CNT_WIDTH : INTEGER := INTEGER(ceil(log2(real(MAX_COUNT)))); -- Bit width for counter
CONSTANT BLINK_WIDTH : INTEGER := INTEGER(ceil(log2(real(N_BLINKS + 1)))); -- Bit width for blink counter
signal counter : unsigned(CNT_WIDTH-1 downto 0) := (others => '0');
signal blink_cnt : unsigned(BLINK_WIDTH-1 downto 0) := (others => '0');
signal blinking : std_logic := '0';
signal led_reg : std_logic := '0';
SIGNAL counter : unsigned(CNT_WIDTH - 1 DOWNTO 0) := (OTHERS => '0'); -- Main blink period counter
SIGNAL blink_cnt : unsigned(BLINK_WIDTH - 1 DOWNTO 0) := (OTHERS => '0'); -- Number of completed blinks
SIGNAL blinking : STD_LOGIC := '0'; -- Indicates if blinking is active
SIGNAL led_reg : STD_LOGIC := '0'; -- Register for LED output
signal start_prev : std_logic := '0';
signal start_edge : std_logic;
SIGNAL start_prev : STD_LOGIC := '0'; -- Previous value of start_blink
SIGNAL start_edge : STD_LOGIC; -- Rising edge detector for start_blink
begin
BEGIN
-- Output assignment
led <= led_reg;
process(clk, aresetn)
begin
if aresetn = '0' then
counter <= (others => '0');
blink_cnt <= (others => '0');
blinking <= '0';
led_reg <= '0';
-- Main process: handles blinking logic and state
PROCESS (clk, aresetn)
BEGIN
IF aresetn = '0' THEN
-- Asynchronous reset: clear all registers and outputs
counter <= (OTHERS => '0');
blink_cnt <= (OTHERS => '0');
blinking <= '0';
led_reg <= '0';
start_prev <= '0';
start_edge <= '0';
elsif rising_edge(clk) then
-- Rileva fronte di salita di start_blink
start_edge <= start_blink and not start_prev;
ELSIF rising_edge(clk) THEN
-- Detect rising edge on start_blink input
start_edge <= start_blink AND NOT start_prev;
start_prev <= start_blink;
if blinking = '0' then
if start_edge = '1' then
blinking <= '1';
counter <= (others => '0');
blink_cnt <= (others => '0');
led_reg <= '1';
end if;
else -- blinking = '1'
if counter = to_unsigned(MAX_COUNT - 1, counter'length) then
counter <= (others => '0');
led_reg <= not led_reg;
IF blinking = '0' THEN
-- Idle state: wait for start_blink rising edge to begin blinking
IF start_edge = '1' THEN
blinking <= '1';
counter <= (OTHERS => '0');
blink_cnt <= (OTHERS => '0');
led_reg <= '1'; -- Start with LED ON
END IF;
ELSE -- blinking = '1'
-- Blinking state: count clock cycles for ON/OFF periods
IF counter = to_unsigned(MAX_COUNT - 1, counter'length) THEN
counter <= (OTHERS => '0');
led_reg <= NOT led_reg; -- Toggle LED state
if led_reg = '1' then -- fine fase ON
IF led_reg = '1' THEN -- End of ON phase
blink_cnt <= blink_cnt + 1;
if blink_cnt + 1 = to_unsigned(N_BLINKS, blink_cnt'length) then
blinking <= '0';
led_reg <= '0';
end if;
end if;
else
counter <= counter + 1;
end if;
end if;
end if;
end process;
end architecture;
-- Check if required number of blinks is reached
IF blink_cnt + 1 = to_unsigned(N_BLINKS, blink_cnt'length) THEN
blinking <= '0'; -- Stop blinking
led_reg <= '0'; -- Ensure LED is OFF at end
END IF;
END IF;
ELSE
counter <= counter + 1; -- Increment counter
END IF;
END IF;
END IF;
END PROCESS;
END ARCHITECTURE;

View File

@@ -1,6 +1,8 @@
---------- DEFAULT LIBRARIES -------
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;
------------------------------------
ENTITY packetizer IS
GENERIC (
@@ -32,7 +34,7 @@ ARCHITECTURE rtl OF packetizer IS
SIGNAL s_axis_tready_int : STD_LOGIC;
SIGNAL m_axis_tvalid_int : STD_LOGIC;
SIGNAL trigger : STD_LOGIC := '0';
SIGNAL trigger : STD_LOGIC := '0'; -- Used to control when to send data
BEGIN
@@ -45,57 +47,62 @@ BEGIN
IF rising_edge(clk) THEN
IF aresetn = '0' THEN
state <= SENDING_HEADER;
data_buffer <= (OTHERS => '0');
m_axis_tdata <= (OTHERS => '0');
s_axis_tready_int <= '0';
m_axis_tvalid_int <= '0';
ELSE
-- Input data - slave
s_axis_tready_int <= m_axis_tready;
IF s_axis_tvalid = '1' AND s_axis_tready_int = '1' THEN
data_buffer <= s_axis_tdata;
END IF;
-- Output data - master
-- Clear valid flag when master interface is ready
IF m_axis_tready = '1' THEN
m_axis_tvalid_int <= '0';
END IF;
IF trigger = '1' AND (m_axis_tvalid_int = '0' OR m_axis_tready = '1') THEN
m_axis_tvalid_int <= '1';
m_axis_tdata <= data_buffer;
-- Send data when triggered
IF trigger = '1' THEN
IF (m_axis_tvalid_int = '0' OR m_axis_tready = '1') THEN
m_axis_tvalid_int <= '1';
m_axis_tdata <= data_buffer;
s_axis_tready_int <= '1'; -- Enable slave interface
trigger <= '0';
trigger <= '0';
ELSE
s_axis_tready_int <= '0'; -- Block slave interface to avoid data loss
END IF;
END IF;
-- State machine for packetization
CASE state IS
WHEN SENDING_HEADER =>
s_axis_tready_int <= '1'; -- Enable slave interface
IF s_axis_tvalid = '1' AND s_axis_tready_int = '1' THEN
m_axis_tdata <= STD_LOGIC_VECTOR(to_unsigned(HEADER, 8)); -- Prepare header
m_axis_tvalid_int <= '1'; --Send header
m_axis_tdata <= STD_LOGIC_VECTOR(to_unsigned(HEADER, 8)); -- Send header
m_axis_tvalid_int <= '1';
s_axis_tready_int <= m_axis_tready;
IF s_axis_tlast = '1' THEN
s_axis_tready_int <= '0'; -- Block the slave interface to avoid data loss
s_axis_tready_int <= '0'; -- Block slave interface if last
state <= SENDING_FOOTER;
ELSE
state <= STREAMING;
END IF;
trigger <= '1';
END IF;
WHEN STREAMING =>
IF s_axis_tvalid = '1' AND s_axis_tready_int = '1' THEN
s_axis_tready_int <= m_axis_tready;
IF s_axis_tlast = '1' THEN
s_axis_tready_int <= '0'; -- Block the slave interface to avoid data loss
s_axis_tready_int <= '0'; -- Block slave interface if last
state <= SENDING_FOOTER;
END IF;
@@ -104,7 +111,7 @@ BEGIN
WHEN SENDING_FOOTER =>
IF m_axis_tvalid_int = '0' OR m_axis_tready = '1' THEN
s_axis_tready_int <= '0'; -- Block the slave interface to avoid data loss
s_axis_tready_int <= '0'; -- Block slave interface
data_buffer <= STD_LOGIC_VECTOR(to_unsigned(FOOTER, 8)); -- Send footer
m_axis_tvalid_int <= '1';
@@ -119,4 +126,4 @@ BEGIN
END PROCESS;
END ARCHITECTURE rtl;
END ARCHITECTURE;

View File

@@ -1,6 +1,8 @@
---------- DEFAULT LIBRARIES -------
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
------------------------------------
ENTITY rgb2gray IS
PORT (