web-dev-qa-db-fra.com

Verilog gener/genvar dans un bloc always

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.

12
user1684538

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.

16
Andy

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
5
Greg

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
2
Morgan

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
2
user597225

pour verilog juste faire

parameter ROWBITS = 4;
reg [ROWBITS-1:0] temp;
always @(posedge sysclk) begin
  temp <= {ROWBITS{1'b0}}; // fill with 0
end
0
manu

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
0