Struct 有没有办法在Verilog中定义类似C结构的东西

Struct 有没有办法在Verilog中定义类似C结构的东西,struct,verilog,hdl,Struct,Verilog,Hdl,我有一个用Verilog(重要的不是SystemVerilog)编写的项目,由于在设计的不同部分之间传递的信号数量太多,它变得有点难以管理。因为我有几个模块都需要相同的信号,所以我想尝试将它们合并成数量较少的命名对象。问题是如何做到这一点 假设这是我人为的例子: module mymodule(sig_a_in, sig_b_in, sig_c_in, sig_d_in, sig_e_in, sig_a_out, sig_b_out, sig_c_out, sig

我有一个用Verilog(重要的不是SystemVerilog)编写的项目,由于在设计的不同部分之间传递的信号数量太多,它变得有点难以管理。因为我有几个模块都需要相同的信号,所以我想尝试将它们合并成数量较少的命名对象。问题是如何做到这一点

假设这是我人为的例子:

module mymodule(sig_a_in, sig_b_in, sig_c_in, sig_d_in, sig_e_in,
                sig_a_out, sig_b_out, sig_c_out, sig_d_out, sig_e_out);

  input wire sig_a_in, sig_b_in, sig_c_in;
  input wire [5  : 0] sig_d_in;
  input wire [31 : 0] sig_e_in;
  output reg sig_a_out, sig_b_out, sig_c_out;
  output reg [5  : 0] sig_d_out;
  output reg [31 : 0] sig_e_out;
endmodule
在我看来,重要的是,为了可读性,我可以通过名称引用信号。但是,我不想把它们单独传递给每个模块。同样,我在这个项目中只使用Verilog,所以SystemVerilog构造是不可能的

我的第一个想法是,我只需将它们组合成一个总线,然后使用定义的名称来引用各个导线。然而,这有点笨重,尤其是当你把其他公交车加入到混合车中时。在我设计的例子中,这是非常简单的,因为信号有一个明显的隐式顺序,但在现实生活中它们没有

`define SIGNAL_BUS_WIDTH 41
`define A 0
`define B 1
`define C 2
`define D 3
`define E 9

module mymodule(signal_bus_in, signal_bus_out);

  input wire [`SIGNAL_BUS_WIDTH-1 : 0] signal_bus_in;
  output reg [`SIGNAL_BUS_WIDTH-1 : 0] signal_bus_out;

  // reference a
  signal_bus_in[`A]
  // reference d?  Not good when names don't have an obvious order
  signal_bus_in[`E-1 : `D]
endmodule
最后,除此之外,工具链还必须能够区分模块正在使用结构中的哪些导线,并仅合成这些导线。并非所有的模块都使用所有的导线,因此我希望避免使用额外的未使用路径。我认为这些工具应该足够智能,可以做到这一点,即使在我上面的总线示例中,但我不能完全确定


在Verilog中有没有一个好方法可以得到我想要的东西?

您可以使用宏来定义每个信号的范围,而不是端点,从而将您的想法进一步扩展:

`define WIDTH 41
`define sigA 0:0
`define sigB 1:1
`define sigC 2:2
`define sigD 8:3
`define sigE 40:9

module mymodule(signal_bus_in, signal_bus_out);

  input wire [`WIDTH-1 : 0] signal_bus_in;
  output reg [`WIDTH-1 : 0] signal_bus_out;

  ...
  // signal a
  signal_bus_in[`sigA];
  // signal d
  signal_bus_in[`sigD];
  ...
当然,这并不像SystemVerilog压缩结构那么简单(这就是它们存在的原因!),但它可以满足您的需要。此外,这也为你的台词增加了顺序,但我看不到任何结构不能做到这一点;即使是结构也会给你的信号增加一个顺序。但是,只要使用宏,除了定义宏外,宏的顺序并不重要


任何好的合成工具都应该能够抛出任何不驱动任何东西或不受任何东西驱动的端口或线路,因此,除非您必须明确告诉它出于某种原因要忽略哪些线路,否则您不应该担心它为未使用的模块管脚合成额外空间。

Verilog没有结构。IMO将所有信号组合成一个长向量(或者你称之为总线)是你最好的选择。但是,您可以稍微改进宏:

`define SIGNAL_BUS_WIDTH 41
`define A 0:0
`define B 1:1
`define C 2:2
`define D 8:3
`define E 40:9

// reference a
signal_bus_in[`A]
// reference d  
signal_bus_in[`D]
// reference e  
signal_bus_in[`E]

大多数合成工具不会为未连接的导线创建额外的逻辑,并将其视为无关紧要。

为了避免过度依赖预处理器,您可以尝试使用
localparam
函数
声明来模拟结构。下面是一个“mybus”结构的模型,其中有四个字段,分别命名为a到D,大小不同,以说明这一想法

您可以将这些支持参数和函数放入一个文件中,该文件只包含在需要构造和分解这种总线的各个模块中。这也许可以让你使用更短的名字而不用担心冲突

module test ;


// Boilerplate structure size definitions -- you could automatically generate these
// with a simple script and put them into an include file.

localparam mybus_a_size = 4;
localparam mybus_a_offset = 0;

localparam mybus_b_size = 8;
localparam mybus_b_offset = mybus_a_offset + mybus_a_size;

localparam mybus_c_size = 4;
localparam mybus_c_offset = mybus_b_offset + mybus_b_size;

localparam mybus_d_size = 6;
localparam mybus_d_offset = mybus_c_offset + mybus_c_size;

localparam mybus_size = mybus_a_size + mybus_b_size + mybus_c_size + mybus_d_size;


// accessor functions, i.e., instead of bus.a you write mybus_a(bus)

function [mybus_a_size-1:0] mybus_a (input [mybus_size-1:0] in);
  mybus_a = in[mybus_a_size + mybus_a_offset - 1 : mybus_a_offset];
endfunction

function [mybus_b_size-1:0] mybus_b (input [mybus_size-1:0] in);
  mybus_b = in[mybus_b_size + mybus_b_offset - 1 : mybus_b_offset];
endfunction

function [mybus_c_size-1:0] mybus_c (input [mybus_size-1:0] in);
  mybus_c = in[mybus_c_size + mybus_c_offset - 1 : mybus_c_offset];
endfunction

function [mybus_d_size-1:0] mybus_d (input [mybus_size-1:0] in);
  mybus_d = in[mybus_d_size + mybus_d_offset - 1 : mybus_d_offset];
endfunction


// constructor function -- build a mybus out of its components

function [mybus_size-1:0] make_mybus(input [mybus_a_size-1:0] a,
                                      input [mybus_b_size-1:0] b,
                                      input [mybus_c_size-1:0] c,
                                      input [mybus_d_size-1:0] d);
  make_mybus = {d,c,b,a};
endfunction


// example of using this stuff

reg [mybus_size - 1 : 0] bus;

initial begin
  bus = make_mybus(1,2,3,4);
  $display("Hello, my bus is { a=%b, b=%b, c=%b, d=%b }", mybus_a(bus), mybus_b(bus), mybus_c(bus), mybus_d(bus));
end

endmodule
这个模型可能是一个很好的起点。一些明显的改进是从一个简单的脚本自动生成所有的样板,并在C++中添加附加的构造函数,如“SETTER”,即

set_mybus_a(mybus, 5)   // set mybus.a = 5

这是给SystemVerilog的。我使用的是Verilog,而不是SystemVerilog。Verilog在处理复杂数据结构时非常有限。这就是为什么在Verilog-2005之后,IEEE用SystemVerilog取代了它。我不担心宏会给线路增加顺序。我只是不想为了找到最高有效位而知道下一个命名信号是哪个。你的建议就可以做到这一点,所以对我来说应该足够好了。