Générer Si les Déclarations en Verilog
Je suis en train de créer un synthesizable, paramétrées, la priorité de l'encodeur en Verilog. Plus précisément, je veux trouver le moins significatif de 1 dans le vecteur et le retour d'un vecteur contenant que des 1. Par exemple:
IN[3:0] | OUT[4:0]
--------+---------
1010 | 00010
1111 | 00001
0100 | 00100
0000 | 10000 (special case)
Donc, si les vecteurs sont de quatre bits, le code est:
if (in[0]==1'b1) least_one = 1;
else if (in[1]==1'b1) least_one = 2;
else if (in[2]==1'b1) least_one = 4;
else if (in[3]==1'b1) least_one = 8;
else out = 16; //special case in==0, set carry bit
J'ai besoin d'un général, de manière évolutive pour ce faire, car l'entrée/sortie longueur du vecteur est paramétrisée. Mon code actuel est:
module least_one_onehot
#(parameter ADDR_WIDTH=4)
(output reg [ADDR_WIDTH:0] least_one,
input [ADDR_WIDTH-1:0] in);
genvar i;
always @(in) begin
if (in[0]==1'b1) least_one = 1;
generate for (i=1; i<ADDR_WIDTH; i=i+1) begin : U
else if (in[i]==1'b1) least_one = 2**i;
end
endgenerate
else least_one = 2**ADDR_WIDTH;
end
endmodule
Lorsque j'essaie de compiler cela, je reçois l'erreur suivante:
file: least_one_onehot.v
generate for (i=1; i<ADDR_WIDTH; i=i+1) begin : U
|
ncvlog: *E,GIWSCP (least_one_onehot.v,10|8): Generated instantiation can only be valid within a module scope [12.1.3(IEEE 2001)].
else if (in[i]==1'b1) least_one = 2**i;
|
ncvlog: *E,NOTSTT (least_one_onehot.v,11|6): expecting a statement [9(IEEE)].
endgenerate
|
ncvlog: *E,GIWSCP (least_one_onehot.v,13|12): Generated instantiation can only be valid within a module scope [12.1.3(IEEE 2001)].
else least_one = 2**ADDR_WIDTH;
|
ncvlog: *E,NOTSTT (least_one_onehot.v,14|5): expecting a statement [9(IEEE)]
J'ai essayé les diverses dispositions de la générer, si, et toujours déclarations, le tout sans succès. Quelqu'un connais la syntaxe correcte pour cela? Cas de déclaration de mise en œuvre ou d'autres solutions de rechange serait aussi bien. Merci.
out
?Il y a une différence entre la procédure de contextes et de module de contextes. Voir this réponse.
Devrait être un peu plus large que d'en accueillir de zéro pour tous les cas. J'ai précisé le post original.
OriginalL'auteur DrDean | 2013-02-25
Vous devez vous connecter pour publier un commentaire.
Je pense que vous ne comprenez pas comment générer des œuvres. Ce n'est pas un texte pré-processeur qui émet le code à générer/endgenerate paire avec des substitutions appropriées. Vous avez une totale syntaxique des entités à l'intérieur de la paire. Je n'ai pas accès à un simulateur en ce moment, mais cela pourrait faire l'affaire pour vous (totalement non testé)
Ordinairement Verilog se plaignaient de la non-constant bit largeur tranche mais depuis qu'il est au sein d'un générer une boucle, elle pourrait fonctionner.
À défaut de quelque chose comme ci-dessus vous reste plus qu'à tester pour le premier ensemble de bits dans une boucle for et puis décoder ce résultat.
assign
à tous lesleast_one[N] =
consolidés. Sinon, votre code ressemble à compiler correctement.Magnuson: Une inefficacité dans ce code (qui ne devient apparent lorsque
ADDR_WIDTH
devient grand), c'est que sa taille est de O(N log N) où N=ADDR_WIDTH
. Le calcul deleast_one
peut très facilement être formulé comme un parallèle préfixe de calcul ce qui rend la taille de la conception de O(N). Fondamentalement, il exploite le fait que les termes|in[i-1:0]
ont bien la logique en commun.Quand je fais face à un problème comme celui-ci (en particulier lorsque le bit largeur est grande), où il est difficile d'écrire le parallèle préfixe calcul logique dans un
generate
déclaration, j'utilise un (paramétrable), le script Perl pour générer le SystemVerilog code et à l'appeler dans un Makefile avant que je compile pour la simulation ou de synthèse.OriginalL'auteur Brian Magnuson
Vous ne pas besoin de générer un bloc. Vous pouvez utiliser:
Si vous voulez vraiment utiliser un générer le bloc, vous devez attribuer à chaque bit.
OriginalL'auteur Greg
Personnellement, j'aime bien le bloc de code suivant pour ce dont vous avez besoin:
attribuer out = {1'b1,en} & ((~{1'b1,en})+1);
Vous pouvez essayer ce (chute de la très haute bits pour la lisibilité), mais j'aime explicitement faire les deux compliment pour éviter d'éventuels problèmes de compatibilité.
attribuer out = en & (-1*);
OriginalL'auteur jelman