84 lines
2.6 KiB
Systemverilog
84 lines
2.6 KiB
Systemverilog
|
||
// 同步FIFO模块,可参数化配置
|
||
module fifo_sync #(
|
||
parameter DATA_WIDTH = 8, // 数据位宽
|
||
parameter DEPTH = 16, // FIFO深度
|
||
parameter USE_RAM = 0, // 是否使用RAM存储(0: 寄存器数组, 1: RAM)
|
||
parameter OUT_REG = 1 // 输出是否为reg型(1: 输出寄存器, 0: 直通)
|
||
)(
|
||
input wire clk,
|
||
input wire rst_n,
|
||
input wire wr_en,
|
||
input wire [DATA_WIDTH-1:0] din,
|
||
input wire rd_en,
|
||
output wire [DATA_WIDTH-1:0] dout,
|
||
output wire empty,
|
||
output wire full,
|
||
output wire [$clog2(DEPTH):0] data_count
|
||
);
|
||
|
||
localparam ADDR_WIDTH = $clog2(DEPTH);
|
||
|
||
reg [ADDR_WIDTH:0] wr_ptr, rd_ptr;
|
||
reg [DATA_WIDTH-1:0] mem [0:DEPTH-1];
|
||
reg [DATA_WIDTH-1:0] dout_reg;
|
||
wire [DATA_WIDTH-1:0] dout_wire;
|
||
|
||
// 写操作
|
||
always @(posedge clk or negedge rst_n) begin
|
||
if (!rst_n) begin
|
||
wr_ptr <= 0;
|
||
end else if (wr_en && !full) begin
|
||
wr_ptr <= wr_ptr + 1'b1;
|
||
end
|
||
end
|
||
|
||
// 读操作
|
||
always @(posedge clk or negedge rst_n) begin
|
||
if (!rst_n) begin
|
||
rd_ptr <= 0;
|
||
end else if (rd_en && !empty) begin
|
||
rd_ptr <= rd_ptr + 1'b1;
|
||
end
|
||
end
|
||
|
||
// 数据计数
|
||
assign data_count = wr_ptr - rd_ptr;
|
||
assign empty = (wr_ptr == rd_ptr);
|
||
assign full = (data_count == DEPTH);
|
||
|
||
generate
|
||
if (USE_RAM) begin : USE_RAM_BLOCK
|
||
// RAM实现(可替换为实际RAM IP)
|
||
always @(posedge clk) begin
|
||
if (wr_en && !full)
|
||
mem[wr_ptr[ADDR_WIDTH-1:0]] <= din;
|
||
end
|
||
assign dout_wire = mem[rd_ptr[ADDR_WIDTH-1:0]];
|
||
end else begin : USE_REG_BLOCK
|
||
// 寄存器数组实现
|
||
always @(posedge clk) begin
|
||
if (wr_en && !full)
|
||
mem[wr_ptr[ADDR_WIDTH-1:0]] <= din;
|
||
end
|
||
assign dout_wire = mem[rd_ptr[ADDR_WIDTH-1:0]];
|
||
end
|
||
endgenerate
|
||
|
||
// 输出寄存器可选
|
||
generate
|
||
if (OUT_REG) begin : OUT_REG_BLOCK
|
||
always @(posedge clk or negedge rst_n) begin
|
||
if (!rst_n)
|
||
dout_reg <= {DATA_WIDTH{1'b0}};
|
||
else if (rd_en && !empty)
|
||
dout_reg <= dout_wire;
|
||
end
|
||
assign dout = dout_reg;
|
||
end else begin : OUT_WIRE_BLOCK
|
||
assign dout = dout_wire;
|
||
end
|
||
endgenerate
|
||
|
||
endmodule
|