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

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

Mucit23

Selamlar,

PSOC üzerinde Verilog Öğrenmeye çalışıyorum. Şuanda temel işlemleri öğrendim sayılır ama karmaşık işlemlerde hala mantık yürütemiyorum.

İleride lazım olacağı için SPI mantığını verilog da yapmaya çalışıyorum. Tek kanal basitçe 8 bitlik veriyi seri olarak dışarı çıkartan bir spi bloğu yazmaya çalışıyorum.

Bunun için bir verilog dosyası oluşturdum. Girişleri çıkışları tanımladım. Veri girişi için psoc'a özel komutlarla bir adres tanımladım. Bundan sonra tıkandım kaldım.

`include "cypress.v"
//`#end` -- edit above this line, do not edit this line
// Generated on 02/28/2017 at 10:07
// Component: ParalelToSerial
module ParalelToSerial (
	output  CLKOUT,
	output  DOUT,
	input   CLKIN
);

//`#start body` -- edit after this line, do not edit this line
    reg clk_count,count_start;
    wire dout=0;
    wire clkout=0;
    
    
    wire [7:0] control_reg_out;
    assign DOUT = dout;
    assign CLKOUT = clkout;

    cy_psoc3_control #(.cy_init_value (8'b00000000), .cy_force_order(`TRUE)) //Default mode
    myControlReg(.control(control_reg_out));
    
    always @ (posedge CLKIN)
    begin
    
    end
    
//`#end` -- edit above this line, do not edit this line
endmodule


Buradaki kodlar içerisinde aşağıdaki kodlarla bir kontrol registeri tanımlıyorum. Bu register ile C tarafından Verilog tarafına veri aktarabiliyorum. Bir adres gibi düşünün. C tarafında bu adrese bir veri yazınca Veri doğrudan Verilog tarafında kullanılabiliyor. Yani control_reg_out değişkenim benim dışarıya seri olarak aktarılacak olan verim.

Bundan sonra clock sinyalinin her bir yükselen kenarında veriyi sıra ile dışarı aktarım çıkışta clock sinyali üretmem lazım. Burada takıldım.
Örnek SPI kodlarını inceliyorum ama bir sürü kontrol var. Anlaşılır bir kod bulamadım.

Bu konuda yardımcı olabilecek olan varmı? Bundan sonra nasıl yapmam gerekiyor? Veriyi nasıl seri olarak göndereceğim? Aynı zamanda clock sinyali nasıl üreteceğim?

Verilog veya VHDL bilen kimler var?

furkanyx


Mucit23

@furkanyx Hocam o kodu inceledim. Çok karmaşık işin içinden çıkamadım.

Ben anlamak için kodu kendim yazayım diyorum. Son derece basit 8 bitlik veriyi clk ile birlikte seri olarak dışarı çıkaran bir verilog programı yazmaya çalışıyorum. Şuanda onunla ilgili çalışıyorum.

Ben bir kod yazdım. status ve control_reg_out adında iki adet değişkenim var. control_reg_out benim gönderilecek verimi saklıyor. Eğer status değişkeninin 0. biti 1 olursa control_reg_out değişkenini Seri olarak dışarı verip status değişkeninin 0. bitini '0' yaptıktan sonra dursun istiyorum. Bunu yapabilirsem geriye kalan teferruatlarıda yapabilirim.

Yazdığım kod aşağıdaki gibi.

`include "cypress.v"
//`#end` -- edit above this line, do not edit this line
// Generated on 02/28/2017 at 10:07
// Component: ParalelToSerial
module ParalelToSerial (
	output  CLKOUT,
	output  DOUT,
	input   CLKIN
);

//`#start body` -- edit after this line, do not edit this line
    reg clk_count;
    reg dout;
    reg clkout;    
    reg [7:0] status;
    reg [7:0] control_reg_out;
    
    assign DOUT = dout;
    assign CLKOUT = clkout;
    
    cy_psoc3_control #(.cy_init_value (8'b00000000), .cy_force_order(`TRUE)) //Default mode
    MyTxReg(.control(control_reg_out));
    cy_psoc3_control #(.cy_init_value (8'b00000000), .cy_force_order(`TRUE)) //Default mode
    MyStatus(.control(status)); 
        
    always @ (posedge CLKIN)
    begin

       if(status==1'b1)
       begin
         clkout = 0;
         dout=control_reg_out[clk_count];
         clkout = 1;
         
         clk_count = clk_count + 1;
         
         if(clk_count == 8)
         begin
           status = 0;
         end
       end
       else
       begin
          clk_count=0;
          dout=0;
          clkout=0;
       end

    end

//`#end` -- edit above this line, do not edit this line
endmodule


Tabi yukarıdaki kodu çalıştıramadım. Muhtemelen mantık hatası yapıyorum.

Ama basit işlemler yapabiliyorum. Örneğin  status değişkeninin 0. bitine göre dout'a bağlı bir ledi yakıp söndürebiliyorum.

Bu konuda biraz yardımcı olabilirseniz gerisini getirebilirim.

Mucit23

Mesela basitçe bir soru sorayım aklıma gelmişken

Atama işlemlerinde neden eşit ('=') kullanmak yerine küçük eşit ('<=') kullanılıyor?

status <=1'b0 gibi


muhittin_kaplan

Syntax i anlamaya calisma mucit, kabul et.
(Sola ok gibi duruyor)

M_B

Alıntı yapılan: Mucit23 - 28 Şubat 2017, 14:59:41
Mesela basitçe bir soru sorayım aklıma gelmişken

Atama işlemlerinde neden eşit ('=') kullanmak yerine küçük eşit ('<=') kullanılıyor?

status <=1'b0 gibi

Hocam konuyu bilmiyorum ama yazdığınız kodta status 1 den kucuk veya eşit demiyormu ?
İmkanın sınırlarını görmek için imkansızı denemek lazım.                                                             Fatih Sultan Mehmet

Mucit23

Hocam yok incelediğim örneklerde atama işlemleri için kullanılmış.

superconductor

"<=", non-blocking atama yapar. Üst üste yazdığınız non-blocking atamalar aynı anda diğer bir deyişle paralel işlem görürler.
"=", blocking atama yapar. Sıralı işlem görürler.

Şu site oldukça yararlı: http://www.asic-world.com/tidbits/blocking.html

furkanyx

Kucukesit ifadesi always blogunun icinde olmasindan kaynakli. Behavioral tasarimlarda atamalar register da tutulmalidir. Non blocking in mantigi bu sekildedir. Registerlarda tutma sebebi de paralel islem yapabilmesindendir. Spi in temel mantigi da clk ile beraber data registerindaki datayi clock polaritesiyle beraber cikisa tek bit aktarmak. Attigim kodda once spi modulune verilen clock bolunerek spi clock u oluşturuyor. Ayni zamana dusen kenar veya yukselen kenari tespit edip flag degerini değiştiriyor. Daha snra data yollamak icin eger ki spiclk ve kenarflag 1 ise shift registerin son bitini cikis registerna yaz yapiyor ve bu islem 8 kere (veya 16 kere tasarima gore degisir) gerçekleştiğinde aktarim tamamlandi flag i aktif edilir. Pek sagliklik bir anlatim olmamis olabilir.  Mobilden anca bu kadar :)

Mucit23

Yarın yine birkaç deneme yapacağım. Teşekkürler. Küçük eşit mantığını anladım

Mucit23

#10
Selamlar


Verilogdaki şu mantığı çözemedim gitti. Mantığı bi anlasam resmen yürüyecem böyle. Yardıma ihtiyacım var.
Basitçe bir SPI modülü tasarlamaya çalışıyorum. Bir adet status değişkeni birde MyTxReg adında değişkenlerim var
Amacım kısaca şudur. status değişkenim 0x01 olursa MyTxReg içerisindeki 8 bit veriyi spi protoklüne göre dışarı çıkarmak istiyorum.
Bunun için aşağıdaki kodları yazdım.

`include "cypress.v"
//`#end` -- edit above this line, do not edit this line
// Generated on 02/28/2017 at 10:07
// Component: ParalelToSerial
module ParalelToSerial (
	output  CLKOUT,
	output  DOUT,
	input   CLKIN
);


//`#start body` -- edit after this line, do not edit this line
    reg clk_count;
    reg dout;
    reg clkout;    
    reg [7:0] status;
    reg [7:0] control_reg_out;
    
    cy_psoc3_control #(.cy_init_value (8'b00000000), .cy_force_order(`TRUE)) //Default mode
    MyTxReg(.control(control_reg_out));
    cy_psoc3_control #(.cy_init_value (8'b00000000), .cy_force_order(`TRUE)) //Default mode
    MyStatus(.control(status)); 
        
    always @ (posedge CLKIN)
    begin


       if(status==1'b1)
       begin
         clkout = 0;
         dout=control_reg_out[clk_count];
         clkout = 1;
         
         clk_count = clk_count + 1;
         
         if(clk_count == 8)
         begin
           status = 0;
         end
       end
       else
       begin
          clk_count=0;
          dout=0;
          clkout=0;
       end
    end
       
    assign DOUT = dout;
    assign CLKOUT = clkout;
//`#end` -- edit above this line, do not edit this line
endmodule


Fakat çok problem var. Çalışmıyor. Mantık hatasımı yapıyorum anlayamıyorum. Bu kodu gerçekte denediğimde CLKOUT pininden hiçbirşey çıkmazken DOUT pininden MyTxReg içerisindeki bilgiden bağımsız olarak kare dalga çıkıyor. Kare dalganın frekansı ise Modüle uyguladığım giriş frekansının yarısı, Girişte 1Khz uyguluyorum DOUT'dan 500Hz kare dalga çıkıyor.


Ne alaka anlamıyorum.
Sorun nedir bilgisi olan varmı neyi yanlış yapıyorum? Dediğim gibi bi mantığı anlasam hepsini halledeceğim.

superconductor

Clk_count tek bit tanimli en az 4 bit tanimlaman gerekmez mi ?

Mucit23

Hocam aklım C'ye gidiyor işte. Evet onu düzelttim.
Şuanda  dout=control_reg_out[clk_count]; satırı çalışıyor. control_reg_out içeriğindeki 8 bitlik bilgi seri olarak dışarı veriliyor.

Fakat clock üretemiyorum. Clock nasıl üretirim?

superconductor

Clockout' u direk clkin'e assign etsen?

Mucit23

hocam selamlar
Olabilir belki ama Transfer tamamlandığımda sistemin  durması gerekiyor. Bu işi yapamadım. Onu nasıl yaparım.
Dediğim gibi Verilog ile ilk defa uğraşıyorum bu yüzden bilgim zayıf.