接口中用于 RTL 可读性的 assign 语句会在综合中导致赋值或缓冲区

assign statement for RTL readability in an interface causes assignments or a buffer in synthesis

我们有一个与 modports 连接的接口,看起来像这样:

interface test_interface (clk, in1, out1);
    input logic in1;
    output logic out1;
    input logic clk;
    logic mid1;
    logic aliased_signal;

    modport a_to_b (
        input in1,
        input clk,
        output mid1,
        input aliased_signal
    );

    modport b_to_a (
        input clk,
        input mid1,
        output out1,
        output aliased_signal
    );

endinterface : test_interface

module top(clock, inpad, outpad);
    input logic clock;
    input logic inpad;
    output logic outpad;

    test_interface test_if(.clk(clock), .in1(inpad), .out1(outpad));

    a A0(.a2b(test_if));
    b B0(.b2a(test_if));

endmodule

module a ( test_interface.a_to_b a2b);

    always_ff @(posedge a2b.clk) begin
        a2b.mid1 <= a2b.in1 & a2b.aliased_signal;
    end

endmodule

module b (test_interface.b_to_a b2a);

    assign b2a.aliased_signal = b2a.out1;

    always_ff @(posedge b2a.clk) begin
        b2a.out1 <= ~b2a.mid1;
    end

endmodule

这是一个简单的例子,但可以说明问题。在实际设计中,例如,我们有 32 位输出和其中的 8 位可能到一个地方,8 位到另一个地方,等等。在目的地,他们想使用在目的地模块中更有意义的名称,因此正在使用赋值在接口中创建这些名称,以便目标代码不会仅使用接口中混淆总线名称的部分位。

虽然上面的模拟很好,结果是综合期间的赋值语句(即使显然使用 always_comb),虽然我们可以让综合工具插入缓冲区来使 APR 满意,但当这些信号基本上只是用作方便的别名。

是否有一种带有 SV 接口的 RTL 编码风格允许这样 "aliasing" 而不会在 synthesis/APR 工具的下游造成复杂性?

下面是一个更接近我正在尝试做的例子。 "obfuscated_name" 信号是 a 模块的输出,因为某些模块直接使用接口中的名称(这可以清理为仅执行 a->b 连接正在执行的操作),但我得到了相同的错误如果我连接到 mid2 a->c 而不是直接使用 obfuscated_name 信号,则来自 IUS 和 DC。

interface test_interface(clk, in1, out1, out2);
    input logic [7:0] in1;
    output logic [3:0] out1;
    output logic [3:0] out2;
    input logic clk;
    logic [7:0] obfuscated_name;
    logic [3:0] mid1;
    logic [3:0] mid2;

    modport a_mp (
        input clk,
        input in1,
        output obfuscated_name
    );

    modport a_to_b (
        input clk,
        input .mid1(obfuscated_name[3:0]),
        output out1
    );

    modport a_to_c (
        input clk,
        input obfuscated_name,
        output out2
    );

endinterface : test_interface

module a ( test_interface.a_mp a_intf);

    always_ff @(posedge a_intf.clk) begin
        a_intf.obfuscated_name <= ~a_intf.in1;
    end

endmodule

module b (test_interface.a_to_b b_intf);

    always_ff @(posedge b_intf.clk) begin
        b_intf.out1 <= b_intf.mid1;
    end

endmodule


module c (test_interface.a_to_c c_intf);

    always_ff @(posedge c_intf.clk) begin
        c_intf.out2 <= ~c_intf.obfuscated_name[7:4];
    end

endmodule



module top( input logic clock,
            input logic [7:0] inpad,
            output logic [3:0] outpad1,
            output logic [3:0] outpad2 );


    test_interface test_if(.clk(clock), .in1(inpad), .out1(outpad1), .out2(outpad2));

    a A0(.a_intf(test_if));
    b B0(.b_intf(test_if));
    c C0(.c_intf(test_if));

endmodule

我从 IUS 得到的错误是:

ncvlog: *E,MODPXE (test_interface.sv,18|18): Unsupported modport expression for port identifier 'mid1'.

DC 给出了这个错误:

Error: ./b.sv:1: The construct 'b_intf.mid1 (modport expression without a modport from parent)' is not supported in synthesis. (VER-700)

我希望我在这里做了一些无知的事情,这可能是我正在尝试做的事情。

Verilog 中有一个称为 端口表达式 .name_of_port(expression_to_be_connected_to_port) 的功能,大多数人都在 模块实例端口列表 中识别它他们没有意识到的也可以用在模块减速端口列表头中。这声明了端口的名称,以及连接到端口的表达式。这样,可以将较大的内部总线的较小部分 select 制成端口。

module DUT(input clk, inout .data(bus[7:0]) );
  wire [31:0] bus;
endmodule
module top;
  reg clock;
  wire [7:0] mydata;
  DUT d1(.data(mydata), .clk(clock) );
endmodule

在 SystemVerilog 中,您可以使用 modport 表达式执行相同的操作。

interface test_interface (clk, in1, out1);
    input logic in1;
    output logic out1;
    input logic clk;
    logic mid1;
    logic aliased_signal;

    modport a_to_b (
        input in1,
        input clk,
        output mid1,
        input .aliased_signal(out1) // modport expression
    );

    modport b_to_a (
        input clk,
        input mid1,
        output out1
    );

endinterface : test_interface

module top( input logic clock,
            input logic inpad,
            output logic outpad );


    test_interface test_if(.clk(clock), .in1(inpad), .out1(outpad));

    a A0(.a2b(test_if));
    b B0(.b2a(test_if));

endmodule

module a ( test_interface.a_to_b a2b);

    always_ff @(posedge a2b.clk) begin
        a2b.mid1 <= a2b.in1 & a2b.aliased_signal; // port reference to alias
    end

endmodule

module b (test_interface.b_to_a b2a);

    always_ff @(posedge b2a.clk) begin
        b2a.out1 <= ~b2a.mid1;
    end

endmodule