chisel - chisel 中的 systemverilog 联合类型

标签 chisel

我将一些systermverilog代码重写到chisel中,但我找不到在chisel中表达systemverilog的打包联合的好方法。例如,

typedef struct packed {
    logic [3:0]     version;
    logic [3:0]     ihl;
    logic [7:0]     tos;
    logic [15:0]    total_length;
    logic [15:0]    id;
    logic           reserved;
    logic           df;
    logic           mf;
    logic [12:0]    frag_offset;
    logic [7:0]     ttl;
    logic [7:0]     protocol;
    logic [15:0]    checksum;
    logic [31:0]    ip_sa;
    logic [31:0]    ip_da;
} ipv4_s;

typedef struct packed {
    logic [63:0] DW0;
    logic [63:0] DW1;
    logic [31:0] DW2;
} common_20b_s;

typedef union packed {
    ipv4_s  structured;
    common_20b_s array;
    logic [$bits(ipv4_s)-1:0] bits;
} ipv4_hdr_u;

module test (
    input clk,
    input [$bits(ipv4_s)-1:0] pkt_stream_in,
    input [3:0] mode,
    input [127:0] config_in,
    output reg [$bits(ipv4_s)-1:0] pkt_stream_out
);

    ipv4_hdr_u ipv4_hdr;
    always @* begin
        ipv4_hdr.bits = pkt_stream_in;

        case(mode)
            0: ipv4_hdr.structured.ip_sa = config_in[31:0];
            1: ipv4_hdr.array.DW0 = config_in[63:0];
        endcase
    end

    always @(posedge clk)
        pkt_stream_out <= ipv4_hdr.bits;

endmodule: test

对于ipv4_scommon_2b_s这两个数据结构,结构中的每个字段都可以单独更新,但是要凿。有什么办法可以表达这种功能吗?

最佳答案

没有对打包联合的内置支持,但您可以创建自定义类(子类型Bundle)并自己构建类似的东西。它会导致更多的样板,所以我认为一些内置支持会很好,但它可以完成工作:

可运行音译:https://scastie.scala-lang.org/5jOMpEYuRbu9VbzScvDffQ

粘贴在下面:

import chisel3._
import chisel3.util._
import chisel3.stage.ChiselStage

class IPV4_s extends Bundle {
  val version = UInt(4.W)
  val ihl = UInt(4.W)
  val tos = UInt(8.W)
  val total_length = UInt(16.W)
  val id = UInt(16.W)
  val reserved = Bool()
  val df = Bool()
  val mf = Bool()
  val frag_offset = UInt(13.W)
  val ttl = UInt(8.W)
  val protocol = UInt(8.W)
  val checksum = UInt(16.W)
  val ip_sa = UInt(32.W)
  val ip_da = UInt(32.W)
}
object IPV4_s {
  // Utility, I got sick of typing this righthand expression
  val width = (new IPV4_s).getWidth
}

class Common_20b_s extends Bundle {
  val DW0 = UInt(64.W)
  val DW1 = UInt(64.W)
  val DW2 = UInt(32.W)
}


class IPV4_hdr_u extends Bundle {
  val bits = UInt(IPV4_s.width.W)
  // These helpers aren't really necessary but can save some typing
  def asIPV4_s = this.asTypeOf(new IPV4_s)
  def asCommon_20b_s = this.asTypeOf(new Common_20b_s)
}

class Test extends MultiIOModule {
  // clock is inherited
  val pkt_stream_in = IO(Input(new IPV4_hdr_u))
  val mode = IO(Input(UInt(4.W)))
  val config_in = IO(Input(UInt(128.W)))
  val pkt_stream_out = IO(Output(new IPV4_hdr_u))

  // Default to using stream_in
  val ipv4_hdr = WireInit(pkt_stream_in)
  switch (mode) {
    is (0.U) {
      // Cast input and use temporary for subfield assignment
      val t = WireInit(pkt_stream_in.asIPV4_s)
      t.ip_sa := config_in(31, 0)
      ipv4_hdr := t.asTypeOf(new IPV4_hdr_u)
    }
    is (1.U) {
      val t = WireInit(pkt_stream_in.asCommon_20b_s)
      t.DW0 := config_in(63, 0)
      ipv4_hdr := t.asTypeOf(new IPV4_hdr_u)
    }
  }
  pkt_stream_out := ipv4_hdr
}

关于chisel - chisel 中的 systemverilog 联合类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62112755/

相关文章:

scala - 在 Chisel 中使用 Vec[Mem] 会很好

hardware - 是否可以避免指定默认值以便在 Chisel 中获得 X?

verilog - 如何在Chisel3中进行门级仿真?

chisel - 将子模块的寄存器添加到新建/实例化它的模块的 regmap() 中

hdl - 如何在Chisel中正确定义输出Reg

chisel - 模块是对象还是类?

chisel - 使用动态索引时如何显示我的线路名称?

chisel - 如何表达Vec的指定索引范围?

Chisel:嵌套向量中丢失的解耦方向性