axi stream协议的具体内容可参见从零学习AXI4总线(二):AXI4-Stream 介绍和AXI4-Stream协议总结
以下是一个简单的HDL示例,完成的功能是master向slave写入512个数据(1,2,3,…,511,512)
主机代码:
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2021/06/13 20:42:20
// Design Name:
// Module Name: axis_master
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module axis_master(
input logic ACLK,
input logic ARESETn,
input logic start,
input logic TREADY,
output logic done,
output logic TVALID,
output logic [31:0] TDATA,
output logic [3:0] TSTRB,
output logic [3:0] TKEEP,
output logic TLAST,
output logic TID,
output logic TDEST,
output logic TUSER //TID,TDEST,TUSER用于多机通信
);
parameter N=512;
logic [31:0] tx_buffer [0:N-1]; //待传输的值
logic [31:0] tx_cnt;
//初始化tx_buffer
always_ff@(posedge ACLK,negedge ARESETn)
if(~ARESETn)
begin
for(int i=0;i<N;i++)
tx_buffer[i]<=i+1;
end
else
begin
;
end
//TVALID
always_ff@(posedge ACLK,negedge ARESETn)
if(~ARESETn)
TVALID<=0;
else if(start)
TVALID<=1;
else if(TVALID&&TREADY&&TLAST) //最后一个数据传输完成,拉低TVALID
TVALID<=0;
//tx_cnt
always_ff@(posedge ACLK,negedge ARESETn)
if(~ARESETn)
tx_cnt<=0;
else if(start)
tx_cnt<=0;
else if(TVALID&&TREADY) //每完成一次数据传输,tx_cnt加1
tx_cnt<=tx_cnt+1;
//TLAST
always_ff@(posedge ACLK,negedge ARESETn)
if(~ARESETn)
TLAST<=0;
else if(tx_cnt==N-2&&TVALID&&TREADY) //倒数第二个数据传输完成,拉高TLAST
TLAST<=1;
else if(TVALID&&TREADY&&TLAST) //最后一个数据传输完成后,拉低
TLAST<=0;
//TDATA
always_comb
begin
TDATA=tx_buffer[tx_cnt];
end
//TSTRB
always_ff@(posedge ACLK,negedge ARESETn)
if(~ARESETn)
TSTRB<=4'b0000;
else if(start)
TSTRB<=4'b1111;
//TKEEP
always_ff@(posedge ACLK,negedge ARESETn)
if(~ARESETn)
TKEEP<=4'b0000;
else if(start)
TKEEP<=4'b1111;
//done
always_ff@(posedge ACLK,negedge ARESETn)
if(~ARESETn)
done<=0;
else if(TVALID&&TLAST&&TREADY) //最后一个数据传输完成
done<=1;
else
done<=0;
endmodule
从机代码:
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2021/06/13 20:43:04
// Design Name:
// Module Name: axis_slave
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module axis_slave(
input logic ACLK,
input logic ARESETn,
input logic start, //可以开始接收数据
input logic TVALID,
input logic TLAST,
input logic [31:0] TDATA,
input logic [3:0] TSTRB,
input logic [3:0] TKEEP,
input logic TID,
input logic TDEST,
input logic TUSER,
output logic TREADY,
output logic done //数据接收完毕
);
parameter N = 1024;
logic [31:0] rx_buffer [0:N-1]; //接收缓冲区
logic [31:0] rx_cnt; //接收计数器
logic [3:0] bytemask;
//rx_cnt
always_ff@(posedge ACLK,negedge ARESETn)
if(~ARESETn)
rx_cnt<=0;
else if(start)
rx_cnt<=0;
else if(TVALID&&TREADY) //每完成一次数据传输,rx_cnt加1
rx_cnt<=rx_cnt+1;
//done
always_ff@(posedge ACLK,negedge ARESETn)
if(~ARESETn)
done<=0;
else if(TVALID&&TREADY&&TLAST) //最后一个数据接收完成,done拉高
done<=1;
else
done<=0;
//bytemask
assign bytemask=TSTRB & TKEEP; //tstrb和tkeep同时为高时才是有效字节
//rx_buffer
always_ff@(posedge ACLK)
if(TVALID&&TREADY) //接收数据
begin
for(int i=0;i<4;i++)
begin
rx_buffer[rx_cnt][(8*i+7) -:8]<=((bytemask[i]==1'b1)?TDATA[(8*i+7)-:8]:8'h00);
end
end
//TREADY
always_ff@(posedge ACLK,negedge ARESETn)
if(~ARESETn)
TREADY<=0;
else if(start)
TREADY<=1;
else if(TLAST&&TREADY&&TVALID) //最后一个数据传输完成
TREADY<=0;
//
always_ff@(posedge ACLK)
if(done)
begin
for(int i=0;i<512;i++)
begin
$display("%d",rx_buffer[i]);
end
end
endmodule
测试文件代码:
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2021/06/13 21:43:09
// Design Name:
// Module Name: axis_tb
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module axis_tb;
logic ACLK;
logic ARESETn;
logic TVALID;
logic TREADY;
logic TLAST;
logic [31:0] TDATA;
logic [3:0] TSTRB;
logic [3:0] TKEEP;
logic TID;
logic TUSER;
logic TDEST;
logic master_start;
logic master_done;
logic slave_start;
logic slave_done;
//ACLK
initial
begin
ACLK=0;
forever begin
#5 ACLK=~ACLK;
end
end
//ARESETn
initial
begin
ARESETn=0;
#20
ARESETn=1;
end
//start
initial
begin
master_start=0;
slave_start=0;
#100
master_start=1;
slave_start=1;
#10
master_start=0;
slave_start=0;
end
//instance
axis_master M(
.ACLK(ACLK),
.ARESETn(ARESETn),
.start(master_start),
.TREADY(TREADY),
.done(master_done),
.TVALID(TVALID),
.TDATA(TDATA),
.TSTRB(TSTRB),
.TKEEP(TKEEP),
.TLAST(TLAST),
.TID(TID),
.TDEST(TDEST),
.TUSER(TUSER) //TID,TDEST,TUSER用于多机通信
);
axis_slave S(
.ACLK(ACLK),
.ARESETn(ARESETn),
.start(slave_start), //可以开始接收数据
.TVALID(TVALID),
.TLAST(TLAST),
.TDATA(TDATA),
.TSTRB(TSTRB),
.TKEEP(TKEEP),
.TID(TID),
.TDEST(TDEST),
.TUSER(TUSER),
.TREADY(TREADY),
.done(slave_done) //数据接收完毕
);
endmodule