part 2 · 2020. 12. 16. · noc_block_gain.v crossbar chdr axi-stream settings bus user code noc...

Post on 23-Jan-2021

12 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

RFNoC 3 WorkshopPart 2

Jonathon Pendlum – Ettus ResearchNeel Pandeya – Ettus Research

August 2020

1

▪ Part 1

▪ RFNoC Framework Overview

▪ Hands on Demos

▪ Part 2

▪ RFNoC FPGA & Software Architecture

▪ Hands on RFNoC Block Development

▪ Advanced RFNoC Topics

Schedule

2

▪ Two main ways to get RFNoC

▪ Install with PyBOMBs

▪ PyBOMBs install already done in our VM!

▪ ~/rfnoc-workshop

▪ To reproduce see RFNoC Getting Started Guide▪ https://kb.ettus.com/Getting_Started_with_RFNoC_Development

▪ Manual install

▪ Install dependencies

▪ Build UHD, GNU Radio, and gr-ettus

Getting RFNoC

3

� Installed with gr-ettus (via PyBOMBs)

� Generate OOT RFNoC modules

� Similar concept to gr_modtool

� Creates skeleton code for a pass through RFNoC block

� Verilog for RFNoC Block

� Test bench

� UHD C++ block controller / NoC Script XML

� GNU Radio Companion XML

� Everything in one place!

RFNoC modtool

4

� cd ~/rfnoc-workshop

� source setup_env.sh

� rfnocmodtool help

Using RFNoC modtool

5

� Steps to create our block:

� source ~/rfnoc-workshop/setup_env.sh

� cd ~/rfnoc-workshop/src

� rfnocmodtool newmod tutorial

� cd rfnoc-tutorial

� rfnocmodtool add gain� Enter valid argument list, including default arguments: (leave blank)

� Add Python QA Code? [y/N] N

� Add C++ QA Code? [y/N] N

� Block NoC ID (Hexadecimal): E7757E5700000001

� Skip Block Controllers Generation? [UHD block ctrl files] [y/N] N

� Skip Block interface files Generation? [GRC block ctrl files] [y/N] N

Using RFNoC modtool

6

RFNoC modtool output

7

� grc� tutorial_gain.xml – GRC XML Block Description

� include/tutorial� GNU Radio & UHD Block Controller C++ headers

� lib� GNU Radio & UHD Block Controller C++ impls

� rfnoc/blocks� gain.xml – Noc Script XML

� rfnoc/fpga-src� noc_block_gain.v – RFNoC Block HDL

� rfnoc/testbench/noc_block_gain_tb� noc_block_gain_tb.sv – RFNoC Block HDL test bench

Directory Structure

8

RFNoC Framework

GNU Radio

GRC Bindings (XML) Block Code (Python / C++)

UHD

Noc Script (XML) Block Controller (C++)

FPGA

RFNoC Block Code (Verilog, VHDL, IP, BD, HLS)

9

RFNoC Framework

GNU Radio

GRC Bindings (XML) Block Code (Python / C++)

UHD

Noc Script (XML) Block Controller (C++)

FPGA

RFNoC Block Code (Verilog, VHDL, IP, BD, HLS)

10

� Open ~/rfnoc-workshop/src/rfnoc-tutorial/rfnoc/fpga-src/noc_block_gain.v

� Editor choices in VM:� (g)vim

� emacs

� nano

� gedit

� geany

� notepadqq

� mousepad

Gain RFNoC Block

11

Gain RFNoC Block

noc_block_gain.v

Crossbar

CHDR AXI-Stream Settings Bus

User Code

NoC Shell

Sample Data

AXI Wrapper

User Registers

Data PacketsCommand &ResponsePackets

NoC ID: 0xE7757E5700000001

12

Gain RFNoC Block

noc_block_gain.v

Crossbar

CHDR AXI-Stream Settings Bus

User Code

NoC Shell

Sample Data

AXI Wrapper

User Registers

Data PacketsCommand &ResponsePackets

NoC ID: 0xE7757E5700000001

� Each block has a unique 64-bit block ID

13

Gain RFNoC Block Parameters

� Each block has a unique 64-bit block ID

14

Gain RFNoC Block Parameters

� STR_SINK_FIFOSIZE (power of 2) used for flow control

� Sets flow control receive FIFO depth, generally leave at 11

15

Gain RFNoC Block

noc_block_gain.v

Crossbar

CHDR AXI-Stream Settings Bus

User Code

NoC Shell

Sample Data

AXI Wrapper

User Registers

Data PacketsCommand &ResponsePackets

NoC ID: 0xE7757E5700000001

� Each block has one connection to crossbar

� Block communicates to other blocks and host via crossbar

16

Gain RFNoC Block I/O

� Each block has one connection to crossbar

� Input and output AXI stream� Carries CHDR packets (discussed later)

17

Gain RFNoC Block I/O

� Each block has one connection to crossbar

� Input and output AXI stream� Carries CHDR packets (discussed later)

� AXI stream on bus_clk domain. User logic uses ce_clk domain.Can be the same clock.

18

Gain RFNoC Block I/O

� Debug not currently used for anything

19

D2

� Part of ARM AMBA standard

� Simple handshake / flow control protocol:� Upstream block asserts tvalid

� Downstream block asserts tready

� Data is consumed when tvalid & tready == 1

� tlast used to delimit packets

AXI-Stream

clk

tready

tlast

tdata D/C D0 D1 D/C

tvalid

20

� tdata & tlast have no meaning when tvalid == 0

� Once tvalid is asserted, it cannot be deasserted

without at least one tready cycle

� Why AXI-Stream?

� Industry standard => Lots of existing IP

� No need for complicated strobes – data flows through

� Enhances reusability & composability

AXI-Stream

AXI StreamBlock

AXI StreamBlock

tready

tvalid

tlast

tdata

21

D1

� RFNoC’s packet format

� CHDR = Compressed Header

CHDR over AXI-Stream

clk

tready

tlast

tdata D/C Header D0 D/C

tvalid

22

� Packet type based on bits 63, 62, & 60

CHDR Packet Protocol

PktType

Has Time Seq # Length (in bytes)

63 - 62 61

EOB SRC SID DST SID

Fractional Time (Optional, Has Time = 1)

60 59 - 48 47 - 32 31 - 16 15 - 0

63 62 60 Packet Type

0 0 0 Data

0 0 1 Data (End of Burst)

0 1 0 Flow Control

1 0 0 Command

1 1 0 Response

1 1 1 Response (Error)

Payload

23

� 16 bit Stream ID

� 256 unique crossbar (or device) IDs

� 16 ports per crossbar

� 16 (logical) ports per block

� Example Crossbar ID: 2, Port: 1, Block Port: 0

SID: 2.1.0

Stream IDs

SID

CrossbarCrossbar

PortBlockPort

15 - 8 7 - 4 3 - 0

24

Gain RFNoC Block

noc_block_gain.v

Crossbar

CHDR AXI-Stream Settings Bus

User Code

NoC Shell

Sample Data

AXI Wrapper

User Registers

Data PacketsCommand &ResponsePackets

NoC ID: 0xE7757E5700000001

25

Gain RFNoC Block

noc_block_gain.v

Crossbar

CHDR AXI-Stream Settings Bus

User Code

NoC Shell

Sample Data

AXI Wrapper

User Registers

Data PacketsCommand &ResponsePackets

NoC ID: 0xE7757E5700000001

� Standard boilerplate RFNoC interfacing code� Not strictly required

� Muxes / demuxes CHDR packets� Data, command, response

� Handles flow control

� Crosses clock domains26

Noc Shell Parameters

� NOC_ID and STR_SINK_FIFOSIZE module parameters

27

Noc Shell I/O

� Connection to crossbar

28

Noc Shell I/O

� clk is the user logic clock domain, usually connected to ce_clk

� Noc Shell internally crosses clock domains29

Noc Shell I/O

� Settings bus: User register write and readback

� set_time and set_has_time for timed commands30

Gain RFNoC Block

noc_block_gain.v

Crossbar

CHDR AXI-Stream Settings Bus

User Code

NoC Shell

Sample Data

AXI Wrapper

User Registers

Data PacketsCommand &ResponsePackets

NoC ID: 0xE7757E5700000001

31

� Settings Bus 8-bit address = 256 regs

� NoC Shell Regs: 0 – 127

� Special registers to setup NoC Shell

� 0 – 4: Flow Control

� 5 – 8: SIDs (Src, Next Dst, Resp In, Resp Out)

� 124: User readback address

� 127: NoC Shell readback address

� User Regs: 128 – 255

Register Space

32

� Control packet payload sets addr & data

� [63:0] = {24’d0, set_addr[7:0], set_data[31:0]}

� Response packet payload has readback data

� User must assert readback strobe (or leave 1’b1)

Settings Bus

clk

set_stb

set_data

rb_data D/C R0

set_addr D/C A0 A1D/C D/C

D/C D0 D1D/C D/C

R1

rb_stb

33

Noc Shell I/O

� Access registers in other blocks

� cmdout: CHDR command packets out� Register write (i.e. settings bus writes) in other blocks

� ackin: CHDR response (ack) packets in� Register readback from other blocks

� Output by other block’s noc shell (remember rb_stb?)

� We will go over an example block using this port later 34

Gain RFNoC Block

noc_block_gain.v

Crossbar

CHDR AXI-Stream Settings Bus

User Code

NoC Shell

Sample Data

AXI Wrapper

User Registers

Data PacketsCommand &ResponsePackets

NoC ID: 0xE7757E5700000001

35

Noc Shell I/O

� str_sink: CHDR data packets out

� str_src: CHDR data packets in

36

Gain RFNoC Block

noc_block_gain.v

Crossbar

CHDR AXI-Stream Settings Bus

User Code

NoC Shell

Sample Data

AXI Wrapper

User Registers

Data PacketsCommand &ResponsePackets

NoC ID: 0xE7757E5700000001

37

NoC Shell Internals

From Crossbar

To Crossbar

Dem

ux

Mu

xFIFO

Data

Response

Command

Flow Control

CommandProcessor

Data

Response

Command

Flow Control

Source Flow Control

Flow Control Responder Observe

str_sink_*

ackin_*

set_*

rb_*

str_src_*

cmdout_*

Clock Crossing FIFO

Clock Crossing FIFO

Clock Crossing FIFO

Clock Crossing FIFO

bus_clk ce_clk38

Noc Shell I/O

� Useful stream IDs for forming packets

39

Noc Shell I/O

� VITA time input to control timed settings bus writes

� Avoid using this approach

� Only useful in special circumstances such as Radio Core

� For timed command examples, see DDC / DUC blocks

40

Noc Shell I/O

� Automatically asserted when UHD initializes the block at start up

� Can be used as a user logic reset

41

Gain RFNoC Block

noc_block_gain.v

Crossbar

CHDR AXI-Stream Settings Bus

User Code

NoC Shell

Sample Data

AXI Wrapper

User Registers

Data PacketsCommand &ResponsePackets

NoC ID: 0xE7757E5700000001

42

Gain RFNoC Block

noc_block_gain.v

Crossbar

CHDR AXI-Stream Settings Bus

User Code

NoC Shell

Sample Data

AXI Wrapper

User Registers

Data PacketsCommand &ResponsePackets

NoC ID: 0xE7757E5700000001

� Simplify interface for user

� Convert CHDR data packets into data stream

43

AXI Wrapper Parameters

� SIMPLE_MODE: auto generate output packet header� Useful if input / output rate is 1:1

� Examples:

� FIR Filter that does not decimate or interpolate

� FFT

� Gain block

� If not 1:1, header must be handled manually

� N:M integer ratio blocks can use the module AXI Rate Change

� See DUC / DDC RFNoC blocks

44

AXI Wrapper Parameters

� CHDR data packets to / from Noc Shell

� Notice ce_clk & bus_clk, there is an clock crossing FIFO inside

� next_dst_sid: Stream ID of next RFNoC block (or host) in flowgraph

45

AXI Wrapper Parameters

� Sample stream to / from user

� 32-bit wide, typically sc16 (16-bit I, 16-bit Q)

� tlast indicates packet boundaries46

AXI Wrapper Parameters

� Packet headers

� Must set s_axis_data_tuser if SIMPLE_MODE = 0

47

AXI Wrapper Parameters

� Must set s_axis_data_tuser if SIMPLE_MODE = 0

� Incoming packet header

� Outgoing packet header

48

AXI Wrapper Parameters

� Legacy, can be ignored

49

AXI Wrapper Parameters

� Resize incoming packet length

� Must set parameter RESIZE_INPUT_PACKET = 1(not shown)

50

AXI Wrapper

Framer

Deframer

Header FIFO

1 0

User Provided CHDR Header

To NoC Shell From User IP

FIFO

Sample Data

Sample Data

SIMPLE_MODE

Next Destination

Resize Input

Resize Output

bus_clk ce_clk51

Gain RFNoC Block

noc_block_gain.v

Crossbar

CHDR AXI-Stream Settings Bus

User Code

NoC Shell

Sample Data

AXI Wrapper

User Registers

Data PacketsCommand &ResponsePackets

NoC ID: 0xE7757E5700000001

52

Gain RFNoC Block

noc_block_gain.v

Crossbar

CHDR AXI-Stream Settings Bus

User Code

NoC Shell

Sample Data

AXI Wrapper

User Registers

Data PacketsCommand &ResponsePackets

NoC ID: 0xE7757E5700000001

� Many implementation options for user code� HDL: Verilog, SystemVerilog, VHDL

� Vivado IP: FIR, FFT, DDS, CORDIC, Turbo Decoder, etc

� Vivado Block Diagrams (BD): Microblaze

� Vivado High-Level Synthesis (HLS): C and C++

� User read/write registers to support configuration, control, and status readback

53

Gain RFNoC Block

noc_block_gain.v

CHDR AXI-Stream Settings Bus

NoC Shell

AXI Wrapper

SR 128: Gain

SampleData

RB 0: Gain

Data PacketsCommand & ResponsePackets

NoC ID: 0xE7757E5700000001

54

Gain RFNoC Block

noc_block_gain.v

CHDR AXI-Stream Settings Bus

NoC Shell

AXI Wrapper

SampleData

RB 0: Gain

Data PacketsCommand & ResponsePackets

NoC ID: 0xE7757E5700000001

� Multiply data stream with constant value set via

user register

SR 128: Gain

55

� Open rfnoc-tutorial/rfnoc/fpga-src/noc_block_gain.v

� Change TEST_REG_0 into a 16-bit register SR_GAIN

Write Custom HDL

localparam [7:0] SR_GAIN = SR_USER_REG_BASE;localparam [7:0] SR_TEST_REG_1 = SR_USER_REG_BASE + 8'd1;

wire [15:0] gain;setting_reg #(.my_addr(SR_GAIN), .awidth(8), .width(16))

sr_gain (.clk(ce_clk), .rst(ce_rst),.strobe(set_stb), .addr(set_addr), .in(set_data), .out(gain), .changed());

always @(posedge ce_clk) begincase(rb_addr)8'd0 : rb_data <= {48'd0, gain};8'd1 : rb_data <= {32'd0, test_reg_1};default : rb_data <= 64'h0BADC0DE0BADC0DE;

endcaseend

56

Write Custom HDL

57

� Write constant multiplier

� Vivado will infer a multiplier, likely using a DSP48

Write Custom HDL

wire [15:0] i, q;wire [31:0] i_mult_gain, q_mult_gain;

assign i = m_axis_data_tdata[31:16];assign q = m_axis_data_tdata[15:0];

assign i_mult_gain = i*gain;assign q_mult_gain = q*gain;

assign m_axis_data_tready = s_axis_data_tready;assign s_axis_data_tvalid = m_axis_data_tvalid;assign s_axis_data_tlast = m_axis_data_tlast;assign s_axis_data_tdata = {i_mult_gain[15:0], q_mult_gain[15:0]};

58

Write Custom HDL

59

RFNoC Test Bench Infrastructure

Crossbar

DUTRFNoCBlock

noc_block_tb

NoC Shell

AXI Wrapper

� Sets up a realistic, simulated RFNoC infrastructure

� Simple API for interacting with blocks

Test bench

RFNoCBlock

RFNoC Sim Lib API

60

RFNoC Test Bench Infrastructure

Crossbar

noc_block_tb

NoC Shell

AXI Wrapper

� Need to fill out testbench

RFNoC Sim Lib APInoc_block_gain.v

NoC Shell

AXI Wrapper

SR 128: GainRB 0: Gain

Test bench

61

� Initial setup:

� source ~/rfnoc-workshop/setup_env.sh

� cd ~/rfnoc-workshop/src/rfnoc-tutorial

� mkdir build && cd build/

� cmake ../

� make test_tb

� make noc_block_gain_tb

� Test bench failed… need to update it for our block!

Noc Block Gain Test Bench

62

� Edit rfnoc-tutorial/rfnoc/testbenches/

noc_block_gain_tb/noc_block_gain_tb.sv

Write Test Bench

initial begin : tb_mainstring s;logic [31:0] random_word;logic [63:0] readback;shortint gain;

`TEST_CASE_START("Write / readback user registers");random_word = $random();tb_streamer.write_user_reg(sid_noc_block_gain, noc_block_gain.SR_GAIN,

random_word[15:0]);tb_streamer.read_user_reg(sid_noc_block_gain, 0, readback);$sformat(s, "User register 0 incorrect readback! Expected: %0d, Actual %0d",

readback[15:0], random_word[15:0]);`ASSERT_ERROR(readback[15:0] == random_word[15:0], s);

63

Write Test Bench

64

� Edit rfnoc-tutorial/rfnoc/testbenches/

noc_block_gain_tb/noc_block_gain_tb.sv

Write Test Bench

`TEST_CASE_START("Test sequence");gain = 100;tb_streamer.write_user_reg(sid_noc_block_gain, noc_block_gain.SR_GAIN, gain);forkbegincvita_payload_t send_payload;for (int i = 0; i < SPP/2; i++) beginsend_payload.push_back({16'(i),16'(i),16'(i),16'(i)});

endtb_streamer.send(send_payload);

end

tb_streamer.recv(recv_payload,md);for (int i = 0; i < SPP/2; i++) beginexpected_value = {16'(i*gain),16'(i*gain),16'(i*gain),16'(i*gain)};

65

Write Test Bench

66

� source ~/rfnoc-workshop/setup_env.sh

� cd ~/rfnoc-workshop/src/rfnoc-tutorial/build

� make noc_block_gain_tb

Check Test Bench Again

67

68

� uhd_image_builder

� Command line tool for building bitstreams

� Allows specifying RFNoC blocks to include

� Note: make sure to include DDC and DUC!

� For full details on usage, see getting started

� GUI version: uhd_image_builder_gui.py

� source ~/rfnoc-workshop/setup_env.sh

� cd ~/rfnoc-workshop/src/uhd-fpga/usrp3/tools/scripts

� ./uhd_image_builder_gui.py

Generate Bitstream

69

uhd_image_builder_gui.py

70

uhd_image_builder_gui.py

71

uhd_image_builder_gui.py

72

uhd_image_builder_gui.py

73

uhd_image_builder_gui.py

74

uhd_image_builder_gui.py

75

� Select device (X310_RFNOC_HG, etc…)

� ‘Add OOT Blocks’ to import RFNoC OOT Blocks

� Select RFNoC blocks and add them to image with

‘>>’ button

� Use ‘Generate .bit file’ to call Vivado to build bitstream

� Bitstream will be in uhd-fpga/usrp3/top/<device>/build

� Our premade bitstream is located at

rfnoc-workshop/src/uhd_x310_fpga_RFNOC_HG_1.bit

Steps to using GUI

76

� Vivado occasionally fails to make timing with our

simple design

� Multipliers in FPGAs can have long critical paths

� Add a register stage to break up critical path

� Our premade bitstream has this register

Fix Timing Error

77

Fix Timing Error

78

RFNoC Framework

GNU Radio

GRC Bindings (XML) Block Code (Python / C++)

UHD

Noc Script (XML) Block Controller (C++)

FPGA

Computation Engine Code (Verilog, VHDL, Coregen, HLS)

79

RFNoC Framework

GNU Radio

GRC Bindings (XML) Block Code (Python / C++)

UHD

Noc Script (XML) Block Controller (C++)

FPGA

Computation Engine Code (Verilog, VHDL, Coregen, HLS)

80

RFNoC Framework

GNU Radio

GRC Bindings (XML) Block Code (Python / C++)

UHD

Noc Script (XML) Block Controller (C++)

FPGA

Computation Engine Code (Verilog, VHDL, Coregen, HLS)

81

� C++ Code

� Tells UHD about block’s capabilities, configuration

� Exposes methods to access and control block� Example: set_taps() for FIR filter RFNoC block

� Default block controller class covers most cases

� Custom implementation often not required!� Read / write registers

� Independently perform operation(s) on a data stream

� Examples: FIFO, FFT, Signal Generator, Fosphor

� rfnoc-tutorial/lib/gain_block_ctrl_impl.cpp� Our simple block does not need to do anything!

Block Controller Class

82

RFNoC Framework

GNU Radio

GRC Bindings (XML) Block Code (Python / C++)

UHD

Noc Script (XML) Block Controller (C++)

FPGA

Computation Engine Code (Verilog, VHDL, Coregen, HLS)

83

RFNoC Framework

GNU Radio

GRC Bindings (XML) Block Code (Python / C++)

UHD

Noc Script (XML) Block Controller (C++)

FPGA

Computation Engine Code (Verilog, VHDL, Coregen, HLS)

84

� XML based DSL for block configuration

� No recompilation!

� Describe NOC ID, user registers, input & output ports

� Create args to customize writing to registers

� Statically typed, quasi-functional

� Basic types: Integers, Strings, Doubles

� Basic arithmetic and logic operations available

� Validate input

� Skeleton file generated by RFNoC modtool!

Noc Script

85

� Add Gain settings register and arg to our block

� Open rfnoc-tutorial/rfnoc/blocks/gain.xml:

Noc Script

<registers><setreg><name>GAIN</name><address>128</address>

</setreg></registers><args><arg><name>gain</name><type>double</type><value>1.0</value><check>GE($gain, 0.0) OR LE($gain, 32767.0)</check><check_message>Gain must be in range [0, 32767].</check_message><action>SR_WRITE("GAIN", IROUND($gain))</action>

</arg></args>

86

Gain RFNoC Block Noc Script

87

Noc Script

noc_block_gain.v

CHDR AXI-Stream Settings Bus

NoC Shell

AXI Wrapper

SampleData

RB 0: Gain

Data PacketsCommand & ResponsePackets

NoC ID: 0xE7757E5700000001

SR 128: Gain

88

Noc Script

noc_block_gain.v

CHDR AXI-Stream Settings Bus

NoC Shell

AXI Wrapper

SampleData

RB 0: Gain

Data PacketsCommand & ResponsePackets

NoC ID: 0xE7757E5700000001

SR 128: Gain

<?xml version="1.0"?><!--Default XML file--><nocblock><name>gain</name><blockname>gain</blockname><ids><id revision="0">E7757E5700000001</id>

</ids>...

89

Noc Script

noc_block_gain.v

CHDR AXI-Stream Settings Bus

NoC Shell

AXI Wrapper

SampleData

RB 0: Gain

Data PacketsCommand & ResponsePackets

NoC ID: 0xE7757E5700000001

SR 128: Gain

...<ports><sink><name>in</name>

</sink><source><name>out</name>

</source></ports>

</nocblock>

90

Noc Script

noc_block_gain.v

CHDR AXI-Stream Settings Bus

NoC Shell

AXI Wrapper

SampleData

RB 0: Gain

Data PacketsCommand & ResponsePackets

NoC ID: 0xE7757E5700000001

SR 128: Gain

<registers><setreg><name>GAIN</name><address>128</address>

</setreg></registers>

91

RFNoC Framework

GNU Radio

GRC Bindings (XML) Block Code (Python / C++)

UHD

Noc Script (XML) Block Controller (C++)

FPGA

Computation Engine Code (Verilog, VHDL, Coregen, HLS)

92

RFNoC Framework

GNU Radio

GRC Bindings (XML) Block Code (Python / C++)

UHD

Noc Script (XML) Block Controller (C++)

FPGA

Computation Engine Code (Verilog, VHDL, Coregen, HLS)

93

� C++ or Python

� How does GNU Radio interface to RFNoC?

� via C++ infrastructure code in gr-ettus

� Gr-ettus provides a base RFNoC block class

� Users extend base class for their RFNoC blocks

� Many blocks can use base class “as is”

� No C++ or Python code!

� rfnoc-tutorial/lib/gain_impl.cc

� Our simple block does not need to do anything!

GNU Radio Block Code

94

RFNoC Framework

GNU Radio

GRC Bindings (XML) Block Code (Python / C++)

UHD

Noc Script (XML) Block Controller (C++)

FPGA

Computation Engine Code (Verilog, VHDL, Coregen, HLS)

95

RFNoC Framework

GNU Radio

GRC Bindings (XML) Block Code (Python / C++)

UHD

Noc Script (XML) Block Controller (C++)

FPGA

Computation Engine Code (Verilog, VHDL, Coregen, HLS)

96

� XML

� Describes GNU Radio blocks to GRC

� No recompilation!

� Requirement of GNU Radio Companion

� Not strictly necessary for GNU Radio

� Tutorial on how to write them:gnuradio.org/redmine/projects/gnuradio/wiki/GNURadioCompanion

� Skeleton file generated by RFNoC modtool!

GNU Radio Companion Bindings

97

� Add ‘Gain’ parameter

� Add callback to set gain arg

� Edit rfnoc-tutorial/grc/tutorial_gain.xml:

GRC XML

self.$(id).set_arg("gain", $gain)</make><callback>set_arg("gain", $gain)</callback>

<param><name>Gain</name><key>gain</key><value>1.0</value><type>real</type>

</param>

98

GRC XML

99

RFNoC Framework

GNU Radio

GRC Bindings (XML) Block Code (Python / C++)

UHD

Noc Script (XML) Block Controller (C++)

FPGA

Computation Engine Code (Verilog, VHDL, Coregen, HLS)

100

� Install:

� source ~/rfnoc-workshop/setup_env.sh

� cd ~/rfnoc-workshop/src/rfnoc-tutorial/build

� make install

� Program bitstream:

� Turn on X310

� source ~/rfnoc-workshop/src/uhd-fpga/usrp3/top/

x300/setupenv.sh

� viv_jtag_program ~/rfnoc-workshop/src/

usrp_x310_fpga_RFNOC_HG_2.bit

Installation

101

� Open rfnoc_gain flowgraph

� source ~/rfnoc-workshop/setup_env.sh

� gnuradio-companion

� Open ~/rfnoc-workshop/src/rfnoc-tutorial-complete/

examples/rfnoc_gain.grc

Testing in HW

102

� UHD RFNoC C++ API application

� How to use command packets

� Tune DSP offset in DDC / DUC

Advanced Topics

103

� RFNoC apps can use only UHD’s C++ API

� Design flow:� Create device3 usrp object

� Grab block controller objects

� Setup graph

� Setup blocks either with block controller methods, block args, and/or writing registers� Creating a block controller method is more complex, but allows

using C++ syntax

� Block arg is an <arg> defined in Noc Script XML

� Directly writing to a register is the simplest

� Setup streamers

� Run app with send() / recv()

� There is some overlap with existing API

UHD RFNoC C++ App

104

� RFNoC C++ app for the gain block:� Transmits sine wave through FIFO and Gain block

� Receives amplified sine wave and sends samples to GNU Radio for plotting via UDP

� User can change gain via console

� cp ~/rfnoc-workshop/src/gain-app-example/* ~/rfnoc-workshop/src/rfnoc-tutorial/apps/

� Edit ~/rfnoc-workshop/src/rfnoc-tutorial/apps/rfnoc_gain_example.cpp

� Most of the code is already filled out, we will fill in some of the important RFNoC related parts

Gain RFNoC C++ App

105

� Add code to:� Setup device3 usrp object with device args

� Grab block controller objects for fifo and gain blocks� Name string comes from Gain block’s Noc Script XML,

see tag <blockname>

� Setup graph and connect blocks

� C++11 auto keyword makes this easier

Gain RFNoC C++ App

auto usrp = uhd::device3::make(std::string(usrp_args));

auto fifo_block_ctrl = usrp->get_block_ctrl(uhd::rfnoc::block_id_t(0, "FIFO"));

auto gain_block_ctrl = usrp->get_block_ctrl(uhd::rfnoc::block_id_t(0, "gain"));

auto graph = usrp->create_graph("gain_graph");graph->connect(fifo_block_ctrl->get_block_id(),

gain_block_ctrl->get_block_id());

106

� Add code to setup RX and TX streamers

� Streamers have built in args such as “block_id”

and “spp” that have special meaning

� Streamer connections are defined with “block_id”

Gain RFNoC C++ App

uhd::stream_args_t rx_stream_args("fc32", "sc16");rx_stream_args.args["block_id"] = gain_block_ctrl->get_block_id();rx_stream_args.args["spp"] = boost::lexical_cast<std::string>(spp);auto rx_stream = usrp->get_rx_stream(rx_stream_args);

uhd::stream_args_t tx_stream_args("fc32", "sc16");tx_stream_args.args["block_id"] = fifo_block_ctrl->get_block_id();tx_stream_args.args["spp"] = boost::lexical_cast<std::string>(spp);auto tx_stream = usrp->get_tx_stream(tx_stream_args);

107

Gain RFNoC C++ App

108

� Add code to control gain at runtime

� This code could have also been set_arg() or a call

to a custom block controller method

Gain RFNoC C++ App

if ((s.length() > 0) && (not stop)) {try {

uint16_t gain = boost::lexical_cast<uint16_t>(s);gain_block_ctrl->sr_write("GAIN", gain);

}catch (boost::bad_lexical_cast) {

std::cout << "Invalid gain." << std::endl;}

}

109

Gain RFNoC C++ App

110

� Rerun cmake and build

� source ~/rfnoc-workshop/setup_env.sh

� cd ~/rfnoc-workshop/src/rfnoc-tutorial/build

� cmake ..

� make install

� Now rfnoc_gain_example should be in path

� Need to start GNU Radio flowgraph first

Gain RFNoC C++ App

111

� Open gnuradio-companion

� Run ~/rfnoc-workshop/src/rfnoc-tutorial-

complete/examples/rfnoc_gain_cpp.grc

Gain RFNoC C++ App

112

� In new terminal run rfnoc_gain_example

� source ~/rfnoc-workshop/setup_env.sh

� rfnoc_gain_example

Gain RFNoC C++ App

113

� If you see an error, make sure the GNU Radio

flowgraph is running first!

Gain RFNoC C++ App

114

� Registers are set via CHDR command packets

� Noc Shell’s cmdout port allows users to send command packets� Users can configure other blocks without host in FPGA

� Example: send commands to Radio core to set hardware gain, retune frontend without host latency

� dsptune: example block to show how to use command packets to offset tune with DDC & DUC� Also shows how to create Out-of-Tree C++ block

controllers for UHD and GNU Radio

� Code located in rfnoc-tutorial-complete

RFNoC Block Command Packets

115

� Program X310 with second bitstream

� source ~/rfnoc-workshop/src/uhd-fpga/usrp3/top/

x300/setupenv.sh

� viv_jtag_program ~/rfnoc-workshop/src/

usrp_x310_RFNOC_HG_2.bit

� Run dsptune GNU Radio Companion flowgraph at

~/rfnoc-workshop/src/rfnoc-tutorial-

complete/examples/tutorial_dsptune.grc

dsptune RFNoC Block Walkthrough

116

dsptune RFNoC Block Walkthrough

117

dsptune RFNoC Block Walkthrough

118

dsptune RFNoC Block Walkthrough

� List of Offset Tuning Frequencies in Hz

� Can have up to 256 frequencies

� Send by hitting enter while text box has focus

119

dsptune RFNoC Block Walkthrough

� Frequency will update every 0.1 secs

� Update by hitting enter while text box has focus

120

� Open ~/rfnoc-workshop/src/rfnoc-tutorial-complete/rfnoc/fpga-src/noc_block_dsptune.v

� Design:� Frequency list loaded into FIFO via settings bus

� axi_setting_reg handles all of this

� Tune delay setting register

� State machine to create and send command packets

� How do we know what Stream ID to send to?

� Uses next_dst_sid. This requires that the DDC or DUC must be the next block in the flowgraph. This is one of many valid approaches. Another approach would be to get the SID from UHD and program a setting register. We could have also tried to find the DDC / DUC by using command packets to read the NOC ID of every block connected to the crossbar.

dsptune RFNoC Block Walkthrough

121

dsptune RFNoC Block Walkthrough

� Frequency list stored in AXI Setting Register:

� Has AXI stream interface and internal FIFO

� List is consumed so it must be reprogrammed

122

Dsptune RFNoC Block Walkthrough

� Time Offset, called Tune Delay in the flowgraph, is a

normal settings register

123

Dsptune RFNoC Block Walkthrough

� State machine:

� If FIFO has a

frequency

� Reads FIFO

� Waits for time offset

� Sends command

packet

� Repeat

124

Dsptune RFNoC Block Walkthrough

� Command packets controlled by State Machine

� Payload is frequency register address and frequency offset

� Samples pass through unchanged

125

� dsptune sends a list or vector of frequencies

� But Noc Script XML does not support vectors

� Need to create C++ UHD block controller and GNU Radio block code

� GNU Radio dsptune block code:~/rfnoc-workshop/src/rfnoc-tutorial-complete/lib/dsptune_impl.cc

� UHD dsptune block controller:~/rfnoc-workshop/src/rfnoc-tutorial-complete/lib/dsptune_block_ctrl_impl.cpp

dsptune RFNoC Block Walkthrough

126

dsptune GR Block Code

� Added set_freqs() method that simply calls block

controller’s set_freqs() and passes freqs vector

127

dsptune UHD Block Controller

� Error checking

128

Dsptune UHD Block Controller

� Round frequencies and send via direct register write

129

Dsptune UHD Block Controller

� This is how UHD is aware of the Out-of-Tree block

� Macro registers block with UHD

� Name string must match block’s Noc Script XML

� rfnocmodtool generates this code automatically

130

dsptune GRC XML

� Setting “time_offset” is similar to “gain” in gain block

� Notice callback for set_freqs()

� SWIG bindings allow Python to directly call GNU Radio

block method

131

132

Final Takeaway

RFNoC is for FPGAs is what GNU Radio is for GPPs

RFNoC GNU Radio

Infrastructure for SDR applications

Handles data movement between blocks (AXI-Based) (Circular Buffers)

Takes care of boring and recurring tasks(Flow control,

addressing, routing)(R/W pointer up-

dating, tag handling)

Provides library of blocks (Growing) (Huge and well-tested)

Has a graphical front end (gr-ettus) (GRC)

Open Source

Writes your blocks for you

133

top related