FPGA seri iletişimine dayalı yüksek kaliteli blog yayınlarının ayrıntılı analizi

Bir omuz kazanın sırt çantası

Bu ne kadar zor?

Bir şans ver!

_

Uzun basın tanıma

[Konu]: FPGA tabanlı seri iletişimin ayrıntılı analizi

[Yazar]: LinCoding

[Zaman]: 2016.11.28

Seri iletişim çok yaygın olarak kullanılmaktadır ve ilke çok basittir. Seri iletişimdeki en önemli şey, baud hızı kavramıdır. Anlamıyorsanız, Baidu ve ardından veri formatı, 1 başlangıç biti, 8 bit Veri biti, 1 eşlik biti (isteğe bağlı), 1 durdurma biti.

Önce sonuçlara bakın (PC veriyi FPGA'ya gönderir ve FPGA veriyi aldıktan sonra PC'ye sağlam bir şekilde gönderir):

(Kaynak kodu CrazyBingo'dan gelir, telif hakkına saygı duyun)

Doğrudan aşağıdaki programa bakın.

1, dize Bağlantı noktası alma modülü

modül uart_receiver (inputclk, // global saat inputrst_n, // global sıfırlama inputclk_16bps, inputrxd, outputreg rxd_data, outputregrxd_flag);

İlk bölüm girdi ve çıktının tanımıdır, dikkat edilmesi gereken iki nokta vardır:

1. Seri port alıcı modülü için, prensip olarak, örnekleme için 16 kat baud hızı kullanılır, bu nedenle clk_16bps girişi yapılır ve bu giriş sinyali, "FPGA'ya Dayalı Keyfi Frekans Bölmesinin Ayrıntılı Analizi" makalesinde divide_clken çıkışından gelir.

2. Bir sistem için, birçok modülden oluşur.Modül birbiriyle iletişim kurmalıdır.Giriş modülü için "giriş tamamlandı bayrak sinyali" vazgeçilmezdir ve bayrak sinyali Çıktı, bu örnekte rxd_flag, önceki anahtar geri alma makalesindeki key_flag ve SPI makalesindeki rxd_flag gibi girdi verileriyle senkronize edilir.Bu nedenle, bu da sabit bir mod haline gelmelidir!

// ----------------------------------- // giriş sinyalini senkronize et regrxd_sync; her zaman @ (posedge clk veya negedge rst_n) start if (! rst_n) rxd_sync < = 1'b1; aksi takdirde rxd_sync < = rxd; son

İkinci kısım, alıcı modül olduğu için, alınan sinyal diğer saat alanlarından gelir, bu nedenle sinyali kendi saat alanınızla senkronize etmek için bir vuruş yapmanız gerekir.Tabii ki iki vuruş da mümkündür!

// ----------------------------------- // FSM'yi al: localparamR_IDLE = 4'd0; localparamR_START kodlayın = 4'd1; localparamR_SAMPLE = 4'd2; localparamR_STOP = 4'd3; // ------------------------------- ---- // FSM localparam alSMP_TOP = 4'd15; localparamSMP_CENTER = 4'd7; regsmp_cnt; regrxd_cnt; regrxd_state; her zaman @ (posedge clk veya negedge rst_n) başlar if (! rst_n) smp_cnt başlar < = 4'd0; rxd_cnt < = 4'd0; rxd_state < = R_IDLE; başka durumu sonlandır (rxd_state) R_IDLE: smp_cnt'ye başlar < = 4'd0; rxd_cnt < = 4'd0; eğer (! Rxd_sync) rxd_state < = R_START; başka rxd_state < = R_IDLE; son R_START: eğer (clk_16bps) smp_cnt ile başlarsa < = smp_cnt + 1'b1; eğer (smp_cnt == SMP_CENTER rxd_sync) rxd_cnt başlar < = 4'd0; rxd_state < = R_IDLE; aksi takdirde bitir (smp_cnt == SMP_TOP) rxd_cnt başlar < = 4'd1; rxd_state < = R_SAMPLE; aksi takdirde end rxd_cnt başlar < = rxd_cnt; rxd_state < = rxd_state; end end else start smp_cnt < = smp_cnt; rxd_cnt < = rxd_cnt; rxd_state < = rxd_state; end R_SAMPLE: eğer (clk_16bps) smp_cnt ile başlarsa < = smp_cnt + 1'b1; eğer (smp_cnt == SMP_TOP) başlarsa (rxd_cnt < 4'd8) rxd_cnt'ye başlar < = rxd_cnt + 1'b1; rxd_state < = R_SAMPLE; aksi takdirde end rxd_cnt başlar < = 4'd9; rxd_state < = R_STOP; end end, else başla rxd_cnt < = rxd_cnt; rxd_state < = rxd_state; end end else start smp_cnt < = smp_cnt; rxd_cnt < = rxd_cnt; rxd_state < = rxd_state; end R_STOP: eğer (clk_16bps) smp_cnt ile başlarsa < = smp_cnt + 1'b1; eğer (smp_cnt == SMP_TOP) rxd_cnt başlar < = 4'd0; rxd_state < = R_IDLE; başka son rxd_cnt başlar < = rxd_cnt; rxd_state < = rxd_state; end end else start smp_cnt < = smp_cnt; rxd_cnt < = rxd_cnt; rxd_state < = rxd_state; varsayılan son: smp_cnt'ye başlayın < = 4'd0; rxd_cnt < = 4'd0; rxd_state < = R_IDLE; son harf sonu

Üçüncü kısım, gerçekten çok uzun olan uzun durum makinesidir, ancak temelde tekrar eden içeriktir. Dikkat edilmesi gereken birkaç nokta vardır:

1. Seri port alıcı modülü için, alınan verinin kararlılığını en üst düzeye çıkarmak için, örneklemek için 16 kat baud hızı kullanıyoruz, yani her veri bitinde 16 örnekleme noktası var.Bu durumda, elbette en çok Ortadaki örnekleme noktasındaki veriler prensipte en kararlı olanıdır ve gerçekten de böyledir. Bu nedenle, mevcut örnekleme noktasını saymak için bir smp_cnt sinyaline ihtiyaç vardır ve 16 nokta örneklendiğinde, bir sonraki veri bitini örneklemek için rxd_cnt 1 artırılır.

2. Halihazırda örneklenen verinin sayısını saymak için rxd_cnt sinyalini kullanın. Bu her zaman bloğun sadece rxd_cnt değişikliğini içerdiği ve bir diğerinde her zaman, her bit üzerindeki verilerin rxd_cnt durumuna göre değerleneceği unutulmamalıdır.

3. Seri bağlantı noktası aktarımının özelliklerinden dolayı, başlangıç biti, iletimin başlangıcı olarak düşük seviyeye değişir, bu da başlangıç bitinin aslında iletimin başlangıcı için bir etkinleştirme sinyali olduğu anlamına gelir, bu nedenle durum makinesinin BOŞTA durumu her zaman izlemek için Başlangıç bitinin değişip değişmediği.

regrxd_data_r; her zaman @ (posedge clk veya negedge rst_n) başlarsa (! rst_n) rxd_data_r < = 8'd0; else if (rxd_state == R_SAMPLE clk_16bps smp_cnt == SMP_CENTER) case (rxd_cnt) 4'd1: rxd_data_r başla < = rxd_sync; 4'd2'yi bitir: rxd_data_r'yi başlat < = rxd_sync; son 4'd3: rxd_data_r başla < = rxd_sync; son 4'd4: rxd_data_r başla < = rxd_sync; son 4'd5: rxd_data_r başla < = rxd_sync; son 4'd6: rxd_data_r başla < = rxd_sync; son 4'd7: rxd_data_r başla < = rxd_sync; son 4'd8: rxd_data_r başla < = rxd_sync; varsayılan son: rxd_data_r ile başlayın < = 8'd0; endcase else if (rxd_state == R_STOP) rxd_data_r < = rxd_data_r; başka rxd_data_r < = rxd_data_r; end

Dördüncü bölüm, farklı bitlerdeki verileri elde etmek için rxd_cnt değerine göre değeri elde etmektir.

always @ (posedge clk veya negedge rst_n) başlasa (! rst_n) rxd_data başlasın < = 8'd0; rxd_flag < = 1'b0; eğer (rxd_state == R_STOP clk_16bps smp_cnt == SMP_TOP) başlarsa rxd_data < = rxd_data_r; rxd_flag < = 1'b1; aksi takdirde end rxd_data başlar < = rxd_data; rxd_flag < = 1'b0; bitiş sonu

Beşinci bölüm, eşzamanlı olarak rxd_data ve rxd_flag sinyallerinin çıkışını sağlamaktır. Çıkışı senkronize etmek için, rxd_data'ya çıktıyı rxd_flag ile senkronize etmek için bir atış vermek üzere bir birinci seviye D flip-flopu da kullanılır.

2. Seri bağlantı noktası gönderme modülü

modül uart_transfer (inputclk, // global saat inputrst_n, // global sıfırlama inputclk_16bps, inputtxd_en, input txd_data, outputreg txd, outputregtxd_flag);

Birinci kısım, giriş ve çıkışın tanımıdır, bir gönderme modülü olduğu için elbette bir etkinleştirme sinyalinin gönderilmesi gerekir, ikinci olarak, tam bir bayrak sinyali göndermek gerekir. Tabii ki, bir gönderme etkinleştirme sinyali olduğu için, durum makinesi kaçınılmazdır. clk_16bps, seri port alıcı modülüyle aynıdır.

// ----------------------------------- // FSM'yi al: localparam'ı kodlaT_IDLE = 4'd0; localparamT_SEND = 4'd1; // ----------------------------------- // FSM yerel parametresini alSMP_TOP = 4 ' d15; localparamSMP_CENTER = 4'd7; regsmp_cnt; regtxd_cnt; regtxd_state; her zaman @ (posedge clk veya negedge rst_n) başlarsa (! rst_n) smp_cnt başlar < = 4'd0; txd_cnt < = 4'd0; txd_state < = T_IDLE; başka durumu sonlandır (txd_state) T_IDLE: smp_cnt'ye başla < = 4'd0; txd_cnt < = 4'd0; eğer (txd_en) txd_state < = T_SEND; başka txd_state < = T_IDLE; son T_SEND: eğer (clk_16bps) smp_cnt ile başlarsa < = smp_cnt + 1'b1; eğer (smp_cnt == SMP_TOP) başlarsa (txd_cnt < 4'd9) txd_cnt'ye başlar < = txd_cnt + 1'b1; txd_state < = T_SEND; başka son txd_cnt ile başlar < = 4'd0; txd_state < = T_IDLE; end end else başla txd_cnt < = txd_cnt; txd_state < = txd_state; end end else start smp_cnt < = smp_cnt; txd_cnt < = txd_cnt; txd_state < = txd_state; varsayılan son: smp_cnt ile başlar < = 4'd0; txd_cnt < = 4'd0; txd_state < = T_IDLE; son harf sonu

İkinci kısım, uzun gönderme durumu makinesidir.Seri port alıcı modülüne kıyasla nispeten basittir.Farkı, gönderdiği için veriyi sadece ilk örnekleme noktasında göndermemiz gerektiğidir. 16'ya ulaştığında, gönderilecek bir sonraki biti değiştirmeniz yeterlidir.

her zaman @ (*) start if (txd_state == T_SEND) case (txd_cnt) 4'd0: begin txd = 1'b0; end 4'd1: begin txd = txd_data; end 4'd2: begin txd = txd_data; end 4 'd3: begin txd = txd_data; end 4'd4: begin txd = txd_data; end 4'd5: begin txd = txd_data; end 4'd6: begin txd = txd_data; end 4'd7: begin txd = txd_data; bitiş 4 'd8: start txd = txd_data; end 4'd9: begin txd = 1'b1; end default: begin txd = 1'b1; end endcase else txd = 1'b1; end

Üçüncü bölüm, verileri txd_cnt sayısına göre göndermektir.Bu modülün verileri hizalamak için kombinasyonel bir mantık olduğuna dikkat edin!

Şekil 1

şekil 2

Şekil 2, Şekil 1'in büyütülmüş bir versiyonudur. Saat kenarlarının hizalı olduğu görülebilmektedir.

Sıralı mantığa değiştirilirse, aşağıdaki prosedür:

always @ (posedge clk veya negedge rst_n) başla if (! rst_n) txd < = 1'b1; else if (txd_state == T_SEND) case (txd_cnt) 4'd0: begin txd = 1'b0; end 4'd1: begin txd = txd_data; end 4'd2: begin txd = txd_data; bitiş 4 'd3: begin txd = txd_data; end 4'd4: begin txd = txd_data; end 4'd5: begin txd = txd_data; end 4'd6: begin txd = txd_data; end 4'd7: begin txd = txd_data; bitiş 4 'd8: start txd = txd_data; end 4'd9: begin txd = 1'b1; end default: begin txd = 1'b1; end endcase else txd = 1'b1; end

Ardından aşağıda gösterildiği gibi:

always @ (posedge clk veya negedge rst_n) başla if (! rst_n) txd_flag < = 1'b0; else if (txd_state == T_SEND clk_16bps smp_cnt == SMP_TOP txd_cnt == 4'd9) txd_flag < = 1'b1; aksi takdirde txd_flag < = 1'b0; son

Son kısım, aktarım tamamlanma işareti sinyalini çıkarmaktır.

Böylelikle FPGA tabanlı bir seri haberleşme tamamlanmış olur.Üst seviye modülde alınan veriyi direkt olarak gönderen modüle iletebiliriz ve veriyi PC tarafında seri hata ayıklama asistanı üzerinden gönderebiliriz ve ardından FPGA veriyi sağlam olarak geri gönderir Pano düzeyinde doğrulamayı tamamlayın.

sonuç olarak:

1. Alıcı modül için, alma tamamlandıktan sonra alma tamamlama bayrağı sinyali gereklidir ve alınan verilerle eşzamanlı olarak çıkılmalıdır.

2. Modülleri göndermek için, bir gönderme etkinleştirme sinyali ve bir gönderme tamamlama işareti sinyali bulunmalıdır ve durum makinesinin BOŞTA durumu, göndermeyi etkinleştirme sinyalinin değişikliğini izlemek için kullanılır.

Kontrast şirin! "Rise of the Apes 3" Tanrı, Maurice'in kimliğinin gizli gizemine yardımcı olur
önceki
Yeni çekiç, Nut Pro adında çevrimdışı çalıştı; WikiLeaks, CIA'nın sızıntılar için izleme aracını ortaya çıkardı | Lei Feng Morning Post
Sonraki
Batı Japonya'daki en büyük anime geçit töreni! Nihonbashi Sokak Festivali COS Koleksiyonu
Tiyatro deminingi | Ay Yeni Yılı filmlerinin iyi olmadığını söyleyebilirim
2019 yılında lojistik endüstrisinin büyümesi, yeniliği ve potansiyel krizi
Bir sonraki çıkış! OPPO, ekran parmak izlerini binlerce yuan telefona yaygınlaştırıyor
Yalama Ekran Süresi | Yakışıklı yüzünüzle Kristen Stewart
Dikey Orman, Gökyüzü Şehri ... Üniversite öğrencileri, yapı taşları, karton ve atık gazetelerle geleceğin şehrini inşa ediyor
FPGA tabanlı bir ARINC659 veri yolu analizörünün tasarımı ve uygulaması
Diğer yol? Nokia'nın yeni telefonunun "yan yana yaklaşımı" başka bir başarıya ulaşabilir mi?
Vatandaşlar güneşin, kumsalın ve güzel dalgaların tadını çıkarmak için Jiangbeizui'ye akın ediyor
Omuz omuza bakmaktan, Stephen Chow hayranlarının kendini geliştirmesini başardı.
Valse 2017 | GAN araştırmasının yıllık ilerlemesinin gözden geçirilmesi
ARINC659 Veri Yolu Teknolojisine Genel Bakış
To Top