VHDL ile ilk program denemem hakkinda?

Başlatan z, 06 Aralık 2018, 06:18:43

z

http://www.vhdl.club/2016/01/27/69/ sitesindeki ornegin uzerinde oynayarak asagidaki kodu hazirladim.

Hatalarimi ve daha iyi yazilmis halini konusabilirmiyiz?

Amac: 10 bitlik pwm portumuz var. Bu porta datayi yerlestirip Load girisini 1 yaparsak porttaki data pwm uretmek uzere fpga icine aliniyor.

Rst ile pwm donanimi resetlenebiliyor.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
 
entity pwm is
  
    Port( 
        in_clk   : in std_logic;      ; Pwm Clock                         
        in_rst   : in std_logic;      ; Pwm Reset                         
        in_ld    : in std_logic;      ; Pwm Data Load                         
        in_d0    : in std_logic       ; Pwm Data0
        in_d1    : in std_logic       ; Pwm Data1
        in_d2    : in std_logic       ; Pwm Data2
        in_d3    : in std_logic       ; Pwm Data3
        in_d4    : in std_logic       ; Pwm Data4
        in_d5    : in std_logic       ; Pwm Data5
        in_d6    : in std_logic       ; Pwm Data6
        in_d7    : in std_logic       ; Pwm Data7
        in_d8    : in std_logic       ; Pwm Data8
        in_d9    : in std_logic       ; Pwm Data9
        out_data : out std_logic      ; Pwm Output 
     );

end pwm;
 
architecture Tanimlamar of pwm is
 
    signal pwm_shadow_reg : integer range 0 to 1023 ;
    signal pwm_reg        : integer range 0 to 1023 ;
    signal pwm_cnt        : integer range 0 to 1023
    signal pwm_clk        : std_logic;      
 
begin
 
    pwm_clk <= in_clk                         

;   PWM Data Portunu PWM Registerine okuma islemi

    process(pwm_clk, in_ld)
    begin
        if rising_edge(pwm_clk) then
           if in_ld = '1' then
              pwm_reg <= 512*in_d9 + 256*in_d8 + 128*in_d7 + 64*in_d6 +32*in_d5 + 16*in_d4 + 8*in_d3 + 4*in_d2 + 2*in_d1  + in_d0;
           endif
        endif
    end process;
 
;   Resetleme ve sayma islemi

    process(pwm_clk, in_rst)
    begin
        if in_rst = '1' then
           pwm_cnt <= 0;
           pwm_reg <= 0;
           pwm_shadow_reg <= 0;
        elsif rising_edge(pwm_clk) then
           if pwm_cnt = 1023 then
              pwm_cnt <= 0;
              pwm_shadow_reg  <= pwm_reg;
           else
              pwm_cnt <= pwm_cnt + 1;
           end if;            
        end if;
    end process;

;   PWM sinyali uretme islemi

    process(pwm_clk)
    begin
        if rising_edge(pwm_clk) then
             if pwm_cnt < pwm_shadow_reg then
                out_data <= '1';
             else
                out_data <= '0';
             end if;
        end if;
    end procesS;
 
end Tanimlamar;


Power on asamasinda tum registerlerin otomatik sifiranmasi nasil olur?

Asagidaki satir yerine (dogrumu yazdim bilmiyorum) daha guzel bir kod nasil yazilir?

pwm_reg <= 512*in_d9 + 256*in_d8 + 128*in_d7 + 64*in_d6 +32*in_d5 + 16*in_d4 + 8*in_d3 + 4*in_d2 + 2*in_d1  + in_d0;


Giris ve cikis pinerinin hangi pinler olacagini kod icinde tanimlayabilirmiyim?
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

MC_Skywalker

#1
Tanımladığını Registere ilk değer olarak 0 atayarak yapabilirsiniz.

singnal Bir_register    : std_logic_vector(0 to 3) := "0000"

Pin tanımlamalarını ayrıca bir Constrains dosyasında yapıyorsunuz. proje içine oluşturuyorsunuz ki bu hem hangi pin olduğunu ve hangi loji seviye ile çalıştığını tanımlıyor (LVCMOS33 vb.)
set_property IOSTANDARD LVCMOS33 [get_ports Qdeğil]
set_property PACKAGE_PIN E19 [get_ports Qdeğil]

z

signal pwm_shadow_reg : integer range 0 to 1023 : '000000000'

Peki yukaridaki yazim ile asagidaki yazim ayni anlama mi geliyor?

signal pwm_shadow_reg : std_logic_vector(0 to 9) : '000000000'
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

MC_Skywalker

Birnde integer bir tanımlama yapıp ilk değeri 0 veryorsunuz, diğerinde ise bit türünden tanımlama yapıp ilk değeri 0 versiyorsunuz. 

yaplan işe aynı anlamda.

z

#4
Peki yukaridaki programda hata yok diyelim.

Simdi FPGA icine ayni pwm blogundan 8 tane yerlestirmek isteyeyim. FPGA in 10 bitlik pwm deger yukleme girisi 8 kanal icin de ortak kullaniliyor olsun. 8 Pwm regden hangisine yukleme yapacagim 3 girisli adres hatti uzerinden girilen deger ile belirlenecek olsun.

Verdigim kodu 8 kanal icin tek tek yazmak yerine bu programi fonksiyon olarak yazip 8 kanali bu fonskiyonla iliskilendirebilirmiyiz?

Mumkunse program olarak burda verebilirmisiniz?
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

z

#5
Gelistirme ortamini kurdum ve calisti.

Yukaridaki programda pek cok hata verdi. Aciklamalarin onune -- isareti koymak gerekiyor.

se IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

 
entity pwm is
  
    Port( 
          in_clk   : in std_logic ; -- Clock                        
          in_rst   : in std_logic ; -- Reset                         
          in_ld    : in std_logic ; -- Load                         
          in_data  : in std_logic_vector(9 downto 0); 
          out_data : out std_logic  
    );
end pwm;
 
architecture Tanimlamalar of pwm is
 
    signal pwm_shadow_reg : std_logic_vector(9 downto 0);
    signal pwm_reg        : std_logic_vector(9 downto 0);
    signal pwm_cnt        : std_logic_vector(9 downto 0);
    signal pwm_clk        : std_logic;
 
begin
 
    pwm_clk <= in_clk ;                        

--  PWM Data Portunu PWM Registerine okuma islemi

    process(pwm_clk, in_ld)
    begin
        if rising_edge(pwm_clk) then
           if in_ld = '1' then
           pwm_reg <= in_data;
           end if;
        end if;
    end process;
 
--   Resetleme ve sayma islemi

    process(pwm_clk, in_rst)
    begin
        if in_rst = '1' then
           pwm_cnt <= (others=>'0');
           pwm_reg <= (others=>'0');
           pwm_shadow_reg <= (others=>'0');
        elsif rising_edge(pwm_clk) then
           if pwm_cnt = 1023 then
              pwm_cnt <= (others=>'0');
              pwm_shadow_reg  <= pwm_reg;
           else
              pwm_cnt <= pwm_cnt + 1;
           end if;            
        end if;
    end process;

--  PWM sinyali uretme islemi

    process(pwm_clk)
    begin
        if rising_edge(pwm_clk) then
             if pwm_cnt < pwm_shadow_reg then
                out_data <= '1';
             else
                out_data <= '0';
             end if;
        end if;
    end process;
 
end Tanimlamalar;

Bu programdaki ERROR:HDLCompiler:1401 - "/home/ise/MyProject/PWM.vhd" Line 35: Signal pwm_reg[9] in unit pwm is connected to following multiple drivers:

Hatasini yok edemiyorum.

pwm_reg tanimladim ve bunun bir register olmasini dusundum. Fakat yaptigim tanim dogrumu emin degilim.
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

devrecii

Error gayet güzel açıklamış;

pwm_reg[9] e farklı yerlerde atama yapmışsınız,  bilgisayar programı gibi sırayla değil hepsi aynı anda olduğu için farklı yerlerde atama yapılamaz  kısa devre olur  ;D  tek procss içinde atama yapabilirsiniz.


muuzoo

Alıntı yapılan: z - 06 Aralık 2018, 11:31:34Gelistirme ortamini kurdum ve calisti.

Yukaridaki programda pek cok hata verdi. Aciklamalarin onune -- isareti koymak gerekiyor.

se IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

 
entity pwm is
  
    Port( 
          in_clk   : in std_logic ; -- Clock                        
          in_rst   : in std_logic ; -- Reset                         
          in_ld    : in std_logic ; -- Load                         
          in_data  : in std_logic_vector(9 downto 0); 
          out_data : out std_logic  
    );
end pwm;
 
architecture Tanimlamalar of pwm is
 
    signal pwm_shadow_reg : std_logic_vector(9 downto 0);
    signal pwm_reg        : std_logic_vector(9 downto 0);
    signal pwm_cnt        : std_logic_vector(9 downto 0);
    signal pwm_clk        : std_logic;
 
begin
 
    pwm_clk <= in_clk ;                        

--  PWM Data Portunu PWM Registerine okuma islemi

    process(pwm_clk, in_ld)
    begin
        if rising_edge(pwm_clk) then
           if in_ld = '1' then
           pwm_reg <= in_data;
           end if;
        end if;
    end process;
 
--   Resetleme ve sayma islemi

    process(pwm_clk, in_rst)
    begin
        if in_rst = '1' then
           pwm_cnt <= (others=>'0');
           pwm_reg <= (others=>'0');
           pwm_shadow_reg <= (others=>'0');
        elsif rising_edge(pwm_clk) then
           if pwm_cnt = 1023 then
              pwm_cnt <= (others=>'0');
              pwm_shadow_reg  <= pwm_reg;
           else
              pwm_cnt <= pwm_cnt + 1;
           end if;            
        end if;
    end process;

--  PWM sinyali uretme islemi

    process(pwm_clk)
    begin
        if rising_edge(pwm_clk) then
             if pwm_cnt < pwm_shadow_reg then
                out_data <= '1';
             else
                out_data <= '0';
             end if;
        end if;
    end process;
 
end Tanimlamalar;

Bu programdaki ERROR:HDLCompiler:1401 - "/home/ise/MyProject/PWM.vhd" Line 35: Signal pwm_reg[9] in unit pwm is connected to following multiple drivers:

Hatasini yok edemiyorum.

pwm_reg tanimladim ve bunun bir register olmasini dusundum. Fakat yaptigim tanim dogrumu emin degilim.

Hocam problemin nedeni aynı sinyale iki farklı noktadan değer ataması yapmanız. Kaba bir benzetme yaparsam "signal" yapıları bir yazılım dilindeki global değişkenlere benzetilebilir. Fakat bir farkla bir sinyale sadece tek bir yerden değer atanabilir. Fakat istenilen yerden o değere erişilebilir.

Sizin örneğinizde pem_reg sinyaline ilk process de atama yapmışsınız in_data ile. Fakat ikinci process'in reset kısmında değerini sıfırlamaya çalışmışsınız. pwm_reg içeriğini sıfırlamak için değer atadığınız process içerisindeki rst kısmında yapın bu işlemi.
gunluk.muuzoo.gen.tr - Kişisel karalamalarım...

z

#8
10 bitlik pwm_reg registerine sadece cipin 10 pininden gelen datayi yukluyorum. Baska bir atama yokki.

Bu satir da asagida.

pwm_reg <= in_data;

Reset ile sifirlamaya calistigim yerde bu registeri olusturan Flip floplarin reset pinine sinyal yollanmiyor mu?

Ama evet orada registere 0  yukledim.  Dogru.

Peki bahsettigim sekilde resetleme islemi nasil yapilir?

Yada program nasil isler hale getirilir?
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

muuzoo

Alıntı yapılan: z - 06 Aralık 2018, 13:26:3110 bitlik pwm_reg registerine sadece cipin 10 pininden gelen datayi yukluyorum. Baska bir atama yokki.

Bu satir da asagida.

pwm_reg <= in_data;

Hocam aşağıdaki kodun rst kımına bakarsanız orada değeri sıfırlamışsınız, pwm_reg <= (others => '0')

--   Resetleme ve sayma islemi

    process(pwm_clk, in_rst)
    begin
        if in_rst = '1' then
           pwm_cnt <= (others=>'0');
           pwm_reg <= (others=>'0');
           pwm_shadow_reg <= (others=>'0');
        elsif rising_edge(pwm_clk) then
           if pwm_cnt = 1023 then
              pwm_cnt <= (others=>'0');
              pwm_shadow_reg  <= pwm_reg;
           else
              pwm_cnt <= pwm_cnt + 1;
           end if;            
        end if;
    end process;
gunluk.muuzoo.gen.tr - Kişisel karalamalarım...

z

Evet evet anladim.

Peki bir registeri sifirlamanin iki yolu var.

- Deger yukleyerek
- Reset pinini sinyal uygulayarak.

2. secenekle Resetleme yapamazmiyim? Nasil yaparim?
Bana e^st de diyebilirsiniz.   www.cncdesigner.com

muuzoo

@z hocam ilk process kısmına da bir rst işlemi ekleyip o regin içeriğinin sıfırlanmasını sağlayabilirsiniz. Örneğin:

    process(pwm_clk, in_rst, in_ld)
    begin
        if in_rst = '1' then
          pwm_reg <= (others=>'0');
        elsif rising_edge(pwm_clk) then
          if in_ld = '1' then
              pwm_reg <= in_data;
          end if;
        end if;
    end process;
gunluk.muuzoo.gen.tr - Kişisel karalamalarım...

muuzoo

Alıntı yapılan: z - 06 Aralık 2018, 13:35:45Evet evet anladim.

Peki bir registeri sifirlamanin iki yolu var.

- Deger yukleyerek
- Reset pinini sinyal uygulayarak.

2. secenekle Resetleme yapamazmiyim? Nasil yaparim?

Aslında hocam hepsi aynı kapıya çıkıyor. Kodun rst kısmı sizin istediğiniz başlangıç değerlerini oluşturuyor. Bu durumda yaptığınz şey aslında o sinyale değer yüklemek. Reset konumunda ilgili sinyale istediğiniz değeri (türüne uygun olarak) atayabilirsiniz. Her zaman 1 ya da 0 olmak zorunda değil. Örneğin başlangıç konumunda (resetlendiğinde) değeri 512 olsun derseniz onu atarsınız. Her resetlendiğinde register içeriği 512 değerini alır.
gunluk.muuzoo.gen.tr - Kişisel karalamalarım...

z

Demek istedigim

10 bitlik pwm_reg registeri 10 adet FF dan olusuyor.

Bu FF'larin D girisine Clk esliginde 0 yuklersem registere sifir yazmis olurum.


Fakat bu FFlarin R girisine sinyal verirsem de registerime sifir yuklemis olurum.

pwm_reg.R=1 gibi bir numara cekemiyormuyuz?


Sematik cizimde bu resetleme sinyali ile registeri sifirlama isini kolayca asabilirdik.
Herhalde VHDL de de benzer bir cozum vardir.

Neyse onerdiginiz degisikligi yapip devam edeyim.



Bana e^st de diyebilirsiniz.   www.cncdesigner.com

muuzoo

#14
Alıntı yapılan: z - 06 Aralık 2018, 13:46:01Demek istedigim

10 bitlik pwm_reg registeri 10 adet FF dan olusuyor.

Bu FF'larin D girisine Clk esliginde 0 yuklersem registere sifir yazmis olurum.


Fakat bu FFlarin R girisine sinyal verirsem de registerime sifir yuklemis olurum.

pwm_reg.R=1 gibi bir numara cekemiyormuyuz?


Sematik cizimde bu resetleme sinyali ile registeri sifirlama isini kolayca asabilirdik.
Herhalde VHDL de de benzer bir cozum vardir.

Neyse onerdiginiz degisikligi yapip devam edeyim.


Hocam zaten önerdiğim yöntem dediğiniz şey ile aynı. Size örnek verdiğim kod parçası asenkron reset olarak geçer. Yani clock girişnden bağımsız olarak etki eder. O yüzden pwm_reg <= (others => '0') yaptığımda (kodun rst kımında yapıyorum bu atamayı) rst girişlerine uygulamış oluyorum. Eğer değerlerini 1 olarak ayarlarsam da set girişlerine bağlanmış oluyor. D girişlerine değer atamıyorum doğrudan rst ya da set kısmına erişmiş oluyorum.

gunluk.muuzoo.gen.tr - Kişisel karalamalarım...