Continue to Site

[SOLVED] Controlled Frequency and Phase Shifts

nliaqat

Newbie level 6
Newbie level 6
Joined
Mar 31, 2025
Messages
11
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Activity points
86
What is a general approach to control both the 10KHZ frequency and phase (angle) shifts of a N-number of signals generation.

Code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity triangle_wave_gen is
    Port (
        clk       : in  STD_LOGIC;
        reset     : in  STD_LOGIC;
        triangle  : out STD_LOGIC_VECTOR(9 downto 0)  -- Output: -511 to 511
    );
end triangle_wave_gen;

architecture Behavioral of triangle_wave_gen is

    signal ramp_counter : unsigned(9 downto 0) := (others => '0'); -- 10-bit counter for 1024 steps
    signal triangle_val : integer range -511 to 511;


begin

    process(clk)
    begin
        if rising_edge(clk) then
            
            if reset = '1' then
                ramp_counter <= (others => '0');
            else
                -- Ramp with wrap-around (modulo 1024)
                if ramp_counter = 1023 then
                    ramp_counter <= (others => '0');
                else
                    ramp_counter <= ramp_counter + 1;
                end if;
            end if;
        end if;
    end process;

    -- Triangle generation and scaling
    process(ramp_counter)
        variable temp : integer;
    begin
        -- Create triangle wave from ramp
        if ramp_counter < 512 then
            temp := to_integer(ramp_counter);  -- 0 to 511
        else
            temp := 1023 - to_integer(ramp_counter); -- 511 down to 0
        end if;

        -- Scale to -511 to +511
        triangle_val <= 2 * temp - 511;

        -- Output conversion to std_logic_vector
        triangle <= std_logic_vector(to_signed(triangle_val, 10));
    end process;

end Behavioral;
 
Your question is unclear. Are you trying to generate "N number" of triangle waves? You've apparently already figured out how to generate one. Changing the increment value from 1 to some other value will change the frequency. Adding a delay will effect a phase shift.
 
Two signals of different frequency have no constant phase shift. To read sense into the question, you are apparently talking about

1. same frequency signals of different phase.
2. specifically you are talking about triangle signals

A general method has been sketched in your previous thread. https://www.edaboard.com/threads/spwm-generation.414610/post-1791309

Variable frequency generation can be achieved by NCO phase accumulator, see https://en.m.wikipedia.org/wiki/Numerically_controlled_oscillator

Generic_NCO.png


Phase can be modified by adding an offset to accumulator output. Like for the accumulator itself, you are using modulo arithmetic. Multiple phase shifted ramp outputs are represented by different offsets.

Finally the ramp (sawtooth) signal(s) can be converted to the intended waveform, e.g. triangle or sine.
 
Two signals of different frequency have no constant phase shift. To read sense into the question, you are apparently talking about

1. same frequency signals of different phase.
2. specifically you are talking about triangle signals

A general method has been sketched in your previous thread. https://www.edaboard.com/threads/spwm-generation.414610/post-1791309

Variable frequency generation can be achieved by NCO phase accumulator, see https://en.m.wikipedia.org/wiki/Numerically_controlled_oscillator

View attachment 198743

Phase can be modified by adding an offset to accumulator output. Like for the accumulator itself, you are using modulo arithmetic. Multiple phase shifted ramp outputs are represented by different offsets.

Finally the ramp (sawtooth) signal(s) can be converted to the intended waveform, e.g. triangle or sine.
First, thank you for your great guidance. However, in my previous thread, my triangular wave code isn't consistently generating the exact desired frequency. For example, when I set the target frequency to 1 kHz, the actual output often ends up being higher or lower—such as 1.2 kHz or 900 Hz—rather than the expected 1 kHz. In my previous code, I am using the following formula to calculate :
Code:
 CLK_CYCLES_PER_SAMPLE : integer := (CLK_FREQ / (WAVE_FREQ * SAMPLES_PER_CYCLE)).
[CENTER]
[/CENTER]
--- Updated ---

Your question is unclear. Are you trying to generate "N number" of triangle waves? You've apparently already figured out how to generate one. Changing the increment value from 1 to some other value will change the frequency. Adding a delay will effect a phase shift.
Yes, i want to make a general code for N number of triangular waves and how i can make a geeneral code taht will work also for N-phase shifts crossponding to repective triangel wave having 1024 sampels point.
 
Last edited:
For example, when I set the target frequency to 1 kHz, the actual output often ends up being higher or lower—such as 1.2 kHz or 900 Hz—rather than the expected 1 kHz.
Makes no sense for me. I don't even see where's CLK_CYCLES_PER_SAMPLE and SAMPLES_PER_CYCLE in your post#1 code. Anyway, NCO frequency generation works differently and hasn't much to do with your code.
 
Until your input/ output makes sense....

This may not be what you want but was the method how sampling scopes were invented.

I used to generate phase shift with my Doppler designs using a sample and hold. By subsampling a synchronous carrier of the desired shape ( Sawtooth, triangle, sine etc) phase shifting the sampling point produces the difference frequency with the exact same shape. The phase shift was the distance of the moving transmitter and the frequency was velocity.

Triangle waves as we know are the integral of all the odd harmonics of square waves with a 90 deg lag. Do you want multiple harmonics?
 
What is a general approach to control both the 10KHZ frequency and phase (angle) shifts of a N-number of signals generation.

Code:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity triangle_wave_gen is
    Port (
        clk       : in  STD_LOGIC;
        reset     : in  STD_LOGIC;
        triangle  : out STD_LOGIC_VECTOR(9 downto 0)  -- Output: -511 to 511
    );
end triangle_wave_gen;

architecture Behavioral of triangle_wave_gen is

    signal ramp_counter : unsigned(9 downto 0) := (others => '0'); -- 10-bit counter for 1024 steps
    signal triangle_val : integer range -511 to 511;


begin

    process(clk)
    begin
        if rising_edge(clk) then
    
            if reset = '1' then
                ramp_counter <= (others => '0');
            else
                -- Ramp with wrap-around (modulo 1024)
                if ramp_counter = 1023 then
                    ramp_counter <= (others => '0');
                else
                    ramp_counter <= ramp_counter + 1;
                end if;
            end if;
        end if;
    end process;

    -- Triangle generation and scaling
    process(ramp_counter)
        variable temp : integer;
    begin
        -- Create triangle wave from ramp
        if ramp_counter < 512 then
            temp := to_integer(ramp_counter);  -- 0 to 511
        else
            temp := 1023 - to_integer(ramp_counter); -- 511 down to 0
        end if;

        -- Scale to -511 to +511
        triangle_val <= 2 * temp - 511;

        -- Output conversion to std_logic_vector
        triangle <= std_logic_vector(to_signed(triangle_val, 10));
    end process;

end Behavioral;
I am not comfortable the way you generated your triangular wave. It seems like your code would generate 'temp' in the sequence 0,...,511,511,...,0,0,...,511,511,...,0,0,...

Your integer range is -512 to +511.

Why not use SIGNED data type, reset to 0, and then alternately increase to upper range value and decrease to the lower range value?
 
Last edited:


Write your reply...

LaTeX Commands Quick-Menu:

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top