Maciej G.

Maciej G. Projektant /
Programista, Famor
S.A.

Temat: Komunikacja SPI -> Arduino - Elbert v2(Spartan III)

Cześć,

kończąc kurs CPLD/FPGA ze strony:

https://startingelectronics.org/software/VHDL-CPLD-cour...

wypróbowałem komunikację SPI (FPGA is SPI slave) pomiędzy Ardiuon Uno a moją płytka FPGA "Elbert v2)

https://numato.com/elbert-v2-spartan-3a-fpga-developmen...

Oto pliki projektu ISE Webpack 14.7

Moduł klienta SPI (3 sygnały : MOSI - data, Slave enable, SPI clock):


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity SPI_rx2_top is
Port ( SCK : in STD_LOGIC; -- SPI input clock
DATA : in STD_LOGIC; -- SPI serial data input
CS : in STD_LOGIC; -- chip select input (active low)
LED : inout STD_LOGIC_VECTOR (7 downto 0));
end SPI_rx2_top;

architecture Behavioral of SPI_rx2_top is
signal dat_reg : STD_LOGIC_VECTOR (7 downto 0);
begin

process (SCK)
begin
if (SCK'event and SCK = '1') then -- rising edge of SCK
if (CS = '0') then -- SPI CS must be selected
-- shift serial data into dat_reg on each rising edge
-- of SCK, MSB first
dat_reg <= dat_reg(6 downto 0) & DATA;
end if;
end if;
end process;

-- only update LEDs when not shifting (CS inactive)
LED <= dat_reg when (CS = '1') else LED;

end Behavioral;


A tu plik "user constraints" dla mojej płytki:



NET "SCK" LOC = "P19";
NET "DATA" LOC = "P21";
NET "CS" LOC = "P18";

// PINY ZGODNIE Z INSTRUKCJA DO PLYTKI (ODREBNY PIN DO KAZDEGO Z WYJSC)
NET "LED<0>" LOC = "P46"; //LED0
NET "LED<1>" LOC = "P47"; //LED1
NET "LED<2>" LOC = "P48"; //LED2
NET "LED<3>" LOC = "P49"; //LED3
NET "LED<4>" LOC = "P50"; //LED4
NET "LED<5>" LOC = "P51"; //LED5
NET "LED<6>" LOC = "P54"; //LED6
NET "LED<7>" LOC = "P55"; //LED7



A tu przykładowy kod dla Arduino :


*
Digital Pot Control

This example controls an Analog Devices AD5206 digital potentiometer.
The AD5206 has 6 potentiometer channels. Each channel's pins are labeled
A - connect this to voltage
W - this is the pot's wiper, which changes when you set it
B - connect this to ground.

The AD5206 is SPI-compatible,and to command it, you send two bytes,
one with the channel number (0 - 5) and one with the resistance value for the
channel (0 - 255).

The circuit:
* All A pins of AD5206 connected to +5V
* All B pins of AD5206 connected to ground
* An LED and a 220-ohm resisor in series connected from each W pin to ground
* CS - to digital pin 10 (SS pin)
* SDI - to digital pin 11 (MOSI pin)
* CLK - to digital pin 13 (SCK pin)

created 10 Aug 2010
by Tom Igoe

Thanks to Heather Dewey-Hagborg for the original tutorial, 2005

*/


// inslude the SPI library:
#include <SPI.h>


// set pin 10 as the slave select for the digital pot:
const int slaveSelectPin = 10;

void setup() {
// set the slaveSelectPin as an output:
pinMode(slaveSelectPin, OUTPUT);
// initialize SPI:
SPI.begin();
}

void loop() {
// go through the six channels of the digital pot:
for (int channel = 0; channel < 6; channel++) {
// change the resistance on this channel from min to max:
for (int level = 0; level < 255; level++) {
digitalPotWrite(channel, level);
delay(10);
}
// wait a second at the top:
delay(100);
// change the resistance on this channel from max to min:
for (int level = 0; level < 255; level++) {
digitalPotWrite(channel, 255 - level);
delay(10);
}
}

}

void digitalPotWrite(int address, int value) {
// take the SS pin low to select the chip:
digitalWrite(slaveSelectPin, LOW);
// send in the address and value via SPI:
SPI.transfer(address);
SPI.transfer(value);
// take the SS pin high to de-select the chip:
digitalWrite(slaveSelectPin, HIGH);
}
Użyte 3 piny 13, 1, 10 - opis w programie. Komunikacja działa bez zarzutu.

Pozdrawiam
Ten post został edytowany przez Autora dnia 11.08.17 o godzinie 17:13
Jakub Tyburski

Jakub Tyburski Asystent dydaktyczny
- Wojskowa Akademia
Techniczna w War...

Temat: Komunikacja SPI -> Arduino - Elbert v2(Spartan III)

Generalnie nieźle, ale można to jeszcze lekko uporządkować w następujący sposób:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity SPI_rx2_top is
port ( SCK, DATA, CS : in STD_LOGIC;
LED : inout STD_LOGIC_VECTOR (7 downto 0));
end SPI_rx2_top;

architecture Behavioral of SPI_rx2_top is
signal dat_reg : STD_LOGIC_VECTOR (7 downto 0);
begin

process (SCK)
begin
if rising_edge(SCK) then
if (CS = '0') then dat_reg <= dat_reg(6 downto 0) & DATA; else LED <= dat_reg; end if;
end if;
end process;

end Behavioral;


Dlaczego tak? Ponieważ kod, który pokazałeś prowadzi do syntezowania zatrzasków w układzie FPGA (kod, który dałeś prowadzi do budowy następującego układu: http://imgur.com/a/cjQwO ), które nie zawsze w oczekiwany przez nas sposób się zachowują (sam się o tym wiele razy przekonałem). Dlatego też dąży się do unikania ich i "podczepiania" wszystkiego pod logikę sekwencyjną (czyli krótko mówiąc: pod zegar). Wówczas układ się nawet upraszcza przy zachowaniu tej samej funkcjonalności (tak jak tutaj już po użyciu mojego kodu: http://imgur.com/a/Emrnt ). Całość rzecz jasna testowana w oparciu o Quartusa co prawda, ale podobnie Xilinx też się będzie zachowywał :)Ten post został edytowany przez Autora dnia 12.08.17 o godzinie 12:37
Jakub Tyburski

Jakub Tyburski Asystent dydaktyczny
- Wojskowa Akademia
Techniczna w War...

Temat: Komunikacja SPI -> Arduino - Elbert v2(Spartan III)

Można też kombinować w ten sposób:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity SPI_rx2_top is
Port ( SCK, DATA, CS : in STD_LOGIC;
LED : inout STD_LOGIC_VECTOR (7 downto 0));
end SPI_rx2_top;

architecture Behavioral of SPI_rx2_top is
signal dat_reg : STD_LOGIC_VECTOR (7 downto 0);
begin

process (SCK)
begin
if (CS = '1') then LED <= dat_reg;
elsif rising_edge(SCK) then dat_reg <= dat_reg(6 downto 0) & DATA;
end if;
end process;

end Behavioral;


ale prowadzi to do tego samego tj do powstawania zatrzasków jak w przypadku twojego kodu.Ten post został edytowany przez Autora dnia 12.08.17 o godzinie 12:51
Maciej G.

Maciej G. Projektant /
Programista, Famor
S.A.

Temat: Komunikacja SPI -> Arduino - Elbert v2(Spartan III)

Jakub T.:
Można też kombinować w ten sposób:
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity SPI_rx2_top is
Port ( SCK, DATA, CS : in STD_LOGIC;
LED : inout STD_LOGIC_VECTOR (7 downto 0));
end SPI_rx2_top;

architecture Behavioral of SPI_rx2_top is
signal dat_reg : STD_LOGIC_VECTOR (7 downto 0);
begin

process (SCK)
begin
if (CS = '1') then LED <= dat_reg; [/quote]> elsif rising_edge(SCK) then dat_reg <= dat_reg(6 downto > 0) & DATA; [quote] end if;
end process;

end Behavioral;


ale prowadzi to do tego samego tj do powstawania zatrzasków jak w przypadku twojego kodu.

Podobno zatrzasków w implementacji należy unikać (ze względu właśnie na asynchroniczność układu), ale czy zawsze jest to możliwe? Albo inaczej, czy są jakieś metody postępowaniaa aby implementację przerobić na synchroniczną? Czy raczej jest to sztuka polegająca na doświadczeniu?

PozdrawiamTen post został edytowany przez Autora dnia 12.08.17 o godzinie 13:56
Jakub Tyburski

Jakub Tyburski Asystent dydaktyczny
- Wojskowa Akademia
Techniczna w War...

Temat: Komunikacja SPI -> Arduino - Elbert v2(Spartan III)

Unikać należy tam gdzie się da oczywiście (jasna sprawa, że nie we wszystkich zastosowaniach da się uniknąć - to by było za pięknie). A metoda postępowania generalnie jest taka- umieszczać całość w procesie zawierającym warunek reagujący na zbocze narastające lub opadające (to co jest umieszczone w procesie z takim warunkiem to nic innego jak w najprostszym przypadku układ podłączony do jednego wielkiego przerzutnika typu D). Niemniej to też na swój sposób sztuka polegania na doświadczeniu (są czasem takie kody, że środowisko nawet jeśli z kodu wynika, że będzie ciut asynchronicznie to i tak wpakuje to w sposób synchroniczny - i vicewersa). Stąd też warto po syntezie spojrzeć w podglądy RTL jak środowisko zsyntezowało kod, aby mieć 100% pewność, że nie będą zatrzaski występować (sam kod jak widać to jednak nie wszystko w przypadku układów programowalnych :) )Ten post został edytowany przez Autora dnia 12.08.17 o godzinie 14:17

Następna dyskusja:

Virtex6, Spartan 6




Wyślij zaproszenie do