Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
13 years ago

How can I detect vector changes in other processes?

Hi All,

I’d like to experiment with various frequency & duty cycles to control a little motor with PWM. I’m using a DE0 devboard and the frequency & duty cycles are user programmable with the switches. My problem is that I don’t know how to reset my signals to 0 when either SW_FREQUENCY_SELECT_VECTOR or SW_DUTY_CYCLE_VECTOR is changed ( devkit switches are toggled) .

How can I detect vector changes in other processes?

My code:

LIBRARY IEEE;

use IEEE.STD_LOGIC_1164.ALL;

use IEEE.STD_LOGIC_UNSIGNED.ALL;

use IEEE.STD_LOGIC_ARITH.ALL;

--FREQUENCY CALCULATION

--50 000 000 50MHz

-- 1 000 000 1MHz

-- 20 000 20kHz

--

--

--50 000 000 / 20 000 = 2500 "0000100111000100"; - 20kHz

--

--250000ns

--250us

----------------

--

-- 0 000 100Hz 500000 "1111010000100100000"

-- 1 001 1000Hz 50000 "0001100001101010000"

-- 2 010 2200Hz 22727 "0000101100011000111"

-- 3 011 5000Hz 10000 "0000010011100010000"

-- 4 100 10000Hz 5000 "0000001001110001000"

-- 5 101 15000Hz 3333 "0000000110100000101"

-- 6 110 22000Hz 2272 "0000000100011100000"

-- 7 111 32000Hz 1562 "0000000011000011010"

---------------

--DUTY CYCLE CALCULATION

-- duty_cycle_stop = ( SW_FREQUENCY_VECTOR / 100 ) * SW_DUTY_CYCLE_VECTOR

-- example

-- 1250 = ( 2500 / 100 ) * 50

--

ENTITY PWM5 IS

PORT(

CLK : IN STD_LOGIC ;

LED0,LED1,LED2 : OUT STD_LOGIC ;

SW_VECTOR : IN std_logic_vector(9 downto 0);

BUTTON0,BUTTON1,BUTTON2 : IN STD_LOGIC ;

GPIO0_PIN2,GPIO0_PIN4 : OUT STD_LOGIC

);

END PWM5;

architecture PWMARCH of PWM5 is

alias RESET : STD_LOGIC is BUTTON0;

alias PWM_PIN : STD_LOGIC is GPIO0_PIN2;

alias SW_FREQUENCY_SELECT_VECTOR : std_logic_vector(2 downto 0) is SW_VECTOR(9 downto 7);

alias SW_DUTY_CYCLE_VECTOR : std_logic_vector(6 downto 0) is SW_VECTOR(6 downto 0);

signal count,duty_count : integer:=0;

signal duty_cycle_stop : integer:=0;

signal duty_cycle : STD_LOGIC;

signal SW_FREQUENCY_VECTOR : std_logic_vector(18 downto 0) :="0001100001101010000"; -- 1 50000 1000Hz

begin

--process(SW_FREQUENCY_SELECT_VECTOR,SW_VECTOR )

process(SW_FREQUENCY_SELECT_VECTOR)

begin

case SW_FREQUENCY_SELECT_VECTOR is

when "000" =>

SW_FREQUENCY_VECTOR <= "1111010000100100000"; -- 0 500000 100Hz

when "001" =>

SW_FREQUENCY_VECTOR <= "0001100001101010000"; -- 1 50000 1000Hz

when "010" =>

SW_FREQUENCY_VECTOR <= "0000101100011000111"; -- 2 22727 2200Hz

when "011" =>

SW_FREQUENCY_VECTOR <= "0000010011100010000"; -- 3 10000 5000Hz

when "100" =>

SW_FREQUENCY_VECTOR <= "0000001001110001000"; -- 4 5000 10000Hz

when "101" =>

SW_FREQUENCY_VECTOR <= "0000000110100000101"; -- 5 3333 15000Hz

when "110" =>

SW_FREQUENCY_VECTOR <= "0000000100011100000"; -- 6 2272 22000Hz

when "111" =>

SW_FREQUENCY_VECTOR <= "0000000011000011010"; -- 7 1562 32000Hz

-- will never reach this

when others =>

SW_FREQUENCY_VECTOR <= "0000010011100010000";

end case;

end process;

-- Update duty cycle

--process(SW_DUTY_CYCLE_VECTOR,SW_FREQUENCY_VECTOR,SW_FREQUENCY_SELECT_VECTOR,SW_VECTOR)

process(SW_DUTY_CYCLE_VECTOR,SW_FREQUENCY_VECTOR)

begin

-- duty_cycle_stop <= ( SW_FREQUENCY_VECTOR / 100 ) * SW_DUTY_CYCLE_VECTOR;

duty_cycle_stop <= ( conv_integer(SW_FREQUENCY_VECTOR) / 100 ) * conv_integer(SW_DUTY_CYCLE_VECTOR);

end process;

-- main process

process(CLK)

begin

if(RESET = '0') then

count <= 0;

duty_count <= 0;

duty_cycle <='0';

elsif(CLK'event and CLK='1') then

count <= count +1; --increment counter.

--see whether counter value is reached,if yes turn on the duty cycle

if(count >= conv_integer(SW_FREQUENCY_VECTOR)) then

count <= 0;

duty_count <= 0;

LED2 <='1';

PWM_PIN <='1';

duty_cycle <='1';

end if;

-- Duty cycle

if ( duty_cycle = '1' ) then

duty_count <= duty_count +1;

-- keep duty cycle high until duty_cycle_stop is reached

if(duty_count = duty_cycle_stop ) then

LED2 <= '0';

PWM_PIN <='0';

duty_cycle <='0';

end if;

end if;

end if;

end process;

end PWMARCH;

Thanks,

James

4 Replies

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    register them, and then look for a rising or falling edge on inside the clocked process:

    
    if rising_edge(clk) then
      if input = '1' and input_reg = '0' then --rising edge
        --reset
      end if;
      input_reg <= input;
    end if;
    
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi Tricky,

    Your solution would work if I was looking for a change in a STD_LOGIC but I need to detect changes on STD_LOGIC_VECTOR. Shall I check rising or falling edges on every bit in a vector?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    If you don't care about whether its a rising or falling edge can't you just use the /= operator (reg /= input)? Not sure how fast you are clocking the register but if it is a slow clock I think this would be fine.

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    The solution is exactly the same: register it and use the inequality:

    if input /= input_reg then