Skip to content

Commit d5ed0e1

Browse files
committed
Added support for randomized bus values when AXI stream master is inactive.
1 parent eabe333 commit d5ed0e1

4 files changed

Lines changed: 158 additions & 102 deletions

File tree

vunit/vhdl/verification_components/src/axi_pkg.vhd

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,12 @@ package axi_pkg is
2424
subtype axi4_size_t is std_logic_vector(2 downto 0);
2525

2626
-- This policy controls what value the bus signals are assigned when not driving valid
27-
-- data. All zeros, all ones, all unknown values, or holding last valid value.
27+
-- data. All zeros, all ones, all unknown values, holding last valid value, or
28+
-- random zeros and ones.
2829

2930
-- 'X' violates the all lower case naming rule but is kept to match the corresponding
3031
-- std_logic value it represents.
3132
-- vsg_off type_500
32-
type inactive_bus_policy_t is ('0', '1', 'X', hold);
33+
type inactive_bus_policy_t is ('0', '1', 'X', hold, rand01);
3334
-- vsg_on
3435
end package;

vunit/vhdl/verification_components/src/axi_stream_master.vhd

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,8 @@ begin
161161
s <= (s'range => '1');
162162
when hold =>
163163
null;
164+
when rand01 =>
165+
s <= rnd.RandSlv(s'length);
164166
end case;
165167
end;
166168

@@ -175,6 +177,8 @@ begin
175177
s <= '1';
176178
when hold =>
177179
null;
180+
when rand01 =>
181+
s <= to_stdulogic(rnd.RandBit);
178182
end case;
179183
end;
180184

vunit/vhdl/verification_components/src/axi_stream_pkg.vhd

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -987,7 +987,8 @@ package body axi_stream_pkg is
987987
impure function p_to_stall_config(vec : integer_vector_ptr_t) return stall_config_t is
988988
variable stall_config : stall_config_t;
989989
begin
990-
stall_config.stall_probability := real(get(vec, stall_probability_idx)) * (2.0 ** (-single_precision_mantissa_length));
990+
stall_config.stall_probability := real(get(vec, stall_probability_idx)) *
991+
(2.0 ** (-single_precision_mantissa_length));
991992
stall_config.min_stall_cycles := get(vec, min_stall_idx);
992993
stall_config.max_stall_cycles := get(vec, max_stall_idx);
993994

@@ -1018,7 +1019,7 @@ package body axi_stream_pkg is
10181019
send(net, slave.p_actor, msg);
10191020
end;
10201021

1021-
procedure get_stall_config(
1022+
procedure get_stall_config(
10221023
signal net : inout network_t;
10231024
slave : axi_stream_slave_t;
10241025
stall_config : out stall_config_t

vunit/vhdl/verification_components/test/tb_axi_stream.vhd

Lines changed: 148 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ use work.sync_pkg.all;
2020

2121
library osvvm;
2222
use osvvm.RandomPkg.all;
23+
use osvvm.CoveragePkg.all;
2324

2425
entity tb_axi_stream is
2526
generic(
@@ -133,6 +134,7 @@ begin
133134
variable previous_inactive_policy : inactive_bus_policy_t := 'X';
134135
variable inactive_policy_read_back : inactive_bus_policy_t;
135136
variable loop_count : natural := 0;
137+
variable cov : CoverageIDType;
136138

137139
impure function select_policy(
138140
modified_signal, signal_to_check : axi_stream_signal_t;
@@ -154,33 +156,86 @@ begin
154156
check(is_already_handled(msg_type));
155157
end;
156158

157-
procedure check(inactive_data, packet_data : std_logic_vector; inactive_policy : inactive_bus_policy_t) is
159+
function to_sl(policy : inactive_bus_policy_t) return std_logic is
158160
begin
159-
if inactive_policy = '0' then
160-
check_equal(inactive_data, std_logic_vector'((inactive_data'range => '0')));
161-
elsif inactive_policy = '1' then
162-
check_equal(inactive_data, std_logic_vector'((inactive_data'range => '1')));
163-
elsif inactive_policy = 'X' then
164-
check_equal(inactive_data, std_logic_vector'((inactive_data'range => 'X')));
165-
elsif inactive_policy = hold then
161+
if policy = '0' then
162+
return '0';
163+
elsif policy = '1' then
164+
return '1';
165+
elsif policy = 'X' then
166+
return 'X';
167+
end if;
168+
169+
check_failed("Cannot convert inactive_bus_policy " & inactive_bus_policy_t'image(policy) & " to std_logic.");
170+
return 'U';
171+
end;
172+
173+
procedure check(
174+
add_to_coverage : boolean;
175+
inactive_data, packet_data : std_logic;
176+
inactive_policy : inactive_bus_policy_t
177+
) is
178+
begin
179+
if inactive_policy = hold then
166180
check_equal(inactive_data, packet_data);
181+
elsif inactive_policy = rand01 then
182+
check_not_unknown(inactive_data);
167183
else
168-
check_failed;
184+
check_equal(inactive_data, to_sl(inactive_policy));
185+
end if;
186+
187+
if add_to_coverage then
188+
if inactive_policy = rand01 then
189+
-- Randomized bits should cover '0' (bin 0) and '1' (bin 1).
190+
ICover(cov, to_integer(inactive_data));
191+
else
192+
-- Non-randomized bits are immediately covered.
193+
ICover(cov, 0);
194+
ICover(cov, 1);
195+
end if;
169196
end if;
170197
end;
171198

172-
procedure check(inactive_data, packet_data : std_logic; inactive_policy : inactive_bus_policy_t) is
199+
procedure check(
200+
add_to_coverage : boolean;
201+
inactive_data, packet_data : std_logic_vector;
202+
inactive_policy : inactive_bus_policy_t
203+
) is
173204
begin
174-
if inactive_policy = '0' then
175-
check_equal(inactive_data, '0');
176-
elsif inactive_policy = '1' then
177-
check_equal(inactive_data, '1');
178-
elsif inactive_policy = 'X' then
179-
check_equal(inactive_data, 'X');
180-
elsif inactive_policy = hold then
205+
if inactive_data'length = 1 then
206+
check(
207+
add_to_coverage,
208+
inactive_data(inactive_data'left),
209+
packet_data(packet_data'left),
210+
inactive_policy
211+
);
212+
return;
213+
end if;
214+
215+
if inactive_policy = hold then
181216
check_equal(inactive_data, packet_data);
217+
elsif inactive_policy = rand01 then
218+
check_not_unknown(inactive_data);
182219
else
183-
check_failed;
220+
check_equal(inactive_data, std_logic_vector'((inactive_data'range => to_sl(inactive_policy))));
221+
end if;
222+
223+
if add_to_coverage then
224+
if inactive_policy = rand01 then
225+
-- Randomized vectors should cover values whose bits are not all the same (bin 0), and
226+
-- not the packet data (bin 1).
227+
if inactive_data /= (inactive_data'range => '0') and inactive_data /= (inactive_data'range => '1') then
228+
ICover(cov, 0);
229+
end if;
230+
231+
if inactive_data /= packet_data then
232+
ICover(cov, 1);
233+
end if;
234+
else
235+
-- Non-randomized vectors are immediately covered.
236+
ICover(cov, 0);
237+
ICover(cov, 1);
238+
end if;
184239
end if;
185240
end;
186241

@@ -777,6 +832,7 @@ begin
777832
disable(get_logger("monitor:rule 10"), error);
778833
disable(get_logger("master:rule 10"), error);
779834
disable(get_logger("slave:rule 10"), error);
835+
780836
for inactive_policy in inactive_bus_policy_t'left to inactive_bus_policy_t'right loop
781837
for axi_stream_signal in work.axi_stream_pkg.tuser downto work.axi_stream_pkg.tdata loop
782838
set_inactive_axi_stream_policy(net, master_axi_stream, inactive_policy, axi_stream_signal);
@@ -788,71 +844,76 @@ begin
788844
tid => x"11", tdest => x"22", tuser => x"33"
789845
);
790846
last := '1' when axi_stream_transaction.tlast else '0';
791-
push_axi_stream(
792-
net,
793-
master_axi_stream,
794-
tdata => axi_stream_transaction.tdata,
795-
tlast => last,
796-
tkeep => axi_stream_transaction.tkeep,
797-
tstrb => axi_stream_transaction.tstrb,
798-
tid => axi_stream_transaction.tid,
799-
tdest => axi_stream_transaction.tdest,
800-
tuser => axi_stream_transaction.tuser
801-
);
802847

803-
pop_axi_stream(net, slave_axi_stream, data, last, keep, strb, id, dest, user);
804-
wait until rising_edge(aclk);
805-
for sig in work.axi_stream_pkg.tdata to work.axi_stream_pkg.tuser loop
806-
case sig is
807-
when work.axi_stream_pkg.tdata =>
808-
check(
809-
tdata,
810-
axi_stream_transaction.tdata,
811-
select_policy(axi_stream_signal, work.axi_stream_pkg.tdata, inactive_policy, previous_inactive_policy)
812-
);
813-
when work.axi_stream_pkg.tlast =>
814-
check(
815-
tlast,
816-
last,
817-
select_policy(axi_stream_signal, work.axi_stream_pkg.tlast, inactive_policy, previous_inactive_policy)
818-
);
819-
when work.axi_stream_pkg.tkeep =>
820-
check(
821-
tkeep,
822-
axi_stream_transaction.tkeep,
823-
select_policy(axi_stream_signal, work.axi_stream_pkg.tkeep, inactive_policy, previous_inactive_policy)
824-
);
825-
when work.axi_stream_pkg.tstrb =>
826-
check(
827-
tstrb,
828-
axi_stream_transaction.tstrb,
829-
select_policy(axi_stream_signal, work.axi_stream_pkg.tstrb, inactive_policy, previous_inactive_policy)
830-
);
831-
when work.axi_stream_pkg.tid =>
832-
check(
833-
tid,
834-
axi_stream_transaction.tid,
835-
select_policy(axi_stream_signal, work.axi_stream_pkg.tid, inactive_policy, previous_inactive_policy)
836-
);
837-
when work.axi_stream_pkg.tdest =>
838-
check(
839-
tdest,
840-
axi_stream_transaction.tdest,
841-
select_policy(axi_stream_signal, work.axi_stream_pkg.tdest, inactive_policy, previous_inactive_policy)
842-
);
843-
when work.axi_stream_pkg.tuser =>
844-
check(
845-
tuser,
846-
axi_stream_transaction.tuser,
847-
select_policy(axi_stream_signal, work.axi_stream_pkg.tuser, inactive_policy, previous_inactive_policy)
848-
);
849-
end case;
850-
loop_count := loop_count + 1;
848+
cov := NewID(
849+
axi_stream_signal_t'image(axi_stream_signal) & "_" &
850+
inactive_bus_policy_t'image(inactive_policy)
851+
);
852+
AddBins(cov, GenBin(0,1));
853+
854+
while not IsCovered(cov) loop
855+
push_axi_stream(
856+
net,
857+
master_axi_stream,
858+
tdata => axi_stream_transaction.tdata,
859+
tlast => last,
860+
tkeep => axi_stream_transaction.tkeep,
861+
tstrb => axi_stream_transaction.tstrb,
862+
tid => axi_stream_transaction.tid,
863+
tdest => axi_stream_transaction.tdest,
864+
tuser => axi_stream_transaction.tuser
865+
);
866+
pop_axi_stream(net, slave_axi_stream, data, last, keep, strb, id, dest, user);
867+
wait until rising_edge(aclk);
868+
869+
check(
870+
axi_stream_signal = work.axi_stream_pkg.tdata,
871+
tdata,
872+
axi_stream_transaction.tdata,
873+
select_policy(axi_stream_signal, work.axi_stream_pkg.tdata, inactive_policy, previous_inactive_policy)
874+
);
875+
check(
876+
axi_stream_signal = work.axi_stream_pkg.tlast,
877+
tlast,
878+
last,
879+
select_policy(axi_stream_signal, work.axi_stream_pkg.tlast, inactive_policy, previous_inactive_policy)
880+
);
881+
check(
882+
axi_stream_signal = work.axi_stream_pkg.tkeep,
883+
tkeep,
884+
axi_stream_transaction.tkeep,
885+
select_policy(axi_stream_signal, work.axi_stream_pkg.tkeep, inactive_policy, previous_inactive_policy)
886+
);
887+
check(
888+
axi_stream_signal = work.axi_stream_pkg.tstrb,
889+
tstrb,
890+
axi_stream_transaction.tstrb,
891+
select_policy(axi_stream_signal, work.axi_stream_pkg.tstrb, inactive_policy, previous_inactive_policy)
892+
);
893+
check(
894+
axi_stream_signal = work.axi_stream_pkg.tid,
895+
tid,
896+
axi_stream_transaction.tid,
897+
select_policy(axi_stream_signal, work.axi_stream_pkg.tid, inactive_policy, previous_inactive_policy)
898+
);
899+
check(
900+
axi_stream_signal = work.axi_stream_pkg.tdest,
901+
tdest,
902+
axi_stream_transaction.tdest,
903+
select_policy(axi_stream_signal, work.axi_stream_pkg.tdest, inactive_policy, previous_inactive_policy)
904+
);
905+
check(
906+
axi_stream_signal = work.axi_stream_pkg.tuser,
907+
tuser,
908+
axi_stream_transaction.tuser,
909+
select_policy(axi_stream_signal, work.axi_stream_pkg.tuser, inactive_policy, previous_inactive_policy)
910+
);
851911
end loop;
912+
loop_count := loop_count + 1;
852913
end loop;
853914
previous_inactive_policy := inactive_policy;
854915
end loop;
855-
check_equal(loop_count, 4 * 7 * 7);
916+
check_equal(loop_count, 5 * 7);
856917

857918
elsif run("test global inactive bus policy") then
858919
for inactive_policy in inactive_bus_policy_t'('0') to inactive_bus_policy_t'('1') loop
@@ -878,27 +939,16 @@ begin
878939

879940
pop_axi_stream(net, slave_axi_stream, data, last, keep, strb, id, dest, user);
880941
wait until rising_edge(aclk);
881-
for sig in work.axi_stream_pkg.tdata to work.axi_stream_pkg.tuser loop
882-
case sig is
883-
when work.axi_stream_pkg.tdata =>
884-
check(tdata, "", inactive_policy);
885-
when work.axi_stream_pkg.tlast =>
886-
check(tlast, '-', inactive_policy);
887-
when work.axi_stream_pkg.tkeep =>
888-
check(tkeep, "", inactive_policy);
889-
when work.axi_stream_pkg.tstrb =>
890-
check(tstrb, "", inactive_policy);
891-
when work.axi_stream_pkg.tid =>
892-
check(tid, "", inactive_policy);
893-
when work.axi_stream_pkg.tdest =>
894-
check(tdest, "", inactive_policy);
895-
when work.axi_stream_pkg.tuser =>
896-
check(tuser, "", inactive_policy);
897-
end case;
898-
loop_count := loop_count + 1;
899-
end loop;
942+
check(false, tdata, "", inactive_policy);
943+
check(false, tlast, '-', inactive_policy);
944+
check(false, tkeep, "", inactive_policy);
945+
check(false, tstrb, "", inactive_policy);
946+
check(false, tid, "", inactive_policy);
947+
check(false, tdest, "", inactive_policy);
948+
check(false, tuser, "", inactive_policy);
949+
loop_count := loop_count + 1;
900950
end loop;
901-
check_equal(loop_count, 2 * 7);
951+
check_equal(loop_count, 2);
902952
end if;
903953
test_runner_cleanup(runner, allow_disabled_errors => running_test_case = "test signal inactive bus policy");
904954
end process;

0 commit comments

Comments
 (0)