高效的VIVADO BlockDesign设计方法:将自己设计的模块信号以总线形式聚合

微信公众号获取更多FPGA相关源码:
在这里插入图片描述

1.前言

在FPGA的顶层设计中,常常会涉及到诸多模块进行相互连接。通常情况下,我们会使用verilog语言中的模块例化,来完成各个模块之间的连接,但是这样可读性太差,过一段时间再来看项目,或者交给其他人,要理清模块之间的连接情况,需要额外花费大量时间。

2.使用BlockDesign图形化设计的好处

下图展示了基于802.11a协议设计OFDM发射机时的顶层各模块模块连接图,数据流和控制信号以总线的方式连接,这样线条就会很少,看上去就十分的清晰。

OFDM 802.11a 发射部分的顶层连接图

如果使用代码例化连接是下面这样:

//Copyright 1986-2018 Xilinx, Inc. All Rights Reserved.
//--------------------------------------------------------------------------------
//Tool Version: Vivado v.2018.3 (win64) Build 2405991 Thu Dec  6 23:38:27 MST 2018
//Date        : Tue May 28 14:50:05 2024
//Host        : BF-202305231136 running 64-bit major release  (build 9200)
//Command     : generate_target OFDM_TX.bd
//Design      : OFDM_TX
//Purpose     : IP block netlist
//--------------------------------------------------------------------------------
`timescale 1 ps / 1 ps

(* CORE_GENERATION_INFO = "OFDM_TX,IP_Integrator,{x_ipVendor=xilinx.com,x_ipLibrary=BlockDiagram,x_ipName=OFDM_TX,x_ipVersion=1.00.a,x_ipLanguage=VERILOG,numBlks=13,numReposBlks=13,numNonXlnxBlks=0,numHierBlks=0,maxHierDepth=0,numSysgenBlks=0,numHlsBlks=0,numHdlrefBlks=11,numPkgbdBlks=0,bdsource=USER,da_board_cnt=2,da_clkrst_cnt=2,synth_mode=Global}" *) (* HW_HANDOFF = "OFDM_TX.hwdef" *) 
module OFDM_TX
   (TxPWR,
    dac_din_rdy,
    dac_dout,
    dac_dout_Index,
    dac_dout_last,
    dac_dout_vld,
    mcu_config_din,
    mcu_config_din_start,
    mcu_config_din_vld,
    mcu_config_dout_rdy,
    mcu_mac_din,
    mcu_mac_din_vld,
    mcu_mac_dout_rdy,
    sys_clk,
    sys_rst_n);
  output [2:0]TxPWR;
  input dac_din_rdy;
  (* X_INTERFACE_INFO = "xilinx.com:signal:data:1.0 DATA.DAC_DOUT DATA" *) (* X_INTERFACE_PARAMETER = "XIL_INTERFACENAME DATA.DAC_DOUT, LAYERED_METADATA undef" *) output [15:0]dac_dout;
  (* X_INTERFACE_INFO = "xilinx.com:signal:data:1.0 DATA.DAC_DOUT_INDEX DATA" *) (* X_INTERFACE_PARAMETER = "XIL_INTERFACENAME DATA.DAC_DOUT_INDEX, LAYERED_METADATA undef" *) output [8:0]dac_dout_Index;
  output dac_dout_last;
  output dac_dout_vld;
  (* X_INTERFACE_INFO = "xilinx.com:signal:data:1.0 DATA.MCU_CONFIG_DIN DATA" *) (* X_INTERFACE_PARAMETER = "XIL_INTERFACENAME DATA.MCU_CONFIG_DIN, LAYERED_METADATA undef" *) input [20:0]mcu_config_din;
  input mcu_config_din_start;
  input mcu_config_din_vld;
  output mcu_config_dout_rdy;
  (* X_INTERFACE_INFO = "xilinx.com:signal:data:1.0 DATA.MCU_MAC_DIN DATA" *) (* X_INTERFACE_PARAMETER = "XIL_INTERFACENAME DATA.MCU_MAC_DIN, LAYERED_METADATA undef" *) input [7:0]mcu_mac_din;
  input mcu_mac_din_vld;
  output mcu_mac_dout_rdy;
  (* X_INTERFACE_INFO = "xilinx.com:signal:clock:1.0 CLK.SYS_CLK CLK" *) (* X_INTERFACE_PARAMETER = "XIL_INTERFACENAME CLK.SYS_CLK, CLK_DOMAIN OFDM_TX_sys_clk, FREQ_HZ 50000000, INSERT_VIP 0, PHASE 0.000" *) input sys_clk;
  (* X_INTERFACE_INFO = "xilinx.com:signal:reset:1.0 RST.SYS_RST_N RST" *) (* X_INTERFACE_PARAMETER = "XIL_INTERFACENAME RST.SYS_RST_N, INSERT_VIP 0, POLARITY ACTIVE_LOW" *) input sys_rst_n;

  wire clk_wiz_0_clk_out2;
  wire clk_wiz_0_locked;
  wire clk_wiz_clk_out1;
  wire [1:0]convenc_0_m_axis_conv_TDATA;
  wire [3:0]convenc_0_m_axis_conv_TID;
  wire convenc_0_m_axis_conv_TREADY;
  wire convenc_0_m_axis_conv_TSTRB;
  wire convenc_0_m_axis_conv_TVALID;
  wire [15:0]dac_0_dac_dout;
  wire [8:0]dac_0_dac_dout_Index;
  wire dac_0_dac_dout_last;
  wire dac_0_dac_dout_vld;
  wire dac_din_rdy_1;
  wire [15:0]ifft_0_m_axis_ifft_TDATA;
  wire ifft_0_m_axis_ifft_TLAST;
  wire ifft_0_m_axis_ifft_TREADY;
  wire [7:0]ifft_0_m_axis_ifft_TUSER;
  wire ifft_0_m_axis_ifft_TVALID;
  wire interleaver_1_0_m_axis_intv1_TDATA;
  wire [1:0]interleaver_1_0_m_axis_intv1_TID;
  wire interleaver_1_0_m_axis_intv1_TREADY;
  wire interleaver_1_0_m_axis_intv1_TSTRB;
  wire interleaver_1_0_m_axis_intv1_TVALID;
  wire interleaver_2_0_m_axis_intv2_TDATA;
  wire [1:0]interleaver_2_0_m_axis_intv2_TID;
  wire interleaver_2_0_m_axis_intv2_TREADY;
  wire interleaver_2_0_m_axis_intv2_TVALID;
  wire [15:0]maping_0_m_axis_map_TDATA;
  wire maping_0_m_axis_map_TREADY;
  wire [5:0]maping_0_m_axis_map_TUSER;
  wire maping_0_m_axis_map_TVALID;
  wire [20:0]mcu_config_din_1;
  wire mcu_config_din_start_1;
  wire mcu_config_din_vld_1;
  wire [7:0]mcu_mac_din_1;
  wire mcu_mac_din_vld_1;
  wire [15:0]pilot_0_m_axis_pilot_TDATA;
  wire pilot_0_m_axis_pilot_TLAST;
  wire pilot_0_m_axis_pilot_TREADY;
  wire pilot_0_m_axis_pilot_TVALID;
  wire puncture_0_m_axis_punt_TDATA;
  wire [1:0]puncture_0_m_axis_punt_TID;
  wire puncture_0_m_axis_punt_TREADY;
  wire puncture_0_m_axis_punt_TSTRB;
  wire puncture_0_m_axis_punt_TVALID;
  wire scramler_0_m_axis_scram_TDATA;
  wire [3:0]scramler_0_m_axis_scram_TID;
  wire scramler_0_m_axis_scram_TREADY;
  wire scramler_0_m_axis_scram_TSTRB;
  wire scramler_0_m_axis_scram_TVALID;
  wire [15:0]symbol_train_0_m_axis_train_TDATA;
  wire symbol_train_0_m_axis_train_TLAST;
  wire symbol_train_0_m_axis_train_TREADY;
  wire [8:0]symbol_train_0_m_axis_train_TUSER;
  wire symbol_train_0_m_axis_train_TVALID;
  wire sys_clk_1;
  wire sys_rst_n_1;
  wire [2:0]tx_mcu_0_TxPWR;
  wire tx_mcu_0_m_axis_mcu_TDATA;
  wire [3:0]tx_mcu_0_m_axis_mcu_TID;
  wire tx_mcu_0_m_axis_mcu_TREADY;
  wire tx_mcu_0_m_axis_mcu_TSTRB;
  wire tx_mcu_0_m_axis_mcu_TVALID;
  wire tx_mcu_0_mcu_config_dout_rdy;
  wire tx_mcu_0_mcu_dout_scram_load;
  wire [6:0]tx_mcu_0_mcu_dout_scram_seed;
  wire tx_mcu_0_mcu_mac_dout_rdy;
  wire tx_mcu_0_phy_rst_n;
  wire [0:0]util_vector_logic_0_Res;

  assign TxPWR[2:0] = tx_mcu_0_TxPWR;
  assign dac_din_rdy_1 = dac_din_rdy;
  assign dac_dout[15:0] = dac_0_dac_dout;
  assign dac_dout_Index[8:0] = dac_0_dac_dout_Index;
  assign dac_dout_last = dac_0_dac_dout_last;
  assign dac_dout_vld = dac_0_dac_dout_vld;
  assign mcu_config_din_1 = mcu_config_din[20:0];
  assign mcu_config_din_start_1 = mcu_config_din_start;
  assign mcu_config_din_vld_1 = mcu_config_din_vld;
  assign mcu_config_dout_rdy = tx_mcu_0_mcu_config_dout_rdy;
  assign mcu_mac_din_1 = mcu_mac_din[7:0];
  assign mcu_mac_din_vld_1 = mcu_mac_din_vld;
  assign mcu_mac_dout_rdy = tx_mcu_0_mcu_mac_dout_rdy;
  assign sys_clk_1 = sys_clk;
  assign sys_rst_n_1 = sys_rst_n;
  OFDM_TX_clk_wiz_0_0 clk_wiz_0
       (.clk_in1(sys_clk_1),
        .clk_out1(clk_wiz_clk_out1),
        .clk_out2(clk_wiz_0_clk_out2),
        .locked(clk_wiz_0_locked),
        .resetn(sys_rst_n_1));
  OFDM_TX_convenc_0_0 convenc_0
       (.clk(clk_wiz_clk_out1),
        .conv_din(scramler_0_m_axis_scram_TDATA),
        .conv_din_rate_con(scramler_0_m_axis_scram_TID),
        .conv_din_rdy(convenc_0_m_axis_conv_TREADY),
        .conv_din_sig_flag(scramler_0_m_axis_scram_TSTRB),
        .conv_din_vld(scramler_0_m_axis_scram_TVALID),
        .conv_dout(convenc_0_m_axis_conv_TDATA),
        .conv_dout_rate_con(convenc_0_m_axis_conv_TID),
        .conv_dout_rdy(scramler_0_m_axis_scram_TREADY),
        .conv_dout_sig_flag(convenc_0_m_axis_conv_TSTRB),
        .conv_dout_vld(convenc_0_m_axis_conv_TVALID),
        .rst_n(util_vector_logic_0_Res));
  OFDM_TX_dac_0_0 dac_0
       (.clk(clk_wiz_clk_out1),
        .clk_dac(clk_wiz_0_clk_out2),
        .dac_din_rdy(dac_din_rdy_1),
        .dac_dout(dac_0_dac_dout),
        .dac_dout_Index(dac_0_dac_dout_Index),
        .dac_dout_last(dac_0_dac_dout_last),
        .dac_dout_vld(dac_0_dac_dout_vld),
        .dac_ifft_din(ifft_0_m_axis_ifft_TDATA),
        .dac_ifft_din_Index(ifft_0_m_axis_ifft_TUSER),
        .dac_ifft_din_last(ifft_0_m_axis_ifft_TLAST),
        .dac_ifft_din_vld(ifft_0_m_axis_ifft_TVALID),
        .dac_ifft_dout_rdy(ifft_0_m_axis_ifft_TREADY),
        .dac_train_din(symbol_train_0_m_axis_train_TDATA),
        .dac_train_din_Index(symbol_train_0_m_axis_train_TUSER),
        .dac_train_din_last(symbol_train_0_m_axis_train_TLAST),
        .dac_train_din_vld(symbol_train_0_m_axis_train_TVALID),
        .dac_train_dout_rdy(symbol_train_0_m_axis_train_TREADY),
        .rst_n(util_vector_logic_0_Res));
  OFDM_TX_ifft_0_0 ifft_0
       (.clk(clk_wiz_clk_out1),
        .ifft_din(pilot_0_m_axis_pilot_TDATA),
        .ifft_din_last(pilot_0_m_axis_pilot_TLAST),
        .ifft_din_rdy(ifft_0_m_axis_ifft_TREADY),
        .ifft_din_vld(pilot_0_m_axis_pilot_TVALID),
        .ifft_dout(ifft_0_m_axis_ifft_TDATA),
        .ifft_dout_Index(ifft_0_m_axis_ifft_TUSER),
        .ifft_dout_last(ifft_0_m_axis_ifft_TLAST),
        .ifft_dout_rdy(pilot_0_m_axis_pilot_TREADY),
        .ifft_dout_vld(ifft_0_m_axis_ifft_TVALID),
        .rst_n(util_vector_logic_0_Res));
  OFDM_TX_interleaver_1_0_0 interleaver_1_0
       (.clk(clk_wiz_clk_out1),
        .intv1_din(puncture_0_m_axis_punt_TDATA),
        .intv1_din_Map_Type(puncture_0_m_axis_punt_TID),
        .intv1_din_rdy(interleaver_1_0_m_axis_intv1_TREADY),
        .intv1_din_sig_flag(puncture_0_m_axis_punt_TSTRB),
        .intv1_din_vld(puncture_0_m_axis_punt_TVALID),
        .intv1_dout(interleaver_1_0_m_axis_intv1_TDATA),
        .intv1_dout_Map_Type(interleaver_1_0_m_axis_intv1_TID),
        .intv1_dout_rdy(puncture_0_m_axis_punt_TREADY),
        .intv1_dout_sig_flag(interleaver_1_0_m_axis_intv1_TSTRB),
        .intv1_dout_vld(interleaver_1_0_m_axis_intv1_TVALID),
        .rst_n(util_vector_logic_0_Res));
  OFDM_TX_interleaver_2_0_0 interleaver_2_0
       (.clk(clk_wiz_clk_out1),
        .intv2_din(interleaver_1_0_m_axis_intv1_TDATA),
        .intv2_din_Map_Type(interleaver_1_0_m_axis_intv1_TID),
        .intv2_din_rdy(interleaver_2_0_m_axis_intv2_TREADY),
        .intv2_din_sig_flag(interleaver_1_0_m_axis_intv1_TSTRB),
        .intv2_din_vld(interleaver_1_0_m_axis_intv1_TVALID),
        .intv2_dout(interleaver_2_0_m_axis_intv2_TDATA),
        .intv2_dout_Map_Type(interleaver_2_0_m_axis_intv2_TID),
        .intv2_dout_rdy(interleaver_1_0_m_axis_intv1_TREADY),
        .intv2_dout_vld(interleaver_2_0_m_axis_intv2_TVALID),
        .rst_n(util_vector_logic_0_Res));
  OFDM_TX_maping_0_0 maping_0
       (.clk(clk_wiz_clk_out1),
        .map_din(interleaver_2_0_m_axis_intv2_TDATA),
        .map_din_Map_Type(interleaver_2_0_m_axis_intv2_TID),
        .map_din_rdy(maping_0_m_axis_map_TREADY),
        .map_din_vld(interleaver_2_0_m_axis_intv2_TVALID),
        .map_dout(maping_0_m_axis_map_TDATA),
        .map_dout_Index(maping_0_m_axis_map_TUSER),
        .map_dout_rdy(interleaver_2_0_m_axis_intv2_TREADY),
        .map_dout_vld(maping_0_m_axis_map_TVALID),
        .rst_n(util_vector_logic_0_Res));
  OFDM_TX_pilot_0_0 pilot_0
       (.clk(clk_wiz_clk_out1),
        .pilot_din(maping_0_m_axis_map_TDATA),
        .pilot_din_Index(maping_0_m_axis_map_TUSER),
        .pilot_din_rdy(pilot_0_m_axis_pilot_TREADY),
        .pilot_din_vld(maping_0_m_axis_map_TVALID),
        .pilot_dout(pilot_0_m_axis_pilot_TDATA),
        .pilot_dout_last(pilot_0_m_axis_pilot_TLAST),
        .pilot_dout_rdy(maping_0_m_axis_map_TREADY),
        .pilot_dout_vld(pilot_0_m_axis_pilot_TVALID),
        .rst_n(util_vector_logic_0_Res));
  OFDM_TX_puncture_0_1 puncture_0
       (.clk(clk_wiz_clk_out1),
        .punt_din(convenc_0_m_axis_conv_TDATA),
        .punt_din_rate_con(convenc_0_m_axis_conv_TID),
        .punt_din_rdy(puncture_0_m_axis_punt_TREADY),
        .punt_din_sig_flag(convenc_0_m_axis_conv_TSTRB),
        .punt_din_vld(convenc_0_m_axis_conv_TVALID),
        .punt_dout(puncture_0_m_axis_punt_TDATA),
        .punt_dout_Map_Type(puncture_0_m_axis_punt_TID),
        .punt_dout_rdy(convenc_0_m_axis_conv_TREADY),
        .punt_dout_sig_flag(puncture_0_m_axis_punt_TSTRB),
        .punt_dout_vld(puncture_0_m_axis_punt_TVALID),
        .rst_n(util_vector_logic_0_Res));
  OFDM_TX_scramler_0_0 scramler_0
       (.clk(clk_wiz_clk_out1),
        .rst_n(util_vector_logic_0_Res),
        .scram_din(tx_mcu_0_m_axis_mcu_TDATA),
        .scram_din_rate_con(tx_mcu_0_m_axis_mcu_TID),
        .scram_din_rdy(scramler_0_m_axis_scram_TREADY),
        .scram_din_sig_flag(tx_mcu_0_m_axis_mcu_TSTRB),
        .scram_din_vld(tx_mcu_0_m_axis_mcu_TVALID),
        .scram_dout(scramler_0_m_axis_scram_TDATA),
        .scram_dout_rate_con(scramler_0_m_axis_scram_TID),
        .scram_dout_rdy(tx_mcu_0_m_axis_mcu_TREADY),
        .scram_dout_sig_flag(scramler_0_m_axis_scram_TSTRB),
        .scram_dout_vld(scramler_0_m_axis_scram_TVALID),
        .scram_load(tx_mcu_0_mcu_dout_scram_load),
        .scram_seed(tx_mcu_0_mcu_dout_scram_seed));
  OFDM_TX_symbol_train_0_0 symbol_train_0
       (.clk(clk_wiz_clk_out1),
        .rst_n(util_vector_logic_0_Res),
        .train_din_rdy(symbol_train_0_m_axis_train_TREADY),
        .train_dout(symbol_train_0_m_axis_train_TDATA),
        .train_dout_Index(symbol_train_0_m_axis_train_TUSER),
        .train_dout_last(symbol_train_0_m_axis_train_TLAST),
        .train_dout_vld(symbol_train_0_m_axis_train_TVALID));
  OFDM_TX_tx_mcu_0_0 tx_mcu_0
       (.TxPWR(tx_mcu_0_TxPWR),
        .clk(clk_wiz_clk_out1),
        .mcu_config_din(mcu_config_din_1),
        .mcu_config_din_start(mcu_config_din_start_1),
        .mcu_config_din_vld(mcu_config_din_vld_1),
        .mcu_config_dout_rdy(tx_mcu_0_mcu_config_dout_rdy),
        .mcu_din_rdy(tx_mcu_0_m_axis_mcu_TREADY),
        .mcu_dout(tx_mcu_0_m_axis_mcu_TDATA),
        .mcu_dout_rate_con(tx_mcu_0_m_axis_mcu_TID),
        .mcu_dout_scram_load(tx_mcu_0_mcu_dout_scram_load),
        .mcu_dout_scram_seed(tx_mcu_0_mcu_dout_scram_seed),
        .mcu_dout_sig_flag(tx_mcu_0_m_axis_mcu_TSTRB),
        .mcu_dout_vld(tx_mcu_0_m_axis_mcu_TVALID),
        .mcu_mac_din(mcu_mac_din_1),
        .mcu_mac_din_vld(mcu_mac_din_vld_1),
        .mcu_mac_dout_rdy(tx_mcu_0_mcu_mac_dout_rdy),
        .phy_rst_n(tx_mcu_0_phy_rst_n),
        .rst_n(clk_wiz_0_locked),
        .tx_end(1'b0));
  OFDM_TX_util_vector_logic_0_1 util_vector_logic_0
       (.Op1(clk_wiz_0_locked),
        .Op2(tx_mcu_0_phy_rst_n),
        .Res(util_vector_logic_0_Res));
endmodule

是不是,看着就头大?但是使用BlockDesign图形化设计,也不一定就那么好,如果连接的线条太多也是很容易出错的,很容易错连,漏连。相比之下,使用verilog例化的话,能够减少出错的概率。

但是如果能在设计中添加总线,那么一堆信号就可以使用一根线来进行来接,这样就会使BlockDesign的设计出错概率大大减小,连接思路也会更加清晰。

3.如何使用BlockDesign

新建FPGA工程,在完成了自己的各个子模块之后,点击Creat Block Design,创建一个bd文件。

Creat Block Design

Block Design其实就是一个容器,这个容器里面我们放入IP并且通过把IP接口通过连线的方式相互关联,这样图形化的设计效率要高一些,也更加直观。

单击"+"号添加我们需要用到的IP:

添加IP

输入IP的关键字可以进行搜索:

搜索IP

想要添加自己的模块,找到Design Sources里面需要添加的模块,右键选择Add Module to Block Design。

添加自己的模块

添加完成之后,就可以根据需求去进行模块之间的连接。连接完成之后,顶层的输入输出需要通过Creat Port进行添加。在空白部分点击右键,选择Creat Port:

空白部分点击右键,选择Creat Port

然后配置端口的相关参数。

端口参数

比如这样,配置一个输入时钟端口s_aclk:
输入时钟端口

输入时钟端口s_aclk,和模块进行连接:

端口和模块进行连接

Design Sources里面找到db文件,右键选择Creat HDL Wrapper,可以生成顶层模块的verlig HDL的例化连接代码。如上面第2节所展示的代码那样。

Creat HDL Wrapper

4.如何将BlockDesign里面的信号聚合成总线形式

一般信号聚合成总线形式,有两种方法:端口声明遵循xilinx对于总线的命名方式、使用xilinx的原语进行总线封装。

4.1 端口声明遵循xilinx对于总线的命名方式

这里以AXI Stream协议为例,端口命名时遵循,从机到主机以s_axis_开头,主机到从机以m_axis_开头,代码如下所示:

module test123(
		input  wire m_aclk					,
		input  wire s_aclk                  ,
		input  wire s_aresetn               ,
		input  wire s_axis_tvalid           ,
		output wire s_axis_tready           ,
		input  wire [15 : 0] s_axis_tdata   ,
		input  wire s_axis_tlast            ,
		input  wire [7 : 0] s_axis_tuser    ,
		output wire m_axis_tvalid           ,
		input  wire m_axis_tready           ,
		output wire [15 : 0] m_axis_tdata   ,
		output wire m_axis_tlast            ,
		output wire [7 : 0] m_axis_tuser    
    );
endmodule

添加到Block Design里面,端口就聚合在一起,形成了总线。

AXI Stream

4.2 使用xilinx的原语进行总线封装

左上角,选择Lanquage Templates,打开

Lanquage Templates

输入AXI Stream:

Lanquage Templates AXI Stream

可以看到相关原语如何使用:

// Normally AXI is automatically inferred.  However, if the names of your ports do not match, you can force the
// the creation of an interface and map the physical ports to the logical ports by using the X_INTERFACE_INFO
// attribute before each physical port
// Parameters are typically computed by the Block Diagram and annotated onto the cell (no need to specify these)
// axis - AMBA AXI4-Stream Interface (slave directions)
// 
// Allowed parameters:
//  CLK_DOMAIN                - Clk Domain                (string default: <blank>) 
//  PHASE                     - Phase                     (float) 
//  FREQ_HZ                   - Frequency                 (float default: 100000000) 
//  LAYERED_METADATA          - Layered Metadata          (string default: <blank>) 
//  HAS_TLAST                 - Has Tlast                 (long) {false - 0, true - 1}
//  HAS_TKEEP                 - Has Tkeep                 (long) {false - 0, true - 1}
//  HAS_TSTRB                 - Has Tstrb                 (long) {false - 0, true - 1}
//  HAS_TREADY                - Has Tready                (long) {false - 0, true - 1}
//  TUSER_WIDTH               - Tuser Width               (long) 
//  TID_WIDTH                 - Tid Width                 (long) 
//  TDEST_WIDTH               - Tdest Width               (long) 
//  TDATA_NUM_BYTES           - Tdata Num Bytes           (long) 
module my_module (
  (* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 <interface_name> TID" *)
  // Uncomment the following to set interface specific parameter on the bus interface.
  //  (* X_INTERFACE_PARAMETER = "CLK_DOMAIN <value>,PHASE <value>,FREQ_HZ <value>,LAYERED_METADATA <value>,HAS_TLAST <value>,HAS_TKEEP <value>,HAS_TSTRB <value>,HAS_TREADY <value>,TUSER_WIDTH <value>,TID_WIDTH <value>,TDEST_WIDTH <value>,TDATA_NUM_BYTES <value>" *)
  input [<left_bound>:0] <s_tid>, // Transfer ID tag (optional)
  (* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 <interface_name> TDEST" *)
  input [<left_bound>:0] <s_tdest>, // Transfer Destination (optional)
  (* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 <interface_name> TDATA" *)
  input [<left_bound>:0] <s_tdata>, // Transfer Data (optional)
  (* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 <interface_name> TSTRB" *)
  input [<left_bound>:0] <s_tstrb>, // Transfer Data Byte Strobes (optional)
  (* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 <interface_name> TKEEP" *)
  input [<left_bound>:0] <s_tkeep>, // Transfer Null Byte Indicators (optional)
  (* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 <interface_name> TLAST" *)
  input <s_tlast>, // Packet Boundary Indicator (optional)
  (* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 <interface_name> TUSER" *)
  input [<left_bound>:0] <s_tuser>, // Transfer user sideband (optional)
  (* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 <interface_name> TVALID" *)
  input <s_tvalid>, // Transfer valid (required)
  (* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 <interface_name> TREADY" *)
  output <s_tready>, // Transfer ready (optional)
//  additional ports here
);

在自己的代码里面,像例子那样,端口前面添加原语,进行总线聚合。

module dac(
																				input				clk					,
																				input				clk_dac				,
																				input				rst_n       		,			
(* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 s_axis_ifft_dac TDATA" *)	input	[15:0]		dac_ifft_din   		,
(* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 s_axis_ifft_dac TVALID" *)	input				dac_ifft_din_vld	,	
(* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 s_axis_ifft_dac TLAST" *)	input				dac_ifft_din_last   ,
(* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 s_axis_ifft_dac TUSER" *)	input	[7:0]		dac_ifft_din_Index	,
(* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 s_axis_ifft_dac TREADY" *)	output				dac_ifft_dout_rdy	,
	
(* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 s_axis_train_dac TDATA" *)	input	[15:0]		dac_train_din    	,
(* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 s_axis_train_dac TVALID" *)input				dac_train_din_vld	,
(* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 s_axis_train_dac TLAST" *)	input				dac_train_din_last 	, 	
(* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 s_axis_train_dac TUSER" *)	input	[8:0]		dac_train_din_Index	,
(* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 s_axis_train_dac TREADY" *)output				dac_train_dout_rdy	,
  
(* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 m_axis_dac TREADY" *)  	input				dac_din_rdy			,
(* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 m_axis_dac TDATA" *)		output	[15:0]		dac_dout    		,	
(* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 m_axis_dac TVALID" *)		output				dac_dout_vld		,	
(* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 m_axis_dac TLAST" *)		output				dac_dout_last  		,
(* X_INTERFACE_INFO = "xilinx.com:interface:axis:1.0 m_axis_dac TUSER" *)		output	[8:0]		dac_dout_Index  	

);

然后在Block Design里面就完成了总线的聚合。

image

当然如果有需求,也可以使用自己定义的总线,而不使用xilinx官方的总线,这个相对比较复杂,后面有机会再讲。

微信公众号获取更多FPGA相关源码:
在这里插入图片描述

### 回答1: Vivado Block Design 是一种用于 FPGA 设计的可视化设计工具,可以通过简单的拖拽和连接操作快速设计出复杂的硬件电路。在 Vivado Block Design 中,用户可以将不同的硬件模块抽象成一个个 IP 核,并将它们拼接在一起构成一个完整的硬件系统。同时,用户还可以通过 Block Design 来进行 RTL 设计和仿真等工作,提高设计效率和设计质量。 ### 回答2: Vivado Block Design 是 Xilinx 公司的一款图形化设计工具,可以用于 FPGA设计和实现。它可以帮助设计人员在不需要编写代码的情况下,通过拖拽和连接各种模块来创建一个完整的 FPGA 设计Block Design 的核心组成部分是 IP(Intellectual Property)模块。这些模块提供了各种功能,比如时钟管理、数据传输等,让设计人员能够轻松地将各种模块打包在一起创建一个完整的设计。 使用 Block Design 进行 FPGA设计有许多优点。首先,它可以加速设计时间,因为设计人员只需要拖放和连接各种 IP 模块,而无需进行繁琐的手动设计。此外,它还可以提高设计的可重用性和可维护性,使得更容易进行调试和功能升级。 当设计人员使用 Vivado Block Design 时,他们可以从 IP 目录中选择不同的 IP 模块。这些 IP 模块既可以是由 Xilinx 公司提供的标准 IP,也可以是用户自己编写的 IP。此外,Block Design 的界面非常简单,任何人都可以在很短的时间内学会如何使用它。 总之,Vivado Block Design 是一款极为强大的 FPGA 设计工具,可以帮助设计人员快速创建高质量的 FPGA 设计。无论是从时间、可重用性还是可维护性来看,它都是一个高效能的工具,值得设计人员掌握和使用。 ### 回答3: Vivado Block Design 是一种基于 IP 核的设计方法,可以在 Vivado 工具中创建和管理复杂的 FPGA 系统。它的主要目的是简化 FPGA 设计流程,并提高设计效率和可重用性。 Vivado Block Design 是一个包含多个 IP 核的设计,这些 IP 核可以通过拖放和连接,用于创建复杂的逻辑系统。在 Vivado Block Design 中,设计人员可以通过 IP Integrator 界面来方便的建立复杂的硬件系统,并在此界面上建立各个 IP 和他们的连接方式。这种方法可以减少硬件设计人员的工作量,也可以增加他们的创作灵活性,进一步优化设计效率。 此外,Vivado Block Design 还具有简单且易于维护的特性。在设计过程中,设计人员可以将设计分成多个模块,从而提高设计的可重用性。这使得修改和维护单个模块成为可能,而不必打破系统整体功能。这也是一种很好的方式,可以使 FPGAs 设计团队更为高效地协作。 总之,Vivado Block设计是一种快速、高效设计FPGA System的方法,它极大地降低了硬件开发周期和成本。通过掌握Vivado Block Design的技术,设计人员可以更好地管理系统设计中的细节,并快速地创建可以满足应用需求的硬件系统。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值