--- Sample Code for LSU EE 4702-1 Spring 2001
---
--- Population Modules and Testbench
---
-- Note: synthesizablity not tested.
--- Utility functions.
library ieee;
use ieee.std_logic_1164.all;
package mystuff is
function "srl" (a:std_logic_vector; n:natural) return std_logic_vector;
function "srl" (a:integer; n:natural) return integer;
end mystuff;
package body mystuff is
function "srl" (a:std_logic_vector; n:natural) return std_logic_vector is
variable b: std_logic_vector ( a'range );
begin
b := ( others => '0' );
b( b'high - n downto b'low ) := a( a'high downto a'low + n );
return b;
end;
function "srl" (a:integer; n:natural) return integer is
variable p:integer;
begin
if a >= 0 then
return a / 2 ** n;
else
p:= (-a) / 2 ** n;
if p > 0 then p:= p - 1; end if;
return integer'high / 2 ** (n-1) - p;
end if;
end;
end mystuff;
--- Combinational Population Counter
library ieee;
use ieee.std_logic_1164.all;
library Std_DevelopersKit;
use Std_DevelopersKit.Std_Regpak.all;
library work;
use work.mystuff.all;
entity popsc is
port( pop:out std_logic_vector (3 downto 0);
a: in std_logic_vector (7 downto 0));
end entity popsc;
architecture form1 of popsc is
begin
process(a)
variable pop_work: std_logic_vector ( pop'range );
variable a_work: std_logic_vector ( a'range );
begin
pop_work := ( others => '0' );
a_work := a;
for i in a'range loop
pop_work := pop_work + a_work(0);
a_work := a_work srl 1;
end loop;
pop <= pop_work;
end process;
end form1;
--- Sequential Population Counters
library ieee;
use ieee.std_logic_1164.all;
library Std_DevelopersKit;
use Std_DevelopersKit.Std_Regpak.all;
library work;
use work.mystuff.all;
entity pops is
port( pop:out std_logic_vector (3 downto 0);
rdy:out std_logic;
a: in std_logic_vector (7 downto 0);
clk:in std_logic);
end entity pops;
architecture form3 of pops is
begin
process
variable pop_work: std_logic_vector ( pop'range );
variable a_work, a_copy: std_logic_vector ( a'range ) := ( others => '0' );
begin
wait until rising_edge(clk);
if a_copy /= a then
wait until rising_edge(clk);
rdy <= '0';
pop_work := to_stdlogicvector(0,pop'length);
a_work := a;
a_copy := a;
wait until rising_edge(clk);
while a_work /= 0 loop
wait until rising_edge(clk);
pop_work := pop_work + a_work(0);
a_work := a_work srl 1;
end loop;
pop <= pop_work;
wait until rising_edge(clk);
end if;
if a_copy = a then rdy <= '1'; else rdy <= '0'; end if;
end process;
end form3;
library ieee;
use ieee.std_logic_1164.all;
library Std_DevelopersKit;
use Std_DevelopersKit.Std_Regpak.all;
use Std_DevelopersKit.Std_IOpak.all;
library work;
use work.mystuff.all;
entity poptb is end;
architecture a of poptb is
signal clk:std_logic:= '0';
signal rdy:std_logic;
signal pout,pout2:std_logic_vector (3 downto 0);
signal num:std_logic_vector (7 downto 0) := ( others => '0' );
function pop(a : integer) return integer is
variable p: integer := 0;
variable b: integer := a;
begin
while b /= 0 loop
p := p + b mod 2;
b := b srl 1;
end loop;
return p;
end;
begin
pop1:entity work.pops(form3) port map(pout,rdy,num,clk);
pop2:entity work.popsc(form1) port map(pout2,num);
clk <= not clk after 2 ns;
process
variable check: integer := 0;
begin
num <= to_stdlogicvector(1,num'length);
wait until rdy = '0'; wait until rdy = '1';
for i in 0 to 255 loop
num <= to_stdlogicvector(i,num'length);
if num /= i then wait until rdy = '0'; end if;
wait until rdy = '1';
assert '0' & pout = pop(i)
report "Seq wrong value i " & to_string(i) & " pop: " & to_string(pout)
severity failure;
assert '0' & pout2 = pop(i)
report "Cmb wrong value i " & to_string(i) & " pop: " & to_string(pout2)
severity failure;
check := check + to_integer( '0' & pout );
end loop;
assert check = 256 * 4
report "Incorrect check.";
assert false
report "Done with tests."
severity failure;
end process;
end a;