User Tools

Site Tools


usersguide:usersguide

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
usersguide:usersguide [2022/02/27 20:56]
dpisuperadmin
usersguide:usersguide [2022/03/12 23:13] (current)
dpisuperadmin [Software Defined Peripherals on the Baseboard4]
Line 56: Line 56:
 The Baseboard connects to your computer using a USB-serial link.  Data over the link consists of packets of binary data that read and write the registers in the software defined peripherals in DPCore.  Your high level application could communicate with the Baseboard directly but almost everyone finds it easier to deal with an API that translates high-level API commands into read and write packets to the Baseboard.  Dpdaemon provides this easy to use API for your applications. The Baseboard connects to your computer using a USB-serial link.  Data over the link consists of packets of binary data that read and write the registers in the software defined peripherals in DPCore.  Your high level application could communicate with the Baseboard directly but almost everyone finds it easier to deal with an API that translates high-level API commands into read and write packets to the Baseboard.  Dpdaemon provides this easy to use API for your applications.
 You can download and install dpdaemon with the following commands: You can download and install dpdaemon with the following commands:
-      git clone https://github.com/DemandPeripherals/dpdaemon.git +    git clone https://github.com/DemandPeripherals/dpdaemon.git 
-      cd dpdaemon +    cd dpdaemon 
-      make +    make 
-      sudo make install +    sudo make install 
-The Baseboard has an FTDI USB-to-serial interface.  Connect the Baseboard to your computer and determine the name of the serial port.  Start dpdaemon with the command+The Baseboard has an FTDI USB-to-serial interface.  Connect the Baseboard to your computer and determine the name of the serial port.  The USB serial port is owned by the group dialout. Add yourself to the group dialout and start dpdaemon with the commands
-      dpdaemon -l /usr/local/lib/DPCore.bin -s /dev/ttyUSB0+    sudo addgroup $LOGNAME dialout 
 +    dpdaemon -l /usr/local/lib/DPCore.bin -s /dev/ttyUSB0
  
-You can perform a quick test that everything is working by changing the LEDs on the Baseboard with the command+You can perform a quick test that everything is working by changing the LEDs on the Baseboard with the commands
-      /usr/local/bin/dpset bb4io leds 55+    export PATH=$PATH:/usr/local/bin/ 
 +    dpset bb4io leds 55
  
 Dpdaemon is a true daemon in that, by default, it will disassociate from the controlling terminal, respawn itself, and use syslog() to report errors.  You can change this behavior with the -f command line option.  This keeps the daemon in the foreground.  The -e command option tells the daemon to not use syslog() and to report errors to the controlling terminal. Dpdaemon is a true daemon in that, by default, it will disassociate from the controlling terminal, respawn itself, and use syslog() to report errors.  You can change this behavior with the -f command line option.  This keeps the daemon in the foreground.  The -e command option tells the daemon to not use syslog() and to report errors to the controlling terminal.
Line 181: Line 183:
         sys.exit()         sys.exit()
          
- 
-==== Build a Robot Using a Baseboard4 ==== 
-==== Use ROS2 to Control Your Robot ==== 
-==== How to Write a Custom Driver for dpdaemon ==== 
-==== A Brief Introduction to Verilog ==== 
-In this section you will see how to use Verilog to build FPGA applications. The purpose of this section is to give non-Verilog users a sense of how Verilog works.  This is an advanced section and is entirely optional.  To appreciate this section you should already be familiar with digital circuit design. This section is broken into four topics: 
-  * "hello world" in Verilog 
-  * use iverilog to test your Verilog circuit 
-  * install the Xilinx compiler 
-  * compile your design and test it on the Baseboard 
- 
-=== "Hello World" in Verilog === 
-Most programming languages have a sample application that prints the phrase "Hello, World!" to the console. This application is often used to validate the installation of the language and its tool chain.  For microcontrollers and FPGAs the equivalent application usually flashes an LED on the development board.  The Verilog program below implements a counter on the Baseboard LEDs.  Save the following as counter.v 
-    // Simple up counter for the Baseboard. 
-    // Visible update rate is about 12 times per second 
-     
-    module counter(CK12, LEDS); 
-        input   CK12;        // 12.5 MHz input clock 
-        output  [7:0] LEDS;  // eight LEDs on Baseboard 
-     
-        reg [27:0] count;    // 28 bit counter 
-     
-        initial 
-        begin 
-            count = 0; 
-        end 
-     
-        always @(posedge CK12) 
-        begin 
-            count <= count + 28'b1; 
-        end 
-     
-        assign LEDS = count[27:20];   // display high 8 bits of counter 
-     
-    endmodule 
- 
-Have you ever seen a circuit board with gold or copper fingers for the connector?  If so, you are already familiar with the idea of a //module// You can always think of a Verilog modules as a complete circuit board with the names of the connector pins given in the module definition. 
-    module counter(CK12, LEDS); 
-        input   CK12;        // 12.5 MHz input clock 
-        output  [7:0] LEDS;  // eight LEDs on Baseboard 
-Think of this counter module as a circuit board with nine signal pins on its edge.  Clearly the code inside the module describes the digital circuitry on the imaginary circuit board. 
- 
-You already know that a register is just an array of flip-flops.  In Verilog you create a register using the //reg// keyword.  You have to tell the compiler how many flip-flops you want in the register by specifying the upper and lower flip-flop numbers. 
-        reg [27:0] count;    // 28 bit counter 
- 
-You can tell the Verilog compiler what values to place in registers when the FPGA is loaded.  This is called the //initial// value of the register.  Do this with the initial construct. 
-        initial 
-        begin 
-            count = 0; 
-        end 
- 
-Consider a flip-flop.  It has an input and an output.  In Verilog inputs always appear on the left hand side of an assignment and outputs always appear on the right hand side.  While not obvious, this is true for the following: 
-        always @(posedge CK12) 
-        begin 
-            count <= count + 28'b1; 
-        end 
-The left hand side is the input to the count register and the right hand side is the output of count plus one.  The output of an edge-triggered flip-flop is given a value only on the edge of its input clock.  Register assignments must appear inside a block that defines the clock source for the registers.  That is what the ''always @(posedge CK12)'' line does.  Verilog uses a special syntax to show an edge-triggered flip-flop assignment.  That is the ''<''''='' syntax.  This can only appear in a block with a clock source.  Some flip-flop schematic symbols use a tiny triangle at the clock input.  You can think of the "<" in ''<''''='' as that clock symbol.   
- 
-Assignment outside of a synchronous block is done with just an equal sign.  This is called a //continuous assignment// and is how you connect one module to another and how you connect inputs and outputs.  Continuous assignments are also handy for giving a simple name to a complex piece of logic.  In the counter application the line 
-        assign LEDS = count[27:20];   // display high 8 bits of counter 
-sets the value of LEDS to the high eight bits of the counter. Just as you should not drive a wire with two different output, so Verilog wants just one output driving a wire or input.  The following will generate a Verilog compiler error. 
-    assign outputA = inputX; 
-    assign outputA = count + 1; 
- 
- 
-=== Test Your Verilog Design Using Iverilog === 
-//Bob: describe why you'd want to do simulation// 
- 
-Install iverilog and gtkwave on a Debian system with the command: 
-    sudo apt-get install iverilog gtkwave 
- 
-//Bob: describe how a test bench works in iverilog// 
- 
-Save the following as counter_tb.v 
-    //  iverilog test bench for the simple counter in counter.v 
-     
-    `timescale 10ns/10ns 
-     
-    module counter_tb; 
-        // direction is relative to the DUT 
-        reg    clk;          // 12.5 MHz system clock 
-        wire   [7:0] leds;   // LEDs on Baseboard 
-     
-        // Add the device under test 
-        counter counter_dut(clk, leds); 
-     
-        // generate the clock 
-        initial  clk = 0; 
-        always   #4 clk = ~clk;  // half period is 40ns == 4 * timescale 
-     
-        initial 
-        begin 
-            $dumpfile ("counter_tb.xt2"); 
-            $dumpvars (0, counter_tb); 
-     
-            // 100 million steps of 10ns is one tenth of a second 
-            #100000000 
-            $finish; 
-        end 
-    endmodule 
- 
-Run the simulation, convert the output to a gtkwave format, and display the results with the commands: 
-    iverilog -o counter_tb.vvp counter_tb.v counter.v 
-    vvp counter_tb.vvp -lxt2 
-    gtkwave counter_tb.xt2  
- 
-To view the LED waveforms click on "counter_tb" and "counter_dut" in the top left gtkview pane.  Then click on "LEDS" in the lower left pane.  Double click on "LEDS" in the display pane to expand the eight lines.  Hold down the CTRL key and use the mouse scroll wheel to compress the display until the whole second of simulation is displayed.  The display should look something like this: 
-{{ :usersguide:counter_leds.png?600 |}} 
- 
-=== Install and Test the Xilinx Toolchain === 
-Once your simulation output is correct you are ready to compile and download your design to the FPGA. 
-This section describes how to install the Xilinx FPGA design tools, how to use the Xilinx command line tools to compile a Verilog design, and how to download the compiled code to the Baseboard.  A later section will describe how to automate all these steps in a Makefile. 
- 
-The Baseboard uses a Xilinx Spartan-3E and a USB interface for both downloads and a host interface.  Since the Baseboard is downloaded through a USB serial port you do not need a JTAG cable or dongle. 
- 
-Xilinx provides a set of free design tools, ISE, which are part of their WebPACK download.  To get the WebPack download you have to select it, register with Xilinx, and start the download. 
- 
-Start by going to the Xilinx download site at: http://www.xilinx.com/support/download/index.htm.  Click on "ISE Archive" link and select "14.7" and then "Full Installer for Linux" This will take you to a login page where you can select "Create Account" (since you probably don't already have a Xilinx account).  You activate the account using a token sent in email.  Your first login will present a page asking you to verify your name and address.  The download starts automatically after selecting Download at the bottom of the name verification page. 
- 
-Install the software by untarring the download file and running the "xsetup" script in the top level directory.  If installing as a non-root user, you might want to create /opt/Xilinx/14.7 beforehand and give yourself write permission on it. 
- 
-The installation will ask which products to install.  We suggest the "ISE WebPACK" as it is the smallest and has everything you'll need.  You need to "Acquire or Manage a License Key" but you do need to install the Cable Drivers.  Selecting Next then Install should start the installation. 
- 
-Once the installation is complete you can add the Xilinx Verilog compiler toolchain to you path and verify that it can be found with the commands: 
-    export PATH=$PATH:/opt/Xilinx/14.7/ISE_DS/ISE/bin/lin64 
-    which ise 
- 
-By default, ise opens a graphical integrated development environment.  DPcore is //make// based and you do not need to learn the IDE.  You may recall that compiling a C++ or C program is broken into the steps of preprocessing, compiler pass 1, compiler pass 2, assembly, and linking.  All these steps occur even though you only type g++ or gcc.  In the same way, Verilog is compiled to binary in several steps. 
- 
-Before compiling your Verilog to an FPGA binary you need to tell the compiler how the wires in the Verilog module map to the physical FPGA pins.  Xilinx uses a "user constraints file" (.ucf) for this.  The minimum UCF file for your counter is shown below.  Save it as counter.ucf 
-    NET "CK12"      LOC = "P39"  ;    # 12.5 MHz clock 
-    NET "LEDS[0]"   LOC = "P70"  ;    # LED 0 
-    NET "LEDS[1]"   LOC = "P71"  ;    # LED 1 
-    NET "LEDS[2]"   LOC = "P62"  ;    # LED 2 
-    NET "LEDS[3]"   LOC = "P66"  ;    # LED 3 
-    NET "LEDS[4]"   LOC = "P67"  ;    # LED 4 
-    NET "LEDS[5]"   LOC = "P68"  ;    # LED 5 
-    NET "LEDS[6]"   LOC = "P63"  ;    # LED 6 
-    NET "LEDS[7]"   LOC = "P65"  ;    # LED 7 
- 
-The commands that Xilinx uses to compile Verilog for a SPartan3 can be hidden by a Makefile but you might be interested in the steps involved.  There is insufficient space in this tutorial to give detailed descriptions of the commands. Your download of the Xilinx tools includes comprehensive manuals for the Xilinx command line tools which you can consult if you are interested.  Look in ISE/doc/usenglish/books/docs/ The following paragraphs give a brief overview of the commands involved. 
- 
-The first command, xst, synthesizes the Verilog file into a hardware design that is saved as a netlist file with an .ngc extension.  Xilinx's xst program is actually a command line interpreter and it expects input from standard-in.  Use an echo command and a pipe operator to give xst input from standard-in if you want to keep all of your build information in a Makefile.  
-    echo "run -ifn counter.v -ifmt Verilog -ofn counter.ngc -p xc3s100e-4-vq100" | xst 
- 
-You have to specify the input file, the input file format, the name of the output file and the exact type of FPGA.  Xst generates several report files and directories, but the real output is a netlist file with an .ngc extension that is required for the next command. You can examine the output files and reports to better understand the how the synthesis works and an appendix in the xst manual describes the output files and reports in detail. 
- 
-The ngdbuild command further decomposes the design into FPGA native elements such as flip-flops, gates, and RAM blocks. 
- 
-    ngdbuild  -p xc3s100e-4-vq100 -uc counter.ucf  counter.ngc 
- 
-It is the ngdbuild command that first considers the pin location, loading, and timing requirements specified in the user constraints file, counter.ucf.  Like the other Xilinx commands, ngdbuild produces several reports but its real output is a "Native Generic Database" stored in a .ngd file. 
- 
-The Xilinx map command converts the generic elements from the step above to the elements specific to the target FPGA. It also performs a design rules check on the overall design. The map command produces two files, a Physical Constraints File file and a Native Circuit Description file, that are used in subsequent commands. 
- 
-    map -detail -pr b counter.ngd 
- 
-The map command produces quite a few reports.  As you gain experience with FPGA design you may come to rely on these report to help identify design and timing problems. 
- 
-The place and route command (par) uses the Physical Constraints File and the Native Circuit Description to produce another Native Circuit Description file which contains the fully routed FPGA design. 
- 
-    par counter.ncd parout.ncd counter.pcf 
- 
-Output processing starts with the bitgen program which converts the fully routed FPGA design into the pattern of configuration bits found in the FPGA after download. 
- 
-    bitgen -g StartUpClk:CClk -g CRC:Enable parout.ncd counter.bit counter.pcf 
- 
-The bitgen program lets you specify which clock pin to use during initialization and whether or not to  generate a CRC checksum on the download image.  Files which contain a raw FPGA download pattern are called bitstream files and traditionally has a .bit file extension.  Bitstream files are good for downloads using JTAG but since we're downloading over a USB serial connection one more command is required to convert the bitstream file into a download file. 
- 
-    promgen -w -p bin -o counter.bin -u 0 counter.bit 
- 
-The promgen program is a utility that converts bitstream files into various PROM file formats.  The format for the Baseboard is called bin so the promgen command uses the -p bin option.  The output of promgen, counter.bin, is what you download to the Baseboard FPGA card. 
- 
-All of the commands described above, including xst, ngdbuild, map, par, bitgen, and promgen have excellent PDF manuals in either the ISE/doc/usenglish/books/docs/xst directory or the ISE/doc/usgnglish/de/dev directory of your WebPACK installation. 
- 
-    echo "run -ifn counter.v -ifmt Verilog -ofn counter.ngc -p xc3s100e-4-vq100" | xst 
-    ngdbuild  -p xc3s100e-4-vq100 -uc counter.ucf  counter.ngc 
-    map -detail -pr b counter.ngd 
-    par counter.ncd parout.ncd counter.pcf 
-    bitgen -g StartUpClk:CClk -g CRC:Enable parout.ncd counter.bit counter.pcf 
-    promgen -w -p bin -o counter.bin -u 0 counter.bit 
- 
-When the Baseboard powers up or after pressing the reset button the FPGA waits for an binary image from the serial port. Linux serial port drivers can suppress certain characters from an output stream.  To prevent this you need to turn off post processing on the serial port.with the command: 
-     sudo stty --file=/dev/ttyUSB0 -opost  # We want raw output 
- 
-Press the reset button and send the FPGA binary to the Baseboard with the command: 
-    cat counter.bin > /dev/ttyUSB0 
- 
-If all has gone well you should see an up counter on the Baseboard LEDs. 
- 
- 
-==== How to Write a Wishbone Peripheral ==== 
-In this section you will see how to build your own custom Verilog peripheral.  This is an advanced section and is entirely optional.  To appreciate this section you should already be familiar with digital circuit design and Verilog. This section is broken into five topics: 
-  * the DPcore Wishbone bus 
-  * build a Verilog peripheral for DPcore 
-  * fold your peripheral in the DPcore build system. 
- 
-=== The Wishbone Bus === 
-A Wishbone Bus is a synchronous, parallel data bus intended to connect on-chip peripherals to an on-chip CPU.  Wishbone describes both the interface signals to the peripherals as well as the how the peripherals are connected to each other and to the CPU.  The full specification is at [[https://cdn.opencores.org/downloads/wbspec_b4.pdf|Wishbone specification]].  Wishbone is a common interface for many of the project at [[https://opencores.org|Opencores]]. 
- 
-In the case of DPcore, the Wishbone bus does not connect to a CPU but to an interface to a host computer.   
- 
-{{ :usersguide:wb_p2p.gif?300|}} 
- 
-Wishbone supports different peripherals/CPU interconnect topologies.  You may already be familiar with a //shared bus// topology since early PCs used these as the ISA and PCI buses.  A //crossbar// topology is often used when peripherals need to communicate amongst themselves or with a DMA controller.  A //point-to-point// topology is often used when the bandwidth requirements of a peripheral would interfere with access to other peripherals.  A //ring// topology is often used when speed is less important than the amount of FPGA fabric used in the system.  DPcore uses a ring topology.  Note that the topology does not necessarily affect the address, data, and control lines going to and from the peripheral.  The diagram to the right shows the major Wishbone signals in a point-to-point topology. 
- 
-Wishbone gives a general description of a peripheral bus.  For example, Wishbone buses can be 8, 16, 32, or 64 bits wide.  It is up the the implementer to decide things like bus width, clock frequencies, and which controls lines to use.  The Wishbone specification lists and defines both required and optional bus signals. 
- 
-{{ :usersguide:wb_sdp_arch.png?400|}} 
- 
-The diagram to the right shows the topology for PDcore.  It shows two of the possible sixteen peripherals.  The DPcore data bus is 8 bits wide.  Each peripheral has 8 bits of internal addressing.  That is, each peripheral can have up to 256 8-bit registers.  You have previously seen that one advantage of DPcore is that you can have any mix of peripherals you want.  This diagram illustrates why.  All peripherals have the same interface, so any peripheral can be substituted for any other. 
- 
- 
-The paragraphs below describe the Wishbone bus as implemented for DPcore.  We use _X to indicate both input (_I) and output (_O) signals.  Instead of the terms Master and Slave we use the term Controller and Peripheral which better match our use of Wishbone.  In our implementation when a peripheral is not selected it must route DAT_I to DAT_O unchanged--.  
- 
-Peripheral Signal Names : 
-CLK_I : System clock.  All peripherals use this 20 MHz clock to drive state machines and other peripheral logic.  This is used by the controller and all peripherals. 
- 
-WE_I : Write enable.  This is set to indicate a register write into the peripheral.  A zero for WE_I indicates a read operation. 
- 
-STB_I : Strobe.  This is set to indicate that a bus cycle to this peripheral is in progress.  The cycle can be either a register read/write or a poll. 
- 
-TGA_I : Address tag.  A bus cycle with TGA_I set is a normal register read/write.  For a read bus cycle with TGA_I cleared, the peripheral places the number of bytes it wishes to send to the host on DAT_O.  A DAT_O value of zero indicates that the peripheral has no data for the host at this time.  If DAT_O is non-zero the controller internally generates a read request for the number of bytes specified. 
- 
-ADR_I : Address.  An 8 bit address that specifies which register in the peripheral to read or write.  The peripheral can treat some addresses as simple register reads/writes and other addresses as top-of-stack for a FIFO. 
- 
-STALL_O : Stalled.  The peripheral asserts this signal to indicate that more system clock cycles are needed to complete the bus cycle. The controller waits for STALL_O to be deasserted before completing the read or write operation. 
- 
-ACK_O : Acknowledge.  The peripheral asserts ACK_O to tell the controller that the read or write bus cycle has successfully completed.  This signal is used in FIFO accesses to indicate that a FIFO is full (on write) or empty (on read).  The controller write successive bytes to the same address to fill a FIFO.  As long as the bytes are successfully written, the peripheral asserts ACK_O.  When a byte can not be written, the peripheral does not raise ACK and the controller knows that the FIFO is full and the sequence of writes stops at that point.  The controller sends an acknowledgment to the host giving the number of bytes written (or read).  This lets the host application know how many bytes were successfully written to the FIFO letting the application resend the unacknowledged bytes at a later time. 
- 
-DAT_X : An 8 bit data bus that is passed in ring from the bus controller through all peripherals and back to the bus controller.   This arrangement is close to the Wishbone Data Flow Interconnection but the data path is a ring.  This arrangement is sometime called a "serpentine" bus. 
-The "Port Size" is 8 bits and the "Granularity" is 8 bits.  There is no "Endianness" associated with the data bus.   
-During a bus write cycle the peripheral latches DAT_I into the selected register. During a read bus cycle the peripheral ignore DAT_I and places the requested data on DAT_O. 
- 
-The Verilog code fragment below shows a typical peripheral interface definition.  "Clocks" are system available strobes that occur every 100ns, 1.0us, 10us, 100us, 1.0ms, 10ms, 100ms, and 1 second.  The four inout pins go to the FPGA pins.  Some peripherals have eight instead of four FPGA pins.  
- 
-  module dp_peri(CLK_I,WE_I,TGA_I,STB_I,ADR_I,STALL_O,ACK_O,DAT_I,DAT_O,clocks,pins); 
-      input  CLK_I;            // system clock 
-      input  WE_I;             // direction. Read-from-peri==0; Write-to-peri==1 
-      input  TGA_I;            // ==1 for register read/write, ==0 for data-to-send poll 
-      input  STB_I;            // ==1 if peri is addressed for r/w or poll 
-      input  [7:0] ADR_I;      // address of target register 
-      output STALL_O;          // ==1 if we need more clk cycles to complete 
-      output ACK_O;            // ==1 if we claim the address and complete the read/write 
-      input  [7:0] DAT_I;      // Data INto the peripheral; 
-      output [7:0] DAT_O;      // Data OUTput from the peripheral, = DAT_I if not us. 
-      input  [7:0] clocks;     // 100ns to 1 second pulses synchronous CLK_I 
-      inout  [3:0] pins;       // FPGA pins for this peripheral 
- 
- 
-The DPcore implementation of Wishbone is fairly bare-bones.  That is, it does not use other Wishbone signals such as: RST_I, TGD_I, TGD_O, CYC_I, ERR_O, LOCK_I, RTY_O, SEL_I, or TGC_I. 
- 
- 
- 
-=== Download, Build, and Test DPcore === 
- 
- 
-You can download the source code for DPcore and build a binary image with the following commands: 
-        git clone https://github.com/DemandPeripherals/DPCore.git 
-        cd DPCore/src 
-        # Edit perilist to set the peripherals in your build 
-        vi perilist 
-        make 
-Expect several warnings about signals without loads.  This happens because some pins are defined but never used. 
- 
-        sudo cp DPCore.bin /usr/local/lib 
-        # start dpdaemon and test Baseboard LEDs 
-        dpdaemon -l /usr/local/lib/DPCore.bin -s /dev/ttyUSB0 
-        /usr/local/bin/dpset bb4io leds 55 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
- 
  
  
  
  
usersguide/usersguide.1645995395.txt.gz · Last modified: 2022/02/27 20:56 by dpisuperadmin