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 |
|
|
-- Author:
|
22 |
|
|
-- D. van der Schuur May 2012 Initial
|
23 |
|
|
-- E. Kooistra Jan 2018 Removed unused generics and added remarks.
|
24 |
|
|
-- Purpose: Provide access to an MM slave via file IO
|
25 |
|
|
-- Description:
|
26 |
|
|
-- See mm_file_pkg.
|
27 |
|
|
--
|
28 |
|
|
-- * Optional MM file IO throttle via g_mm_timeout, g_mm_pause:
|
29 |
|
|
-- Default g_mm_timeout=0 ns for full speed MM file IO rate. Optional use
|
30 |
|
|
-- g_mm_timeout>0 ns to throttle MM file IO rate. The mm_master_out wr and
|
31 |
|
|
-- rd strobes are monitored. As long as a strobe occurs within
|
32 |
|
|
-- g_mm_timeout then the MM file IO operates at full speed. When no strobe
|
33 |
|
|
-- occurs within g_mm_timeout, then a delay of g_mm_pause is inserted
|
34 |
|
|
-- until the next MM file IO access will be done. This throttling reduces
|
35 |
|
|
-- the file IO rate when the MM slave is idle and picks up again at full
|
36 |
|
|
-- speed when MM slave accesses appear again.
|
37 |
|
|
--
|
38 |
|
|
-- The g_mm_timeout is in ns, and not defined in number of mm_clk cycles,
|
39 |
|
|
-- to make it independent of the simulation mm_clk period. This is
|
40 |
|
|
-- important to be able to handle clock domain crossings between a fast
|
41 |
|
|
-- simulation mm_clk and a relatively slow internal dp_clk. If the
|
42 |
|
|
-- g_mm_timeout is too short then it will occur for every MM access that
|
43 |
|
|
-- needs a MM-DP clock domain crossing. A dp_clk typically runs at
|
44 |
|
|
-- about 100 or 200 MHz, so period < about 10 ns. A clock domain crossing
|
45 |
|
|
-- takes about 25 clock cycles in both clock domains (see
|
46 |
|
|
-- common_reg_cross_domain.vhd). Hence a suitable default value for
|
47 |
|
|
-- g_mm_timeout is about 250 ns. With some margin use 1000 ns.
|
48 |
|
|
-- The g_mm_pause is defined in ns, but could as well have been defined
|
49 |
|
|
-- in number mm_clk cycle. Use g_mm_pause default 100 ns to have a factor
|
50 |
|
|
-- 1000 reduction in file IO rate witk c_mmf_mm_clk_period = 100 ps, while
|
51 |
|
|
-- not introducing too much delay in case a new MM access is pending.
|
52 |
|
|
--
|
53 |
|
|
-- Remarks:
|
54 |
|
|
-- * Positional mapping of generics and port:
|
55 |
|
|
-- If necessary new generics or ports should be added after the existing
|
56 |
|
|
-- generics or ports, because then existing mm_file instances that use
|
57 |
|
|
-- positional mapping instead of explicit name mapping (with =>) still
|
58 |
|
|
-- compile ok.
|
59 |
|
|
--
|
60 |
|
|
-- * Default g_mm_rd_latency=2:
|
61 |
|
|
-- The default g_mm_rd_latency=2 to fit both MM reg (which typically have rd
|
62 |
|
|
-- latency 1) and MM ram (for which some have rd latency 2). This works
|
63 |
|
|
-- because the mm_master_out.rd strobes have gaps. The maximum rd strobe
|
64 |
|
|
-- rate appears to be 1 strobe in every 4 cycles. By using default
|
65 |
|
|
-- g_mm_rd_latency=2 the mm_file instances do not explicitly have to map the
|
66 |
|
|
-- actual MM slave rd latency, because using 2 fits all. This ensures
|
67 |
|
|
-- that all existing mm_file instances that do not map g_mm_rd_latency still
|
68 |
|
|
-- work and for new mm_file instances it avoids the need to know whether the
|
69 |
|
|
-- MM slave actually has rd latency 1 or 2.
|
70 |
|
|
--
|
71 |
|
|
-- * Default g_file_enable='1':
|
72 |
|
|
-- Default the mm_file instance will open the files. However if the MM slave
|
73 |
|
|
-- will not be used in a test, then it can be good to use g_file_enable='0'
|
74 |
|
|
-- to avoid these files. For multi tb or tb with many mm_file instances this
|
75 |
|
|
-- limits the number of file handlers and may help to improve the simulation
|
76 |
|
|
-- speed (and stability).
|
77 |
|
|
--
|
78 |
|
|
LIBRARY IEEE, common_pkg_lib, common_ram_lib;
|
79 |
|
|
USE IEEE.std_logic_1164.ALL;
|
80 |
|
|
USE IEEE.numeric_std.ALL;
|
81 |
|
|
USE common_pkg_lib.common_pkg.ALL;
|
82 |
|
|
USE common_pkg_lib.tb_common_pkg.ALL;
|
83 |
|
|
USE common_ram_lib.common_ram_pkg.ALL;
|
84 |
|
|
USE work.tb_common_mem_pkg.ALL;
|
85 |
|
|
USE common_pkg_lib.common_str_pkg.ALL;
|
86 |
|
|
USE work.mm_file_pkg.ALL;
|
87 |
|
|
USE IEEE.std_logic_textio.ALL;
|
88 |
|
|
USE std.textio.ALL;
|
89 |
|
|
|
90 |
|
|
ENTITY mm_file IS
|
91 |
|
|
GENERIC (
|
92 |
|
|
g_file_prefix : STRING; -- e.g. "ppsh" will create i/o files ppsh_stat.txt and ppsh_ctrl.txt
|
93 |
|
|
g_file_enable : STD_LOGIC := '1'; -- default use '1' to enable file IO, use '0' to disable file IO and force mm_master_out to c_mem_mosi_rst
|
94 |
|
|
g_mm_rd_latency : NATURAL := 2; -- default use 2 to fit 0, 1 or 2, must be >= read latency of the MM slave
|
95 |
|
|
g_mm_timeout : TIME := c_mmf_mm_timeout; -- use 0 ns for full speed MM, use > 0 ns to define time without MM access after which the MM file IO is paused
|
96 |
|
|
g_mm_pause : TIME := c_mmf_mm_pause -- defines time for which MM file IO is paused to reduce the file IO rate when the MM slave is idle
|
97 |
|
|
);
|
98 |
|
|
PORT (
|
99 |
|
|
mm_rst : IN STD_LOGIC;
|
100 |
|
|
mm_clk : IN STD_LOGIC;
|
101 |
|
|
|
102 |
|
|
mm_master_out : OUT t_mem_mosi := c_mem_mosi_rst;
|
103 |
|
|
mm_master_in : IN t_mem_miso := c_mem_miso_rst
|
104 |
|
|
);
|
105 |
|
|
END mm_file;
|
106 |
|
|
|
107 |
|
|
|
108 |
|
|
ARCHITECTURE str OF mm_file IS
|
109 |
|
|
|
110 |
|
|
CONSTANT c_rd_file_name : STRING := g_file_prefix & ".ctrl";
|
111 |
|
|
CONSTANT c_wr_file_name : STRING := g_file_prefix & ".stat";
|
112 |
|
|
|
113 |
|
|
SIGNAL i_mm_master_out : t_mem_mosi;
|
114 |
|
|
|
115 |
|
|
-- Optional file IO throttle control
|
116 |
|
|
SIGNAL strobe : STD_LOGIC;
|
117 |
|
|
SIGNAL pause : STD_LOGIC;
|
118 |
|
|
SIGNAL polling : STD_LOGIC := '0'; -- monitor signal to view in Wave window when mmf_mm_from_file() is busy
|
119 |
|
|
SIGNAL timebegin : TIME := 0 ns;
|
120 |
|
|
SIGNAL timeout : TIME := 0 ns;
|
121 |
|
|
|
122 |
|
|
BEGIN
|
123 |
|
|
|
124 |
|
|
mm_master_out <= i_mm_master_out;
|
125 |
|
|
|
126 |
|
|
no_file : IF g_file_enable='0' GENERATE
|
127 |
|
|
i_mm_master_out <= c_mem_mosi_rst;
|
128 |
|
|
END GENERATE;
|
129 |
|
|
|
130 |
|
|
gen_file : IF g_file_enable='1' GENERATE
|
131 |
|
|
|
132 |
|
|
p_file_to_mm : PROCESS
|
133 |
|
|
BEGIN
|
134 |
|
|
i_mm_master_out <= c_mem_mosi_rst;
|
135 |
|
|
|
136 |
|
|
-- Create the ctrl file that we're going to read from
|
137 |
|
|
print_str("[" & time_to_str(NOW) & "] " & c_rd_file_name & ": Created" );
|
138 |
|
|
mmf_file_create(c_rd_file_name);
|
139 |
|
|
|
140 |
|
|
WHILE TRUE LOOP
|
141 |
|
|
mmf_mm_from_file(mm_clk, mm_rst, i_mm_master_out, mm_master_in, c_rd_file_name, c_wr_file_name, g_mm_rd_latency);
|
142 |
|
|
|
143 |
|
|
-- Optional file IO throttle control
|
144 |
|
|
IF g_mm_timeout>0 ns AND pause='1' THEN
|
145 |
|
|
polling <= '0';
|
146 |
|
|
WAIT FOR g_mm_pause; -- Pause the file IO when MM timeout is enabled and no strobes appeared for g_mm_timeout
|
147 |
|
|
|
148 |
|
|
proc_common_wait_some_cycles(mm_clk, 1); -- Realign to mm_clk, not needed but done to resemble return from mmf_mm_from_file()
|
149 |
|
|
polling <= '1';
|
150 |
|
|
END IF;
|
151 |
|
|
END LOOP;
|
152 |
|
|
|
153 |
|
|
WAIT;
|
154 |
|
|
END PROCESS;
|
155 |
|
|
|
156 |
|
|
-- Optional file IO throttle control
|
157 |
|
|
gen_mm_timeout_control : IF g_mm_timeout>0 ns GENERATE
|
158 |
|
|
strobe <= i_mm_master_out.wr OR i_mm_master_out.rd; -- detect MM access
|
159 |
|
|
|
160 |
|
|
pause <= NOT strobe WHEN timeout>g_mm_timeout ELSE '0'; -- issue MM file IO pause after strobe timeout
|
161 |
|
|
|
162 |
|
|
-- Use mm_clk event to update time based on NOW, without event it does not update
|
163 |
|
|
p_mm_now : PROCESS(mm_rst, mm_clk)
|
164 |
|
|
BEGIN
|
165 |
|
|
IF mm_rst='1' THEN
|
166 |
|
|
-- during reset no timeouts
|
167 |
|
|
timebegin <= NOW;
|
168 |
|
|
timeout <= 0 ns;
|
169 |
|
|
ELSE
|
170 |
|
|
-- use MM access to restart timeout
|
171 |
|
|
IF strobe='1' THEN
|
172 |
|
|
timebegin <= NOW;
|
173 |
|
|
END IF;
|
174 |
|
|
timeout <= NOW - timebegin;
|
175 |
|
|
END IF;
|
176 |
|
|
END PROCESS;
|
177 |
|
|
END GENERATE;
|
178 |
|
|
|
179 |
|
|
END GENERATE;
|
180 |
|
|
|
181 |
|
|
END str;
|
182 |
|
|
|