SURF  1.0
QuadPortRam.vhd
Go to the documentation of this file.
1 -------------------------------------------------------------------------------
2 -- File : QuadPortRam.vhd
3 -- Company : SLAC National Accelerator Laboratory
4 -- Created : 2013-12-18
5 -- Last update: 2016-04-19
6 -------------------------------------------------------------------------------
7 -- Description: This module infers a Quad Port RAM as 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
27 entity QuadPortRam is
28  generic (
29  TPD_G : time := 1 ns;
30  RST_POLARITY_G : sl := '1'; -- '1' for active high rst, '0' for active low
31  REG_EN_G : boolean := true;
32  MODE_G : string := "read-first";
33  BYTE_WR_EN_G : boolean := false;
34  DATA_WIDTH_G : integer range 1 to (2**24) := 16;
35  BYTE_WIDTH_G : integer := 8;
36  ADDR_WIDTH_G : integer range 1 to (2**24) := 4;
37  INIT_G : slv := "0");
38  port (
39  -- Port A (Read/Write)
40  clka : in sl := '0';
41  en_a : in sl := '1';
42  wea : in sl := '0';
43  weaByte : in slv(wordCount(DATA_WIDTH_G, BYTE_WIDTH_G)-1 downto 0) := (others => '0');
44  rsta : in sl := not(RST_POLARITY_G);
45  addra : in slv(ADDR_WIDTH_G-1 downto 0) := (others => '0');
46  dina : in slv(DATA_WIDTH_G-1 downto 0) := (others => '0');
47  douta : out slv(DATA_WIDTH_G-1 downto 0);
48  -- Port B (Read Only)
49  clkb : in sl := '0';
50  en_b : 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  -- Port C (Read Only)
55  en_c : in sl := '1';
56  clkc : in sl := '0';
57  rstc : in sl := not(RST_POLARITY_G);
58  addrc : in slv(ADDR_WIDTH_G-1 downto 0) := (others => '0');
59  doutc : out slv(DATA_WIDTH_G-1 downto 0);
60  -- Port D (Read Only)
61  en_d : in sl := '1';
62  clkd : in sl := '0';
63  rstd : in sl := not(RST_POLARITY_G);
64  addrd : in slv(ADDR_WIDTH_G-1 downto 0) := (others => '0');
65  doutd : out slv(DATA_WIDTH_G-1 downto 0));
66 end QuadPortRam;
67 
68 architecture rtl of QuadPortRam is
69 
70  -- Initial RAM Values
71  constant NUM_BYTES_C : natural := wordCount(DATA_WIDTH_G, BYTE_WIDTH_G);
72  constant FULL_DATA_WIDTH_C : natural := NUM_BYTES_C*BYTE_WIDTH_G;
73 
74  constant INIT_C : slv(DATA_WIDTH_G-1 downto 0) := ite(INIT_G = "0", slvZero(DATA_WIDTH_G), INIT_G);
75 
76 
77  -- Shared memory
78  type mem_type is array ((2**ADDR_WIDTH_G)-1 downto 0) of slv(DATA_WIDTH_G-1 downto 0);
79  signal mem : mem_type := (others => INIT_C);
80 
81  signal weaByteInt : slv(weaByte'range);
82 
83  -- Attribute for XST (Xilinx Synthesis)
84  attribute ram_style : string;
85  attribute ram_style of mem : signal is "distributed";
86 
87  attribute ram_extract : string;
88  attribute ram_extract of mem : signal is "TRUE";
89 
90  -- Attribute for Synplicity Synthesizer
91  attribute syn_ramstyle : string;
92  attribute syn_ramstyle of mem : signal is "distributed";
93 
94  attribute syn_keep : string;
95  attribute syn_keep of mem : signal is "TRUE";
96 
97 begin
98 
99 
100  -- MODE_G check
101  assert (MODE_G = "no-change") or (MODE_G = "read-first") or (MODE_G = "write-first")
102  report "MODE_G must be either no-change, read-first, or write-first"
103  severity failure;
104 
105  weaByteInt <= weaByte when BYTE_WR_EN_G else (others => wea);
106 
107  -- Port A
108  PORT_A_NOT_REG : if (REG_EN_G = false) generate
109 
110  process(clka)
111  begin
112  if rising_edge(clka) then
113  if (en_a = '1') then
114  for i in NUM_BYTES_C-1 downto 0 loop
115  if (weaByteInt(i) = '1') then
116  mem(conv_integer(addra))(minimum(DATA_WIDTH_G-1, (i+1)*BYTE_WIDTH_G-1) downto i*BYTE_WIDTH_G) <=
117  dina(minimum(DATA_WIDTH_G-1, (i+1)*BYTE_WIDTH_G-1) downto i*BYTE_WIDTH_G);
118  end if;
119  end loop;
120  end if;
121  end if;
122  end process;
123 
124  douta <= mem(conv_integer(addra));
125 
126 
127  end generate;
128 
129  PORT_A_REG : if (REG_EN_G = true) generate
130 
131  NO_CHANGE_MODE : if MODE_G = "no-change" generate
132  process(clka)
133  begin
134  if rising_edge(clka) then
135  if en_a = '1' then
136  for i in NUM_BYTES_C-1 downto 0 loop
137  if (weaByteInt(i) = '1') then
138  mem(conv_integer(addra))(minimum(DATA_WIDTH_G-1, (i+1)*BYTE_WIDTH_G-1) downto i*BYTE_WIDTH_G) <=
139  dina(minimum(DATA_WIDTH_G-1, (i+1)*BYTE_WIDTH_G-1) downto i*BYTE_WIDTH_G);
140  end if;
141  end loop;
142  end if;
143  end if;
144  end process;
145 
146  process(clka)
147  begin
148  if rising_edge(clka) then
149  if (en_a = '1' and weaByteInt = 0) then
150  douta <= mem(conv_integer(addra)) after TPD_G;
151  end if;
152  if rsta = RST_POLARITY_G then
153  douta <= INIT_C after TPD_G;
154  end if;
155  end if;
156  end process;
157 
158  end generate;
159 
160  READ_FIRST_MODE : if MODE_G = "read-first" generate
161  process(clka)
162  begin
163  if rising_edge(clka) then
164  if en_a = '1' then
165  douta <= mem(conv_integer(addra)) after TPD_G;
166  for i in 0 to NUM_BYTES_C-1 loop
167  if (weaByteInt(i) = '1') then
168  mem(conv_integer(addra))(minimum(DATA_WIDTH_G-1, (i+1)*BYTE_WIDTH_G-1) downto i*BYTE_WIDTH_G) <=
169  dina(minimum(DATA_WIDTH_G-1, (i+1)*BYTE_WIDTH_G-1) downto i*BYTE_WIDTH_G);
170  end if;
171  end loop;
172  end if;
173  if rsta = RST_POLARITY_G then
174  douta <= INIT_C after TPD_G;
175  end if;
176  end if;
177  end process;
178  end generate;
179 
180  WRITE_FIRST_MODE : if MODE_G = "write-first" generate
181  process(clka)
182  begin
183  if rising_edge(clka) then
184  if en_a = '1' then
185  for i in NUM_BYTES_C-1 downto 0 loop
186  if (weaByteInt(i) = '1') then
187  mem(conv_integer(addra))(minimum(DATA_WIDTH_G-1, (i+1)*BYTE_WIDTH_G-1) downto i*BYTE_WIDTH_G) <=
188  dina(minimum(DATA_WIDTH_G-1, (i+1)*BYTE_WIDTH_G-1) downto i*BYTE_WIDTH_G);
189  end if;
190  end loop;
191  douta <= mem(conv_integer(addra)) after TPD_G;
192  end if;
193 
194  if rsta = RST_POLARITY_G then
195  douta <= INIT_C after TPD_G;
196  end if;
197  end if;
198  end process;
199  end generate;
200 
201  end generate;
202 
203 -- Port B
204  PORT_B_REG : if (REG_EN_G = true) generate
205  process(clkb)
206  begin
207  if rising_edge(clkb) then
208  if rstb = RST_POLARITY_G then
209  doutb <= INIT_C after TPD_G;
210  elsif en_b = '1' then
211  doutb <= mem(conv_integer(addrb)) after TPD_G;
212  end if;
213  end if;
214  end process;
215  end generate;
216 
217  PORT_B_NOT_REG : if (REG_EN_G = false) generate
218  doutb <= mem(conv_integer(addrb));
219  end generate;
220 
221  -- Port C
222  PORT_C_REG : if (REG_EN_G = true) generate
223  process(clkc)
224  begin
225  if rising_edge(clkc) then
226  if rstc = RST_POLARITY_G then
227  doutc <= INIT_C after TPD_G;
228  elsif en_c = '1' then
229  doutc <= mem(conv_integer(addrc)) after TPD_G;
230  end if;
231  end if;
232  end process;
233  end generate;
234 
235  PORT_C_NOT_REG : if (REG_EN_G = false) generate
236  doutc <= mem(conv_integer(addrc));
237  end generate;
238 
239  -- Port D
240  PORT_D_REG : if (REG_EN_G = true) generate
241  process(clkd)
242  begin
243  if rising_edge(clkd) then
244  if rstd = RST_POLARITY_G then
245  doutd <= INIT_C after TPD_G;
246  elsif en_d = '1' then
247  doutd <= mem(conv_integer(addrd)) after TPD_G;
248  end if;
249  end if;
250  end process;
251  end generate;
252 
253  PORT_D_NOT_REG : if (REG_EN_G = false) generate
254  doutd <= mem(conv_integer(addrd));
255  end generate;
256 
257 end rtl;
in en_bsl := '1'
Definition: QuadPortRam.vhd:50
in weasl := '0'
Definition: QuadPortRam.vhd:42
in rstdsl :=not ( RST_POLARITY_G)
Definition: QuadPortRam.vhd:63
in dinaslv( DATA_WIDTH_G- 1 downto 0) :=( others => '0')
Definition: QuadPortRam.vhd:46
in weaByteslv( wordCount( DATA_WIDTH_G, BYTE_WIDTH_G)- 1 downto 0) :=( others => '0')
Definition: QuadPortRam.vhd:43
in clkasl := '0'
Definition: QuadPortRam.vhd:40
BYTE_WIDTH_Ginteger := 8
Definition: QuadPortRam.vhd:35
BYTE_WR_EN_Gboolean := false
Definition: QuadPortRam.vhd:33
std_logic sl
Definition: StdRtlPkg.vhd:28
in en_asl := '1'
Definition: QuadPortRam.vhd:41
ADDR_WIDTH_Ginteger range 1 to ( 2** 24):= 4
Definition: QuadPortRam.vhd:36
out doutdslv( DATA_WIDTH_G- 1 downto 0)
Definition: QuadPortRam.vhd:65
TPD_Gtime := 1 ns
Definition: QuadPortRam.vhd:29
in clkcsl := '0'
Definition: QuadPortRam.vhd:56
out doutaslv( DATA_WIDTH_G- 1 downto 0)
Definition: QuadPortRam.vhd:47
MODE_Gstring := "read-first"
Definition: QuadPortRam.vhd:32
in addraslv( ADDR_WIDTH_G- 1 downto 0) :=( others => '0')
Definition: QuadPortRam.vhd:45
out doutbslv( DATA_WIDTH_G- 1 downto 0)
Definition: QuadPortRam.vhd:53
in rstcsl :=not ( RST_POLARITY_G)
Definition: QuadPortRam.vhd:57
_library_ ieeeieee
out doutcslv( DATA_WIDTH_G- 1 downto 0)
Definition: QuadPortRam.vhd:59
in addrcslv( ADDR_WIDTH_G- 1 downto 0) :=( others => '0')
Definition: QuadPortRam.vhd:58
INIT_Gslv := "0"
Definition: QuadPortRam.vhd:37
in en_csl := '1'
Definition: QuadPortRam.vhd:55
in addrdslv( ADDR_WIDTH_G- 1 downto 0) :=( others => '0')
Definition: QuadPortRam.vhd:64
RST_POLARITY_Gsl := '1'
Definition: QuadPortRam.vhd:30
in addrbslv( ADDR_WIDTH_G- 1 downto 0) :=( others => '0')
Definition: QuadPortRam.vhd:52
in rstasl :=not ( RST_POLARITY_G)
Definition: QuadPortRam.vhd:44
in rstbsl :=not ( RST_POLARITY_G)
Definition: QuadPortRam.vhd:51
REG_EN_Gboolean := true
Definition: QuadPortRam.vhd:31
in clkbsl := '0'
Definition: QuadPortRam.vhd:49
DATA_WIDTH_Ginteger range 1 to ( 2** 24):= 16
Definition: QuadPortRam.vhd:34
std_logic_vector slv
Definition: StdRtlPkg.vhd:29
in clkdsl := '0'
Definition: QuadPortRam.vhd:62
in en_dsl := '1'
Definition: QuadPortRam.vhd:61