Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Altera_Forum
Honored Contributor I
811 Views

Adjustable frequency generator

Hi, 

 

I am trying to implement adjustable rectangular wave generator in MAX10. The code below: 

 

library ieee;use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity DIVIDER_2 is port( clk: in STD_LOGIC; O : out STD_LOGIC ); end DIVIDER_2; architecture DIVIDER_2 of DIVIDER_2 is signal divider: integer range 0 to 20000:=666; -- USTAWIAMY DZIELNIK signal counter: integer range 0 to 2000:=0; signal OI : STD_LOGIC; begin O <= OI; process (clk) is begin if rising_edge (clk) then if (counter < divider) then counter <= counter + 1; else OI <= not OI; counter <= 0; divider <= divider + 1; end if; end if; end process; end DIVIDER_2; 

 

It doesn't work. Without incrementation divider each half cycle, works well. 

Does anyone have any idea what is wrong?
0 Kudos
5 Replies
Altera_Forum
Honored Contributor I
24 Views

Just think a bit. 

 

Counter is implemented in synthesis as unsigned(11 downto 0) with an actual range of 0 to 2047. Once divider value exceeds 2047, the else conditions becomes never true and output toggling and further increment of divider stops. 

 

Consider what you exactly want to achieve and design the code respectively.
Altera_Forum
Honored Contributor I
24 Views

I already changed that and it still doesn't work. 

 

library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity DIVIDER_2 is port( clk: in STD_LOGIC; O : out STD_LOGIC ); end DIVIDER_2; architecture DIVIDER_2 of DIVIDER_2 is signal OI : STD_LOGIC; signal divider: integer range 0 to 20000:=666; -- set divider signal counter: integer range 0 to 20000:=0; begin O <= OI; process (clk) is begin if rising_edge (clk) then if (counter < divider) then counter <= counter + 1; else OI <= not OI; counter <= 0; divider <= divider + 1; end if; end if; end process; end DIVIDER_2;  

 

Osciloscope png presents output O at channel 2. 

 

https://alteraforum.com/forum/attachment.php?attachmentid=14137&stc=1
Altera_Forum
Honored Contributor I
24 Views

You can just implement it in the same way as a DDS. For example, you could have a 32-bit unsigned phase accumulator and 32-bit unsigned tuneword. Choose the tuneword to get the frequency you want and just increment the phase accumulator by it each clock cycle. By using an unsigned, it will automatically wrap around.  

 

For a normal DDS, you would use the upper few bits as an index into a sin wave table. In your case, the upper bit is your square wave.  

 

The tuneword is just F * 2**32 / Fclk
Altera_Forum
Honored Contributor I
24 Views

There is problem with division in fpga. I need as I sad variable frequency. So there are 2 possible ways: make table with tuning words or calculate them.  

fclk=400MHz 

fout=150-400kHz, resolution 100Hz 

2500(2^21)tuning words 

In my experience division doesn't work on fpga.
Altera_Forum
Honored Contributor I
24 Views

People do division in FPGA's all the time. You just need to normalize it. Say you need to multiply by 1.3. Normalize it to use a power of 2 division by say 1024 * 1.3 = 1331. So to multiply 12 * 1.3 you do 12 * 1331 = 15972 and then right shift by 10 (ie 2^10 = 1024) to get 15. You can round to nearest integer by adding in the highest order bit that is shifted out. For example, 15972 is 11_1110_0110_0100 binary and bit 9 is a 1 so the result is 16. So now you just need a multiplier, 1 bit adder and slice out the result.  

 

You don't say how you want to vary the frequency. Your original post makes it seem like you are trying to steadily decrease it with each half wave and won't work as written for the reason FvM said. You could do that by decrimenting the tuneword.  

 

For your second attempt, 20000 is not a power of 2. What do you think is going to happen when divider and counter get to 20000 and you add 1?