AXI stream协议简易实现(基于System verilog)

背景

最近再看AXI协议的内容,对axi stream进行简易的实现,便于以后回忆

axi stream协议很简单,就是传输数据,不像axi4和axi lite有多个通道,只有一对握手信号tready和tvalid,tdata数据流有三种类型,是根据TKKEP和TSTRB决定的,tlast是最后一个数据的标志
在这里插入图片描述

代码实现(使用sv中的interface)

代码中并没有考虑传输类型,仅仅是为了熟悉stream协议以及interface的使用

在使用interface中,遇到的问题:
1.modport的端口方向:需要和声明的modport自身一致
2. 在实例化带有interface的模块时,需要传进去的是接口的 实例化,而不是 实例化.modport

axi_stream_if

import axi_stream_pkg::*;

interface axi_stream_if;
logic tvalid;
logic tready;
logic tlast;
data_t tdata;

modport master (
    output tdata,
    input tready,
    output tvalid, tlast
);

modport slave (
input tvalid, tlast,
input tdata,
output tready
);

endinterface //interfacename

axi_stream_master

import axi_stream_pkg::*;

module axi_stream_master (
    input clk,
    input rstn,
    axi_stream_if.master axi_master,
    input logic start
);

parameter STREAM_LEN = 7;
parameter S0 = 1'b0, S1 = 1'b1;
logic state, next_state;
data_t axi_data_o;
logic [2:0] master_counter;
logic start_r;

assign axi_master.tvalid = state == S1;
assign axi_master.tlast = (state == S1)&& (master_counter == STREAM_LEN);
assign axi_master.tdata = axi_data_o;

always @(posedge clk or negedge rstn) begin
   if(!rstn) 
     state <= S0;
   else 
     state <= next_state;
end

always @(posedge clk or negedge rstn) begin
    if(!rstn) begin
        axi_data_o <= 32'h123456;
        master_counter <= 0;
    end
    else if(axi_master.tvalid & axi_master.tready) begin
        axi_data_o <= axi_data_o + 4;
        master_counter <= master_counter + 1;
    end
end

always @(posedge clk or negedge rstn) begin 
    if(!rstn) 
        start_r <= 0;
    else 
        start_r <= start;
end

always @(*) begin
    next_state = 0;
    case(state)
        S0 : begin
             if(start_r) next_state = S1; 
             else        next_state = S0;
        end
        S1 : begin if(axi_master.tlast) next_state <= S0;
             else                       next_state <= S1;
        end
    endcase
end

endmodule

axi_stream_slave

import axi_stream_pkg::*;

module axi_stream_slave (
    input clk, 
    input rstn,
    axi_stream_if.slave axi_slave
);
    
data_t mem[0:7];
logic [2:0] slave_counter;

integer i;
always @(posedge clk or negedge rstn) begin
    if(!rstn)
        for(i=0;i<8;i++)
            mem[i] <= 0;
    else if(axi_slave.tvalid & axi_slave.tready)
        mem[slave_counter] = axi_slave.tdata;
end

always @(posedge clk or negedge rstn) begin
    if(!rstn)
        axi_slave.tready = 1;
    else if(axi_slave.tlast)
        axi_slave.tready = 0;
end

always @(posedge clk or negedge rstn) begin
    if(!rstn)
        slave_counter <= 0;
    else if(axi_slave.tvalid & axi_slave.tready)
        slave_counter <= slave_counter + 1;
end

endmodule

axi_stream_pkg

package axi_stream_pkg;
  typedef logic [31:0] data_t;
  
endpackage

stimulus

import axi_stream_pkg::*;

module stimulus;
    axi_stream_if axi_stream_if();

    logic start, clk, rstn;

axi_stream_slave u_axi_stream_slave(
    .clk  ( clk  ),
    .rstn ( rstn ),
    .axi_slave (axi_stream_if)
);

axi_stream_master u_axi_stream_master(
    .clk                             ( clk                             ),
    .rstn                            ( rstn                            ),
    .axi_master            ( axi_stream_if ),
    .start                     ( start                     )
);

initial begin
    clk = 1'b0;
    rstn = 1'b1;
    #2 rstn = 1'b0;
    #2 rstn = 1'b1;
    start = 1;
    #20 start = 0;
end

always #5 clk = ~clk;


endmodule

仿真波形

在这里插入图片描述

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值