ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

同步和异步FIFO

2021-11-28 13:02:59  阅读:175  来源: 互联网

标签:异步 同步 addr read RAM FIFO write WIDTH input


在这里插入图片描述
FiFo外部是没有地址的,外部端口只负责读写,内部RAM有地址
在这里插入图片描述
FIFO可以在一边读,一边写,两边读写速度可不一样,
RAM中的控件可以重复利用,某个数据位读走后,可再存入新的数据。
两边速度不同的情况下,RAM的空间和两边读写速度满足一定的公式就可随意读写

FIFO中的RAM设计

module dp_ram #(parameter	DLY       = 1,
                          	RAM_WIDTH = 8,
                          	RAM_DEPTH = 16,
                          	ADDR_WIDTH= 4)
               (input       write_clock,
                input       read_clock,
                input       write_allow,
                input       read_allow,
                input       [ADDR_WIDTH-1:0] write_addr,
                input       [ADDR_WIDTH-1:0] read_addr,
                input       [RAM_WIDTH-1 :0] write_data,
                output  reg [RAM_WIDTH-1 :0] read_data);
    
    reg [RAM_WIDTH-1:0] memory[RAM_DEPTH-1:0];

    always @(posedge write_clock) begin
        if(write_allow)
            memory[write_addr] <= #DLY write_data;
    end

    always @(posedge read_clock) begin
        if(read_allow)
            read_data <= #DLY memory[read_addr];
    end
endmodule

同步FIFO的设计

在这里插入图片描述
FIFO原则:先进先出

同步FIFO的设计

1. 通过计数判断fifo空满

`timescale 1ns/10ps

module SYNCFIFO#(parameter  DATA_WIDTH = 8,
                            ADDR_WIDTH = 9)
                (input  wire                 fifo_rst,       //复位信号
                 input  wire                 clock,          //读写的同步时钟
                 input  wire                 read_enable,    
                 input  wire                 write_enable,
                 input  reg [DATA_WIDTH-1:0] write_data,
                 output reg [DATA_WIDTH-1:0] read_data,
                 output reg                  full,          //满信号
                 output reg                  empty,         //空信号    
                 output reg [ADDR_WIDTH-1:0] fcounter
                 );

    wire    read_allow   = (read_enable  && !empty);    //读允许+不空
    wire    write_allow  = (write_enable && !full);     //写允许+不满

    dp_ram fifo_ram(
        .write_clock(clock),
        .read_clock (clock),
        .write_allow(write_allow),
        .read_allow (read_allow),
        .read_addr  (read_addr),
        .write_addr (write_addr),
        .write_data (write_data),
        .read_data  (read_data)
    );
    
    /*
     * 1. 判断fifo的空满
     */
    always @(posedge clock or posedge fifo_rst)
        if(fifo_rst)
            empty <= 'b1;
        else
            empty <= (!write_enable && (fcounter[8:1] == 8'h0) && 
                     ((fcounter[0] == 0)||read_enable));

    always @(posedge clock or posedge fifo_rst)
        if(fifo_rst)
            full <= 'b1;
        else 
            full <=  (!read_enable && (fcounter[8:1] == 8'hFF) && 
                     ((fcounter[0] == 1)||write_enable));
    
    /* 
     * 2. 产生读写地址 
     */
    always @(posedge clock or posedge fifo_rst)
        if(fifo_rst)
            read_addr <= 'h0;
        else if(read_allow)
            read_addr <= read_addr + 'b1;

    always @(posedge clock or posedge fifo_rst)
        if(fifo_rst)
            write_addr <= 'h0;
        else if(write_allow)
            write_addr <= write_addr + 'b1;

    /*
     * 3. 读写计数(写:计数器加1;读:计数器减1)
     */
    always @(posedge clock or posedge fifo_rst)
        if(fifo_rst)
            fcounter <= 'h0;
        else if((!read_allow && write_allow)||(read_allow && !write_allow))
        begin
            if(write_allow) fcounter <= fcounter + 'b1;
            else fcounter <= fcounter - 'b1;
        end
endmodule

2. 通过地址扩展位判断fifo空满

module sync_fifo(
    input       clk,
                rst,
                write_enable,
                read_enable,
    input       [7:0] data_in,
    output  reg [7:0] data_out,
    output      empty,
                full
);
    /* 数据宽度为8bit,深度为16的RAM */
    reg [7:0] mem[15:0];    
    
    /* 地址 */
    wire[3:0] w_addr, w_addr;
    reg [4:0] r_addr_a, w_addr_a;

    assign r_addr = r_addr_a[3:0];
    assign w_addr = w_addr_a[3:0];
    
    /* 读 */
    always@(posedge clk or negedge rst) begin
        if(!rst)    
            r_addr_a <= 5'b0;   //复位,读地址清零
        else begin
            if(rd_en == 1 && empty == 0) begin  //当读允许,非空时执行
                data_out <= mem[r_addr];        //读出数据
                r_addr_a <= r_addr_a + 1;       //读地址加1
            end
        end
    end
    
    /* 写 */
    always@(posedge clk or negedge rst) begin
        if(!rst)    
            w_addr_a <= 5'b0;   //复位,写地址清零   
        else begin
            if(wr_en == 1 && full == 0) begin   //当写允许,非满时执行
                mem[w_addr] <= data_in;         //数据写入指定地址
                w_addr_a <= w_addr_a + 1;       //写地址加1
            end
        end
    end

    /* 判断空满 */
    assign empty = (r_addr_a == w_addr_a) ? 1 : 0;
    assign full  = (r_addr_a[4] != w_addr_a[4] && 
                    r_addr_a[3:0] == w_addr_a[3:0]) ? 1 : 0;

endmodule

标签:异步,同步,addr,read,RAM,FIFO,write,WIDTH,input
来源: https://blog.csdn.net/weixin_41846089/article/details/121582256

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有