EmbDev.net

Forum: FPGA, VHDL & Verilog Clock frequency reducer


von Eric J. (coderic)


Rate this post
useful
not useful
I am trying to divide my input clock signal by 10 - effectively setting 
my out HIGH 5 of ten clock pulses and LOW the other 5.

However, my counter idea does not work - the clk_ou2 signal doesn't 
update at all, and I do not know why.

1
library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4
5
entity Taktteiler is
6
7
port (
8
    clk_in : in std_logic;
9
    clk_out : out std_logic;
10
    reset : in std_logic
11
);
12
end Taktteiler;
13
14
architecture rtl of Taktteiler is
15
16
signal counter : unsigned(3 downto 0);
17
signal clk_out2 : std_logic := '0';
18
19
begin
20
process(clk_in)
21
    begin
22
        if(rising_edge(clk_in)) then
23
            counter <= counter + 1;
24
            if std_logic_vector(counter) = "101" then --reset the counter at 101
25
                counter <= (others => '0');
26
                clk_out2 <= clk_out2 XOR '1'; --toggle the out2 signal
27
            end if;
28
        end if;
29
        if reset = '1' then --reset on HIGH reset input
30
            counter <= (others => '0');
31
            clk_out2 <= '0';
32
        end if;
33
end process;
34
clk_out <= clk_out2;
35
end architecture rtl;

von Achim S. (Guest)


Rate this post
useful
not useful
counter is a 4 bit vector. It can never be equal to "101", because that 
ist a 3 bit vector. So std_logic_vector(counter) = "101" will never be 
true...

Try to replace line 24 by
    if counter="0101" then

If it works, then check, if you really divide by 10 or by some other 
value..

von Duke Scarring (Guest)


Attached files:

Rate this post
useful
not useful
I prefer a simple solution with just a single shift register:
1
library ieee;
2
use ieee.std_logic_1164.all;
3
4
entity clk_divider is
5
    port
6
    (
7
        clk_in  : in  std_logic;
8
        clk_out : out std_logic
9
    );
10
end entity clk_divider;
11
12
architecture rtl of clk_divider is
13
14
    signal clk_reg : std_logic_vector( 9 downto 0) := "0000011111";
15
16
begin
17
    
18
    process
19
    begin
20
        wait until rising_edge( clk_in);
21
        clk_reg <= clk_reg( clk_reg'high-1 downto 0) & clk_reg( clk_reg'high);
22
    end process;
23
24
    clk_out <= clk_reg( clk_reg'high);
25
26
end architecture rtl;

Duke

von Lothar M. (Company: Titel) (lkmiller) (Moderator)


Rate this post
useful
not useful
Eric J. wrote:
> signal counter : unsigned(3 downto 0);
Achim S. wrote:
> counter is a 4 bit vector. It can never be equal to "101"
To get rid of such kind of problems I would use an integer range 0 to 9 
for counting.
Then the compare for 0 and 5 is easily human readable:
1
:
2
signal counter : unsigned(3 downto 0);
3
:
4
:
5
   process(clk_in)
6
   begin
7
      if(rising_edge(clk_in)) then
8
         if counter<9 then counter <= counter + 1;
9
         else              counter <= 0;
10
         end if;   
11
         if counter = 0 then clk_out <= '0'; end if;
12
         if counter = 5 then clk_out <= '1'; end if;
13
   end process;
14
:

Duke Scarring wrote:
> I prefer a simple solution with just a single shift register
I prefer the very same without any process ;-)
1
library ieee;
2
use ieee.std_logic_1164.all;
3
4
entity clk_divider is
5
    port ( clk_in  : in  std_logic;
6
           clk_out : out std_logic);
7
end entity clk_divider;
8
9
architecture rtl of clk_divider is
10
    signal clk_reg : std_logic_vector(9 downto 0) := "0000011111";
11
begin
12
    clk_reg <= clk_reg(8 downto 0) & clk_reg(9) when rising_edge(clk_in);
13
    clk_out <= clk_reg(9);
14
end architecture rtl;

: Edited by Moderator
Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.