Forum Discussion
Altera_Forum
Honored Contributor
10 years agoThis sounds exactly like a little experiment we ran.
I managed to create a 128 bit down counter that gave an FMax of 450 Mhz in Timequest (using a stratix 4, all pins virtual). To make it an upcounter you can simply invert the output. It is split into 16x 8 bit down counters. Each counter outputs an "is_0" signal that is generated when counter = 1 and it is enabled. The enable of the next counter simply ANDs all the 0s together.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity cnt8 is
port (
clk : in std_logic;
clk_en : in std_logic;
load : in std_logic;
load_val : in unsigned(7 downto 0);
is_0 : out std_logic
);
end entity cnt8;
architecture rtl of cnt8 is
signal cnt : unsigned(7 downto 0);
begin
cnt_proc : process(clk)
begin
if rising_edge(clk) then
if load = '1' then
cnt <= load_val;
if load_val = 0 then
is_0 <= '1';
else
is_0 <= '0';
end if;
elsif clk_en = '1' then
cnt <= cnt - 1;
if cnt = 1 then
is_0 <= '1';
else
is_0 <= '0';
end if;
end if;
end if;
end process;
end architecture rtl;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_misc.all;
entity counter_challenge is
port (
clk : in std_logic;
load_val : in unsigned(127 downto 0);
load : in std_logic;
done : out std_logic
);
end entity counter_challenge;
architecture rtl of counter_challenge is
signal cnt : unsigned(127 downto 0);
signal load_r : std_logic;
signal load_val_r : unsigned(127 downto 0);
signal is_0_array : std_logic_vector(0 to 15);
begin
cnt_proc : process(clk)
begin
if rising_edge(clk) then
load_r <= load;
load_val_r <= load_val;
if and_reduce( is_0_array ) = '1' and load = '0' then
done <= '1';
else
done <= '0';
end if;
end if;
end process;
counter_gen : for i in 0 to 15 generate
signal count_en : std_logic;
begin
process(is_0_array)
variable cnt_en_high : std_logic;
variable cnt_en_low : std_logic;
begin
cnt_en_high := '0';
cnt_en_low := '1';
for j in 0 to i-1 loop
cnt_en_low := cnt_en_low and is_0_array(j);
end loop;
for j in i to 15 loop
cnt_en_high := cnt_en_high or not is_0_array(j);
end loop;
count_en <= cnt_en_low and cnt_en_high;
end process;
cnt8_inst : entity work.cnt8
port map (
clk => clk,
clk_en => count_en,
load => load_r,
load_val => load_val_r( (i+1)*8 -1 downto i*8 ),
is_0 => is_0_array(i)
);
end generate counter_gen;
end architecture rtl;