深入 AXI4匯流排 (四):RAM 讀取實戰

本系列我想深入探尋 AXI4 匯流排。不過事情總是這樣,不能我說想深入就深入。當前我對 AXI匯流排的理解尚談不上深入。但我希望通過一系列文章,讓讀者能和我一起深入探尋 AXI4。

光說不練,雲玩家。這篇文章中我們就通過訪問一個 AXI4 介面的 RAM 的實際操作,加深我們對 AXI4 匯流排的理解。

我們的實驗平台是 ISE 14.7 以及 modelsim 10.2, RAM 的 ip 使用 ISE 的 block memory generator 生成,Intel 方面的工具和 ip 我不是太熟悉,但想必很多內容都是共通的。

Native V.S AXI4 ?

首先使用 ip 核生成器生成一個 AXI4 的 ip 核,我們先比較一下 Native 介面和 AXI4 介面的 RAM。

一號選手:Native

首先登場的是一號選手:Natiiiive,他有著小小的身板,地址,輸入數據,輸出數據,使能,時鐘介面錯落有致,簡潔分明。小快靈是他的信仰,好用好上手是他的宣言。

二號選手:AXI4

接下來登場的是 AXIFour,他的身板恐怕是 Native 的三倍,更大的身板,更大的力量是他的座右銘。「通用性」,「標準匯流排」是他掛在嘴上的口頭禪

Ok,Stop,兩者之間其實並不是一個競爭關係,沒有孰勝孰劣的比較。Native 介面數據線更少,但不夠通用,自然也沒有匯流排的概念;AXI4 支持標準化的,通用匯流排訪問,可以將多個 RAM 掛載到一條匯流排上,通過 ID 區分不同的 RAM,但介面要確實複雜地多。

AXI 匯流排讀寫 RAM 實戰

首先構建 AXI4 介面的 RAM ip核,在工程中添加 ip 核文件

選擇 AXI 協議,另外關於 AXI-Lite 協議將會在以後的文章中介紹。AXI-Lite 協議簡化了 AXI 協議,但不支持突發傳輸操作。

在 Slave Option 中選擇 Memory Slave,因為 RAM 作為一個存儲介質,不能主動發起操作,在 AXI 傳輸中只能作為從機。作為從機有兩種選項,Memory Slave 作為存儲介質,使用完整的 AXI 匯流排;Peripheral Slave 不是很熟悉,在該模式下不支持突發傳輸。

在 Memory Type 中,如果使用 AXI 匯流排,則只能選擇單口RAM。而 Native 介面是支持多種模式的,包括 ROM,雙口 RAM 等。

Native 介面下可以選擇多種模式

之後選擇適合的數據匯流排寬度和 RAM 深度即可以生成 RAM 。

在工程中為新生成的 ip 核添加 testbench。

首先是非突發傳輸(突發傳輸長度為 1 的突發傳輸。。)寫入與讀取操作,即寫入地址,寫入一次數據。讀取操作時,也先寫入數據,然後讀取。下圖中為了說明一些細節,進行了兩次同樣的流程。

Testbench 的時序部分

initial begin
// Initialize Inputs
//....初值均賦為0 除 bready 外
s_axi_bready = 1;

// Wait 100 ns for global reset to finish
#100;

// Add stimulus here
s_aresetn = 1;

repeat(2) begin
#100;
//aw channel
s_axi_awaddr = 32b100;
s_axi_awlen = 0;
s_axi_awsize = 3b010;
s_axi_awburst = 0;
#20;
s_axi_awvalid = 1;
#20;
//wait(s_axi_awready == 1 && s_aclk == 1);
s_axi_awvalid = 0;

#100;
//w channel
s_axi_wdata = 32h01020304;
s_axi_wstrb = 4b1111;
s_axi_wlast = 1;
s_axi_wvalid = 1;
#20;
s_axi_wlast = 0;
s_axi_wvalid = 0;
s_axi_wstrb = 4b0;

#100;
//ar channel
s_axi_araddr = 32b100;
s_axi_arlen = 0;
s_axi_arsize = 3b010;
s_axi_arburst = 0;
#20;
s_axi_arvalid = 1;
#20;
//wait(s_axi_arready == 1 && s_aclk == 1);
s_axi_arvalid = 0;

#100;
//r channel
s_axi_rready = 1;
end

end

always #10 s_aclk = ~s_aclk;

我們關注一些細節,有關 RAM IP 核的一些特性,比如當完成一次寫入時,RAM 的 AXREADY 信號會拉低約 6 個時鐘之後,才會拉高允許下一次地址寫入發生;而 XREADY 信號則會保持低電平直到下一次地址地址寫入之後,才會拉高準備接收數據。

通過實踐發現了 AXI4 在讀取時的一個特性,如果在讀取時,將突發傳輸長度設為 2,突發傳輸寬度設為 16 位,數據匯流排寬度為 32 位,即通過兩次 16 位傳輸讀取寫入的 32 位數據 0x01020304。實踐後發現,實際上會讀取兩次 0x01020304,需要主機自行整理數據,因為主機實際上知道,自己讀取的數據寬度是 16 位,數據匯流排寬度為 32 位。

讀者可以通過模擬結果看到本系列之前的文章中提到,握手機制,AXI 各信號線的含義以及突發傳輸機制等。

ljgibbs:深入 AXI4 匯流排(一)握手機制?

zhuanlan.zhihu.com圖標ljgibbs:深入 AXI4 匯流排(二)架構?

zhuanlan.zhihu.com圖標ljgibbs:深入 AXI4 匯流排(三)突發傳輸機制?

zhuanlan.zhihu.com圖標

接下來嘗試突發傳輸操作

Testbench 部分

// Wait 100 ns for global reset to finish
#100;

// Add stimulus here
s_aresetn = 1;

repeat(2) begin
#100;
//aw channel
s_axi_awaddr = 32b100;
s_axi_awlen = 8d3;
s_axi_awsize = 3b010;
s_axi_awburst = 2b01;
#20;
s_axi_awvalid = 1;
#20;
//wait(s_axi_awready == 1 && s_aclk == 1);
s_axi_awvalid = 0;

#100;
//w channel
s_axi_wdata = 32h01020304;
s_axi_wstrb = 4b1111;
repeat (3) begin
s_axi_wdata = s_axi_wdata + 1b1;
s_axi_wvalid = 1;
#20;
s_axi_wvalid = 0;
#20;
end
s_axi_wdata = s_axi_wdata + 1b1;
s_axi_wvalid = 1;
s_axi_wlast = 1;
#20
s_axi_wlast = 0;
s_axi_wvalid = 0;
#100;
//ar channel
s_axi_araddr = 32b100;
s_axi_arlen = 8d7;
s_axi_arsize = 3b001;
s_axi_arburst = 2b01;
#20;
s_axi_arvalid = 1;
#20;
//wait(s_axi_arready == 1 && s_aclk == 1);
s_axi_arvalid = 0;

#100;
//r channel
s_axi_rready = 1;
end

end

突發傳輸類型為 INCR,寫入時,突發傳輸長度為 4,寬度為 32 位;讀取時長度為 8,寬度為 16 位,模擬的結果和預期一致。

結語

光說不練假把式,本文結合本系列之前的文章,進行一次 AXI4 匯流排訪問 RAM 的實戰。之前我也只使用過 datamover ip 來訪問 AXI4 匯流排,這也是我第一次直接操作 AXI4 匯流排。本文中的例子是一個基礎的舉例,之後還會進行更多的模擬,比如進行多 RAM 掛載在一條匯流排上的操作。


推薦閱讀:

TAG:通信 | 現場可編輯邏輯門陣列(FPGA) |