0 卖盘信息
BOM询价
您现在的位置: 首页 > 技术方案 >工业控制 > 基于FPGA的sysGen算法系统设计方案

基于FPGA的sysGen算法系统设计方案

来源: elecfans
2021-08-18
类别:工业控制
eye 7
文章创建人 拍明

原标题:基于FPGA设计的sysGen算法系统设计方案

  一、前言

  利用FPGA设计算法一直以来都是热点,同样也是难点。将复杂的数学公式 模型通过硬件系统来搭建,在低延时 高并行性等优势背后极大提高了设计难度和开发周期。Xilinx公司的sysGen(system generator)工具扩展了MATLAB的simulink,提供很多IP Catalog中没有的基础模块和针对DSP应用的硬件模型。工程师利用丰富的模块和MATLAB强大的数据处理及可视化能力能够更快速完成设计与仿真验证工作。

  二、sysGen算法系统设计

  本文以个最简单的例子讲述利用sysGen搭建算法IP核,并集成到IP Integrator中作为ZYNQ PS端CPU的“定制外设”。仅用于测试目的。设计需求:在sysGen中搭建系统,将输入定点整数数据*2后输出,输入位宽为8bit。

  

pIYBAF9uKDmAGlS-AACLMgeqkdk369.png


  在System Generator token中设定仿真步长为1sec。点击需要观测的信号连线,右击选择Xilinx add to viewer。启动仿真并启动Xilinx waveform viewer:

  本质上就是调用Vivado的XSim工具进行行为仿真。仿真结果可见完成预期目标,现双击System Generator token ,选择Compiliation类型为IP Catalog并勾选Create testbench,按下Generate生成IP核。

  三、仿真测试

  根据User Guide介绍sysGen是“周期和比特精准的”,我们还是在Vivado环境下再次验证下。netlist文件夹内子文件夹ip_catalog中为IP核示例工程,由于自动生成了testbench,打开后直接进行行为仿真。sysGen在创建testbench时会将经过gatein和gateout的数据储存到文件中,testbench进行的工作为:将gatein数据作为测试激励送入到相应设计输入端口,之后把设计输出得到结果与gateout文件数据进行逐一比较从而验证设计是否与sysGen环境下仿真结果一致。

  发现个比较有意思的现象,自动生成的testbench中clock生成并约束的50MHz,而是认为进行了拓展。

  仿真波形如图:

  将clock处改动为50MHz后,经过测试发现如果系统一开始就输入数据,前几个数据没有被真正处理,输出错误。可能是软件BUG吧,不过这种情况也非常少见,实际系统中输入数据大多情况会启动一段时间后才输入。这里等待100ns后再启动clock翻转:

  改动后仿真波形:

  四、AXI-Stream总线形式IP

  到此算法IP的设计与验证结束。如果想将这个IP核导入到IP Integrator中作为CPU的外设,其接口必须满足AXI总线标准,因此回到sysGen中更改端口名称和位宽。端口要符合AXI-Stream标准信号名称,位宽为8bit整数倍。

  

o4YBAF9uKEiAVeSPAARNJArcqqo731.png


  生成IP核后,打开新的工程,导入该IP核到repository。

  五、Block Design系统搭建

  系统结构与上一篇该系列博文类似,均是以AXI DMA为核心的Loop系统,只是将AXI-Stream Data FIFO改成了自定义IP核。由于IP核slave和master接口只包含tdata和tvalid信号,因此需要添加接口衔接的一些简单逻辑。tready信号和tkeep信号直接连接constant使用常数驱动,DMA的s_axis_s2mm接口的tlast由wrapper内计数器逻辑驱动,将system中FCLK_CLK0 peripheral_aresetn m_axis_tvalid和s_axis_s2mm_tlast信号引出到wrapper中。

  有一点比较坑:自定义IP通过AXI总线与DMA互联时,总线下相应的接口不一定会正确对应,所以需要分别将两端的每个接口相连。可以通过打开综合后的设计来确认连线无误。

  自动生成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

  当自定义IP核输出256个数据时,拉高tlast信号结束传输。打开综合后的设计,添加调试探针,抓取DMA与自定义IP之间的接口信号,set up debug后完成接下来的流程。

  六、软硬件联调

  在硬件系统中定义数据帧长度为256个,数据位宽为16bit,因此C代码中DMA启动传输函数中数据长度参数为512byte。测试数据生成与检测代码非常简单:

  我们直接查看ILA抓取AXI S总线波形:

  看到CPU产生数据从1到4重复递增,IP核输出结果从2到8重复递增,输出为输入的2倍。

  传输完成后进入DMA发送和接收中断,软件检测结果正确。在Memory窗口能够直接查看内存绝对地址里的数据,选定DDR接收缓存区起始地址,其中的数据与AXI总线传回数据一致,证明系统联调成功。之后任意算法模块均可采用本文方式进行设计和集成,可以说一劳永逸!


责任编辑:David

【免责声明】

1、本文内容、数据、图表等来源于网络引用或其他公开资料,版权归属原作者、原发表出处。若版权所有方对本文的引用持有异议,请联系拍明芯城(marketing@iczoom.com),本方将及时处理。

2、本文的引用仅供读者交流学习使用,不涉及商业目的。

3、本文内容仅代表作者观点,拍明芯城不对内容的准确性、可靠性或完整性提供明示或暗示的保证。读者阅读本文后做出的决定或行为,是基于自主意愿和独立判断做出的,请读者明确相关结果。

4、如需转载本方拥有版权的文章,请联系拍明芯城(marketing@iczoom.com)注明“转载原因”。未经允许私自转载拍明芯城将保留追究其法律责任的权利。

拍明芯城拥有对此声明的最终解释权。

相关资讯

方案推荐
基于MC33771主控芯片的新能源锂电池管理系统解决方案

基于MC33771主控芯片的新能源锂电池管理系统解决方案

AMIC110 32位Sitara ARM MCU开发方案

AMIC110 32位Sitara ARM MCU开发方案

基于AMIC110多协议可编程工业通信处理器的32位Sitara ARM MCU开发方案

基于AMIC110多协议可编程工业通信处理器的32位Sitara ARM MCU开发方案

基于展讯SC9820超低成本LTE芯片平台的儿童智能手表解决方案

基于展讯SC9820超低成本LTE芯片平台的儿童智能手表解决方案

基于TI公司的AM437x双照相机参考设计

基于TI公司的AM437x双照相机参考设计

基于MTK6580芯片的W2智能手表解决方案

基于MTK6580芯片的W2智能手表解决方案