找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3731|回复: 0
收起左侧

同步FIFO的Verilog实现

[复制链接]
ID:105323 发表于 2016-2-23 01:19 | 显示全部楼层 |阅读模式
转了一篇别人写的,没看一眼代码,因为最不喜欢的就是看别人写的代码。今天抽空自己写了一段小代码,在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


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表