Add testbench for LED blinker, enhance bram_writer with state management, and update test script for overflow/underflow handling
This commit is contained in:
74
LAB2/sim/tb_led_blinker.vhd
Normal file
74
LAB2/sim/tb_led_blinker.vhd
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
library ieee;
|
||||||
|
use ieee.std_logic_1164.all;
|
||||||
|
use ieee.numeric_std.all;
|
||||||
|
|
||||||
|
entity tb_led_blinker is
|
||||||
|
end entity;
|
||||||
|
|
||||||
|
architecture behavior of tb_led_blinker is
|
||||||
|
-- Constants
|
||||||
|
constant CLK_PERIOD_NS : time := 10 ns;
|
||||||
|
constant BLINK_PERIOD_MS : integer := 1000;
|
||||||
|
constant N_BLINKS : integer := 4;
|
||||||
|
|
||||||
|
-- DUT signals
|
||||||
|
signal clk : std_logic := '0';
|
||||||
|
signal aresetn : std_logic := '0';
|
||||||
|
signal start_blink : std_logic := '0';
|
||||||
|
signal led : std_logic;
|
||||||
|
|
||||||
|
begin
|
||||||
|
-- Clock process
|
||||||
|
clk_process : process
|
||||||
|
begin
|
||||||
|
while true loop
|
||||||
|
clk <= not clk;
|
||||||
|
wait for CLK_PERIOD_NS / 2;
|
||||||
|
end loop;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
-- Instantiate DUT
|
||||||
|
uut: entity work.led_blinker
|
||||||
|
generic map (
|
||||||
|
CLK_PERIOD_NS => 10,
|
||||||
|
BLINK_PERIOD_MS => BLINK_PERIOD_MS,
|
||||||
|
N_BLINKS => N_BLINKS
|
||||||
|
)
|
||||||
|
port map (
|
||||||
|
clk => clk,
|
||||||
|
aresetn => aresetn,
|
||||||
|
start_blink => start_blink,
|
||||||
|
led => led
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Stimulus process
|
||||||
|
stimulus : process
|
||||||
|
begin
|
||||||
|
-- Reset
|
||||||
|
aresetn <= '0';
|
||||||
|
wait for 50 ns;
|
||||||
|
aresetn <= '1';
|
||||||
|
wait for 50 ns;
|
||||||
|
|
||||||
|
-- Primo impulso di start_blink
|
||||||
|
start_blink <= '1';
|
||||||
|
wait for 10 ns;
|
||||||
|
start_blink <= '0';
|
||||||
|
|
||||||
|
-- Aspetta met<65> blinking, poi rilancia start_blink
|
||||||
|
wait for 3 sec;
|
||||||
|
|
||||||
|
-- Secondo impulso (durante blinking)
|
||||||
|
start_blink <= '1';
|
||||||
|
wait for 10 ns;
|
||||||
|
start_blink <= '0';
|
||||||
|
|
||||||
|
-- Aspetta che finisca tutto
|
||||||
|
wait for 10 sec;
|
||||||
|
|
||||||
|
-- Fine simulazione
|
||||||
|
assert false report "Test completed." severity failure;
|
||||||
|
end process;
|
||||||
|
|
||||||
|
end architecture;
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ ARCHITECTURE rtl OF bram_writer IS
|
|||||||
);
|
);
|
||||||
END COMPONENT;
|
END COMPONENT;
|
||||||
|
|
||||||
TYPE state_type IS (IDLE, RECEIVING, CHECK_START_CONV, CONVOLUTION);
|
TYPE state_type IS (IDLE, RECEIVING, CHECK_DATA, CONVOLUTION);
|
||||||
SIGNAL state : state_type := IDLE;
|
SIGNAL state : state_type := IDLE;
|
||||||
|
|
||||||
SIGNAL s_axis_tready_int : STD_LOGIC := '0';
|
SIGNAL s_axis_tready_int : STD_LOGIC := '0';
|
||||||
@@ -58,6 +58,8 @@ ARCHITECTURE rtl OF bram_writer IS
|
|||||||
|
|
||||||
SIGNAL wr_addr : STD_LOGIC_VECTOR(ADDR_WIDTH - 1 DOWNTO 0) := (OTHERS => '0'); -- Write address for BRAM
|
SIGNAL wr_addr : STD_LOGIC_VECTOR(ADDR_WIDTH - 1 DOWNTO 0) := (OTHERS => '0'); -- Write address for BRAM
|
||||||
|
|
||||||
|
SIGNAL overflow_flag : STD_LOGIC := '0'; -- Overflow flag for BRAM write
|
||||||
|
|
||||||
BEGIN
|
BEGIN
|
||||||
|
|
||||||
-- Instantiate BRAM controller
|
-- Instantiate BRAM controller
|
||||||
@@ -100,6 +102,8 @@ BEGIN
|
|||||||
write_ok <= '0';
|
write_ok <= '0';
|
||||||
overflow <= '0';
|
overflow <= '0';
|
||||||
underflow <= '0';
|
underflow <= '0';
|
||||||
|
|
||||||
|
overflow_flag <= '0';
|
||||||
ELSE
|
ELSE
|
||||||
-- Default assignments for each clock cycle
|
-- Default assignments for each clock cycle
|
||||||
start_conv <= '0';
|
start_conv <= '0';
|
||||||
@@ -126,24 +130,27 @@ BEGIN
|
|||||||
IF s_axis_tvalid = '1' AND s_axis_tready_int = '1' THEN
|
IF s_axis_tvalid = '1' AND s_axis_tready_int = '1' THEN
|
||||||
-- Check for overflow: if address reaches max image size
|
-- Check for overflow: if address reaches max image size
|
||||||
IF unsigned(wr_addr) = (IMG_SIZE ** 2 - 1) THEN
|
IF unsigned(wr_addr) = (IMG_SIZE ** 2 - 1) THEN
|
||||||
overflow <= '1';
|
overflow_flag <= '1';
|
||||||
state <= IDLE;
|
END IF;
|
||||||
ELSE
|
|
||||||
-- Increment write address and write data to BRAM
|
|
||||||
wr_addr <= STD_LOGIC_VECTOR(unsigned(wr_addr) + 1);
|
|
||||||
bram_we <= '1'; -- Enable write to BRAM
|
|
||||||
bram_data_in <= s_axis_tdata; -- Write data to BRAM
|
|
||||||
|
|
||||||
-- Check for last data signal
|
-- Increment write address and write data to BRAM
|
||||||
IF s_axis_tlast = '1' THEN
|
wr_addr <= STD_LOGIC_VECTOR(unsigned(wr_addr) + 1);
|
||||||
state <= CHECK_START_CONV;
|
bram_we <= '1'; -- Enable write to BRAM
|
||||||
END IF;
|
bram_data_in <= s_axis_tdata; -- Write data to BRAM
|
||||||
|
|
||||||
|
-- Check for last data signal
|
||||||
|
IF s_axis_tlast = '1' THEN
|
||||||
|
state <= CHECK_DATA;
|
||||||
END IF;
|
END IF;
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
WHEN CHECK_START_CONV =>
|
WHEN CHECK_DATA =>
|
||||||
-- Check for underflow: if not enough data received
|
-- Check for overflow/underflow
|
||||||
IF unsigned(wr_addr) < (IMG_SIZE ** 2 - 2) THEN
|
IF overflow_flag = '1' THEN
|
||||||
|
overflow <= '1';
|
||||||
|
overflow_flag <= '0';
|
||||||
|
state <= IDLE;
|
||||||
|
ELSIF unsigned(wr_addr) < (IMG_SIZE ** 2 - 1) THEN
|
||||||
underflow <= '1';
|
underflow <= '1';
|
||||||
state <= IDLE;
|
state <= IDLE;
|
||||||
ELSE
|
ELSE
|
||||||
|
|||||||
@@ -1,28 +1,78 @@
|
|||||||
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;
|
||||||
|
|
||||||
entity led_blinker is
|
entity led_blinker is
|
||||||
generic (
|
generic (
|
||||||
CLK_PERIOD_NS: POSITIVE :=10;
|
CLK_PERIOD_NS : positive := 10;
|
||||||
BLINK_PERIOD_MS : POSITIVE :=1000;
|
BLINK_PERIOD_MS : positive := 1000;
|
||||||
N_BLINKS : POSITIVE := 4
|
N_BLINKS : positive := 4
|
||||||
);
|
);
|
||||||
port (
|
port (
|
||||||
clk : in std_logic;
|
clk : in std_logic;
|
||||||
aresetn : in std_logic;
|
aresetn : in std_logic;
|
||||||
start_blink : in std_logic;
|
start_blink : in std_logic;
|
||||||
led: out std_logic
|
led : out std_logic
|
||||||
);
|
);
|
||||||
end entity led_blinker;
|
end entity;
|
||||||
|
|
||||||
architecture rtl of led_blinker is
|
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))));
|
||||||
|
|
||||||
|
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 start_prev : std_logic := '0';
|
||||||
|
signal start_edge : std_logic;
|
||||||
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
|
led <= led_reg;
|
||||||
|
|
||||||
|
process(clk, aresetn)
|
||||||
|
begin
|
||||||
|
if aresetn = '0' then
|
||||||
|
counter <= (others => '0');
|
||||||
|
blink_cnt <= (others => '0');
|
||||||
|
blinking <= '0';
|
||||||
|
led_reg <= '0';
|
||||||
|
start_prev <= '0';
|
||||||
|
start_edge <= '0';
|
||||||
|
|
||||||
end architecture;
|
elsif rising_edge(clk) then
|
||||||
|
-- Rileva fronte di salita di start_blink
|
||||||
|
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 led_reg = '1' then -- fine fase ON
|
||||||
|
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;
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import sys
|
""" import sys
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
def install_and_import(package, package_name=None):
|
def install_and_import(package, package_name=None):
|
||||||
@@ -16,7 +16,7 @@ install_and_import("serial", "pyserial")
|
|||||||
install_and_import("PIL", "pillow")
|
install_and_import("PIL", "pillow")
|
||||||
install_and_import("tqdm")
|
install_and_import("tqdm")
|
||||||
install_and_import("numpy")
|
install_and_import("numpy")
|
||||||
install_and_import("scipy")
|
install_and_import("scipy") """
|
||||||
|
|
||||||
from serial import Serial
|
from serial import Serial
|
||||||
import serial.tools.list_ports
|
import serial.tools.list_ports
|
||||||
@@ -25,8 +25,11 @@ from PIL import Image
|
|||||||
from scipy.signal import convolve2d
|
from scipy.signal import convolve2d
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
IMAGE_NAME2 = "test2.png"
|
IMAGE_OF = r'C:\DESD\LAB2\test\test_of.png'
|
||||||
IMAGE_NAME1 = "test1.png"
|
IMAGE_UF = r'C:\DESD\LAB2\test\test_uf.png'
|
||||||
|
IMAGE_NAME3 = r'C:\DESD\LAB2\test\test3.png'
|
||||||
|
IMAGE_NAME2 = r'C:\DESD\LAB2\test\test2.png'
|
||||||
|
IMAGE_NAME1 = r'C:\DESD\LAB2\test\test1.png'
|
||||||
|
|
||||||
BASYS3_PID = 0x6010
|
BASYS3_PID = 0x6010
|
||||||
BASYS3_VID = 0x0403
|
BASYS3_VID = 0x0403
|
||||||
@@ -42,16 +45,19 @@ for port in serial.tools.list_ports.comports():
|
|||||||
if not dev:
|
if not dev:
|
||||||
raise RuntimeError("Basys 3 Not Found!")
|
raise RuntimeError("Basys 3 Not Found!")
|
||||||
|
|
||||||
test_n = int(input("Insert test number (1 or 2): ").strip())
|
test_n = int(input("Insert test number (1, 2, 3, overflow (4) or underflow (5)): ").strip())
|
||||||
|
|
||||||
if test_n not in [1, 2]:
|
if test_n not in [1, 2, 3, 4, 5]:
|
||||||
raise RuntimeError("Test number must be 1 or 2")
|
raise RuntimeError("Test number must be 1, 2, 3, 4 (overflow) or 5 (underflow)")
|
||||||
|
|
||||||
dev = Serial(dev, 115200)
|
dev = Serial(dev, 115200)
|
||||||
|
|
||||||
img = Image.open(IMAGE_NAME1 if test_n == 1 else IMAGE_NAME2)
|
img = Image.open(IMAGE_NAME1 if test_n == 1 else IMAGE_NAME2 if test_n == 2 else IMAGE_NAME3 if test_n == 3 else IMAGE_UF if test_n == 5 else IMAGE_OF)
|
||||||
if img.mode != "RGB":
|
if img.mode != "RGB":
|
||||||
img = img.convert("RGB")
|
img = img.convert("RGB")
|
||||||
|
|
||||||
|
IMG_WIDTH, IMG_HEIGHT = img.size # Get dimensions from the image
|
||||||
|
|
||||||
mat = np.asarray(img, dtype=np.uint8)
|
mat = np.asarray(img, dtype=np.uint8)
|
||||||
|
|
||||||
mat = mat[:, :, :3]
|
mat = mat[:, :, :3]
|
||||||
@@ -75,6 +81,13 @@ for i in tqdm(range(IMG_HEIGHT)):
|
|||||||
dev.write(b'\xf1')
|
dev.write(b'\xf1')
|
||||||
dev.flush()
|
dev.flush()
|
||||||
|
|
||||||
|
if test_n == 4:
|
||||||
|
print("Check for overflow (LED U16)")
|
||||||
|
exit()
|
||||||
|
elif test_n == 5:
|
||||||
|
print("Check for underflow (LED U19)")
|
||||||
|
exit()
|
||||||
|
|
||||||
res = dev.read(IMG_HEIGHT * IMG_WIDTH + 2)
|
res = dev.read(IMG_HEIGHT * IMG_WIDTH + 2)
|
||||||
|
|
||||||
res_img = np.frombuffer(res[1:-1], dtype=np.uint8)
|
res_img = np.frombuffer(res[1:-1], dtype=np.uint8)
|
||||||
|
|||||||
BIN
LAB2/test/test_of.png
Normal file
BIN
LAB2/test/test_of.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 65 KiB |
BIN
LAB2/test/test_uf.png
Normal file
BIN
LAB2/test/test_uf.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 35 KiB |
@@ -47,7 +47,7 @@
|
|||||||
<Option Name="IPStaticSourceDir" Val="$PIPUSERFILESDIR/ipstatic"/>
|
<Option Name="IPStaticSourceDir" Val="$PIPUSERFILESDIR/ipstatic"/>
|
||||||
<Option Name="EnableBDX" Val="FALSE"/>
|
<Option Name="EnableBDX" Val="FALSE"/>
|
||||||
<Option Name="DSABoardId" Val="basys3"/>
|
<Option Name="DSABoardId" Val="basys3"/>
|
||||||
<Option Name="WTXSimLaunchSim" Val="22"/>
|
<Option Name="WTXSimLaunchSim" Val="31"/>
|
||||||
<Option Name="WTModelSimLaunchSim" Val="0"/>
|
<Option Name="WTModelSimLaunchSim" Val="0"/>
|
||||||
<Option Name="WTQuestaLaunchSim" Val="0"/>
|
<Option Name="WTQuestaLaunchSim" Val="0"/>
|
||||||
<Option Name="WTIesLaunchSim" Val="0"/>
|
<Option Name="WTIesLaunchSim" Val="0"/>
|
||||||
@@ -101,6 +101,7 @@
|
|||||||
</Config>
|
</Config>
|
||||||
</FileSet>
|
</FileSet>
|
||||||
<FileSet Name="sim_1" Type="SimulationSrcs" RelSrcDir="$PSRCDIR/sim_1" RelGenDir="$PGENDIR/sim_1">
|
<FileSet Name="sim_1" Type="SimulationSrcs" RelSrcDir="$PSRCDIR/sim_1" RelGenDir="$PGENDIR/sim_1">
|
||||||
|
<Filter Type="Srcs"/>
|
||||||
<File Path="$PPRDIR/../../sim/tb_bram_writer.vhd">
|
<File Path="$PPRDIR/../../sim/tb_bram_writer.vhd">
|
||||||
<FileInfo>
|
<FileInfo>
|
||||||
<Attr Name="UsedIn" Val="synthesis"/>
|
<Attr Name="UsedIn" Val="synthesis"/>
|
||||||
@@ -156,9 +157,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="$PSRCDIR/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="$PSRCDIR/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"/>
|
||||||
@@ -167,9 +166,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="$PSRCDIR/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="$PSRCDIR/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"/>
|
||||||
|
|||||||
Reference in New Issue
Block a user