zoukankan      html  css  js  c++  java
  • Verilog学习笔记简单功能实现(八)...............同步FIFO

    Part 1,功能定义:

     用16*8 RAM实现一个同步先进先出(FIFO)队列设计。由写使能端控制该数据流的写入FIFO,并由读使能控制FIFO中数据的读出。写入和读出的操作(高电平有效)由时钟的上升沿触发。当FIFO的数据满和空的时候分别设置相应的高电平加以指示。FIFO是英文First In First Out 的缩写,是一种先进先出的数据缓存器,它与普通存储器的区别是没有外部读写地址线,这样使用起来非常简单,但缺点就是只能顺序写入数据,顺序的读出数据,其数据地址由内部读写指针自动加1完成,不能像普通存储器那样可以由地址线决定读取或写入某个指定的地址。

    所谓同步FIFO是指读时钟和写时钟采用同一个时钟。同时,异步FIFO就是指读写时钟不一致。

    Part 2.顶层信号定义: 

    信号名称

    I/O

    功能描述

    源/目标

    备注

    Rst

    In

    全局复位(低有效)

    管脚

     

    Clk

    In

    全局时钟

    管脚

    频率10Mhz;占空比:50%

    W_en

    In

    高有效写使能

    管脚

     

    R_en

    In

    高有效读使能

    管脚

     

    Data_in[7:0] 

    In

    数据输入端

    管脚

     

    Data_out[7:0]

    Out

    数据输出端

    管脚

     

    Empty

    Out

    空指示信号

    管脚

    为高时表示fifo空

    Full

    Out

    满指示信号

    管脚

    为高时表示fifo满

     

     

     

     

     

     

     

     

     

     

     

     

     


      

     

    Part 3.顶层模块即划分: 

    该同步fifo可划分为如下四个模块,如图所示:

    ①存储器模块(RAM)    ——用于存放及输出数据;

    ②读地址模块(r_addr)  ——用于读地址的产生;

    ③写地址模块(w_addr)——用于写地址的产生

    ④标志模块(flag_gen) ---- 用于产生FIFO当前空满状态。

     

     

    Part 4.RAM块: 

    RAM块的源码 

    本设计中采用16*8的双扣RAM,以循环读写的方式实现。

    根据r_addr模块产生的读地址在,读使能(ren==1)时,将r_addr[4:0]地址中的对应单元的数据在时钟上升沿到来时,读出到data_out[7:0]中;

    根据w_addr模块产生的写地址,在写实能(wen==1)时,在时钟沿的上升沿到来时,将data_in[7:0]中的数据写入到w_addr[4:0]地址对应的单元。

     1 //16*8 RAM define (七个端口)
     2 module RAM(clk,ren,wen,r_addr,w_addr,data_in,data_out);
     3   input clk,ren,wen;
     4   input [4:0]r_addr,w_addr;
     5   input [7:0]data_in;
     6   output [7:0]data_out;
     7   reg [7:0]data_out;
     8   reg [7:0]fifo[15:0];
     9   always @(posedge clk)
    10   begin
    11   if(ren==1)
    12   begin data_out<=fifo[r_addr]; end
    13   end
    14   always @(posedge clk)
    15   begin
    16   if(wen==1)
    17   begin fifo[w_addr]<=data_in; end
    18   end
    19 endmodule

     

    Part 5.r_addr产生块:

    该模块用于产生FIFO读数据时所用的地址。由于16个RAM单元可以用4位地址线寻址。本模块用5位计数器(rd_addr[4:0])实现读地址的产生。

    在复位时(rst=0),读地址值为0。

    如果FIFO未空(~empty)且有读使能(r_en)有效,则r_addr[4:0]加1;否则不变。

     1 //read address genaration
     2 module r_addr_gen(clk,rst,ren,r_addr,empty);
     3   input clk,rst,ren,empty;
     4   output [4:0]r_addr;
     5   reg [4:0]r_addr;
     6   always @(posedge clk)                //negedge rst can be here to make it asynchronous
     7   begin
     8   if (!rst) begin r_addr<=5'b00000; end
     9     else if(ren==1&&empty==0) begin r_addr<=r_addr+1;end
    10       else begin r_addr<=5'b00000;  end
    11   end
    12 endmodule

     

    Part 6.w_addr产生块:

    该模块用于产生FIFO写数据时所用的地址。由于16个RAM单元可以用4位地址线寻址。

    在复位时(rst=0),写地址值为0。

    如果FIFO未满(~full)且有写使能(w_en)有效,则w_addr[4:0]加1;否则不变。

     

     1 //write address genaration
     2 module w_addr_gen(clk,rst,wen,w_addr,full);
     3   input clk,rst,wen,full;
     4   output [4:0]w_addr;
     5   reg [4:0]w_addr;
     6   always @(posedge clk)                //negedge rst can be here to make it asynchronous
     7   begin
     8   if (!rst) begin w_addr<=5'b00000; end
     9     else if(wen==1&&full==0) begin w_addr<=w_addr+1;end
    10       else begin w_addr<=5'b00000;  end
    11   end
    12 endmodule

    Part 7.空满标志产生块: 

    flag_gen模块产生FIFO空满标志。本模块设计并不用读写地址判定FIFO是否空满。设计一个计数器,该计数器(pt_cnt)用于指示当前周期中FIFO中数据的个数。由于FIFO中最多只有16个数据,因此采用5位计数器来指示FIFO中数据个数。具体计算如下:

    1)复位的时候,count=0;

    2)如果w_en和r_en同时有效的时候,count不加也不减;表示同时对FIFO进行读写操作的时候,FIFO中的数据个数不变。

    3)如果w_en有效且full=0,则count+1;表示写操作且FIFO未满时候,FIFO中的数据个数增加了1;

    4)如果r_en有效且empty=0,则count-1; 表示读操作且FIFO未满时候,FIFO中的数据个数减少了1;

    5)如果count=0的时候,表示FIFO空,需要设置empty=1;如果count=16的时候,表示FIFO现在已经满,需要设置full=1。

     1 //empty and full flag gennaration
     2 module flag_gen(clk,rst,ren,wen,empty,full);
     3   input clk,ren,wen,rst;
     4   output empty,full;
     5   reg empty,full;
     6   reg [4:0]count;
     7   parameter max=5'b01111;
     8   
     9   always @(posedge clk)
    10   begin
    11   if(!rst) begin count<=0;end
    12     else case({ren,wen})
    13          2'b00: count<=count;
    14          2'b01: if(count!=max) count<=count+1;
    15          2'b10: if(count!=5'b0)count<=count-1;
    16          2'b11: count<=count;
    17          default:count<=count;
    18          endcase
    19   end
    20   
    21   always @(count)
    22   begin
    23   if (count==max) full<=1;
    24     else full<=0;
    25   end 
    26   
    27   always @(count)
    28   begin
    29   if (count==5'b0) empty<=1;
    30     else empty<=0;
    31   end
    32 endmodule

     

     

  • 相关阅读:
    虚拟机virtualBox
    在scala命令行中加入类库
    使用git submodule
    Julia1.x安装
    texshop 使用技巧
    vimdiff换行
    双系统磁盘挂载失败
    www.wolframalpha.com
    sublime3激活方法
    实验数据
  • 原文地址:https://www.cnblogs.com/SYoong/p/6108780.html
Copyright © 2011-2022 走看看