Last active
August 29, 2015 13:55
-
-
Save hiyuh/8782789 to your computer and use it in GitHub Desktop.
simple 3 dimension ROM by using array.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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