【FPGA】基于verilog复杂逻辑电路设计——FIFO存储器设计

本文介绍了FIFO(FirstInFirstOut)的概念,包括其工作原理、重要参数如宽度、深度、满标志和空标志。接着,通过一个Verilog模块展示了FIFO存储器的设计,包括读写指针的管理以及满空标志的检测。最后,提供了一个测试程序用于验证FIFO的功能。
摘要由CSDN通过智能技术生成

目录

1.1 FIFO概述

1.2 FIFO存储器的设计

1.3测试程序


1.1 FIFO概述

          FIFO是英文First In First Out 的缩写,是一种先进先出的数据缓存器,他与普通存储器的区别是没有外部读写地址线,这样使用起来非常简单,但缺点就是只能顺序写入数据,顺序的读出数据,其数据地址由内部读写指针自动加1完成,不能像普通存储器那样可以由地址线决定读取或写入某个指定的地址。

FIFO的一些重要参数

     FIFO的宽度:也就是英文资料里常看到的THE WIDTH,它指的是FIFO一次读写操作的数据位,就像MCU8位和16位,ARM 32位等等。

   FIFO的深度:THE DEEPTH,它指的是FIFO可以存储多少个N位的数据(如果宽度为N)。如一个8位的FIFO,若深度为8,它可以存储88位的数据,深度为12 ,就可以存储128位的数据。

    满标志:FIFO已满或将要满时由FIFO的状态电路送出的一个信号,以阻止FIFO的写操作继续向FIFO中写数据而造成溢出(overflow)。

    空标志:FIFO已空或将要空时由FIFO的状态电路送出的一个信号,以阻止FIFO的读操作继续从FIFO中读出数据而造成无效数据的读出(underflow)。

 读指针:指向下一个读出地址。读完后自动加1

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

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

1.2 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]; //定义fifomem存储器有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

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

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

always @(count) begin

   if (count == 2'b00)

      emptyp <= 1‘b1;      //count为0时emptyp赋为1

   else

      emptyp <= 1'b0;

end





always @(count) begin

   if (count == MAX_COUNT)

      fullp <= 1‘b1;                     //计数到最大时fullp赋为1

   else

      fullp <= 1'b0;

end



endmodule

1.3测试程序

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
发出的红包

打赏作者

Simuworld

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值