FIFO设计

同步FIFO写法:

第一步,确定IO:

时钟、复位,读请求、写请求,读数据、写数据,满、空8个

第二步,确定变量:

input wire clk, reset_n;
input wire write_en, read_en;
input wire [3:0] write_data;
output wire [3:0] read_data;
output reg full, empty;
reg [3:0] mem[3:0];
reg [3:0] write_addr, read_addr;

第三步,读数据、写数据:

always@(posedge clk)
  begin
    if(~full)
      mem[write_addr]<=write_data;
  end
assign read_data = mem[read_addr];

第四步,地址产生:

always@(posedge clk)
  begin
    if(~full&&write_en)
      write_addr<=write_addr+1;
    if(~empty&&read_en)
      read_addr<=read_addr+1;
  end

第五步,满空状态产生

always@(posedge clk)
  begin
    if(read_addr+1==write_addr)
      empty<=1;
    else
      empty<=0;
    if((write_addr+1==read_addr)||(write_addr==15&&read_addr==0))
      full<=1;
    else
      full<=0;
  end

第六步,加上复位

异步FIFO写法:

第一步,确定IO:

读时钟,写时钟,复位,读请求,写请求,读数据,写数据,满、空9个

第二步,确定变量:

input wire read_clk, write_clk;
input wire reset_n;
input wire read_en, write_en;
input wire [3:0] read_data;
output wire [3:0] write_data;
output reg full, empty;
reg [7:0] mem[3:0];
reg [3:0] read_addr, write_addr;
reg [4:0] read_bin, write_bin;
reg [4:0] read_gray, write_gray;
reg [4:0] read_bin_next, write_bin_next;
reg [4:0] read_gray_next, write_gray_next;
reg [4:0] read_gray_write1, write_gray _read1;
reg [4:0] read_gray_write2, write_gray _write2;

第三步,读数据,写数据:

always@(posedge write_clk)
  begin
    if(~full&&write_en)
      mem[write_addr] <= write_data;
  end
assign read_data = mem[read_addr];

第四步,读地址,写地址:

地址同步,地址产生,地址刷新

always@(posedge write_clk)
  {read_gray_write2, read_gray_write1}<={read_gray_write1, read_gray};
always@(posedge read_clk)
  {write_gray_read2, write_gray_read1}<={write_gray_read1, write_gray};

assign read_addr = read_bin[3:0];
assign write_addr = write_bin[3:0];
assign read_bin_next = read_bin + (~empty)&&read_en;
assign write_bin_next = write_bin + (~full)&&write_en;
assign read_gray_next = (read_bin_next>>1)^read_bin_next;
assign write_gray_next = (write_bin_next>>1)^write_bin_next;

always@(posedge write_clk)
  {write_bin, write_gray}<={write_bin_next, write_gray_next};
always@(posedge read_clk)
  {read_bin, read_gray}<={read_bin_next, read_gray_next};

第五步,满空判断:

always@(posedge write_clk)
  full<=(write_gray_next=={~read_gray_read2[4:3], read_gray_write2[2:0]});
always@(posedge read_clk)
  empty<=(read_gray_next==write_gray_read2);

异步FIFO完整代码:

module a_fifo(
	input read_clk,
	input write_clk,
	input read_rst_n,
	input write_rst_n,
	input read,
	input write,
	output [7:0] r_data,
	input [7:0] w_data, 
	output full,
	output empty
);
reg [7:0] mem[3:0];
reg [4:0] read_bin = 0,read_gray = 0,read_gray_w1,read_gray_w2;
reg [4:0] write_bin = 0,write_gray = 0,write_gray_r1,write_gray_r2;
reg r_full = 0,r_empty =1; 
wire [4:0] read_bin_next,read_gray_next,write_bin_next,write_gray_next;
wire [3:0] read_addr,write_addr;
assign r_data = mem[read_addr];
always@(posedge write_clk)
	if(write&&~full)
		mem[write_addr] <= w_data;
always@(posedge write_clk,negedge write_rst_n)
	if(write_rst_n==0)
		{read_gray_w2,read_gray_w1} <= 0;
	else
		{read_gray_w2,read_gray_w1} <= {read_gray_w1,read_gray};
always@(posedge read_clk,negedge read_rst_n)
	if(read_rst_n==0)
		{write_gray_r2,write_gray_r1} <= 0;
	else
		{write_gray_r2,write_gray_r1} <= {write_gray_r1,write_gray};
always@(posedge read_clk,negedge read_rst_n)
	if(read_rst_n==0)
		{read_bin,read_gray} <= 0;
	else
		{read_bin,read_gray} <= {read_bin_next,read_gray_next};
always@(posedge write_clk,negedge write_rst_n)
	if(write_rst_n==0)
		{write_bin,write_gray} <= 0;
	else
		{write_bin,write_gray} <= {write_bin_next,write_gray_next};
assign read_addr = read_bin[3:0];
assign read_bin_next = read_bin + (read & ~r_empty);
assign read_gray_next = (read_bin_next>>1) ^ read_bin_next;
assign write_addr = write_bin[3:0];
assign write_bin_next = write_bin + (write & ~r_full);
assign write_gray_next = (write_bin_next>>1) ^ write_bin_next;
always@(posedge write_clk,negedge write_rst_n)
	if(write_rst_n==0)
		r_full <= 0;
	else
		r_full <= (write_gray_next == {~read_gray_w2[4:3],read_gray_w2[2:0]});
assign full = r_full;
always@(posedge read_clk,negedge read_rst_n)
	if(read_rst_n==0)
		r_empty <= 1;
	else
		r_empty <= (read_gray_next == write_gray_r2);
assign empty = r_empty;
endmodule

发表评论

电子邮件地址不会被公开。 必填项已用*标注