当前位置:   article > 正文

verilog实例—sync_fifo_sync fifo

sync fifo


一、FIFO

  • 同步FIFO 即时钟同步
  • FIFO是什么,有什么用?
    First Input First Output的缩写,先入先出队列,这是一种传统的按序执行方法,先进入的指令先完成并引退,跟着才执行第二条指令。
  • 端口
    在这里插入图片描述
    在这里插入图片描述

二、skills

1、读写地址变化方式

1、关于写地址的变化,只需考虑we有效的情况:

只写不读时:若FIFO满,则写失败,写地址不变;若FIFO不满,则写一定成功,写地址加1。
又写又读时:若FIFO满,读写为同一单元,因读操作只需读取旧数据,所以读写都成功,写地址加1;若FIFO不满,则进行读写操作的是两个不同单元,所以写一定成功,所以写地址也加1。

总结,wr_en && (!full || (full && rd_en))时,写地址加1;其他情况,写地址不变。因为只有写成功(写地址加1)的情况,才能让RAM的写使能有效,所以RAM的写使能也为wr_en && (!full || (full && rd_en))。

2、关于读地址的变化,只需考虑re有效的情况:

只读不写时:若FIFO空,则读失败,读地址不变;若FIFO不空则读一定成功,读地址加1.。
又读又写时:若FIFO空,则读写为同一单元,由于单元内无旧数据,读失败,只有写成功,此时读地址不变;若FIFO不空,则进行读写操作的是两个不同单元,所以读一定成功,读地址加1。

总结,(re有效&&empty标志无效)时,读地址加1;其他情况,读地址不变。因为只有读成功(读地址加1)的情况,才能让RAM的读使能有效,所以RAM的读使能也为(re有效&&empty标志无效)。

2、notes

  • FIFO满时,和空时,读写指针指向同一地址
  • 满时,读写使能为1,可同时读写
  • 空时,读写使能为1,只能写

三、RTL design

module sync_fifo(
        clk,
        rst,    //async
        wr_data,
        wr_en,
        rd_data,
        rd_en,
        full,
        empty
        );
    
    parameter   DATA_WIDTH = 32,
                DATA_DEPTH = 8,
                ADD_WIDTH  = 3;

    input       clk;
    input       rst;
    input       wr_data;
    input       wr_en;
    input       rd_en;

    output      rd_data;
    output      full;
    output      empty;
    
    reg [DATA_WIDTH-1:0]    wr_data;
    reg [DATA_WIDTH-1:0]    rd_data;
    reg [DATA_WIDTH-1:0]    ram_32_8[DATA_DEPTH-1:0];
    reg [ADD_WIDTH-1:0]     wr_add;
    reg [ADD_WIDTH-1:0]     rd_add;
    reg [ADD_WIDTH-1+1:0]   data_count;
    
    wire         full;
    wire        empty;
    reg         wr_enbuf;
    reg         rd_enbuf;

    assign wr_enbuf = wr_en && (!full || (full && rd_en));
    assign rd_enbuf = rd_en && !empty;
    //写指针移动
    always@(posedge clk or negedge rst)begin
        if(!rst)
            wr_add <= 3'b0;
        else if(wr_enbuf)
            wr_add <= wr_add + 1'b1;
        end

    //读指针移动
    always@(posedge clk or negedge rst)begin
        if(!rst)
            rd_add <= 3'b0;
        else if(rd_enbuf)
            rd_add <= rd_add + 1'b1;
        end
    //数据计数器
    always@(posedge clk or negedge rst)begin//case is good
        if(!rst)
            data_count <= 4'b0;
        else begin 
            if(rd_enbuf && wr_enbuf) //writing while reading
                data_count <= data_count;
            else if(wr_enbuf)     //writing
                data_count <= data_count + 1'b1;
            else if(rd_enbuf)    //reading
                data_count <= data_count - 1'b1;
        end
    end

    //满空判断
//    always@(posedge clk or negedge rst)begin
//        if(!rst)
//            full <= 1'b0;
//        else 
//            //full <= (!rd_enbuf && data_count == 4'b1000)||(!rd_enbuf && data_count == 4'b0111 && wr_enbuf)||(rd_enbuf && wr_enbuf && data_count == 4'b1000);
//    end
    assign full = data_count == 4'b1000;


//    always@(posedge clk or negedge rst)begin
//        if(!rst)
//            empty <= 1'b1;
//        else 
//            //empty <= (!wr_enbuf && data_count == 3'b000)||(!wr_enbuf && data_count ==3'b001 && rd_enbuf);
//        end
    assign empty = data_count == 0;

    //ram写读数据
    always@(posedge clk or negedge rst)begin
        if(!rst)begin
            integer i ;
            for(i=0;i < DATA_DEPTH;i=i+1)
                begin
                ram_32_8[i] <= 32'b0;
                end
        end
        else if(wr_enbuf)begin
                ram_32_8[wr_add] <= wr_data;
        end
    end


    always@(posedge clk or negedge rst)begin
        if(!rst)begin
            rd_data <= 32'b0;
        end
        else if(rd_enbuf)begin
            rd_data <= ram_32_8[rd_add];
        end
    end

endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111

  • tb
`timescale 1ps/1ps
module test;
    //data type spicifiction
    reg         clk;
    reg         rst;
    reg [31:0]  wr_data;
    reg         wr_en;
    reg         rd_en;

    wire [31:0] rd_data;
    wire        full;
    wire        empty;

    //reset all
    initial begin
        clk   = 0;
        rst   = 1;

        wr_en = 0;
        rd_en = 0;

        wr_data = 32'b0;

     #2 rst   = 0;
     #5 rst   = 1;

    end
    
    //clock genarating
    always #0.5 clk = ~clk;
        
    //stimulate
    initial begin
        #10 wr_en = 1;
            rd_en = 0;
        #10 wr_en = 0;
            rd_en = 1;
        #10 wr_en = 1;
            rd_en = 0;
        #3  rd_en = 1;
        #10 
        repeat(100) begin
            #5 wr_en = {$random}%2;
               rd_en = {$random}%2;
        end
    end
    
    always #1 wr_data = {$random}%10;
    
    //module instantiation
     sync_fifo u_sync_fifo(
        .clk            (clk    ),
        .rst            (rst    ),    
        .wr_data        (wr_data),
        .wr_en          (wr_en  ),
        .rd_data        (rd_data),
        .rd_en          (rd_en  ),
        .full           (full   ),
        .empty          (empty  ) 
        );

    //stop
    initial begin
        forever begin
            #100
            //$display("---gyc---:%d",$time);
            if($time >= 2000)begin
                $finish;
            end
        end
    end
endmodule
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72

4、veidi graph

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/206718
推荐阅读
相关标签
  

闽ICP备14008679号