SystemVerilog中结合interface实现输出数据总线的功能(2)

在上一篇文章中说明了如何使用SystemVerilog的interface来实现FPGA内部的输出数据总线功能,但仅给出了传输单个数据的方法。然而在实际应用中,我们可能会遇到需要传输多个数据的需求,此时前文给出的方案将存在一定的局限性。虽然我们可以声明多个不同的interface实例来分别传输这些数据,但总没有仅通过一个interface实例传输来得方便。

要将多个数据通过一个interface传输,我们首先想到的是SystemVerilog的struct——通过将这些待传输的数据用struct打包,便可以通过一个interface传输了。但问题也随之而来了:
1.struct不像interface那样支持参数化,对不同位宽的数据必须单独定义struct,这显然有悖于泛化编程的思想;
2.数据总线interface中定义的struct类型不能被外部模块引用,只能通过interface中定义的modport来传输给外部的目标模块,然而interface的一个modport只能传递一个struct实例,对需要使用不同struct实例的外部模块来说需求显然无法满足,即无法实现多个外部模块与interface内部不同struct实例的连接。

实际上,interface也可以实现struct的数据打包功能,而由于interface支持参数化,这也使得对打包数据的泛化编程变得可能;而且,interface支持定义modport,支持嵌入运算代码,使得其功能比struct更加强大。

因此,传输多个数据的数据总线的解决方案是:
1.用interface打包待传输数据,然后在数据总线interface中声明多个打包interface的实例;
2.外部模块以打包interface或其内定义的modport作为形参,而在外部模块实例化时,选择数据总线interface中与本模块实例对应的打包interface实例连接至本模块实例上。
示例代码:

interface data_transfer;
wire[31:0] data1;
wire[15:0] data2;
endinterface

interface if_dbus #(
    parameter LINKED_MDL
) (
    output data_transfer odbus
);
    logic[LINKED_MDL_CNT-1:0] ocs;
    data_transfer data2sel[LINKED_MDL_CNT-1:0];
    always_comb begin
        odbus = '0;
        for (int i = 0; i < LINKED_MDL_CNT; i++) begin
            if (ocs[i]) odbus = data2sel[i];
        end
    end
endinterface

应用示例:

module dbus_mdl1 #(
   parameter DATA1,
   parameter DATA2
)(
   output data_transfer o_data
);
   assign o_data.data1 = 32'(DATA1);
   assign o_data.data2 = 16'(DATA2);
endmodule
module dbus_mdl2 #(
    parameter DATA1,
    parameter DATA2
)(
    output data_transfer data_o
);
    assign data_o.data1 = 32'(DATA1);
    assign data_o.data2 = 16'(DATA2);
endmodule

module tb_if_dbus;
    data_transfer dbus2exam;
    if_dbus #(
        .LINKED_MDL_CNT(5)
    ) dbus_ifi(
        .odbus(dbus2exam)
    );
    genvar i;
    generate
        for (i= 0; i < 3; i++) begin:MDL1_GEN
            dbus_mdl1 #(
                .DATA1(i),
                .DATA2(i*2)
            ) im(
                .o_data(dbus_ifi.data2sel[i])
            );
        end
        for (i = 3; i < 5; i++) begin:MDL2_GEN
            dbus_mdl2 #(
                .DATA1(i),
                .DATA2(i*3)
            ) im2(
                .o_data(dbus_ifi.data2sel[i])
            );
        end
    endgenerate
    // 测试总线输出数据的代码,查看dbus2exam
    reg clk;
    initial begin
        clk = 0;
    end
    always #1 clk = ~clk;
    reg[2:0] idxcntr;
    initial begin
        idxcntr = '0;
    end
    always_ff @(posedge clk) begin
        idxcntr = idxcntr + 1;
    end
    always_comb begin
        dbus_ifi.ocs = '0;
        if (idxcntr < 5) dbus_ifi.ocs[i] = 1'b1;
    end
endmodule

你可能感兴趣的:(HDL,HDL,FPGA,打包数据总线)