同步fifo设计

154 阅读2分钟

设计实现一个512x8的双端口RAM:

RAM宽度为8bit

RAM深度为512

ADDR位宽2^9 = 512

//双口RAM

module DUALRAM(Read_clock,Write_clock,Read_allow,Write_allow,Read_addr,Write_addr,Write_data,Read_data);

parameter DLY = 1;
parameter RAM_WIDTH = 8;
parameter RAM_DEPTH = 512;
parameter ADDR_WIDTH = 9;

input Read_clock ,Write_clock;
input [RAM_WIDTH-1:0]Write_data;
input [ADDR_WIDTH-1:0]Read_addr;
input [ADDR_WIDTH-1:0]Write_addr;
input Read_allow,Write_allow;

output [RAM_WIDTH-1:0]Read_data;
reg [RAM_WIDTH-1:0]Read_data;

reg [RAM_WIDTH-1:0] Mem[RAM_DEPTH-1:0];  //前面为内存宽度,后面为内存深度。reg类型的数组




always@(posedge Write_clock) begin
    if(Wirte_allow)
        Mem[Write_addr] <= #DLY Write_data;
end
always@(posedge Read_clock) begin

    if(Read_allow)
        Read_data <= #DLY Mem[Read_addr];
end
endmodule

// fifo 设计,full不能写,empty不能读。关键在于full和empty的产生

方法1: 用长度计数器factor,执行写操作,长度加1,执行读操作,factor减1。

方法2:地址位扩展一位,用最高位来判断空满,低位地址为R_ADDR = W_ADDR。用10位地址信号,最高位判断空满。

高位相等,则为空。不相等则为满。

// 产生full empty信号,根据Read_enable,Write_enable产生 Read_allow和Write_allow。

// 产生Read_addr和Write_addr。 通过这两个信号,通过双口ram完成read_data 和 write_data。

//fifo控制

1 fifo 对双口ram通过read_allow 和wirte_allow,实现数据的存储和读取。

2 而read_allow 和wirte_allow是通过full和empty,read_enable,write_enable来实现的,所以full和empty的生成很重要。空满信号又是根据Fcount计数器间接控制,Fcount的生成也很关键。

3 Fcount 的更新。

module SYNCFIFO(Fifo_rst,Clock,Read_enable,Write_enable,Write_data,Read_data,Full,Empty,Fcounter);
    
    parameter DATA_WIDTH = 8;
    parameter ADDR_WIDTH = 9;
    
    input Fifo_rst;
    input Clock;
    input Read_enable;
    input Write_enable;
    input [DATA_WIDTH-1:0] Write_data;
    output [DATA_WIDTH-1:0] Read_data;
    
    output Full;
    output Empty;
    output [ADDR_WIDTH-1:0] Fcounter;
    
    reg [DATA_WIDTH-1:0] Read_data;
    reg Full;
    reg Empty;
    reg [ADDR_WIDTH-1:0] Fcounter;
    reg [ADDR_WIDTH-1:0] Read_addr;
    reg [ADDR_WIDTH-1:0] Write_addr;
    
    wire Read_allow = (Read_enable && !empty);  // 空不能读
    wire Write_allow = (Write_enable && !Full); //满不能写
    
    DUALRAM U_RAM(
    .Read_clock(Clock),
    .Write_clock(Clock),
    .Read_allow(Read_allow),
    .Write_allow(Write_allow),
    .Read_addr(Read_addr),
    .Write_addr(Write_addr),
    .Write_data(Write_data),
    .Read_data(Read_data)
    );
 //  空满信号的产生  
always@(posedge Clock or posedge Fifo_rst)
      if(Fifo_rst)
          Empty <= 1'b1;
      else
          Empty <= (!Write_enable && (Fcount[8:1] == 8'b0) && ((Fcount[0] == 1'b0) || Read_enable));
          
always@(posedge Clock or posedge Fifo_rst)
    if(Fifo_rst)
        Full <= 1'b1;
    else
        Full <= (!Read_enable && (Fcount[8:1] == 8'hFF) && ((Fcount[0] == 1'b1) || Write_enable));
// 计数器

always@(posedge Clock or posedge Fifo_rst)
     if(Fifo_rst)
        Fcount <= 1'b0;
     else if(read_enable && write_enable)
         Fcount <= Fcount;
     else if(Read_allow)
         Fcount <= Fcount - 1'b1;
     else if(Write_allow)
         Fcount <= Fcount + 1'b1;
     else
         Fcount <= Fcount;
         
// 写数据  读数据控制。 通过Read_allow和Write_allow和双口ram联系起来
always@(posedge Clock or posedge Fifo_rst)
      if(Fifo_rst)
          Read_addr <= 1'b0;
      else if(Read_allow)
          Read_addr <= Read_addr + 1'b1;
always@(posedge Clock or posedge Fifo_rst)
      if(Fifo_rst)
          Write_addr <= 1'b0;
      else if(Write_allow)
          Write_addr <= Write_addr + 1'b1;


endmodule