1 / 19

Communicating with UniBoard

Communicating with UniBoard. Harro Verkouter/JIVE. UniBoard communication: WHY + HOW. Polyphase Filterbank. Nios2 CPU. registers. registers. registers. Delay Module. registers. 1Gbit PHY. FPGA. VHDL. Hardware. Software. VHDL. Hardware. Nios2 CPU. Nios2 CPU. Nios2 CPU. Nios2

elina
Télécharger la présentation

Communicating with UniBoard

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Communicating with UniBoard Harro Verkouter/JIVE

  2. UniBoard communication: WHY + HOW Polyphase Filterbank Nios2 CPU registers registers registers Delay Module registers 1Gbit PHY FPGA VHDL Hardware Software

  3. VHDL Hardware Nios2 CPU Nios2 CPU Nios2 CPU Nios2 CPU Software 1Gbit PHY 1Gbit PHY 1Gbit PHY 1Gbit PHY FPGA FPGA FPGA FPGA windows/unix UniBoard Control Computer EthernetSwitch EthernetSwitch

  4. Server VHDL Hardware Nios2 CPU Software IPv4 over ethernet Client windows/unix Control Computer

  5. Client/Server • Client initiates a request to a Server • UDP/IP packet with proprietary payload • Server processes the payload, generating reply • Server sends back the reply to the Client

  6. UDP/IP

  7. UniBoard commandpacket Packetformat Generic instruction format Wait-for-1PPS instruction prefix Write config data [program FLASH image]

  8. Available commands Read N 32bit words starting from START ADDRESS (Over)Write N 32bit words from the packet to START ADDRESS Read/Modify/Write N 32bit words from START ADDRESS + packet to START ADDRESS

  9. Client/Server implementation Server • C-code running on the embedded NiosII CPU • support IP/ARP (Address Resolution Protocol) Client • library supporting the protocol and commands

  10. Client library requirements • 1 UniBoard => 8 FPGAs to control • e.g. facilitate 1-command-to-many-FPGAs • one ‘broken’ FPGA should not stall communications to others • deal with loss of command- and/or reply packet • geared towards hardware registers • support oddly sized fields (single/multibit not-multiple-of-8) • fields located at arbitrary bit-offsets in register • support “addressing” a range of registers as one entity • binary protocol • byteorder aware + safe • be flexible, yet destination bit-width safe • 64bit variable with value of ‘2’ into 2bit field = ok, 8bit ‘4’ not • debugging options on the FPGA are severely limited • certainly w/o affecting timing • portable to different flavours of OS/cpu Goal is not overengineering but combining ease of use whilst eliminating as much difficult-to-detect problems before commands are sent to the FPGA(s)

  11. Client library implementation in ... • C? • highly portable • binds easily to other languages • lot of effort to make it flexible and safe • even then not really simple to use for other than trivial cases • C++? • templates allow for flexibility and safety and generic usage patterns • STL at least great for bookkeeping, also other usefull stuff • does not bind very well (if at all) to other languages • Python? • ease of use • allows safety and flexibility with moderate effort • vast array of support libs available • does not bind to other languages (for all practical purposes)

  12. Erlang chosen for implementation • exceptionally good at dealing w/ binary data, bitfields, endianness • it was designed and built for doing just that (#) • because it is a functional programming language • very high level = very expressive = very high productivity • safe: let functions execute only if specific conditions are met • distributed, fault tolerant systems (see #) • transparent, safe multithreading across multiple hosts (see #) • built on the assumption things WILL go wrong (see #) • not new (inception 1985, open sourced in 1998) • scripted + bytecompiled (like Python, JAVA) • well supported on UNIX, Windows and Mac • shallow learningcurve (see #)

  13. Erlang’s weaknesses • does not bind with other languages (same as Python) • binding C/C++ to Python/Erlang possible, however need other way around • there are other (better?) ways than linking in code • not good for textprocessing

  14. Erlang: data and the outside world • MySQL (external module) • JSON (external module) • lightweight data-interchange format • built-in: • webserver + dynamic webpages (map URL -> Erlang fn) • http client • GUI toolkit based on WxWindows • “ports” • mechanism to start and communicate with external process via stdout/stdin using a packetized, line-oriented or a DIY protocol • can be coded in Your Favourite Language-du-jour

  15. Example: FIR filter with C/S Registers 3 2 1 0 ADDRESS 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 0x00000024 | P N N N | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ P = PPS_ENABLE (1bit) NNN = NUM_TAP (3bit) +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 0x00001000 | MODEL COEFFICIENT 0 (float32) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | MODEL COEFFICIENT 1 (float32) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ .... .... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 0x00001006 | MODEL COEFFICIENT 6 (float32) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 0x0000abcc | CONTROL/STATUS REGISTER | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

  16. File: firfilter.erl -module(firfilter). %% this module is called firfilter, driving one of those -import(fpga). %% enables us to use functions from the client library -behaviour(fpga.personality). %% this module implements an FPGA personality %% Return the list of registers defined for this personality. %% Called automatically by the FPGA control framework registers() -> {ok, [ %% a 3 bit field starting at bit 5 in the word at 0x24 fpga:bitrange(num_tap, 5, 3, 16#24), %% another bit in that same register/word fpga:bit(pps_enable, 28, 16#24), %% one word (32bits) at location 0xabcc fpga:word(control_status, 16#abcc), %% A sequence of 7 floats “float-range” starting at 0x1000 fpga:frange(model, 16#1000, 7) ]}. %% define a high-level command for this personality start_filter(FPGA, NumTap) -> %% disable the PPS fpga:execute(FPGA, fpga:write(pps_enable, 0)), %% read the control status register case fpga:execute(FPGA, fpga:read(control_status)) of %% if the control_status register is “1” (zero) %% we must first XOR it with “42” ... 1 -> fpga:execute(FPGA, fpga:xor(control_status, 42)); %% otherwise do nothing _ -> ok end, %% now write the number of taps into the register for that and immediately %% after that start the PPS again. So far we only used single commands, %% however, you can easily execute a number of commands in one go: fpga:execute(FPGA, [fpga:write(num_tap, NumTap), fpga:write(pps_enable, 1)]). -module(firfilter). %% this module is called firfilter, driving one of those -import(fpga). %% enables us to use functions from the client library -behaviour(fpga.personality). %% this module implements an FPGA personality %% Return the list of registers defined for this personality. %% Called automatically by the FPGA control framework registers() -> {ok, [ %% a 3 bit field starting at bit 5 in the word at 0x24 fpga:bitrange(num_tap, 5, 3, 16#24), %% another bit in that same register/word fpga:bit(pps_enable, 28, 16#24), %% one word (32bits) at location 0xabcc fpga:word(control_status, 16#abcc), %% A sequence of 7 floats “float-range” starting at 0x1000 fpga:frange(model, 16#1000, 7) ] }. %% define a high-level command for this personality start_filter(FPGA, NumTap) -> %% disable the PPS fpga:execute(FPGA, fpga:write(pps_enable, 0)), %% read the control status register case fpga:execute(FPGA, fpga:read(control_status)) of %% if the control_status register is “1” (zero) %% we must first XOR it with “42” ... 1 -> fpga:execute(FPGA, fpga:xor(control_status, 42)); %% otherwise do nothing _ -> ok end, %% now write the number of taps into the register for that and immediately %% after that start the PPS again. So far we only used single commands, %% however, you can easily execute a number of commands in one go: fpga:execute(FPGA, [fpga:write(num_tap, NumTap), fpga:write(pps_enable, 1)]).

  17. File: controlfilter.erl -module(controlfilter). -import(fpga). -import(udpprotocol). -import(firfilter). -export([test_it/0]). %% Make the test-function available to others %% Define a function which tests the ‘system’. test_it() -> %% create a controlling process which ‘connects’ to the remote FPGA %% via the UDP protocol as defined in [...]. We pass the personality %% module as argument so the fpga controller knows the defined registers. RemoteFPGA = fpga:fpga(firfilter, udpprotocol, [{host, “192.168.0.42”}]), %% and execute the high-level function ... firfilter:start_filter(RemoteFPGA, 128), true. -module(controlfilter). -import(fpga). -import(udpprotocol). -import(firfilter). -export([test_it/0]). %% Make the test-function available to others %% Define a function which tests the ‘system’. test_it() -> %% create a controlling process which ‘connects’ to the remote FPGA %% via the UDP protocol as defined in [...]. We pass the personality %% module as argument so the fpga controller knows the defined registers. RemoteFPGA = fpga:fpga(firfilter, udpprotocol, [{host, “192.168.0.42”}]), %% and execute the high-level function ... firfilter:start_filter(RemoteFPGA, 128), true. [macverkouter]Okay->erl Erlang R13A (erts-5.7) [source] [64-bit] [smp:2:2] [rq:2] [async-threads:0] [kernel-poll:false] Eshell V5.7 (abort with ^G) 1> c(controlfilter). {ok,controlfilter} 2> controlfilter:test_it(). true 3>

  18. Final thoughts • the Erlang client library • implements full, multithreaded, type- platform- and byteordesafe and very thoroughly errorchecked access to the commands (both on the in- and outputs) • allows sending an arbitrary long list of commands • break up into >1 packet if necessary and reassemble the output into one answer • attempts to graciously deal with • lost UDP packets (retries up to three times) • timeouts/FPGA deadishness • dedicated single- or many-chip testprograms can easily be scripted and subsequently be executed manually from the shell • integrating in existing control environment: • assume acces to finite amount of high level commands needed • code these procedures in Erlang • build TCP/IP based wrapper • or use an intermediate “port” process (eg in Python - @JIVE we’ve done that)

  19. Final final thoughts ... • If everything else fails .... • the protocol & commands are simple enough to implement them in any language that supports UDP sockets and binary data • http://www.erlang.org • http://www.json.org • http://erlport.org • Python baseclass for “ports”

More Related