Refactor KittCar and KittCarPWM for improved LED control; update simulation settings and add testbench
This commit is contained in:
85
LAB1/sim/tb_KittCarPWM.vhd
Normal file
85
LAB1/sim/tb_KittCarPWM.vhd
Normal 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;
|
||||||
@@ -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);
|
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 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
|
BEGIN
|
||||||
|
|
||||||
-- Sincronous logic
|
-- Sincronous logic
|
||||||
PROCESS (clk, reset)
|
PROCESS (clk, reset)
|
||||||
VARIABLE counter : UNSIGNED(46 DOWNTO 0) := (OTHERS => '0');
|
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
|
BEGIN
|
||||||
IF reset = '1' THEN
|
IF reset = '1' THEN
|
||||||
leds_sr <= (OTHERS => '0');
|
leds_sr <= (OTHERS => '0');
|
||||||
counter := (OTHERS => '0');
|
counter := (OTHERS => '0');
|
||||||
ELSIF rising_edge(clk) THEN
|
ELSIF rising_edge(clk) THEN
|
||||||
|
|
||||||
|
-- Handle the switch
|
||||||
|
n_period := unsigned('0' & sw) + 1;
|
||||||
|
|
||||||
-- Kitt logic
|
-- Kitt logic
|
||||||
IF unsigned(leds_sr) = 0 THEN
|
IF unsigned(leds_sr) = 0 THEN
|
||||||
leds_sr(0) <= '1';
|
leds_sr(0) <= '1';
|
||||||
up <= '1';
|
up := '1';
|
||||||
ELSIF leds_sr(led'HIGH) = '1' THEN
|
ELSIF leds_sr(led'HIGH) = '1' THEN
|
||||||
up <= '0';
|
up := '0';
|
||||||
ELSIF leds_sr(led'LOW) = '1' THEN
|
ELSIF leds_sr(led'LOW) = '1' THEN
|
||||||
up <= '1';
|
up := '1';
|
||||||
END IF;
|
END IF;
|
||||||
|
|
||||||
-- Increment the counter
|
-- Increment the counter
|
||||||
@@ -75,12 +78,6 @@ BEGIN
|
|||||||
END IF;
|
END IF;
|
||||||
END PROCESS;
|
END PROCESS;
|
||||||
|
|
||||||
-- Handle the switch
|
|
||||||
PROCESS (sw)
|
|
||||||
BEGIN
|
|
||||||
n_period <= unsigned('0' & sw) + 1;
|
|
||||||
END PROCESS;
|
|
||||||
|
|
||||||
led <= leds_sr;
|
led <= leds_sr;
|
||||||
|
|
||||||
END Behavioral;
|
END Behavioral;
|
||||||
@@ -32,10 +32,7 @@ END KittCarPWM;
|
|||||||
ARCHITECTURE Behavioral OF KittCarPWM IS
|
ARCHITECTURE Behavioral OF KittCarPWM IS
|
||||||
COMPONENT PulseWidthModulator
|
COMPONENT PulseWidthModulator
|
||||||
GENERIC (
|
GENERIC (
|
||||||
BIT_LENGTH : INTEGER RANGE 1 TO 16;
|
BIT_LENGTH : INTEGER
|
||||||
T_ON_INIT : POSITIVE;
|
|
||||||
PERIOD_INIT : POSITIVE;
|
|
||||||
PWM_INIT : STD_LOGIC
|
|
||||||
);
|
);
|
||||||
PORT (
|
PORT (
|
||||||
reset : IN STD_LOGIC;
|
reset : IN STD_LOGIC;
|
||||||
@@ -47,88 +44,79 @@ ARCHITECTURE Behavioral OF KittCarPWM IS
|
|||||||
);
|
);
|
||||||
END COMPONENT;
|
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 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
|
BEGIN
|
||||||
|
|
||||||
-- Instantiate the PWM
|
-- Instantiate the PWM modules
|
||||||
PWM : FOR i IN 1 TO TAIL_LENGTH GENERATE
|
PWM : FOR i IN 1 TO TAIL_LENGTH GENERATE
|
||||||
BEGIN
|
BEGIN
|
||||||
PWM : PulseWidthModulator
|
PWM : PulseWidthModulator
|
||||||
GENERIC MAP(
|
GENERIC MAP(
|
||||||
BIT_LENGTH => BIT_LENGTH,
|
BIT_LENGTH => BIT_LENGTH
|
||||||
T_ON_INIT => 64,
|
|
||||||
PERIOD_INIT => 128,
|
|
||||||
PWM_INIT => '0'
|
|
||||||
)
|
)
|
||||||
PORT MAP(
|
PORT MAP(
|
||||||
reset => reset,
|
reset => reset,
|
||||||
clk => clk,
|
clk => clk,
|
||||||
Ton => STD_LOGIC_VECTOR(to_unsigned(i, BIT_LENGTH)),
|
Ton => STD_LOGIC_VECTOR(to_unsigned(i, BIT_LENGTH)),
|
||||||
Period => STD_LOGIC_VECTOR(to_unsigned(TAIL_LENGTH - 1, BIT_LENGTH)),
|
Period => STD_LOGIC_VECTOR(to_unsigned(TAIL_LENGTH - 1, BIT_LENGTH)),
|
||||||
PWM => leds_pwm(i - 1)
|
PWM => pwms(i - 1)
|
||||||
);
|
);
|
||||||
END GENERATE;
|
END GENERATE;
|
||||||
|
|
||||||
-- Sincronous logic
|
-- Synchronous logic for LED control
|
||||||
PROCESS (clk, reset)
|
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
|
BEGIN
|
||||||
IF reset = '1' THEN
|
IF reset = '1' THEN
|
||||||
leds_sr <= (OTHERS => 0);
|
leds_sig <= (OTHERS => '0'); -- Turn off all LEDs
|
||||||
led_sig <= (OTHERS => '0');
|
leds_sr := (OTHERS => 0); -- Reset shift register
|
||||||
counter := (OTHERS => '0');
|
counter := (OTHERS => '0'); -- Reset counter
|
||||||
up <= '1';
|
up := '1'; -- Set initial direction
|
||||||
ELSIF rising_edge(clk) THEN
|
ELSIF rising_edge(clk) THEN
|
||||||
|
-- Update period multiplier based on switches
|
||||||
|
n_period := unsigned('0' & sw) + 1;
|
||||||
|
|
||||||
-- Kitt logic: Update direction
|
-- Increment counter
|
||||||
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
|
|
||||||
counter := counter + to_unsigned(CLK_PERIOD_NS, counter'LENGTH);
|
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
|
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
|
-- Shift LEDs based on direction
|
||||||
led_sig <= (OTHERS => '0');
|
|
||||||
|
|
||||||
-- Shift the leds
|
|
||||||
IF up = '1' THEN
|
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
|
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;
|
END IF;
|
||||||
|
|
||||||
-- Assign the LEDs
|
counter := (OTHERS => '0'); -- Reset counter
|
||||||
FOR i IN 0 TO TAIL_LENGTH - 1 LOOP
|
END IF;
|
||||||
led_sig(leds_sr(i)) <= leds_pwm(i);
|
|
||||||
|
-- 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;
|
END LOOP;
|
||||||
|
|
||||||
-- Reset the counter
|
|
||||||
counter := (OTHERS => '0');
|
|
||||||
END IF;
|
|
||||||
END IF;
|
END IF;
|
||||||
END PROCESS;
|
END PROCESS;
|
||||||
|
|
||||||
-- Handle the switch
|
-- Assign LED signals to output
|
||||||
PROCESS (sw)
|
led <= leds_sig;
|
||||||
BEGIN
|
|
||||||
n_period <= unsigned('0' & sw) + 1;
|
|
||||||
END PROCESS;
|
|
||||||
|
|
||||||
led <= led_sig;
|
|
||||||
|
|
||||||
END Behavioral;
|
END Behavioral;
|
||||||
@@ -33,10 +33,7 @@ use IEEE.NUMERIC_STD.ALL;
|
|||||||
|
|
||||||
entity PulseWidthModulator is
|
entity PulseWidthModulator is
|
||||||
Generic(
|
Generic(
|
||||||
BIT_LENGTH : INTEGER RANGE 1 to 16 := 8;
|
BIT_LENGTH : INTEGER RANGE 1 to 16 := 8
|
||||||
T_ON_INIT : POSITIVE := 64;
|
|
||||||
PERIOD_INIT : POSITIVE := 128;
|
|
||||||
PWM_INIT : STD_LOGIC := '0'
|
|
||||||
);
|
);
|
||||||
Port (
|
Port (
|
||||||
reset : IN STD_LOGIC;
|
reset : IN STD_LOGIC;
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
<Option Name="IPUserFilesDir" Val="$PIPUSERFILESDIR"/>
|
<Option Name="IPUserFilesDir" Val="$PIPUSERFILESDIR"/>
|
||||||
<Option Name="IPStaticSourceDir" Val="$PIPUSERFILESDIR/ipstatic"/>
|
<Option Name="IPStaticSourceDir" Val="$PIPUSERFILESDIR/ipstatic"/>
|
||||||
<Option Name="EnableBDX" Val="FALSE"/>
|
<Option Name="EnableBDX" Val="FALSE"/>
|
||||||
<Option Name="WTXSimLaunchSim" Val="0"/>
|
<Option Name="WTXSimLaunchSim" Val="26"/>
|
||||||
<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"/>
|
||||||
@@ -107,9 +107,15 @@
|
|||||||
</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"/>
|
<Filter Type="Srcs"/>
|
||||||
|
<File Path="$PPRDIR/../../sim/tb_KittCarPWM.vhd">
|
||||||
|
<FileInfo>
|
||||||
|
<Attr Name="UsedIn" Val="synthesis"/>
|
||||||
|
<Attr Name="UsedIn" Val="simulation"/>
|
||||||
|
</FileInfo>
|
||||||
|
</File>
|
||||||
<Config>
|
<Config>
|
||||||
<Option Name="DesignMode" Val="RTL"/>
|
<Option Name="DesignMode" Val="RTL"/>
|
||||||
<Option Name="TopModule" Val="KittCarPWM"/>
|
<Option Name="TopModule" Val="tb_KittCarPWM"/>
|
||||||
<Option Name="TopLib" Val="xil_defaultlib"/>
|
<Option Name="TopLib" Val="xil_defaultlib"/>
|
||||||
<Option Name="TopAutoSet" Val="TRUE"/>
|
<Option Name="TopAutoSet" Val="TRUE"/>
|
||||||
<Option Name="TransportPathDelay" Val="0"/>
|
<Option Name="TransportPathDelay" Val="0"/>
|
||||||
|
|||||||
Reference in New Issue
Block a user