Refactor KittCar and KittCarPWM for improved LED control; update simulation settings and add testbench

This commit is contained in:
2025-03-22 17:02:22 +01:00
parent f6c568b416
commit 7b51306696
5 changed files with 145 additions and 72 deletions

View File

@@ -0,0 +1,85 @@
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.NUMERIC_STD.ALL;
ENTITY tb_KittCarPWM IS
END tb_KittCarPWM;
ARCHITECTURE testbench OF tb_KittCarPWM IS
-- Test constants
CONSTANT CLK_PERIOD : TIME := 10 ns;
CONSTANT RESET_TIME : TIME := 10*CLK_PERIOD;
CONSTANT TEST_DURATION : TIME := 10000 ms;
CONSTANT PERIOD : TIME := 10ms;
-- Signals
SIGNAL clk : STD_LOGIC := '0';
SIGNAL reset : STD_LOGIC := '0';
SIGNAL sw : STD_LOGIC_VECTOR(15 DOWNTO 0) := (OTHERS => '0');
SIGNAL led : STD_LOGIC_VECTOR(15 DOWNTO 0);
-- Device Under Test (DUT) instance
COMPONENT KittCarPWM
GENERIC (
CLK_PERIOD_NS : POSITIVE := 10;
MIN_KITT_CAR_STEP_MS : POSITIVE := 1;
NUM_OF_SWS : INTEGER := 16;
NUM_OF_LEDS : INTEGER := 16;
TAIL_LENGTH : INTEGER := 4
);
PORT (
reset : IN STD_LOGIC;
clk : IN STD_LOGIC;
sw : IN STD_LOGIC_VECTOR(NUM_OF_SWS - 1 DOWNTO 0);
led : OUT STD_LOGIC_VECTOR(NUM_OF_LEDS - 1 DOWNTO 0)
);
END COMPONENT;
BEGIN
-- Connect DUT
dut_KittCarPWM : KittCarPWM
GENERIC MAP (
CLK_PERIOD_NS => 10,
MIN_KITT_CAR_STEP_MS => 1,
NUM_OF_SWS => 16,
NUM_OF_LEDS => 16,
TAIL_LENGTH => 4
)
PORT MAP (
reset => reset,
clk => clk,
sw => sw,
led => led
);
-- Clock generation process
clk <= not clk after CLK_PERIOD/2;
-- Reset Process
reset_wave :process
begin
reset <= '1';
wait for RESET_TIME;
reset <= not reset;
wait;
end process;
-- Test process
stim_proc : PROCESS
BEGIN
-- wait for reset
sw <= "0000000000000000";
WAIT FOR RESET_TIME;
-- Start
for I in 0 to 2**16-1 loop
sw <= std_logic_vector(to_unsigned(I, 16));
WAIT FOR PERIOD;
end loop;
-- End simulation
WAIT;
END PROCESS;
END testbench;

View File

@@ -33,27 +33,30 @@ ARCHITECTURE Behavioral OF KittCar IS
CONSTANT MIN_KITT_CAR_STEP_NS : UNSIGNED(46 DOWNTO 0) := to_unsigned(MIN_KITT_CAR_STEP_MS * 1000000, 47);
SIGNAL leds_sr : STD_LOGIC_VECTOR(led'RANGE) := (OTHERS => '0');
SIGNAL n_period : UNSIGNED(NUM_OF_SWS DOWNTO 0) := to_unsigned(1, NUM_OF_SWS + 1);
SIGNAL up : STD_LOGIC := '1';
BEGIN
-- Sincronous logic
PROCESS (clk, reset)
VARIABLE counter : UNSIGNED(46 DOWNTO 0) := (OTHERS => '0');
VARIABLE n_period : UNSIGNED(NUM_OF_SWS DOWNTO 0) := to_unsigned(1, NUM_OF_SWS + 1);
VARIABLE up : STD_LOGIC := '1';
BEGIN
IF reset = '1' THEN
leds_sr <= (OTHERS => '0');
counter := (OTHERS => '0');
ELSIF rising_edge(clk) THEN
-- Handle the switch
n_period := unsigned('0' & sw) + 1;
-- Kitt logic
IF unsigned(leds_sr) = 0 THEN
leds_sr(0) <= '1';
up <= '1';
up := '1';
ELSIF leds_sr(led'HIGH) = '1' THEN
up <= '0';
up := '0';
ELSIF leds_sr(led'LOW) = '1' THEN
up <= '1';
up := '1';
END IF;
-- Increment the counter
@@ -75,12 +78,6 @@ BEGIN
END IF;
END PROCESS;
-- Handle the switch
PROCESS (sw)
BEGIN
n_period <= unsigned('0' & sw) + 1;
END PROCESS;
led <= leds_sr;
END Behavioral;

View File

@@ -32,10 +32,7 @@ END KittCarPWM;
ARCHITECTURE Behavioral OF KittCarPWM IS
COMPONENT PulseWidthModulator
GENERIC (
BIT_LENGTH : INTEGER RANGE 1 TO 16;
T_ON_INIT : POSITIVE;
PERIOD_INIT : POSITIVE;
PWM_INIT : STD_LOGIC
BIT_LENGTH : INTEGER
);
PORT (
reset : IN STD_LOGIC;
@@ -47,88 +44,79 @@ ARCHITECTURE Behavioral OF KittCarPWM IS
);
END COMPONENT;
TYPE led_reg IS ARRAY (TAIL_LENGTH - 1 DOWNTO 0) OF INTEGER RANGE 0 TO led'HIGH;
TYPE leds_sr_type IS ARRAY (TAIL_LENGTH - 1 DOWNTO 0) OF INTEGER RANGE led'LOW TO led'HIGH;
CONSTANT MIN_KITT_CAR_STEP_NS : UNSIGNED(46 DOWNTO 0) := to_unsigned(MIN_KITT_CAR_STEP_MS * 1000000, 47);
CONSTANT BIT_LENGTH : INTEGER RANGE 1 TO 16 := 8;
CONSTANT BIT_LENGTH : INTEGER := 5;
SIGNAL pwms : STD_LOGIC_VECTOR(TAIL_LENGTH - 1 DOWNTO 0) := (OTHERS => '0');
SIGNAL leds_sig : STD_LOGIC_VECTOR(NUM_OF_LEDS - 1 DOWNTO 0) := (OTHERS => '0');
SIGNAL leds_sr : led_reg := (OTHERS => 0);
SIGNAL leds_pwm : STD_LOGIC_VECTOR(TAIL_LENGTH - 1 DOWNTO 0) := (OTHERS => '0');
SIGNAL led_sig : STD_LOGIC_VECTOR(NUM_OF_LEDS - 1 DOWNTO 0) := (OTHERS => '0');
SIGNAL n_period : UNSIGNED(NUM_OF_SWS DOWNTO 0) := to_unsigned(1, NUM_OF_SWS + 1);
SIGNAL up : STD_LOGIC := '1';
BEGIN
-- Instantiate the PWM
-- Instantiate the PWM modules
PWM : FOR i IN 1 TO TAIL_LENGTH GENERATE
BEGIN
PWM : PulseWidthModulator
GENERIC MAP(
BIT_LENGTH => BIT_LENGTH,
T_ON_INIT => 64,
PERIOD_INIT => 128,
PWM_INIT => '0'
BIT_LENGTH => BIT_LENGTH
)
PORT MAP(
reset => reset,
clk => clk,
Ton => STD_LOGIC_VECTOR(to_unsigned(i, BIT_LENGTH)),
Period => STD_LOGIC_VECTOR(to_unsigned(TAIL_LENGTH - 1, BIT_LENGTH)),
PWM => leds_pwm(i - 1)
PWM => pwms(i - 1)
);
END GENERATE;
-- Sincronous logic
-- Synchronous logic for LED control
PROCESS (clk, reset)
VARIABLE counter : UNSIGNED(46 DOWNTO 0) := (OTHERS => '0');
VARIABLE up : STD_LOGIC := '1'; -- Direction of LED movement
VARIABLE leds_sr : leds_sr_type := (OTHERS => 0); -- Shift register for LED positions
VARIABLE counter : UNSIGNED(46 DOWNTO 0) := (OTHERS => '0'); -- Timing counter
VARIABLE n_period : UNSIGNED(NUM_OF_SWS DOWNTO 0) := to_unsigned(1, NUM_OF_SWS + 1); -- Period multiplier
BEGIN
IF reset = '1' THEN
leds_sr <= (OTHERS => 0);
led_sig <= (OTHERS => '0');
counter := (OTHERS => '0');
up <= '1';
leds_sig <= (OTHERS => '0'); -- Turn off all LEDs
leds_sr := (OTHERS => 0); -- Reset shift register
counter := (OTHERS => '0'); -- Reset counter
up := '1'; -- Set initial direction
ELSIF rising_edge(clk) THEN
-- Update period multiplier based on switches
n_period := unsigned('0' & sw) + 1;
-- Kitt logic: Update direction
IF leds_sr(TAIL_LENGTH - 1) = led'high THEN
up <= '0';
ELSIF leds_sr(TAIL_LENGTH - 1) = led'low THEN
up <= '1';
END IF;
-- Increment the counter
-- Increment counter
counter := counter + to_unsigned(CLK_PERIOD_NS, counter'LENGTH);
-- Calculate the number of periods
-- Check if counter exceeds threshold
IF counter >= (MIN_KITT_CAR_STEP_NS * n_period) THEN
-- Update direction
IF leds_sr(leds_sr'HIGH) = led'high THEN
up := '0'; -- Change to backward
ELSIF leds_sr(leds_sr'HIGH) = led'low THEN
up := '1'; -- Change to forward
END IF;
-- Reset led_sig
led_sig <= (OTHERS => '0');
-- Shift the leds
-- Shift LEDs based on direction
IF up = '1' THEN
leds_sr <= (leds_sr(TAIL_LENGTH - 1) + 1) & leds_sr(TAIL_LENGTH - 1 DOWNTO 1);
leds_sr := (leds_sr(leds_sr'HIGH) + 1) & leds_sr(leds_sr'HIGH DOWNTO 1);
ELSE
leds_sr <= (leds_sr(TAIL_LENGTH - 1) - 1) & leds_sr(TAIL_LENGTH - 1 DOWNTO 1);
leds_sr := (leds_sr(leds_sr'HIGH) - 1) & leds_sr(leds_sr'HIGH DOWNTO 1);
END IF;
-- Assign the LEDs
FOR i IN 0 TO TAIL_LENGTH - 1 LOOP
led_sig(leds_sr(i)) <= leds_pwm(i);
counter := (OTHERS => '0'); -- Reset counter
END IF;
-- Assign PWM signals to LEDs
leds_sig <= (OTHERS => '0');
FOR i IN leds_sr'REVERSE_RANGE LOOP
leds_sig(leds_sr(i)) <= pwms(i);
END LOOP;
-- Reset the counter
counter := (OTHERS => '0');
END IF;
END IF;
END PROCESS;
-- Handle the switch
PROCESS (sw)
BEGIN
n_period <= unsigned('0' & sw) + 1;
END PROCESS;
led <= led_sig;
-- Assign LED signals to output
led <= leds_sig;
END Behavioral;

View File

@@ -33,10 +33,7 @@ use IEEE.NUMERIC_STD.ALL;
entity PulseWidthModulator is
Generic(
BIT_LENGTH : INTEGER RANGE 1 to 16 := 8;
T_ON_INIT : POSITIVE := 64;
PERIOD_INIT : POSITIVE := 128;
PWM_INIT : STD_LOGIC := '0'
BIT_LENGTH : INTEGER RANGE 1 to 16 := 8
);
Port (
reset : IN STD_LOGIC;

View File

@@ -46,7 +46,7 @@
<Option Name="IPUserFilesDir" Val="$PIPUSERFILESDIR"/>
<Option Name="IPStaticSourceDir" Val="$PIPUSERFILESDIR/ipstatic"/>
<Option Name="EnableBDX" Val="FALSE"/>
<Option Name="WTXSimLaunchSim" Val="0"/>
<Option Name="WTXSimLaunchSim" Val="26"/>
<Option Name="WTModelSimLaunchSim" Val="0"/>
<Option Name="WTQuestaLaunchSim" Val="0"/>
<Option Name="WTIesLaunchSim" Val="0"/>
@@ -107,9 +107,15 @@
</FileSet>
<FileSet Name="sim_1" Type="SimulationSrcs" RelSrcDir="$PSRCDIR/sim_1" RelGenDir="$PGENDIR/sim_1">
<Filter Type="Srcs"/>
<File Path="$PPRDIR/../../sim/tb_KittCarPWM.vhd">
<FileInfo>
<Attr Name="UsedIn" Val="synthesis"/>
<Attr Name="UsedIn" Val="simulation"/>
</FileInfo>
</File>
<Config>
<Option Name="DesignMode" Val="RTL"/>
<Option Name="TopModule" Val="KittCarPWM"/>
<Option Name="TopModule" Val="tb_KittCarPWM"/>
<Option Name="TopLib" Val="xil_defaultlib"/>
<Option Name="TopAutoSet" Val="TRUE"/>
<Option Name="TransportPathDelay" Val="0"/>