- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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, JamesLink Copied
4 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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;
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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?- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
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.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The solution is exactly the same: register it and use the inequality:
if input /= input_reg then
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page