1. Overview
SDR-B1 is a SDR hardware platform launched by Zencheer Communication. It uses Xilinx Zynq XC7Z045 FPGA and ADI AD9361/AD9363. Its size is as small as 59*88mm. It is suitable for applications such as drone networking and broadband data transmission. This document describes the setup process for the SDR-B1 development environment and is intended for engineers with a certain level of technical background.
The hardware architecture of the SDR-B1 is shown in the figure below.
The setup process for the development environment is roughly divided into three parts: creating a Vivado project based on the SDR-B1 hardware design to generate the bitstream and HDF files, setting up the PetaLinux project, and performing tests using the official ADI software.
2. Related Software
- cygwin
- Xilinx Vivado 2019.1, you need to log in to download it, and you cannot use the free license, otherwise, the XC7Z045 is not supported.
- Xilinx Petalinux 2019.1, you need to log in to download it, too.
- ADI meta-adi 2019_R2
- ADI hdl_2019_r2
- ADI IIO Oscilloscope
Note that ADI HDL 2019_R2 must be used with Vivado 2019.1.
3. Create the Vivado Project
(1) Install Cygwin, and during the installation select make and git under the Devel category, the required dependency packages will be selected automatically.
(2) Add the directories where Cygwin and Vivado are installed to the system environment variables, as shown in the figure below.
(3) Download and extract hdl_2019_r2, place it in an appropriate directory, run Cygwin64 Terminal, switch to the hdl-hdl_2019_r2\projects\adrv9361z7035 directory, run make, and wait for the compilation to finish to obtain the Vivado project files.
(4) Open the project file under ccbob_lvds with Vivado, then save the project as a new one via File --> Project --> Save As. Enter sdr-b1 in the Project name field and select the E:/Projects directory in the Project location field, as shown in the figure below.
(5) Double-click system.bd in the project files, and the block diagram will appear in the window on the right, as shown in the figure below.
(6) Double-click the ZYNQ block and reconfigure it according to the actual SDR-B1 hardware, mainly the MIO, RAM, and the operating voltages of BANK0/1. For SDR-B1, the specific settings are summarized as follows:
MIO settings
| 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 settings
| 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) Since the SDR-B1 does not use the serial transceivers, delete axi_pz_xcvrlb and its related connections from the block diagram. Then connect axi_gpreg to the M05_AXI port of axi_cpu_interconnect. Double-click axi_cpu_interconnect and change Number of Master Interfaces to 6, as shown in the figure below.
Then validate the design to ensure there are no errors.
(8) Click Settings under Project Manager and change the device to XC7Z045FFG900-2.
(9) Modify system_top.v and the constraint files, and comment out gt_ref_clk, gt_rx_n, gt_rx_p, gt_tx_n, and gt_tx_p in system_wrapper. Then generate the bitstream. If errors occur due to missing files, copy the files from the original hdl directory. The modified system_top.v is as follows.
`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) Click on generate bitstream, after the bitstream file is generated, export the hardware, then copy out system_top.hdf and system_top.bit for use in the PetaLinux build.
4. Setting Up the PetaLinux Project
We recommend using Ubuntu 18.04.6 LTS to build the PetaLinux project. In this document, the code is stored in the /home/lics/data/code directory.
(1) Log in to Ubuntu, switch to the /home/lics/data/code directory, and enter the following commands:
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) Obtain the meta-adi code by entering the following commands in sequence:
git clone https://github.com/analogdevicesinc/meta-adi.git
cd meta-adi
git checkout 2019_R2
Modify meta-adi-xilinx/recipes-bsp/device-tree/files/pl-delete-nodes-zynq-adrv9361-z7035-bob.dtsi, remove the line /delete-node/ &axi_pz_xcvrlb; from it. After this modification, the pl-delete-nodes-zynq-adrv9361-z7035-bob.dtsi file is as follows:
/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) Configure the sdr_b1 project by entering the following commands in sequence (the /home/lics/data/share/sdr_b1/ directory contains the system_top.hdf and system_top.bit files).
cd sdr_b1
cp -a /home/lics/data/share/sdr_b1/* .
petalinux-config --get-hw-description=/home/lics/data/code/petalinux/sdr_b1
On the configuration screen, select Yocto Settings and press Enter. On the next configuration screen, select User Layers and press Enter. In user layer 0, enter the path to meta-adi-core, i.e. /home/lics/data/code/petalinux/meta-adi/meta-adi-core. In user layer 1, enter the path to meta-adi-xilinx, i.e. /home/lics/data/code/petalinux/meta-adi/meta-adi-xilinx, as shown in the figure below.
Then exit and save.
Edit project-spec/meta-user/conf/petalinuxbsp.conf and add the following line:
KERNEL_DTB = "zynq-adrv9361-z7035-bob"
(4) Build PetaLinux by entering the following commands:
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/
At this point, you should be able to see the generated binary files in the /home/lics/data/share/linux directory.
5. Firmware Verification
(1) Copy the BOOT.bin and image.ub files obtained in step 4 to the TF card. Note that the TF card must be formatted as FAT32, not FAT, otherwise an “Unable to read image.ub” error will occur.
(2) Insert the TF card into the TF card slot of the SDR-B1, properly connect the SDR-B1’s Ethernet port, serial port, and power supply, and connect the host PC’s serial port to the SDR-B1’s UART1.
(3) Run a serial terminal program such as PuTTY, set the baud rate to 115200, then power on the SDR-B1. You should see the SDR-B1 boot messages, as shown in the figure below.
(4) After the system has finished booting, enter the username root and the password analog to log into Linux. Then enter the following command to configure the IP address for eth0. Make sure that the host PC and the SDR-B1 have IP addresses in the same subnet.
ifconfig eth0 192.168.2.77
(5) Run the ADI IIO Oscilloscope software. In the dialog that pops up, click Manual, and enter ip:192.168.2.77 in the address field. Be sure to enter it completely, otherwise it will not work properly.
(6) Click Refresh, and you will see the relevant information for the SDR-B1, as shown in the figure below.
(7) Click Connect to establish a connection with the SDR-B1, after which you can properly acquire the relevant waveforms, as shown in the figure below.









