同步fifo设计
信号列表
-
clk:fifo操作时钟
-
wr_en:fifo写使能,在wr_en有效的情况下,上升沿采集wdata数据。
-
wdata:fifo写数据。
-
full:fifo满有效。高电平时,代表当前wdata并未写入fifo。
-
rd_en:fifo读使能。在rd_en有效,empty无效时,数据同步送出fifo。
-
empty:fifo空有效。高电平时,代表当前rdata无效。
要点
使用两个地址寄存器,分别为raddr和waddr,假设fifo深度为8,则地址位置从000->111,只需要让raddr和waddr是4个位宽,并且让对fifo读写操作后,raddr和waddr地址加1即可。
当raddr[3:0]=waddr[3:0],则代表fifo是空的。
当raddr[3]!=waddr[3] raddr[2:0]=waddr[2:0],则代表fifo是满的。
verilog
module fifo_syn #(
parameter wa = 3,
parameter wd = 4)
(
input rst_n,
input clk,
input wr_en,
input [wd-1:0] wdata,
output full,
input rd_en,
output [wd-1:0] rdata,
output empty
);
//syn [wa-1:0] raddr ^ [wa-1:0] raddr
reg [wa:0] raddr;
reg [wa:0] waddr;
wire condition_1 = &(~(raddr[wa-1:0]^waddr[wa-1:0]));
wire condition_2 = &(~(raddr[wa]^waddr[wa]));
assign full = ~condition_2&condition_1;
assign empty = condition_1&condition_2;
parameter deep = (1<<wa)-1;
reg [wd-1:0] fifo_mem[deep:0] ;
always @(posedge clk) begin
if(!rst_n)
waddr <= {wa{1'b0}};
else if(wr_en&&!full) begin
fifo_mem[waddr[wa-1:0]] <= wdata;
waddr <= waddr + 1'b1;
end
end
assign rdata = (!empty&&rd_en)?fifo_mem[raddr[wa-1:0]]:{wd{1'b0}};
always @(posedge clk) begin
if(!rst_n)
raddr <= {wa{1'b0}};
else if(rd_en&&!empty) begin
raddr <= raddr + 1'b1;
end
end
endmodule
`timescale 1ns / 1ps
module tb();
reg clk;
reg rst_n;
reg wr_en,rd_en;
wire empty,full;
reg [3:0] wdata;
wire [3:0] rdat