Forum: FPGA, VHDL & Co. Custom SPI slave mit microblaze


von FPGA B. (beginner_eda)


Angehängte Dateien:

Lesenswert?

Hallo,
ich probiere custom SPI slave zu schreiben, RX part(mosi von master) 
funktioniert schon aber Tx part(miso zum master) geht halb clock cycle 
recht verschoben entsprechend SPI clock.
here ist meine VHDL code:
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.STD_LOGIC_ARITH.ALL;
4
use IEEE.STD_LOGIC_UNSIGNED.ALL;
5
--use ieee.numeric_std.all;
6
library UNISIM;
7
use UNISIM.VCOMPONENTS.ALL;
8
entity spi_top is
9
port (
10
11
XADC_GPIO_0 : in std_logic; --mosi
12
XADC_GPIO_2 : in std_logic; --slave select
13
XADC_GPIO_3 : in std_logic; --slave clock
14
15
XADC_GPIO_1 : out std_logic; --miso
16
reset : in STD_LOGIC;
17
rs232_uart_rxd : in STD_LOGIC;
18
rs232_uart_txd : out STD_LOGIC;
19
sys_diff_clock_clk_n : in STD_LOGIC;
20
sys_diff_clock_clk_p : in STD_LOGIC
21
);
22
end spi_top;
23
architecture STRUCTURE of spi_top is
24
component design_1 is
25
port (
26
rs232_uart_rxd : in STD_LOGIC;
27
rs232_uart_txd : out STD_LOGIC;
28
dip_switches_4bits_tri_i : in STD_LOGIC_VECTOR ( 7 downto 0 );
29
dip_switches_4bits_0_tri_o : out STD_LOGIC_VECTOR ( 7 downto 0 );
30
out_clk : out STD_LOGIC;
31
out_clk_1 : out STD_LOGIC;
32
gpio_rtl_tri_i : in STD_LOGIC_VECTOR ( 0 to 0 );
33
gpio_rtl_0_tri_i : in STD_LOGIC_VECTOR ( 0 to 0 );
34
-- reset_gpio : out STD_LOGIC_VECTOR ( 0 to 0 );
35
sys_diff_clock_clk_n : in STD_LOGIC;
36
sys_diff_clock_clk_p : in STD_LOGIC;
37
reset : in STD_LOGIC
38
);
39
end component design_1;
40
signal clock_rtl1 : std_logic:='0';
41
signal clock_rtl2 : std_logic;
42
signal out_clk_p : std_logic;
43
signal out_clk_p1 : std_logic:='0';
44
signal count1m : std_logic_vector(3 downto 0):="0000";
45
signal count1mp : std_logic_vector(3 downto 0):="0000";
46
signal mosi_8bit: std_logic_vector (7 downto 0);
47
signal miso_8bit: std_logic_vector (7 downto 0);
48
signal miso_8bit_new: std_logic_vector (7 downto 0);
49
signal miso_int: std_logic_vector (7 downto 0);
50
signal count :STD_LOGIC_VECTOR (2 downto 0) := "000";
51
signal control, control1, clk_out, clk_out1: std_logic;
52
signal gpio1: std_logic;
53
signal gpio2: std_logic;
54
signal gpio3: std_logic;
55
signal gpio4: std_logic;
56
signal gpio_int: std_logic;
57
signal int_ctrl:std_logic;
58
signal reset_gpio_int : STD_LOGIC_VECTOR ( 0 to 0 );
59
signal count_natural : natural:=7;
60
signal XADC_GPIO_0_dly1: std_logic;
61
signal XADC_GPIO_1_dly1: std_logic;
62
signal XADC_GPIO_2_dly1: std_logic;
63
signal XADC_GPIO_3_dly1: std_logic;
64
begin
65
gpio1 <= XADC_GPIO_0;
66
67
XADC_GPIO_1 <= gpio2;
68
69
spi_slave_mosi:process(XADC_GPIO_3) 
70
begin
71
if rising_edge(XADC_GPIO_3) then
72
-- gpio1 <= XADC_GPIO_0;
73
if XADC_GPIO_2 = '0' then
74
mosi_8bit(0) <= gpio1;
75
mosi_8bit(1) <= mosi_8bit(0);
76
mosi_8bit(2) <= mosi_8bit(1);
77
mosi_8bit(3) <= mosi_8bit(2);
78
mosi_8bit(4) <= mosi_8bit(3);
79
mosi_8bit(5) <= mosi_8bit(4);
80
mosi_8bit(6) <= mosi_8bit(5);
81
mosi_8bit(7) <= mosi_8bit(6);
82
end if;
83
end if; 
84
end process;
85
 
86
control_slave_mosi:process(clock_rtl1) 
87
begin
88
if rising_edge(clock_rtl1) then
89
int_ctrl <= XADC_GPIO_2;
90
if (int_ctrl = '0' and XADC_GPIO_2 = '1' ) then
91
control <= '1';
92
else
93
control <= '0';
94
end if; 
95
end if; 
96
end process;
97
98
99
spi_slave_miso:process(XADC_GPIO_3) 
100
begin
101
if rising_edge(XADC_GPIO_3) then
102
103
if XADC_GPIO_2 = '0' then
104
105
gpio2 <= miso_8bit(count_natural);
106
107
count_natural <= count_natural - 1;
108
if (count_natural=0) then
109
110
count_natural <= 7;
111
end if;
112
end if;
113
end if; 
114
end process;
115
116
117
118
clk_1mhz:process (clock_rtl2)
119
begin
120
if rising_edge (clock_rtl2) then
121
if count1m=4 then
122
clock_rtl1 <= not clock_rtl1;
123
count1m <= "0000";
124
else
125
count1m <= count1m + '1';
126
end if;
127
128
end if;
129
130
end process;
131
 
132
133
design_inst: design_1
134
port map (
135
dip_switches_4bits_tri_i(7 downto 0) => mosi_8bit,
136
dip_switches_4bits_0_tri_o(7 downto 0) => miso_8bit,
137
gpio_rtl_tri_i(0) => control,
138
gpio_rtl_0_tri_i(0) => XADC_GPIO_3,
139
reset => reset,
140
-- reset_gpio(0) => reset_gpio_int(0),
141
rs232_uart_rxd => rs232_uart_rxd,
142
rs232_uart_txd => rs232_uart_txd,
143
sys_diff_clock_clk_n => sys_diff_clock_clk_n,
144
sys_diff_clock_clk_p => sys_diff_clock_clk_p,
145
out_clk => clock_rtl2,
146
out_clk_1 => out_clk_p
147
);
148
149
150
end STRUCTURE;

und C code:
1
#include <stdio.h>
2
#include "platform.h"
3
#include "xgpio.h"
4
#include "xparameters.h"
5
#include "microblaze_sleep.h"
6
void print(char *str);
7
//declare an XGpio and XGpio instance
8
XGpio GPIO_0;
9
XGpio_Config GPIO_0_conf;
10
XGpio GPIO_1;
11
XGpio_Config GPIO_1_conf;
12
13
int main()
14
{
15
// GPIO 0
16
GPIO_0_conf.BaseAddress = XPAR_AXI_GPIO_0_BASEADDR;
17
GPIO_0_conf.DeviceId = XPAR_AXI_GPIO_0_DEVICE_ID;
18
GPIO_0_conf.InterruptPresent = XPAR_GPIO_0_INTERRUPT_PRESENT;
19
GPIO_0_conf.IsDual = XPAR_GPIO_0_IS_DUAL;
20
//Initialize the XGpio instance
21
XGpio_CfgInitialize(&GPIO_0, &GPIO_0_conf, GPIO_0_conf.BaseAddress);
22
XGpio_SetDataDirection(&GPIO_0, 1, 0xff);
23
XGpio_SetDataDirection(&GPIO_0, 2, 0x01);
24
 
25
// GPIO 1
26
GPIO_1_conf.BaseAddress = XPAR_AXI_GPIO_1_BASEADDR;
27
GPIO_1_conf.DeviceId = XPAR_AXI_GPIO_1_DEVICE_ID;
28
GPIO_1_conf.InterruptPresent = XPAR_GPIO_1_INTERRUPT_PRESENT;
29
GPIO_1_conf.IsDual = XPAR_GPIO_1_IS_DUAL;
30
//Initialize the XGpio instance
31
XGpio_CfgInitialize(&GPIO_1, &GPIO_1_conf, GPIO_1_conf.BaseAddress);
32
XGpio_SetDataDirection(&GPIO_1, 1, 0x00);
33
XGpio_SetDataDirection(&GPIO_1, 2, 0x01);
34
 
35
init_platform();
36
print("Hello World\n\r");
37
u32 input;
38
u32 read;
39
u32 control;
40
// check = 0x3;
41
while(1){
42
//Read the switches values
43
// input = XGpio_DiscreteRead(&GPIO_0, 1);
44
// read = (input & 0xff);
45
xil_printf("outjustprint\n" );
46
// xil_printf("out = %x\n", XGpio_DiscreteRead(&GPIO_0, 1) );
47
if(( XGpio_DiscreteRead(&GPIO_0, 2) & 0x01))
48
{
49
xil_printf("read = %x\n", XGpio_DiscreteRead(&GPIO_0, 1));
50
51
}
52
// if(( XGpio_DiscreteRead(&GPIO_1, 2) & 0x01) == 0)
53
XGpio_DiscreteWrite(&GPIO_1, 1, 0x26);
54
// XGpio_DiscreteWrite(&GPIO_1, 1, 0x000000ee);
55
}
56
return 0;
57
}

ich weiss nicht wie das halb clock cycle recht Verschiebung für Tx 
part(miso zum master) fixieren?

P.S. sorry für meine Grammatikfehler.

: Bearbeitet durch User
von Klakx (Gast)


Lesenswert?

schreib doch ein paar Sätze mehr und führe mich damit zur Problemstelle 
in deinem Code. Für VHDL wäre es ebenfalls hilfreich die entsprechende 
Formatierung zu verwenden
1
VHDL-Code
.

PS: Du hattest es doch auch mit der Xilinx Komponente probiert. Hat 
diese nun funktioniert?

von FPGA B. (beginner_eda)


Lesenswert?

Klakx schrieb:
> schreib doch ein paar Sätze mehr und führe mich damit zur Problemstelle
> in deinem Code. Für VHDL wäre es ebenfalls hilfreich die entsprechende
> Formatierung zu verwenden
>
MISO Signal von SPI Slave zum SPI Master nicht synchronisiert mit SPI 
Clock sondern halb clock recht Verschiebung.
1
library IEEE;
2
use IEEE.STD_LOGIC_1164.ALL;
3
use IEEE.STD_LOGIC_ARITH.ALL;
4
use IEEE.STD_LOGIC_UNSIGNED.ALL;
5
--use ieee.numeric_std.all;
6
library UNISIM;
7
use UNISIM.VCOMPONENTS.ALL;
8
entity spi_top is
9
port (
10
11
XADC_GPIO_0 : in std_logic; --mosi
12
XADC_GPIO_2 : in std_logic; --slave select
13
XADC_GPIO_3 : in std_logic; --slave clock
14
15
XADC_GPIO_1 : out std_logic; --miso
16
reset : in STD_LOGIC;
17
rs232_uart_rxd : in STD_LOGIC;
18
rs232_uart_txd : out STD_LOGIC;
19
sys_diff_clock_clk_n : in STD_LOGIC;
20
sys_diff_clock_clk_p : in STD_LOGIC
21
);
22
end spi_top;
23
architecture STRUCTURE of spi_top is
24
component design_1 is
25
port (
26
rs232_uart_rxd : in STD_LOGIC;
27
rs232_uart_txd : out STD_LOGIC;
28
dip_switches_4bits_tri_i : in STD_LOGIC_VECTOR ( 7 downto 0 );
29
dip_switches_4bits_0_tri_o : out STD_LOGIC_VECTOR ( 7 downto 0 );
30
out_clk : out STD_LOGIC;
31
out_clk_1 : out STD_LOGIC;
32
gpio_rtl_tri_i : in STD_LOGIC_VECTOR ( 0 to 0 );
33
gpio_rtl_0_tri_i : in STD_LOGIC_VECTOR ( 0 to 0 );
34
-- reset_gpio : out STD_LOGIC_VECTOR ( 0 to 0 );
35
sys_diff_clock_clk_n : in STD_LOGIC;
36
sys_diff_clock_clk_p : in STD_LOGIC;
37
reset : in STD_LOGIC
38
);
39
end component design_1;
40
signal clock_rtl1 : std_logic:='0';
41
signal clock_rtl2 : std_logic;
42
signal out_clk_p : std_logic;
43
signal out_clk_p1 : std_logic:='0';
44
signal count1m : std_logic_vector(3 downto 0):="0000";
45
signal count1mp : std_logic_vector(3 downto 0):="0000";
46
signal mosi_8bit: std_logic_vector (7 downto 0);
47
signal miso_8bit: std_logic_vector (7 downto 0);
48
signal miso_8bit_new: std_logic_vector (7 downto 0);
49
signal miso_int: std_logic_vector (7 downto 0);
50
signal count :STD_LOGIC_VECTOR (2 downto 0) := "000";
51
signal control, control1, clk_out, clk_out1: std_logic;
52
signal gpio1: std_logic;
53
signal gpio2: std_logic;
54
signal gpio3: std_logic;
55
signal gpio4: std_logic;
56
signal gpio_int: std_logic;
57
signal int_ctrl:std_logic;
58
signal reset_gpio_int : STD_LOGIC_VECTOR ( 0 to 0 );
59
signal count_natural : natural:=7;
60
signal XADC_GPIO_0_dly1: std_logic;
61
signal XADC_GPIO_1_dly1: std_logic;
62
signal XADC_GPIO_2_dly1: std_logic;
63
signal XADC_GPIO_3_dly1: std_logic;
64
begin
65
gpio1 <= XADC_GPIO_0;
66
67
XADC_GPIO_1 <= gpio2;
68
69
spi_slave_mosi:process(XADC_GPIO_3) 
70
begin
71
if rising_edge(XADC_GPIO_3) then
72
-- gpio1 <= XADC_GPIO_0;
73
if XADC_GPIO_2 = '0' then
74
mosi_8bit(0) <= gpio1;
75
mosi_8bit(1) <= mosi_8bit(0);
76
mosi_8bit(2) <= mosi_8bit(1);
77
mosi_8bit(3) <= mosi_8bit(2);
78
mosi_8bit(4) <= mosi_8bit(3);
79
mosi_8bit(5) <= mosi_8bit(4);
80
mosi_8bit(6) <= mosi_8bit(5);
81
mosi_8bit(7) <= mosi_8bit(6);
82
end if;
83
end if; 
84
end process;
85
 
86
control_slave_mosi:process(clock_rtl1) 
87
begin
88
if rising_edge(clock_rtl1) then
89
int_ctrl <= XADC_GPIO_2;
90
if (int_ctrl = '0' and XADC_GPIO_2 = '1' ) then
91
control <= '1';
92
else
93
control <= '0';
94
end if; 
95
end if; 
96
end process;
97
98
99
spi_slave_miso:process(XADC_GPIO_3) 
100
begin
101
if rising_edge(XADC_GPIO_3) then
102
103
if XADC_GPIO_2 = '0' then
104
105
gpio2 <= miso_8bit(count_natural);
106
107
count_natural <= count_natural - 1;
108
if (count_natural=0) then
109
110
count_natural <= 7;
111
end if;
112
end if;
113
end if; 
114
end process;
115
116
117
118
clk_1mhz:process (clock_rtl2)
119
begin
120
if rising_edge (clock_rtl2) then
121
if count1m=4 then
122
clock_rtl1 <= not clock_rtl1;
123
count1m <= "0000";
124
else
125
count1m <= count1m + '1';
126
end if;
127
128
end if;
129
130
end process;
131
 
132
133
design_inst: design_1
134
port map (
135
dip_switches_4bits_tri_i(7 downto 0) => mosi_8bit,
136
dip_switches_4bits_0_tri_o(7 downto 0) => miso_8bit,
137
gpio_rtl_tri_i(0) => control,
138
gpio_rtl_0_tri_i(0) => XADC_GPIO_3,
139
reset => reset,
140
-- reset_gpio(0) => reset_gpio_int(0),
141
rs232_uart_rxd => rs232_uart_rxd,
142
rs232_uart_txd => rs232_uart_txd,
143
sys_diff_clock_clk_n => sys_diff_clock_clk_n,
144
sys_diff_clock_clk_p => sys_diff_clock_clk_p,
145
out_clk => clock_rtl2,
146
out_clk_1 => out_clk_p
147
);
148
149
150
end STRUCTURE;
.

> PS: Du hattest es doch auch mit der Xilinx Komponente probiert. Hat
> diese nun funktioniert?

Habe viele Mühe gegeben um Xilinx IP Core als SPI Slave zu benutzen 
trotzdem habe ich es nicht geschafft. Bin eigentlich ratlos mit alle 
konfigurationen.

Beitrag "Konfiguriere Xilinx SPI IP als Slave"

 und deswegen als Alternativ probiere ich Custom SPI Program zu 
verwenden.

: Bearbeitet durch User
von Klakx (Gast)


Lesenswert?

Ok schonmal hilfreich das so lesen zu können. Erstes Problem sehe ich 
mit den 3 clocks. Die sind zwar synchron zueinander, aber man muss gut 
aufpassen, dass die Bits richtig übernommen werden. Das konnte ich mir 
jetzt nicht anschauen.

Zweite Sache. Diese Takte gehen nicht an die flipflops sondern du 
taktest mit gpio Signalen. Besser ist es diese Signale als enable zu 
nehmen und die Takte zu verwenden. Das erzeugt sonst ggf ebenso 
unterschiedliches Verhalten zwischen Simulation und realem System.

Als frickeligen Workaround kannst du dein mosi_8bit vector verlängern 
und zur richtigen Stelle abgreifen.

Ansonsten zeig auch mal die waveform mit dem Problem und allen 
relevanten Signalen. Die Taktfrequenzen sind mir ebenso unbekannt. Warum 
überhaupt soviele Takte.

von Robert K. (Firma: Medizintechnik) (robident)


Lesenswert?

Wir sind auch an einer ähnlichen Sache dran und ich habe den Eindruck, 
dass das mit diesem AXI und Vivado noch nicht so ganz ausgereift zu sein 
scheint. Die Blocksymbole nach dieser Methodik verführen dazu, viele 
Takte herzunehmen und erklären eigentlich nicht, wann welcher Block mit 
welchem Takt zu treiben wäre.

Hier scheint mir ein Problem darin zu bestehen, dass SPI-Takte, die 
keine FPGA-Takte sind, als solche verwendet werden. Auch bei dem 
XADC_GPIO_3 bin ich mir nicht sicher, ob das ein Takt sein muss oder man 
den besser pollen sollte.

von Klakx (Gast)


Lesenswert?

Robert K. schrieb:
> Wir sind auch an einer ähnlichen Sache dran und ich habe den
> Eindruck,
> dass das mit diesem AXI und Vivado noch nicht so ganz ausgereift zu sein
> scheint. Die Blocksymbole nach dieser Methodik verführen dazu, viele
> Takte herzunehmen und erklären eigentlich nicht, wann welcher Block mit
> welchem Takt zu treiben wäre.

Verführen ja. Dann denkt man auch, dass man beliebig addressieren 
könnte. Da sollte man auch aufpassen. Man sollte aber schon vor dem 
Blockdesign wissen, wo welcher Takt rankommt. In VHDL ist das nicht 
anders. Clockkonzept + Datenblatt lesen. Man kann sich sicher streiten 
zwischen zusätzliche Überprüfungen/Einschränkungen/Komplexität und 
Freiheitsgrade/Anwenderfehlerquellen/Einfachheit :)

Robert K. schrieb:
> Hier scheint mir ein Problem darin zu bestehen, dass SPI-Takte, die
> keine FPGA-Takte sind, als solche verwendet werden. Auch bei dem
> XADC_GPIO_3 bin ich mir nicht sicher, ob das ein Takt sein muss oder man
> den besser pollen sollte.

Bei diesen Designs <50MHz macht man es sich sowieso wesentlich leichter, 
wenn mit seinem schnellem FPGA-Takt einfach die Signale überabtastet und 
die Flanke erkennt. Dann gibt es nur einen Takt.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.