Cher journal,
Hier, j'ai découvert que l'on pouvait faire du code récursif en Verilog.
Le verilog, qu'est-ce que c'est que quoi ?
Verilog est un vieux langage de description matériel. Il sert à modéliser des circuits qui pourront être ensuite simulé et être implémenté sur un FPGA ou en ASIC.
En guise d'exemple, voici un petit module qui fait clignoter une DEL :
`define CLOCK_FREQUENCY 25000000 // Number of clock tick in 1 second - 25Mhz
`define LED_TICKS_COUNT `CLOCK_FREQUENCY // Switch the LED state every second
module LedBlink(o_led, i_clock, i_nreset);
output reg o_led;
input i_clock, i_nreset;
reg [24:0] r_counter; // 25 bits counter, up to 33,554,341
always @(posedge i_clock, negedge i_nreset) begin
if (!i_nreset) begin
// Reset the counter and switch off the LED
r_counter <= 0;
o_led <= 0;
end else if (r_counter == `LED_TICKS_COUNT) begin
// Reset the counter and switch the LED state
r_counter <= 0;
o_led <= !o_led;
end else begin
// Update the counter
r_counter <= r_counter + 1;
end
end
endmodule
Le code ci dessus est équivalent à ce circuit :
Paramètres
Il est possible de rendre les modules plus génériques via l'utilisation de paramètres dont la valeur est définissable lors de instanciation du module. Par exemple, au lieu d'avoir un module qui fait des additions sur 8 bits et un autre sur 16 bits, il est possible d'en avoir qu'un seul dont la taille est générique :
module Adder(z, a, b);
// Paramètre permettant de définir la taille de l'adder
parameter WIDTH = 8; // Valeur par défaut
// La taille des entrées/sorties dépend du paramètre WIDTH
output [WIDTH - 1:0] z;
input [WIDTH - 1:0] a, b;
assign z = a + b;
endmodule
module Foo(z1, z2, a, b);
output [7:0] z1;
output [15:0] z2;
input [15:0] a, b;
// Instantiation de l'adder en utilisant la valeur par défaut du paramètre
Adder adder8(.z(z1), .a(a[7:0]), .b(b[7:0]));
// Instantiation de l'adder en choississant la valeur du paramètre
Adder #(.WIDTH(16)) adder16(.z(z2), .a(a), .b(b));
endmodule
La récursivité avec un exemple à la con
Il est possible de créer une nouvelle instance d'un module en lui même et de jouer avec les paramètres pour définir la condition d'arrêt.
Nous allons prendre l'exemple d'un registre à décalage. Une manière de l'écrire serait de la manière suivante :
module ShiftRegister(q, d, clk);
parameter WIDTH = 8;
output reg q;
input d, clk;
reg [WIDTH - 2:0] data;
always @(posedge clk) begin
{q, data} <= {data, d};
end
endmodule
Mais pourquoi faire simple et propre quand on peut utiliser de la récursion ? Mr Olivier Cogis, mon professeur d'algorithmie, disait qu'une forêt est une forêt vide ou un arbre et une forêt. Réutilisons ce principe pour définir notre registre à bascule :
module ShiftRegister(q, d, clk);
parameter WIDTH = 4;
output q;
input d, clk;
if (WIDTH <= 0) begin
// Forêt vide
assign q = d; // passthrough
end else begin
// Un arbre
reg data;
always @(posedge clk) begin
data <= d;
end
// Une forêt
ShiftRegister #(.WIDTH(WIDTH - 1)) sr(.q(q), .d(data), .clk(clk));
end
endmodule
Multiplexeur
Bon, je ne vais te mentir, l'exemple ci dessus n'est pas vraiment une bonne pratique. Mais il a le mérite d'être pour introduire le sujet. Par contre, j'ai trouvé un cas où la récursion est bien pratique : l'écriture d'un multiplexeur, mux de son petit nom.
Le mux de base, le mux 2, possède 2 entrées (d'où le nom), un sélecteur S et d'unes ortie Z. Quand S vaut 0, on retrouve la valeur de A sur la sortie Z sinon celle de B. Sa table de vérité est
B A S | Z
---------
X 0 0 | 0
X 1 0 | 1
0 X 1 | 0
1 X 1 | 1
que l'on peut simplifier en
S | Z
-----
0 | A
1 | B
Bref, c'est l'opérateur ternaire de l'électronique (Z = S ? B : A
).
En chaînant les mux2 sous forme d'arbre, il est possible d'obtenir des multiplexeurs plus grands, tel que le mux4 :
et le mux 8 :
Comme tu est très perspicace, tu auras remarqué que un mux 2^S
est constitué de 2 mux 2^(S - 1)
et un mux 2. Le mux 4 (S = 2) est ainsi constitué de 2 mux 2 reliés par un mux 2 et le mux 8 (S = 3) est constitué de 2 mux 4 relié par un mux 2.
module Mux(z, d, s);
parameter S = 3;
output z;
input [2 ** S - 1:0] d;
input [S - 1:0] s;
if (S == 1) begin
assign z = s ? d[1] : d[0];
end else begin
wire z1, z2;
Mux #(.S(S - 1)) mux1(.z(z1), .d(d[2 ** (S - 1) - 1:0]), .s(s[S - 2:0]));
Mux #(.S(S - 1)) mux2(.z(z2), .d(d[2 ** S - 1:2 ** (S - 1)]), .s(s[S - 2:0]));
assign z = s[S - 1] ? z2 : z1;
end
endmodule
# Demande d'édition
Posté par jtremesay (site web personnel) . Évalué à 5.
Me suis planté de bouton et ai cliqué sur publié à la place du prévisualiser.
Est-ce qu'un modo pourrai corriger la phrase « En chaînant les mux2 sous forme d'arbre, il est possible d'obtenir des multiplexeurs plus grands, tel que le mux :» et ajouter «4» à la fin (-> «tel que le mux 4 :») et remplacer l'image juste en dessous par celle là ? https://i.zcraft.fr/3724891588696559.png
Merci !
[^] # Re: Demande d'édition
Posté par Benoît Sibaud (site web personnel) . Évalué à 7.
Corrigé, merci.
# Merci!
Posté par batousky . Évalué à 3.
C'est la première fois que je vois du Verilog sans me sentir complément perdu!
Très instructif, merci :)
# lisibilité
Posté par flavien75 . Évalué à 2.
Il n'y a pas a dire, le VHDL est et restera plus lisible:
Les vrais naviguent en -42
[^] # Re: lisibilité
Posté par gringonz . Évalué à 1.
Oui, entièrement d'accord. Le seul avantage de verilog est d'être plus compact. Mais j'ai aussi découvert à mes dépends que tu peux affecter un mot de 12 bits sur un de 10 et qu'il ne dit rien contrairement à VHDL.
# Conseil pour débuter ?
Posté par RB . Évalué à 1.
Hello,
ça m'intéresserait de me mettre aux FPGA et je regardais justement avec quel environnement je pouvais débuter (matériel et logiciel).
Je n'ai pas un background en électronique et pas d'expérience ou d'études dans le domaine du design de circuit.
Pour écrire du VHDL/Verilog j'ai donc besoin d'un logiciel qui me guide assez bien et qui me permette de simuler le circuit avant déploiement dans un environnement assez bien intégré/compréhensible.
Malheureusement c'est un domaine ou il y a beaucoup de proprio, avez-vous des conseils ?
Merci !
[^] # Re: Conseil pour débuter ?
Posté par gringonz . Évalué à 1. Dernière modification le 07 mai 2020 à 15:37.
Effectivement majoritairement du propriétaire mais qui tourne sous linux. Les choses bougent aussi, cf des journaux récent sur ce forum.
Pour la simulation VHDL en tout libre j'utilise ghdl avec gtkwave pour visualiser les chonos (développé par un français).
C'est pour la synthèse et placement routage que c'est plus fermé, selon le FPGA cible.
[^] # Re: Conseil pour débuter ?
Posté par sebosebo . Évalué à 0. Dernière modification le 17 mai 2020 à 11:38.
Salut,
Je te conseille d'aller sur le blog de Fabien:
http://www.fabienm.eu/flf/
Il est un bon point de départ pour connaitre les outils libres existants dans le domaine.
Il a d'ailleurs publié quelques dépêches ici.
Après, il y a deux axes:
- apprendre le langage pour pouvoir le tester sur une carte de développement (il faut donc un peu investir car rien ne vaut un test pour voir sa création s'exécuter ;-)
- apprendre à vérifier son code grâce aux simulateurs
Sébastien
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.