Loading

同步FIFO的移位寄存器、双口RAM实现方式与异步FIFO

同步FIFO的两种实现方式

基于移位寄存器的同步FIFO

`timescale 1ns/1ps

module sync_fifo
#(
	parameter DATA_WIDTH = 8,
	parameter FIFO_DEPTH = 8
)
(
	input rst_n,
	input clk,
	input [DATA_WIDTH-1:0] din,
	input push,
	input pop,
	output [DATA_WIDTH-1:0] dout,
	output reg full,
	output reg empty
);

localparam A_EMPTY = 0;
localparam A_FULL = FIFO_DEPTH - 2;

reg [DATA_WIDTH-1:0] mem [FIFO_DEPTH-1:0];
integer read_cnt;

// write data
integer i;
always @(posedge clk)begin
	if (push & ~full)begin
		for(i = 0; i < FIFO_DEPTH; i = i + 1)begin
      mem[i+1] <= mem[i];
      mem[0] <= din;
		end
	end
end

// read pointer
// read pointer is initialized as FIFO_DEPTH-1'b1
always @(posedge clk or negedge rst_n)begin
	if(!rst_n)
		read_cnt <= FIFO_DEPTH-1'b1;
	else if(push & !pop & !full) begin
		if(read_cnt == FIFO_DEPTH-1'b1)
			read_cnt <= 0;
		else
			read_cnt <= read_cnt + 1'b1;
	end
	else if (!push & pop & !empty)begin
		if(read_cnt == A_EMPTY)
			read_cnt <= FIFO_DEPTH - 1'b1;
    else
			read_cnt <= read_cnt - 1'b1;
	end
end

// empty indicating
  always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
      empty <= 1'b1;
    else if (~push & pop & ((read_cnt == A_EMPTY) == 1'b1))
      empty <= 1'b1;
    else if (!pop & push)
      empty <= 1'b0;
  end
  
  always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
      full <= 1'b0;
    else if (push & ~pop & (read_cnt == A_FULL))
      full <= 1'b1;
    else if (pop & !push)
      full <= 1'b0;
  end
  
  // data output
  assign dout = (FIFO_DEPTH == 1) ? mem[0] : mem[read_cnt];
endmodule


`timescale 1ns/1ps
module tb;
  reg clk, rst_n;
  reg [7:0] din;
  wire [7:0] dout;
  reg push, pop;
  initial begin
    clk = 0;
    #5 clk = 1;
    forever #5 clk = ~clk;
  end
  
  initial begin
    rst_n = 0;
    #15 rst_n = 1;
  end
  
  initial begin
    push = 0;
    #29 push = 1;
    #89 push = 0;
    pop = 1;
    #169 
    pop = 0;
    $finish;
  end
  
  initial begin
    forever #9 din = $random();
  end
  
  sync_fifo inst (
  rst_n, clk, din, push, pop, dout, full, empty
  );
endmodule

基于双口RAM的同步FIFO

`timescale 1ns/1ns
module dual_port_RAM
#(
	parameter WIDTH = 8,
  parameter DEPTH = 16
)
(
	input wclk,
  input wenc,
  input [$clog2(DEPTH)-1:0] waddr,
  input [WIDTH-1:0] wdata,
  input rclk,
  input renc,
  input [$clog2(DEPTH)-1:0] raddr,
  output reg [WIDTH-1:0] rdata
);

reg [WIDTH-1:0] mem [0:DEPTH-1];
always @(posedge wclk)begin
  if(wenc)
    mem[waddr] <= wdata;
end
always @(posedge rclk)begin
  if(renc)
    rdata <= mem[raddr];
end
endmodule


// -------------------------------------------------------
module sfifo
#(
	parameter WIDTH = 8,
	parameter DEPTH = 16
)
(
	input clk,
	input rst_n,
	input winc,
	input rinc,
	input [WIDTH-1:0] wdata,
	
	output reg wfull,
	output reg rempty,
	output wire [WIDTH-1:0] rdata
);
parameter ADDR_WIDTH = $clog2(DEPTH);

reg [ADDR_WIDTH:0] wr_ptr, rd_ptr;
wire wenc, renc;

//assign wfull = (wr_ptr - rd_ptr) == DEPTH;
//assign rempty = wr_ptr == rd_ptr;


assign wenc = winc & ~wfull;
assign renc = rinc & ~rempty;
  
  always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
      wfull <= 1'b0;
      rempty <= 1'b0;
    end
    else begin
        wfull = (wr_ptr - rd_ptr) == DEPTH;
        rempty = wr_ptr == rd_ptr;
    end
  end

always @(posedge clk or negedge rst_n)begin
  if(!rst_n)
    wr_ptr <= 1'b0;
  else if (wenc)
    wr_ptr <= wr_ptr + 1'b1;
  else 
    wr_ptr <= wr_ptr;
end

always @(posedge clk or negedge rst_n)begin
  if(!rst_n)
    rd_ptr <= 1'b0;
  else if (renc)
    rd_ptr <= rd_ptr + 1'b1;
  else
    rd_ptr <= rd_ptr;
end

dual_port_RAM inst
(
  clk, wenc, wr_ptr[ADDR_WIDTH-1:0], wdata, clk, renc, rd_ptr[ADDR_WIDTH-1:0],
  rdata
);
endmodule

异步FIFO双口RAM

`timescale 1ns/1ns
module dual_port_RAM
  #(
  parameter WIDTH = 8,
  parameter DEPTH = 16
  )
  (
    input wclk,
    input wenc,
    input [$clog2(DEPTH)-1:0] waddr,
    input [WIDTH-1:0] wdata,
    
    input rclk,
    input renc,
    input [$clog2(DEPTH)-1:0] raddr,
    output reg [WIDTH-1:0] rdata
  );
  
  reg [WIDTH-1:0] mem [DEPTH-1:0];
  
  always @(posedge wclk)begin
    if(wenc)
      mem[waddr] <= wdata;
  end
  
  always @(posedge rclk) begin
    if(renc)
      rdata <= mem[raddr];
  end
endmodule

// --------------------------------------------
module asyn_fifo
  #(
  	parameter WIDTH = 8,
    parameter DEPTH = 16
  )
  (
  	input wclk,
    input rclk,
    input wrstn,
    input rrstn,
    input winc,
    input rinc,
    input [WIDTH-1:0] wdata,
    
    output wire wfull,
    output wire rempty,
    output wire [WIDTH-1:0] rdata
  );
  
  parameter ADDR_WIDTH = $clog2(DEPTH);
  
  reg [ADDR_WIDTH:0] wr_ptr, wr_grey0, wr_grey1, wr_grey2;
  reg [ADDR_WIDTH:0] rd_ptr, rd_grey0, rd_grey1, rd_grey2;
  wire [ADDR_WIDTH:0] wr_grey, rd_grey;
  wire wenc, renc;
  
  assign wr_grey = wr_ptr >> 1 ^ wr_ptr;
  assign rd_grey = rd_ptr >> 1 ^ rd_ptr;
  assign wfull = wr_grey0 == {~rd_grey2[ADDR_WIDTH:ADDR_WIDTH-1], rd_grey2[ADDR_WIDTH-2:0]};
  assign rempty = rd_grey0 == wr_grey2;
  assign wenc = winc & ~wfull;
  assign renc = rinc & ~rempty;
  
  always @(posedge wclk or negedge wrstn)begin
    if(!wrstn)
      wr_ptr <= 1'b0;
    else if (wenc)
      wr_ptr <= wr_ptr + 1'b1;
  end
  
  always @(posedge rclk or negedge rrstn)begin
    if(!rrstn)
      rd_ptr <= 1'b0;
    else if (renc)
      rd_ptr <= rd_ptr + 1'b1;
  end
  
  always @(posedge wclk or negedge wrstn)begin
    if(!wrstn)
      wr_grey0 <= 1'b0;
    else
      wr_grey0 <= wr_grey;
  end
  
  always @(posedge rclk or negedge rrstn)begin
    if(!rrstn)
      rd_grey0 <= 1'b0;
    else
      rd_grey0 <= rd_grey;
  end
  
  always @(posedge wclk or negedge wrstn)begin
    if(!wrstn)
    {rd_grey2, rd_grey1} <= 'b0;
    else
    {rd_grey2, rd_grey1} <= {rd_grey1, rd_grey0};
  end
  
  always @(posedge rclk or negedge rrstn)begin
    if (!rrstn)
    {wr_grey2, wr_grey1} <= 'b0;
    else
    {wr_grey2, wr_grey1} <= {wr_grey1, wr_grey0};
  end
  
  dual_port_RAM inst
  (wclk, wenc, wr_ptr[ADDR_WIDTH-1:0], wdata, 
   rclk, renc, rd_ptr[ADDR_WIDTH-1:0], rdata);
endmodule
posted @ 2022-08-02 17:07  pu1se  阅读(1033)  评论(0)    收藏  举报