一、前言
利用FPGA設(shè)計(jì)算法一直以來都是熱點(diǎn),同樣也是難點(diǎn)。將復(fù)雜的數(shù)學(xué)公式 模型通過硬件系統(tǒng)來搭建,在低延時(shí) 高并行性等優(yōu)勢背后極大提高了設(shè)計(jì)難度和開發(fā)周期。Xilinx公司的sysGen(system generator)工具擴(kuò)展了MATLAB的simulink,提供很多IP Catalog中沒有的基礎(chǔ)模塊和針對DSP應(yīng)用的硬件模型。工程師利用豐富的模塊和MATLAB強(qiáng)大的數(shù)據(jù)處理及可視化能力能夠更快速完成設(shè)計(jì)與仿真驗(yàn)證工作。
二、sysGen算法系統(tǒng)設(shè)計(jì)
本文以個(gè)最簡單的例子講述利用sysGen搭建算法IP核,并集成到IP Integrator中作為ZYNQ PS端CPU的“定制外設(shè)”。僅用于測試目的。設(shè)計(jì)需求:在sysGen中搭建系統(tǒng),將輸入定點(diǎn)整數(shù)數(shù)據(jù)*2后輸出,輸入位寬為8bit。
在System Generator token中設(shè)定仿真步長為1sec。點(diǎn)擊需要觀測的信號連線,右擊選擇Xilinx add to viewer。啟動仿真并啟動Xilinx waveform viewer:
本質(zhì)上就是調(diào)用Vivado的XSim工具進(jìn)行行為仿真。仿真結(jié)果可見完成預(yù)期目標(biāo),現(xiàn)雙擊System Generator token ,選擇Compiliation類型為IP Catalog并勾選Create testbench,按下Generate生成IP核。
三、仿真測試
根據(jù)User Guide介紹sysGen是“周期和比特精準(zhǔn)的”,我們還是在Vivado環(huán)境下再次驗(yàn)證下。netlist文件夾內(nèi)子文件夾ip_catalog中為IP核示例工程,由于自動生成了testbench,打開后直接進(jìn)行行為仿真。sysGen在創(chuàng)建testbench時(shí)會將經(jīng)過gatein和gateout的數(shù)據(jù)儲存到文件中,testbench進(jìn)行的工作為:將gatein數(shù)據(jù)作為測試激勵送入到相應(yīng)設(shè)計(jì)輸入端口,之后把設(shè)計(jì)輸出得到結(jié)果與gateout文件數(shù)據(jù)進(jìn)行逐一比較從而驗(yàn)證設(shè)計(jì)是否與sysGen環(huán)境下仿真結(jié)果一致。
發(fā)現(xiàn)個(gè)比較有意思的現(xiàn)象,自動生成的testbench中clock生成并約束的50MHz,而是認(rèn)為進(jìn)行了拓展。
仿真波形如圖:
將clock處改動為50MHz后,經(jīng)過測試發(fā)現(xiàn)如果系統(tǒng)一開始就輸入數(shù)據(jù),前幾個(gè)數(shù)據(jù)沒有被真正處理,輸出錯(cuò)誤。可能是軟件BUG吧,不過這種情況也非常少見,實(shí)際系統(tǒng)中輸入數(shù)據(jù)大多情況會啟動一段時(shí)間后才輸入。這里等待100ns后再啟動clock翻轉(zhuǎn):
改動后仿真波形:
四、AXI-Stream總線形式IP
到此算法IP的設(shè)計(jì)與驗(yàn)證結(jié)束。如果想將這個(gè)IP核導(dǎo)入到IP Integrator中作為CPU的外設(shè),其接口必須滿足AXI總線標(biāo)準(zhǔn),因此回到sysGen中更改端口名稱和位寬。端口要符合AXI-Stream標(biāo)準(zhǔn)信號名稱,位寬為8bit整數(shù)倍。
生成IP核后,打開新的工程,導(dǎo)入該IP核到repository。
五、Block Design系統(tǒng)搭建
系統(tǒng)結(jié)構(gòu)與上一篇該系列博文類似,均是以AXI DMA為核心的Loop系統(tǒng),只是將AXI-Stream Data FIFO改成了自定義IP核。由于IP核slave和master接口只包含tdata和tvalid信號,因此需要添加接口銜接的一些簡單邏輯。tready信號和tkeep信號直接連接constant使用常數(shù)驅(qū)動,DMA的s_axis_s2mm接口的tlast由wrapper內(nèi)計(jì)數(shù)器邏輯驅(qū)動,將system中FCLK_CLK0 peripheral_aresetn m_axis_tvalid和s_axis_s2mm_tlast信號引出到wrapper中。
有一點(diǎn)比較坑:自定義IP通過AXI總線與DMA互聯(lián)時(shí),總線下相應(yīng)的接口不一定會正確對應(yīng),所以需要分別將兩端的每個(gè)接口相連。可以通過打開綜合后的設(shè)計(jì)來確認(rèn)連線無誤。
自動生成wrapper后改動添加代碼如下:
`timescale 1 ps / 1 ps
module user_wrapper
(DC,
DDR_addr,
DDR_ba,
DDR_cas_n,
DDR_ck_n,
DDR_ck_p,
DDR_cke,
DDR_cs_n,
DDR_dm,
DDR_dq,
DDR_dqs_n,
DDR_dqs_p,
DDR_odt,
DDR_ras_n,
DDR_reset_n,
DDR_we_n,
//FCLK_CLK0,
FIXED_IO_ddr_vrn,
FIXED_IO_ddr_vrp,
FIXED_IO_mio,
FIXED_IO_ps_clk,
FIXED_IO_ps_porb,
FIXED_IO_ps_srstb,
RES,
SCLK,
SDIN,
VBAT,
VDD
//m_axis_tvalid,
//peripheral_aresetn,
//s_axis_s2mm_tlast
);
output DC;
inout [14:0]DDR_addr;
inout [2:0]DDR_ba;
inout DDR_cas_n;
inout DDR_ck_n;
inout DDR_ck_p;
inout DDR_cke;
inout DDR_cs_n;
inout [3:0]DDR_dm;
inout [31:0]DDR_dq;
inout [3:0]DDR_dqs_n;
inout [3:0]DDR_dqs_p;
inout DDR_odt;
inout DDR_ras_n;
inout DDR_reset_n;
inout DDR_we_n;
//output FCLK_CLK0;
inout FIXED_IO_ddr_vrn;
inout FIXED_IO_ddr_vrp;
inout [53:0]FIXED_IO_mio;
inout FIXED_IO_ps_clk;
inout FIXED_IO_ps_porb;
inout FIXED_IO_ps_srstb;
output RES;
output SCLK;
output SDIN;
output VBAT;
output VDD;
//output [0:0]m_axis_tvalid;
//output [0:0]peripheral_aresetn;
//input s_axis_s2mm_tlast;
localparam DATA_NUM = 256;
wire DC;
wire [14:0]DDR_addr;
wire [2:0]DDR_ba;
wire DDR_cas_n;
wire DDR_ck_n;
wire DDR_ck_p;
wire DDR_cke;
wire DDR_cs_n;
wire [3:0]DDR_dm;
wire [31:0]DDR_dq;
wire [3:0]DDR_dqs_n;
wire [3:0]DDR_dqs_p;
wire DDR_odt;
wire DDR_ras_n;
wire DDR_reset_n;
wire DDR_we_n;
wire FCLK_CLK0;
wire FIXED_IO_ddr_vrn;
wire FIXED_IO_ddr_vrp;
wire [53:0]FIXED_IO_mio;
wire FIXED_IO_ps_clk;
wire FIXED_IO_ps_porb;
wire FIXED_IO_ps_srstb;
wire RES;
wire SCLK;
wire SDIN;
wire VBAT;
wire VDD;
wire [0:0]m_axis_tvalid;
wire [0:0]peripheral_aresetn;
wire s_axis_s2mm_tlast;
reg [8-1:0] cnt;
wire add_cnt;
wire end_cnt;
system system_i
(.DC(DC),
.DDR_addr(DDR_addr),
.DDR_ba(DDR_ba),
.DDR_cas_n(DDR_cas_n),
.DDR_ck_n(DDR_ck_n),
.DDR_ck_p(DDR_ck_p),
.DDR_cke(DDR_cke),
.DDR_cs_n(DDR_cs_n),
.DDR_dm(DDR_dm),
.DDR_dq(DDR_dq),
.DDR_dqs_n(DDR_dqs_n),
.DDR_dqs_p(DDR_dqs_p),
.DDR_odt(DDR_odt),
.DDR_ras_n(DDR_ras_n),
.DDR_reset_n(DDR_reset_n),
.DDR_we_n(DDR_we_n),
.FCLK_CLK0(FCLK_CLK0),
.FIXED_IO_ddr_vrn(FIXED_IO_ddr_vrn),
.FIXED_IO_ddr_vrp(FIXED_IO_ddr_vrp),
.FIXED_IO_mio(FIXED_IO_mio),
.FIXED_IO_ps_clk(FIXED_IO_ps_clk),
.FIXED_IO_ps_porb(FIXED_IO_ps_porb),
.FIXED_IO_ps_srstb(FIXED_IO_ps_srstb),
.RES(RES),
.SCLK(SCLK),
.SDIN(SDIN),
.VBAT(VBAT),
.VDD(VDD),
.m_axis_tvalid(m_axis_tvalid),
.peripheral_aresetn(peripheral_aresetn),
.s_axis_s2mm_tlast(s_axis_s2mm_tlast));
always @(posedge FCLK_CLK0)begin
if(!peripheral_aresetn)begin
cnt end
else if(add_cnt)begin
if(end_cnt)
cnt else
cnt end
end
assign add_cnt = m_axis_tvalid;
assign end_cnt = add_cnt && cnt== DATA_NUM-1;
assign s_axis_s2mm_tlast = end_cnt;
endmodule
user_wrapper
當(dāng)自定義IP核輸出256個(gè)數(shù)據(jù)時(shí),拉高tlast信號結(jié)束傳輸。打開綜合后的設(shè)計(jì),添加調(diào)試探針,抓取DMA與自定義IP之間的接口信號,set up debug后完成接下來的流程。
六、軟硬件聯(lián)調(diào)
在硬件系統(tǒng)中定義數(shù)據(jù)幀長度為256個(gè),數(shù)據(jù)位寬為16bit,因此C代碼中DMA啟動傳輸函數(shù)中數(shù)據(jù)長度參數(shù)為512byte。測試數(shù)據(jù)生成與檢測代碼非常簡單:
我們直接查看ILA抓取AXI S總線波形:
看到CPU產(chǎn)生數(shù)據(jù)從1到4重復(fù)遞增,IP核輸出結(jié)果從2到8重復(fù)遞增,輸出為輸入的2倍。
傳輸完成后進(jìn)入DMA發(fā)送和接收中斷,軟件檢測結(jié)果正確。在Memory窗口能夠直接查看內(nèi)存絕對地址里的數(shù)據(jù),選定DDR接收緩存區(qū)起始地址,其中的數(shù)據(jù)與AXI總線傳回?cái)?shù)據(jù)一致,證明系統(tǒng)聯(lián)調(diào)成功。之后任意算法模塊均可采用本文方式進(jìn)行設(shè)計(jì)和集成,可以說一勞永逸!
編輯:hfy
發(fā)布評論請先 登錄
相關(guān)推薦
評論