Forum: FPGA, VHDL & Co. ZYBO Zynq-7000 Development Board - erste Schritte
Hallo,
meine ersten Schritte auf einem FPGA + Vivado.
Ziel des Projektes ist ein Roboterarm in der Art:
http://letsmakerobots.com/robot/project/micro-servo-robot
Mein persönliches Ziel, VHDL-2008 verstehen.
Meine Bitte an die Profis sind vor allem Tips wie es besser geht.
Codemäßig und Stilmäßig.
Ein PWM Signal habe ich schon mal generiert, das war nicht so schwer,
als nächstes kam dann das auslesen eines ADCs mittels i2c (PmodAD2 - 4
channel 12-bit A/D converter)
Den i2c habe ich hinbekommen, zumindest dass ich den ADC adressiere und
der mir dann jeweils nach Acks die Kanäle nacheinander ausgibt.
ich habe vier LEDs auf dem Board da versuche ich im Moment die ersten
4-Bits des 1.Kanals auf die LEDs zu legen um zu verstehen wie ich Daten
grundsätzlich abgreife. Funktioniert leider nicht wirklich.
Als Bild füge ich mal den Stand der Dinge als Schematics ein und den
Code als zip.
Zum programmieren nehme ich notepad++ das erleichtert mir die Arbeit
finde ich.
Im Moment sind pwm und i2c noch in zwei Projekten getrennt.
Hier ist auch mal mein PWM signal
top_modul 1 | library IEEE;
| 2 | use IEEE.STD_LOGIC_1164.ALL;
| 3 |
| 4 | entity pwm_top is
| 5 | port (
| 6 | -- Inputs
| 7 | Clk_125MHz : in std_logic;
| 8 | btn_0 : in std_logic; -- Steuerung PWM
| 9 | btn_1 : in std_logic; -- Steuerung PWM
| 10 |
| 11 | -- Outputs
| 12 | led_0 : out std_logic;
| 13 | led_1 : out std_logic;
| 14 | je_0 : out std_logic -- Ausgang zum Servo
| 15 | );
| 16 | end pwm_top;
| 17 |
| 18 | architecture Archi of pwm_top is
| 19 | signal Clk_75MHz, Clk_500kHz, Clk_12_288MHz, Clk_3_072MHz, Clk_250kHz, Clk_48kHz : std_logic;
| 20 |
| 21 | begin
| 22 | ClockTree: entity work.ClockTree port map ( Clk_125MHz, Clk_75MHz, Clk_12_288MHz, Clk_3_072MHz, Clk_500kHz, Clk_250kHz, Clk_48kHz );
| 23 | pwm: entity work.pwm port map (btn_0, btn_1, led_0, led_1, Clk_48kHz, je_0); --generic map ( tastgrad => 50 )
| 24 | end Archi;
|
pwm 1 | library IEEE; use IEEE.STD_LOGIC_1164.ALL, IEEE.NUMERIC_STD.ALL;
| 2 | library UNISIM; use UNISIM.VComponents.all;
| 3 |
| 4 | entity pwm is
| 5 | -- generic ( tastgrad : integer := 960);
| 6 |
| 7 | port (
| 8 | btn_0, btn_1 : in std_logic;
| 9 | led_0, led_1 : out std_logic;
| 10 | Clk_48kHz : in std_logic;
| 11 | pwm : out std_logic
| 12 | );
| 13 |
| 14 | end pwm;
| 15 |
| 16 | architecture Archi of pwm is
| 17 | signal counter1 : unsigned(9 downto 0);
| 18 | signal tastgrad : integer := 48;
| 19 | signal tastgradnext : integer := 0;
| 20 | signal button : std_logic;
| 21 | begin
| 22 |
| 23 | tastgradnext <= tastgrad +10 when btn_0 else tastgrad-10;
| 24 | button <= (btn_0 xor btn_1);
| 25 | tastgrad <= tastgradnext when rising_edge(button);
| 26 |
| 27 | process begin
| 28 | wait until rising_edge(Clk_48kHz);
| 29 |
| 30 | counter1 <= counter1 + 1;
| 31 |
| 32 | pwm <= '1' when 0 <= counter1 and counter1 < tastgrad else '0';
| 33 |
| 34 | if counter1 = 10d"960" then
| 35 | counter1 <= 10d"0";
| 36 | end if;
| 37 |
| 38 |
| 39 | end process;
| 40 |
| 41 | end Archi;
|
tjah aber wo ist dann das Problem? Wenn keins dann kannst ja einfach
ruhig weitermachen mit zynq?
Das Problem ist dass die LEDs 0 und 2 nie leuchten und 1 und 3 nur
flackern. Und das unabhängig vom Wert den der ADC liefert.
Code: i2c_out.vhd
1 | library IEEE; use IEEE.STD_LOGIC_1164.ALL, IEEE.NUMERIC_STD.ALL;
| 2 | library UNISIM; use UNISIM.VComponents.all;
| 3 |
| 4 | entity i2c_out is
| 5 | Port (
| 6 | Clk : in std_logic;
| 7 | SDA : out std_logic;
| 8 | SCL : out std_logic;
| 9 | bitCounter : out unsigned(4 downto 0); -- 0 bis 18 0,1 = x 2,3 = CH, 4-18=Data
| 10 | CHcounter : out unsigned(1 downto 0) --
| 11 |
| 12 | );
| 13 | end i2c_out;
| 14 |
| 15 | architecture Behavioral of i2c_out is
| 16 | type ROM is array (0 to 26) of std_logic_vector(7 downto 0);
| 17 |
| 18 | -- i2c Rom:
| 19 | -- 8E = Start
| 20 | -- FF = Idle
| 21 | -- 06 = 0 oder Ack
| 22 | -- F6 = 1
| 23 | -- 17 = Stop
| 24 | signal UM_INIT : ROM := ( X"FF", X"FF", X"FF", X"FF", X"17", X"FF", X"FF", X"FF", X"8E", -- Initialisierung
| 25 | X"06", X"F6", X"06", X"F6", X"06", X"06", X"06", X"F6", X"F6", -- Adressierung rom_id = 10 - 18
| 26 | -- Adresse -R - Ack von ADC
| 27 | X"F6", X"F6", X"F6", X"F6", X"F6", X"F6", X"F6",X"F6", X"06", -- ch 1 rom_id = 18 - 26 bits: 0-8
| 28 | -- x x 0 1 rom_id = 20,21 CH_ID
| 29 | -- Daten von ADC ChI Bit 11-8 - Ack von Master rom_id = 22-26 D11-D9 bits: 9-17
| 30 | others => X"00");
| 31 |
| 32 | signal counterB : integer := 3;
| 33 | signal counterR : integer := 0;
| 34 |
| 35 | signal frameCounter : integer := 0; -- 0 bis 1
| 36 |
| 37 | begin
| 38 |
| 39 |
| 40 | process begin
| 41 | wait until rising_edge(Clk);
| 42 |
| 43 |
| 44 | if counterB = 3 then
| 45 | SCL <= UM_INIT(counterR)(counterB);
| 46 | SDA <= UM_INIT(counterR)(counterB+4);
| 47 | counterB <= 2;
| 48 |
| 49 | elsif counterB = 2 then
| 50 | SCL <= UM_INIT(counterR)(counterB);
| 51 | SDA <= UM_INIT(counterR)(counterB+4);
| 52 | counterB <= 1;
| 53 |
| 54 | elsif counterB = 1 then
| 55 | SCL <= UM_INIT(counterR)(counterB);
| 56 | SDA <= UM_INIT(counterR)(counterB+4);
| 57 | counterB <= 0;
| 58 |
| 59 | elsif counterB = 0 then
| 60 | SCL <= UM_INIT(counterR)(counterB);
| 61 | SDA <= UM_INIT(counterR)(counterB+4);
| 62 |
| 63 |
| 64 |
| 65 | if counterR /= 26 then -- wenn Counter kleiner 26 dann weiter
| 66 | counterB <= 3;
| 67 | counterR <= counterR + 1;
| 68 | else
| 69 | if bitCounter /= 5d"18" then
| 70 | bitCounter <= bitCounter + 1;
| 71 | counterB <= 3;
| 72 | counterR <= 18;
| 73 | if frameCounter = 0 then
| 74 | frameCounter <= 1;
| 75 | else
| 76 | frameCounter <= 0;
| 77 | if CHcounter /= 2d"3" then
| 78 | CHcounter <= CHcounter + 2d"1";
| 79 | else
| 80 | CHcounter <= 2d"0";
| 81 | end if;
| 82 | end if;
| 83 | else
| 84 | bitCounter <= 5d"0";
| 85 | end if;
| 86 | end if;
| 87 | end if;
| 88 | end process;
| 89 | end Behavioral;
|
Code: SDA_read.vhd
1 | library IEEE; use IEEE.STD_LOGIC_1164.ALL, IEEE.NUMERIC_STD.ALL;
| 2 |
| 3 | entity SDA_read is
| 4 | port (
| 5 | SDA : in std_logic;
| 6 | SCL : in std_logic;
| 7 | bitCounter : in unsigned(4 downto 0);
| 8 | data : out std_logic_vector(11 downto 0)
| 9 | );
| 10 | end SDA_read;
| 11 |
| 12 | architecture Archi of SDA_read is
| 13 |
| 14 | begin
| 15 |
| 16 | -- data_en <= '1' when (bitCounter > 3 and bitCounter < 8) or (bitCounter > 9 and bitCounter < 18);
| 17 |
| 18 |
| 19 | process begin
| 20 | wait until rising_edge(SCL);
| 21 | if bitCounter = 5d"4" then
| 22 | data(0) <= SDA;
| 23 | elsif bitCounter = 5d"5" then
| 24 | data(1) <= SDA;
| 25 | elsif bitCounter = 5d"6" then
| 26 | data(2) <= SDA;
| 27 | elsif bitCounter = 5d"7" then
| 28 | data(3) <= SDA;
| 29 | elsif bitCounter = 5d"10" then
| 30 | data(4) <= SDA;
| 31 | elsif bitCounter = 5d"11" then
| 32 | data(5) <= SDA;
| 33 | elsif bitCounter = 5d"12" then
| 34 | data(6) <= SDA;
| 35 | elsif bitCounter = 5d"13" then
| 36 | data(7) <= SDA;
| 37 | elsif bitCounter = 5d"14" then
| 38 | data(8) <= SDA;
| 39 | elsif bitCounter = 5d"15" then
| 40 | data(9) <= SDA;
| 41 | elsif bitCounter = 5d"16" then
| 42 | data(10) <= SDA;
| 43 | elsif bitCounter = 5d"17" then
| 44 | data(11) <= SDA;
| 45 | end if;
| 46 |
| 47 | end process;
| 48 | end Archi;
|
Code: CH_read.vhd
1 | library IEEE; use IEEE.STD_LOGIC_1164.ALL, IEEE.NUMERIC_STD.ALL;
| 2 |
| 3 | entity CH_read is
| 4 | -- später soll der Kanal übergeben werden
| 5 | -- generic (
| 6 | -- CH : unsigned(1 downto 0)
| 7 | -- );
| 8 | port (
| 9 | data : in std_logic_vector(11 downto 0);
| 10 | CHs : in unsigned(1 downto 0);
| 11 | SCL : in std_logic;
| 12 | dataout : out std_logic_vector(11 downto 0)
| 13 |
| 14 | );
| 15 | end CH_read;
| 16 |
| 17 | architecture Archi of CH_read is
| 18 |
| 19 | begin
| 20 |
| 21 | process begin
| 22 | wait until rising_edge(SCL);
| 23 | if CHs = 2d"0" then
| 24 | dataout <= data;
| 25 | end if;
| 26 | end process;
| 27 | end Archi;
|
Code: led_out.vhd
1 | library IEEE;
| 2 | use IEEE.STD_LOGIC_1164.ALL;
| 3 |
| 4 | entity led_out is
| 5 | Port (
| 6 | data : in std_logic_vector(11 downto 0);
| 7 | led : out std_logic_vector(3 downto 0)
| 8 | );
| 9 | end led_out;
| 10 |
| 11 | architecture Behavioral of led_out is
| 12 |
| 13 | begin
| 14 | led <= data(3 downto 0);
| 15 |
| 16 | end Behavioral;
|
tjah warum machst du dir leben soo kompliziert ??
1) PS7 I2C auf EMIO
2) I2C als external bus
3) C code schreiben, prüfen das all OK
und DANACH weiter.
0 lines of VHDL nix zu prüfen nichts was nicht gehen kann.
nur C code..
Und wie soll ich VHDL verstehen wenn ich alles in C schreibe?
Inzwischen geht alles so wie ich es mir vorstelle.
na für VHDL brauchst du ja aber kein ZYNQ :)
Am besten ist leider SIMULATION, da brauchst du überhaupt keine
hardware. Ist aber langweilig, ich weiss. Aber für lernen ist simulation
gut. muss nur gut verstehen was ist synthisierbar, was nicht.
Du wirst nicht darum herumkommen, Deinen Entwurf zu simulieren und die
Funktion der einzelnen Module zu verifizieren.
Ausserdem solltest Du Dich mit VHDL-Coding-Guidelines vertraut machen.
Z.B. verwendest Du ein Konstrukt namens "positional association" in
Deinen Port Mappings - eine wunderbare Möglichkeit sich ins eigene Bein
zu schiessen (bei "named association" hilft Dir der Parser, fehlerhafte
Mappings zu finden - bei positional tappst Du einfach im Dunkeln).
Dann fällt mir auf, dass Dein Code keine FSMs beschreibt.
[vhdl]wait until rising_edge(Clk_48kHz);[/vdhl]
mag synthetisierbar sein, aber bist Du sicher welche Schaltung die
Synthese tatsächlich daraus macht.
Und du wirst die Arbeitsweise des ADCs verifizieren müssen:
- liegt tatsächlich die vorgesehene SCL Frequenz an?
- Wird ACK richtig erkannt?
- Werden die Bits an die richtige Position im Datenvektor übertragen
usw.
- Welche Datenwerte erhälst Du für Vdd bzw. GND am ADC Eingang?
BTW: Du hast die LEDs mit den LSBs Deines Datenwortes verbunden,
abhängig von der Wandlungsgeschwindigkeit dürfte das für das Flackern
veranwortlich sein.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
|