This post features a game activity to learn more about the differences between AMD Xilinx Spartan-6 and AMD Xilinx Spartan-7 FPGAs with the help of the Emubot sequencing robot.
This post is part 10 of my contribution to the "7 Ways to Leave Your Spartan-6" program, learning about the Xilinx Spartan-7 FPGA on the Digilent Arty S7 50 board.
In the video the Emubot is programmed to solve the path for the Static Power features from the AMD Xilinx Spartan-6 to the AMD Xilinx Spartan-7
Learning the differences between Spartan-6 and Spartan-7 with the Emubot
The activity is a game of finding the best path from Spartan-6 to Spartan-7 for seven of its main features using the Emubot programmable sequence robot.
About the Emubot:
- The Emubot is a simplified Logo turtle we have developed on the AMD-Xilinx Spartan-7 FPGA of the Digilent Arty S7 board.
- Emubot can be programmed to go forward and turn left and right by pressing the corresponding buttons. "Emubot like emus cannot fly or walk backwards, only forwards"
- Emubot can also "see" the colors that are under the robot.
The Game Board
The board is a 4x4 cell matrix with a Spartan-6 cell as the start and a Spartan-7 cell as the finish. The other fourteen cells contain seven Spartan-6 features and the other seven the corresponding upgraded Spartan-7 features.
Games Rules
Starting from the Spartan-6 starting cell, create a path that drives the Emubot to the Spartan-7 finish cell. On the way, you must first pass through a Spartan-6 characteristic cell and then pass through the cell with the improved or equivalent characteristic of the Spartan-7.The path has to end at the Spartan-7 cell.
The Goal of the Game
Drive the robot from the Spartan-6 cell to the Spartan-7 cell and complete the seven paths.
Learning a few more facts along the way:
- Spartan-6 FPGAs use 45nm technology whereas Spartan-7 and other 7 series of FPGAs are manufactured using 28nm technology and are 30% faster compared to Spartan 6 FPGAs.
- Spartan-7 devices also offer newer features like an integrated ADC, dedicated security features, and Q-grade (-40 to +125°C) on all commercial devices.
- Spartan-7 comes with XADC which is a 1 MSPS ADC which enables the developer to observe the internal supply voltages and die temperature.
- Spartan-6 LXT FPGAs provide multi-gigabit GTP transceivers with a maximum speed of 3.125 Gbps.
- Spartan-7 FPGAs do not have high-speed transceivers. If your design requires high-speed transceivers, you cannot migrate the design to Spartan-7 FPGAs. You’ll need to use another member of the Xilinx 7 Series, including Artix-7, Kintex-7, or Virtex-7 FPGAs or the Zynq 7000 SoC family. 7 series devices which support transceivers can support higher data rates or up to 6/25 Gb/s
ug429_7Series_Migration.pdf • Viewer • Documentation Portal (xilinx.com)
Migrating Xilinx Spartan-6 to 7 Series & Beyond (avnet.com)
Path 1: The CLB Structures. Logic Cells, LUTs, Slices, and CLBs
- Optional: Place one color card over the Spartan-6 CLB Structure cell and other color card over the Spartan-7 CLB Structure cell.
- Drive the robot from the Spartan-6 cell to the Spartan-7 cell passing through the Spartan-6 CLB Structure cell and the Spartan-7 CLB Structure cell in order.
Learning a few more facts along the way:
The "logic cells" is a kind of metric that can be used to compare between different families of devices. Originally a "logic cell" was a physical element of the FPGA fabric consisting of a 4-input LUT followed by a flip-flop. The Spartan-6 introduced a new 6-input LUT architecture.
- The Spartan-6 and Spartan-7 FPGAs have similar 6-input Lock Up Tables (LUTs) with two associated flip flops.
- The architectures of both FPGA families combine eight logic cells to create a slice. Each Spartan-6 FPGA slice contains four LUTs and eight flip-flops
- The Spartan-6 and Spartan-7 FPGAs incorporate two slice types: Slice_M and Slice_L.
- The Slice_M LUT can act as a distributed memory or a shift register. The Slice_L cannot.
- Two slices combine to create a configurable logic block (CLB).
- Spartan-6 FPGAs also have a Slice_X, which is the most basic of the three slice configurations.
- Functions that were implemented using a Spartan-6 Slice_X can be easily accommodated within a Slice_L, and logic synthesis for Spartan-7 devices will automatically retarget Slice_X usage to Slice_L, which can improve your design’s performance.
- Total I/O Count: Spartan-6 Maximum 576 user I/O (in XC6SLX150). Spartan-7 Maximum 400 user I/O (in XC7S100).
- Logic Cells: Spartan-6 Maximum 147,443 logic cells (in XC6SLX150). Spartan-7 Maximum 102,400 logic cells (in XC7S100).
- Flip Flops: Spartan-6 Maximum 184,304 flip flops (in XC6SLX150).. Spartan-7 Maximum 128,000 flip flops (in XC7S100).
Spartan-6 FPGA Configurable Logic Block
7 Series FPGAs Configurable Logic Block User Guide (UG474) (xilinx.com)
Path 2: The Block RAMs
- Optional: Place one color card over the Spartan-6 Block RAM cell and another color card over the Spartan-7 Block RAM cell.
- Drive the robot from the Spartan-6 cell to the Spartan-7 cell passing through the Spartan-6 Block RAM cell and the Spartan-7 Block RAM cell in order.
Learning a few more facts along the way:
Block RAMs (or BRAM) stands for Block Random Access Memory. Block RAMs are used for storing large amounts of data inside of your FPGA. Block RAMs can replace a lot of traditional logic.
- Block RAM (BRAM) architectures differ significantly between Spartan-6 and Spartan-7 FPGAs.
- Spartan-6 BRAMs are arranged as 18-Kbit blocks, which can be configured as two 9-Kbit blocks.
- Each Spartan-7 BRAM has a 36-Kbit capacity and can be configured as two 18-Kbit memories.
- For most applications, logic synthesis will automatically retarget the larger Spartan-7 BRAMs.
- The Spartan-7 BRAM offers several significant improvements over the BRAM block used in Spartan-6 FPGAs.
- Spartan-7 BRAMs have built-in FIFO capabilities, easy facility for cascading BRAMs, and built-in Error Correction Codes (ECC).
- Total Block RAM (Kbits): Spartan-6 Maximum 4,824 (in XC6SLX150). Spartan-7 Maximum 4,320 (in XC7S100).
Migration: If the design is organized with many smaller memories constructed from BRAMs, then you may need a larger Spartan-7 FPGA to support that many small memories.
Xilinx UG383 Spartan-6 Block RAM User Guide
7 Series FPGAs Data Sheet: Overview (DS180) (xilinx.com)
Path 3: The Digital Signal Processing (DSP) Slices
- Optional: Place one color card over the Spartan-6 DSP Slice cell and another color card over the Spartan-7 DSP Slice cell.
- Drive the robot from the Spartan-6 cell to the Spartan-7 cell passing through the Spartan-6 DSP Slice cell and the Spartan-7 DSP Slice cell in order.
Learning a few more facts along the way:
- Both Spartan-6 and Spartan-7 provide dedicated DSP Slices incorporating single-cycle, hardware multiplier/accumulators (MACs).
- Spartan-6 FPGAs employ a DSP48A1 slice with an 18×18-bit signed multiplier.
- Spartan-7 FPGAs employ a much more advanced DSP48E1 slice, which implements a 25×18-bit signed multiply.
- A and B registers can be concatenated in the 7 series
- The A register feeds the pre-adder in the 7 series instead of the B register
- The DSP48E1 cascading capability on both pipeline paths allows larger multipliers and larger post-adders.
- The DSP48E1 slice supports a SIMD (Single Instruction Multiple Data) mode, which allows increased throughput
- The DSP48E1 can implement an ALU that performs any of ten different logic functions on the two input operands.
- The DSP48E1 slice also incorporates a built-in pattern detector
- The DSP48E1 incorporates a 17-bit shift register.
-
DSP Slices: Spartan-6 Maximum 180 DSP Slices (in XC6SLX150). Spartan-7 Maximum 160 DSP Slices (in XC7S100).
Migration
- The Xilinx Vivado logic-synthesis engine should map designs using the older DSP48A1 slice to the newer DSP48E1 slice automatically.
- Spartan-6 family DSP designs can be converted to the 7 series. The DSP48E1 slice’s advanced functions, such as SIMD mode, won’t be mapped in automatically.
- Xilinx provides language templates in the Vivado editor to ease the use of these newer DSP features.
- Virtex-6 family DSP designs migrate directly to the DSP resources of the 7 series.
- Migration of designs with cascaded DSP slices should consider the number of DSP slices per column.
7 Series DSP48E1 Slice User Guide (UG479) (xilinx.com)
Path 4: The Clocking
- Optional: Place one color card over the Spartan-6 Clocking cell another color card over the Spartan-7 Clocking cell.
- Drive the robot from the Spartan-6 cell to the Spartan-7 cell passing through the Spartan-6 Clocking cell and the Spartan-7 Clocking cell in order.
Learning a few more facts along the way:
- The Spartan-7 FPGA’s clocking architecture is significantly simpler than the clocking architecture implemented in Spartan-6 FPGAs.
- Clocking in a Spartan-6 FPGA employs several different buffer types including BUFG, BUFH, BUFIO2, and BUFPLL.
- Spartan-6 FPGAs provide several other clocking resources including Digital Clock Managers (DCM) and Phase Locked Loops (PLL).
- Spartan-7 FPGAs implement a simpler clocking architecture that boosts performance significantly.
Migration:
- Xilinx design software will automatically migrate most Spartan-6 buffers, such as BUFH and BUFG,
- you will need to migrate buffers that are specific to Spartan-6, like BUFIO2, manually if you have directly instantiated them in your design.
Spartan-6 FPGA Clocking Resources
7 Series FPGAs Clocking Resources User Guide (UG472) (xilinx.com)
Path 5: The Memory Interfaces
- Optional: Place one color card over the Spartan-6 Memory Interfaces cell and another color card over the Spartan-7 Memory Interfaces cell.
- Drive the robot from the Spartan-6 cell to the Spartan-7 cell passing through the Spartan-6 Memory Interfaces cell and the Spartan-7 Memory Interfaces cell in order.
Learning a few more facts along the way:
Interfacing with high-performance external SDRAMs is critical for many FPGA-based designs.
- Both Spartan-6 and Spartan-7 FPGAs can interface directly with DDR, DDR2, DDR3, and LPDDR SDRAMs.
- Spartan-6 FPGAs incorporate as many as four hardened, integrated memory-controller blocks.
- Spartan-7 FPGAs implement the memory controller with a soft IP core and a hardened memory PHY. This design scheme gives Spartan-7 FPGAs more design flexibility.
- The Spartan-7 soft memory controller IP supports DDR2, DDR3, DDR3L, and LPDDR2 SDRAMs.
Spartan-6 FPGA Memory Interface Solutions
Xilinx DS176 7 Series FPGAs Memory Interface Solutions
Path 6: The Static Power
- Optional: Place one color card over the Spartan-6 Static Power cell and another color card over the Spartan-7 Static Power cell.
- Drive the robot from the Spartan-6 cell to the Spartan-7 cell passing through the Spartan-6 Static Power cell and the Spartan-7 Static Power cell in order.
Learning a few more facts along the way:
- Spartan 6 series of FPGAs operate at 1.2V (1.0V Low Power Mode) core voltage,
- Spartan 7 FPGAs operate at 1.0V (0.95V Low Power Mode) core voltage consumes 50% less power at nominal voltage and 70% lower static power at V-low.
Path 7: The Developing Tools
- Optional: Place one color card over the Spartan-6 Developing Tools cell and another color card over the Spartan-7 Developing Tools cell.
- Drive the robot from the Spartan-6 cell to the Spartan-7 cell passing through the Spartan-6 Developing Tools cell and the Spartan-7 Developing Tools cell in order.
Learning a few more facts along the way:
- Spartan 6 FPGAs are only supported by Xilinx ISE Design Suit.
- Spartan-6 devices use the ISE, EDK, PlanAhead, and SDK tool chain.
- 7 series FPGAs are supported by Xilinx Vivado tool along with Vitis HLS and Vitis IDE for software development.
- Vivado uses XDC which are based on the SDC format.
- ISE uses the UCF format.
- There is a huge improvement in design efficiency gained by using Vivado tools.
- The Vivado tool has been created for the 7 Series devices (Virtex-7, Kintex-7, Artix-7, and Zynq-7000).
- As new device families are developed and released by Xilinx, they will also be supported with the Vivado tool set.
- There is no plan to support earlier device families in the Vivado tool.
Vivado ML Overview (xilinx.com)
ISE to Vivado Design Suite Migration Guide
Game Variants
Reorder the cells
You can reorder the cells as you want. Here is a paper implementation.
Color cards
Emubot can see colors. You can put up to three colored cards, red, green and blue, and Emubot will indicate the order in which they have been passed the first time.
You can use them as check cells in challenges.
Total Score
You have an initial score of 1000 points for each step forward you are penalized with 50 points.
RGB LEDs
The two RGB LEDs indicate if the robot has passed over the blue and red cards with the respective colors.
Game Source Code
The application can be downloaded from the github repository under E14SpartanMigrationProgram/bot/src/emubot_find_path_app.c
GitHub - javagoza/E14SpartanMigrationProgram
It's a very simple application that makes extensive use of the Bot Application Framework.
/************************************************************************/
/* */
/* emubot_find_path_app.c -- emubot application */
/* This file is part of the Arty S7 Bot Library */
/* */
/************************************************************************/
/* Author: Enrique Albertos */
/************************************************************************/
/*
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
*/
/************************************************************************/
/* Module Description: */
/* */
/* This file contains the emubot find path application */
/* After initial powering, the sequence memory is cleared. */
/* Toggle PROGRAM/RUN mode with toggle switch SW3. */
/* In PROGRAM mode the user can press a sequence of commands, */
/* which are stored in the sequence memory. */
/* A maximum of 48 commands can be stored; each command being either */
/* one forward movement or a left/right turn. */
/* User can delete commands with the DELETE button, */
/* BTN3 in PROGRAM MODE. */
/* Each forward command causes the unit to move approx. 20cm forward. */
/* Each turn command causes the unit to rotate 90 degres. */
/* When the user finish programming the sequence the user can change */
/* to RUN mode changing SW3 from PROG to RUN. */
/* The sequence will not start until the user press the RUN button, */
/* BTN3 in RUN MODE. */
/* In all the modes the OLED display shows the function for each button.*/
/* When the RUN button is pressed, the Emubot will execute all the */
/* commands stored in order. */
/* After each forward command the color under the robot is checked. */
/* Score starts with 1000 points. Each forward step substracts 50 points*/
/* When the command sequence completes, the Emubot will stop, */
/* then show the score and the color squence detected */
/* */
/************************************************************************/
/* Revision History: */
/* */
/* 2022/07/23: (EAC) created */
/* */
/************************************************************************/
#include "emubot_find_path_app.h"
#include "sleep.h"
#include "PmodCOLOR.h"
#define MAX_ACTIONS 16 * 3
static char bot_actions[MAX_ACTIONS];
/* Array containing a user defined font table. There can be up
** to 32 user defined characters. This table only defines 24
** of them.
** Each 8-byte row below defines one character glyph.
*/
uint8_t arrowsFont[cbOledFontUser] = { 0x00, 0x04, 0x06, 0x7F, 0x7F, 0x06, 0x04,
0x00, // Char 000 (.)
0x00, 0x10, 0x30, 0x7F, 0x7F, 0x30, 0x10, 0x00, // Char 001 (.)
0x08, 0x08, 0x08, 0x2A, 0x3E, 0x1C, 0x08, 0x00, // Char 002 (.)
0x08, 0x1C, 0x3E, 0x2A, 0x08, 0x08, 0x08, 0x00, // Char 003 (.)
};
#define CHAR_FORWARD 0
#define CHAR_LEFT 3
#define CHAR_RIGHT 2
#define CELL_SIZE_WIDTH 18.0 // cell size width in cm
#define CELL_SIZE_HEIGTH 18.0 // cell size width in cm
typedef enum Orientation {
VERTICAL = 0, HORIZONTAL = 1
} Orientation;
PmodCOLOR colorSensor;
void emu_bot_find_path_application() {
COLOR_Data data;
int score;
Orientation orientation = VERTICAL;
BotDrivers botDrivers;
BOT_init(&botDrivers);
int actions_number = 0;
xil_printf("EMU BOT find path application Started\r\n");
for (int ch = 0; ch < 0x04; ch++) {
OLED_DefUserChar(&botDrivers.oled, ch, &arrowsFont[ch * cbOledChar]);
}
OLED_SetCharUpdate(&botDrivers.oled, 0);
OLED_ClearBuffer(&botDrivers.oled);
OLED_SetCursor(&botDrivers.oled, 0, 0);
while (1) {
if (SWITCHES_DRIVER_poll_switch4(&botDrivers.switchesDriver)) {
OLED_SetCharUpdate(&botDrivers.oled, 1);
OLED_Clear(&botDrivers.oled);
OLED_SetCursor(&botDrivers.oled, 0, 3);
OLED_PutString(&botDrivers.oled, "LFT FWD RGT DEL");
OLED_SetCursor(&botDrivers.oled, 0, 0);
while (SWITCHES_DRIVER_poll_switch4(&botDrivers.switchesDriver)
&& actions_number < MAX_ACTIONS) {
if (BUTTONS_DRIVER_button1_pressed(&botDrivers.buttonsDriver)) {
bot_actions[actions_number++] = 'L';
OLED_PutChar(&botDrivers.oled, CHAR_LEFT);
}
if (BUTTONS_DRIVER_button2_pressed(&botDrivers.buttonsDriver)) {
bot_actions[actions_number++] = 'F';
OLED_PutChar(&botDrivers.oled, CHAR_FORWARD);
}
if (BUTTONS_DRIVER_button3_pressed(&botDrivers.buttonsDriver)) {
bot_actions[actions_number++] = 'R';
OLED_PutChar(&botDrivers.oled, CHAR_RIGHT);
}
if (BUTTONS_DRIVER_button4_pressed(&botDrivers.buttonsDriver)) {
if (actions_number > 0) {
actions_number--;
OLED_PutChar(&botDrivers.oled, ' ');
OLED_RecedeCursor(&botDrivers.oled);
OLED_RecedeCursor(&botDrivers.oled);
OLED_PutChar(&botDrivers.oled, ' ');
OLED_RecedeCursor(&botDrivers.oled);
}
}
OLED_PutChar(&botDrivers.oled, '_');
OLED_RecedeCursor(&botDrivers.oled);
usleep(100000);
OLED_PutChar(&botDrivers.oled, ' ');
OLED_RecedeCursor(&botDrivers.oled);
usleep(100000);
}
}
if (actions_number > 0) {
score = 1000;
COLOR_SetLED(&botDrivers.color, 1);
OLED_SetCursor(&botDrivers.oled, 0, 3);
OLED_PutString(&botDrivers.oled, "STOP RUN");
OLED_SetCursor(&botDrivers.oled, 0, 0);
// wait for run or stop button
while (!((BUTTONS_DRIVER_poll(&botDrivers.buttonsDriver) & 0b1001)
> 0)) {
usleep(1000);
}
OLED_SetCursor(&botDrivers.oled, 0, 3);
OLED_PutString(&botDrivers.oled, "STOP ");
OLED_SetCursor(&botDrivers.oled, 0, 0);
OLED_SetCursor(&botDrivers.oled, 0, 0);
OLED_PutString(&botDrivers.oled, " ");
OLED_PutString(&botDrivers.oled, " ");
OLED_PutString(&botDrivers.oled, " ");
OLED_SetCursor(&botDrivers.oled, 0, 0);
sleep(1);
int colorSequence[3];
int colorSequenceIndex = 0;
for (int i = 0; i < actions_number; ++i) {
if (BUTTONS_DRIVER_button1_pressed(&botDrivers.buttonsDriver)) {
// Cancel the sequence and exit
actions_number = 0;
OLED_Clear(&botDrivers.oled);
OLED_SetCursor(&botDrivers.oled, 0, 3);
OLED_PutString(&botDrivers.oled, " CANCEL");
sleep(1);
break;
}
if (bot_actions[i] == 'L') {
// turn the robot to the left 90 degrees
LEDS_DRIVER_set_led1_on(&botDrivers.ledsDriver);
OLED_PutChar(&botDrivers.oled, CHAR_LEFT);
DRIVING_DRIVER_turn_left_degrees(&botDrivers.drivingDriver,
90);
LEDS_DRIVER_set_led1_off(&botDrivers.ledsDriver);
if (orientation == VERTICAL) {
orientation = HORIZONTAL;
} else {
orientation = VERTICAL;
}
}
if (bot_actions[i] == 'R') {
// turn the robot to the right 90 degrees
LEDS_DRIVER_set_led3_on(&botDrivers.ledsDriver);
OLED_PutChar(&botDrivers.oled, CHAR_RIGHT);
DRIVING_DRIVER_turn_right_degrees(&botDrivers.drivingDriver,
90);
LEDS_DRIVER_set_led3_off(&botDrivers.ledsDriver);
if (orientation == VERTICAL) {
orientation = HORIZONTAL;
} else {
orientation = VERTICAL;
}
}
if (bot_actions[i] == 'F') {
LEDS_DRIVER_set_led2_on(&botDrivers.ledsDriver);
OLED_PutChar(&botDrivers.oled, CHAR_FORWARD);
// move the robot forward if the cells are not square
// move depending on orientation
if (orientation == VERTICAL) {
DRIVING_DRIVER_drive_forward_cm(
&botDrivers.drivingDriver,
CELL_SIZE_HEIGTH);
} else {
DRIVING_DRIVER_drive_forward_cm(
&botDrivers.drivingDriver,
CELL_SIZE_WIDTH);
}
LEDS_DRIVER_set_led2_off(&botDrivers.ledsDriver);
// check color under the robot
usleep(500000);
data = COLOR_GetData(&botDrivers.color);
usleep(2400);
data = COLOR_GetData(&botDrivers.color);
usleep(2400);
// detect blue color
if (data.r >> 10 < data.b >> 10 && data.g >> 11 < data.b >> 11) {
if (colorSequenceIndex < 3){
colorSequence[colorSequenceIndex++] = COLOR_BLUE;
}
xil_printf("BLUE\r\n");
RGB_LEDS_DRIVER_set_rgb_led1_blue_on(&botDrivers.rgbLedsDriver);
}
// detect red color
if (data.r >> 11 > data.b >> 11 && data.r >> 11 > data.g >> 11) {
if (colorSequenceIndex < 3){
colorSequence[colorSequenceIndex++] = COLOR_RED;
}
xil_printf("RED\r\n");
RGB_LEDS_DRIVER_set_rgb_led2_red_on(&botDrivers.rgbLedsDriver);
}
// detect green color
if (data.g >> 11 > data.b >> 11 && data.g >> 11 > data.r >> 11) {
if (colorSequenceIndex < 3){
colorSequence[colorSequenceIndex++] = COLOR_GREEN;
}
xil_printf("GREEN\r\n");
RGB_LEDS_DRIVER_set_rgb_led1_green_on(&botDrivers.rgbLedsDriver);
}
}
score = score - 50;
}
// Display Score
COLOR_SetLED(&botDrivers.color, 0);
OLED_SetCursor(&botDrivers.oled, 0, 0);
OLED_PutString(&botDrivers.oled, "SCORE: ");
OLED_putIntVariable(&botDrivers.oled, score);
BUTTONS_DRIVER_reset(&botDrivers.buttonsDriver);
// Display registeres color sequence
OLED_SetCursor(&botDrivers.oled, 0, 1);
for (int i =0; i< colorSequenceIndex; i++ ){
if(colorSequence[i] == COLOR_BLUE){
OLED_PutString(&botDrivers.oled, "BLUE ");
}
if(colorSequence[i] == COLOR_RED){
OLED_PutString(&botDrivers.oled, "RED ");
}
if(colorSequence[i] == COLOR_GREEN){
OLED_PutString(&botDrivers.oled, "GREEN ");
}
}
// wait for button showing score
while (!((BUTTONS_DRIVER_poll(&botDrivers.buttonsDriver) & 0b1001)
> 0)) {
usleep(1000);
}
}
RGB_LEDS_DRIVER_set_rgb_leds_state(&botDrivers.rgbLedsDriver, 0);
OLED_SetCharUpdate(&botDrivers.oled, 0);
OLED_ClearBuffer(&botDrivers.oled);
OLED_SetCursor(&botDrivers.oled, 0, 0);
OLED_PutString(&botDrivers.oled, " EmuBot v1.0");
OLED_SetCursor(&botDrivers.oled, 0, 2);
OLED_PutString(&botDrivers.oled, "SW3 -> PROG MODE");
OLED_Update(&botDrivers.oled);
actions_number = 0;
BUTTONS_DRIVER_reset(&botDrivers.buttonsDriver);
}
}
References
- ug429_7Series_Migration.pdf • Viewer • Documentation Portal (xilinx.com)
- Spartan-6 FPGA Configurable Logic Block
- 7 Series FPGAs Configurable Logic Block User Guide (UG474) (xilinx.com)
- Xilinx UG383 Spartan-6 Block RAM User Guide
- 7 Series FPGAs Data Sheet: Overview (DS180) (xilinx.com)
- 7 Series DSP48E1 Slice User Guide (UG479) (xilinx.com)
- Spartan-6 FPGA DSP48A1 Slice
- Spartan-6 FPGA Clocking Resources
- 7 Series FPGAs Clocking Resources User Guide (UG472) (xilinx.com)
- MicroBlaze Soft Processor Core (xilinx.com)
- ISE Design Suite (xilinx.com)
- Vivado ML Overview (xilinx.com)
- Xilinx Power Estimator (XPE)
- ISE to Vivado Design Suite Migration Guide
- Spartan-7 Deep Dive: What You Need to Know for Updating Your Design
- Spartan-6 FPGA Memory Interface Solutions
- Xilinx DS176 7 Series FPGAs Memory Interface Solutions
- Spartan-6 FPGA Clocking Resources
- 7 Series FPGAs Clocking Resources User Guide (UG472) (xilinx.com)