Premier in-premier (FIFO) en utilisant Verilog
-
21-12-2019 - |
Question
Bonjour j'ai vraiment besoin d'aide avec cette parce que c'est de me conduire fou, je suis fou d'utiliser Spartan 3e et ci-dessous est le fichier .V pour FIFO et après ce fichier .ucff ... je me demande simplement pourquoi je ne peux pas écrire / lire à la mémoire mêmeBien que je n'obtiens aucune erreur lorsque je génère le fichier binaire et programmez le FPGA !!
module fifo (
input [3:0] data_in,
input clk, rst, rd, wr,
output empty, full,
output reg [3:0] fifo_cnt,
output reg [3:0] data_out
);
reg [3:0] fifo_ram[0:7];
reg [2:0] rd_ptr, wr_ptr;
assign empty = (fifo_cnt==0);
assign full = (fifo_cnt==8);
always @( posedge clk )
begin: write
if(wr && !full) fifo_ram[wr_ptr] <= data_in;
else if(wr && rd) fifo_ram[wr_ptr] <= data_in;
end
always @( posedge clk )
begin: read
if(rd && !empty)
data_out <= fifo_ram[rd_ptr];
else if(rd && wr && empty)
data_out <= fifo_ram[rd_ptr];
end
always @( posedge clk )
begin: pointer
if( rst )
begin
wr_ptr <= 0;
rd_ptr <= 0;
end
else
begin
wr_ptr <= ((wr && !full)||(wr && rd)) ? wr_ptr+1 : wr_ptr;
rd_ptr <= ((rd && !empty)||(wr && rd)) ? rd_ptr+1 : rd_ptr;
end
end
always @( posedge clk )
begin: count
if( rst )
fifo_cnt <= 0;
else
begin
case ({wr,rd})
2'b00 : fifo_cnt <= fifo_cnt;
2'b01 : fifo_cnt <= (fifo_cnt==0) ? 0 : fifo_cnt-1;
2'b10 : fifo_cnt <= (fifo_cnt==8) ? 8 : fifo_cnt+1;
2'b11 : fifo_cnt <= fifo_cnt;
default: fifo_cnt <= fifo_cnt;
endcase
end
end
endmodule
# ==== Clock Source ====
NET "clk" LOC = "C9" | IOSTANDARD = LVCMOS33;
NET "clk" PERIOD = 5ns HIGH 40%;
NET "rst" LOC "D18" | IOSTANDARD = LVTTL | PULLDOWN ;
NET "wr" LOC "H13" | IOSTANDARD = LVTTL | PULLDOWN ;
NET "rd" LOC "K17" | IOSTANDARD = LVTTL | PULLDOWN ;
# ==== Slide Switches (SW) ====
NET "data_in<0>" LOC = "L13" | IOSTANDARD = LVTTL | PULLUP ; #// SW1
NET "data_in<1>" LOC = "L14" | IOSTANDARD = LVTTL | PULLUP ; #// SW2
NET "data_in<2>" LOC = "H18" | IOSTANDARD = LVTTL | PULLUP ; #// SW3
NET "data_in<3>" LOC = "N17" | IOSTANDARD = LVTTL | PULLUP ; #// SW4
# ==== Discrete LEDs (LED) ====
NET "data_out<3>" LOC = "F11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
NET "data_out<2>" LOC = "E11" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
NET "data_out<1>" LOC = "E12" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
NET "data_out<0>" LOC = "F12" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
NET "empty" LOC "E9" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
NET "full" LOC "F9" | IOSTANDARD = LVTTL | SLEW = SLOW | DRIVE = 8 ;
La solution
D'accord, j'ai essayé ceci sur un tableau de Deug-nano qui utilise une partie d'altera cyclone IV et a été capable de le faire fonctionner. Votre logique est donc bonne. La seule chose que j'ai ajoutée est une détection de bord pour les signaux RD et WR.
Avec votre code actuel (et mon tableau) lorsque vous appuyez sur un commutateur, je reçois de nombreuses lectures ou écrites contiguës. Donc, une simple pression de l'interrupteur WR remplirait la FIFO et une simple pression de l'interrupteur de lecture viderait la FIFO.
J'ai renommé votre signal d'entrée RD sur rd_in et le signal WR sur wr_in et ajouté le code suivant:
always @( posedge clk )
begin: edge_detect
rd_in_d <= rd_in;
wr_in_d <= wr_in;
rd = (rd_in && !rd_in_d);
wr = (wr_in && !wr_in_d);
end
qui vous donnera une seule pulsation RD / WR uniquement lorsqu'un bord montant des signaux RD_IN ou WR_IN est détecté.
Assurez-vous que vos signaux de commutation sont faibles lorsque le commutateur n'est pas enfoncé car il apparaît que vous supposez. Sur mon tableau, les entrées de commutation sont toujours élevées (résistances à pull-up) et ne vont que si le commutateur est enfoncé. Étant donné qu'une presse de l'interrupteur crée une condition logique basse, je devais inverser les signaux RD / WR pour les amener à fonctionner correctement avec votre code.
J'espère que cela vous aidera!