Verilog'da Basit SPI modülü tasarımı

Başlatan Mucit23, 28 Şubat 2017, 11:19:45

Mucit23

Hocam aslında şöyle bir sorun var.

Normalde Reset sinyalinin dışarıdan ne zaman geleceği belli olmuyor. Sizin senkron örneğinizdeki gibi yaparsam şöyle bir sorun oluşuyor.

always @(posedge clk) begin
   if(reset)
      reg <= 0; //reset condition
   else
      reg <= whatever; //non-reset condition
end

Bu komutta if şartının sorgulanabilmesi için Clock sinyalinin periyodu kadar beklemek gerekiyor. Benim Reset sinyalim bir pulse olarak geliyor. pulse genişliği C kodumun işlenme hızı kadar.

Eğer aşağıdaki gibi yaparsamda bir hata alıyorum. Aslında olması gereken budur
always @(posedge clk or posedge reset) begin
    if(reset == 1'b1)
       reg <= 0; //reset condition
    else
       reg <= whatever; // non-reset condition
end

Aldığım hata aşağıdaki gibi.
"A single 'if' statement testing asynchronous conditions is expected"

Bu hatayı çözemedim malesef. Ama biraz daha uğraşsam olacak gibi. Dediğim gibi öğrenerek gidiyorum. Bu yüzden çok hata yapıyorum

muuzoo

Yazdığınız kodu gönderebilirseniz daha kolay fikir yürütebiliriz. Ben de verilog' dan fazla anlamam.Okumam var da yazmam pek yok verilog ile  :)  tecrübem daha çok VHDL üzerine ama temelde donanım tasarımı. O yüzden kod üzerinden gitsek daha iyi olur sanki.
gunluk.muuzoo.gen.tr - Kişisel karalamalarım...

Mucit23

#32
hocam şuanda kodum bu şekilde

module ParalelToSerial (
	output  Busy,
	output  Clkout,
	output  Dout,
	input   Clkin,
	input  [7:0] Din,
	input   Reset,
	input   Start
);

//`#start body` -- edit after this line, do not edit this line

    reg dout;
    reg clkout;
    reg reset;
    reg tx_en;
    reg [7:0]tx_buf;
    reg [3:0]cnt_spi;

    initial begin
      tx_buf[7] <= 1'b0;
      reset <= 1'b0;
      clkout <= 1'b0;
      tx_en <= 1'b0;
      cnt_spi <= 1'b0;
    end

    always @ (negedge Clkin)
    begin  
          if(Reset == 1'b1)  //Eğer Reset girişi set olursa reset flag'ini sıfırla
          begin
             reset <= 1'b0;
          end 

          if (Start == 1'b1 && reset == 1'b0)  //Eğer Reset Flağı sıfır ise ve Start girişi 1 olursa 1 byte gönder ve dur. 
          begin      
            reset <= 1'b1;
            tx_buf <= Din;
            tx_en <= 1'b1;
          end
       
          if(tx_en == 1'b1)// shift işlemi yap
          begin    
             tx_buf <= {tx_buf[6:0], 1'b0};
             cnt_spi <= cnt_spi + 1; 
          end
        
          if(cnt_spi==7)  //aktarım tamamlandı
          begin
             cnt_spi <= 1'b0;
             tx_en <= 1'b0;
          end
    end

    assign Busy = tx_en;
    assign Dout = tx_buf[7];
    assign Clkout = tx_en & Clkin;    
    
//`#end` -- edit above this line, do not edit this line
endmodule


Hocam nasıl çözeceğiz bu işi. Siz VHDL için anlatın ben verilog'da uygulamaya çalışırım.  :)  Reset girişi ve ve Start girişinin Clock girişinden bağımsız olarak hemen işleme alınması lazım. Diğer türlü Start ve Reset girişlerini always @ (negedge Clkin) bloğunun içerisinde if ile kontrol edersem önreğin reset veya start sinyali verdikten sonra Clock sinyalinin periyodu kadar sonra işleme alınabiliyor.

Dolayısıyla ben C kodunda Start=1 yaptıktan sonra biraz bekleme yapmam gerekiyor.

Hocam özellikle Start girişini senkron bir şekilde yapmam lazım. Bu hepsini çözüyor diyebilirim.



muuzoo

Hata vermesinin sebebi şu. if reset else yapısının else kısmını oluşturmamışsınız. Diğer bütün durumlar reset koşulunun sağlanmadığı durumlarda çalışmalı yani else ya da else if gibi bir yapı ile devam etmelisiniz. Sizin kodunuzda ise sadece if yapıları var. Koşulların sağlanmadığı durumlara dair bir durum yok. Genelde ben bu tarz haberleşme yapıları için FSM yapısı kurmayı tercih eder state tanımlar ve kodu ona göre tasarlarım. Örneğin IDLE, START, TRANSMIT v.b. durumlar oluşturup state aralrında gezinirim.
gunluk.muuzoo.gen.tr - Kişisel karalamalarım...

Mucit23

Hocam o bahsettiğinizi bir kod örneğinde görmüşüm. Switch case yapısına benzer bir yapı ile yapmıştı. Yarın birazda onunla uğraşayım. Bu mantık yanlış olabilir.

Ama anlamadığım nokta şu ki her if yapısına boş bir else yapısı tanımlasam yine aynı hatayı alıyorum.

muuzoo

Önemli olan reset cond. için yaptığınız tanımalama.
if reset
----- Reset durumunda yapılacaklar
else
---- Diğer tüm işlemler.
end
gunluk.muuzoo.gen.tr - Kişisel karalamalarım...

Mucit23

Hocam Tamam bunda sıkıntı yok. Peki Start girişini nasıl yapabilirim? Asıl problem o. Start girişi 1 olduğu anda işleme başlaması lazım. Şuanki haliyle bir sonraki Clock darbesini bekliyor.  Normalde Reset durumu dediğiniz gibi olabilir ama Start'ın sıfır olma durumu için Bir senaryom yok. Aslında biraz kafam karıştı ???

Mucit23

Hocam birde benim psoc üzerindeki verilog derleyicisi always @(*) bloğuna herzaman hata veriyor. Syntax error veriyor. Bu yapı sanırım Psoc üzerindeki verilog'da yok.


PSOC için hazırlamış verilog'a ait bir döküman buldum. Bu dökümandsa always bloğu anlatılmış.





Hocam Alt tarafta Sesivity list kısmında şunu söylemiş.


Alıntı Yap
The sensitivity list can contain only asynchronous triggers or only synchronous triggers, but not both. For example, the sensitivity list cannot contain always @ (x or posedge clock).
Yani anladığım kadarıyla always bloğuna senkron ve asenkron tetikleme kaynakları aynı anda kullanılamıyor.
İkisini beraber kullanmanın bir yolunu bulmam gerekiyor. Hocam benim şuanda tek sıkıntım Start girişini senkron bir şekilde algılamak.


Bu iş için nasıl bir yöntem önerirsiniz

Mucit23

Hocam birde şunu sorayım.

İki farklı always bloğunda aynı register üzerinde işlem yapmak istersek hata alıyoruz. Bu VHDL içindemi böyle? Yani bana saçma geliyor. Bir registere birden fazla always bloğunda işlem yapmak istersek nasıl bir yöntem izlenir. Bu işler nasıl yapılır öğrenmek istiyorum.

Hocam hakkınızı helal edin çok soru soruyorum ama dediğim gibi Verilog komple farklı bir dünya.

muuzoo

Alıntı YapHocam birde şunu sorayım.

İki farklı always bloğunda aynı register üzerinde işlem yapmak istersek hata alıyoruz. Bu VHDL içindemi böyle? Yani bana saçma geliyor. Bir registere birden fazla always bloğunda işlem yapmak istersek nasıl bir yöntem izlenir. Bu işler nasıl yapılır öğrenmek istiyorum.

Hocam hakkınızı helal edin çok soru soruyorum ama dediğim gibi Verilog komple farklı bir dünya.

Tabi ki VHDL'de de öyle. Bunu yazılım mantığı ile düşünmeyin, yazdığınız kodun karşılığında bir devre oluşturuluyor. Kaynak ve hedef mantığında düşünün. PSOC üzerinde muhtemelen bazı kısıtlamalar var. Şu pdf dosyasındaki örnek kod faydalı olacaktır sanıyorum. Hem reset kullanımı hem de enable kullanımı için bir örnek. 14. sayfada

http://www.cypress.com/file/42161/download
gunluk.muuzoo.gen.tr - Kişisel karalamalarım...

Mucit23

Devre mantığını anladım. Üzerinde bayağı düşünmem lazım. Örneği biraz inceleyeyim hocam.

superconductor

Hocam, always bloklarinin ayni durum ile tetiklendigini dusunun, ornegin clock sinyalinin yukselen kenari. Birinci always icinde register'a 0 yazdiniz, ikinci always icinde ayni register'a farkli bir deger yazdiniz. Bu islemler ayni anda gerceklenecek.. bu durumda register'a ne yazilacak?    Bu durumu şöyle özetleyebiliriz.. iki adet buffer var çıkışları birbirine bağli.. birinin girisine 1 digerine 0 verdik, bu durumda çıkış durumu belirsiz olacaktir.