Refactor img_conv and tb_img_conv: enhance state management, improve signal handling, and add varied memory initialization for convolution processing
This commit is contained in:
@@ -17,90 +17,132 @@
|
||||
-- Additional Comments:
|
||||
--
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
|
||||
library IEEE;
|
||||
use IEEE.STD_LOGIC_1164.ALL;
|
||||
LIBRARY IEEE;
|
||||
USE IEEE.STD_LOGIC_1164.ALL;
|
||||
|
||||
-- Uncomment the following library declaration if using
|
||||
-- arithmetic functions with Signed or Unsigned values
|
||||
use IEEE.NUMERIC_STD.ALL;
|
||||
USE IEEE.NUMERIC_STD.ALL;
|
||||
|
||||
-- Uncomment the following library declaration if instantiating
|
||||
-- any Xilinx leaf cells in this code.
|
||||
--library UNISIM;
|
||||
--use UNISIM.VComponents.all;
|
||||
|
||||
entity img_conv_tb is
|
||||
-- Port ( );
|
||||
end img_conv_tb;
|
||||
ENTITY img_conv_tb IS
|
||||
-- Port ( );
|
||||
END img_conv_tb;
|
||||
|
||||
architecture Behavioral of img_conv_tb is
|
||||
ARCHITECTURE Behavioral OF img_conv_tb IS
|
||||
|
||||
component img_conv is
|
||||
generic(
|
||||
LOG2_N_COLS: POSITIVE :=8;
|
||||
LOG2_N_ROWS: POSITIVE :=8
|
||||
COMPONENT 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;
|
||||
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);
|
||||
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 component;
|
||||
END COMPONENT;
|
||||
|
||||
constant LOG2_N_COLS: POSITIVE :=2;
|
||||
constant LOG2_N_ROWS: POSITIVE :=2;
|
||||
CONSTANT LOG2_N_COLS : POSITIVE := 2;
|
||||
CONSTANT LOG2_N_ROWS : POSITIVE := 2;
|
||||
|
||||
type mem_type is array(0 to (2**LOG2_N_COLS)*(2**LOG2_N_ROWS)-1) of std_logic_vector(6 downto 0);
|
||||
TYPE mem_type IS ARRAY(0 TO (2 ** LOG2_N_COLS) * (2 ** LOG2_N_ROWS) - 1) OF STD_LOGIC_VECTOR(6 DOWNTO 0);
|
||||
|
||||
signal mem : mem_type := (0=>"0000001",others => (others => '0'));
|
||||
-- Fill memory with more varied values
|
||||
SIGNAL mem : mem_type := (
|
||||
0 => "0000001",
|
||||
1 => "0101010",
|
||||
2 => "0011100",
|
||||
3 => "1110001",
|
||||
4 => "0001011",
|
||||
5 => "0110110",
|
||||
6 => "1001001",
|
||||
7 => "1111111",
|
||||
8 => "0000111",
|
||||
9 => "0010010",
|
||||
10 => "0100101",
|
||||
11 => "0111000",
|
||||
12 => "1001100",
|
||||
13 => "1011011",
|
||||
14 => "1100110",
|
||||
15 => "1010101"
|
||||
);
|
||||
|
||||
signal clk : std_logic :='0';
|
||||
signal aresetn : std_logic :='0';
|
||||
SIGNAL clk : STD_LOGIC := '0';
|
||||
SIGNAL aresetn : STD_LOGIC := '0';
|
||||
|
||||
signal m_axis_tdata : std_logic_vector(7 downto 0);
|
||||
signal m_axis_tvalid : std_logic;
|
||||
signal m_axis_tready : std_logic;
|
||||
signal m_axis_tlast : std_logic;
|
||||
SIGNAL m_axis_tdata : STD_LOGIC_VECTOR(7 DOWNTO 0);
|
||||
SIGNAL m_axis_tvalid : STD_LOGIC;
|
||||
SIGNAL m_axis_tready : STD_LOGIC;
|
||||
SIGNAL m_axis_tlast : STD_LOGIC;
|
||||
|
||||
signal conv_addr: std_logic_vector(LOG2_N_COLS+LOG2_N_ROWS-1 downto 0);
|
||||
signal conv_data: std_logic_vector(6 downto 0);
|
||||
SIGNAL conv_addr : STD_LOGIC_VECTOR(LOG2_N_COLS + LOG2_N_ROWS - 1 DOWNTO 0);
|
||||
SIGNAL conv_data : STD_LOGIC_VECTOR(6 DOWNTO 0);
|
||||
|
||||
signal start_conv: std_logic;
|
||||
signal done_conv: std_logic;
|
||||
SIGNAL start_conv : STD_LOGIC;
|
||||
SIGNAL done_conv : STD_LOGIC;
|
||||
|
||||
begin
|
||||
SIGNAL tready_block_req : STD_LOGIC := '0';
|
||||
|
||||
m_axis_tready<='1';
|
||||
BEGIN
|
||||
|
||||
clk <= not clk after 5 ns;
|
||||
-- m_axis_tready logic with blocking step
|
||||
PROCESS (clk)
|
||||
VARIABLE block_counter : INTEGER := 0;
|
||||
VARIABLE tready_blocked : BOOLEAN := FALSE;
|
||||
BEGIN
|
||||
IF rising_edge(clk) THEN
|
||||
IF tready_block_req = '1' AND NOT tready_blocked THEN
|
||||
tready_blocked := TRUE;
|
||||
block_counter := 0;
|
||||
END IF;
|
||||
|
||||
process (clk)
|
||||
begin
|
||||
if(rising_edge(clk)) then
|
||||
conv_data<=mem(to_integer(unsigned(conv_addr)));
|
||||
end if;
|
||||
end process;
|
||||
IF tready_blocked THEN
|
||||
IF block_counter < 19 THEN
|
||||
m_axis_tready <= '0';
|
||||
block_counter := block_counter + 1;
|
||||
ELSE
|
||||
m_axis_tready <= '1';
|
||||
tready_blocked := FALSE;
|
||||
block_counter := 0;
|
||||
END IF;
|
||||
ELSE
|
||||
m_axis_tready <= '1';
|
||||
END IF;
|
||||
END IF;
|
||||
END PROCESS;
|
||||
|
||||
img_conv_inst: img_conv
|
||||
generic map(
|
||||
clk <= NOT clk AFTER 5 ns;
|
||||
|
||||
PROCESS (clk)
|
||||
BEGIN
|
||||
IF (rising_edge(clk)) THEN
|
||||
conv_data <= mem(to_integer(unsigned(conv_addr)));
|
||||
END IF;
|
||||
END PROCESS;
|
||||
|
||||
img_conv_inst : img_conv
|
||||
GENERIC MAP(
|
||||
LOG2_N_COLS => LOG2_N_COLS,
|
||||
LOG2_N_ROWS => LOG2_N_ROWS
|
||||
)
|
||||
port map(
|
||||
PORT MAP(
|
||||
clk => clk,
|
||||
aresetn => aresetn,
|
||||
m_axis_tdata => m_axis_tdata,
|
||||
@@ -113,16 +155,31 @@ begin
|
||||
done_conv => done_conv
|
||||
);
|
||||
|
||||
process
|
||||
begin
|
||||
wait for 10 ns;
|
||||
aresetn<='1';
|
||||
wait until rising_edge(clk);
|
||||
start_conv<='1';
|
||||
wait until rising_edge(clk);
|
||||
start_conv<='0';
|
||||
wait;
|
||||
end process;
|
||||
PROCESS
|
||||
BEGIN
|
||||
WAIT FOR 10 ns;
|
||||
aresetn <= '1';
|
||||
WAIT UNTIL rising_edge(clk);
|
||||
start_conv <= '1';
|
||||
WAIT UNTIL rising_edge(clk);
|
||||
start_conv <= '0';
|
||||
|
||||
-- Wait some cycles, then request tready block for 10 cycles
|
||||
WAIT FOR 200 ns;
|
||||
tready_block_req <= '1';
|
||||
WAIT UNTIL rising_edge(clk);
|
||||
tready_block_req <= '0';
|
||||
|
||||
end Behavioral;
|
||||
WAIT FOR 300 ns;
|
||||
tready_block_req <= '1';
|
||||
WAIT UNTIL rising_edge(clk);
|
||||
tready_block_req <= '0';
|
||||
|
||||
WAIT FOR 200 ns;
|
||||
tready_block_req <= '1';
|
||||
WAIT UNTIL rising_edge(clk);
|
||||
tready_block_req <= '0';
|
||||
|
||||
WAIT;
|
||||
END PROCESS;
|
||||
END Behavioral;
|
||||
@@ -27,150 +27,314 @@ ENTITY img_conv IS
|
||||
END ENTITY img_conv;
|
||||
|
||||
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));
|
||||
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')));
|
||||
TYPE offset_array IS ARRAY(0 TO 2) OF INTEGER;
|
||||
CONSTANT offset : offset_array := (-1, 0, 1);
|
||||
|
||||
-- Parametri immagine
|
||||
CONSTANT IMG_WIDTH : INTEGER := 2 ** LOG2_N_COLS; -- Larghezza dell'immagine
|
||||
CONSTANT IMG_HEIGHT : INTEGER := 2 ** LOG2_N_ROWS; -- Altezza dell'immagine
|
||||
|
||||
-- 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);
|
||||
TYPE state_type IS (IDLE, START_CONVOLUTING, CONVOLUTING, WAIT_READY);
|
||||
SIGNAL state : state_type := IDLE;
|
||||
|
||||
-- Contatori per riga e colonna
|
||||
SIGNAL row, col : INTEGER RANGE 0 TO IMG_HEIGHT - 1 := 0;
|
||||
SIGNAL col : UNSIGNED(LOG2_N_COLS - 1 DOWNTO 0) := (OTHERS => '0');
|
||||
SIGNAL row : UNSIGNED(LOG2_N_ROWS - 1 DOWNTO 0) := (OTHERS => '0');
|
||||
|
||||
SIGNAL col_mat_idx_prv : INTEGER := 0;
|
||||
SIGNAL row_mat_idx_prv : INTEGER := 0;
|
||||
|
||||
SIGNAL col_mat_idx : INTEGER := 0;
|
||||
SIGNAL row_mat_idx : INTEGER := 0;
|
||||
|
||||
SIGNAL col_mat_idx_nxt : INTEGER := 0;
|
||||
SIGNAL row_mat_idx_nxt : INTEGER := 0;
|
||||
|
||||
SIGNAL conv_data_out, conv_data_int, conv_data_mul : SIGNED(10 DOWNTO 0) := (OTHERS => '0');
|
||||
|
||||
SIGNAL m_axis_tvalid_int : STD_LOGIC;
|
||||
|
||||
SIGNAL trigger, prepare_data, ready_data, send_data : STD_LOGIC := '0';
|
||||
SIGNAL tlast : STD_LOGIC := '0';
|
||||
SIGNAL save_data : STD_LOGIC := '0';
|
||||
|
||||
BEGIN
|
||||
|
||||
-- Aggiornamento dell'indirizzo di lettura (mapping riga-colonna)
|
||||
conv_addr <= STD_LOGIC_VECTOR(to_unsigned(row * IMG_WIDTH + col, conv_addr'length));
|
||||
m_axis_tvalid <= m_axis_tvalid_int;
|
||||
|
||||
-- Processo principale: macchina a stati per la gestione della convoluzione
|
||||
PROCESS (clk, aresetn)
|
||||
PROCESS (clk)
|
||||
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
|
||||
IF rising_edge(clk) THEN
|
||||
IF aresetn = '0' THEN
|
||||
|
||||
-- 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;
|
||||
-- Reset all signals
|
||||
state <= IDLE;
|
||||
|
||||
col <= (OTHERS => '0');
|
||||
row <= (OTHERS => '0');
|
||||
|
||||
col_mat_idx_nxt <= 0;
|
||||
row_mat_idx_nxt <= 0;
|
||||
|
||||
col_mat_idx_prv <= 0;
|
||||
row_mat_idx_prv <= 0;
|
||||
|
||||
col_mat_idx <= 0;
|
||||
row_mat_idx <= 0;
|
||||
|
||||
conv_data_out <= (OTHERS => '0');
|
||||
conv_data_int <= (OTHERS => '0');
|
||||
conv_data_mul <= (OTHERS => '0');
|
||||
|
||||
m_axis_tvalid_int <= '0';
|
||||
m_axis_tdata <= (OTHERS => '0');
|
||||
m_axis_tlast <= '0';
|
||||
|
||||
done_conv <= '0';
|
||||
|
||||
trigger <= '0';
|
||||
prepare_data <= '0';
|
||||
ready_data <= '0';
|
||||
send_data <= '0';
|
||||
tlast <= '0';
|
||||
save_data <= '0';
|
||||
|
||||
conv_addr <= (OTHERS => '0');
|
||||
|
||||
ELSE
|
||||
-- Default values for signals
|
||||
done_conv <= '0';
|
||||
m_axis_tlast <= '0';
|
||||
|
||||
CASE state IS
|
||||
WHEN IDLE =>
|
||||
-- Default values in IDLE
|
||||
done_conv <= '0';
|
||||
-- Inizializza la finestra a zero per gestire il padding superiore
|
||||
window <= (OTHERS => (OTHERS => (OTHERS => '0')));
|
||||
state <= LOAD_PIXEL;
|
||||
END IF;
|
||||
m_axis_tlast <= '0';
|
||||
m_axis_tvalid_int <= '0';
|
||||
m_axis_tdata <= (OTHERS => '0');
|
||||
conv_data_out <= (OTHERS => '0');
|
||||
conv_data_int <= (OTHERS => '0');
|
||||
conv_data_mul <= (OTHERS => '0');
|
||||
trigger <= '0';
|
||||
prepare_data <= '0';
|
||||
ready_data <= '0';
|
||||
send_data <= '0';
|
||||
tlast <= '0';
|
||||
save_data <= '0';
|
||||
conv_addr <= (OTHERS => '0');
|
||||
|
||||
-- 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;
|
||||
IF start_conv = '1' THEN
|
||||
state <= START_CONVOLUTING;
|
||||
|
||||
-- Aggiorna la colonna destra della finestra con il nuovo pixel
|
||||
FOR i IN 0 TO 2 LOOP
|
||||
window(i)(2) <= conv_data;
|
||||
END LOOP;
|
||||
-- Reset the convolution matrix position
|
||||
row <= (OTHERS => '0');
|
||||
col <= (OTHERS => '0');
|
||||
|
||||
-- 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;
|
||||
-- Request the first pixel and set pointer to second pixel
|
||||
row_mat_idx_prv <= 0;
|
||||
col_mat_idx_prv <= 0;
|
||||
|
||||
state <= COMPUTE;
|
||||
row_mat_idx <= 1;
|
||||
col_mat_idx <= 1;
|
||||
|
||||
-- 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;
|
||||
row_mat_idx_nxt <= 1;
|
||||
col_mat_idx_nxt <= 2;
|
||||
|
||||
-- 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
|
||||
conv_addr <= (OTHERS => '0');
|
||||
conv_data_out <= (OTHERS => '0');
|
||||
conv_data_int <= (OTHERS => '0');
|
||||
conv_data_mul <= (OTHERS => '0');
|
||||
trigger <= '0';
|
||||
prepare_data <= '0';
|
||||
ready_data <= '0';
|
||||
send_data <= '0';
|
||||
tlast <= '0';
|
||||
save_data <= '0';
|
||||
m_axis_tvalid_int <= '0';
|
||||
m_axis_tdata <= (OTHERS => '0');
|
||||
m_axis_tlast <= '0';
|
||||
state <= LOAD_PIXEL;
|
||||
done_conv <= '0';
|
||||
END IF;
|
||||
|
||||
WHEN START_CONVOLUTING =>
|
||||
conv_addr <= STD_LOGIC_VECTOR(
|
||||
TO_UNSIGNED(
|
||||
(TO_INTEGER(col) + offset(col_mat_idx_nxt)) +
|
||||
(TO_INTEGER(row) + offset(row_mat_idx_nxt)) * (2 ** LOG2_N_COLS),
|
||||
conv_addr'length
|
||||
)
|
||||
);
|
||||
|
||||
state <= CONVOLUTING;
|
||||
|
||||
WHEN CONVOLUTING =>
|
||||
-- Convolution operation: accumulate the result of current pixel and kernel coefficient
|
||||
conv_addr <= STD_LOGIC_VECTOR(
|
||||
TO_UNSIGNED(
|
||||
(TO_INTEGER(col) + offset(col_mat_idx_nxt)) +
|
||||
(TO_INTEGER(row) + offset(row_mat_idx_nxt)) * (2 ** LOG2_N_COLS),
|
||||
conv_addr'length
|
||||
)
|
||||
);
|
||||
|
||||
conv_data_mul <= RESIZE(
|
||||
SIGNED('0' & conv_data) * TO_SIGNED(conv_mat(col_mat_idx_prv, row_mat_idx_prv), 5),
|
||||
conv_data_mul'length
|
||||
);
|
||||
|
||||
IF ready_data = '1' THEN
|
||||
conv_data_out <= conv_data_int + conv_data_mul;
|
||||
conv_data_int <= (OTHERS => '0');
|
||||
ELSE
|
||||
conv_data_int <= conv_data_int + conv_data_mul;
|
||||
END IF;
|
||||
|
||||
trigger <= '0';
|
||||
|
||||
WHEN WAIT_READY =>
|
||||
-- Wait for m_axis_tready signal to be asserted before sending data and continue convolution
|
||||
IF m_axis_tready = '1' THEN
|
||||
conv_addr <= STD_LOGIC_VECTOR(
|
||||
TO_UNSIGNED(
|
||||
(TO_INTEGER(col) + offset(col_mat_idx_nxt)) +
|
||||
(TO_INTEGER(row) + offset(row_mat_idx_nxt)) * (2 ** LOG2_N_COLS),
|
||||
conv_addr'length
|
||||
)
|
||||
);
|
||||
|
||||
save_data <= '0';
|
||||
state <= CONVOLUTING;
|
||||
END IF;
|
||||
|
||||
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),
|
||||
conv_data_mul'length
|
||||
);
|
||||
|
||||
IF ready_data = '1' THEN
|
||||
conv_data_out <= conv_data_int + conv_data_mul;
|
||||
conv_data_int <= (OTHERS => '0');
|
||||
ELSE
|
||||
conv_data_int <= conv_data_int + conv_data_mul;
|
||||
END IF;
|
||||
|
||||
save_data <= '1';
|
||||
END IF;
|
||||
|
||||
END CASE;
|
||||
|
||||
-- Output data - master
|
||||
IF m_axis_tready = '1' THEN
|
||||
m_axis_tvalid_int <= '0';
|
||||
END IF;
|
||||
|
||||
-- Wait for m_axis_tready signal to be asserted before continuing convolution
|
||||
IF m_axis_tready = '0' AND m_axis_tvalid_int = '1' THEN
|
||||
state <= WAIT_READY;
|
||||
END IF;
|
||||
|
||||
IF send_data = '1' AND (m_axis_tvalid_int = '0' OR m_axis_tready = '1') THEN
|
||||
m_axis_tvalid_int <= '1';
|
||||
|
||||
IF tlast = '1' THEN
|
||||
state <= IDLE;
|
||||
done_conv <= '1';
|
||||
m_axis_tlast <= '1';
|
||||
tlast <= '0';
|
||||
END IF;
|
||||
|
||||
-- Stato di default: ritorna a IDLE
|
||||
WHEN OTHERS =>
|
||||
state <= IDLE;
|
||||
END CASE;
|
||||
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
|
||||
m_axis_tdata <= STD_LOGIC_VECTOR(TO_UNSIGNED(127, m_axis_tdata'length));
|
||||
ELSE
|
||||
m_axis_tdata <= STD_LOGIC_VECTOR(conv_data_out(7 DOWNTO 0));
|
||||
END IF;
|
||||
|
||||
-- Reset accumulator and trigger
|
||||
conv_data_out <= (OTHERS => '0');
|
||||
send_data <= '0';
|
||||
END IF;
|
||||
|
||||
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
|
||||
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
|
||||
IF tlast = '0' THEN
|
||||
trigger <= '1'; -- Send last data
|
||||
tlast <= '1';
|
||||
END IF;
|
||||
|
||||
ELSIF row_mat_idx_nxt = 2 THEN
|
||||
-- End of kernel, move to next image row
|
||||
col <= (OTHERS => '0');
|
||||
row <= row + 1;
|
||||
|
||||
row_mat_idx_nxt <= 0;
|
||||
col_mat_idx_nxt <= 1; -- new row adding padding
|
||||
|
||||
trigger <= '1'; -- Send data
|
||||
|
||||
ELSE
|
||||
-- Move to next kernel row
|
||||
row_mat_idx_nxt <= row_mat_idx_nxt + 1;
|
||||
col_mat_idx_nxt <= 0;
|
||||
|
||||
END IF;
|
||||
|
||||
ELSIF col_mat_idx_nxt = 2 THEN
|
||||
IF row_mat_idx_nxt = 1 AND row = (2 ** LOG2_N_ROWS - 1) THEN
|
||||
-- End of kernel column at last image row, move to next image column
|
||||
col <= col + 1;
|
||||
|
||||
row_mat_idx_nxt <= 0;
|
||||
col_mat_idx_nxt <= 0;
|
||||
|
||||
trigger <= '1'; -- Send data
|
||||
|
||||
ELSIF row_mat_idx_nxt = 2 THEN
|
||||
-- End of kernel column and row, move to next image column
|
||||
col <= col + 1;
|
||||
|
||||
IF row = 0 THEN
|
||||
row_mat_idx_nxt <= 1; -- first row adding padding
|
||||
ELSE
|
||||
row_mat_idx_nxt <= 0;
|
||||
END IF;
|
||||
col_mat_idx_nxt <= 0;
|
||||
|
||||
trigger <= '1'; -- Send data
|
||||
|
||||
ELSE
|
||||
-- Move to next kernel column
|
||||
IF col = 0 THEN
|
||||
col_mat_idx_nxt <= 1; -- first column adding padding
|
||||
ELSE
|
||||
col_mat_idx_nxt <= 0;
|
||||
END IF;
|
||||
row_mat_idx_nxt <= row_mat_idx_nxt + 1;
|
||||
|
||||
END IF;
|
||||
|
||||
ELSE
|
||||
-- Continue kernel sweep: increment kernel column index
|
||||
col_mat_idx_nxt <= col_mat_idx_nxt + 1;
|
||||
|
||||
END IF;
|
||||
|
||||
prepare_data <= trigger; -- Pipeline trigger for data output waiting for last data
|
||||
ready_data <= prepare_data;
|
||||
send_data <= ready_data;
|
||||
|
||||
row_mat_idx_prv <= row_mat_idx;
|
||||
col_mat_idx_prv <= col_mat_idx;
|
||||
|
||||
row_mat_idx <= row_mat_idx_nxt;
|
||||
col_mat_idx <= col_mat_idx_nxt;
|
||||
END IF;
|
||||
|
||||
END IF;
|
||||
END IF;
|
||||
END PROCESS;
|
||||
|
||||
|
||||
205
LAB2/vivado/img_conv_test/img_conv_test.xpr
Normal file
205
LAB2/vivado/img_conv_test/img_conv_test.xpr
Normal file
@@ -0,0 +1,205 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Product Version: Vivado v2020.2 (64-bit) -->
|
||||
<!-- -->
|
||||
<!-- Copyright 1986-2020 Xilinx, Inc. All Rights Reserved. -->
|
||||
|
||||
<Project Version="7" Minor="54" Path="C:/DESD/LAB2/vivado/img_conv_test/img_conv_test.xpr">
|
||||
<DefaultLaunch Dir="$PRUNDIR"/>
|
||||
<Configuration>
|
||||
<Option Name="Id" Val="ac254788b71e44ff92abc438d357ca04"/>
|
||||
<Option Name="Part" Val="xc7a35tcpg236-1"/>
|
||||
<Option Name="CompiledLibDir" Val="$PCACHEDIR/compile_simlib"/>
|
||||
<Option Name="CompiledLibDirXSim" Val=""/>
|
||||
<Option Name="CompiledLibDirModelSim" Val="$PCACHEDIR/compile_simlib/modelsim"/>
|
||||
<Option Name="CompiledLibDirQuesta" Val="$PCACHEDIR/compile_simlib/questa"/>
|
||||
<Option Name="CompiledLibDirIES" Val="$PCACHEDIR/compile_simlib/ies"/>
|
||||
<Option Name="CompiledLibDirXcelium" Val="$PCACHEDIR/compile_simlib/xcelium"/>
|
||||
<Option Name="CompiledLibDirVCS" Val="$PCACHEDIR/compile_simlib/vcs"/>
|
||||
<Option Name="CompiledLibDirRiviera" Val="$PCACHEDIR/compile_simlib/riviera"/>
|
||||
<Option Name="CompiledLibDirActivehdl" Val="$PCACHEDIR/compile_simlib/activehdl"/>
|
||||
<Option Name="SimulatorInstallDirModelSim" Val=""/>
|
||||
<Option Name="SimulatorInstallDirQuesta" Val=""/>
|
||||
<Option Name="SimulatorInstallDirIES" Val=""/>
|
||||
<Option Name="SimulatorInstallDirXcelium" Val=""/>
|
||||
<Option Name="SimulatorInstallDirVCS" Val=""/>
|
||||
<Option Name="SimulatorInstallDirRiviera" Val=""/>
|
||||
<Option Name="SimulatorInstallDirActiveHdl" Val=""/>
|
||||
<Option Name="SimulatorGccInstallDirModelSim" Val=""/>
|
||||
<Option Name="SimulatorGccInstallDirQuesta" Val=""/>
|
||||
<Option Name="SimulatorGccInstallDirIES" Val=""/>
|
||||
<Option Name="SimulatorGccInstallDirXcelium" Val=""/>
|
||||
<Option Name="SimulatorGccInstallDirVCS" Val=""/>
|
||||
<Option Name="SimulatorGccInstallDirRiviera" Val=""/>
|
||||
<Option Name="SimulatorGccInstallDirActiveHdl" Val=""/>
|
||||
<Option Name="TargetLanguage" Val="VHDL"/>
|
||||
<Option Name="BoardPart" Val="digilentinc.com:basys3:part0:1.1"/>
|
||||
<Option Name="BoardPartRepoPaths" Val="$PPRDIR/../../../../Users/david/AppData/Roaming/Xilinx/Vivado/2020.2/xhub/board_store/xilinx_board_store"/>
|
||||
<Option Name="ActiveSimSet" Val="sim_1"/>
|
||||
<Option Name="DefaultLib" Val="xil_defaultlib"/>
|
||||
<Option Name="ProjectType" Val="Default"/>
|
||||
<Option Name="IPOutputRepo" Val="$PCACHEDIR/ip"/>
|
||||
<Option Name="IPDefaultOutputPath" Val="$PGENDIR/sources_1"/>
|
||||
<Option Name="IPCachePermission" Val="read"/>
|
||||
<Option Name="IPCachePermission" Val="write"/>
|
||||
<Option Name="EnableCoreContainer" Val="FALSE"/>
|
||||
<Option Name="CreateRefXciForCoreContainers" Val="FALSE"/>
|
||||
<Option Name="IPUserFilesDir" Val="$PIPUSERFILESDIR"/>
|
||||
<Option Name="IPStaticSourceDir" Val="$PIPUSERFILESDIR/ipstatic"/>
|
||||
<Option Name="EnableBDX" Val="FALSE"/>
|
||||
<Option Name="DSABoardId" Val="basys3"/>
|
||||
<Option Name="WTXSimLaunchSim" Val="150"/>
|
||||
<Option Name="WTModelSimLaunchSim" Val="0"/>
|
||||
<Option Name="WTQuestaLaunchSim" Val="0"/>
|
||||
<Option Name="WTIesLaunchSim" Val="0"/>
|
||||
<Option Name="WTVcsLaunchSim" Val="0"/>
|
||||
<Option Name="WTRivieraLaunchSim" Val="0"/>
|
||||
<Option Name="WTActivehdlLaunchSim" Val="0"/>
|
||||
<Option Name="WTXSimExportSim" Val="0"/>
|
||||
<Option Name="WTModelSimExportSim" Val="0"/>
|
||||
<Option Name="WTQuestaExportSim" Val="0"/>
|
||||
<Option Name="WTIesExportSim" Val="0"/>
|
||||
<Option Name="WTVcsExportSim" Val="0"/>
|
||||
<Option Name="WTRivieraExportSim" Val="0"/>
|
||||
<Option Name="WTActivehdlExportSim" Val="0"/>
|
||||
<Option Name="GenerateIPUpgradeLog" Val="TRUE"/>
|
||||
<Option Name="XSimRadix" Val="hex"/>
|
||||
<Option Name="XSimTimeUnit" Val="ns"/>
|
||||
<Option Name="XSimArrayDisplayLimit" Val="1024"/>
|
||||
<Option Name="XSimTraceLimit" Val="65536"/>
|
||||
<Option Name="SimTypes" Val="rtl"/>
|
||||
<Option Name="SimTypes" Val="bfm"/>
|
||||
<Option Name="SimTypes" Val="tlm"/>
|
||||
<Option Name="SimTypes" Val="tlm_dpi"/>
|
||||
<Option Name="MEMEnableMemoryMapGeneration" Val="TRUE"/>
|
||||
<Option Name="DcpsUptoDate" Val="TRUE"/>
|
||||
</Configuration>
|
||||
<FileSets Version="1" Minor="31">
|
||||
<FileSet Name="sources_1" Type="DesignSrcs" RelSrcDir="$PSRCDIR/sources_1" RelGenDir="$PGENDIR/sources_1">
|
||||
<Filter Type="Srcs"/>
|
||||
<File Path="$PPRDIR/../../src/img_conv.vhd">
|
||||
<FileInfo>
|
||||
<Attr Name="UsedIn" Val="synthesis"/>
|
||||
<Attr Name="UsedIn" Val="simulation"/>
|
||||
</FileInfo>
|
||||
</File>
|
||||
<Config>
|
||||
<Option Name="DesignMode" Val="RTL"/>
|
||||
<Option Name="TopModule" Val="img_conv"/>
|
||||
<Option Name="TopAutoSet" Val="TRUE"/>
|
||||
</Config>
|
||||
</FileSet>
|
||||
<FileSet Name="constrs_1" Type="Constrs" RelSrcDir="$PSRCDIR/constrs_1" RelGenDir="$PGENDIR/constrs_1">
|
||||
<Filter Type="Constrs"/>
|
||||
<Config>
|
||||
<Option Name="ConstrsType" Val="XDC"/>
|
||||
</Config>
|
||||
</FileSet>
|
||||
<FileSet Name="sim_1" Type="SimulationSrcs" RelSrcDir="$PSRCDIR/sim_1" RelGenDir="$PGENDIR/sim_1">
|
||||
<Filter Type="Srcs"/>
|
||||
<File Path="$PPRDIR/../../sim/tb_img_conv.vhd">
|
||||
<FileInfo>
|
||||
<Attr Name="UsedIn" Val="synthesis"/>
|
||||
<Attr Name="UsedIn" Val="simulation"/>
|
||||
</FileInfo>
|
||||
</File>
|
||||
<Config>
|
||||
<Option Name="DesignMode" Val="RTL"/>
|
||||
<Option Name="TopModule" Val="img_conv_tb"/>
|
||||
<Option Name="TopLib" Val="xil_defaultlib"/>
|
||||
<Option Name="TopAutoSet" Val="TRUE"/>
|
||||
<Option Name="TransportPathDelay" Val="0"/>
|
||||
<Option Name="TransportIntDelay" Val="0"/>
|
||||
<Option Name="SelectedSimModel" Val="rtl"/>
|
||||
<Option Name="PamDesignTestbench" Val=""/>
|
||||
<Option Name="PamDutBypassFile" Val="xil_dut_bypass"/>
|
||||
<Option Name="PamSignalDriverFile" Val="xil_bypass_driver"/>
|
||||
<Option Name="PamPseudoTop" Val="pseudo_tb"/>
|
||||
<Option Name="SrcSet" Val="sources_1"/>
|
||||
</Config>
|
||||
</FileSet>
|
||||
<FileSet Name="utils_1" Type="Utils" RelSrcDir="$PSRCDIR/utils_1" RelGenDir="$PGENDIR/utils_1">
|
||||
<Filter Type="Utils"/>
|
||||
<Config>
|
||||
<Option Name="TopAutoSet" Val="TRUE"/>
|
||||
</Config>
|
||||
</FileSet>
|
||||
</FileSets>
|
||||
<Simulators>
|
||||
<Simulator Name="XSim">
|
||||
<Option Name="Description" Val="Vivado Simulator"/>
|
||||
<Option Name="CompiledLib" Val="0"/>
|
||||
</Simulator>
|
||||
<Simulator Name="ModelSim">
|
||||
<Option Name="Description" Val="ModelSim Simulator"/>
|
||||
</Simulator>
|
||||
<Simulator Name="Questa">
|
||||
<Option Name="Description" Val="Questa Advanced Simulator"/>
|
||||
</Simulator>
|
||||
<Simulator Name="Riviera">
|
||||
<Option Name="Description" Val="Riviera-PRO Simulator"/>
|
||||
</Simulator>
|
||||
<Simulator Name="ActiveHDL">
|
||||
<Option Name="Description" Val="Active-HDL Simulator"/>
|
||||
</Simulator>
|
||||
</Simulators>
|
||||
<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="$PSRCDIR/utils_1/imports/synth_1">
|
||||
<Strategy Version="1" Minor="2">
|
||||
<StratHandle Name="Vivado Synthesis Defaults" Flow="Vivado Synthesis 2020"/>
|
||||
<Step Id="synth_design"/>
|
||||
</Strategy>
|
||||
<ReportStrategy Name="Vivado Synthesis Default Reports" Flow="Vivado Synthesis 2020"/>
|
||||
<Report Name="ROUTE_DESIGN.REPORT_METHODOLOGY" Enabled="1"/>
|
||||
<RQSFiles/>
|
||||
</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="$PSRCDIR/utils_1/imports/impl_1">
|
||||
<Strategy Version="1" Minor="2">
|
||||
<StratHandle Name="Vivado Implementation Defaults" Flow="Vivado Implementation 2020"/>
|
||||
<Step Id="init_design"/>
|
||||
<Step Id="opt_design"/>
|
||||
<Step Id="power_opt_design"/>
|
||||
<Step Id="place_design"/>
|
||||
<Step Id="post_place_power_opt_design"/>
|
||||
<Step Id="phys_opt_design"/>
|
||||
<Step Id="route_design"/>
|
||||
<Step Id="post_route_phys_opt_design"/>
|
||||
<Step Id="write_bitstream"/>
|
||||
</Strategy>
|
||||
<ReportStrategy Name="Vivado Implementation Default Reports" Flow="Vivado Implementation 2020"/>
|
||||
<Report Name="ROUTE_DESIGN.REPORT_METHODOLOGY" Enabled="1"/>
|
||||
<RQSFiles/>
|
||||
</Run>
|
||||
</Runs>
|
||||
<Board>
|
||||
<Jumpers/>
|
||||
</Board>
|
||||
<DashboardSummary Version="1" Minor="0">
|
||||
<Dashboards>
|
||||
<Dashboard Name="default_dashboard">
|
||||
<Gadgets>
|
||||
<Gadget Name="drc_1" Type="drc" Version="1" Row="2" Column="0">
|
||||
<GadgetParam Name="REPORTS" Type="string_list" Value="impl_1#impl_1_route_report_drc_0 "/>
|
||||
</Gadget>
|
||||
<Gadget Name="methodology_1" Type="methodology" Version="1" Row="2" Column="1">
|
||||
<GadgetParam Name="REPORTS" Type="string_list" Value="impl_1#impl_1_route_report_methodology_0 "/>
|
||||
</Gadget>
|
||||
<Gadget Name="power_1" Type="power" Version="1" Row="1" Column="0">
|
||||
<GadgetParam Name="REPORTS" Type="string_list" Value="impl_1#impl_1_route_report_power_0 "/>
|
||||
</Gadget>
|
||||
<Gadget Name="timing_1" Type="timing" Version="1" Row="0" Column="1">
|
||||
<GadgetParam Name="REPORTS" Type="string_list" Value="impl_1#impl_1_route_report_timing_summary_0 "/>
|
||||
</Gadget>
|
||||
<Gadget Name="utilization_1" Type="utilization" Version="1" Row="0" Column="0">
|
||||
<GadgetParam Name="REPORTS" Type="string_list" Value="synth_1#synth_1_synth_report_utilization_0 "/>
|
||||
<GadgetParam Name="RUN.STEP" Type="string" Value="synth_design"/>
|
||||
<GadgetParam Name="RUN.TYPE" Type="string" Value="synthesis"/>
|
||||
</Gadget>
|
||||
<Gadget Name="utilization_2" Type="utilization" Version="1" Row="1" Column="1">
|
||||
<GadgetParam Name="REPORTS" Type="string_list" Value="impl_1#impl_1_place_report_utilization_0 "/>
|
||||
</Gadget>
|
||||
</Gadgets>
|
||||
</Dashboard>
|
||||
<CurrentDashboard>default_dashboard</CurrentDashboard>
|
||||
</Dashboards>
|
||||
</DashboardSummary>
|
||||
</Project>
|
||||
Reference in New Issue
Block a user