FIFO的verilog代码

    FIFO是英文First In First Out 的缩写,是一种先进先出的数据缓存器,他与普通存储器的区别是没有外部读写地址线,这样使用起来非常简单,但缺点就是只能顺序写入数据,顺序的读出数据,其数据地址由内部读写指针自动加1完成,不能像普通存储器那样可以由地址线决定读取或写入某个指定的地址。
FIFO的一些重要参数
 1、FIFO的宽度:也就是英文资料里常看到的THE WIDTH,它指的是FIFO一次读写操作的数据位,就像MCU有8位和16位,ARM 32位等等。
 2、FIFO的深度:THE DEEPTH,它指的是FIFO可以存储多少个N位的数据(如果宽度为N)。如一个8位的FIFO,若深度为8,它可以存储8个8位的数据,深度为12 ,就可以存储12个8位的数据。
    3、满标志:FIFO已满或将要满时由FIFO的状态电路送出的一个信号,以阻止FIFO的写操作继续向FIFO中写数据而造成溢出(overflow)。
    4、空标志:FIFO已空或将要空时由FIFO的状态电路送出的一个信号,以阻止FIFO的读操作继续从FIFO中读出数据而造成无效数据的读出(underflow)。
 5、读指针:指向下一个读出地址。读完后自动加1。

 6、写指针:指向下一个要写入的地址的,写完自动加1。


     对于FIFO,读写指针都指向一个内存的初始位置,每进行一次读写操作,相应的指针就递增一次,指向下一个内存位置。当指针移动到了内存的最后一个位置时,它又重新跳回初始位置。在FIFO非满或非空的情况下,这个过程将随着读写控制信号的变化一直进行下去。如果FIFO处于空的状态,下一个读动作将会导致向下溢(underflow),一个无效的数据被读人;同样,对于一个满了的FIFO,进行写动作将会导致向上溢出(overflow),一个有用的数据被新写入的数据覆盖。这两种情况都属于误动作,因此需要设置满和空两个信号,对满信号置位表示FIFO处于满状态,对满信号复位表示FIFO非满,还有空间可以写入数据;对空信号置位表示FIFO处于空状态,对空信号复位表示FIFO非空,还有有效的数据可以读出。

/**************************************
* Module: fifo
* Date:2014-08-10  
* Author: hemmingway@163.com     
*
* Description: FIFO存储器设计
***************************************/
module  fifo(clk,rstp,din,writep,readp,dout,emptyp,fullp
);
input           clk;
input           rstp;      // 复位信号
input[15:0]     din;
input           readp;
input           writep;
output[15:0]    dout;
output          emptyp;
output          fullp;
parameter       DEPTH = 2,
                MAX_COUNT=2'b11;      //定义地址最大值
               
reg             emptyp;
reg             fullp;
reg[15:0]       dout;
reg[(DEPTH-1):0]    tail;
reg[(DEPTH-1):0]    head;
reg[(DEPTH-1):0]    count;
reg[15:0]           fifomem[0:MAX_COUNT];       //  定义fifo存储器,4个16位的存储器

// dout被赋给tail指针指向的数值
always @(posedge clk)  begin
  if(rstp==1) begin
    dout <= 16'h0000;       // 复位信号有效置0
  end
  else begin
    dout <= fifomem[tail];   //将fifomem中第tail个单元给dout
  end
end

// 写入数据
always @(posedge clk) begin
    if(rstp==1'b0 && writep == 1'b1 && fullp == 1'b0) begin
        fifomem[head]<=din;      // 写入
    end
end

// head指针递增
always @(posedge clk) begin
    if(rstp==1'b1) begin
        head<=2'b00;
    end
    else begin
        if(writep==1'b1 && fullp==1'b0) begin
        head<=head+1;
        end
    end
end

//tail指针递增
always @(posedge clk) begin
    if(rstp==1'b1) begin
        tail<=2'b00;
    end
    else begin
        if(readp==1'b1 && emptyp==1'b0) begin
        tail<=tail+1;
        end
    end
end

// 计数器
always @(posedge clk) begin
   if (rstp == 1'b1) begin
      count <= 2'b00;
   end
   else begin
      case ({readp, writep})
         2'b00: count <= count;
         2'b01: 
            if (count != MAX_COUNT) 
               count <= count + 1;     //为写状态时计数器进行加法计数
         2'b10: 
            if (count != 2'b00)
               count <= count - 1;    //为读状态计数器进行减法计数
         2'b11:
           count <= count;
      endcase
   end
end

// empty指针
always @(count) begin
   if (count == 2'b00)
      emptyp <= 1'b1;      //count为0时emptyp赋为1
   else
      emptyp <= 1'b0;
end

// fullp指针
always @(count) begin
   if (count == MAX_COUNT)
      fullp <= 1'b1;                     //计数到最大时fullp赋为1
   else
      fullp <= 1'b0;
end

endmodule




/**************************************
* Module: test_fifo
* Date:2014-08-10  
* Author: hemmingway@163.com     
*
* Description: FIFO测试程序
***************************************/
module  test_fifo;

reg         clk;
reg         rstp;
reg [15:0]  din;
reg         readp;
reg         writep;
wire [15:0] dout;
wire        emptyp;
wire        fullp;

reg [15:0]  value;
fifo U1 (.clk(clk),.rstp(rstp),.din(din),.readp(readp),.writep(writep),.dout(dout),
   .emptyp(emptyp),.fullp(fullp));

// 读任务
task read_word;
begin
   @(negedge clk);
   readp = 1;
   @(posedge clk) #5;
   readp = 0;
end
endtask
   
// 写任务
task write_word;
input [15:0]    value;
begin
   @(negedge clk);
   din = value;
   writep = 1;
   @(posedge clk);
   #5;
   din = 16'hzzzz;
   writep = 0;
end
endtask


initial begin
   clk = 0;
   forever begin
      #10 clk = 1;
      #10 clk = 0;
   end
end


initial begin
 //test1;
   test2;  //调用测试模块2
end


task test1;
begin
   din = 16'hzzzz;
   writep = 0;
   readp = 0;
   rstp = 1;
   #50 rstp = 0;
   #50;
   write_word (16'h1111);
   write_word (16'h2222);
   write_word (16‘h3333);   //写入3个数据
   read_word;
   read_word;               //读两个
   write_word (16‘h4444);   //在写一个数据
   repeat (6) begin
      read_word;
end
   write_word (16'h0001);
   write_word (16'h0002);
   write_word (16'h0003);
   write_word (16'h0004);
   write_word (16'h0005);
   write_word (16'h0006);
   write_word (16'h0007);
   write_word (16'h0008);
repeat (6) begin
      read_word;
   end
end
endtask


task test2;
reg [15:0] writer_counter;
begin
   writer_counter = 16'h0001;
   din = 16'hzzzz;
   writep = 0;
   readp = 0;
   rstp = 1;
   #50   rstp = 0;
   #50;
   fork
     //写数据
    begin
         repeat (500) begin
            @(negedge clk);
            if (fullp == 1'b0) begin
               write_word (writer_counter);
               #5;
               writer_counter = writer_counter + 1;
            end
               #50;
         end
    end
      //读数据
      begin
         forever begin
            @(negedge clk);
            if (emptyp == 1'b0) begin
               read_word;
            end  
          #50;
         end
      end
   join
end
endtask


endmodule


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值