• 异步FIFO问题 二


    同步FIFO, verilog:

    module fifo(clock,reset,read,write,fifo_in,fifo_out,fifo_empty,fifo_half,fifo_full);
      input clock,reset,read,write;
      input [15:0]fifo_in;
      output[15:0]fifo_out;
      output fifo_empty,fifo_half,fifo_full;//标志位
      reg [15:0]fifo_out;
      reg [15:0]ram[15:0];
      reg [3:0]read_ptr,write_ptr,counter;//指针与计数
      wire fifo_empty,fifo_half,fifo_full;
    
      always@(posedge clock)
      if(reset)
        begin
          read_ptr=0;
          write_ptr=0;
          counter=0;
          fifo_out=0;                    //初始值
        end
      else
        case({read,write})
          2'b00:
                counter=counter;        //没有读写指令
          2'b01:                            //写指令,数据输入fifo
                begin
                  ram[write_ptr]=fifo_in;
                  counter=counter+1;
                  write_ptr=(write_ptr==15)?0:write_ptr+1;
                end
          2'b10:                          //读指令,数据读出fifo
                begin
                  fifo_out=ram[read_ptr];
                  counter=counter-1;
                  read_ptr=(read_ptr==15)?0:read_ptr+1;
                end
          2'b11:                        //读写指令同时,数据可以直接输出
                begin
                  if(counter==0)
                    fifo_out=fifo_in;
                  else
                    begin
                      ram[write_ptr]=fifo_in;
                      fifo_out=ram[read_ptr];
                      write_ptr=(write_ptr==15)?0:write_ptr+1;
                      read_ptr=(read_ptr==15)?0:write_ptr+1;
                    end
                  end
            endcase
    
            assign fifo_empty=(counter==0);    //标志位赋值 组合电路
            assign fifo_half=(counter==8);
            assign fifo_full=(counter==15);
    
        endmodule

    异步FIFO实现:

    module fifo1(rdata, wfull, rempty, wdata, winc, wclk, wrst_n,rinc, rclk, rrst_n);
    parameter DSIZE = 8; parameter ASIZE = 4;
    output [DSIZE-1:0] rdata;
    output wfull;
    output rempty;
    input [DSIZE-1:0] wdata;
    input winc, wclk, wrst_n;
    input rinc, rclk, rrst_n;
    reg wfull,rempty;
    reg [ASIZE:0] wptr, rptr, wq2_rptr, rq2_wptr, wq1_rptr,rq1_wptr;
    reg [ASIZE:0] rbin, wbin;
    reg [DSIZE-1:0] mem[0:(1<<ASIZE)-1];
    wire [ASIZE-1:0] waddr, raddr;
    wire [ASIZE:0] rgraynext, rbinnext,wgraynext,wbinnext;
    wire rempty_val,wfull_val;
    //-----------------双口RAM存储器--------------------
    assign rdata=mem[raddr];
    always@(posedge wclk)
    if (winc && !wfull) mem[waddr] <= wdata;
    //-------------同步rptr 指针-------------------------
    always @(posedge wclk or negedge wrst_n)
    if (!wrst_n) {wq2_rptr,wq1_rptr} <= 0;
    else {wq2_rptr,wq1_rptr} <= {wq1_rptr,rptr};
    //-------------同步wptr指针---------------------------
    always @(posedge rclk or negedge rrst_n)
    if (!rrst_n) {rq2_wptr,rq1_wptr} <= 0;
    else {rq2_wptr,rq1_wptr} <= {rq1_wptr,wptr};
    //-------------rempty产生与raddr产生-------------------
    always @(posedge rclk or negedge rrst_n) // GRAYSTYLE2 pointer
    begin
    if (!rrst_n) {rbin, rptr} <= 0;
    else {rbin, rptr} <= {rbinnext, rgraynext};
    end
    // Memory read-address pointer (okay to use binary to address memory)
    assign raddr = rbin[ASIZE-1:0];
    assign rbinnext = rbin + (rinc & ~rempty);
    assign rgraynext = (rbinnext>>1) ^ rbinnext;
    // FIFO empty when the next rptr == synchronized wptr or on reset
    assign rempty_val = (rgraynext == rq2_wptr);
    always @(posedge rclk or negedge rrst_n)
    begin
    if (!rrst_n) rempty <= 1'b1;
    else rempty <= rempty_val;
    end
    //---------------wfull产生与waddr产生------------------------------
    always @(posedge wclk or negedge wrst_n) // GRAYSTYLE2 pointer
    if (!wrst_n) {wbin, wptr} <= 0;
    else {wbin, wptr} <= {wbinnext, wgraynext};
    // Memory write-address pointer (okay to use binary to address memory)
    assign waddr = wbin[ASIZE-1:0];
    assign wbinnext = wbin + (winc & ~wfull);
    assign wgraynext = (wbinnext>>1) ^ wbinnext;
    assign wfull_val = (wgraynext=={~wq2_rptr[ASIZE:ASIZE-1], wq2_rptr[ASIZE-2:0]}); //:ASIZE-1]
    always @(posedge wclk or negedge wrst_n)
    if (!wrst_n) wfull <= 1'b0;
    else wfull <= wfull_val;
    endmodule
  • 相关阅读:
    Weekly blog for week 1908
    Weekly blog for week 1907
    Weekly blog for week 1905&1906
    Weekly blog for week 1904
    Write Week 3 Blog beforehand
    Add Week 2 Blog
    First week of a new year
    Andriod-Log
    bat
    学习方法
  • 原文地址:https://www.cnblogs.com/liheng369/p/8536816.html
Copyright © 2020-2023  润新知