1 |
19 |
sckoarn |
-------------------------------------------------------------------------------
|
2 |
|
|
-- Copyright 2011 Ken Campbell
|
3 |
|
|
-- All Rights Reserved
|
4 |
|
|
-------------------------------------------------------------------------------
|
5 |
|
|
-- $Author: ken $
|
6 |
|
|
--
|
7 |
|
|
-- $date: $
|
8 |
|
|
--
|
9 |
|
|
-- $Id: $
|
10 |
|
|
--
|
11 |
|
|
-- $Source: $
|
12 |
|
|
--
|
13 |
|
|
-- Description :
|
14 |
|
|
-- Code snipets from / for various VHDL Test Bench Facilities.
|
15 |
|
|
--
|
16 |
|
|
-- Contents:
|
17 |
|
|
-- Section 1: Code from Usage Tips: Interrupts and Waiting.
|
18 |
|
|
-- Section 2: Code from CPU emulation: some starter commands
|
19 |
|
|
-- Section 3: Code for internal test bench implementation
|
20 |
|
|
-- Section 4: Code for Verify commands
|
21 |
23 |
sckoarn |
--
|
22 |
19 |
sckoarn |
------------------------------------------------------------------------------
|
23 |
23 |
sckoarn |
-- Redistribution and use in source and binary forms, with or without
|
24 |
|
|
-- modification, in whole or part, are permitted:
|
25 |
19 |
sckoarn |
--
|
26 |
23 |
sckoarn |
-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
27 |
|
|
-- AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
28 |
|
|
-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
29 |
|
|
-- ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
30 |
|
|
-- LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
31 |
|
|
-- CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
32 |
|
|
-- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
33 |
|
|
-- INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
34 |
|
|
-- CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
35 |
|
|
-- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
36 |
|
|
-- POSSIBILITY OF SUCH DAMAGE.
|
37 |
19 |
sckoarn |
-------------------------------------------------------------------------------
|
38 |
|
|
-------------------------------------------------------------------------------------
|
39 |
|
|
--###################################################################################
|
40 |
|
|
-- Section 1: Interrupts and Waiting.
|
41 |
|
|
architecture bhv of tb_xxx is
|
42 |
|
|
-- ...
|
43 |
|
|
constant MAX_TIME : integer := 60000;
|
44 |
|
|
-- ...
|
45 |
|
|
|
46 |
|
|
Read_file : process
|
47 |
|
|
-- ...
|
48 |
|
|
define_instruction(inst_list, "WAIT_IRQ", 0);
|
49 |
|
|
-- ...
|
50 |
|
|
--------------------------------------------------
|
51 |
|
|
elsif (instruction(1 to len) = "WAIT_IRQ") then
|
52 |
|
|
temp_int := 0; -- initialize counter
|
53 |
|
|
while(dut_irq /= '1') then -- while IRQ not asserted
|
54 |
|
|
wait for clk'event and clk = '1'; -- wait for clock cycle
|
55 |
|
|
temp_int := temp_int + 1; -- add one to clock counter
|
56 |
|
|
assert (temp_int /= MAX_TIME) -- if count = max time quit.
|
57 |
|
|
report "Error: Time out while waiting for IRQ!!"
|
58 |
|
|
severity failure;
|
59 |
|
|
end loop;
|
60 |
|
|
|
61 |
|
|
-------------------------------------------------------------------------------------------
|
62 |
|
|
define_instruction(inst_list, "MAX_WAIT_SET", 1);
|
63 |
|
|
-- ...
|
64 |
|
|
--------------------------------------------------------
|
65 |
|
|
elsif (instruction(1 to len) = "MAX_WAIT_SET") then
|
66 |
|
|
MAX_TIME <= par1; -- set the max
|
67 |
|
|
wait for 0 ps;
|
68 |
|
|
|
69 |
|
|
architecture bhv of tb_xxx is
|
70 |
|
|
-- ...
|
71 |
|
|
signal irq_expect : boolean := false;
|
72 |
|
|
-- ...
|
73 |
|
|
Read_file : process
|
74 |
|
|
-- ...
|
75 |
|
|
define_instruction(inst_list, "EXPECT_IRQ", 1);
|
76 |
|
|
-- ...
|
77 |
|
|
--------------------------------------------------------------------------------
|
78 |
|
|
elsif (instruction(1 to len) = "EXPECT_IRQ") then
|
79 |
|
|
if(par1 = 0) then
|
80 |
|
|
irq_expect <= false;
|
81 |
|
|
else
|
82 |
|
|
irq_expect <= true;
|
83 |
|
|
end if;
|
84 |
|
|
wait for 0 ps;
|
85 |
|
|
-- ...
|
86 |
|
|
end process Read_file;
|
87 |
|
|
|
88 |
|
|
------------------------
|
89 |
|
|
irq_mon:
|
90 |
|
|
process(clk, dut_irq)
|
91 |
|
|
begin
|
92 |
|
|
-- on the falling edge, assume rising edge assertion, one clock wide
|
93 |
23 |
sckoarn |
if(clk'event and clk = '0') then
|
94 |
19 |
sckoarn |
if(dut_irq = '1') then
|
95 |
|
|
if(irq_expect = true) then
|
96 |
|
|
assert (false)
|
97 |
|
|
report "NOTE: An expected IRQ occurred."
|
98 |
|
|
severity note;
|
99 |
|
|
else
|
100 |
|
|
assert (false)
|
101 |
|
|
report "ERROR: An unexpected IRQ occurred."
|
102 |
|
|
severity failure;
|
103 |
|
|
end if;
|
104 |
|
|
end if;
|
105 |
|
|
end if;
|
106 |
|
|
end process irq_mon;
|
107 |
|
|
-- END Section 1:
|
108 |
|
|
--###################################################################################
|
109 |
|
|
|
110 |
|
|
|
111 |
|
|
-------------------------------------------------------------------------------------
|
112 |
|
|
--###################################################################################
|
113 |
|
|
-- Section 2: CPU Emulation Commands
|
114 |
|
|
-- starting from the top of the bhv architecture
|
115 |
|
|
architecture bhv of xxx_tb is
|
116 |
|
|
-- create type for cpu array of registers
|
117 |
|
|
-- Type needed for CPU registers, it can be resized if needed
|
118 |
|
|
type cpu_reg_array is array(0 to 7) of std_logic_vector(31 downto 0);
|
119 |
|
|
-- optional constant to help test for zero
|
120 |
|
|
constant zeros : std_logic_vector(31 downto 0) := (others => '0');
|
121 |
|
|
-- ...
|
122 |
|
|
-- ...
|
123 |
|
|
--------------------------------------------------------------------------
|
124 |
|
|
Read_file: process
|
125 |
|
|
-- ... variable definitions
|
126 |
|
|
-------------------
|
127 |
|
|
-- CCR def
|
128 |
|
|
-- bit 0 zero, will be set when results are zero
|
129 |
|
|
-- bit 1 equal, will be set when compared values are equal
|
130 |
|
|
-- bit 2 greater than, will be set when source1 is > source2
|
131 |
|
|
-- bit 3 less than, will be set when source1 is < source2
|
132 |
|
|
-- others undefined
|
133 |
|
|
variable v_reg_ccr : std_logic_vector(7 downto 0); -- condition code register
|
134 |
|
|
variable v_regs : cpu_reg_array; -- Create variable of cpu regs
|
135 |
|
|
variable v_tmp_bit : std_logic; -- nice place to store a bit temp
|
136 |
|
|
variable v_read_data : std_logic_vector(31 downto 0);
|
137 |
|
|
-- ...
|
138 |
|
|
begin -- process Read_file
|
139 |
|
|
-- ...
|
140 |
|
|
define_instruction(inst_list, "READ_TO_REG", 2);
|
141 |
|
|
define_instruction(inst_list, "REG_TO_VAR", 2);
|
142 |
|
|
define_instruction(inst_list, "MOV", 2);
|
143 |
|
|
define_instruction(inst_list, "MOVI", 2);
|
144 |
|
|
define_instruction(inst_list, "AND", 3);
|
145 |
|
|
define_instruction(inst_list, "ANDI", 3);
|
146 |
|
|
define_instruction(inst_list, "OR", 3);
|
147 |
|
|
define_instruction(inst_list, "NOT", 2);
|
148 |
|
|
define_instruction(inst_list, "XOR", 3);
|
149 |
|
|
define_instruction(inst_list, "SLL", 2);
|
150 |
|
|
define_instruction(inst_list, "SLR", 2);
|
151 |
|
|
define_instruction(inst_list, "CMP", 2);
|
152 |
|
|
define_instruction(inst_list, "BE", 1);
|
153 |
|
|
define_instruction(inst_list, "BZ", 1);
|
154 |
|
|
define_instruction(inst_list, "BB", 4);
|
155 |
|
|
|
156 |
|
|
------------------------------------------------------------------------
|
157 |
|
|
-- Read, test, and load the stimulus file
|
158 |
|
|
read_instruction_file(stimulus_file, inst_list, defined_vars, inst_sequ,
|
159 |
|
|
file_list);
|
160 |
|
|
-- initialize last info
|
161 |
|
|
last_sequ_num := 0;
|
162 |
|
|
last_sequ_ptr := inst_sequ;
|
163 |
|
|
-- initialize registers -- this is the zering of the registers and CCR
|
164 |
|
|
v_regs := (others => (others => '0'));
|
165 |
|
|
v_reg_ccr := (others => '0');
|
166 |
|
|
-- ...
|
167 |
|
|
--------------------------------------------------------------------------
|
168 |
|
|
-- READ_TO_REG
|
169 |
|
|
-- Read a addressed location to the local register array
|
170 |
|
|
-- par1 address
|
171 |
|
|
-- par2 target reg (index)
|
172 |
|
|
elsif(instruction(1 to len) = "READ_TO_REG") then
|
173 |
|
|
v_temp_vec1 := std_logic_vector(conv_unsigned(par1, 32));
|
174 |
|
|
STM_ADD <= v_temp_vec1;
|
175 |
|
|
STM_DAT <= (others => 'Z');
|
176 |
|
|
STM_RWN <= '1';
|
177 |
|
|
wait for 1 ps;
|
178 |
|
|
STM_REQ_N <= '0';
|
179 |
|
|
wait until STM_ACK_N'event and STM_ACK_N = '0';
|
180 |
|
|
STM_REQ_N <= '1';
|
181 |
|
|
STM_ADD <= (others => 'Z');
|
182 |
|
|
v_read_data := STM_DAT;
|
183 |
|
|
v_regs(par2) := STM_DAT;
|
184 |
|
|
STM_RWN <= '1';
|
185 |
|
|
wait for 1 ps;
|
186 |
23 |
sckoarn |
|
187 |
19 |
sckoarn |
--------------------------------------------------------------------------
|
188 |
|
|
-- REG_TO_VAR
|
189 |
|
|
-- Write a register array value to a Variable.
|
190 |
|
|
-- par1 target reg (index)
|
191 |
|
|
-- par2 Variable to update with value from target reg
|
192 |
|
|
elsif(instruction(1 to len) = "REG_TO_VAR") then
|
193 |
|
|
temp_int := to_uninteger(v_regs(par1)); --<< NEW to_uninteger conversion function
|
194 |
|
|
update_variable(defined_vars, par2, temp_int, valid);
|
195 |
|
|
-- the to_uninteger function was added because to add the function through
|
196 |
|
|
-- std_developerskit overflowed my PE student simulator. I am tired of
|
197 |
|
|
-- conversion and created my own function, tb_pkg contained. see additional
|
198 |
|
|
-- code at the bottom of this section. You can replace this with functions
|
199 |
|
|
-- you usually use, or use std_developerskit if you are on real tools.
|
200 |
|
|
--------------------------------------------------------------------------
|
201 |
|
|
-- MOV
|
202 |
|
|
-- Move one register contents to another register. Source contents maintained
|
203 |
|
|
-- par1 reg1 index
|
204 |
|
|
-- par2 reg2 index
|
205 |
|
|
elsif(instruction(1 to len) = "MOV") then
|
206 |
|
|
v_regs(par2) := v_regs(par1);
|
207 |
23 |
sckoarn |
|
208 |
19 |
sckoarn |
--------------------------------------------------------------------------
|
209 |
|
|
-- MOVI
|
210 |
|
|
-- Move value passed to destination register
|
211 |
|
|
-- par1 value
|
212 |
|
|
-- par2 reg index
|
213 |
|
|
elsif(instruction(1 to len) = "MOVI") then
|
214 |
|
|
v_regs(par2) := std_logic_vector(conv_unsigned(par1, 32));
|
215 |
23 |
sckoarn |
|
216 |
19 |
sckoarn |
--------------------------------------------------------------------------
|
217 |
|
|
-- AND
|
218 |
|
|
-- AND two registers and write results to target register
|
219 |
|
|
-- par1 reg1 index
|
220 |
|
|
-- par2 reg2 index
|
221 |
|
|
-- par3 target results reg index
|
222 |
|
|
elsif(instruction(1 to len) = "AND") then
|
223 |
|
|
v_regs(par3) := v_regs(par1) and v_regs(par2);
|
224 |
|
|
if(v_regs(par3) = zeros) then
|
225 |
|
|
v_reg_ccr(0) := '1';
|
226 |
|
|
else
|
227 |
|
|
v_reg_ccr(0) := '0';
|
228 |
|
|
end if;
|
229 |
|
|
|
230 |
|
|
--------------------------------------------------------------------------
|
231 |
|
|
-- ANDI
|
232 |
|
|
-- AND the passed value with the indexed register and store in register index
|
233 |
|
|
-- par1 value
|
234 |
|
|
-- par2 reg index
|
235 |
|
|
-- par3 target results reg index
|
236 |
|
|
elsif(instruction(1 to len) = "ANDI") then
|
237 |
|
|
v_regs(par3) := std_logic_vector(conv_unsigned(par1, 32)) and v_regs(par2);
|
238 |
|
|
if(v_regs(par3) = zeros) then
|
239 |
|
|
v_reg_ccr(0) := '1';
|
240 |
|
|
else
|
241 |
|
|
v_reg_ccr(0) := '0';
|
242 |
|
|
end if;
|
243 |
|
|
|
244 |
|
|
--------------------------------------------------------------------------
|
245 |
|
|
-- OR
|
246 |
|
|
-- OR two registers and write results to target register
|
247 |
|
|
-- par1 reg1 index
|
248 |
|
|
-- par2 reg2 index
|
249 |
|
|
-- par3 target results reg index
|
250 |
|
|
elsif(instruction(1 to len) = "OR") then
|
251 |
|
|
v_regs(par3) := v_regs(par1) or v_regs(par2);
|
252 |
|
|
if(v_regs(par3) = zeros) then
|
253 |
|
|
v_reg_ccr(0) := '1';
|
254 |
|
|
else
|
255 |
|
|
v_reg_ccr(0) := '0';
|
256 |
|
|
end if;
|
257 |
|
|
|
258 |
|
|
--------------------------------------------------------------------------
|
259 |
|
|
-- XOR
|
260 |
|
|
-- XOR two registers and write results to target register
|
261 |
|
|
-- par1 reg1 index
|
262 |
|
|
-- par2 reg2 index
|
263 |
|
|
-- par3 target results reg index
|
264 |
|
|
elsif(instruction(1 to len) = "XOR") then
|
265 |
|
|
v_regs(par3) := v_regs(par1) xor v_regs(par2);
|
266 |
|
|
if(v_regs(par3) = zeros) then
|
267 |
|
|
v_reg_ccr(0) := '1';
|
268 |
|
|
else
|
269 |
|
|
v_reg_ccr(0) := '0';
|
270 |
|
|
end if;
|
271 |
|
|
|
272 |
|
|
--------------------------------------------------------------------------
|
273 |
|
|
-- NOT
|
274 |
|
|
-- NOT a register and write results to target register
|
275 |
|
|
-- par1 reg1 index
|
276 |
|
|
-- par2 target results reg index
|
277 |
|
|
elsif(instruction(1 to len) = "NOT") then
|
278 |
|
|
v_regs(par2) := not v_regs(par1);
|
279 |
|
|
if(v_regs(par2) = zeros) then
|
280 |
|
|
v_reg_ccr(0) := '1';
|
281 |
|
|
else
|
282 |
|
|
v_reg_ccr(0) := '0';
|
283 |
|
|
end if;
|
284 |
|
|
|
285 |
|
|
--------------------------------------------------------------------------
|
286 |
|
|
-- SLL
|
287 |
|
|
-- Shift the register left rotate the upper bits into the lower bits
|
288 |
|
|
-- par1 reg1 index
|
289 |
|
|
-- par2 bit positions to Left
|
290 |
|
|
elsif(instruction(1 to len) = "SLL") then
|
291 |
|
|
v_temp_vec1 := v_regs(par1);
|
292 |
|
|
temp_int := par2 - 1;
|
293 |
|
|
v_regs(par1) := v_temp_vec1(31-par2 downto 0) & v_temp_vec1(31 downto 31 - temp_int);
|
294 |
23 |
sckoarn |
|
295 |
19 |
sckoarn |
--------------------------------------------------------------------------
|
296 |
|
|
-- SLR
|
297 |
|
|
-- Shift the register right rotate the lower bits into the upper bits
|
298 |
|
|
-- par1 reg1 index
|
299 |
|
|
-- par2 bit positions to Right
|
300 |
|
|
elsif(instruction(1 to len) = "SLR") then
|
301 |
|
|
v_temp_vec1 := v_regs(par1);
|
302 |
|
|
temp_int := par2 - 1;
|
303 |
|
|
v_regs(par1) := v_temp_vec1(temp_int downto 0) & v_temp_vec1(31 downto par2);
|
304 |
23 |
sckoarn |
|
305 |
19 |
sckoarn |
--------------------------------------------------------------------------
|
306 |
|
|
-- CMP
|
307 |
|
|
-- Compare one register against another and set CCR bits, no effect on registers
|
308 |
|
|
-- par1 reg1 index source1
|
309 |
|
|
-- par2 reg2 index source2
|
310 |
|
|
elsif(instruction(1 to len) = "CMP") then
|
311 |
|
|
v_reg_ccr := (others => '0');
|
312 |
|
|
if(v_regs(par1) = v_regs(par2)) then
|
313 |
|
|
v_reg_ccr(1) := '1';
|
314 |
|
|
elsif(v_regs(par1) > v_regs(par2)) then
|
315 |
|
|
v_reg_ccr(2) := '1';
|
316 |
|
|
elsif(v_regs(par1) < v_regs(par2)) then
|
317 |
|
|
v_reg_ccr(3) := '1';
|
318 |
|
|
end if;
|
319 |
23 |
sckoarn |
|
320 |
19 |
sckoarn |
if(v_regs(par1) = zeros) then
|
321 |
|
|
v_reg_ccr(1) := '0';
|
322 |
|
|
end if;
|
323 |
23 |
sckoarn |
|
324 |
19 |
sckoarn |
--------------------------------------------------------------------------
|
325 |
|
|
-- BE
|
326 |
|
|
-- Branch if equal
|
327 |
|
|
-- par1 jump location
|
328 |
|
|
elsif(instruction(1 to len) = "BE") then
|
329 |
|
|
if(v_reg_ccr(1) = '1') then
|
330 |
|
|
v_line := par1 - 1;
|
331 |
|
|
wh_state := false;
|
332 |
|
|
wh_stack := (others => 0);
|
333 |
|
|
wh_dpth := 0;
|
334 |
|
|
wh_ptr := 0;
|
335 |
|
|
--stack := (others => 0);
|
336 |
|
|
--stack_ptr := 0;
|
337 |
23 |
sckoarn |
end if;
|
338 |
|
|
|
339 |
19 |
sckoarn |
--------------------------------------------------------------------------
|
340 |
|
|
-- BZ
|
341 |
|
|
-- Branch if Zero
|
342 |
|
|
-- par1 jump location
|
343 |
|
|
elsif(instruction(1 to len) = "BZ") then
|
344 |
|
|
if(v_reg_ccr(0) = '1') then
|
345 |
|
|
v_line := par1 - 1;
|
346 |
|
|
wh_state := false;
|
347 |
|
|
wh_stack := (others => 0);
|
348 |
|
|
wh_dpth := 0;
|
349 |
|
|
wh_ptr := 0;
|
350 |
|
|
--stack := (others => 0);
|
351 |
|
|
--stack_ptr := 0;
|
352 |
23 |
sckoarn |
end if;
|
353 |
|
|
|
354 |
19 |
sckoarn |
--------------------------------------------------------------------------
|
355 |
|
|
-- BB
|
356 |
|
|
-- Branch if bit in register is set/clear
|
357 |
|
|
-- par1 register
|
358 |
|
|
-- par2 register bit index
|
359 |
|
|
-- par3 compare value : 0/1
|
360 |
|
|
-- par4 jump location
|
361 |
|
|
elsif(instruction(1 to len) = "BB") then
|
362 |
|
|
v_temp_vec1 := v_regs(par1);
|
363 |
|
|
if(par3 = 0) then
|
364 |
|
|
v_tmp_bit := '0';
|
365 |
|
|
else
|
366 |
|
|
v_tmp_bit := '1';
|
367 |
|
|
end if;
|
368 |
|
|
if(v_temp_vec1(par2) = v_tmp_bit) then
|
369 |
|
|
v_line := par4 - 1;
|
370 |
|
|
wh_state := false;
|
371 |
|
|
wh_stack := (others => 0);
|
372 |
|
|
wh_dpth := 0;
|
373 |
|
|
wh_ptr := 0;
|
374 |
|
|
--stack := (others => 0);
|
375 |
|
|
--stack_ptr := 0;
|
376 |
23 |
sckoarn |
end if;
|
377 |
19 |
sckoarn |
-- ...
|
378 |
23 |
sckoarn |
end process Read_file;
|
379 |
19 |
sckoarn |
end bhv;
|
380 |
|
|
-- Stimulus_file commands used for testing. I used no VERIFY command
|
381 |
|
|
-- as I watched the functionality in single stepping through code.
|
382 |
|
|
DEFINE_VAR dat x01
|
383 |
|
|
EQU_VAR dat x12345678
|
384 |
|
|
MASTR_WRITE 3 $dat
|
385 |
|
|
READ_TO_REG 3 0
|
386 |
|
|
OR 0 1 2
|
387 |
|
|
AND 0 2 1
|
388 |
|
|
MOV 1 3
|
389 |
|
|
XOR 0 1 4
|
390 |
|
|
NOT 4 5
|
391 |
|
|
SLL 0 1
|
392 |
|
|
SLL 1 2
|
393 |
|
|
SLL 2 3
|
394 |
|
|
SLL 3 4
|
395 |
|
|
SLR 0 1
|
396 |
|
|
SLR 1 2
|
397 |
|
|
SLR 2 3
|
398 |
|
|
SLR 3 4
|
399 |
|
|
MOVI x87654321 7
|
400 |
|
|
|
401 |
|
|
ANDI 0 0 0
|
402 |
|
|
BZ $B1
|
403 |
|
|
MOVI x1234678 0
|
404 |
|
|
|
405 |
|
|
B1:
|
406 |
|
|
CMP 1 2
|
407 |
|
|
BE $B2
|
408 |
|
|
MOVI 0 1
|
409 |
|
|
|
410 |
|
|
B2:
|
411 |
|
|
BB 0 0 1 $B3
|
412 |
|
|
BB 0 0 0 $B3 "Didnt jup as expected
|
413 |
|
|
MOVI 0 1
|
414 |
|
|
|
415 |
|
|
B3:
|
416 |
|
|
|
417 |
|
|
FINISH
|
418 |
|
|
|
419 |
|
|
--------------------------------------------------------------------------------
|
420 |
|
|
-- tb_pkg function
|
421 |
|
|
--- header section
|
422 |
|
|
-------------------------------------------------------------------------
|
423 |
|
|
-- convert a std_logic_vector to an unsigned integer
|
424 |
|
|
function to_uninteger ( constant vect : in std_logic_vector
|
425 |
|
|
) return integer;
|
426 |
|
|
-- body section
|
427 |
|
|
---------------------------------------------------------------------------------------
|
428 |
|
|
function to_uninteger ( constant vect : in std_logic_vector
|
429 |
|
|
) return integer is
|
430 |
|
|
variable result : integer := 0;
|
431 |
|
|
variable len : integer := vect'length;
|
432 |
|
|
variable idx : integer;
|
433 |
|
|
variable tmp_str : text_field;
|
434 |
|
|
variable file_name: text_line;
|
435 |
|
|
begin
|
436 |
|
|
-- point to start of string
|
437 |
|
|
idx := 1;
|
438 |
|
|
-- convert std_logic_vector to text_field
|
439 |
|
|
for i in len - 1 downto 0 loop
|
440 |
|
|
if(vect(i) = '1') then
|
441 |
|
|
tmp_str(idx) := '1';
|
442 |
|
|
elsif(vect(i) = '0') then
|
443 |
|
|
tmp_str(idx) := '0';
|
444 |
|
|
else
|
445 |
|
|
assert(false)
|
446 |
|
|
report LF & "ERROR: Non 0/1 value found in std_logic_vector passed to to_uninteger function!!" & LF &
|
447 |
|
|
"Returning 0."
|
448 |
|
|
severity note;
|
449 |
|
|
return result;
|
450 |
|
|
end if;
|
451 |
|
|
idx := idx + 1;
|
452 |
|
|
end loop;
|
453 |
|
|
-- call bin txt to int fuction with dummy fn and sequ idx
|
454 |
|
|
result := bin2integer(tmp_str, file_name, idx);
|
455 |
|
|
return result;
|
456 |
23 |
sckoarn |
|
457 |
19 |
sckoarn |
end to_uninteger;
|
458 |
|
|
|
459 |
|
|
|
460 |
23 |
sckoarn |
|
461 |
19 |
sckoarn |
-- Section 2: END
|
462 |
|
|
--###################################################################################
|
463 |
|
|
|
464 |
23 |
sckoarn |
--
|
465 |
19 |
sckoarn |
--###################################################################################
|
466 |
|
|
-- Section 3: Begin
|
467 |
|
|
-- This section presents the code needed to make an internal test bench
|
468 |
|
|
-- an optional compile item through the use of VHDL generics and generate
|
469 |
23 |
sckoarn |
-- statements.
|
470 |
19 |
sckoarn |
|
471 |
|
|
-- this is the top enity or at the level where you can assign the
|
472 |
|
|
-- en_bfm generic and it makes sense
|
473 |
|
|
entity my_top_dut is
|
474 |
|
|
generic (
|
475 |
|
|
g_en_bfm : integer := 0
|
476 |
|
|
);
|
477 |
|
|
port (
|
478 |
|
|
-- top port definitions
|
479 |
|
|
);
|
480 |
|
|
end enity my_top_dut;
|
481 |
|
|
|
482 |
|
|
|
483 |
|
|
architecture struct of my_top_dut is
|
484 |
|
|
-- this is the component of an internal block of my_top_dut
|
485 |
|
|
component rtl_block
|
486 |
|
|
port (
|
487 |
|
|
reset_n : in std_logic;
|
488 |
|
|
clk_in : in std_logic;
|
489 |
|
|
-- ...
|
490 |
|
|
);
|
491 |
|
|
end component;
|
492 |
|
|
-- bhv_block has the same pin out as rtl_block, except for the generic
|
493 |
|
|
component bhv_block
|
494 |
|
|
generic (
|
495 |
|
|
stimulus_file: in string
|
496 |
|
|
);
|
497 |
|
|
port (
|
498 |
|
|
reset_n : in std_logic;
|
499 |
|
|
clk_in : in std_logic;
|
500 |
|
|
-- ...
|
501 |
|
|
);
|
502 |
|
|
end component;
|
503 |
|
|
--....
|
504 |
|
|
begin
|
505 |
|
|
-- if generic is default value, include rtl
|
506 |
|
|
if(g_en_bfm = 0) generate
|
507 |
|
|
begin
|
508 |
|
|
rtl_b1: rtl_block
|
509 |
|
|
port map(
|
510 |
|
|
reset_n => reset_n,
|
511 |
|
|
clk_in => clk,
|
512 |
|
|
-- ...
|
513 |
|
|
);
|
514 |
|
|
end generate;
|
515 |
|
|
-- if generic is set for bhv, include it
|
516 |
|
|
if(g_en_bfm = 1) generate
|
517 |
|
|
begin
|
518 |
|
|
bfm: bhv_block
|
519 |
|
|
generic map(
|
520 |
|
|
stimulus_file => "stm/stimulus_file.stm"
|
521 |
|
|
)
|
522 |
|
|
port map(
|
523 |
|
|
reset_n => reset_n,
|
524 |
|
|
clk_in => clk,
|
525 |
|
|
-- ...
|
526 |
|
|
);
|
527 |
|
|
end generate;
|
528 |
|
|
-- ...
|
529 |
|
|
end struct;
|
530 |
|
|
|
531 |
|
|
-- Section 3 End:
|
532 |
|
|
--###################################################################
|
533 |
|
|
|
534 |
|
|
--####################################################################
|
535 |
|
|
-- Section 4 Start:
|
536 |
|
|
-- This section provides some example VERIFY commands.
|
537 |
|
|
--------------------------------------------------------------------------
|
538 |
|
|
Read_file: process
|
539 |
|
|
-- ...
|
540 |
|
|
variable v_tmp_bit : std_logic;
|
541 |
|
|
variable v_upb : integer := 31; -- upper bounds
|
542 |
|
|
variable v_lob : integer := 0; -- lower bounds
|
543 |
|
|
variable v_temp_read : std_logic_vector(31 downto 0);
|
544 |
|
|
-- ...
|
545 |
|
|
define_instruction(inst_list, "SLICE_SET", 2);
|
546 |
|
|
define_instruction(inst_list, "VERIFY", 1);
|
547 |
|
|
define_instruction(inst_list, "VERIFY_BIT", 2);
|
548 |
|
|
define_instruction(inst_list, "VERIFY_SLICE", 1);
|
549 |
|
|
-- ...
|
550 |
|
|
|
551 |
23 |
sckoarn |
|
552 |
19 |
sckoarn |
-----------------------------------------------------------------------------
|
553 |
|
|
-- SLICE_SET set the slice of the data for testing
|
554 |
|
|
-- par1 upper bound value - must be larger than par2 and less than 32
|
555 |
|
|
-- par2 lower bound value
|
556 |
|
|
elsif (instruction(1 to len) = "SLICE_SET") then
|
557 |
|
|
-- test user input.
|
558 |
|
|
assert (par1 < 32 and par1 >= 1)
|
559 |
|
|
report LF & "ERROR: Par1 in SLICE_SET command input range is out of bounds" & LF &
|
560 |
|
|
"Found on line " & (integer'image(file_line)) & " in file " & file_name
|
561 |
|
|
severity failure;
|
562 |
|
|
assert (par2 < 31 and par2 >= 0)
|
563 |
|
|
report LF & "ERROR: Par2 in SLICE_SET command input range is out of bounds" & LF &
|
564 |
|
|
"Found on line " & (integer'image(file_line)) & " in file " & file_name
|
565 |
|
|
severity failure;
|
566 |
|
|
assert (par1 > par2)
|
567 |
|
|
report LF & "ERROR: SLICE_SET command bounds incorrectly defined. Par1 must be greater than Par2." & LF &
|
568 |
|
|
"Found on line " & (integer'image(file_line)) & " in file " & file_name
|
569 |
|
|
severity failure;
|
570 |
|
|
-- update variables
|
571 |
|
|
v_upb := par1;
|
572 |
|
|
v_lob := par2;
|
573 |
23 |
sckoarn |
|
574 |
19 |
sckoarn |
-----------------------------------------------------------------------------
|
575 |
|
|
-- VERIFY test that the data in temp_read is the passed value.
|
576 |
|
|
-- par1 value to test against.
|
577 |
|
|
elsif (instruction(1 to len) = "VERIFY") then
|
578 |
|
|
v_temp_vec1 := std_logic_vector(conv_unsigned(par1, 32));
|
579 |
23 |
sckoarn |
|
580 |
19 |
sckoarn |
assert (v_temp_vec1 = v_temp_read)
|
581 |
|
|
report LF & "ERROR: VERIFY command compare value was not as expected!!" &
|
582 |
|
|
LF & "Got " & (to_hstring(v_temp_read)) &
|
583 |
|
|
LF & "Expected " & (to_hstring(v_temp_vec1)) & LF &
|
584 |
|
|
"Found on line " & (integer'image(file_line)) & " in file " & file_name
|
585 |
|
|
severity failure;
|
586 |
23 |
sckoarn |
|
587 |
19 |
sckoarn |
-----------------------------------------------------------------------------
|
588 |
|
|
-- VERIFY_BIT test that the data bit in temp_read is the passed value.
|
589 |
|
|
-- par1 index into 32 bit temp_read
|
590 |
|
|
-- par2 bit value
|
591 |
|
|
elsif (instruction(1 to len) = "VERIFY_BIT") then
|
592 |
|
|
assert (par1 >= 0 and par1 < 32)
|
593 |
|
|
report LF & "ERROR: VERIFY_BIT command bit index is out of range. Valid is 0 - 31." & LF &
|
594 |
|
|
"Found on line " & (integer'image(file_line)) & " in file " & file_name
|
595 |
|
|
severity failure;
|
596 |
|
|
if(par2 = 0) then
|
597 |
|
|
v_tmp_bit := '0';
|
598 |
|
|
else
|
599 |
|
|
v_tmp_bit := '1';
|
600 |
|
|
end if;
|
601 |
|
|
assert (v_temp_read(par1) = v_tmp_bit)
|
602 |
|
|
report LF & "ERROR: VERIFY_BIT command miss-compare!" & LF &
|
603 |
|
|
"We tested for " & (integer'image(par2)) & LF &
|
604 |
|
|
"Found on line " & (integer'image(file_line)) & " in file " & file_name
|
605 |
|
|
severity failure;
|
606 |
23 |
sckoarn |
|
607 |
19 |
sckoarn |
-----------------------------------------------------------------------------
|
608 |
|
|
-- VERIFY_SLICE test that the data in temp_read is the passed value.
|
609 |
|
|
-- par1 value
|
610 |
|
|
elsif (instruction(1 to len) = "VERIFY_SLICE") then
|
611 |
|
|
v_temp_vec1 := (others => '0');
|
612 |
|
|
temp_int := v_upb - v_lob + 1;
|
613 |
|
|
v_temp_vec1(v_upb downto v_lob) := std_logic_vector(conv_unsigned(par1, temp_int));
|
614 |
|
|
-- no need to test ranges here
|
615 |
|
|
assert (v_temp_vec1(v_upb downto v_lob) = v_temp_read(v_upb downto v_lob))
|
616 |
|
|
report LF & "ERROR: VERIFY_SLICE Compare Value was not as expected!!" &
|
617 |
|
|
LF & "Got " & (to_hstring(v_temp_read(v_upb downto v_lob))) &
|
618 |
|
|
LF & "Expected " & (to_hstring(v_temp_vec1(v_upb downto v_lob))) & LF &
|
619 |
|
|
"Found on line " & (integer'image(file_line)) & " in file " & file_name
|
620 |
|
|
severity failure;
|
621 |
23 |
sckoarn |
|
622 |
19 |
sckoarn |
-- END Section 4
|
623 |
|
|
--#######################################################################################
|