背景
最近再看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