Setting Up the Development Environment for the SDR-B1

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

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.

 

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>