clock enable question

J

Jim

Guest
I created the following clock enable block:

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity clock_enable is
generic (
OUTPUT_CLOCK_ENABLE_PERIOD : time;
INPUT_CLOCK_ENABLE_PERIOD : time
);
port (
clk : in std_logic;
reset : in std_logic;
enable : in std_logic;
clock_enable : out std_logic
);
end clock_enable;

architecture behavioral of clock_enable is
constant CE_CLOCK_ENABLE_TIMEOUT_COUNT : natural :=
OUTPUT_CLOCK_ENABLE_PERIOD / INPUT_CLOCK_ENABLE_PERIOD;
signal clock_enable_i : std_logic := '0';
begin
clock_enable <= clock_enable_i;

pr_clock_enable_counter: process (clk, reset)
variable v_count : natural range 0 to
CE_CLOCK_ENABLE_TIMEOUT_COUNT;
begin
if reset = '1' then
clock_enable_i <= '0';
v_count := 0;
elsif rising_edge(clk) then
clock_enable_i <= '0';

if enable = '1' then
v_count := v_count + 1;

if v_count = CE_CLOCK_ENABLE_TIMEOUT_COUNT then
v_count := 0;
clock_enable_i <= '1';
end if;
end if;
end if;
end process pr_clock_enable_counter;
end architecture behavioral;

I am trying to use it as follows:

entity clock_enables is
port (
clk : in std_logic;
reset : in std_logic;
clock_enable_1_us : out std_logic;
clock_enable_1_ms : out std_logic
);
end clock_enables;

architecture structural of clock_enables is
signal clock_enable_1_us_i : std_logic;
begin
clock_enable_1_us <= clock_enable_1_us_i;

clock_enable_1_us_component : entity work.clock_enable generic map
(
OUTPUT_CLOCK_ENABLE_PERIOD => 1 ms,
INPUT_CLOCK_ENABLE_PERIOD => SYSCLOCK_PERIOD
) port map (
clk => clk,
reset => reset,
enable => '1',
clock_enable => clock_enable_1_us_i
);
clock_enable_1_ms_component : entity work.clock_enable generic map
(
OUTPUT_CLOCK_ENABLE_PERIOD => 1 ms,
INPUT_CLOCK_ENABLE_PERIOD => 1 us
) port map (
clk => clk,
reset => reset,
enable => clock_enable_1_us_i,
clock_enable => clock_enable_1_ms
);
end architecture structural;

The 1 us enable is correct, but the 1 ms clock enable that uses the 1
us clock enable is at the wrong frequency. When I look at the
synthesis output, the same size counter (7 bits) is used for the 1 ms
clock enable as for the 1 us clock enable. Does anyone have any ideas
what I am doing incorrectly?

Thanks,

Jim
 
On Jan 21, 2:46 pm, Jim <james.kn...@gmail.com> wrote:

The 1 us enable is correct, but the 1 ms clock enable that uses the 1
us clock enable is at the wrong frequency.  When I look at the
synthesis output, the same size counter (7 bits) is used for the 1 ms
clock enable as for the 1 us clock enable.
Your counters are not the right size...your 1 ms counter will need to
count to 1000 so it should take 10 bits, not 8. Since you didn't
specify what the system clock period is that drives the 1 us timer
it's not clear how many bits wide that should be. In any case, you
should consider using a simulator to detect the cause of functional
problems, not a synthesis report.

Does anyone have any ideas
what I am doing incorrectly?
The generic that specifies the output clock period of your 1us timer
is set to 1 ms instead of 1 us.
clock_enable_1_us_component : entity work.clock_enable generic map
(
OUTPUT_CLOCK_ENABLE_PERIOD => 1 ms,

Kevin Jennings
 
The generic that specifies the output clock period of your 1us timer
is set to 1 ms instead of 1 us.
    clock_enable_1_us_component : entity work.clock_enable generic map
(
        OUTPUT_CLOCK_ENABLE_PERIOD => 1 ms,

Kevin Jennings
Thanks, Kevin. The 1 ms was really 1 us. I changed that while
debugging. The 1 us component works and the module simulates
correctly for 1 us and 1 ms clock enables. I am under the impression
that when you set the range for the natural type the correct size
logic vector will be synthesized. Is that correct?

I changed the vhdl to pass in a generic name MAX_COUNT as a natural
and that works. I call the module as follows:

clock_enable_1_us_component : entity work.clock_enable generic map
(
MAX_COUNT => 1 us / SYSCLOCK_PERIOD
) port map (
clk => clk,
reset => reset,
enable => '1',
clock_enable => clock_enable_1_us_i
);

clock_enable_1_ms_component : entity work.clock_enable generic map
(
MAX_COUNT => 1 ms / 1 us
) port map (
clk => clk,
reset => reset,
enable => clock_enable_1_us_i,
clock_enable => clock_enable_1_ms
);

I just don't understand why it works this way, but not the original
way.
 
On Jan 22, 5:41 pm, Jim <james.kn...@gmail.com> wrote:
The generic that specifies the output clock period of your 1us timer
is set to 1 ms instead of 1 us.
    clock_enable_1_us_component : entity work.clock_enable generic map
(
        OUTPUT_CLOCK_ENABLE_PERIOD => 1 ms,

Kevin Jennings

Thanks, Kevin.  The 1 ms was really 1 us.  I changed that while
debugging.  The 1 us component works and the module simulates
correctly for 1 us and 1 ms clock enables.  I am under the impression
that when you set the range for the natural type the correct size
logic vector will be synthesized.  Is that correct?
Yes. I pass generics of type time into entities all of the time and
use them in the same fashion as you showed in your post. It works and
using 'time' more clearly specifies the intention on the interface.
The conversion to constants happens in the architecture and is used to
define the upper end of the integer range (again same as the code you
posted). One thing to keep in mind if you need to be as accurate as
possible is that the division of two 'time' types I don't think will
round off, instead I think it's a truncate. In your usage this won't
be a problem, but as a general solution I have a 'round' function that
takes as input two 'times', does the division and returns an integer
(function round(A:time; B: time) return integer;)

I changed the vhdl to pass in a generic name MAX_COUNT as a natural
and that works.  I call the module as follows:

clock_enable_1_us_component : entity work.clock_enable generic map
(
    MAX_COUNT => 1 us / SYSCLOCK_PERIOD
) port map (
    clk => clk,
    reset => reset,
    enable => '1',
    clock_enable => clock_enable_1_us_i
);

clock_enable_1_ms_component : entity work.clock_enable generic map
(
    MAX_COUNT => 1 ms / 1 us
) port map (
    clk => clk,
    reset => reset,
    enable => clock_enable_1_us_i,
    clock_enable => clock_enable_1_ms
);

I just don't understand why it works this way, but not the original
way.
Since you said at the start of this post "The 1 ms was really 1 us. I
changed that while debugging.", it's not clear just what is not
working and what are you actually getting when you use 'time'
generics. Also, since you changed the code, one can't help much since
we don't know what you have. Does it work in sim, but not in actual
hardware? My usages of using type 'time' have been with Quartus,
maybe other tools don't handle 'time' as well.

Kevin Jennings
 

Welcome to EDABoard.com

Sponsor

Back
Top