1 |
19 |
sckoarn |
----------------
|
2 |
|
|
-- simple packet generator
|
3 |
|
|
--
|
4 |
|
|
------------------------------------------------------------------------------
|
5 |
|
|
-- First we start of with the definition of the packet array type
|
6 |
|
|
-- and the pack_out record for pins on the entity and comp.
|
7 |
|
|
-- The size of the whole system can be changed by changing the
|
8 |
|
|
-- array and record types.
|
9 |
|
|
library IEEE;
|
10 |
|
|
use IEEE.STD_LOGIC_1164.all;
|
11 |
|
|
|
12 |
|
|
package pgen is
|
13 |
|
|
|
14 |
|
|
type arr128x8 is array(0 to 127) of std_logic_vector(7 downto 0);
|
15 |
|
|
|
16 |
|
|
type pack_out is record
|
17 |
|
|
dout : arr128x8;
|
18 |
|
|
drdy : std_logic;
|
19 |
|
|
end record;
|
20 |
|
|
end package pgen;
|
21 |
|
|
|
22 |
|
|
------------------------------------------------------------------------------
|
23 |
|
|
-- this is an example packet generator for BFM's
|
24 |
|
|
-- for details of the full functionality, see the accomaning documentation
|
25 |
|
|
--
|
26 |
|
|
-- the packet_gen implementation demonstrates:
|
27 |
|
|
-- self generating data, incrementing and random
|
28 |
|
|
-- data loading from a file and file opening
|
29 |
|
|
-- setting a text entity from the stimulus file, i.e. the file name
|
30 |
|
|
-- direct setting of text data from the stimulus file.
|
31 |
|
|
-- use of the new stimulus port definition.
|
32 |
|
|
library IEEE;
|
33 |
|
|
use IEEE.STD_LOGIC_1164.all;
|
34 |
|
|
use IEEE.STD_LOGIC_ARITH.all;
|
35 |
|
|
use std.textio.all;
|
36 |
|
|
use work.tb_pkg.all;
|
37 |
|
|
library synthworks;
|
38 |
|
|
use SynthWorks.RandomBasePkg.all;
|
39 |
|
|
use SynthWorks.RandomPkg.all;
|
40 |
|
|
use work.pgen.all;
|
41 |
|
|
|
42 |
|
|
entity packet_gen is
|
43 |
|
|
generic (
|
44 |
|
|
pgen_id : integer := 0
|
45 |
|
|
);
|
46 |
|
|
port (
|
47 |
|
|
packet_out : out pack_out;
|
48 |
|
|
request : in std_logic;
|
49 |
|
|
fname : in stm_text;
|
50 |
|
|
-- env access port
|
51 |
|
|
STM_IN : in stm_sctl;
|
52 |
|
|
STM_OUT : out stm_sack
|
53 |
|
|
);
|
54 |
|
|
end packet_gen;
|
55 |
|
|
|
56 |
|
|
architecture bhv of packet_gen is
|
57 |
|
|
|
58 |
|
|
-- create the file handle for loading data from file.
|
59 |
|
|
file load_file : text;
|
60 |
|
|
|
61 |
|
|
-----------------------------------------------------------------------------
|
62 |
|
|
-- driven by STIM_access
|
63 |
|
|
signal stim_addr: std_logic_vector(31 downto 0);
|
64 |
|
|
signal stim_write_dat: std_logic_vector(31 downto 0);
|
65 |
|
|
signal rd_req: std_logic := '0';
|
66 |
|
|
signal wr_req: std_logic := '0';
|
67 |
|
|
-----------------------------------------------------------------------------
|
68 |
|
|
-- driven by REG_access
|
69 |
|
|
signal stim_read_dat: std_logic_vector(31 downto 0);
|
70 |
|
|
signal req_ack: std_logic := '0';
|
71 |
|
|
signal open_lfile : std_logic := '0';
|
72 |
|
|
-- the addressable register set
|
73 |
|
|
signal cnt_reg: std_logic_vector(31 downto 0);
|
74 |
|
|
signal seed_reg: std_logic_vector(31 downto 0) := "00010001000111000011000010000100";
|
75 |
|
|
signal config_reg: std_logic_vector(31 downto 0);
|
76 |
|
|
signal errors_reg: std_logic_vector(31 downto 0);
|
77 |
|
|
signal stm_idx : integer;
|
78 |
|
|
signal stm_wdata : std_logic_vector(7 downto 0);
|
79 |
|
|
signal stm_w : std_logic;
|
80 |
|
|
|
81 |
|
|
signal clear_trig: std_logic := '0';
|
82 |
|
|
signal ready : std_logic;
|
83 |
|
|
|
84 |
|
|
|
85 |
|
|
begin
|
86 |
|
|
|
87 |
|
|
output_drive:
|
88 |
|
|
process (STM_IN.rst_n, seed_reg, request, open_lfile, stm_w)
|
89 |
|
|
variable v_dat_array : arr128x8; --<< array type from pgen package
|
90 |
|
|
variable v_tmp_dat : unsigned(7 downto 0);
|
91 |
|
|
variable v_randv : RandomPType;
|
92 |
|
|
variable v_tmp_int : integer;
|
93 |
|
|
variable v_stat : file_open_status;
|
94 |
|
|
variable rline : line;
|
95 |
|
|
variable j : integer;
|
96 |
|
|
variable incp : std_logic;
|
97 |
|
|
variable v_fisopen : boolean := false;
|
98 |
|
|
begin
|
99 |
|
|
-- if we get a request and are enabled
|
100 |
|
|
if((STM_IN.rst_n'event and STM_IN.rst_n = '0') or seed_reg'event) then
|
101 |
|
|
v_tmp_int := to_uninteger(seed_reg);
|
102 |
|
|
v_randv.InitSeed(v_tmp_int);
|
103 |
|
|
packet_out.dout <= (others => (others => '0'));
|
104 |
|
|
packet_out.drdy <= '0';
|
105 |
|
|
incp := '0';
|
106 |
|
|
if(v_fisopen = true) then
|
107 |
|
|
file_close(load_file);
|
108 |
|
|
v_fisopen := false;
|
109 |
|
|
end if;
|
110 |
|
|
elsif(request'event and request = '1' and cnt_reg(0) = '1') then
|
111 |
|
|
case config_reg(3 downto 0) is
|
112 |
|
|
-- inc pattern
|
113 |
|
|
when "0000" =>
|
114 |
|
|
if(incp = '0') then
|
115 |
|
|
v_tmp_dat := (others => '0');
|
116 |
|
|
for i in 0 to v_dat_array'length-1 loop
|
117 |
|
|
v_dat_array(i) := std_logic_vector(v_tmp_dat);
|
118 |
|
|
v_tmp_dat := v_tmp_dat + 1;
|
119 |
|
|
end loop;
|
120 |
|
|
incp := '1';
|
121 |
|
|
end if;
|
122 |
|
|
-- random pattern
|
123 |
|
|
when "0001" =>
|
124 |
|
|
v_tmp_dat := (others => '0');
|
125 |
|
|
for i in 0 to v_dat_array'length-1 loop
|
126 |
|
|
-- v_tmp_int := v_randv.RandInt(0, 255);
|
127 |
|
|
v_dat_array(i) := std_logic_vector(conv_unsigned(v_randv.RandInt(0, 255),8));
|
128 |
|
|
end loop;
|
129 |
|
|
incp := '0';
|
130 |
|
|
-- file load
|
131 |
|
|
when "0010" =>
|
132 |
|
|
j := 0;
|
133 |
|
|
while(not endfile(load_file) and j < v_dat_array'length-1) loop
|
134 |
|
|
readline(load_file, rline);
|
135 |
|
|
v_dat_array(j)(7 downto 4) := c2std_vec(rline(1));
|
136 |
|
|
v_dat_array(j)(3 downto 0) := c2std_vec(rline(2));
|
137 |
|
|
j := j + 1;
|
138 |
|
|
end loop;
|
139 |
|
|
incp := '0';
|
140 |
|
|
-- user input mode, do not generate as user filled through stimulus
|
141 |
|
|
when "0011" =>
|
142 |
|
|
null;
|
143 |
|
|
incp := '0';
|
144 |
|
|
when others =>
|
145 |
|
|
-- do an assert here
|
146 |
|
|
assert(false)
|
147 |
|
|
report "Invalid control mode for Patern Generator, nothing done." & LF
|
148 |
|
|
severity note;
|
149 |
|
|
end case;
|
150 |
|
|
packet_out.dout <= v_dat_array;
|
151 |
|
|
-- if there was an open file event
|
152 |
|
|
elsif(open_lfile'event and open_lfile = '1') then
|
153 |
|
|
-- if a file is open, close it first
|
154 |
|
|
if(v_fisopen = true) then
|
155 |
|
|
file_close(load_file);
|
156 |
|
|
end if;
|
157 |
|
|
-- open the file
|
158 |
|
|
file_open(v_stat, load_file, fname, read_mode);
|
159 |
|
|
assert(v_stat = open_ok)
|
160 |
|
|
report LF & "Error: Unable to open data file " & fname
|
161 |
|
|
severity failure;
|
162 |
|
|
v_fisopen := true;
|
163 |
|
|
-- if there was a stumuls write, write the array index
|
164 |
|
|
elsif(stm_w'event and stm_w = '1') then
|
165 |
|
|
v_dat_array(stm_idx) := stm_wdata;
|
166 |
|
|
end if;
|
167 |
|
|
end process output_drive;
|
168 |
|
|
|
169 |
|
|
-------------------------------------------------------------------------------
|
170 |
|
|
-------------------------------------------------------------------------------
|
171 |
|
|
-- STIM Reg Access process
|
172 |
|
|
REG_access:
|
173 |
|
|
process
|
174 |
|
|
|
175 |
|
|
variable v_temp_int: integer;
|
176 |
|
|
variable v_reload: integer := 0;
|
177 |
|
|
variable v_tmp_int: integer;
|
178 |
|
|
|
179 |
|
|
begin
|
180 |
|
|
-- reset from stimulus system
|
181 |
|
|
if(STM_IN.rst_n'event and STM_IN.rst_n = '0') then
|
182 |
|
|
v_reload := 0;
|
183 |
|
|
stm_w <= '0';
|
184 |
|
|
-- standard registers
|
185 |
|
|
stim_read_dat <= (others => '0');
|
186 |
|
|
req_ack <= '0';
|
187 |
|
|
cnt_reg <= (others => '0');
|
188 |
|
|
config_reg <= (others => '0');
|
189 |
|
|
errors_reg <= (others => '0');
|
190 |
|
|
|
191 |
|
|
-- if is a write access
|
192 |
|
|
elsif(wr_req' event and wr_req = '1') then
|
193 |
|
|
-- create index 0 to 63
|
194 |
|
|
v_temp_int := conv_integer(unsigned(stim_addr(6 downto 0)));
|
195 |
|
|
-- create first level of addressing
|
196 |
|
|
case stim_addr(31 downto 12) is
|
197 |
|
|
-- first level decode
|
198 |
|
|
when "00000000000000000000" =>
|
199 |
|
|
-- create register access level of addressing
|
200 |
|
|
-- seconde level of decode
|
201 |
|
|
case stim_addr(11 downto 0) is
|
202 |
|
|
when "000000000000" =>
|
203 |
|
|
cnt_reg <= stim_write_dat;
|
204 |
|
|
open_lfile <= stim_write_dat(1);
|
205 |
|
|
when "000000000001" =>
|
206 |
|
|
config_reg <= stim_write_dat;
|
207 |
|
|
when "000000000010" =>
|
208 |
|
|
assert(false)
|
209 |
|
|
report ">>>> ERROR: The errors register is read only!!" & LF
|
210 |
|
|
severity note;
|
211 |
|
|
-- errors_reg <= stim_write_dat;
|
212 |
|
|
when "000000000011" =>
|
213 |
|
|
seed_reg <= stim_write_dat;
|
214 |
|
|
|
215 |
|
|
-- when "000000000100" =>
|
216 |
|
|
-- access0_word <= stim_write_dat;
|
217 |
|
|
-- action_trig <= '1';
|
218 |
|
|
-- when "000000000101" =>
|
219 |
|
|
-- access1_word <= stim_write_dat;
|
220 |
|
|
|
221 |
|
|
when others =>
|
222 |
|
|
assert(false)
|
223 |
|
|
report "Out of bounds write attempt in packet_gen " & integer'image(pgen_id) &
|
224 |
|
|
", noting done." & LF
|
225 |
|
|
severity note;
|
226 |
|
|
end case;
|
227 |
|
|
-- array addressing
|
228 |
|
|
when "00000000000000000001" =>
|
229 |
|
|
if(stim_addr(11 downto 7) /= "00000") then
|
230 |
|
|
assert(false)
|
231 |
|
|
report "Out of bounds write attempt in packet_gen " & integer'image(pgen_id) &
|
232 |
|
|
", noting done." & LF
|
233 |
|
|
severity note;
|
234 |
|
|
else
|
235 |
|
|
stm_idx <= v_temp_int;
|
236 |
|
|
stm_wdata <= stim_write_dat(7 downto 0);
|
237 |
|
|
stm_w <= '1';
|
238 |
|
|
end if;
|
239 |
|
|
when others =>
|
240 |
|
|
assert(false)
|
241 |
|
|
report "Out of bounds write attempt in packet_gen " & integer'image(pgen_id) &
|
242 |
|
|
", noting done." & LF
|
243 |
|
|
severity note;
|
244 |
|
|
end case;
|
245 |
|
|
-- acknowlage the request
|
246 |
|
|
req_ack <= '1';
|
247 |
|
|
wait until wr_req'event and wr_req = '0';
|
248 |
|
|
req_ack <= '0';
|
249 |
|
|
|
250 |
|
|
-- if is a read
|
251 |
|
|
elsif (rd_req' event and rd_req = '1') then
|
252 |
|
|
-- create first level of addressing
|
253 |
|
|
case stim_addr(31 downto 12) is
|
254 |
|
|
-- first level decode
|
255 |
|
|
when "00000000000000000000" =>
|
256 |
|
|
-- create register access level of addressing
|
257 |
|
|
-- seconde level of decode
|
258 |
|
|
case stim_addr(11 downto 0) is
|
259 |
|
|
when "000000000010" =>
|
260 |
|
|
stim_read_dat <= errors_reg;
|
261 |
|
|
errors_reg <= (others => '0');
|
262 |
|
|
when "000000000011" =>
|
263 |
|
|
stim_read_dat <= seed_reg;
|
264 |
|
|
|
265 |
|
|
when others =>
|
266 |
|
|
assert(false)
|
267 |
|
|
report "Read Location access ERROR: packet_gen" & integer'image(pgen_id) &
|
268 |
|
|
", noting done." & LF
|
269 |
|
|
severity note;
|
270 |
|
|
end case;
|
271 |
|
|
when others =>
|
272 |
|
|
assert(false)
|
273 |
|
|
report "Read Location access ERROR: packet_gen" & integer'image(pgen_id) &
|
274 |
|
|
", noting done." & LF
|
275 |
|
|
severity note;
|
276 |
|
|
end case;
|
277 |
|
|
-- acknowlage the request
|
278 |
|
|
req_ack <= '1';
|
279 |
|
|
wait until rd_req'event and rd_req = '0';
|
280 |
|
|
req_ack <= '0';
|
281 |
|
|
|
282 |
|
|
end if;
|
283 |
|
|
-- clear the trigger signals
|
284 |
|
|
cnt_reg(1) <= '0';
|
285 |
|
|
open_lfile <= '0';
|
286 |
|
|
stm_w <= '0';
|
287 |
|
|
|
288 |
|
|
wait on rd_req, wr_req, STM_IN.rst_n, clear_trig;
|
289 |
|
|
end process REG_access;
|
290 |
|
|
|
291 |
|
|
-------------------------------------------------------------------------------
|
292 |
|
|
-- STIM Access port processes
|
293 |
|
|
--
|
294 |
|
|
STIM_access:
|
295 |
|
|
process
|
296 |
|
|
begin
|
297 |
|
|
if(STM_IN.rst_n' event and STM_IN.rst_n = '0') then
|
298 |
|
|
STM_OUT <= stm_neut;
|
299 |
|
|
-- if read cycle
|
300 |
|
|
elsif(STM_IN.req_n' event and STM_IN.req_n = '0' and STM_IN.rwn = '1') then
|
301 |
|
|
stim_addr <= STM_IN.addr;
|
302 |
|
|
rd_req <= '1';
|
303 |
|
|
wait until req_ack' event and req_ack = '1';
|
304 |
|
|
STM_OUT.rdat <= stim_read_dat;
|
305 |
|
|
rd_req <= '0';
|
306 |
|
|
wait for 1 ps;
|
307 |
|
|
STM_OUT.ack_n <= '0';
|
308 |
|
|
wait until STM_IN.req_n' event and STM_IN.req_n = '1';
|
309 |
|
|
wait for 1 ps;
|
310 |
|
|
STM_OUT <= stm_neut;
|
311 |
|
|
|
312 |
|
|
-- if Write
|
313 |
|
|
elsif(STM_IN.req_n' event and STM_IN.req_n = '0' and STM_IN.rwn = '0') then
|
314 |
|
|
stim_addr <= STM_IN.addr;
|
315 |
|
|
stim_write_dat <= STM_IN.wdat;
|
316 |
|
|
wr_req <= '1';
|
317 |
|
|
wait until req_ack' event and req_ack = '1';
|
318 |
|
|
wait for 1 ps;
|
319 |
|
|
wr_req <= '0';
|
320 |
|
|
wait for 1 ps;
|
321 |
|
|
STM_OUT.ack_n <= '0';
|
322 |
|
|
wait until STM_IN.req_n' event and STM_IN.req_n = '1';
|
323 |
|
|
wait for 1 ps;
|
324 |
|
|
STM_OUT <= stm_neut;
|
325 |
|
|
end if;
|
326 |
|
|
|
327 |
|
|
STM_OUT.rdy_n <= ready;
|
328 |
|
|
wait on STM_IN.req_n, STM_IN.rst_n, ready;
|
329 |
|
|
end process STIM_access;
|
330 |
|
|
|
331 |
|
|
end bhv;
|