Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] Frequency divider with changeable frequency

Status
Not open for further replies.

Feco

Newbie level 6
Joined
May 13, 2013
Messages
12
Helped
0
Reputation
0
Reaction score
0
Trophy points
1,281
Activity points
1,371
Hello everyone.

I'm new to the FPGA world and a got a little problem.

I wanted to make a simple frequency divider with changeable frequency rate. The first part works good (there are lot of tutorials), but the second...
I have 8 buttons, with them I wanted to change the frequency between 0 and 255 Hz. It seemed, that it is an easy task. I coded it and its working, but not properly. When I use the buttons there is a delay time around 3-4 seconds (or even more). I don't think it should work that way. Is there any possibility to correct that delay?

Here is the code:

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


entity clk_div is
    Port ( CLK  : in  STD_LOGIC;
			  Freq : in  STD_LOGIC_VECTOR(7 downto 0);
           CLK2 : out  STD_LOGIC);
end clk_div;

architecture Behavioral of clk_div is

signal max : integer := (100000000/(to_integer(signed(Freq))*2))-1;
signal CLK_count : STD_LOGIC_VECTOR (30 downto 0);
signal sCLK2 : STD_LOGIC;
begin

process(CLK, max)
begin

if (rising_edge(CLK)) then
	if (CLK_count = max) then
		CLK_count <= (others => '0');
		sCLK2 <= not(sCLK2);
	else
		CLK_count <= CLK_count + 1;
	end if;
else
	null;
end if;
end process;

CLK2 <= sCLK2;
end Behavioral;

Maybe the type conversion takes long time?
If it matter, I use Digilent Nexys3 board with Spartan 6 FPGA.

Thanks.
 

You are checking the 'CLK_count' to see if it matches 'max'. If you change the settings for 'max' to something less than what the count is already at, you have to let in count all the way up to where it wraps back to zero, then count from that point to see the 'max' value again. You can either change the if statement to check for >= to 'max' (and adjust for the one extra count difference), or change it to < and swap the if and else parts of the statement so it adds to the count when the count is less than 'max'.


*** Why don't you use an integer for the clock count as well??
 
Last edited:
  • Like
Reactions: Feco

    Feco

    Points: 2
    Helpful Answer Positive Rating
Type conversions mean nothing in logic - remember on the circuit its just a load of bits. Types in VHDL are just for user convenience.

And why do you have an else clause with the clock?
 

the statement
Code:
signal max : integer := (100000000/(to_integer(signed(Freq))*2))-1;
bothers me.

I think this only works with generics, not with a port input.
So if you want Max to be kept up to date, you'll need to assign it differently.

Code:
And why do you have an else clause with the clock?
actually, he doesn't. "null" has no meaning in real logic. But to be clear, you can leave the else clause out.
be carefull to check Max (an integer) against Clk_Count (a std_logic_vector). VHDL is strongly typed.
And with Max changing, you better check for Count <= Max as :
Code:
if reset = '1' then -- I prefer a hard coded reset
   sCLK2 <= '0';
   Clk_Count <= 0; -- define as natural
elsif rising_edge(Clk) then
   if Clk_Count <= Max then
      sCLK2 <= not sCLK2;
      Clk_Count <= 0;
   else
      Clk_Count <= Clk_Count + 1;
   end if;
end if;
 
  • Like
Reactions: tpetar

    tpetar

    Points: 2
    Helpful Answer Positive Rating
The reason for the delay has been explained correctly by bking, I think.

Although the type conversion doesn't involve a problem, the divider inferred from the max expression requires a lot of logic. I guess, you actually want Freq interpreted as unsigned quantity!

By changing the design to a use a DDS phase accumulator, the logic effort can be most likely reduced.
Code:
if akku >= 100000000 then
  akku <= akku + Freq -100000000;
  sCLK2 <= not sCKL2;
else
  akku <= akku + Freq;
end if;
In contrast to the original design, it will generate an exact fractional division.

P.S.:
the statement
Code:
signal max : integer := (100000000/(to_integer(signed(Freq))*2))-1;bothers me.

I think this only works with generics, not with a port input.
So if you want Max to be kept up to date, you'll need to assign it differently.

This is possibly tool dependent, but most tools will infer a divider for this expression.
 
  • Like
Reactions: tpetar

    tpetar

    Points: 2
    Helpful Answer Positive Rating
bking's was the correct answer, it solved the problem, thanks.

*** Why don't you use an integer for the clock count as well??

Well, I have no idea, I just learnt that way, but you are right, I should use integer.

And why do you have an else clause with the clock?

I think it's better to know that 'else nothing happens...'


Now I have a new problem with that. It works great except between 127-255. I don't know why. I changed to freq from (7 downto 0) to (8 downto 0), now it works between 127-255, but not between 256-511. So there is something wrong with the most significant bit. Any idea why?
 

I think it's better to know that 'else nothing happens...'

I dont. And its not included in any register templates anywhere. Think about it - do you ever think anything ever could happen in that else block? if you ever did include code in there, you will get synthesis failures and quirky simulation results.


Now I have a new problem with that. It works great except between 127-255. I don't know why. I changed to freq from (7 downto 0) to (8 downto 0), now it works between 127-255, but not between 256-511. So there is something wrong
with the most significant bit. Any idea why?

Got a testbench?
 

It works great except between 127-255.
As already said, you make an erroneous conversion to signed(), which explains the observation. Should be unsigned().
 
  • Like
Reactions: tpetar and Feco

    Feco

    Points: 2
    Helpful Answer Positive Rating

    tpetar

    Points: 2
    Helpful Answer Positive Rating
I think it's better to know that 'else nothing happens...
You just think it is. ;) Remember, it's called hardware description language for a reason. You try and describe your design according to a set of rules such that THE SYNTHESIZER (aka, not you) thinks it's a good idea and understands what logic to infer. While you may think it's pretty, the synthesizer may go WTF? and decide to infer something unintended based on your attempted hardware description. It really is just a matter of knowing what templates the synthesizer will recognize, and sticking with it. Making up your own because you feel it makes sense to you will not help you in getting a working design.

Short version: stick to the boring templates and stuff will actually work as intended.
 

Oh, I haven't seen it, thx.
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top