1. 概述
SDR-B1是正旗通信推出的软件无线电硬件平台,采用Xilinx Zynq XC7Z045 FPGA及ADI AD9361/AD9363无线收发芯片,其尺寸仅为59*88mm,适用于无人机组网、宽带数据传输等应用场景。本文档给出SDR-B1开发环境的搭建过程,适合于具备一定技术基础的工程师。
SDR-B1的硬件架构如下图所示。
开发环境的搭建过程大致分为三个部分:根据SDR-B1的硬件设计搭建Vivado工程并得到Bitstream及HDF文件,搭建Petalinux工程,使用ADI官方软件进行测试。
2. 涉及到的软件
- cygwin
- Xilinx Vivado 2019.1,需要登陆后下载,不能使用免费license,否则不支持7045
- Xilinx Petalinux 2019.1,需要登陆后下载
- ADI meta-adi 2019_R2
- ADI hdl_2019_r2
- ADI IIO Oscilloscope
注意,ADI hdl 2019_R2必须使用Vivado 2019.1。
3. 创建Vivado工程
(1) 安装cygwin,安装过程中,选择devel分类下面的make与git,会自动选择依赖包。
(2) 将cygwin及Vivado所在的目录添加至系统环境变量,如下图所示。
(3) 下载并解压hdl_2019_r2,放在合适的目录下,运行Cygwin64 Terminal,切换到hdl-hdl_2019_r2\projects\adrv9361z7035目录下,make,等待编译完成,得到Vivado工程文件。
(4) 使用Vivado打开ccbob_lvds下面的工程文件,然后将工程另存为另一个工程,File-->Project-->Save as,Project name一栏填写sdr-b1,Project location一栏选择E:/Projects目录,如下图所示。
(5) 双击工程文件中的system.bd,右侧窗口出现框图,如下图所示。
(6) 双击ZYNQ,根据SDR-B1的实际情况重新配置,主要就是MIO、RAM及BANK0/1的工作电压,对于SDR-B1,具体设置汇总如下:
MIO设置
MIO Pin | Peripheral | Signal | IO Type |
MIO 0 | NAND Flash | cs | LVCMOS 3.3V |
MIO 1 | GPIO | gpio[1] | LVCMOS 3.3V |
MIO 2 | NAND Flash | ale | LVCMOS 3.3V |
MIO 3 | NAND Flash | we_b | LVCMOS 3.3V |
MIO 4 | NAND Flash | data[2] | LVCMOS 3.3V |
MIO 5 | NAND Flash | data[0] | LVCMOS 3.3V |
MIO 6 | NAND Flash | data[1] | LVCMOS 3.3V |
MIO 7 | NAND Flash | cle | LVCMOS 3.3V |
MIO 8 | NAND Flash | re_b | LVCMOS 3.3V |
MIO 9 | NAND Flash | data[4] | LVCMOS 3.3V |
MIO 10 | NAND Flash | data[5] | LVCMOS 3.3V |
MIO 11 | NAND Flash | data[6] | LVCMOS 3.3V |
MIO 12 | NAND Flash | data[7] | LVCMOS 3.3V |
MIO 13 | NAND Flash | data[3] | LVCMOS 3.3V |
MIO 14 | NAND Flash | busy | LVCMOS 3.3V |
MIO 15 | GPIO | gpio[15] | LVCMOS 3.3V |
MIO 16 | Enet 0 | tx_clk | LVCMOS 1.8V |
MIO 17 | Enet 0 | txd[0] | LVCMOS 1.8V |
MIO 18 | Enet 0 | txd[1] | LVCMOS 1.8V |
MIO 19 | Enet 0 | txd[2] | LVCMOS 1.8V |
MIO 20 | Enet 0 | txd[3] | LVCMOS 1.8V |
MIO 21 | Enet 0 | tx_ctl | LVCMOS 1.8V |
MIO 22 | Enet 0 | rx_clk | LVCMOS 1.8V |
MIO 23 | Enet 0 | rxd[0] | LVCMOS 1.8V |
MIO 24 | Enet 0 | rxd[1] | LVCMOS 1.8V |
MIO 25 | Enet 0 | rxd[2] | LVCMOS 1.8V |
MIO 26 | Enet 0 | rxd[3] | LVCMOS 1.8V |
MIO 27 | Enet 0 | rx_ctl | LVCMOS 1.8V |
MIO 28 | Enet 1 | tx_clk | LVCMOS 1.8V |
MIO 29 | Enet 1 | txd[0] | LVCMOS 1.8V |
MIO 30 | Enet 1 | txd[1] | LVCMOS 1.8V |
MIO 31 | Enet 1 | txd[2] | LVCMOS 1.8V |
MIO 32 | Enet 1 | txd[3] | LVCMOS 1.8V |
MIO 33 | Enet 1 | tx_ctl | LVCMOS 1.8V |
MIO 34 | Enet 1 | rx_clk | LVCMOS 1.8V |
MIO 35 | Enet 1 | rxd[0] | LVCMOS 1.8V |
MIO 36 | Enet 1 | rxd[1] | LVCMOS 1.8V |
MIO 37 | Enet 1 | rxd[2] | LVCMOS 1.8V |
MIO 38 | Enet 1 | rxd[3] | LVCMOS 1.8V |
MIO 39 | Enet 1 | rx_ctl | LVCMOS 1.8V |
MIO 40 | SD 0 | clk | LVCMOS 1.8V |
MIO 41 | SD 0 | cmd | LVCMOS 1.8V |
MIO 42 | SD 0 | data[0] | LVCMOS 1.8V |
MIO 43 | SD 0 | data[1] | LVCMOS 1.8V |
MIO 44 | SD 0 | data[2] | LVCMOS 1.8V |
MIO 45 | SD 0 | data[3] | LVCMOS 1.8V |
MIO 46 | UART 0 | rx | LVCMOS 1.8V |
MIO 47 | UART 0 | tx | LVCMOS 1.8V |
MIO 48 | UART 1 | tx | LVCMOS 1.8V |
MIO 49 | UART 1 | rx | LVCMOS 1.8V |
MIO 50 | SD 0 | cd | LVCMOS 1.8V |
MIO 51 | ENET Reset | reset | LVCMOS 1.8V |
MIO 52 | Enet 0 | mdc | LVCMOS 1.8V |
MIO 53 | Enet 0 | mdio | LVCMOS 1.8V |
DDR 设置
Parameter name | Value |
Enable DDR | 1 |
Memory Part | MT41K128M16 JT-125 |
DRAM bus width | 32 Bit |
ECC | Disabled |
BURST Length (lppdr only) | 8 |
Internal Vref | 0 |
Operating Frequency (MHz) | 533.333333 |
HIGH temperature | Normal (0-85) |
DRAM IC bus width | 16 Bits |
DRAM Device Capacity | 2048 MBits |
Speed Bin | DDR3_1066F |
BANK Address Count | 3 |
ROW Address Count | 14 |
COLUMN Address Count | 10 |
CAS Latency | 7 |
CAS Write Latency | 6 |
RAS to CAS Delay | 7 |
RECHARGE Time | 7 |
tRC (ns ) | 48.75 |
tRASmin ( ns ) | 35 |
tFAW | 40 |
ADDITIVE Latency | 0 |
Write levelling | 1 |
Read gate | 1 |
Read gate | 1 |
DQS to Clock delay [0] (ns) | -0.053 |
DQS to Clock delay [1] (ns) | -0.059 |
DQS to Clock delay [2] (ns) | 0.065 |
DQS to Clock delay [3] (ns) | 0.066 |
Board delay [0] (ns) | 0.264 |
Board delay [1] (ns) | 0.265 |
Board delay [2] (ns) | 0.33 |
Board delay [3] (ns) | 0.33 |
(7) 由于SDR-B1没有用到串行收发器,所以删除框图中axi_pz_xcvrlb及相关的连接线;将axi_gpreg连接至axi_cpu_interconnet的M05_AXI端口;双击axi_cpu_interconnet,将Number of Master Interfaces改为6,如下图。
然后validate design,保证无错。
(8) 点击Project Manager下面的Settings,修改芯片型号为XC7Z045FFG900-2。
(9) 修改system_top.v及约束文件,并且注释掉system_wrapper中的gt_ref_clk,gt_rx_n,gt_rx_p,gt_tx_n,gt_tx_p,然后Generate Bitsteam,如果因为缺少文件报错,则把原hdl目录下的文件复制过去,修改过后的system_top.v如下。
`timescale 1ns/100ps
module system_top (
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,
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,
inout iic_scl,
inout iic_sda,
// inout [19:0] gpio_bd,
input rx_clk_in_p,
input rx_clk_in_n,
input rx_frame_in_p,
input rx_frame_in_n,
input [ 5:0] rx_data_in_p,
input [ 5:0] rx_data_in_n,
output tx_clk_out_p,
output tx_clk_out_n,
output tx_frame_out_p,
output tx_frame_out_n,
output [ 5:0] tx_data_out_p,
output [ 5:0] tx_data_out_n,
output enable,
output txnrx,
// input clkout_in,
// output clkout_out,
inout gpio_clksel,
inout gpio_resetb,
inout gpio_sync,
inout gpio_en_agc,
inout [ 3:0] gpio_ctl,
inout [ 7:0] gpio_status,
output spi_csn,
output spi_clk,
output spi_mosi,
input spi_miso,
input clk_pl,
input rst_in,
output led1,
output led2,
output led3,
output led4
// output [85:0] gp_out,
// input [85:0] gp_in
// input gt_ref_clk_p,
// input gt_ref_clk_n,
// output [ 3:0] gt_tx_p,
// output [ 3:0] gt_tx_n,
// input [ 3:0] gt_rx_p,
// input [ 3:0] gt_rx_n
);
reg [26:0] clk_ref=27'd0;
always@(posedge clk_pl)
begin
if(~rst_in)
clk_ref <= 0;
else
clk_ref <=clk_ref + 1'b1;
end
assign led1=clk_ref[26];
assign led2=clk_ref[26];
assign led3=clk_ref[26];
assign led4=clk_ref[26];
// internal signals
// wire gt_ref_clk;
// wire [95:0] gp_out_s;
// wire [95:0] gp_in_s;
wire [63:0] gpio_i;
wire [63:0] gpio_o;
wire [63:0] gpio_t;
// assignments
// assign clkout_out = clkout_in;
// assign gp_out[85:0] = gp_out_s[85:0];
// assign gp_in_s[95:86] = gp_out_s[95:86];
// assign gp_in_s[85: 0] = gp_in[85:0];
// instantiations
// IBUFDS_GTE2 i_ibufds_gt_ref_clk (
// .CEB (1'd0),
// .I (gt_ref_clk_p),
// .IB (gt_ref_clk_n),
// .O (gt_ref_clk),
// .ODIV2 ());
// board gpio - 31-0
assign gpio_i[31:20] = gpio_o[31:20];
assign gpio_i[19:0] = gpio_o[19:0];
// ad_iobuf #(.DATA_WIDTH(20)) i_iobuf_bd (
// .dio_t (gpio_t[19:0]),
// .dio_i (gpio_o[19:0]),
// .dio_o (gpio_i[19:0]),
// .dio_p (gpio_bd));
// ad9361 gpio - 63-32
assign gpio_i[63:52] = gpio_o[63:52];
assign gpio_i[50:47] = gpio_o[50:47];
ad_iobuf #(.DATA_WIDTH(16)) i_iobuf (
.dio_t ({gpio_t[51], gpio_t[46:32]}),
.dio_i ({gpio_o[51], gpio_o[46:32]}),
.dio_o ({gpio_i[51], gpio_i[46:32]}),
.dio_p ({ gpio_clksel, // 51:51
gpio_resetb, // 46:46
gpio_sync, // 45:45
gpio_en_agc, // 44:44
gpio_ctl, // 43:40
gpio_status})); // 39:32
// instantiations
system_wrapper i_system_wrapper (
.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),
.enable (enable),
.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),
.gp_in_0 (32'd0), //not used
.gp_in_1 (32'd0), //not used
.gp_in_2 (32'd0), //not used
.gp_in_3 (32'd0), //not used
.gp_out_0 (), //not used
.gp_out_1 (), //not used
.gp_out_2 (), //not used
.gp_out_3 (), //not used
.gpio_i (gpio_i),
.gpio_o (gpio_o),
.gpio_t (gpio_t),
.gps_pps (1'b0),
// .gt_ref_clk (1'b0), //not used
// .gt_rx_n (), //not used
// .gt_rx_p (), //not used
// .gt_tx_n (), //not used
// .gt_tx_p (), //not used
.iic_main_scl_io (iic_scl), //not used
.iic_main_sda_io (iic_sda), //not used
.otg_vbusoc (1'b0),
.rx_clk_in_n (rx_clk_in_n),
.rx_clk_in_p (rx_clk_in_p),
.rx_data_in_n (rx_data_in_n),
.rx_data_in_p (rx_data_in_p),
.rx_frame_in_n (rx_frame_in_n),
.rx_frame_in_p (rx_frame_in_p),
.spi0_clk_i (1'b0),
.spi0_clk_o (spi_clk),
.spi0_csn_0_o (spi_csn),
.spi0_csn_1_o (),
.spi0_csn_2_o (),
.spi0_csn_i (1'b1),
.spi0_sdi_i (spi_miso),
.spi0_sdo_i (1'b0),
.spi0_sdo_o (spi_mosi),
.spi1_clk_i (1'b0),
.spi1_clk_o (),
.spi1_csn_0_o (),
.spi1_csn_1_o (),
.spi1_csn_2_o (),
.spi1_csn_i (1'b1),
.spi1_sdi_i (1'b0),
.spi1_sdo_i (1'b0),
.spi1_sdo_o (),
.tdd_sync_i (1'b0),
.tdd_sync_o (),
.tdd_sync_t (),
.tx_clk_out_n (tx_clk_out_n),
.tx_clk_out_p (tx_clk_out_p),
.tx_data_out_n (tx_data_out_n),
.tx_data_out_p (tx_data_out_p),
.tx_frame_out_n (tx_frame_out_n),
.tx_frame_out_p (tx_frame_out_p),
.txnrx (txnrx),
.up_enable (gpio_o[47]),
.up_txnrx (gpio_o[48]));
endmodule
(10) Export Hardware,将system_top.hdf及system_top.bit复制出来,准备用于Petalinux的编译。
4. 搭建Petalinux工程
我们推荐使用Ubuntu 18.04.6 LTS搭建Petalinux工程,另外在本文档中,代码存放在/home/lics/data/code目录下。
(1) 登录Ubuntu,切换至/home/lics/data/code目录,输入以下命令
mkdir petalinux
cp petalinux-v2019.1-final-installer.run .
cd data/code/petalinux/
./petalinux-v2019.1-final-installer.run
source /home/lics/data/code/petalinux/settings.sh
petalinux-create --type project --template zynq --name sdr_b1
(2) 获取meta-adi代码,依次输入以下命令
git clone https://github.com/analogdevicesinc/meta-adi.git
cd meta-adi
git checkout 2019_R2
修改meta-adi-xilinx/recipes-bsp/device-tree/files/pl-delete-nodes-zynq-adrv9361-z7035-bob.dtsi文件,去掉其中的/delete-node/ &axi_pz_xcvrlb;一行,修改完成后的pl-delete-nodes-zynq-adrv9361-z7035-bob.dtsi如下所示
/delete-node/ &axi_ad9361;
/delete-node/ &misc_clk_0;
/delete-node/ &axi_ad9361_adc_dma;
/delete-node/ &axi_ad9361_dac_dma;
/delete-node/ &axi_gpreg;
/delete-node/ &axi_iic_main;
/delete-node/ &axi_sysid_0;
(3) 配置sdr_b1工程,依次输入以下命令(/home/lics/data/share/sdr_b1/目录存放的是system_top.hdf及system_top.bit文件)
cd sdr_b1
cp -a /home/lics/data/share/sdr_b1/* .
petalinux-config --get-hw-description=/home/lics/data/code/petalinux/sdr_b1
在出现的配置界面上选择Yocto Settings,敲击回车,然后在下一个配置界面上选择User Layers,敲击回车,在user layer 0中填入meta-adi-core的路径,即/home/lics/data/code/petalinux/meta-adi/meta-adi-core,在user layer 1中填入meta-adi-xilinx的路径即/home/lics/data/code/petalinux/meta-adi/meta-adi-xilinx,如下图。
然后退出并保存。
修改project-spec/meta-user/conf/petalinuxbsp.conf,添加一行
KERNEL_DTB = "zynq-adrv9361-z7035-bob"
(4) 编译Petalinux,输入以下命令
petalinux-build
cd images/linux/
petalinux-package --boot --format BIN --fsbl zynq_fsbl.elf --fpga system.bit --u-boot --force
cd ..
rm -rf /home/lics/data/share/linux
cp -a linux /home/lics/data/share/
至此,就可以在/home/lics/data/share/linux目录中看到编译得到的二进制文件了。
5. 固件验证
(1) 将第4步中得到的BOOT.bin及image.ub复制到TF卡中,请注意TF卡需要格式化为FAT32格式,而不是FAT格式,否则会出现Unable to read image.ub错误。
(2) 将TF卡插入SDR-B1的TF卡槽中,妥善连接SDR-B1的网口、串口及电源,并将上位机电脑的串口连接至SDR-B1的UART1上。
(3) 运行串口软件,如putty,将波特率设置为115200,为SDR-B1加电,即可看到SDR-B1的启动信息,如下图。
(4) 待系统启动完成后,输入用户名root,并输入密码analog,进入Linux系统,输入以下命令,为eth0配置IP地址,请确保上位机电脑与SDR-B1具有相同网段的IP地址。
ifconfig eth0 192.168.2.77
(5) 运行ADI IIO Oscilloscope 软件,在弹出的界面中点击Manual处,并在地址栏中填写ip:192.168.2.77,请务必完整填写,否则无法正常使用。
(7) 点击连接,即可与SDR-B1建立联系,并可正常获取相关波形,如下图。