2025-08-06 13:42:13 +08:00
|
|
|
module sync_fifo_64_to_128 #(
|
|
|
|
parameter DATA_IN_WIDTH = 64,
|
|
|
|
parameter DATA_OUT_WIDTH = 128,
|
2025-08-06 22:43:11 +08:00
|
|
|
parameter FIFO_DEPTH = 16
|
|
|
|
|
2025-08-06 13:42:13 +08:00
|
|
|
)(
|
|
|
|
input clk,
|
|
|
|
input rst_n,
|
|
|
|
input wr_en,
|
|
|
|
input [DATA_IN_WIDTH-1:0] wr_data,
|
|
|
|
output full,
|
|
|
|
input rd_en,
|
|
|
|
output [DATA_OUT_WIDTH-1:0] rd_data,
|
|
|
|
output empty
|
|
|
|
);
|
2025-08-06 22:43:11 +08:00
|
|
|
localparam ADDR_WIDTH = $clog2(FIFO_DEPTH);
|
2025-08-06 13:42:13 +08:00
|
|
|
reg [DATA_IN_WIDTH-1:0] mem [FIFO_DEPTH -1 : 0];
|
|
|
|
reg [ADDR_WIDTH : 0] wr_ptr, rd_ptr;
|
|
|
|
wire [ADDR_WIDTH -1:0] wr_addr ,rd_addr;
|
|
|
|
|
|
|
|
assign wr_addr = wr_ptr[ADDR_WIDTH -1:0];
|
|
|
|
assign rd_addr = rd_ptr[ADDR_WIDTH -1:0];
|
|
|
|
|
|
|
|
always@(posedge clk or negedge rst_n) begin
|
|
|
|
if(!rst_n) begin
|
|
|
|
wr_ptr <= 'd0;
|
|
|
|
end else if(wr_en && !full) begin
|
|
|
|
wr_ptr <= wr_ptr + 1'b1;
|
|
|
|
end else begin
|
|
|
|
wr_ptr <= wr_ptr;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
always@(posedge clk or negedge rst_n) begin
|
|
|
|
if(!rst_n) begin
|
|
|
|
rd_ptr <= 'd0;
|
|
|
|
end else if(rd_en && !empty) begin
|
|
|
|
rd_ptr <= rd_ptr + 2'd2;
|
|
|
|
end else begin
|
|
|
|
rd_ptr <= rd_ptr;
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
integer i;
|
|
|
|
always@(posedge clk or negedge rst_n) begin
|
|
|
|
if(!rst_n) begin
|
|
|
|
for(i=0;i<FIFO_DEPTH;i=i+1) begin
|
|
|
|
mem[i] <= 'd0;
|
|
|
|
end
|
|
|
|
end else if(wr_en && !full) begin
|
|
|
|
mem[wr_addr] <= wr_data;
|
|
|
|
end else begin
|
|
|
|
mem[wr_addr] <= mem[wr_addr];
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
assign rd_data = {mem[rd_addr+1],mem[rd_addr]};
|
|
|
|
|
|
|
|
assign full = (wr_ptr - rd_ptr == FIFO_DEPTH) ? 1:0;
|
|
|
|
assign empty = (wr_ptr - rd_ptr <=1) ? 1:0;
|
|
|
|
|
|
|
|
endmodule
|