直接给个简单代码框架吧,深度参数用DEPTH,宽度用DATA_WIDTH。假设是2的幂次方。
module sync_fifo #(parameter DATA_WIDTH=8, DEPTH=16) (input clk, rst_n, wr_en, rd_en, input [DATA_WIDTH-1:0] din, output reg [DATA_WIDTH-1:0] dout, output full, empty);
localparam PTR_WIDTH = $clog2(DEPTH)+1;
reg [PTR_WIDTH-1:0] wr_ptr, rd_ptr;
reg [DATA_WIDTH-1:0] mem [0:DEPTH-1];
// 指针更新
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin wr_ptr<=0; rd_ptr<=0; end
else begin
if(wr_en && !full) begin wr_ptr<=wr_ptr+1; mem[wr_ptr[PTR_WIDTH-2:0]]<=din; end
if(rd_en && !empty) begin rd_ptr<=rd_ptr+1; dout<=mem[rd_ptr[PTR_WIDTH-2:0]]; end
end
end
// 满空判断
assign empty = (wr_ptr == rd_ptr);
assign full = (wr_ptr[PTR_WIDTH-1] != rd_ptr[PTR_WIDTH-1]) && (wr_ptr[PTR_WIDTH-2:0] == rd_ptr[PTR_WIDTH-2:0]);
endmodule
注意,这里指针低部分(去掉最高位)直接当地址用,因为深度是2的幂次方,所以不会溢出。满空判断就是上面说的。实际笔试可能要求用格雷码指针,但同步FIFO一般不需要,不过为了扩展性可以写上。