La position actuelle:Accueil du site>Conception de l'interface UART basée sur la FPGA
Conception de l'interface UART basée sur la FPGA
2022-07-23 18:59:45【QQ 44985628】
Un.、Idées de conception de haut niveau:
UARTC'est - à - dire l'interface universelle de transmission asynchrone(Universal Asynchronous Receiver/Transmitter),Pour faire court au port série,Est une interface de communication commune,Le principe de l'accord n'est pas précisé,Ceux qui ne le savent pas peuvent consulter les documents par eux - mêmes.(Ne pas répéter ne signifie pas que ce n'est pas important,Au contraire.,Pour chaqueFPGAConception,Une bonne compréhension des principes est la base et la prémisse,EtFPGAEtVerilogJuste des outils.)AvecFPGAPour réaliserUART,La clé est deUARTLa séquence de temps utilisée pour envoyer et recevoir les données estVerilogDécrivez - le..
SelonUARTPrincipe du Protocole,Peut transformer toutUARTDivisé en deux modules:Module récepteur série“UART_RX”Et le module d'envoi de port série“UART_TX”,Le premier recevra1Données de série bits“uart_rxd”Convertir en8Bits données parallèles“data[7:0]”,Ce dernier, à son tour,8Bits données parallèles“data[7:0]”Convertir en1Données de série bits“uart_txd”Produits,Enfin, la réception et la réception des données en série.UARTLe diagramme du bloc de fonctions de haut niveau est illustré à la figure1Comme indiqué:
2.、Conception du module récepteur série:
Ce module implémente ce qui sera reçu1Les données de série de bits sont converties en8Bits données parallèles,Et seulement si les données sont saisies, Le module ne fonctionne que , Il faut donc un signal d'activation “rxd_en” Pour contrôler le module ,Quand“rxd_en”Quand ça marche, Le module ne fonctionne que .SelonUARTPrincipe du Protocole,Reçu1 Le premier bit des données de série de bits est le BIT de départ (“0”),Et“uart_rxd” Au ralenti pour “1”, Donc, au début de la réception des données en série ,“uart_rxd” Il doit y avoir un bord de descente , Pour pouvoir détecter ce bord de descente , Chaque fois que le bord de descente arrive “rxd_en”Set to valid, Pour que le module fonctionne ; Chaque fois que toutes les données en série sont reçues ,Encore“rxd_en”Set to invalid, Envoyer simultanément le drapeau d'achèvement de la réception “rx_done”, Pour fermer le module .(À propos deVerilog Comment réaliser la détection des bords , Vous pouvez voir ce que j'ai écrit sur DDS Le blog du générateur de signaux .)
Pendant la réception des données , Le taux est basé sur le taux Baud du port série , Les taux de Baud de port série couramment utilisés sont :1200、2400、4800、9600、14400、57600、115200Attendez un peu!. Donc un compteur de débit Baud est nécessaire “baud_cnt” Comptez l'horloge principale à un taux de Baud spécifique , Chaque fois que ce compteur de débit Baud est plein , Recevoir un chiffre de données .Par exemple, L'horloge principale est 50MHz,Quand le taux de Baud est9600Heure, La valeur maximale du compteur de débit Baud doit être :50000000/9600-1=5207,En ce moment, Chaque fois que le compteur de débit Baud compte 5207 Zéro à l'heure , Réception simultanée d'un bit de données en série .
Dans ce design, Les bits de données sont communs à chaque donnée 10Bits(1Bit Start bit、8Bits de données、1Bit stop bit), Donc dans le processus de réception , Un compteur de bits est nécessaire “bit_cnt” Pour compter les bits de données de chaque série ,Les opérations spécifiques sont les suivantes:: Chaque fois que le compteur de débit Baud est plein , Le compteur de bits augmente automatiquement 1, Jusqu'à ce que la valeur du compteur de bits soit 9Zéro..
Pendant la réception, Pour recevoir des données stables en série , Cette conception permet d'échantillonner et de recevoir des données en série de chaque bit au milieu ,Les opérations spécifiques sont les suivantes:: Chaque fois que le compteur de débit Baud atteint la moitié de la valeur maximale , Pour échantillonner les données de série actuelles , Ensuite, selon la valeur du compteur de bits , Assigner les valeurs échantillonnées aux bits de données parallèles correspondants .En outre, Pour éliminer la métastabilité , Les données en série à recevoir doivent être tamponnées par un registre à deux chiffres avant la détection des bords .
Sur la base de l'analyse ci - dessus, Le diagramme de séquence du module récepteur de port série est illustré à la figure 2Comme indiqué(“uart_rxd_r”- Oui.“uart_rxd” Signal après élimination de l'état métastable et détection du bord du registre ):
Selon le diagramme de séquence, Pour que le module de réception de port série RTLDescription,Écrit parVerilogLes codes sont les suivants::
`timescale 1ns / 1ps
module UART_RX(
input clk, //Horloge principale,50MHz
input rst, //Réinitialiser,Haute efficacité
input uart_tx_data, // Données série envoyées au port série
output reg [7:0] uart_rx_data, // Données parallèles reçues par le port série
output reg rx_done //Recevoir le drapeau d'achèvement
);
parameter CLK_F = 50000000; // Fréquence de l'horloge principale
parameter UART_B = 9600; //Taux de Baud du port série
parameter B_CNT = CLK_F / UART_B; // La valeur maximale du compteur de débit Baud
reg [1:0] uart_tx_data_r1; // Pour éliminer l'état métastable des données en série d'entrée
reg [1:0] uart_tx_data_r2; // Saisissez le registre de détection des bords de données série
reg rxd_en; // Réception du signal d'activation
reg [15:0] baud_cnt = 16'd0; //115200Compteur de débit Baud
reg [3:0] bit_cnt = 4'd0; //Compteur de bits
reg [7:0] rx_data; //Registre des données reçues
/*************** Éliminer la métastabilité des données en série d'entrée *************/
always @ (posedge clk)
begin
uart_tx_data_r1 <= {
uart_tx_data_r1[0] , uart_tx_data};
end
/*************** Saisissez la détection de bord de données série *************/
always @ (posedge clk)
begin
uart_tx_data_r2 <= {
uart_tx_data_r2[0] , uart_tx_data_r1[1]};
end
/*************** Commande du signal d'activation de réception *************/
always @ (posedge clk or negedge rst)
begin
if (rst)
rxd_en <= 1'd0;
else
begin
if (uart_tx_data_r2 == 2'b10)
rxd_en <= 1'd1;
else if ((bit_cnt == 4'd9) && (baud_cnt == B_CNT / 2))
rxd_en <= 1'd0;
else
rxd_en <= rxd_en;
end
end
/*************** Contrôle du compteur de débit Baud *************/
always @ (posedge clk or negedge rst)
begin
if (rst)
baud_cnt <= 16'd0;
else if (rxd_en)
begin
if (baud_cnt == B_CNT - 1)
baud_cnt <= 16'd0;
else
baud_cnt <= baud_cnt + 1'b1;
end
else
baud_cnt <= 16'd0;
end
/*************** Contrôle du compteur de bits *************/
always @ (posedge clk or negedge rst)
begin
if (rst)
bit_cnt <= 4'd0;
else if (rxd_en)
begin
if (baud_cnt == B_CNT - 1)
bit_cnt <= bit_cnt + 1'b1;
else
bit_cnt <= bit_cnt;
end
else
bit_cnt <= 4'd0;
end
/***************Recevoir le cache*************/
always @ (posedge clk or negedge rst)
begin
if (rst)
rx_data <= 8'd0;
else if (rxd_en)
begin
if (baud_cnt == B_CNT / 2)
begin
case (bit_cnt)
4'd1:rx_data[0] <= uart_tx_data_r2[1];
4'd2:rx_data[1] <= uart_tx_data_r2[1];
4'd3:rx_data[2] <= uart_tx_data_r2[1];
4'd4:rx_data[3] <= uart_tx_data_r2[1];
4'd5:rx_data[4] <= uart_tx_data_r2[1];
4'd6:rx_data[5] <= uart_tx_data_r2[1];
4'd7:rx_data[6] <= uart_tx_data_r2[1];
4'd8:rx_data[7] <= uart_tx_data_r2[1];
default:;
endcase
end
else
rx_data <= rx_data;
end
else
rx_data <= 8'd0;
end
/***************Réception*************/
always @ (posedge clk or negedge rst)
begin
if (rst)
uart_rx_data <= 8'd0;
else if (bit_cnt == 4'd9)
uart_rx_data <= rx_data;
else
uart_rx_data <= 8'd0;
end
/*************** Recevoir le contrôle du drapeau d'achèvement *************/
always @ (posedge clk or negedge rst)
begin
if (rst)
rx_done <= 1'd0;
else if (bit_cnt == 4'd9)
rx_done <= 1'd1;
else
rx_done <= 1'd0;
end
endmodule
Écrit partestbeachComme suit:
`timescale 1ns / 1ps
module tb_uart_rx();
reg clk; //Horloge principale,50MHz
reg rst; //Réinitialiser,Faible niveau actif
reg uart_tx_data; // Données série envoyées au port série
wire [7:0] uart_rx_data; // Données parallèles reçues par le port série
wire rx_done; //Recevoir le drapeau d'achèvement
/***************Instanciation modulaire*************/
UART_RX tb_uart_rx(
.clk(clk),
.rst(rst),
.uart_tx_data(uart_tx_data),
.uart_rx_data(uart_rx_data),
.rx_done(rx_done)
);
/*************** Générer l'horloge principale *************/
always #10 clk = ~clk;
/***************Initialisation*************/
initial
begin
clk = 1'd0;
rst = 1'd0;
uart_tx_data = 1'b1;
#1000000
uart_tx_data = 1'b0;
#200000
uart_tx_data = 1'b1;
#200000
uart_tx_data = 1'b0;
#200000
uart_tx_data = 1'b1;
end
endmodule
Les résultats de la simulation sont présentés à la figure 3Comme indiqué, Vous pouvez voir que la fonction de réception est implémentée :
Trois、 Conception du module d'envoi de port série :
La mise en œuvre du module 8 Bits données parallèles converties en 1 Sortie de données série bit , Comme pour le module récepteur , Le module d'envoi de port série a également besoin d'un signal d'activation “txd_en”Pour contrôler,Quand“txd_en”Quand ça marche, Le module ne fonctionne que .SelonUARTPrincipes, Ce n'est qu'après réception du module récepteur , Envoyer le module pour commencer à fonctionner , Par conséquent, le drapeau d'achèvement de la réception dans le module de réception est le drapeau de début de transmission du module de transmission “txd_start”, Il est donc possible de détecter le bord ascendant du drapeau de départ d'envoi pour permettre “txd_en”, Cela permet d'envoyer des modules .
Sur la base de l'analyse ci - dessus, Le diagramme de synchronisation du module d'envoi de port série est illustré à la figure 4Comme indiqué:
Selon le diagramme de séquence,Écrit parVerilogLes codes sont les suivants::
`timescale 1ns / 1ps
module UART_TX(
input clk, //Horloge principale,50MHz
input rst, //Réinitialiser,Haute efficacité
input txd_start, // Envoyer le drapeau de départ
input [7:0] uart_rx_data, // Données parallèles reçues par le port série
output reg uart_tx_data // Données série envoyées par le port série
);
parameter CLK_F = 50000000; // Fréquence de l'horloge principale
parameter UART_B = 9600; //Taux de Baud du port série
parameter B_CNT = CLK_F / UART_B; // La valeur maximale du compteur de débit Baud
reg [1:0] txd_start_r; // Envoyer le registre de détection des bords du drapeau de départ
reg txd_en; //Envoyer un signal d'activation
reg [15:0] baud_cnt = 16'd0; //115200Compteur de débit Baud
reg [3:0] bit_cnt = 4'd0; //Compteur de bits
reg [7:0] tx_data; //Envoyer un registre de données
/*************** Envoyer la détection du bord du drapeau de départ *************/
always @ (posedge clk)
begin
txd_start_r <= {
txd_start_r[0] , txd_start};
end
/*************** Commande du signal d'activation de la transmission *************/
always @ (posedge clk or negedge rst)
begin
if (rst)
txd_en <= 1'd0;
else
begin
if (txd_start_r == 2'b01)
txd_en <= 1'd1;
else if ((bit_cnt == 4'd9) && (baud_cnt == B_CNT / 2))
txd_en <= 1'd0;
else
txd_en <= txd_en;
end
end
/***************Envoyer le cache*************/
always @ (posedge clk or negedge rst)
begin
if (rst)
tx_data <= 8'd0;
else
begin
if (txd_start_r == 2'b01)
tx_data <= uart_rx_data;
else if ((bit_cnt == 4'd9) && (baud_cnt == B_CNT / 2))
tx_data <= 8'd0;
else
tx_data <= tx_data;
end
end
/*************** Contrôle du compteur de débit Baud *************/
always @ (posedge clk or negedge rst)
begin
if (rst)
baud_cnt <= 16'd0;
else if (txd_en)
begin
if (baud_cnt == B_CNT - 1)
baud_cnt <= 16'd0;
else
baud_cnt <= baud_cnt + 1'b1;
end
else
baud_cnt <= 16'd0;
end
/*************** Contrôle du compteur de bits *************/
always @ (posedge clk or negedge rst)
begin
if (rst)
bit_cnt <= 4'd0;
else if (txd_en)
begin
if (baud_cnt == B_CNT - 1)
bit_cnt <= bit_cnt + 1'b1;
else
bit_cnt <= bit_cnt;
end
else
bit_cnt <= 4'd0;
end
/***************Envoyer*************/
always @ (posedge clk or negedge rst)
begin
if (rst)
uart_tx_data <= 1'd1;
else if (txd_en)
begin
case (bit_cnt)
4'd0:uart_tx_data <= 1'd0;
4'd1:uart_tx_data <= tx_data[0];
4'd2:uart_tx_data <= tx_data[1];
4'd3:uart_tx_data <= tx_data[2];
4'd4:uart_tx_data <= tx_data[3];
4'd5:uart_tx_data <= tx_data[4];
4'd6:uart_tx_data <= tx_data[5];
4'd7:uart_tx_data <= tx_data[6];
4'd8:uart_tx_data <= tx_data[7];
4'd9:uart_tx_data <= 1'd1;
default:;
endcase
end
else
uart_tx_data <= 1'd1;
end
endmodule
Écrit partestbeachComme suit:
`timescale 1ns / 1ps
module tb_uart_tx();
reg clk; //Horloge principale,50MHz
reg rst; //Réinitialiser,Faible niveau actif
reg txd_start; // Envoyer le drapeau de départ
reg [7:0] uart_rx_data; // Données parallèles reçues par le port série
wire uart_tx_data; // Données série envoyées par le port série
/***************Instanciation modulaire*************/
UART_TX tb_uart_tx(
.clk(clk),
.rst(rst),
.txd_start(txd_start),
.uart_rx_data(uart_rx_data),
.uart_tx_data(uart_tx_data)
);
/*************** Générer l'horloge principale *************/
always #10 clk = ~clk;
/***************Initialisation*************/
initial
begin
clk = 1'd0;
rst = 1'd0;
txd_start = 1'd0;
uart_rx_data = 8'h5a;
#20
txd_start = 1'd1;
#20
txd_start = 1'd0;
#100000
uart_rx_data = 8'h3f;
#100000
uart_rx_data = 8'he6;
end
endmodule
Les résultats de la simulation sont présentés à la figure 5Comme indiqué, Vous pouvez voir que la fonction d'envoi est implémentée :
Fig.5
Quatre、 .Code de haut niveau et mise en service de son tableau supérieur :
Après la conception des deux sous - modules , Selon le diagramme de bloc de fonctions de haut niveau, vous pouvez écrire RTLDescription,Écrit parVerilogLes codes sont les suivants:( Parce que l'horloge sur mon tableau de développement est l'horloge différentielle , Il est donc nécessaire d'appeler un primitif de conception pour convertir un signal différentiel en signal à une seule extrémité “IBUFDS”, L'utilisation de ce primitif est simple , Il n'y a pas d'introduction ici ,Ceux qui ne le savent pas peuvent consulter les documents par eux - mêmes):
`timescale 1ns / 1ps
module UART_TOP(
input clk_p, // Fin positive de l'horloge principale différentielle ,50MHz
input clk_n, // Fin négative de l'horloge principale différentielle ,50MHz
input rst, //Réinitialiser,Haute efficacité
input uart_rxd, //Récepteur
output uart_txd //L'expéditeur
);
parameter CLK_FREQ = 50000000; // Fréquence de l'horloge principale
parameter UART_BPS = 460800; //Taux de Baud du port série
wire clk; //Horloge principale,50MHz
wire [7:0] uart_rx_data_w; // Câble parallèle dans le port série
wire rx_done_w; // Réception de la ligne de signal d'achèvement
/*************** Horloge différentielle à horloge à une extrémité *************/
IBUFDS #(
.DIFF_TERM("FALSE"),
.IBUF_LOW_PWR("TRUE"),
.IOSTANDARD("DEFAULT")
) IBUFDS_inst (
.O(clk),
.I(clk_p),
.IB(clk_n)
);
/*************** Appelez le module de réception du port série *************/
UART_RX #(
.CLK_F(CLK_FREQ),
.UART_B(UART_BPS)
)
uut_rxd(
.clk(clk),
.rst(rst),
.uart_tx_data(uart_rxd),
.uart_rx_data(uart_rx_data_w),
.rx_done(rx_done_w)
);
/*************** Appelez le module d'envoi du port série *************/
UART_TX #(
.CLK_F(CLK_FREQ),
.UART_B(UART_BPS)
)
uut_txd(
.clk(clk),
.rst(rst),
.txd_start(rx_done_w),
.uart_rx_data(uart_rx_data_w),
.uart_tx_data(uart_txd)
);
endmodule
Synthèse、Après la réalisation, Effectuer la mise en service de la plaque supérieure ,Par souci de simplicité, La conception adopte la boucle pour déboguer et vérifier ,C'est - à - dire:PCEnvoyer les données àFPGAAllez.,FPGA Les données sont reçues par le port série avant d'être retournées par le port série PC. Les résultats de la mise en service sont présentés à la figure 6Comme indiqué,Je vois., Le port série conçu fonctionne correctement :
Mentions de copyright
Auteur de cet article [QQ 44985628],Réimpression s’il vous plaît apporter le lien vers l’original, merci
https://fra.chowdera.com/2022/204/202207231641422375.html
Recommandé par sidebar
- Transplantation de systèmes embarqués
- Saisissez une chaîne de caractères à partir du clavier et affichez différents caractères et le nombre d'occurrences de chaque caractère. (la sortie n'est pas séquentielle) résoudre le problème en utilisant la méthode commune de la classe de chaîne
- 2019 Bar _ Aaai ICCN
- Conditions affectant la vitesse de requête de l'interface
- Stack et file d'attente de l'adaptateur STL
- Analyse de la stratégie de lecture et d'écriture du cache
- Classes et objets (1)
- Expérience II Yuv
- Comment synchroniser
- [arxiv2022] grouptransnet: Group transformer Network for RGB - D Salient Object Detection
Devinez que vous aimez
Avantages de la salle des machines bgp
La fosse Piétinée par l'homme vous dit d'éviter les 10 erreurs courantes dans les tests automatisés
Déterminer s'il s'agit d'un type vide
Langue C - quelques exercices classiques de langue C
Openvino Datawhale
Question 300 Leçon 6 type quadratique
Analyse du code source et de la conception de redis - - 7. Liste rapide
Concepts et différences de bits, bits, octets et mots
Déploiement du projet (version abrégée)
JDBC Learning and simple Encapsulation
Recommandé au hasard
- [Python flask note 5] Blueprint simple à utiliser
- Composants web - cycle de vie des éléments personnalisés
- Entrepôt de données 4.0 Notes - acquisition de données commerciales
- Entrepôt de données 4.0 Notes - acquisition de données sur le comportement de l'utilisateur II
- Affichage itératif des fichiers.h5, opérations de données h5py
- Résumé des connaissances mathématiques communes
- Comment se développe le serveur GPU refroidi à l'eau dans le Centre de données dans le cadre de l'informatique est - Ouest?
- Connaissance du matériel 1 - schéma et type d'interface (basé sur le tutoriel vidéo complet de l'exploitation du matériel de baiman)
- Examen des principes fondamentaux de la structure en acier
- Unity3d: ugui source, Rebuild Optimization
- Solution rapide: xshell ne peut pas glisser dans un dossier ou un paquet
- Rhcsa - - parcourir le contenu du fichier, couper, uniq, trier, utiliser les commandes.tr
- Intégrité du signal (si) intégrité de l'alimentation électrique (PI) notes d'apprentissage (32) Réseau de distribution d'énergie (4)
- Quelle est la raison pour laquelle la plate - forme easygbs ne peut pas lire l'enregistrement vidéo et a un phénomène de streaming répété rtmp?
- Notes du jour 7
- 【 Visual Dispatching Software】 Shanghai Dow Ning apporte netronic download, Trial, tutoriel pour l'Organisation SMB
- 2. Les règles quantitatives
- Événements courants de la souris et du clavier
- C #: in, out, ref Keywords
- Connaissance détaillée du GRE, du mgre; Connaissance de la configuration de base de l'OSPF
- Comment creo 9.0 modifie - t - il rapidement le système de coordonnées Cao?
- Notes du jour 5
- Renforcement de l'apprentissage - points de compréhension du gradient stratégique
- Le shell a besoin de connaître les commandes
- Okrk3399 Development Board Reserved i2c4 Mounting EEPROM
- Optimisation du serveur Cloud Huawei avec connexion clé
- Chapitre 2 requête de base et tri
- 【 langage c】 devinez jeux numériques + applet d'arrêt
- Qu'est - ce que le codage par titre?
- Feignclient utilise un tutoriel détaillé (illustration)
- Kettle implémente une connexion de base de données partagée et insère une instance de composant de mise à jour
- Simulation de modulation et de démodulation du signal CBOC basée sur MATLAB, sortie de corrélation, spectre de puissance et suivi de décalage de fréquence
- Les raccourcis clavier liés à l'onglet ne peuvent pas être utilisés après la mise à jour du vscode
- Expression du suffixe (une question par jour pendant les vacances d'été 4)
- Idées de conception sur l'initialisation des paramètres d'entrée de page
- Éléments de base de la validation des haricots - 04
- Une solution complète au problème du sac à dos dans la programmation dynamique
- Récursion des bosses 1: formule récursive
- Explication détaillée de l'injection aveugle d'erreur SQL
- Données chronologiques dans l'Internet industriel des objets