1 |
2 |
danv |
-------------------------------------------------------------------------------
|
2 |
|
|
--
|
3 |
3 |
danv |
-- Copyright 2020
|
4 |
2 |
danv |
-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
|
5 |
|
|
-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
|
6 |
3 |
danv |
--
|
7 |
|
|
-- Licensed under the Apache License, Version 2.0 (the "License");
|
8 |
|
|
-- you may not use this file except in compliance with the License.
|
9 |
|
|
-- You may obtain a copy of the License at
|
10 |
|
|
--
|
11 |
|
|
-- http://www.apache.org/licenses/LICENSE-2.0
|
12 |
|
|
--
|
13 |
|
|
-- Unless required by applicable law or agreed to in writing, software
|
14 |
|
|
-- distributed under the License is distributed on an "AS IS" BASIS,
|
15 |
|
|
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
16 |
|
|
-- See the License for the specific language governing permissions and
|
17 |
|
|
-- limitations under the License.
|
18 |
2 |
danv |
--
|
19 |
|
|
-------------------------------------------------------------------------------
|
20 |
|
|
|
21 |
|
|
LIBRARY IEEE, common_pkg_lib;
|
22 |
|
|
USE IEEE.STD_LOGIC_1164.ALL;
|
23 |
|
|
USE IEEE.NUMERIC_STD.ALL;
|
24 |
|
|
USE common_pkg_lib.common_pkg.ALL;
|
25 |
|
|
|
26 |
|
|
PACKAGE common_ram_pkg IS
|
27 |
|
|
|
28 |
|
|
------------------------------------------------------------------------------
|
29 |
|
|
-- Simple memory access (for MM control interface)
|
30 |
|
|
------------------------------------------------------------------------------
|
31 |
|
|
|
32 |
|
|
-- Assume the MM bus is for a 32 bit processor, therefore on the processor
|
33 |
|
|
-- side of a memory peripheral typcially use c_word_w = 32 for the address
|
34 |
|
|
-- and data fields in the MM bus records. However the MM bus can also be used
|
35 |
|
|
-- on the user side of a memory peripheral and there the data width should
|
36 |
|
|
-- not be limited by the processor type but rather by the maximum user data
|
37 |
|
|
-- width on the streaming interface.
|
38 |
|
|
--
|
39 |
|
|
-- The std_logic_vector widths in the record need to be defined, because in
|
40 |
|
|
-- a record they can not be unconstrained. A signal that needs less address
|
41 |
|
|
-- or data width simply leaves the unused MSbits at 'X'. The actually used
|
42 |
|
|
-- width of a memory gets set via a generic record type t_c_mem.
|
43 |
|
|
--
|
44 |
|
|
-- The alternative is to not put the std_logic_vector elements in the record,
|
45 |
|
|
-- and declare them seperately, however then the compact representation that
|
46 |
|
|
-- records provide gets lost, because the record then only contains wr_en and
|
47 |
|
|
-- rd_en. Another alternative is to define the address as a integer and the
|
48 |
|
|
-- data as an integer. However this limits their range to 32 bit numbers,
|
49 |
|
|
-- which can be too few for data.
|
50 |
|
|
|
51 |
|
|
-- Do not change these widths, because c_word_w just fits in a VHDL INTEGER
|
52 |
|
|
-- Should wider address range or data width be needed, then define a new
|
53 |
|
|
-- record type eg. t_mem_ctlr or t_mem_bus for that with
|
54 |
|
|
-- sufficient widths.
|
55 |
|
|
|
56 |
|
|
-- Choose smallest maximum slv lengths that fit all use cases, because unconstrained record fields slv is not allowed
|
57 |
|
|
CONSTANT c_mem_address_w : NATURAL := 32; -- address range (suits 32-bit processor)
|
58 |
|
|
CONSTANT c_mem_data_w : NATURAL := 72; -- data width (suit up to 8 bytes, that can also be 9 bit bytes)
|
59 |
|
|
CONSTANT c_mem_address_sz : NATURAL := c_mem_address_w/c_byte_w;
|
60 |
|
|
CONSTANT c_mem_data_sz : NATURAL := c_mem_data_w/c_byte_w;
|
61 |
|
|
|
62 |
|
|
TYPE t_mem_miso IS RECORD -- Master In Slave Out
|
63 |
|
|
rddata : STD_LOGIC_VECTOR(c_mem_data_w-1 DOWNTO 0); -- data width (suits 1, 2 or 4 bytes)
|
64 |
|
|
rdval : STD_LOGIC;
|
65 |
|
|
waitrequest : STD_LOGIC;
|
66 |
|
|
END RECORD;
|
67 |
|
|
|
68 |
|
|
TYPE t_mem_mosi IS RECORD -- Master Out Slave In
|
69 |
|
|
address : STD_LOGIC_VECTOR(c_mem_address_w-1 DOWNTO 0); -- address range (suits 32-bit processor)
|
70 |
|
|
wrdata : STD_LOGIC_VECTOR(c_mem_data_w-1 DOWNTO 0); -- data width (suits 1, 2 or 4 bytes)
|
71 |
|
|
wr : STD_LOGIC;
|
72 |
|
|
rd : STD_LOGIC;
|
73 |
|
|
END RECORD;
|
74 |
|
|
|
75 |
|
|
CONSTANT c_mem_miso_rst : t_mem_miso := ((OTHERS=>'0'), '0', '0');
|
76 |
|
|
CONSTANT c_mem_mosi_rst : t_mem_mosi := ((OTHERS=>'0'), (OTHERS=>'0'), '0', '0');
|
77 |
|
|
|
78 |
|
|
-- Multi port array for MM records
|
79 |
|
|
TYPE t_mem_miso_arr IS ARRAY (INTEGER RANGE <>) OF t_mem_miso;
|
80 |
|
|
TYPE t_mem_mosi_arr IS ARRAY (INTEGER RANGE <>) OF t_mem_mosi;
|
81 |
|
|
|
82 |
|
|
-- Resize functions to fit an integer or an SLV in the corresponding t_mem_miso or t_mem_mosi field width
|
83 |
|
|
FUNCTION TO_MEM_ADDRESS(n : INTEGER) RETURN STD_LOGIC_VECTOR; -- unsigned, use integer to support 32 bit range
|
84 |
|
|
FUNCTION TO_MEM_DATA( n : INTEGER) RETURN STD_LOGIC_VECTOR; -- unsigned, alias of TO_MEM_DATA()
|
85 |
|
|
FUNCTION TO_MEM_UDATA( n : INTEGER) RETURN STD_LOGIC_VECTOR; -- unsigned, use integer to support 32 bit range
|
86 |
|
|
FUNCTION TO_MEM_SDATA( n : INTEGER) RETURN STD_LOGIC_VECTOR; -- sign extended
|
87 |
|
|
FUNCTION RESIZE_MEM_ADDRESS(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- unsigned
|
88 |
|
|
FUNCTION RESIZE_MEM_DATA( vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- unsigned, alias of RESIZE_MEM_UDATA
|
89 |
|
|
FUNCTION RESIZE_MEM_UDATA( vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- unsigned
|
90 |
|
|
FUNCTION RESIZE_MEM_SDATA( vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- sign extended
|
91 |
|
|
FUNCTION RESIZE_MEM_XDATA( vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- set unused MSBits to 'X'
|
92 |
|
|
|
93 |
|
|
|
94 |
|
|
------------------------------------------------------------------------------
|
95 |
|
|
-- Burst memory access (for DDR access interface)
|
96 |
|
|
------------------------------------------------------------------------------
|
97 |
|
|
|
98 |
|
|
-- Choose smallest maximum slv lengths that fit all use cases, because unconstrained record fields slv is not allowed
|
99 |
|
|
CONSTANT c_mem_ctlr_address_w : NATURAL := 32;
|
100 |
|
|
CONSTANT c_mem_ctlr_data_w : NATURAL := 576;
|
101 |
|
|
CONSTANT c_mem_ctlr_burstsize_w : NATURAL := c_mem_ctlr_address_w;
|
102 |
|
|
|
103 |
|
|
TYPE t_mem_ctlr_miso IS RECORD
|
104 |
|
|
rddata : STD_LOGIC_VECTOR(c_mem_ctlr_data_w-1 DOWNTO 0);
|
105 |
|
|
rdval : STD_LOGIC;
|
106 |
|
|
waitrequest_n : STD_LOGIC; -- comparable to DP siso.ready
|
107 |
|
|
done : STD_LOGIC; -- comparable to DP siso.xon, not part of Avalon bus, can eg. act as init done or init ok or ready for next block, useful for DDR controller
|
108 |
|
|
cal_ok : STD_LOGIC;
|
109 |
|
|
cal_fail : STD_LOGIC;
|
110 |
|
|
END RECORD;
|
111 |
|
|
|
112 |
|
|
TYPE t_mem_ctlr_mosi IS RECORD
|
113 |
|
|
address : STD_LOGIC_VECTOR(c_mem_ctlr_address_w-1 DOWNTO 0);
|
114 |
|
|
wrdata : STD_LOGIC_VECTOR(c_mem_ctlr_data_w-1 DOWNTO 0);
|
115 |
|
|
wr : STD_LOGIC;
|
116 |
|
|
rd : STD_LOGIC;
|
117 |
|
|
burstbegin : STD_LOGIC;
|
118 |
|
|
burstsize : STD_LOGIC_VECTOR(c_mem_ctlr_burstsize_w-1 DOWNTO 0);
|
119 |
|
|
flush : STD_LOGIC; -- not part of Avalon bus, but useful for DDR driver
|
120 |
|
|
END RECORD;
|
121 |
|
|
|
122 |
|
|
CONSTANT c_mem_ctlr_miso_rst : t_mem_ctlr_miso := ((OTHERS=>'0'), '0', '0', '0', '0', '0');
|
123 |
|
|
CONSTANT c_mem_ctlr_mosi_rst : t_mem_ctlr_mosi := ((OTHERS=>'0'), (OTHERS=>'0'), '0', '0', '0', (OTHERS=>'0'), '0');
|
124 |
|
|
|
125 |
|
|
-- Multi port array for mem_ctlr records
|
126 |
|
|
TYPE t_mem_ctlr_miso_arr IS ARRAY (INTEGER RANGE <>) OF t_mem_ctlr_miso;
|
127 |
|
|
TYPE t_mem_ctlr_mosi_arr IS ARRAY (INTEGER RANGE <>) OF t_mem_ctlr_mosi;
|
128 |
|
|
|
129 |
|
|
|
130 |
|
|
-- Resize functions to fit an integer or an SLV in the corresponding t_mem_ctlr_miso or t_mem_ctlr_mosi field width
|
131 |
|
|
FUNCTION TO_MEM_CTLR_ADDRESS( n : INTEGER) RETURN STD_LOGIC_VECTOR; -- unsigned, use integer to support 32 bit range
|
132 |
|
|
FUNCTION TO_MEM_CTLR_DATA( n : INTEGER) RETURN STD_LOGIC_VECTOR; -- unsigned
|
133 |
|
|
FUNCTION TO_MEM_CTLR_BURSTSIZE(n : INTEGER) RETURN STD_LOGIC_VECTOR; -- unsigned
|
134 |
|
|
|
135 |
|
|
FUNCTION RESIZE_MEM_CTLR_ADDRESS( vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- unsigned
|
136 |
|
|
FUNCTION RESIZE_MEM_CTLR_DATA( vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- unsigned
|
137 |
|
|
FUNCTION RESIZE_MEM_CTLR_BURSTSIZE(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR; -- unsigned
|
138 |
|
|
|
139 |
|
|
|
140 |
|
|
------------------------------------------------------------------------------
|
141 |
|
|
-- RAM block memory and MM register defintions
|
142 |
|
|
------------------------------------------------------------------------------
|
143 |
|
|
TYPE t_c_mem IS RECORD
|
144 |
|
|
latency : NATURAL; -- read latency
|
145 |
|
|
adr_w : NATURAL;
|
146 |
|
|
dat_w : NATURAL;
|
147 |
|
|
nof_dat : NATURAL; -- optional, nof dat words <= 2**adr_w
|
148 |
|
|
init_sl : STD_LOGIC; -- optional, init all dat words to std_logic '0', '1' or 'X'
|
149 |
|
|
--init_file : STRING; -- "UNUSED", unconstrained length can not be in record
|
150 |
|
|
END RECORD;
|
151 |
|
|
|
152 |
|
|
CONSTANT c_mem_ram_rd_latency : NATURAL := 2; -- note common_ram_crw_crw(stratix4) now also supports read latency 1
|
153 |
|
|
CONSTANT c_mem_ram : t_c_mem := (c_mem_ram_rd_latency, 10, 9, 2**10, 'X'); -- 1 M9K
|
154 |
|
|
|
155 |
|
|
CONSTANT c_mem_reg_rd_latency : NATURAL := 1;
|
156 |
|
|
CONSTANT c_mem_reg : t_c_mem := (c_mem_reg_rd_latency, 1, 32, 1, 'X');
|
157 |
|
|
|
158 |
|
|
CONSTANT c_mem_reg_init_w : NATURAL := 1*256*32; -- >= largest expected value of dat_w*nof_dat (256 * 32 bit = 1k byte)
|
159 |
|
|
|
160 |
|
|
|
161 |
|
|
------------------------------------------------------------------------------
|
162 |
|
|
-- Functions to swap endianess
|
163 |
|
|
------------------------------------------------------------------------------
|
164 |
|
|
FUNCTION func_mem_swap_endianess(mm : t_mem_miso; sz : NATURAL) RETURN t_mem_miso;
|
165 |
|
|
FUNCTION func_mem_swap_endianess(mm : t_mem_mosi; sz : NATURAL) RETURN t_mem_mosi;
|
166 |
|
|
|
167 |
|
|
END common_ram_pkg;
|
168 |
|
|
|
169 |
|
|
PACKAGE BODY common_ram_pkg IS
|
170 |
|
|
|
171 |
|
|
-- Resize functions to fit an integer or an SLV in the corresponding t_mem_miso or t_mem_mosi field width
|
172 |
|
|
FUNCTION TO_MEM_ADDRESS(n : INTEGER) RETURN STD_LOGIC_VECTOR IS
|
173 |
|
|
BEGIN
|
174 |
|
|
RETURN RESIZE_UVEC(TO_SVEC(n, 32), c_mem_address_w);
|
175 |
|
|
END TO_MEM_ADDRESS;
|
176 |
|
|
|
177 |
|
|
FUNCTION TO_MEM_DATA(n : INTEGER) RETURN STD_LOGIC_VECTOR IS
|
178 |
|
|
BEGIN
|
179 |
|
|
RETURN TO_MEM_UDATA(n);
|
180 |
|
|
END TO_MEM_DATA;
|
181 |
|
|
|
182 |
|
|
FUNCTION TO_MEM_UDATA(n : INTEGER) RETURN STD_LOGIC_VECTOR IS
|
183 |
|
|
BEGIN
|
184 |
|
|
RETURN RESIZE_UVEC(TO_SVEC(n, 32), c_mem_data_w);
|
185 |
|
|
END TO_MEM_UDATA;
|
186 |
|
|
|
187 |
|
|
FUNCTION TO_MEM_SDATA(n : INTEGER) RETURN STD_LOGIC_VECTOR IS
|
188 |
|
|
BEGIN
|
189 |
|
|
RETURN RESIZE_SVEC(TO_SVEC(n, 32), c_mem_data_w);
|
190 |
|
|
END TO_MEM_SDATA;
|
191 |
|
|
|
192 |
|
|
FUNCTION RESIZE_MEM_ADDRESS(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
|
193 |
|
|
BEGIN
|
194 |
|
|
RETURN RESIZE_UVEC(vec, c_mem_address_w);
|
195 |
|
|
END RESIZE_MEM_ADDRESS;
|
196 |
|
|
|
197 |
|
|
FUNCTION RESIZE_MEM_DATA(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
|
198 |
|
|
BEGIN
|
199 |
|
|
RETURN RESIZE_MEM_UDATA(vec);
|
200 |
|
|
END RESIZE_MEM_DATA;
|
201 |
|
|
|
202 |
|
|
FUNCTION RESIZE_MEM_UDATA(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
|
203 |
|
|
BEGIN
|
204 |
|
|
RETURN RESIZE_UVEC(vec, c_mem_data_w);
|
205 |
|
|
END RESIZE_MEM_UDATA;
|
206 |
|
|
|
207 |
|
|
FUNCTION RESIZE_MEM_SDATA(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
|
208 |
|
|
BEGIN
|
209 |
|
|
RETURN RESIZE_SVEC(vec, c_mem_data_w);
|
210 |
|
|
END RESIZE_MEM_SDATA;
|
211 |
|
|
|
212 |
|
|
FUNCTION RESIZE_MEM_XDATA(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
|
213 |
|
|
VARIABLE v_vec : STD_LOGIC_VECTOR(c_mem_data_w-1 DOWNTO 0) := (OTHERS=>'X');
|
214 |
|
|
BEGIN
|
215 |
|
|
v_vec(vec'LENGTH-1 DOWNTO 0) := vec;
|
216 |
|
|
RETURN v_vec;
|
217 |
|
|
END RESIZE_MEM_XDATA;
|
218 |
|
|
|
219 |
|
|
|
220 |
|
|
-- Resize functions to fit an integer or an SLV in the corresponding t_mem_miso or t_mem_mosi field width
|
221 |
|
|
FUNCTION TO_MEM_CTLR_ADDRESS(n : INTEGER) RETURN STD_LOGIC_VECTOR IS
|
222 |
|
|
BEGIN
|
223 |
|
|
RETURN RESIZE_UVEC(TO_SVEC(n, 32), c_mem_ctlr_address_w);
|
224 |
|
|
END TO_MEM_CTLR_ADDRESS;
|
225 |
|
|
|
226 |
|
|
FUNCTION TO_MEM_CTLR_DATA(n : INTEGER) RETURN STD_LOGIC_VECTOR IS
|
227 |
|
|
BEGIN
|
228 |
|
|
RETURN RESIZE_UVEC(TO_SVEC(n, 32), c_mem_ctlr_data_w);
|
229 |
|
|
END TO_MEM_CTLR_DATA;
|
230 |
|
|
|
231 |
|
|
FUNCTION TO_MEM_CTLR_BURSTSIZE(n : INTEGER) RETURN STD_LOGIC_VECTOR IS
|
232 |
|
|
BEGIN
|
233 |
|
|
RETURN RESIZE_UVEC(TO_SVEC(n, 32), c_mem_ctlr_burstsize_w);
|
234 |
|
|
END TO_MEM_CTLR_BURSTSIZE;
|
235 |
|
|
|
236 |
|
|
FUNCTION RESIZE_MEM_CTLR_ADDRESS(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
|
237 |
|
|
BEGIN
|
238 |
|
|
RETURN RESIZE_UVEC(vec, c_mem_ctlr_address_w);
|
239 |
|
|
END RESIZE_MEM_CTLR_ADDRESS;
|
240 |
|
|
|
241 |
|
|
FUNCTION RESIZE_MEM_CTLR_DATA(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
|
242 |
|
|
BEGIN
|
243 |
|
|
RETURN RESIZE_UVEC(vec, c_mem_ctlr_data_w);
|
244 |
|
|
END RESIZE_MEM_CTLR_DATA;
|
245 |
|
|
|
246 |
|
|
FUNCTION RESIZE_MEM_CTLR_BURSTSIZE(vec : STD_LOGIC_VECTOR) RETURN STD_LOGIC_VECTOR IS
|
247 |
|
|
BEGIN
|
248 |
|
|
RETURN RESIZE_UVEC(vec, c_mem_ctlr_burstsize_w);
|
249 |
|
|
END RESIZE_MEM_CTLR_BURSTSIZE;
|
250 |
|
|
|
251 |
|
|
|
252 |
|
|
-- Functions to swap endianess
|
253 |
|
|
FUNCTION func_mem_swap_endianess(mm : t_mem_miso; sz : NATURAL) RETURN t_mem_miso IS
|
254 |
|
|
VARIABLE v_mm : t_mem_miso;
|
255 |
|
|
BEGIN
|
256 |
|
|
-- Master In Slave Out
|
257 |
|
|
v_mm.rddata := hton(mm.rddata, sz);
|
258 |
|
|
RETURN v_mm;
|
259 |
|
|
END func_mem_swap_endianess;
|
260 |
|
|
|
261 |
|
|
FUNCTION func_mem_swap_endianess(mm : t_mem_mosi; sz : NATURAL) RETURN t_mem_mosi IS
|
262 |
|
|
VARIABLE v_mm : t_mem_mosi;
|
263 |
|
|
BEGIN
|
264 |
|
|
-- Master Out Slave In
|
265 |
|
|
v_mm.address := mm.address;
|
266 |
|
|
v_mm.wrdata := hton(mm.wrdata, sz);
|
267 |
|
|
v_mm.wr := mm.wr;
|
268 |
|
|
v_mm.rd := mm.rd;
|
269 |
|
|
RETURN v_mm;
|
270 |
|
|
END func_mem_swap_endianess;
|
271 |
|
|
|
272 |
|
|
END common_ram_pkg;
|