URL
https://opencores.org/ocsvn/mod_sim_exp/mod_sim_exp/trunk
Subversion Repositories mod_sim_exp
Compare Revisions
- This comparison shows the changes necessary to convert path
/mod_sim_exp
- from Rev 62 to Rev 61
- ↔ Reverse comparison
Rev 62 → Rev 61
/trunk/rtl/vhdl/ram/dpram_altera.vhd
0,0 → 1,84
-- Quartus II VHDL Template |
-- |
-- Simple Dual-Port RAM with separate read and write addresses and data widths |
-- that are controlled by the parameters RW and WW. RW and WW must specify a |
-- read/write ratio that's supported by the memory blocks in your target |
-- device. Otherwise, no RAM will be inferred. |
|
library ieee; |
use ieee.std_logic_1164.all; |
library altera; |
use altera.altera_standard_functions.all; |
|
entity dpram_altera is |
|
generic ( |
WORDS : natural := 2; |
RW : natural := 1024; |
WW : natural := 32); |
|
port ( |
we : in std_logic; |
clk : in std_logic; |
waddr : in natural range 0 to (WORDS * maximum(RW, WW)) / WW - 1; |
wdata : in std_logic_vector(WW - 1 downto 0); |
raddr : in natural range 0 to (WORDS * maximum(RW, WW)) / RW - 1; |
q : out std_logic_vector(RW - 1 downto 0)); |
|
end dpram_altera; |
|
architecture rtl of dpram_altera is |
|
constant B : natural := minimum(RW, WW); |
constant R : natural := maximum(RW, WW)/B; |
|
-- Use a multidimensional array to model mixed-width |
type word_t is array(R - 1 downto 0) of std_logic_vector(B - 1 downto 0); |
type ram_t is array (0 to WORDS - 1) of word_t; |
|
signal ram : ram_t; |
|
begin -- rtl |
|
-- Must handle read < write and write > read separately |
smaller_read: if RW < WW generate |
signal wdata_local : word_t; |
begin |
|
-- Re-organize the write data to match the RAM word type |
unpack: for i in 0 to R - 1 generate |
wdata_local(i) <= wdata(B*(i+1) - 1 downto B*i); |
end generate unpack; |
|
process(clk, we) |
begin |
if(rising_edge(clk)) then |
if(we = '1') then |
ram(waddr) <= wdata_local; |
end if; |
q <= ram(raddr / R )(raddr mod R); |
end if; |
end process; |
end generate smaller_read; |
|
not_smaller_read: if RW >= WW generate |
signal q_local : word_t; |
begin |
|
-- Re-organize the read data from the RAM to match the output |
unpack: for i in 0 to R - 1 generate |
q(B*(i+1) - 1 downto B*i) <= q_local(i); |
end generate unpack; |
|
process(clk, we) |
begin |
if(rising_edge(clk)) then |
if(we = '1') then |
ram(waddr / R)(waddr mod R) <= wdata; |
end if; |
q_local <= ram(raddr); |
end if; |
end process; |
end generate not_smaller_read; |
|
end rtl; |
/trunk/rtl/vhdl/ram/dpram_xilinx.vhd
0,0 → 1,123
-------------------------------------------------------------------------------- |
-- Entity: ram_xilinx |
-- Date:2013-02-19 |
-- Author: Dinghe |
-- |
-- Description ${cursor} |
-------------------------------------------------------------------------------- |
-- |
-- correctly implemented as Block RAM, no other resources needed. |
-- |
|
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
use ieee.std_logic_arith.all; |
|
entity dpram_xilinx is |
|
generic ( |
WIDTHA : integer := 32; |
SIZEA : integer := 48; |
ADDRWIDTHA : integer := 6; |
WIDTHB : integer := 1536; |
SIZEB : integer := 1; |
ADDRWIDTHB : integer := 1 |
); |
|
port ( |
clkA : in std_logic; |
clkB : in std_logic; |
enB : in std_logic; |
weA : in std_logic; |
addrA : in std_logic_vector(ADDRWIDTHA-1 downto 0); |
addrB : in std_logic_vector(ADDRWIDTHB-1 downto 0); |
diA : in std_logic_vector(WIDTHA-1 downto 0); |
doB : out std_logic_vector(WIDTHB-1 downto 0) |
); |
|
end dpram_xilinx; |
|
architecture behavioral of dpram_xilinx is |
|
function max(L, R: INTEGER) return INTEGER is |
begin |
if L > R then |
return L; |
else |
return R; |
end if; |
end; |
|
function min(L, R: INTEGER) return INTEGER is |
begin |
if L < R then |
return L; |
else |
return R; |
end if; |
end; |
|
function log2 (val: INTEGER) return natural is |
variable res : natural; |
begin |
for i in 0 to 31 loop |
if (val <= (2**i)) then |
res := i; |
exit; |
end if; |
end loop; |
return res; |
end function Log2; |
|
constant minWIDTH : integer := min(WIDTHA,WIDTHB); |
constant maxWIDTH : integer := max(WIDTHA,WIDTHB); |
constant maxSIZE : integer := max(SIZEA,SIZEB); |
constant RATIO : integer := maxWIDTH / minWIDTH; |
|
-- An asymmetric RAM is modelled in a similar way as a symmetric RAM, with an |
-- array of array object. Its aspect ratio corresponds to the port with the |
-- lower data width (larger depth) |
type ramType is array (0 to maxSIZE-1) of std_logic_vector(minWIDTH-1 downto 0); |
|
-- You need to declare ram as a shared variable when : |
-- - the RAM has two write ports, |
-- - the RAM has only one write port whose data width is maxWIDTH |
-- In all other cases, ram can be a signal. |
signal ram : ramType := (others => (others => '0')); |
|
attribute ram_style : string; |
attribute ram_style of ram:signal is "block"; |
|
signal readB : std_logic_vector(WIDTHB-1 downto 0):= (others => '0'); |
signal addrB_i : std_logic_vector(ADDRWIDTHB-1 downto 0):= (others => '0'); |
|
begin |
|
-- port A: only write |
process (clkA) |
begin |
if rising_edge(clkA) then |
if weA = '1' then |
ram(conv_integer(addrA)) <= diA; |
end if; |
end if; |
end process; |
|
-- port B: only read |
process (clkB) |
begin |
if rising_edge(clkB) then |
if enB = '1' then |
addrB_i <= addrB; |
end if; |
doB <= readB; |
end if; |
end process; |
|
ramoutput : for i in 0 to RATIO-1 generate |
readB((i+1)*minWIDTH-1 downto i*minWIDTH) |
<= ram(conv_integer(addrB_i & conv_std_logic_vector(i,log2(RATIO)))); |
end generate; |
|
end behavioral; |
/trunk/rtl/vhdl/ram/tdpram_xilinx.vhd
0,0 → 1,151
-------------------------------------------------------------------------------- |
-- Entity: ram_xilinx |
-- Date:2013-02-19 |
-- Author: Dinghe |
-- |
-- Description ${cursor} |
-------------------------------------------------------------------------------- |
-- |
-- WIDTHA = 32 |
-- SIZEA = 32 --> 2 registers needed |
-- ADDRWIDTHA = 5 |
-- WIDTHB = 512 --> 2 registers needed |
-- SIZEB = 2 |
-- ADDRWIDTHB = 1 |
-- Found 32x32:2x512-bit dual-port RAM <Mram_ram> for signal <ram>. |
-- Found 32-bit register for signal <doA>. |
-- Found 512-bit register for signal <readB>. |
-- Found 512-bit register for signal <doB>. |
-- Found 32-bit register for signal <readA>. |
-- Summary: |
-- inferred 1 RAM(s). |
-- inferred 1088 D-type flip-flop(s). |
-- inferred 17 Multiplexer(s). |
-- |
-- |
library ieee; |
use ieee.std_logic_1164.all; |
use ieee.std_logic_unsigned.all; |
use ieee.std_logic_arith.all; |
|
entity tdpram_xilinx is |
|
generic ( |
WIDTHA : integer := 32; |
SIZEA : integer := 32; |
ADDRWIDTHA : integer := 5; |
WIDTHB : integer := 512; |
SIZEB : integer := 2; |
ADDRWIDTHB : integer := 1 |
); |
|
port ( |
clkA : in std_logic; |
clkB : in std_logic; |
enA : in std_logic; |
enB : in std_logic; |
weA : in std_logic; |
weB : in std_logic; |
addrA : in std_logic_vector(ADDRWIDTHA-1 downto 0); |
addrB : in std_logic_vector(ADDRWIDTHB-1 downto 0); |
diA : in std_logic_vector(WIDTHA-1 downto 0); |
diB : in std_logic_vector(WIDTHB-1 downto 0); |
doA : out std_logic_vector(WIDTHA-1 downto 0); |
doB : out std_logic_vector(WIDTHB-1 downto 0) |
); |
|
end tdpram_xilinx; |
|
architecture behavioral of tdpram_xilinx is |
|
function max(L, R: INTEGER) return INTEGER is |
begin |
if L > R then |
return L; |
else |
return R; |
end if; |
end; |
|
function min(L, R: INTEGER) return INTEGER is |
begin |
if L < R then |
return L; |
else |
return R; |
end if; |
end; |
|
function log2 (val: INTEGER) return natural is |
variable res : natural; |
begin |
for i in 0 to 31 loop |
if (val <= (2**i)) then |
res := i; |
exit; |
end if; |
end loop; |
return res; |
end function Log2; |
|
constant minWIDTH : integer := min(WIDTHA,WIDTHB); |
constant maxWIDTH : integer := max(WIDTHA,WIDTHB); |
constant maxSIZE : integer := max(SIZEA,SIZEB); |
constant RATIO : integer := maxWIDTH / minWIDTH; |
|
-- An asymmetric RAM is modelled in a similar way as a symmetric RAM, with an |
-- array of array object. Its aspect ratio corresponds to the port with the |
-- lower data width (larger depth) |
type ramType is array (0 to maxSIZE-1) of std_logic_vector(minWIDTH-1 downto 0); |
|
-- You need to declare ram as a shared variable when : |
-- - the RAM has two write ports, |
-- - the RAM has only one write port whose data width is maxWIDTH |
-- In all other cases, ram can be a signal. |
shared variable ram : ramType := (others => (others => '0')); |
|
signal readA : std_logic_vector(WIDTHA-1 downto 0):= (others => '0'); |
signal readB : std_logic_vector(WIDTHB-1 downto 0):= (others => '0'); |
signal regA : std_logic_vector(WIDTHA-1 downto 0):= (others => '0'); |
signal regB : std_logic_vector(WIDTHB-1 downto 0):= (others => '0'); |
|
begin |
|
process (clkA) |
begin |
if rising_edge(clkA) then |
if enA = '1' then |
if weA = '1' then |
ram(conv_integer(addrA)) := diA; |
readA <= diA; |
else |
readA <= ram(conv_integer(addrA)); |
end if; |
end if; |
regA <= readA; |
end if; |
end process; |
|
process (clkB) |
begin |
if rising_edge(clkB) then |
if enB = '1' then |
for i in 0 to RATIO-1 loop |
if weB = '1' then |
ram(conv_integer(addrB & conv_std_logic_vector(i,log2(RATIO)))) |
:= diB((i+1)*minWIDTH-1 downto i*minWIDTH); |
end if; |
-- The read statement below is placed after the write statement on purpose |
-- to ensure write-first synchronization through the variable mechanism |
readB((i+1)*minWIDTH-1 downto i*minWIDTH) |
<= ram(conv_integer(addrB & conv_std_logic_vector(i,log2(RATIO)))); |
end loop; |
end if; |
regB <= readB; |
end if; |
end process; |
|
doA <= regA; |
doB <= regB; |
|
end behavioral; |