首页 > 其他分享 >FIFO设计

FIFO设计

时间:2024-01-13 21:44:41浏览次数:19  
标签:wire ADDR read RAM FIFO WIDTH input 设计

  • first in first out,先进先出
  • fifo是基于RAM进行设计的

双端口RAM设计(16*8)

  • 如果大的RAM可以调用IP
  • RAM的关键参数:深度和宽度
module dual_ram
#(
    parameter ADDR_WIDTH = 4,
    parameter RAM_WIDTH = 8,
    parameter DLY=1
)
(
    input   wire                        read_clk    ,
    input   wire                        write_clk   ,
    input   wire    [ADDR_WIDTH-1:0]    read_addr   ,
    input   wire    [ADDR_WIDTH-1:0]    write_addr  ,
    input   wire                        read_allow  ,
    input   wire                        write_allow ,
    input   wire    [RAM_WIDTH-1:0]     write_data  ,
    output  reg   [RAM_WIDTH-1:0]     read_data   
);

    reg [RAM_WIDTH-1:0] memory [ADDR_WIDTH-1:0];

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

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

endmodule

单端口ram

module single_port_ram
#(
    parameter ADDR_WIDTH = 8,
    parameter RAM_WIDTH = 8,
    parameter RAM_DEPTH = 255,
    parameter DLY = 1
)
(
    input   wire                    clk,
    input   wire                    rst_n,
    input   wire [ADDR_WIDTH-1:0]   addr,
    input   wire                    wr_en, // 1-write 0-read
    input   wire [RAM_WIDTH-1:0]    wdata,

    output  wire [RAM_WIDTH-1:0]    rata
);

reg [RAM_DEPTH-1:0] mem [RAM_WIDTH-1:0];

integer i;
always @(posedge clk or negedge rst_n) begin
    if(rst_n)
        for(i=0;i<=255;i=i+1) begin
            mem[i] = 16'h0000;
        end
    else if(wr_en)
        mem[addr] <= wdata;
end


assign radta = (!wr_en) ? mem[addr] : 16'h0000 ;

// always @(posedge clk or negedge rst_n) begin
//     if(!rst_n)
//         radta <= 'h0;
//     else if(!wr_en)
//         r_data <= mem[addr];
// end

endmodule

同步FIFO设计

module sync_fifo
#(
    parameter ADDR_WIDTH = 9,
    parameter RAM_WIDTH = 8
)
(
    input   wire                    fifo_clk,
    input   wire                    fifo_rst_n,
    input   wire                    read_en,
    input   wire                    write_en,
    input   wire [RAM_WIDTH-1:0]    w_data,
    output  wire [RAM_WIDTH-1:0]    r_data,
    output  reg                     empty,
    output  reg                     full,
    output  reg [ADDR_WIDTH-1:0]    fcounter
);

    reg [ADDR_WIDTH-1:0]    write_addr;
    reg [ADDR_WIDTH-1:0]    read_addr;

    wire write_allow = write_en && (!empty);
    wire read_allow = read_en && (!full);


    // empty 
    always @(posedge fifo_clk or negedge fifo_rst_n) begin
        if(fifo_rst_n)
            empty <= 1'b1;
        else
            empty <= (!write_allow) && (fcounter[ADDR_WIDTH-1:1] == 8'h0) && (fcounter[0] == 0||read_allow);    
    end

    // full
    always @(posedge fifo_clk or negedge fifo_rst_n) begin
        if(fifo_rst_n)
            full <= 1'b0;
        else
            full <= (!read_allow) && (fcounter[ADDR_WIDTH-1:1] == 8'hff) && (fcounter[0] == 1||write_allow);    
    end

    always @(posedge fifo_clk or negedge fifo_rst_n) begin
        if(fifo_rst_n)
            fcounter <= {ADDR_WIDTH{1'b0}};
        else if( (!read_allow) && (write_allow)||(read_allow) && (!write_allow)) begin
                if(write_allow)
                    fcounter <= fcounter + 1'b1;
                else
                    fcounter <= fcounter - 1'b1;        
        end
    end
    
    always @(posedge fifo_clk or negedge fifo_rst_n) begin
        if(fifo_rst_n)
            write_addr <= {ADDR_WIDTH{1'b0}};
        else if(write_allow)
            write_addr <= write_addr + 1'b1;
        end

    always @(posedge fifo_clk or negedge fifo_rst_n) begin
        if(fifo_rst_n)
            read_addr <= {ADDR_WIDTH{1'b0}};
        else if(write_allow)
            read_addr <= read_addr + 1'b1;
        end


    dual_ram u_dual_ram
    (
        .read_clk    (fifo_clk),
        .write_clk   (fifo_clk),
        .read_addr   (read_addr),
        .write_addr  (write_addr),
        .read_allow  (read_allow),
        .write_allow (write_allow),
        .write_data  (w_data),
        .read_data   (r_data)
    );
endmodule
module sync_fifo
#(
    parameter ADDR_WIDTH = 4,
    parameter RAM_WIDTH = 8,
    parameter RAM_DEPTH = 16,
)
(
    input   wire                    fifo_clk,
    input   wire                    fifo_rst_n,
    input   wire                    read_en,
    input   wire                    write_en,
    input   wire [RAM_WIDTH-1:0]    w_data,
    output  wire [RAM_WIDTH-1:0]    r_data,
    output  reg                     empty,
    output  reg                     full
);

    // 指针
    reg [ADDR_WIDTH:0]    write_addr;
    reg [ADDR_WIDTH:0]    read_addr;
    wire    [ADDR_WIDTH-1:0] w_addr;
    wire    [ADDR_WIDTH-1:0] r_addr;

    wire write_allow = write_en && (!empty);
    wire read_allow = read_en && (!full);

    reg [RAM_WIDTH-1:0] mem [RAM_DEPTH-1:0];

    always @(posedge fifo_clk or negedge fifo_rst_n) begin
        if(!fifo_rst_n)
            read_addr <= {ADDR_WIDTH{1'b0}};
        else if(read_allow) begin 
            r_data <= mem[read_addr];
            read_addr <= read_addr + 1;
        end
    end

    always @(posedge fifo_clk or negedge fifo_rst_n) begin
        if(!fifo_rst_n)
            write_addr <= {ADDR_WIDTH{1'b0}};
        else if(write_allow) begin 
            mem[write_addr] <= w_data;
            write_addr <= write_addr + 1;
        end
    end

    assign empty = read_addr == write_addr ? 1 : 0;
    assign full = (read_addr[ADDR_WIDTH]!=write_addr[ADDR_WIDTH]) &&
                (read_addr[ADDR_WIDTH-1:0] == write_addr[ADDR_WIDTH-1:0]);

    assign r_addr = read_addr[ADDR_WIDTH-1:0]
    assign w_addr = write_addr[ADDR_WIDTH-1:0]
endmodule

标签:wire,ADDR,read,RAM,FIFO,WIDTH,input,设计
From: https://www.cnblogs.com/Icer-newer/p/17962816

相关文章

  • spring与设计模式之三代理模式
    部分内容引用:https://blog.csdn.net/shulianghan/article/details/119798155一、定义1.1定义对于现实生活中的代理,大家非常好理解。我们需要代理,主要因为几个原因:太忙-例如房产中介、代购目前对象不是自身可以直接接触的-例如托人办事、例如掏钱购买某种服务都可以理解为代......
  • CS5569芯片,CS556,设计资料,CS5569规格书,CS5569原理图,typec转HDMI 8K带PD方案
    集睿致远/ASL的CS5269是一款低成本、低功耗的半导体器件,通过USBType-C连接器将DisplayPort信号转换为HDMI2.1。这款创新的基于USBType-C的DisplayPort接收器具有高性能DSC解码器,集成的HDMI2.1发射器专门针对USBType-C到HDMI2.1转换器而设计,一个NG设备。通过CS5269的先进的解码/......
  • 设计模式之中介者模式
    1.定义多个对象之间通过一个中介者对象进行通信和协作,而不是直接相互交互2.口语化表述中介,这在生活中很常见,比如租房中介通常,有住房出租的房东有很多,需要租房的租客也很多,但是租客难以直接联系房东,这个时候租房中介这个职业就出现了房东将房屋登记到中介这里,租客来中介这里......
  • 从Bitcask存储模型谈超轻量级KV系统设计与实现
    Bitcask介绍Bitcask是一种“基于日志结构的哈希表”(ALog-StructuredHashTableforFastKey/ValueData)Bitcask最初作为分布式数据库Riak的后端出现,Riak中的每个节点都运行一个Bitcask实例,各自存储其负责的数据。抛开论文,我们先通过一篇博客#Bitcask—alog-struc......
  • 金融疆界:支付系统渠道网关的创新设计(一)
    这是《百图解码支付系统设计与实现》专栏系列文章中的第(11.1)篇。点击上方关注,深入了解支付系统的方方面面。整个渠道网关的内容预计会分成5篇来讲:1)定位、术语、概要设计。2)领域模型、状态机设计。3)报文网关。4)文件网关。5)常见差异处理。本篇是其中的第1篇。主要讲清楚什么渠道网关......
  • 个人博客详细设计说明书
    ......
  • 基于单片机的通用传感器监测系统设计(#0526)
    功能描述1、采用51/52单片机作为主控芯片;2、采用AD0832做传感器模数转换;3、采用1602液晶显示:测量值、报警值;4、测量值超过报警值,蜂鸣器报警;5、按键修改报警值,24C02保存报警值;电路设计采用Altium Designer作为电路设计工具。Altium Designer通过把原理图设计、PCB绘制编辑、拓......
  • 基于单片机的篮球计分器系统设计(#0528)
    功能描述1、采用51/52单片机作为主控芯片;2、采用1602液晶显示:两方比分、12分钟倒计时、当前节数、24秒倒计时;3、按键控制:比赛开始/继续/暂停、24s复位、加3分、加2分、加1分;4、每节比赛结束,蜂鸣器提醒;电路设计采用Altium Designer作为电路设计工具。Altium Designer通过把原理......
  • 基于单片机的心形LED电子琴系统设计(#0529)
    功能描述1、采用51/52单片机作为主控芯片;2、通过喇叭播放音调、音乐;3、八个按键对应发出八个音符;4、内置三首音乐,按键切换;5、LED伴随着音调/音乐点亮;6、内置四种花样流水灯,按键切换。电路设计采用Altium Designer作为电路设计工具。Altium Designer通过把原理图设计、PCB绘......
  • 基于单片机的步进电机调控系统设计(#0527)
    功能描述1、采用51/52单片机作为主控芯片;2、采用DC-5V步进减速电机(步进角度5.625°,减速比1/64);3、采用ULN2003作为电机驱动;4、采用一位数码管显示当前转速(10档);5、按键控制正转、反转、加速、减速、停止;6、LED指示正反转状态、监看驱动信号;电路设计采用Altium Designer作为电路......