一个处理ASIX数据流及其功能仿真的例子

一个处理ASIX数据流及其功能仿真的例子


本文主要介绍一个对AXIS数据进行处理和进行功能仿真的例子

1 功能代码

本例子的功能为从输入的AXIS数据包中提取出每一帧第一个时钟周期数据包的前16bit,根据这16bit的数值判断是否为特定的数据包,并随数据包一起输出标识信号。

  • 第一个数据包的前16bit为0x5555,则标识也为0x5555,拉高标识有效信号。
  • 第一个数据包的前16bit为其它数值,则标识为0x0000,拉高标识有效信号。

在本例子中,每一帧的识别通过tvalid的上升沿确定。为了解决帧连续tvalid没有上升沿的情况,在tlast上升沿的时候将tvliad_1d信号拉低,生成一个上升沿。为了解决一帧数据流中间存在无效数据会产生tvalid上升沿的情况,使用state信号标识是否为同一帧数据。

module preproccess #(
    parameter USER_META_DATA_WIDTH = 16,
    parameter TDATA_NUM_BYTES      = 64
) (
   input                              s_axis_aclk,
   input                              s_axis_aresetn,
   // AXIS Slave port
   input  [TDATA_NUM_BYTES*8-1:0]     s_axis_tdata,
   input  [TDATA_NUM_BYTES-1:0]       s_axis_tkeep,
   input                              s_axis_tvalid,
   input                              s_axis_tlast,
   output                             s_axis_tready,
   output [USER_META_DATA_WIDTH-1:0]  meta,
   output                             meta_valid,
   // AXIS Master port  
   output [TDATA_NUM_BYTES*8-1:0]     m_axis_tdata,
   output [TDATA_NUM_BYTES-1:0]       m_axis_tkeep,
   output                             m_axis_tvalid,
   input                              m_axis_tready,
   output                             m_axis_tlast
);

reg                             s_axis_tready_r;
reg [USER_META_DATA_WIDTH-1:0]  meta_r;
reg                             meta_valid_r;
reg [TDATA_NUM_BYTES*8-1:0]     m_axis_tdata_r;
reg [TDATA_NUM_BYTES-1:0]       m_axis_tkeep_r;
reg                             m_axis_tvalid_r;
reg                             m_axis_tlast_r;

assign s_axis_tready = s_axis_tready_r;
assign meta          = meta_r;
assign meta_valid    = meta_valid_r;
assign m_axis_tdata  = m_axis_tdata_r;
assign m_axis_tkeep  = m_axis_tkeep_r;
assign m_axis_tvalid = m_axis_tvalid_r;
assign m_axis_tlast  =m_axis_tlast_r;
   
reg  s_axis_tvalid_1d;
wire s_axis_tvalid_raise;
reg  s_axis_tlast_1d;
wire s_axis_tlast_raise;
always @(posedge s_axis_aclk or negedge s_axis_aresetn) begin
   if (!s_axis_aresetn) begin
      s_axis_tvalid_1d <= 1'b0;
      s_axis_tlast_1d  <= 1'b0;
   end
   else if (s_axis_tlast_raise) begin //解决连续数据流tvalid一直有效的情况
      s_axis_tvalid_1d <= 1'b0;
   end
   else begin
      s_axis_tvalid_1d <= s_axis_tvalid;
      s_axis_tlast_1d  <= s_axis_tlast;
   end
end
assign s_axis_tvalid_raise = ({s_axis_tvalid, s_axis_tvalid_1d} == 2'b10) ? 1 : 0;
assign s_axis_tlast_raise  = ({s_axis_tlast, s_axis_tlast_1d} == 2'b10) ? 1 : 0;

reg state; //状态
always @(posedge s_axis_aclk or negedge s_axis_aresetn) begin
   if (!s_axis_aresetn) begin
      state <= 1'b1;
   end
   else if (s_axis_tlast_raise) begin
      state <= 1'b1;
   end
   else if (s_axis_tvalid_raise) begin
      state <= 1'b0;
   end
   else begin
      state <= state;
   end
end
wire flag; //每一帧第一个数据包的标识,解决一帧数据流中间tvalid信号无效的情况
assign flag = s_axis_tvalid_raise && state;

always @(posedge s_axis_aclk or negedge s_axis_aresetn) begin
   if (!s_axis_aresetn) begin
      s_axis_tready_r <= 1'b0;
      m_axis_tvalid_r <= 1'b0;
      m_axis_tkeep_r  <= 64'd0;
      m_axis_tdata_r  <= 512'd0;
      m_axis_tlast_r  <= 1'b0;
      meta_valid_r    <= 1'b0;
      meta_r          <= 16'd0;
   end
   else if (m_axis_tready) begin
      s_axis_tready_r <= 1'b1;
      m_axis_tvalid_r <= s_axis_tvalid;
      m_axis_tdata_r  <= s_axis_tdata;
      m_axis_tkeep_r  <= s_axis_tkeep;
      m_axis_tlast_r  <= s_axis_tlast;
      if (flag) begin
         meta_valid_r <= 1'b1;
         if (s_axis_tdata[15:0] == 16'h5555) begin
            meta_r <= s_axis_tdata[15:0];
         end
         else begin
            meta_r <= 16'd0;
         end
      end
      else begin
         meta_valid_r <= 1'b0;
         meta_r       <= 16'd0;
      end
   end
   else begin
      s_axis_tready_r <= 1'b0;
      m_axis_tvalid_r <= 1'b0;
      m_axis_tkeep_r  <= 64'd0;
      m_axis_tdata_r  <= 512'd0;
      m_axis_tlast_r  <= 1'b0;
      meta_valid_r    <= 1'b0;
      meta_r          <= 16'd0;
   end
end

endmodule 

2 仿真代码

为了验证代码功能的正确性,仿真了五种情况。仿真代码使用systemverilog实现,功能代码使用verilog实现,需要说明的是在block design中,使用verilog实现的代码可以直接以模块的方式添加到bd中,而systemverilog却不行。但是systemverilog存在很多的优势,如在本例子,赋值不需要指明位宽,而且‘1代表将所有位都置1,在tkeep信号中比较实用。

  • 第一帧数据标识为0x5555
  • 第二帧数据与第一帧数据连续,标识为0x1111
  • 第三帧数据与第二帧数据之间不连续
  • 第四帧数据中间存在无效信号
  • 第五帧数据紧接第四帧
module preproccess_tb ();
localparam TDATA_NUM_BYTES       = 64;
localparam USER_META_DATA_WIDTH  = 16;

// Clocks & Resets
logic s_axis_aclk         = 1'b1;
logic s_axis_aresetn      = 1'b0;

// Metadata
logic [USER_META_DATA_WIDTH-1:0] meta;
logic                            meta_valid;

// AXI Slave port
logic [TDATA_NUM_BYTES*8-1:0]    s_axis_tdata;
logic [TDATA_NUM_BYTES-1:0]      s_axis_tkeep;
logic                            s_axis_tvalid;
logic                            s_axis_tlast;
logic                            s_axis_tready;

// AXI Master port
logic [TDATA_NUM_BYTES*8-1:0]    m_axis_tdata;
logic [TDATA_NUM_BYTES-1:0]      m_axis_tkeep;
logic                            m_axis_tvalid;
logic                            m_axis_tready;
logic                            m_axis_tlast;

always begin
   #5 s_axis_aclk = !s_axis_aclk;
end

initial begin
   #10 begin
      s_axis_aresetn <= 1;
      m_axis_tready  <= 0;
      s_axis_tvalid  <= 0;
      s_axis_tdata   <= 0;
      s_axis_tkeep   <= 0;
      s_axis_tlast   <= 0;
   end
   #10 begin
      m_axis_tready  <= 1;
   end
   #10 begin //第一帧
      s_axis_tvalid  <= 1;
      s_axis_tdata   <= {{448{1'b0}}, 64'h1111_1111_5016_5555};
      s_axis_tkeep   <= '1;
      s_axis_tlast   <= 0;
   end
   #10 begin
      s_axis_tvalid  <= 1;
      s_axis_tdata   <= {512{1'b0}};
      s_axis_tkeep   <= '1;
      s_axis_tlast   <= 1;
   end
   #10 begin //连续的第二帧
      s_axis_tvalid  <= 1;
      s_axis_tdata   <= {{448{1'b0}}, 64'h1111_1111_1111_1111};
      s_axis_tkeep   <= '1;
      s_axis_tlast   <= 0;
   end
   #10 begin
      s_axis_tvalid  <= 1;
      s_axis_tdata   <= {512{1'b0}};
      s_axis_tkeep   <= '1;
      s_axis_tlast   <= 1;
   end
   #10 begin
      s_axis_tvalid  <= 0;
      s_axis_tdata   <= 0;
      s_axis_tkeep   <= 0;
      s_axis_tlast   <= 0;
   end
   #10 begin //非连续的第三帧
      s_axis_tvalid  <= 1;
      s_axis_tdata   <= {{448{1'b0}}, 64'h1111_1111_5016_5555};
      s_axis_tkeep   <= '1;
      s_axis_tlast   <= 0;
   end
   #10 begin
      s_axis_tvalid  <= 1;
      s_axis_tdata   <= {512{1'b1}};
      s_axis_tkeep   <= '1;
      s_axis_tlast   <= 1;
   end
   #10 begin
      s_axis_tvalid  <= 0;
      s_axis_tdata   <= 0;
      s_axis_tkeep   <= 0;
      s_axis_tlast   <= 0;
   end
   #10 begin //中间非连续的第四帧
      s_axis_tvalid  <= 1;
      s_axis_tdata   <= {{448{1'b0}}, 64'h1111_1111_5016_5555};
      s_axis_tkeep   <= '1;
      s_axis_tlast   <= 0;
   end
   #10 begin
      s_axis_tvalid  <= 0;
      s_axis_tdata   <= 0;
      s_axis_tkeep   <= 0;
      s_axis_tlast   <= 0;
   end
   #10 begin
      s_axis_tvalid  <= 1;
      s_axis_tdata   <= {512{1'b1}};
      s_axis_tkeep   <= '1;
      s_axis_tlast   <= 1;
   end
   #10 begin //后续的第五帧
      s_axis_tvalid  <= 1;
      s_axis_tdata   <= {{448{1'b0}}, 64'h1111_1111_5016_5555};
      s_axis_tkeep   <= '1;
      s_axis_tlast   <= 0;
   end
   #10 begin
      s_axis_tvalid  <= 1;
      s_axis_tdata   <= {512{1'b1}};
      s_axis_tkeep   <= '1;
      s_axis_tlast   <= 1;
   end
   #10 begin
      s_axis_tvalid  <= 0;
      s_axis_tdata   <= 0;
      s_axis_tkeep   <= 0;
      s_axis_tlast   <= 0;
   end
end
   
preproccess #(
      .USER_META_DATA_WIDTH (USER_META_DATA_WIDTH),
      .TDATA_NUM_BYTES      (TDATA_NUM_BYTES)
   ) preproccess_i (
      .s_axis_aclk          (s_axis_aclk),
      .s_axis_aresetn       (s_axis_aresetn),

      .meta                 (meta),
      .meta_valid           (meta_valid),

      .s_axis_tdata         (s_axis_tdata),
      .s_axis_tkeep         (s_axis_tkeep),
      .s_axis_tvalid        (s_axis_tvalid),
      .s_axis_tlast         (s_axis_tlast),
      .s_axis_tready        (s_axis_tready),
      
      .m_axis_tdata         (m_axis_tdata),
      .m_axis_tkeep         (m_axis_tkeep),
      .m_axis_tvalid        (m_axis_tvalid),
      .m_axis_tready        (m_axis_tready),
      .m_axis_tlast         (m_axis_tlast)

 );

endmodule

3 功能仿真

功能仿真的结果如下图所示,与预期的结果一致

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值