J'essaie d'obtenir un module pour passer la vérification de la syntaxe dans ISE 12.4, et cela me donne une erreur que je ne comprends pas. D'abord un extrait de code:
parameter ROWBITS = 4;
reg [ROWBITS-1:0] temp;
genvar c;
generate
always @(posedge sysclk) begin
for (c = 0; c < ROWBITS; c = c + 1) begin: test
temp[c] <= 1'b0;
end
end
endgenerate
Lorsque j'essaie de vérifier la syntaxe, le message d'erreur suivant s'affiche:
ERREUR: HDLCompiler: 731 - "test.v" Ligne 46: Affectation de procédure à un le non-enregistrement <c> n'est pas autorisé.
Je ne comprends vraiment pas pourquoi il se plaint. "c" n'est pas un fil, c'est un genvar. Cela devrait être l'équivalent de la syntaxe complètement légale:
reg [3:0] temp;
always @(posedge sysclk) begin
temp[0] <= 1'b0;
temp[1] <= 1'b0;
temp[2] <= 1'b0;
temp[3] <= 1'b0;
end
S'il vous plaît, pas de commentaires sur la façon dont il serait plus facile d'écrire ceci sans générer. Ceci est un exemple réduit d'un morceau de code beaucoup plus complexe impliquant plusieurs ifs et des affectations non bloquantes à "temp". En outre, ne me dites pas simplement qu'il existe de nouvelles versions d'ISE, je le sais déjà. OTOH, si vous savez c'est corrigé dans une version ultérieure d'ISE, veuillez me faire savoir quelle version vous savez fonctionner.
Vous devez inverser l'imbrication à l'intérieur du bloc generate:
genvar c;
generate
for (c = 0; c < ROWBITS; c = c + 1) begin: test
always @(posedge sysclk) begin
temp[c] <= 1'b0;
end
end
endgenerate
Techniquement, cela génère toujours quatre blocs:
always @(posedge sysclk) temp[0] <= 1'b0;
always @(posedge sysclk) temp[1] <= 1'b0;
always @(posedge sysclk) temp[2] <= 1'b0;
always @(posedge sysclk) temp[3] <= 1'b0;
Dans cet exemple simple, il n’ya pas de différence de comportement entre les quatre blocs toujours et un seul bloc contenant toujours quatre assignations, mais dans d’autres cas, ce pourrait être le cas.
L'opération dépendante de genvar doit être résolue lors de la construction de la représentation en mémoire de la conception (dans le cas d'un simulateur) ou lors de la mise en correspondance avec des portes logiques (dans le cas d'un outil de synthèse). Le always @posedge
n'a de sens que lorsque la conception est opérationnelle.
Sous réserve de certaines restrictions, vous pouvez insérer une boucle for dans le bloc always, même pour du code synthétisable. Pour la synthèse, la boucle sera déroulée. Cependant, dans ce cas, la boucle for doit fonctionner avec un reg
, integer
ou similaire. Il ne peut pas utiliser genvar
, car le fait d'avoir la boucle for dans le bloc always décrit une opération qui se produit à chaque front de l'horloge et non une opération pouvant être étendue statiquement lors de l'élaboration de la conception.
Vous n'avez pas besoin de générer un bloc si vous voulez que tous les bits de temp
soient affectés dans le même bloc toujours.
parameter ROWBITS = 4;
reg [ROWBITS-1:0] temp;
always @(posedge sysclk) begin
for (integer c=0; c<ROWBITS; c=c+1) begin: test
temp[c] <= 1'b0;
end
end
Sinon, si votre simulateur prend en charge IEEE 1800 (SytemVerilog), alors
parameter ROWBITS = 4;
reg [ROWBITS-1:0] temp;
always @(posedge sysclk) begin
temp <= '0; // fill with 0
end
end
Si cela ne vous dérange pas de devoir compiler/générer le fichier, vous pouvez utiliser une technique de pré-traitement. Cela vous donne la puissance de la génération, mais aboutit à un fichier Verilog propre qui est souvent plus facile à déboguer et entraîne moins de problèmes de simulateur.
J'utilise RubyIt pour générer des fichiers Verilog à partir de modèles utilisant ERB (Embedded Ruby).
parameter ROWBITS = <%= ROWBITS %> ;
always @(posedge sysclk) begin
<% (0...ROWBITS).each do |addr| -%>
temp[<%= addr %>] <= 1'b0;
<% end -%>
end
Générer le fichier nom_module.v avec:
$ Ruby_it --parameter ROWBITS=4 --outpath ./ --file ./module_name.rv
Le nom_module généré.v
parameter ROWBITS = 4 ;
always @(posedge sysclk) begin
temp[0] <= 1'b0;
temp[1] <= 1'b0;
temp[2] <= 1'b0;
temp[3] <= 1'b0;
end
Dans un module, Verilog contient essentiellement deux constructions: les éléments et les instructions. Les instructions se trouvent toujours dans des contextes procéduraux, qui incluent n'importe quoi entre début, fin, fonctions, tâches, toujours des blocs et des blocs initiaux. Les éléments, tels que les constructions générées, sont listés directement dans le module. Les boucles For et la plupart des déclarations de variable/constante peuvent exister dans les deux contextes.
Dans votre code, il semble que vous souhaitiez que la boucle for soit évaluée en tant qu'élément de génération, mais la boucle fait en réalité partie du contexte procédural du bloc always. Pour qu'une boucle for soit traitée comme une boucle de génération, elle doit être dans le contexte du module. Les mots clés generate..endgenerate sont entièrement facultatifs (certains outils les exigent) et n'ont aucun effet. Voir cette réponse pour un exemple de la façon dont les boucles de génération sont évaluées.
//Compiler sees this
parameter ROWBITS = 4;
reg [ROWBITS-1:0] temp;
genvar c;
always @(posedge sysclk) //Procedural context starts here
begin
for (c = 0; c < ROWBITS; c = c + 1) begin: test
temp[c] <= 1'b0; //Still a genvar
end
end
pour verilog juste faire
parameter ROWBITS = 4;
reg [ROWBITS-1:0] temp;
always @(posedge sysclk) begin
temp <= {ROWBITS{1'b0}}; // fill with 0
end
Pour le dire simplement, vous n’utilisez pas generate
dans un processus always, vous utilisez generate pour créer un processus paramétré ou instancier des modules particuliers, où vous pouvez combiner if-else
ou case
. Ainsi, vous pouvez déplacer ceci pour générer et créer un processus particulier ou une instanciation, par exemple,
module #(
parameter XLEN = 64,
parameter USEIP = 0
)
(
input clk,
input rstn,
input [XLEN-1:0] opA,
input [XLEN-1:0] opB,
input [XLEN-1:0] opR,
input en
);
generate
case(USEIP)
0:begin
always @(posedge clk or negedge rstn)
begin
if(!rstn)
begin
opR <= '{default:0};
end
else
begin
if(en)
opR <= opA+opB;
else
opR <= '{default:0};
end
end
end
1:begin
superAdder #(.XLEN(XLEN)) _adder(.clk(clk),.rstm(rstn), .opA(opA), .opB(opB), .opR(opR), .en(en));
end
endcase
endmodule