63 lines
1.6 KiB
Verilog
63 lines
1.6 KiB
Verilog
module sync_fifo_128_to_64 #(
|
|
parameter DATA_IN_WIDTH = 128,
|
|
parameter DATA_OUT_WIDTH = 64,
|
|
parameter FIFO_DEPTH = 16
|
|
)(
|
|
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
|
|
);
|
|
localparam ADDR_WIDTH = $clog2(FIFO_DEPTH);
|
|
|
|
reg [DATA_OUT_WIDTH-1:0] mem [0 :FIFO_DEPTH -1];
|
|
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 + 2'd2;
|
|
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 + 1'd1;
|
|
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+1'b1],mem[wr_addr]} <= wr_data;
|
|
end else begin
|
|
mem[wr_addr] <= mem[wr_addr];
|
|
end
|
|
end
|
|
|
|
assign rd_data = mem[rd_addr];
|
|
|
|
assign full = (wr_ptr - rd_ptr == FIFO_DEPTH) ? 1:0;
|
|
assign empty = (wr_ptr == rd_ptr) ? 1:0;
|
|
|
|
endmodule
|