使用verilog的先进先出(FIFO)

时间:2014-06-04 01:18:49

标签: memory cpu verilog cpu-architecture hdl

你好我真的需要帮助这个因为它驱使我疯狂使用Spartan 3E和以下是FIFO的.v文件和之后.ucf文件...我只是想知道为什么我不能写/读到内存甚至虽然我生成二进制文件并编程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 ;

1 个答案:

答案 0 :(得分:1)

好的,我在de0-nano电路板上尝试了这个,它使用Altera Cyclone IV器件并且能够使它工作,所以你的逻辑很好。我添加的一件事是对rd和wr信号进行边缘检测。

当您按下开关时,使用当前代码(和我的电路板),我得到了许多连续的读取或写入。因此,只需按一下wr开关即可填充fifo,只需按一下读取开关即可清空fifo。

我将您的rd输入信号重命名为rd_in,将wr信号重命名为wr_in并添加以下代码:

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

只有在检测到rd_in或wr_in信号的上升沿时才会给你一个rd / wr脉冲。

当您没有按下开关时,请确保您的开关信号为低电平,如您所假设的那样。在我的电路板上,开关输入始终为高电平(上拉电阻),仅在按下开关时变为低电平。由于按下开关会产生逻辑低电平状态,因此我必须将rd / wr信号反转,以使它们与您的代码一起正常工作。

希望这有帮助!