From 7b5130669630d194faa87a0bb01b2050d92b24f2 Mon Sep 17 00:00:00 2001 From: Davide Date: Sat, 22 Mar 2025 17:02:22 +0100 Subject: [PATCH] Refactor KittCar and KittCarPWM for improved LED control; update simulation settings and add testbench --- LAB1/sim/tb_KittCarPWM.vhd | 85 ++++++++++++++++ LAB1/src/KittCar.vhd | 19 ++-- LAB1/src/KittCarPWM.vhd | 98 ++++++++----------- LAB1/src/PulseWidthModulator.vhd | 5 +- .../lab1_kit_car_pwm/lab1_kit_car_pwm.xpr | 10 +- 5 files changed, 145 insertions(+), 72 deletions(-) create mode 100644 LAB1/sim/tb_KittCarPWM.vhd diff --git a/LAB1/sim/tb_KittCarPWM.vhd b/LAB1/sim/tb_KittCarPWM.vhd new file mode 100644 index 0000000..c089ee6 --- /dev/null +++ b/LAB1/sim/tb_KittCarPWM.vhd @@ -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; diff --git a/LAB1/src/KittCar.vhd b/LAB1/src/KittCar.vhd index 8da3ccd..662caeb 100644 --- a/LAB1/src/KittCar.vhd +++ b/LAB1/src/KittCar.vhd @@ -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; \ No newline at end of file diff --git a/LAB1/src/KittCarPWM.vhd b/LAB1/src/KittCarPWM.vhd index f2d29a0..62d05e6 100644 --- a/LAB1/src/KittCarPWM.vhd +++ b/LAB1/src/KittCarPWM.vhd @@ -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 - - -- Reset led_sig - led_sig <= (OTHERS => '0'); - - -- Shift the leds - IF up = '1' THEN - leds_sr <= (leds_sr(TAIL_LENGTH - 1) + 1) & leds_sr(TAIL_LENGTH - 1 DOWNTO 1); - ELSE - leds_sr <= (leds_sr(TAIL_LENGTH - 1) - 1) & leds_sr(TAIL_LENGTH - 1 DOWNTO 1); + -- 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; - -- Assign the LEDs - FOR i IN 0 TO TAIL_LENGTH - 1 LOOP - led_sig(leds_sr(i)) <= leds_pwm(i); - END LOOP; + -- Shift LEDs based on direction + IF up = '1' THEN + leds_sr := (leds_sr(leds_sr'HIGH) + 1) & leds_sr(leds_sr'HIGH DOWNTO 1); + ELSE + leds_sr := (leds_sr(leds_sr'HIGH) - 1) & leds_sr(leds_sr'HIGH DOWNTO 1); + END IF; - -- Reset the counter - counter := (OTHERS => '0'); + 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; 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; \ No newline at end of file diff --git a/LAB1/src/PulseWidthModulator.vhd b/LAB1/src/PulseWidthModulator.vhd index bd7c9d5..674779d 100644 --- a/LAB1/src/PulseWidthModulator.vhd +++ b/LAB1/src/PulseWidthModulator.vhd @@ -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; diff --git a/LAB1/vivado/lab1_kit_car_pwm/lab1_kit_car_pwm.xpr b/LAB1/vivado/lab1_kit_car_pwm/lab1_kit_car_pwm.xpr index cff86d3..47c5e4d 100644 --- a/LAB1/vivado/lab1_kit_car_pwm/lab1_kit_car_pwm.xpr +++ b/LAB1/vivado/lab1_kit_car_pwm/lab1_kit_car_pwm.xpr @@ -46,7 +46,7 @@