module sync_fifo_v1 #(
parameter DEPTH = 2,
parameter type T = logic
)(
input clk,
input rst_n,
input wen,
input T data_in,
input ren,
output T data_out,
output full,
output empty
);
localparam ADDR_SIZE = $clog2(DEPTH);
logic [ADDR_SIZE-1:0] waddr;
logic wwrap;
logic [ADDR_SIZE-1:0] raddr;
logic rwrap;
T mem [DEPTH-1:0];
always_ff @(posedge clk) begin
if (wen) begin
mem [waddr] <= data_in;
end
end
assign data_out = mem [raddr];
always_ff @(posedge clk, negedge rst_n) begin
if (!rst_n) begin
{wwrap, waddr} <= '0;
end else if (wen) begin
{wwrap, waddr} <= {wwrap, waddr} + 1'b1;
end
end
always_ff @(posedge clk, negedge rst_n) begin
if (!rst_n) begin
{rwrap, raddr} <= '0;
end else if (ren) begin
{rwrap, raddr} <= {rwrap, raddr} + 1'b1;
end
end
assign full = (wwrap!=rwrap) & (waddr == raddr);
assign empty = (wwrap==rwrap) & (waddr == raddr);
endmodule
module sync_fifo_v2 #(
parameter DEPTH = 2,
parameter type T = logic
)(
input clk,
input rst_n,
input wen,
input T data_in,
input ren,
output T data_out,
output full,
output empty
);
localparam ADDR_SIZE = $clog2(DEPTH);
logic [ADDR_SIZE-1:0] waddr;
logic wwrap;
logic [ADDR_SIZE-1:0] raddr;
logic rwrap;
T mem [DEPTH-1:0];
always_ff @(posedge clk) begin
if (wen) begin
mem [waddr] <= data_in;
end
end
always_ff @(posedge clk) begin
if (ren) begin
data_out <= mem [raddr];
end
end
always_ff @(posedge clk, negedge rst_n) begin
if (!rst_n) begin
{wwrap, waddr} <= '0;
end else if (wen) begin
{wwrap, waddr} <= {wwrap, waddr} + 1'b1;
end
end
always_ff @(posedge clk, negedge rst_n) begin
if (!rst_n) begin
{rwrap, raddr} <= '0;
end else if (ren) begin
{rwrap, raddr} <= {rwrap, raddr} + 1'b1;
end
end
assign full = (wwrap!=rwrap) & (waddr == raddr);
assign empty = (wwrap==rwrap) & (waddr == raddr);
endmodule
module tb_top;
bit clk;
bit rst_n;
initial fork
forever #5 clk = ~clk;
begin
@(posedge clk);
#1 rst_n = 1'b1;
end
join
typedef logic[7:0] T;
// fifo output
T data_out;
logic full;
logic empty;
// fifo input
logic wen;
T data_in;
logic ren;
initial begin
wait(rst_n);
while (1) begin
@(posedge clk);
#1;
wen = (!full | full & ren) & $urandom_range(1, 0);
ren = !empty & $urandom_range(1, 0);
data_in = $random;
end
end
initial begin
#1000;
$finish;
end
sync_fifo_v1 #(
.DEPTH (2),
.T (T)
) i_sync_fifo_v1 (
.*
);
endmodule