Dans ce cours nous verrons comment décrire des fonctions de l'électronique numérique en SystemVerilog.
Plus particulièrement, nous nous intéresserons à la description de:
- la logique combinatoire;
- la logique séquentielle synchrone;
- les machines à états finis;
- les mémoires synchrones.
Les points importants qu'il fat garder sont résumés dans ce qui suit. Pour les détails, référez vous au cour.
Logique combinatoire
- La sortie d'un bloc combinatoire ne dépend que de la valeur de ses entrées.
- Pour les mêmes valeurs des entrées on doit toujours avoir les mêmes valeurs de sortie.
- Pas de mémorisation,
- Pour ne pas se tromper:
- liste de sensibilité automatique en utilisant
always_comb,
- n'utiliser que des affectations immediate (
=),
- donner systématiquement une valeur par défaut aux sorties ou être sûr de couvrir tous les cas,
- liste de sensibilité automatique en utilisant
Exemple
- Un multiplexeur
always_comb
begin
if(x) y = z;
else y = w;
end
// ou
always_comb
begin
y = w;
if(x) y = z;
end
begin
if(x) y = z;
else y = w;
end
// ou
always_comb
begin
y = w;
if(x) y = z;
end
Logique séquentielle
- Dès qu'il y a mémorisation, elle doit être séquentielle.
- Un processus sensible au seul front d'horloge
- et éventuellement un signal de remise à zéro si celui-ci est asynchrone
- Les affectations doivent être différées (
<=)
- L'état initial doit être définit dans le même processus avec une condition de remise à zéro (reset)
Structure de base
- Avec remise à zéro synchrone, le signal de reset ne fait pas partie de la liste de sensibilité
always_ff@(posedge clk)
if (reset)
begin
...
end
else
begin
...
end
if (reset)
begin
...
end
else
begin
...
end
- Avec remise à zéro asynchrone, le signal de reset fait partie de la liste de sensibilité.
- Le reset est actif sur niveau haut:
always_ff@(posedge clk or posedge reset)
if (reset)
begin
...
end
else
begin
...
end
if (reset)
begin
...
end
else
begin
...
end
- Le reset est actif sur niveau bas:
always_ff@(posedge clk or negedge nreset)
if (!nreset)
begin
...
end
else
begin
...
end
if (!nreset)
begin
...
end
else
begin
...
end
Mémoire synchrone simple port
- Au front d'horloge on obtient l'élément pour lequel on a présenté l'adresse
- Au même front on peut modifier ce même élément
Exemples
module sram(input clk, wr,
input [7:0] Addr,
input [7:0] Di,
output logic [7:0] Do );
logic[7:0] mem [0:255];
always_ff @(posedge clk)
begin
if (wr)
mem[Addr] <= Di;
Do <= mem[Addr];
end
endmodule
input [7:0] Addr,
input [7:0] Di,
output logic [7:0] Do );
logic[7:0] mem [0:255];
always_ff @(posedge clk)
begin
if (wr)
mem[Addr] <= Di;
Do <= mem[Addr];
end
endmodule
ou
module sram(input clk, wr,
input [7:0] Addr,
input [7:0] Di,
output [7:0] Do );
logic[7:0] mem [0:255];
logic[7:0] Addr_r;
always_ff @(posedge clk)
begin
if (wr)
mem[Addr] <= Di;
Addr_r <= Addr;
end
assign Do = mem[Addr_r];
endmodule
input [7:0] Addr,
input [7:0] Di,
output [7:0] Do );
logic[7:0] mem [0:255];
logic[7:0] Addr_r;
always_ff @(posedge clk)
begin
if (wr)
mem[Addr] <= Di;
Addr_r <= Addr;
end
assign Do = mem[Addr_r];
endmodule
Mémoire synchrone dual-port
- Deux canaux indépendants pour accéder à la même table
module sram_dp(input clk, wr1, wr2,
input [7:0] Addr1, Addr2,
input [7:0] Di1, Di2,
output logic [7:0] Do1, Do2 );
logic[7:0] mem [0:255];
always_ff @(posedge clk)
begin
if (wr1)
mem[Addr1] <= Di1;
Do1 <= mem[Addr1];
end
always_ff @(posedge clk)
begin
if (wr2)
mem[Addr2] <= Di2;
Do2 <= mem[Addr2];
end
endmodule
input [7:0] Addr1, Addr2,
input [7:0] Di1, Di2,
output logic [7:0] Do1, Do2 );
logic[7:0] mem [0:255];
always_ff @(posedge clk)
begin
if (wr1)
mem[Addr1] <= Di1;
Do1 <= mem[Addr1];
end
always_ff @(posedge clk)
begin
if (wr2)
mem[Addr2] <= Di2;
Do2 <= mem[Addr2];
end
endmodule
Rom synchrone
- Initialiser le contenu de la table et interdire l'écriture
- NE FONCTIONNE QU'AVEC LES FPGAs
module rom (input clk,
input [7:0] Addr,
output logic [7:0] Do );
logic[7:0] mem [0:255];
initial
$readmemh("init.txt", mem);
always_ff @(posedge clk)
Do <= mem[Addr];
endmodule
input [7:0] Addr,
output logic [7:0] Do );
logic[7:0] mem [0:255];
initial
$readmemh("init.txt", mem);
always_ff @(posedge clk)
Do <= mem[Addr];
endmodule
Ressources en ligne "Quartus Prime User Guides" (ICI!)
Plus particulièrement le chapitre 3 «Design Recommendations», et ses sections:
- «Recommended Design Practices»
- «Recommended HDL Coding Styles»
Fichier attaché | Taille |
---|---|
![]() | 290.37 Ko |