Hello,
J'essaie de faire quelque chose de simple : lire les données que me fourni un ADC, et balancer les 8 bits de poids fort sur 8 leds pour voir si ça marche (et par la suite, je trouverai un moyen de tracer le signal pour faire un oscilloscope).
Mais je suis un peu perdu. Ya quelque chose qui marche pas, et se sais pas vraiment comment debugguer ça.
l'ADC en question : http://cds.linear.com/docs/en/datasheet/2308fb.pdf (500ksps / 8 canaux / 12 bits).
Pour la partie intéressante de la doc :
Donc, une horloge de 40MHz, une mesure toutes les 2µs (80 cycles).
Pour une mesure :
convst est à 1 pendant les 2 à 3 premiers cycles (20 à 40 ns d'après la doc, 2/3 cycles donnent 25 / 37.5ns)
sck fait 12 cycles à partir de 1.6µs (12 cycles à partir du 60ème / 80)
on envoie les paramètres de la prochaine mesure via sdi durant les 6 premiers cycles de sck
on récupère la mesure sur sdo pendant les 12 cycles de sck
Les paramètres pour les mesures sont "100010" ou "100000" : Single-ended / canal 0 / unipolar (faut donner un 1 ou 0 pour une mesure unipolaire ?) / le dernier bit est inutile, il n'est pas pris en compte avec un signal convst court.
Ce que j'ai fait :
Une horloge de 50MHz, un PLL pour transformer ça en 40MHz.
clk_adc compte jusque 80 et génère 5 signaux qui sont à 1 à certains moments précis :
o_actconvst à 1 de 0 à 3
o_actsck à 1 de 60 à 72
o_actsdi à 1 de 60 à 66
o_actsdo à 1 de 60 à 72
o_sdocpy à 1 de 72 à 73
(Il y à un retard d'un cycle, mais vu que le retard est le même partout c'est pas gênant je pense.)
Code VHDL : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56 library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; entity clk_adc is port( i_clk_40M: in std_logic; o_actconvst: out std_logic; o_actsck: out std_logic; o_actsdi: out std_logic; o_actsdo: out std_logic; o_sdocpy: out std_logic ); end clk_adc; architecture arch_clk_adc of clk_adc is signal cnt: unsigned(6 downto 0) := (others => '0'); signal act_sck: std_logic := '0'; signal act_sdi: std_logic := '0'; signal act_convst: std_logic := '1'; signal sdo_done: std_logic := '0'; begin process(i_clk_40M) begin if rising_edge(i_clk_40M) then if cnt = 79 then cnt <= (others => '0'); act_convst <= '1'; else cnt <= cnt + 1; if cnt = 2 then act_convst <= '0'; elsif cnt = 59 then act_sdi <= '1'; act_sck <= '1'; elsif cnt = 65 then act_sdi <= '0'; elsif cnt = 71 then act_sck <= '0'; sdo_done <= '1'; elsif cnt = 72 then sdo_done <= '0'; end if; end if; o_actconvst <= act_convst; o_actsck <= act_sck; o_actsdi <= act_sdi; o_actsdo <= act_sck; o_sdocpy <= sdo_done; end if; end process; end arch_clk_adc;
D'après une simulation ça marche correctement (il se passe rien sur la période non montrée):
Filter copie simplement l'horloge si "i_filter" est à 1.Le manque de process m'inquiète un peu vu que je rajoute un délai sur le signal d'horloge (?). Est-ce un problème ?
Code VHDL : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; entity filter is port( i_clk40M: in std_logic; i_filter: in std_logic; o_clk: out std_logic ); end filter; architecture arch_filter of filter is begin o_clk <= i_clk40M and i_filter; end arch_filter;
Niveau simulation ça semble bon aussi :
Send_data converti des données parallèle -> série pour les envoyer à l'ADC.
Code VHDL : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; entity send_data is port( i_clk40M: in std_logic; i_actsdi: in std_logic; i_actconvst: in std_logic; o_data: out std_logic ); end send_data; architecture arch_send_data of send_data is signal data: std_logic_vector(5 downto 0) := "000001"; -- ou "010001" signal s: std_logic_vector(5 downto 0); begin process(i_clk40M) begin if rising_edge(i_clk40M) then if i_actconvst = '1' then s <= data; elsif i_actsdi = '1' then o_data <= s(0); s(4 downto 0) <= s(5 downto 1); end if; end if; end process; end arch_send_data;
Galère à simuler car j'arrive pas à donner la forme que je veux aux signaux d'entrées. Du coup j'utilise des horloges avec des fréquences différentes.
Çà marche une fois sur deux sur la simulation à cause du fait que i_actconvst et i_actsdi puissent être tout deux à 1 sur la simulation, alors qu'ils ne peuvent normalement pas (ils sortent de clk_adc). Quand ils ne sont pas tous les deux à 1, ça marche.
Et enfin store_data fait l'inverse : lis les données de l'ADC (en série) et les écrit en parallèle pour les leds.
Code VHDL : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; entity store_data is port( i_clk40M: in std_logic; i_actsdo: in std_logic; i_sdocpy: in std_logic; i_data: in std_logic; o_data: out std_logic_vector(11 downto 0) ); end store_data; architecture arch_store_data of store_data is signal buff: std_logic_vector(11 downto 0); begin process(i_clk40M) begin if rising_edge(i_clk40M) then if i_actsdo = '1' then buff(10 downto 0) <= buff(11 downto 1); buff(11) <= i_data; elsif i_sdocpy = '1' then o_data <= buff; end if; end if; end process; end arch_store_data;
Même problème pour la simulation, i_actsdo et i_sdocpy ne peuvent normalement pas être à 1 tous les deux en même temps.
o_data(0) contient le bit de poids fort, o_data(11) le bit de poids faible.
Au niveau de l'assignation des pins, je pense que c'est bon (grande image) : http://i.imgur.com/rIBVtNc.png
Dernier truc, concernant l'utilisation, pour le moment j'essaie simplement avec une pile pour voir si je retrouve bien 1.5 V (ou une mesure proche).
J'ai essayé en mettant le - de la pile sur le pin 10, et le + sur le pin 2. Mais je suis vraiment pas sur de ça.
Le +5V sur le pin 1 il est fourni ? Ou faut que je le fournisse ?
La masse commune (pin 10) c'est censée être quoi exactement dans mon cas ? Masse de la carte ? Masse de la pile ?
Normalement avec tout ça, les 8 leds m'affichent les 8 bits de poids fort de la mesure, avec led0 = MSB et led7 = LSB.
Avec rien de branché, les leds m'affichent 1111 1111 (1 = allumé, je m'attendais au contraire, que tout soit éteint oO).
Avec la pile j'ai 0000 1101. (Mesure unipolaire ou dipolaire ne change rien).
Ce qui me donnerait une mesure entre 208 et 223mV (ou entre 3.873 et 3.888V si une led allumée veut dire 0) pour ma pile.
Bref ya évidement quelque chose qui déconne, mais je sais pas où ni comment chercher .
Par où je commence ?
Partager