Skip to content

Instantly share code, notes, and snippets.

@hiyuh
Last active August 29, 2015 13:55
Show Gist options
  • Save hiyuh/8782789 to your computer and use it in GitHub Desktop.
Save hiyuh/8782789 to your computer and use it in GitHub Desktop.
simple 3 dimension ROM by using array.
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
package ROM_3D_PKG is
component ROM_3D is
generic (
Lx : integer range 1 to integer'high := 8;
Ly : integer range 1 to integer'high := 8;
Lz : integer range 1 to integer'high := 8;
W : integer range 1 to integer'high := 8
);
port (
iCLK : in std_logic;
iRE : in std_logic;
iRAx : in integer range 0 to Lx-1;
iRAy : in integer range 0 to Ly-1;
iRAz : in integer range 0 to Lz-1;
oRE : out std_logic;
oRD : out std_logic_vector(W-1 downto 0)
);
end component ROM_3D;
constant cROM_3D_LATENCY : integer := 1;
pure function fROM_3D_D (
iLx : integer range 1 to integer'high;
iLy : integer range 1 to integer'high;
iLz : integer range 1 to integer'high;
iW : integer range 1 to integer'high;
iRAx : integer range 0 to integer'high;
iRAy : integer range 0 to integer'high;
iRAz : integer range 0 to integer'high
) return std_logic_vector;
end package ROM_3D_PKG;
package body ROM_3D_PKG is
pure function fROM_3D_D (
iLx : integer range 1 to integer'high;
iLy : integer range 1 to integer'high;
iLz : integer range 1 to integer'high;
iW : integer range 1 to integer'high;
iRAx : integer range 0 to integer'high;
iRAy : integer range 0 to integer'high;
iRAz : integer range 0 to integer'high
) return std_logic_vector is
variable vD : std_logic_vector(iW-1 downto 0);
begin
vD := std_logic_vector(to_unsigned(integer(round(
real(2**iW-1) * real(iRAx + iRAy + iRAz) / real(iLx + iLy + iLz)
)), iW));
return vD;
end function fROM_3D_D;
end package body ROM_3D_PKG;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.math_real.all;
use work.ROM_3D_PKG.all;
entity ROM_3D is
generic (
Lx : integer range 1 to integer'high := 8;
Ly : integer range 1 to integer'high := 8;
Lz : integer range 1 to integer'high := 8;
W : integer range 1 to integer'high := 8
);
port (
iCLK : in std_logic;
iRE : in std_logic;
iRAx : in integer range 0 to Lx-1;
iRAy : in integer range 0 to Ly-1;
iRAz : in integer range 0 to Lz-1;
oRE : out std_logic;
oRD : out std_logic_vector(W-1 downto 0)
);
begin
end entity ROM_3D;
-- NOTE: Some synthesizer/simulator will fail b/c element subtype
-- indication of tDyz and tDxyz are custom type.
architecture USE_NESTED_ARRAY of ROM_3D is
type tDz is array (0 to Lz-1) of std_logic_vector(W-1 downto 0);
type tDyz is array (0 to Ly-1) of tDz;
type tDxyz is array (0 to Lx-1) of tDyz;
pure function fDxyz (
iDUMMY : boolean
) return tDxyz is
variable vDxyz : tDxyz;
begin
F_Ax : for vAx in 0 to Lx-1 loop
F_Ay : for vAy in 0 to Ly-1 loop
F_Az : for vAz in 0 to Lz-1 loop
vDxyz(vAx)(vAy)(vAz) := fROM_3D_D(Lx, Ly, Lz, W, vAx, vAy, vAz);
end loop F_Az;
end loop F_Ay;
end loop F_Ax;
return vDxyz;
end function fDxyz;
constant cDxyz : tDxyz := fDxyz(true);
signal rRE : std_logic := '0';
signal rRD : std_logic_vector(W-1 downto 0) := cDxyz(0)(0)(0);
begin
P_READ : process (iCLK)
begin
if (rising_edge(iCLK)) then
if (iRE = '1') then
rRE <= '1';
rRD <= cDxyz(iRAx)(iRAy)(iRAz);
else
rRE <= '0';
rRD <= rRD;
end if;
end if;
end process P_READ;
oRE <= rRE;
oRD <= rRD;
end architecture USE_NESTED_ARRAY;
-- NOTE: Some synthesizer/simulator will fail b/c vector indexing
-- is not supported.
architecture USE_VECTOR_ARRAY of ROM_3D is
type tDxyz is array (0 to Lx-1, 0 to Ly-1, 0 to Lz-1) of std_logic_vector(W-1 downto 0);
pure function fDxyz (
iDUMMY : boolean
) return tDxyz is
variable vDxyz : tDxyz;
begin
F_Ax : for vAx in 0 to Lx-1 loop
F_Ay : for vAy in 0 to Ly-1 loop
F_Az : for vAz in 0 to Lz-1 loop
vDxyz(vAx, vAy, vAz) := fROM_3D_D(Lx, Ly, Lz, W, vAx, vAy, vAz);
end loop F_Az;
end loop F_Ay;
end loop F_Ax;
return vDxyz;
end function fDxyz;
constant cDxyz : tDxyz := fDxyz(true);
signal rRE : std_logic := '0';
signal rRD : std_logic_vector(W-1 downto 0) := cDxyz(0, 0, 0);
begin
P_READ : process (iCLK)
begin
if (rising_edge(iCLK)) then
if (iRE = '1') then
rRE <= '1';
rRD <= cDxyz(iRAx, iRAy, iRAz);
else
rRE <= '0';
rRD <= rRD;
end if;
end if;
end process P_READ;
oRE <= rRE;
oRD <= rRD;
end architecture USE_VECTOR_ARRAY;
-- NOTE: When Lx, Ly and Lz is not power of 2, this indexing costs a
-- lot on real hardware b/c multipliers are.
architecture USE_1D_ARRAY of ROM_3D is
type tDxyz is array (0 to Lx*Ly*Lz-1) of std_logic_vector(W-1 downto 0);
pure function fDxyz (
iDUMMY : boolean
) return tDxyz is
variable vDxyz : tDxyz;
begin
F_Ax : for vAx in 0 to Lx-1 loop
F_Ay : for vAy in 0 to Ly-1 loop
F_Az : for vAz in 0 to Lz-1 loop
vDxyz(vAx*Ly*Lz + vAy*Lz + vAz) := fROM_3D_D(Lx, Ly, Lz, W, vAx, vAy, vAz);
end loop F_Az;
end loop F_Ay;
end loop F_Ax;
return vDxyz;
end function fDxyz;
constant cDxyz : tDxyz := fDxyz(true);
signal rRE : std_logic := '0';
signal rRD : std_logic_vector(W-1 downto 0) := cDxyz(0*Ly*Lz + 0*Lz + 0);
begin
P_READ : process (iCLK)
begin
if (rising_edge(iCLK)) then
if (iRE = '1') then
rRE <= '1';
rRD <= cDxyz(iRAx*Ly*Lz + iRAy*Lz + iRAz);
else
rRE <= '0';
rRD <= rRD;
end if;
end if;
end process P_READ;
oRE <= rRE;
oRD <= rRD;
end architecture USE_1D_ARRAY;
-- NOTE: When Lx, Ly and Lz is not power of 2 and big L* are specified,
-- cDxyz becomes huge and is sparsed.
architecture USE_1DwLOG2_ARRAY of ROM_3D is
constant clog2Lx : integer range 0 to integer'high := integer(ceil(log2(real(Lx))));
constant clog2Ly : integer range 0 to integer'high := integer(ceil(log2(real(Ly))));
constant clog2Lz : integer range 0 to integer'high := integer(ceil(log2(real(Lz))));
constant clog2L : integer range 0 to integer'high := clog2Lx + clog2Ly + clog2Lz;
constant cLx : integer range 1 to integer'high := 2**clog2Lx;
constant cLy : integer range 1 to integer'high := 2**clog2Ly;
constant cLz : integer range 1 to integer'high := 2**clog2Lz;
constant cL : integer range 1 to integer'high := 2**clog2L;
type tDxyz is array (0 to cL-1) of std_logic_vector(W-1 downto 0);
pure function fA (
iAx : integer range 0 to cLx-1;
iAy : integer range 0 to cLy-1;
iAz : integer range 0 to cLz-1
) return integer is
variable vA : std_logic_vector(clog2L-1 downto 0);
begin
vA :=
std_logic_vector(to_unsigned(iAx, clog2Lx)) &
std_logic_vector(to_unsigned(iAy, clog2Ly)) &
std_logic_vector(to_unsigned(iAz, clog2Lz));
return to_integer(unsigned(vA));
end function fA;
pure function fDxyz (
iDUMMY : boolean
) return tDxyz is
variable vA : integer range 0 to cL-1;
variable vDxyz : tDxyz;
begin
F_Ax : for vAx in 0 to cLx-1 loop
F_Ay : for vAy in 0 to cLy-1 loop
F_Az : for vAz in 0 to cLz-1 loop
if (vAx > Lx-1 or
vAy > Ly-1 or
vAz > Lz-1) then
vDxyz(fA(vAx, vAy, vAz)) := (W-1 downto 0 => '0');
else
vDxyz(fA(vAx, vAy, vAz)) := fROM_3D_D(Lx, Ly, Lz, W, vAx, vAy, vAz);
end if;
end loop F_Az;
end loop F_Ay;
end loop F_Ax;
return vDxyz;
end function fDxyz;
constant cDxyz : tDxyz := fDxyz(true);
signal rRE : std_logic := '0';
signal rRD : std_logic_vector(W-1 downto 0) := cDxyz(fA(0 , 0, 0));
begin
P_READ : process (iCLK)
begin
if (rising_edge(iCLK)) then
if (iRE = '1') then
rRE <= '1';
rRD <= cDxyz(fA(iRAx, iRAy, iRAz));
else
rRE <= '0';
rRD <= rRD;
end if;
end if;
end process P_READ;
oRE <= rRE;
oRD <= rRD;
end architecture USE_1DwLOG2_ARRAY;
library ieee;
use ieee.std_logic_1164.all;
use work.ROM_3D_PKG.all;
entity array4 is
begin
end entity array4;
architecture test of array4 is
constant cCLK_PERIOD : time := 1.0 ns;
signal sCLK : std_logic := '0';
constant cLx : integer range 1 to integer'high := 2;
constant cLy : integer range 1 to integer'high := 3;
constant cLz : integer range 1 to integer'high := 4;
constant cW : integer range 1 to integer'high := 8;
type tIF is record
ROM_3D_USE_NESTED_ARRAY_oRE : std_logic;
ROM_3D_USE_NESTED_ARRAY_oRD : std_logic_vector(cW-1 downto 0);
ROM_3D_USE_VECTOR_ARRAY_oRE : std_logic;
ROM_3D_USE_VECTOR_ARRAY_oRD : std_logic_vector(cW-1 downto 0);
ROM_3D_USE_1D_ARRAY_oRE : std_logic;
ROM_3D_USE_1D_ARRAY_oRD : std_logic_vector(cW-1 downto 0);
ROM_3D_USE_1DwLOG2_ARRAY_oRE : std_logic;
ROM_3D_USE_1dwLOG2_ARRAY_oRD : std_logic_vector(cW-1 downto 0);
end record tIF;
signal s : tIF;
type tST is (INIT, RUN, DONE);
type t is record
ST : tST;
RE : std_logic;
RAx : integer range 0 to cLx-1;
RAy : integer range 0 to cLy-1;
RAz : integer range 0 to cLz-1;
end record t;
constant c : t := (
ST => INIT,
RE => '0',
RAx => 0,
RAy => 0,
RAz => 0
);
signal g : t := c;
signal r : t := c;
begin
P_CLK : process
begin
W_CLK : while (r.ST /= DONE) loop
sCLK <= '0'; wait for cCLK_PERIOD/2.0;
sCLK <= '1'; wait for cCLK_PERIOD/2.0;
end loop W_CLK;
wait;
end process P_CLK;
P_STIM : process
begin
r.ST <= INIT;
wait until (rising_edge(sCLK));
r.ST <= RUN;
F_RAx : for vRAx in 0 to cLx-1 loop
r.RAx <= vRAx;
F_RAy : for vRAy in 0 to cLy-1 loop
r.RAy <= vRAy;
F_RAz : for vRAz in 0 to cLz-1 loop
r.RAz <= vRAz;
r.RE <= '1';
wait until (rising_edge(sCLK));
r.RE <= '0';
wait until (rising_edge(sCLK));
end loop F_RAz;
end loop F_RAy;
end loop F_RAx;
wait for cROM_3D_LATENCY * cCLK_PERIOD;
r.ST <= DONE;
wait;
end process P_STIM;
g <= transport r after cROM_3D_LATENCY * cCLK_PERIOD;
A_COLL : assert (not
(r.ST = RUN and
((s.ROM_3D_USE_NESTED_ARRAY_oRE = '1' and
s.ROM_3D_USE_NESTED_ARRAY_oRD /= fROM_3D_D(cLx, cLy, cLz, cW, g.RAx, g.RAy, g.RAz)) or
(s.ROM_3D_USE_VECTOR_ARRAY_oRE = '1' and
s.ROM_3D_USE_VECTOR_ARRAY_oRD /= fROM_3D_D(cLx, cLy, cLz, cW, g.RAx, g.RAy, g.RAz)) or
(s.ROM_3D_USE_1D_ARRAY_oRE = '1' and
s.ROM_3D_USE_1D_ARRAY_oRD /= fROM_3D_D(cLx, cLy, cLz, cW, g.RAx, g.RAy, g.RAz)) or
(s.ROM_3D_USE_1DwLOG2_ARRAY_oRE = '1' and
s.ROM_3D_USE_1DwLOG2_ARRAY_oRD /= fROM_3D_D(cLx, cLy, cLz, cW, g.RAx, g.RAy, g.RAz))))
)
report "unexpected RD inequality"
severity failure;
U_ROM_3D_USE_NESTED_ARRAY : ROM_3D
generic map (
Lx => cLx,
Ly => cLy,
Lz => cLz,
W => cW
)
port map (
iCLK => sCLK,
iRE => r.RE,
iRAx => r.RAx,
iRAy => r.RAy,
iRAz => r.RAz,
oRE => s.ROM_3D_USE_NESTED_ARRAY_oRE,
oRD => s.ROM_3D_USE_NESTED_ARRAY_oRD
);
U_ROM_3D_USE_VECTOR_ARRAY : ROM_3D
generic map (
Lx => cLx,
Ly => cLy,
Lz => cLz,
W => cW
)
port map (
iCLK => sCLK,
iRE => r.RE,
iRAx => r.RAx,
iRAy => r.RAy,
iRAz => r.RAz,
oRE => s.ROM_3D_USE_VECTOR_ARRAY_oRE,
oRD => s.ROM_3D_USE_VECTOR_ARRAY_oRD
);
U_ROM_3D_USE_1D_ARRAY : ROM_3D
generic map (
Lx => cLx,
Ly => cLy,
Lz => cLz,
W => cW
)
port map (
iCLK => sCLK,
iRE => r.RE,
iRAx => r.RAx,
iRAy => r.RAy,
iRAz => r.RAz,
oRE => s.ROM_3D_USE_1D_ARRAY_oRE,
oRD => s.ROM_3D_USE_1D_ARRAY_oRD
);
U_ROM_3D_USE_1DwLOG2_ARRAY : ROM_3D
generic map (
Lx => cLx,
Ly => cLy,
Lz => cLz,
W => cW
)
port map (
iCLK => sCLK,
iRE => r.RE,
iRAx => r.RAx,
iRAy => r.RAy,
iRAz => r.RAz,
oRE => s.ROM_3D_USE_1DwLOG2_ARRAY_oRE,
oRD => s.ROM_3D_USE_1DwLOG2_ARRAY_oRD
);
end architecture test;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment