SURF  1.0
SimpleDualPortRam.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 -- File : SimpleDualPortRam.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 either Block RAM or distributed RAM
8 -------------------------------------------------------------------------------
9 -- This file is part of 'SLAC Firmware Standard Library'.
10 -- It is subject to the license terms in the LICENSE.txt file found in the
11 -- top-level directory of this distribution and at:
12 -- https://confluence.slac.stanford.edu/display/ppareg/LICENSE.html.
13 -- No part of 'SLAC Firmware Standard Library', including this file,
14 -- may be copied, modified, propagated, or distributed except according to
15 -- the terms contained in the LICENSE.txt file.
16 -------------------------------------------------------------------------------
17 
18 library ieee;
19 use ieee.std_logic_1164.all;
20 use ieee.std_logic_arith.all;
21 use ieee.std_logic_unsigned.all;
22 
23 use work.StdRtlPkg.all;
24 
25 --! @see entity
26  --! @ingroup base_ram
28  generic (
29  TPD_G : time := 1 ns;
30  RST_POLARITY_G : sl := '1'; -- '1' for active high rst, '0' for active low
31  BRAM_EN_G : boolean := true;
32  DOB_REG_G : boolean := false; -- Extra reg on doutb (folded into BRAM)
33  ALTERA_SYN_G : boolean := false;
34  ALTERA_RAM_G : string := "M9K";
35  BYTE_WR_EN_G : boolean := false;
36  DATA_WIDTH_G : integer range 1 to (2**24) := 16;
37  BYTE_WIDTH_G : integer := 8; -- If BRAM, should be multiple or 8 or 9
38  ADDR_WIDTH_G : integer range 1 to (2**24) := 4;
39  INIT_G : slv := "0");
40  port (
41  -- Port A
42  clka : in sl := '0';
43  ena : in sl := '1';
44  wea : in sl := '0';
45  weaByte : in slv(wordCount(DATA_WIDTH_G, BYTE_WIDTH_G)-1 downto 0) := (others => '0');
46  addra : in slv(ADDR_WIDTH_G-1 downto 0) := (others => '0');
47  dina : in slv(DATA_WIDTH_G-1 downto 0) := (others => '0');
48  -- Port B
49  clkb : in sl := '0';
50  enb : in sl := '1';
51  rstb : in sl := not(RST_POLARITY_G);
52  addrb : in slv(ADDR_WIDTH_G-1 downto 0) := (others => '0');
53  doutb : out slv(DATA_WIDTH_G-1 downto 0));
54 end SimpleDualPortRam;
55 
56 architecture rtl of SimpleDualPortRam is
57 
58  -- Set byte width to word width if byte writes not enabled
59  -- Otherwise block ram parity bits wont be utilized
60  constant BYTE_WIDTH_C : natural := ite(BYTE_WR_EN_G, BYTE_WIDTH_G, DATA_WIDTH_G);
61  constant NUM_BYTES_C : natural := wordCount(DATA_WIDTH_G, BYTE_WIDTH_C);
62  constant FULL_DATA_WIDTH_C : natural := NUM_BYTES_C*BYTE_WIDTH_C;
63 
64  constant INIT_C : slv(FULL_DATA_WIDTH_C-1 downto 0) := ite(INIT_G = "0", slvZero(FULL_DATA_WIDTH_C), INIT_G);
65 
66  constant XST_BRAM_STYLE_C : string := ite(BRAM_EN_G, "block", "distributed");
67  constant ALTERA_BRAM_STYLE_C : string := ite(BRAM_EN_G, ALTERA_RAM_G, "MLAB");
68 
69  -- Shared memory
70  type mem_type is array ((2**ADDR_WIDTH_G)-1 downto 0) of slv(FULL_DATA_WIDTH_C-1 downto 0);
71  shared variable mem : mem_type := (others => INIT_C);
72 
73  signal doutBInt : slv(FULL_DATA_WIDTH_C-1 downto 0);
74 
75  signal weaByteInt : slv(weaByte'range);
76 
77  -- Attribute for XST (Xilinx Synthesis)
78  attribute ram_style : string;
79  attribute ram_style of mem : variable is XST_BRAM_STYLE_C;
80 
81  attribute ram_extract : string;
82  attribute ram_extract of mem : variable is "TRUE";
83 
84  -- Attribute for Synplicity Synthesizer
85  attribute syn_ramstyle : string;
86  attribute syn_ramstyle of mem : variable is XST_BRAM_STYLE_C;
87 
88  attribute syn_keep : string;
89  attribute syn_keep of mem : variable is "TRUE";
90 
91  -- Attribute for Altera Synthesizer
92  attribute ramstyle : string;
93  attribute ramstyle of mem : variable is ALTERA_BRAM_STYLE_C;
94 
95 begin
96 
97  -- ALTERA_RAM_G check
98  assert ((ALTERA_RAM_G = "M512")
99  or (ALTERA_RAM_G = "M4K")
100  or (ALTERA_RAM_G = "M9K")
101  or (ALTERA_RAM_G = "M10K")
102  or (ALTERA_RAM_G = "M20K")
103  or (ALTERA_RAM_G = "M144K")
104  or (ALTERA_RAM_G = "M-RAM"))
105  report "Invalid ALTERA_RAM_G string"
106  severity failure;
107 
108  weaByteInt <= weaByte when BYTE_WR_EN_G else (others => wea);
109 
110  -- Port A
111  process(clka)
112  begin
113  if rising_edge(clka) then
114  if ena = '1' then
115  for i in NUM_BYTES_C-1 downto 0 loop
116  if (weaByteInt(i) = '1') then
117  mem(conv_integer(addra))((i+1)*BYTE_WIDTH_C-1 downto i*BYTE_WIDTH_C) :=
118  resize(dina(minimum(DATA_WIDTH_G-1, (i+1)*BYTE_WIDTH_C-1) downto i*BYTE_WIDTH_C), BYTE_WIDTH_C);
119  end if;
120  end loop;
121  end if;
122  end if;
123  end process;
124 
125 
126  XILINX_BUILD : if (ALTERA_SYN_G = false) generate
127  -- Port B
128  process(clkb)
129  begin
130  if rising_edge(clkb) then
131  if rstb = RST_POLARITY_G then
132  doutbInt <= INIT_C after TPD_G;
133  elsif enb = '1' then
134  doutBInt <= mem(conv_integer(addrb)) after TPD_G;
135  end if;
136  end if;
137  end process;
138 
139  NO_REG : if (not DOB_REG_G) generate
140  doutb <= doutBInt(DATA_WIDTH_G-1 downto 0);
141  end generate NO_REG;
142 
143  REG : if (DOB_REG_G) generate
144  process (clkb)
145  begin
146  if (rising_edge(clkb)) then
147  doutb <= doutBInt(DATA_WIDTH_G-1 downto 0) after TPD_G;
148  end if;
149  end process;
150  end generate REG;
151  end generate;
152 
153  ---------------------------------------------------------------
154  --NOTE: rstb and enb not supported in Altera when inferring RAM
155  ---------------------------------------------------------------
156  ALTERA_BUILD : if (ALTERA_SYN_G = true) generate
157  -- Port B
158  process(clkb)
159  begin
160  if rising_edge(clkb) then
161  doutb <= mem(conv_integer(addrb))(DATA_WIDTH_G-1 downto 0) after TPD_G;
162  end if;
163  end process;
164  end generate;
165 
166 end rtl;
in addrbslv( ADDR_WIDTH_G- 1 downto 0) :=( others => '0')
BRAM_EN_Gboolean := true
in rstbsl :=not ( RST_POLARITY_G)
ALTERA_RAM_Gstring := "M9K"
out doutbslv( DATA_WIDTH_G- 1 downto 0)
DATA_WIDTH_Ginteger range 1 to ( 2** 24):= 16
std_logic sl
Definition: StdRtlPkg.vhd:28
_library_ ieeeieee
Definition: QuadPortRam.vhd:18
ADDR_WIDTH_Ginteger range 1 to ( 2** 24):= 4
BYTE_WR_EN_Gboolean := false
in addraslv( ADDR_WIDTH_G- 1 downto 0) :=( others => '0')
BYTE_WIDTH_Ginteger := 8
ALTERA_SYN_Gboolean := false
in weaByteslv( wordCount( DATA_WIDTH_G, BYTE_WIDTH_G)- 1 downto 0) :=( others => '0')
DOB_REG_Gboolean := false
std_logic_vector slv
Definition: StdRtlPkg.vhd:29
in dinaslv( DATA_WIDTH_G- 1 downto 0) :=( others => '0')