2020.04.02更新:
最近正好用到了這個,貼個能用的代碼幫助大家理解吧。該代碼已通過仿真測試谦去,可以與Xilinx的AXI BRAM Controller一起使用。
該模塊的主要功能是利用AXI4協(xié)議對內(nèi)存進行先寫后讀的反復(fù)操作卦方。代碼如下:
`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date: 01/7/2020 10:41:11 AM
// Design Name:
// Module Name: AXI_read_write
//////////////////////////////////////////////////////////////////////////////////
module AXI_read_write #(
parameter integer UPPER_WIDTH = 8,
parameter integer DATA_WIDTH = 64
)
(
//==========input===============//
M_AXI_ACLK ,
M_AXI_ARESETN ,
M_AXI_awready ,
M_AXI_arready ,
M_AXI_rdata ,
M_AXI_wready ,
M_AXI_rlast ,
M_AXI_rvalid ,
M_AXI_bvalid ,
//==========output===============//
M_AXI_awvalid ,
M_AXI_arvalid ,
M_AXI_wdata ,
M_AXI_rready ,
M_AXI_wlast ,
M_AXI_wvalid ,
M_AXI_awaddr ,
M_AXI_araddr ,
M_AXI_bready
);
//port--------------------------------------
input wire M_AXI_ACLK ;
input wire M_AXI_ARESETN ;
input wire M_AXI_awready ;
input wire M_AXI_arready ;
output reg M_AXI_awvalid ;
output reg M_AXI_arvalid ;
// input wire [1:0] M_AXI_BRESP;
// input wire [1:0] M_AXI_RRESP;
input wire [DATA_WIDTH-1:0] M_AXI_rdata;
output reg [DATA_WIDTH-1:0] M_AXI_wdata;
input wire M_AXI_wready ;
input wire M_AXI_rlast ;
input wire M_AXI_rvalid ;
//---------------------------
output reg M_AXI_rready ;
output reg M_AXI_wlast ;
output reg M_AXI_wvalid ;
output reg [UPPER_WIDTH-1:0] M_AXI_awaddr;
// output reg [7:0] M_AXI_AWLEN = 8'b0;
// output reg [2:0] M_AXI_AWSIZE = 3'b011;//8 byte
//----------------------------
output reg [UPPER_WIDTH-1:0] M_AXI_araddr;
// output reg [7:0] M_AXI_ARLEN = 8'b0;
// output reg [2:0] M_AXI_ARSIZE = 3'b011;//8 byte
//output reg [1:0] M_AXI_ARBURST = 2'b0;//FIXED
input wire M_AXI_bvalid;
output reg M_AXI_bready;
reg [3:0] cnt;
// output reg [DATA_WIDTH/8-1:0] M_AXI_WSTRB;//用于小塊傳輸
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
if (!M_AXI_ARESETN) M_AXI_bready <= 1'b0;
else if (M_AXI_awready) M_AXI_bready <= 1'b1;
else if (M_AXI_wlast) M_AXI_bready <= 1'b0;
else M_AXI_bready <= M_AXI_bready;
end
//Read-Write Control
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
if (!M_AXI_ARESETN) cnt <= 'b0;
else if (cnt == 'd11) cnt <= 'b0;
else cnt <= cnt + 'b1;
end
//write data
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
if (!M_AXI_ARESETN) M_AXI_awaddr <= 'b0;
else if (cnt == 'd1) M_AXI_awaddr <= M_AXI_awaddr + 'h4;
else M_AXI_awaddr <= M_AXI_awaddr;
end
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
if (!M_AXI_ARESETN) M_AXI_awvalid <= 'b0;
else if ((cnt == 'd1) || (cnt == 'd2)) M_AXI_awvalid <= 'b1;
else M_AXI_awvalid <= 'b0;
end
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
if (!M_AXI_ARESETN) begin
M_AXI_wdata <= 'hFFFFFFFF;
M_AXI_wlast <= 'b0;
end
else if (cnt == 'd3) begin
M_AXI_wdata <= M_AXI_wdata + 'hF;
M_AXI_wlast <= 'b1;
end
else begin
M_AXI_wdata <= M_AXI_wdata;
M_AXI_wlast <= 'b0;
end
end
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
if (!M_AXI_ARESETN) M_AXI_wvalid <= 'b0;
else if (cnt == 'd3) M_AXI_wvalid <= 'b1;
else M_AXI_wvalid <= 'b0;
end
//read data
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
if (!M_AXI_ARESETN) M_AXI_araddr <= 'b0;
else if (cnt == 'd5) M_AXI_araddr <= M_AXI_araddr + 'h4;
else M_AXI_araddr <= M_AXI_araddr;
end
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
if (!M_AXI_ARESETN) M_AXI_arvalid <= 'b0;
else if ((cnt == 'd5) || (cnt == 'd6)) M_AXI_arvalid <= 'b1;
else M_AXI_arvalid <= 'b0;
end
always @(posedge M_AXI_ACLK or negedge M_AXI_ARESETN) begin
if (!M_AXI_ARESETN) M_AXI_rready <= 'b0;
else if (M_AXI_arready) M_AXI_rready <= 'b1;
else if (M_AXI_rlast) M_AXI_rready <= 'b0;
else M_AXI_rready <= M_AXI_rready;
end
endmodule
前言:
最近需要對一個已經(jīng)實現(xiàn)功能的IP核添加支持AXI總線接口的數(shù)據(jù)通信接口,于是研究了一下AXI4和AXI4-stream的接口泰佳,下文中大部分內(nèi)容來自于其他博主盼砍,這里寫此篇綜合一下,以便日后查閱逝她。
(`由于本人水平有限浇坐,如有錯誤歡迎指正!`)
1黔宛、初識AXI總線:
1.1近刘、通信模型:
如上圖所示,要通過AXI總線實現(xiàn)通信臀晃,我們需要一個主設(shè)備/上位機(Master)和一個從設(shè)備/下位機(Slave)觉渴,并通過AXI總線將其相連。我們可以將上圖中的主設(shè)備假定為CPU积仗,從設(shè)備假定為RAM疆拘。主設(shè)備和從設(shè)備的通信主要為了實現(xiàn)主設(shè)備對從設(shè)備的讀寫控制。
1.2寂曹、AXI Interconnect:
有時我們需要實現(xiàn)一個主設(shè)備控制多個從設(shè)備,可以使用AXI Interconnect模塊實現(xiàn)該功能÷≡玻可以將其簡單地認為是一個帶仲裁功能的多路選擇器(MUX)漱挚。在配置從設(shè)備的地址時(Address)時,注意設(shè)備地址不能重疊渺氧,且地址分配時需要整塊分配旨涝,而不是簡單地跟在上個設(shè)備分配的地址之后繼續(xù)分配。
舉例如下:
地址分配錯誤如上圖所示侣背,給Slave1分配好地址之后白华,直接接在Slave1的地址之后給Slave2分配地址是不行的,因為Slave2的地址范圍(Address Range)過大贩耐,從0x40001000分配最多只能分配到0x40001FFF弧腥,即最多分配4K,而現(xiàn)在需要分配2G潮太,應(yīng)將地址偏移(Address Offset)設(shè)為2G的邊界(boundary)管搪,即地址偏移+地址范圍=FFFFFFFF,故此時地址偏移應(yīng)該為0x80000000铡买。
1.3更鲁、握手機制:
先放時序圖中的圖樣說明圖:
AXI4和AXi4-stream都支持三種握手機制,但其具體的總線結(jié)構(gòu)是不同的奇钞,詳情在后文中會介紹澡为。這三種握手機制分別是:
VALID before READY:
上圖中的模式為VALID信號先于READY信號拉高,此時數(shù)據(jù)在VALID信號和READY信號為高時景埃,在時鐘上升沿觸發(fā)缀壤,開始傳輸。
READY before VALID:
上圖中的模式為READY信號先于VALID信號拉高纠亚,此時數(shù)據(jù)在VALID信號和READY信號為高時塘慕,在時鐘上升沿觸發(fā),開始傳輸蒂胞。
VALID with READY:
上圖中的模式為READY信號伴隨著VALID信號拉高图呢,此時數(shù)據(jù)在VALID信號和READY信號為高時,在時鐘上升沿觸發(fā)骗随,開始傳輸蛤织。
1.4、Burst:
按照傳統(tǒng)的RAM的讀寫方式鸿染,給定一個Address指蚜,只能讀取或者寫入一個Data,但是在Burst模式下涨椒,給定一個Address摊鸡,可以連續(xù)寫入或者讀取多組數(shù)據(jù)绽媒。
2、AXI4總線:
2.1免猾、AXI4接口:
主設(shè)備接口
從設(shè)備接口
2.2是辕、AXI4讀操作:
如上圖所示,主設(shè)備向從設(shè)備通過讀地址通道指定讀數(shù)據(jù)地址及控制信號猎提,從設(shè)備通過讀數(shù)據(jù)通道將指定地址上的數(shù)據(jù)傳輸給主設(shè)備获三。
在實際代碼中我們采用有限狀態(tài)機(FSM)來實現(xiàn)對相關(guān)信號的控制,這里采用的是VALID before READY握手模式锨苏。
parameter IDLE = 5'b00001; parameter WAIT_START = 5'b00010; parameter SEND_ADDR = 5'b00100; parameter RECEIVE_DATA = 5'b01000; parameter CHECK_CONT = 5'b10000;
1疙教、當狀態(tài)機的當前狀態(tài)為WAIT_START時,master將ARVALID拉高伞租。
2贞谓、slave收到ARVALID信號后,將ARREADY拉高肯夏,持續(xù)到一次burst_len傳完為止经宏。master收到ARREADY拉高的信號后,將ARVALID拉低驯击。
3烁兰、ARADDR在ARVALID為高時給定對應(yīng)地址。
4徊都、RREADY信號在收到RVALID信號為高時拉高沪斟,保持一個周期,讀取出數(shù)據(jù)暇矫。
5主之、RVALID信號由slave控制,具體控制模式參考slave模塊的設(shè)計李根。
6槽奕、當一次讀取的最后一個數(shù)據(jù)包讀取時將RLAST拉高,表示一次Burst讀取完畢房轿。
其中讀操作的信號依賴關(guān)系如下:
如圖可知粤攒,讀操作的兩個channel之間存在如下的依賴關(guān)系:必須等到ARVALID和ARREADY同時為High后,RVALID才能拉高囱持。
2.3夯接、AXI4寫操作:
如上圖所示,主設(shè)備向從設(shè)備通過寫地址通道指定寫數(shù)據(jù)地址及控制信號纷妆,從設(shè)備通過寫數(shù)據(jù)通道將指定數(shù)據(jù)寫到從設(shè)備的指定地址上盔几。待數(shù)據(jù)寫入完成后,從設(shè)備通過寫響應(yīng)通道向主設(shè)備傳遞寫響應(yīng)信號掩幢,表明寫入完成逊拍。
1上鞠、當狀態(tài)機的當前狀態(tài)為WAIT_START時,master將AWVALID拉高顺献。
2旗国、slave收到AWVALID信號后枯怖,將AWREADY拉高注整,持續(xù)到一次burst_len寫完為止.master收到AWREADY拉高的信號后,將AWVALID拉低度硝。
3肿轨、AWADDR在AWVALID為高時給定對應(yīng)地址。
4蕊程、WREADY信號在收到WVALID信號為高時拉高椒袍,保持一個周期,寫入數(shù)據(jù)藻茂。
5驹暑、WVALID信號由slave控制,具體控制模式參考slave模塊說明辨赐。
6优俘、當一次寫入的最后一個數(shù)據(jù)包讀取時將WLAST拉高,表示一次寫入完畢掀序。
7帆焕、BRESP和BVALID都由slave控制,當收到WLAST信號時不恭,BVALID拉高叶雹。
8、BREADY可以一直拉高换吧,也可以在AWREADY信號拉高后保持拉高折晦。直到BVALID信號拉高時將其拉低即可。
其中寫操作的信號依賴關(guān)系如下:
如圖可知沾瓦,ADDR和DATA兩個channel之間不存在依賴關(guān)系满着,需要滿足的是必須等到WVALID和WREADY同時為High,且最后一次傳輸完成后暴拄,BVALID才能拉高漓滔,表明寫操作結(jié)束。
3乖篷、AXI4-stream總線:
3.1响驴、AXI4-stream接口:
AXI4-Stream跟AXI4的區(qū)別在于AXI4-Stream沒有ADDR接口,這樣就不涉及讀寫數(shù)據(jù)的概念了撕蔼,只有簡單的發(fā)送與接收說法豁鲤,減少了延時秽誊,允許無限制的數(shù)據(jù)突發(fā)傳輸規(guī)模。AXI4-Stream的核心思想在于流式處理數(shù)據(jù)琳骡。
一個AXI-stream傳輸?shù)臅r序圖:
其中AXI-stream一般的數(shù)據(jù)傳輸過程如下:
1锅论、首先slave將TREADY信號拉高,表示自己可以接收信號楣号。
2最易、當master將TDATA,TKEEP炫狱,TUSER準備就緒之后藻懒,將TVALID拉高,傳輸開始视译。
3嬉荆、其中TKEEP滿足TKEEP[x] is associated with TDATA[(8x+7):8x],當其被拉高時表示這段數(shù)據(jù)必須傳輸?shù)侥康牡乜岷STRB表示該段信息是否有效鄙早。TUSER可以在傳遞時捎帶用戶信息。具體接口參照使用的AXI-stream接口器件椅亚,并非所有支持AXI-stream接口的器件都含有以上接口限番,其中的一些接口是可選的而不是必需的。
4什往、直到master將TLAST拉高扳缕,TVALID拉低,傳輸結(jié)束别威。