verilator/test_regress/t/t_tri_iface_semantics.v

247 lines
5.5 KiB
Systemverilog

// DESCRIPTION: Verilator: Verilog Test module
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of either the GNU Lesser General Public License Version 3
// or the Perl Artistic License Version 2.0.
// SPDX-FileCopyrightText: 2026 Wilson Snyder
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
// verilog_format: off
`define stop $stop
`define checkh(gotv,expv) do if ((gotv) !== (expv)) begin $write("%%Error: %s:%0d: got='h%x exp='h%x\n", `__FILE__,`__LINE__, (gotv), (expv)); `stop; end while(0);
// verilog_format: on
// verilator lint_off MULTIDRIVEN
// ---------------- Compare semantics (=== / !==) ----------------
interface ifc_cmp;
logic we;
tri [7:0] d;
endinterface
module drv_cmp (
ifc_cmp io_ifc
);
assign io_ifc.d = io_ifc.we ? 8'h5A : 8'hzz;
endmodule
module chk_cmp (
ifc_cmp io_ifc,
output logic is_z,
output logic is_5a,
output logic not_z,
output logic not_5a
);
assign is_z = (io_ifc.d === 8'hzz);
assign is_5a = (io_ifc.d === 8'h5A);
assign not_z = (io_ifc.d !== 8'hzz);
assign not_5a = (io_ifc.d !== 8'h5A);
endmodule
interface ifc_cmp_mp;
logic we;
tri [7:0] d;
modport drv_mp(input we, inout d);
modport chk_mp(input we, inout d);
endinterface
module drv_cmp_mp (
ifc_cmp_mp.drv_mp io_ifc
);
assign io_ifc.d = io_ifc.we ? 8'h5A : 8'hzz;
endmodule
module chk_cmp_mp (
ifc_cmp_mp.chk_mp io_ifc,
output logic is_z,
output logic is_5a,
output logic not_z,
output logic not_5a
);
assign is_z = (io_ifc.d === 8'hzz);
assign is_5a = (io_ifc.d === 8'h5A);
assign not_z = (io_ifc.d !== 8'hzz);
assign not_5a = (io_ifc.d !== 8'h5A);
endmodule
module passthru_cmp (
ifc_cmp io_ifc
);
drv_cmp u_drv (.*);
endmodule
// ---------------- Mixed local + external contributors ----------------
interface ifc_mix;
logic we_local;
logic we_ext;
tri [7:0] d;
assign d = we_local ? 8'hA5 : 8'hzz;
endinterface
module drv_mix (
ifc_mix io_ifc
);
assign io_ifc.d = io_ifc.we_ext ? 8'h3C : 8'hzz;
endmodule
interface ifc_mix_mp;
logic we_local;
logic we_ext;
tri [7:0] d;
modport drv_mp(input we_ext, inout d);
assign d = we_local ? 8'hA5 : 8'hzz;
endinterface
module drv_mix_mp (
ifc_mix_mp.drv_mp io_ifc
);
assign io_ifc.d = io_ifc.we_ext ? 8'h3C : 8'hzz;
endmodule
module t;
// ---- Compare semantics: basic ----
ifc_cmp i_cmp ();
logic is_z, is_5a, not_z, not_5a;
drv_cmp u_drv_cmp (.io_ifc(i_cmp));
chk_cmp u_chk_cmp (
.io_ifc(i_cmp),
.is_z(is_z),
.is_5a(is_5a),
.not_z(not_z),
.not_5a(not_5a)
);
// ---- Compare semantics: modport ----
ifc_cmp_mp i_cmp_mp ();
logic mp_is_z, mp_is_5a, mp_not_z, mp_not_5a;
drv_cmp_mp u_drv_cmp_mp (.io_ifc(i_cmp_mp));
chk_cmp_mp u_chk_cmp_mp (
.io_ifc(i_cmp_mp),
.is_z(mp_is_z),
.is_5a(mp_is_5a),
.not_z(mp_not_z),
.not_5a(mp_not_5a)
);
// ---- Compare semantics: deep hierarchy ----
ifc_cmp i_cmp_deep ();
logic deep_is_z, deep_is_5a, deep_not_z, deep_not_5a;
passthru_cmp u_cmp_deep (.io_ifc(i_cmp_deep));
chk_cmp u_chk_cmp_deep (
.io_ifc(i_cmp_deep),
.is_z(deep_is_z),
.is_5a(deep_is_5a),
.not_z(deep_not_z),
.not_5a(deep_not_5a)
);
// ---- Mixed contributors ----
ifc_mix i_mix ();
drv_mix u_mix (.io_ifc(i_mix));
ifc_mix_mp i_mix_mp ();
drv_mix_mp u_mix_mp (.io_ifc(i_mix_mp));
initial begin
// ---- Compare semantics ----
i_cmp.we = 1'b0;
i_cmp_mp.we = 1'b0;
i_cmp_deep.we = 1'b0;
#1;
`checkh(is_z, 1'b1);
`checkh(is_5a, 1'b0);
`checkh(not_z, 1'b0);
`checkh(not_5a, 1'b1);
`checkh(mp_is_z, 1'b1);
`checkh(mp_is_5a, 1'b0);
`checkh(mp_not_z, 1'b0);
`checkh(mp_not_5a, 1'b1);
`checkh(deep_is_z, 1'b1);
`checkh(deep_is_5a, 1'b0);
#1;
i_cmp.we = 1'b1;
i_cmp_mp.we = 1'b1;
i_cmp_deep.we = 1'b1;
#1;
`checkh(is_z, 1'b0);
`checkh(is_5a, 1'b1);
`checkh(not_z, 1'b1);
`checkh(not_5a, 1'b0);
`checkh(mp_is_z, 1'b0);
`checkh(mp_is_5a, 1'b1);
`checkh(mp_not_z, 1'b1);
`checkh(mp_not_5a, 1'b0);
`checkh(deep_is_z, 1'b0);
`checkh(deep_is_5a, 1'b1);
#1;
i_cmp.we = 1'b0;
i_cmp_mp.we = 1'b0;
i_cmp_deep.we = 1'b0;
#1;
`checkh(is_z, 1'b1);
`checkh(is_5a, 1'b0);
`checkh(not_z, 1'b0);
`checkh(not_5a, 1'b1);
`checkh(mp_is_z, 1'b1);
`checkh(mp_is_5a, 1'b0);
`checkh(mp_not_z, 1'b0);
`checkh(mp_not_5a, 1'b1);
`checkh(deep_is_z, 1'b1);
`checkh(deep_is_5a, 1'b0);
// ---- Mixed contributors ----
i_mix.we_local = 1'b0;
i_mix.we_ext = 1'b0;
i_mix_mp.we_local = 1'b0;
i_mix_mp.we_ext = 1'b0;
#1;
`checkh(i_mix.d, 8'hzz);
`checkh(i_mix_mp.d, 8'hzz);
#1;
i_mix.we_local = 1'b1;
i_mix.we_ext = 1'b0;
i_mix_mp.we_local = 1'b1;
i_mix_mp.we_ext = 1'b0;
#1;
`checkh(i_mix.d, 8'hA5);
`checkh(i_mix_mp.d, 8'hA5);
#1;
i_mix.we_local = 1'b0;
i_mix.we_ext = 1'b1;
i_mix_mp.we_local = 1'b0;
i_mix_mp.we_ext = 1'b1;
#1;
`checkh(i_mix.d, 8'h3C);
`checkh(i_mix_mp.d, 8'h3C);
#1;
i_mix.we_local = 1'b1;
i_mix.we_ext = 1'b1;
i_mix_mp.we_local = 1'b1;
i_mix_mp.we_ext = 1'b1;
#1;
`checkh(i_mix.d, 8'hBD);
`checkh(i_mix_mp.d, 8'hBD);
#1;
i_mix.we_local = 1'b0;
i_mix.we_ext = 1'b0;
i_mix_mp.we_local = 1'b0;
i_mix_mp.we_ext = 1'b0;
#1;
`checkh(i_mix.d, 8'hzz);
`checkh(i_mix_mp.d, 8'hzz);
$write("*-* All Finished *-*\n");
$finish;
end
endmodule