1 ------------------------------------------------------------------------------- 2 -- File : TrueDualPortRam.vhd 3 -- Company : SLAC National Accelerator Laboratory 4 -- Created : 2013-07-11 5 -- Last update: 2016-05-09 6 ------------------------------------------------------------------------------- 7 -- Description: This will infer this module as Block RAM only 9 -- NOTE: TDP ram with read enable logic is not supported. 10 ------------------------------------------------------------------------------- 11 -- This file is part of 'SLAC Firmware Standard Library'. 12 -- It is subject to the license terms in the LICENSE.txt file found in the 13 -- top-level directory of this distribution and at: 14 -- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html. 15 -- No part of 'SLAC Firmware Standard Library', including this file, 16 -- may be copied, modified, propagated, or distributed except according to 17 -- the terms contained in the LICENSE.txt file. 18 ------------------------------------------------------------------------------- 21 use ieee.std_logic_1164.
all;
22 use ieee.std_logic_unsigned.
all;
29 -- MODE_G = {"no-change","read-first","write-first"} 34 DOA_REG_G : := false;
-- Extra output register on doutA. 35 DOB_REG_G : := false;
-- Extra output register on doutB. 52 regcea :
in sl := '1'; -- Clock enable
for extra output reg. Only used
when DOA_REG_G = true
62 regceb :
in sl := '1'); -- Clock enable
for extra output reg. Only used
when DOA_REG_G = true
67 -- Set byte width to word width if byte writes not enabled 68 -- Otherwise block ram parity bits wont be utilized 70 constant NUM_BYTES_C : := wordCount(DATA_WIDTH_G, BYTE_WIDTH_C);
71 constant FULL_DATA_WIDTH_C : := NUM_BYTES_C*BYTE_WIDTH_C;
73 constant INIT_C : slv(FULL_DATA_WIDTH_C-1 downto 0) := ite(INIT_G = "0", slvZero(FULL_DATA_WIDTH_C), INIT_G);
76 type mem_type is array ((2**ADDR_WIDTH_G)-1 downto 0) of slv(FULL_DATA_WIDTH_C-1 downto 0);
77 shared variable mem : mem_type := (others => INIT_C);
79 signal doutAInt : slv(FULL_DATA_WIDTH_C-1 downto 0);
80 signal doutBInt : slv(FULL_DATA_WIDTH_C-1 downto 0);
85 -- Attribute for XST (Xilinx Synthesizer) 86 attribute ram_style : ;
87 attribute ram_style of mem : variable is "block";
89 attribute ram_extract : ;
90 attribute ram_extract of mem : variable is "TRUE";
92 attribute keep : ;
--"keep" is same for XST and Altera 93 attribute keep of mem : variable is true;
--"keep" is same for XST and Altera 95 -- Attribute for Synplicity Synthesizer 96 attribute syn_ramstyle : ;
97 attribute syn_ramstyle of mem : variable is "block";
99 attribute syn_keep : ;
100 attribute syn_keep of mem : variable is "TRUE";
102 -- Attribute for Altera Synthesizer 103 attribute ramstyle : ;
110 report "MODE_G must be either no-change, read-first, or write-first" 112 -- ALTERA_RAM_G check 120 report "Invalid ALTERA_RAM_G string" 127 ------------------------------------------------------------------------------------------------- 129 ------------------------------------------------------------------------------------------------- 130 NO_CHANGE_MODE : if MODE_G = "no-change" generate 134 if rising_edge(clka) then 136 for i in 0 to NUM_BYTES_C-1 loop 137 if (weaByteInt(i) = '1') then 138 mem(conv_integer(addra))((i+1)*BYTE_WIDTH_C-1 downto i*BYTE_WIDTH_C) := 139 resize(dina(minimum(DATA_WIDTH_G-1, (i+1)*BYTE_WIDTH_C-1) downto i*BYTE_WIDTH_C), BYTE_WIDTH_C);
146 -- Vivado does crazy stupid things if output isn't broken out into its own process in 150 if (rising_edge(clka)) then 152 doutAInt <= mem(conv_integer(addra)) after TPD_G;
155 doutAInt <= INIT_C after TPD_G;
163 if rising_edge(clkb) then 165 for i in 0 to NUM_BYTES_C-1 loop 166 if (webByteInt(i) = '1') then 167 mem(conv_integer(addrb))((i+1)*BYTE_WIDTH_C-1 downto i*BYTE_WIDTH_C) := 168 resize(dinb(minimum(DATA_WIDTH_G-1, (i+1)*BYTE_WIDTH_C-1) downto i*BYTE_WIDTH_C), BYTE_WIDTH_C);
177 if (rising_edge(clkb)) then 179 doutBInt <= mem(conv_integer(addrb)) after TPD_G;
182 doutBInt <= INIT_C after TPD_G;
189 ------------------------------------------------------------------------------------------------- 191 ------------------------------------------------------------------------------------------------- 192 READ_FIRST_MODE : if MODE_G = "read-first" generate 196 if rising_edge(clka) then 198 doutAInt <= mem(conv_integer(addra)) after TPD_G;
199 for i in 0 to NUM_BYTES_C-1 loop 200 if (weaByteInt(i) = '1') then 201 mem(conv_integer(addra))((i+1)*BYTE_WIDTH_C-1 downto i*BYTE_WIDTH_C) := 202 resize(dina(minimum(DATA_WIDTH_G-1, (i+1)*BYTE_WIDTH_C-1) downto i*BYTE_WIDTH_C), BYTE_WIDTH_C);
207 doutAInt <= INIT_C after TPD_G;
215 if rising_edge(clkb) then 217 doutBInt <= mem(conv_integer(addrb)) after TPD_G;
218 for i in 0 to NUM_BYTES_C-1 loop 219 if (webByteInt(i) = '1') then 220 mem(conv_integer(addrb))((i+1)*BYTE_WIDTH_C-1 downto i*BYTE_WIDTH_C) := 221 resize(dinb(minimum(DATA_WIDTH_G-1, (i+1)*BYTE_WIDTH_C-1) downto i*BYTE_WIDTH_C), BYTE_WIDTH_C);
226 doutBInt <= INIT_C after TPD_G;
233 ------------------------------------------------------------------------------------------------- 235 ------------------------------------------------------------------------------------------------- 236 WRITE_FIRST_MODE : if MODE_G = "write-first" generate 240 if rising_edge(clka) then 242 for i in 0 to NUM_BYTES_C-1 loop 243 if (weaByteInt(i) = '1') then 244 mem(conv_integer(addra))((i+1)*BYTE_WIDTH_C-1 downto i*BYTE_WIDTH_C) := 245 resize(dina(minimum(DATA_WIDTH_G-1, (i+1)*BYTE_WIDTH_C-1) downto i*BYTE_WIDTH_C), BYTE_WIDTH_C);
248 doutAInt <= mem(conv_integer(addra)) after TPD_G;
251 doutAInt <= INIT_C after TPD_G;
260 if rising_edge(clkb) then 262 for i in 0 to NUM_BYTES_C-1 loop 263 if (webByteInt(i) = '1') then 264 mem(conv_integer(addrb))((i+1)*BYTE_WIDTH_C-1 downto i*BYTE_WIDTH_C) := 265 resize(dinb(minimum(DATA_WIDTH_G-1, (i+1)*BYTE_WIDTH_C-1) downto i*BYTE_WIDTH_C), BYTE_WIDTH_C);
268 doutBInt <= mem(conv_integer(addrb)) after TPD_G;
271 doutBInt <= INIT_C after TPD_G;
279 ------------------------------------------------------------------------------------------------- 280 -- Optional data output registers 281 ------------------------------------------------------------------------------------------------- 282 NO_DOUT_A_REG : if (not DOA_REG_G) generate 284 end generate NO_DOUT_A_REG;
289 if (rising_edge(clka)) then 297 end generate DOUT_A_REG;
299 NO_DOUT_B_REG : if (not DOB_REG_G) generate 301 end generate NO_DOUT_B_REG;
306 if (rising_edge(clkb)) then 314 end generate DOUT_B_REG;
in rstbsl :=not ( RST_POLARITY_G)
ADDR_WIDTH_Ginteger range 1 to ( 2** 24):= 9
in weaByteslv( wordCount( DATA_WIDTH_G, BYTE_WIDTH_G)- 1 downto 0) :=( others => '0')
DATA_WIDTH_Ginteger range 1 to ( 2** 24):= 18
BYTE_WR_EN_Gboolean := false
in webByteslv( wordCount( DATA_WIDTH_G, BYTE_WIDTH_G)- 1 downto 0) :=( others => '0')
out doutaslv( DATA_WIDTH_G- 1 downto 0)
DOB_REG_Gboolean := false
in addraslv( ADDR_WIDTH_G- 1 downto 0) :=( others => '0')
ALTERA_RAM_Gstring := "M9K"
DOA_REG_Gboolean := false
in rstasl :=not ( RST_POLARITY_G)
out doutbslv( DATA_WIDTH_G- 1 downto 0)
MODE_Gstring := "read-first"
in dinaslv( DATA_WIDTH_G- 1 downto 0) :=( others => '0')
in dinbslv( DATA_WIDTH_G- 1 downto 0) :=( others => '0')
in addrbslv( ADDR_WIDTH_G- 1 downto 0) :=( others => '0')