【问题标题】:systemverilog union type in chisel凿子中的systemverilog联合类型
【发布时间】:2020-05-31 07:05:27
【问题描述】:

我将一些 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这两个数据结构,结构中的每个字段都可以单独更新,但是要凿。有没有办法表达这种功能?

【问题讨论】:

    标签: chisel


    【解决方案1】:

    没有对打包联合的内置支持,但您可以创建自定义类(子类型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
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-15
      • 1970-01-01
      • 2018-09-04
      • 2018-07-29
      相关资源
      最近更新 更多