2017-01-30 6 views
0

Je suis un débutant dans Verilog essayant de créer un fichier de registre qui contient des registres 32 bits. Je suis capable d'écrire et de lire tout correctement, cependant, le premier registre (appelons-le R0) qui est à l'adresse 5'b00000 doit toujours être égal à 0 et ne doit pas être modifié à tout moment. En le lisant sur un banc d'essai, le problème survient lorsque R0 devient soudainement "xxxxxxxx" au lieu d'être 0 ou 00000000. Le reste des registres a été lu correctement. Que puis-je faire de mal dans le code et quelle pourrait être la solution de contournement pour celui-ci? Voici le code:Attribuer le premier registre à zéro et ne pas écrire

module regfile (
    clk, 
    nrst, 
    rd_addrA, 
    rd_addrB, 
    wr_addr, 
    wr_en, 
    wr_data, 
    rd_dataA, 
    rd_dataB 
); 

//Input and output ports 
input wire clk; 
input wire nrst; 
input wire [4:0] rd_addrA; 
input wire [4:0] rd_addrB; 
input wire [4:0] wr_addr; 
input wire wr_en; 
input wire [31:0] wr_data; 
output reg [31:0] rd_dataA; 
output reg [31:0] rd_dataB; 

reg [31:0] regfile[0:31]; 
integer i; 

always @ (nrst) 
    begin: RESET 
     if(nrst == 0) begin 
      for(i = 0; i < 32; i++) begin 
       regfile[i] = 0; 
      end 
     end 
    end 

always @(rd_addrA or rd_addrB) 
    begin: READ 
     if(rd_addrA) begin 
      case (rd_addrA) 
       5'b00000: rd_dataA = regfile[0]; 
       5'b00001: rd_dataA = regfile[1]; 
       5'b00010: rd_dataA = regfile[2]; 
       5'b00011: rd_dataA = regfile[3]; 
       5'b00100: rd_dataA = regfile[4]; 
       5'b00101: rd_dataA = regfile[5]; 
       5'b00110: rd_dataA = regfile[6]; 
       5'b00111: rd_dataA = regfile[7]; 
       5'b01000: rd_dataA = regfile[8]; 
       5'b01001: rd_dataA = regfile[9]; 
       5'b01010: rd_dataA = regfile[10]; 
       5'b01011: rd_dataA = regfile[11]; 
       5'b01100: rd_dataA = regfile[12]; 
       5'b01101: rd_dataA = regfile[13]; 
       5'b01110: rd_dataA = regfile[14]; 
       5'b01111: rd_dataA = regfile[15]; 
       5'b10000: rd_dataA = regfile[16]; 
       5'b10001: rd_dataA = regfile[17]; 
       5'b10010: rd_dataA = regfile[18]; 
       5'b10011: rd_dataA = regfile[19]; 
       5'b10100: rd_dataA = regfile[20]; 
       5'b10101: rd_dataA = regfile[21]; 
       5'b10110: rd_dataA = regfile[22]; 
       5'b10111: rd_dataA = regfile[23]; 
       5'b11000: rd_dataA = regfile[24]; 
       5'b11001: rd_dataA = regfile[25]; 
       5'b11010: rd_dataA = regfile[26]; 
       5'b11011: rd_dataA = regfile[27]; 
       5'b11100: rd_dataA = regfile[28]; 
       5'b11101: rd_dataA = regfile[29]; 
       5'b11110: rd_dataA = regfile[30]; 
       5'b11111: rd_dataA = regfile[31]; 
       default: rd_dataA = 16'hXXXX; 
      endcase 
     end 

     if(rd_addrB) begin 
      case (rd_addrB) 
       5'b00000: rd_dataB = regfile[0]; 
       5'b00001: rd_dataB = regfile[1]; 
       5'b00010: rd_dataB = regfile[2]; 
       5'b00011: rd_dataB = regfile[3]; 
       5'b00100: rd_dataB = regfile[4]; 
       5'b00101: rd_dataB = regfile[5]; 
       5'b00110: rd_dataB = regfile[6]; 
       5'b00111: rd_dataB = regfile[7]; 
       5'b01000: rd_dataB = regfile[8]; 
       5'b01001: rd_dataB = regfile[9]; 
       5'b01010: rd_dataB = regfile[10]; 
       5'b01011: rd_dataB = regfile[11]; 
       5'b01100: rd_dataB = regfile[12]; 
       5'b01101: rd_dataB = regfile[13]; 
       5'b01110: rd_dataB = regfile[14]; 
       5'b01111: rd_dataB = regfile[15]; 
       5'b10000: rd_dataB = regfile[16]; 
       5'b10001: rd_dataB = regfile[17]; 
       5'b10010: rd_dataB = regfile[18]; 
       5'b10011: rd_dataB = regfile[19]; 
       5'b10100: rd_dataB = regfile[20]; 
       5'b10101: rd_dataB = regfile[21]; 
       5'b10110: rd_dataB = regfile[22]; 
       5'b10111: rd_dataB = regfile[23]; 
       5'b11000: rd_dataB = regfile[24]; 
       5'b11001: rd_dataB = regfile[25]; 
       5'b11010: rd_dataB = regfile[26]; 
       5'b11011: rd_dataB = regfile[27]; 
       5'b11100: rd_dataB = regfile[28]; 
       5'b11101: rd_dataB = regfile[29]; 
       5'b11110: rd_dataB = regfile[30]; 
       5'b11111: rd_dataB = regfile[31]; 
       default: rd_dataB = 16'hXXXX; 
      endcase 
     end 
    end 

always @ (posedge clk) 
    begin: WRITE 
     if(wr_en == 1'b1) begin 
      if(wr_addr != 5'd0) begin 
       regfile[wr_addr] = #1 wr_data; 
       //$display("%X", regfile[wr_addr]); 
      end 
      else begin 
       $display("R0: %X", regfile[wr_addr]); 
      end 
     end 
    end 

endmodule 

Merci beaucoup pour l'aide.

+0

Publiez votre code testbench pour voir le timing de vos signaux d'entrée. – toolic

+0

Vous devriez également avoir une condition initiale si vous voulez que le registre contienne une valeur, quoi qu'il arrive. Cela garantit que si le GSR ou votre réinitialisation n'est pas atteint pour une raison quelconque, votre 'R0' contiendra la valeur zéro. –

Répondre

1

if(rd_addrA) est interprété comme if(rd_addrA>0). Par conséquent, lire regfile[0] inaccessible. Comme toutes les entrées sont valides, vous ne devriez pas avoir besoin de l'instruction if.

Autres questions non liées à votre question principale:

Votre code est synthétisable pas parce que regfile est affecté dans deux blocs toujours. Vous devez fusionner la réinitialisation et écrire regfile dans un bloc toujours. always @(posedge clk) pour la réinitialisation synchrone (recommencé pour FPGA). always @(posedge clk or negedge nrst) pour la réinitialisation asynchrone (recommencé pour ASIC).

La spécification de la sensibilité dans les blocs combinatoires est un style ancien qui n'est demandé que pour l'édition 1995. Depuis 2001, la sélectivité automatique (always @* ou always @(*)) est le moyen idéal pour démarrer des blocs combinatoires. Les recommandations de style d'en-tête de module ont également changé depuis le Verilog-1995, donc vous devriez lire cela aussi. Le style Verilog-1995 est toujours valide et supporté; juste n'est plus parfait.

La logique synchrone (également appelée regs par une horloge ou une validation de verrouillage) doit être affectée d'affectations non bloquantes (<=). Vous courez un risque plus élevé de correspondance comportementale entre RTL et les portes si vous n'utilisez pas l'assignation bloquante et non bloquante de manière appropriée.

Vos instructions de requête peuvent être simplifiées en une seule ligne: rd_dataA = regfile[rd_addrA];. Mais vérifiez vos résultats synthétisés car certains synthétiseurs n'optimisent pas aussi bien avec ce style qu'avec une déclaration de cas.

+0

pourquoi recommandez-vous la réinitialisation synchrone dans les FPGA. Je pensais qu'une réinitialisation asynchrone était la technique recommandée pour les FPGA et les ASIC – Prashant

+0

La plupart des FPGA ont un nombre limité de flops avec réinitialisation/préréglage asynchrone (le cas échéant); au moins ceux accessibles au concepteur. Les FPGA utilisent généralement des blocs 'initial' pour définir la valeur de réinitialisation à la mise sous tension. Les synthétiseurs ASIC ignorent typiquement les blocs 'initiales ', ce qui explique l'utilisation de la réinitialisation asynchrone. – Greg

+0

Je devrais préciser que la réinitialisation asynchrone devrait surtout être utilisée pour la réinitialisation à la mise sous tension. Pendant les opérations normales, la réinitialisation synchrone est recommandée pour la plupart des scénarios. Exemple: un compteur ne doit jamais se réinitialiser de manière asynchrone (problèmes de méta-stabilité). – Greg