Primero en primer puesto (FIFO) usando Verilog
-
21-12-2019 - |
Pregunta
Hola, realmente necesito ayuda con este Cuz que me conduce loco, estoy usando Spartan 3e y debajo está el archivo .v para FIFO y después de ese archivo .UCF ... me estoy preguntando por qué no puedo escribir / leer a la memoria inclusoAunque no obtengo errores cuando genere el archivo binario y programo el 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 ;
Solución
Bien, lo intenté en un tablero de0-nano que usa una parte de Altera Cyclone IV y pudo hacer que funcione, por lo que su lógica es buena. Lo único que hice agregó es una detección de borde para las señales RD y WR.
Con su código actual (y mi tablero) cuando presione un interruptor que recibí muchas lecturas o escrituras contiguos. Por lo tanto, una sola presión del interruptor WR llenaría el FIFO y una sola presión del interruptor de lectura vaciaría el FIFO.
Rebautimos su señal de entrada RD a RD_IN y la señal WR para WR_IN y agregó el siguiente código:
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
que le dará un solo pulso RD / WR solo cuando se detecta un borde ascendente de las señales RD_IN o WR_IN.
Asegúrese de que las señales de su interruptor sean bajas cuando el interruptor no esté deprimido, ya que parece que está asumiendo. En mi tabla, las entradas del interruptor son siempre altas (resistencias de pull-up) y solo se vuelven bajas cuando se presiona el interruptor. Dado que una prensa del conmutador crea una condición lógica baja, tuvo que invertir las señales RD / WR para que funcionen correctamente con su código.
espero que esto ayude!