原创 同步FIFO的Verilog实现 (转自:快乐丢丢)

2014-9-10 11:20 1425 19 19 分类: FPGA/CPLD
转了一篇别人写的,没看一眼代码,因为最不喜欢的就是看别人写的代码。今天抽空自己写了一段小代码,在ModelSim中仿真了,结果还是正确的。
 
module chipfifo(clk,rst,wr,din,rd,dout,full,empty,half_full);
 
input clk,rst;
input wr,rd;
input [7:0] din;
output [7:0] dout;
output full,empty,half_full;
 
reg [7:0] dout;
reg [4:0] cnt_rd;     //读数据指示器
reg [4:0] cnt_wr;     //写数据指示器
reg [4:0] cnt_data;   //数据个数指示器
reg [7:0] fiforam[15:0];    //FIFO存储数组
 
reg empty,full,half_full;
 
always @ (posedge clk or negedge rst)
begin
 if(!rst)    //异步复位
 begin
  cnt_rd<=5'd0;
  cnt_wr<=5'd0;
  cnt_data<=5'd0;
  full<=1'd0;
  empty<=1'd0;
  half_full<=1'd0;  
 end
 else
 begin
  case({rd,wr})
  2'b01:     //只写操作
  begin
   if(!full)   //FIFO没有写满,则执行写操作
   begin
    if(cnt_data==5'd16)   //FIFO中已经有15个数据,再写就满了
    begin
     fiforam[cnt_wr-1]<=din;
     cnt_data<=cnt_data;
     full<=1'd1;       
     cnt_wr<=4'd0;
    end
    else 
    begin
     fiforam[cnt_wr-1]<=din;
     cnt_data<=cnt_data+5'd1;
     full<=1'd0;       
     if(cnt_wr==5'd16)
      cnt_wr<=4'd1;
     else
      cnt_wr<=cnt_wr+5'd1;
    end
    
    if(cnt_wr==5'd8)  //半满标志
     half_full<=1'd1;
    else
     half_full<=1'd0;
    
    empty<=1'd0;     //只写时空标志为0
   end
   else
   begin
    cnt_rd<=cnt_rd;
    cnt_wr<=cnt_wr;
    cnt_data<=cnt_data;
    full<=full;
    empty<=empty;
    half_full<=half_full;  
   end
  end
  2'b10:  //只读操作
  begin
   if(!empty)   //FIFO没有读空,则执行读操作
   begin
    if(cnt_data==5'd0)   //FIFO中只有1个数据,再读就空了
    begin
     dout<=fiforam[cnt_rd-1];
     cnt_data<=cnt_data;
     empty<=1'd1;             
     cnt_rd<=5'd0;
    end
    else 
    begin
     dout<=fiforam[cnt_rd-1];
     cnt_data<=cnt_data-5'd1;
     empty<=1'd0;       
     if(cnt_rd==5'd16)
      cnt_rd<=5'd0;
     else
      cnt_rd<=cnt_rd+5'd1;
    end
    full<=1'd0;     //只写时空标志为0
   end
   else
   begin
    cnt_rd<=cnt_rd;
    cnt_wr<=cnt_wr;
    cnt_data<=cnt_data;
    full<=full;
    empty<=empty;
    half_full<=half_full; 
   end
  end
  2'b11:     //读写同时进行
  begin
   case({full,empty})
   2'b00:          //既没有写满也没有读空的情况
   begin
    dout<=fiforam[cnt_rd-1];
    if(cnt_rd==5'd16)   //如果指示器到最后了,则转到开始
     cnt_rd<=5'd1;
    else
     cnt_rd<=cnt_rd+5'd1;
     
    fiforam[cnt_wr-1]<=din;      
    if(cnt_wr==5'd16)
     cnt_wr<=5'd1;
    else
     cnt_wr<=cnt_wr+5'd1;    
   end
   2'b01:   //没有写满,但已读空的情况
   begin
    dout<=din;
   end
   2'b10:   //写满的情况
   begin
    dout<=fiforam[cnt_rd-1];
    if(cnt_rd==5'd16)   //如果指示器到最后了,则转到开始
     cnt_rd<=4'd0;
    else
     cnt_rd<=cnt_rd+4'd1;
     
    fiforam[cnt_wr-1]<=din;      
    if(cnt_wr==5'd16)
     cnt_wr<=4'd0;
    else
     cnt_wr<=cnt_wr+4'd1;    
   end
   endcase
  end
  default: 
  begin
   cnt_rd<=cnt_rd;
   cnt_wr<=cnt_wr;
   cnt_data<=cnt_data;
   full<=full;
   empty<=empty;
   half_full<=half_full;  
  end
  endcase
 end
end
 
endmodule

文章评论0条评论)

登录后参与讨论
我要评论
0
19
关闭 站长推荐上一条 /2 下一条