-
Notifications
You must be signed in to change notification settings - Fork 0
/
sync_fifo.sv
73 lines (65 loc) · 2 KB
/
sync_fifo.sv
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
//
// Generic synchronous FIFO
// Depth may or may not be power of 2
//
// Implememtation logic:
// Correctly wrap the write and read pointers based on the depth.
//
module sync_fifo_sv #(WIDTH = 8,
DEPTH = 4
)(
input logic clk,
input logic rst_n,
input logic wr_en_i,
input logic [WIDTH-1:0] wr_data_i,
output logic full_o,
input logic rd_en_i,
output logic [WIDTH-1:0] rd_data_o,
output logic empty_o
);
// creating a local parameter for the depth MSB
localparam MSB = $clog2(DEPTH);
// Instantiating a 2d Memory block for the FIFO
logic [WIDTH-1:0] mem [DEPTH-1:0];
// Write and Read pointers
// Need an extra bit for full/empty
logic [MSB:0] wr_ptr, rd_ptr;
// Empty logic
assign empty_o = (wr_ptr == rd_ptr);
// FUll logic
assign full_o = (wr_ptr[MSB]^rd_ptr[MSB]) && (wr_ptr[MSB-1:0] == rd_ptr[MSB-1:0]);
always_ff@(posedge clk, negedge rst_n) begin
if (!rst_n) begin
wr_ptr <= '0;
end
// Wrap the pointer when reached the required depth
// toggle the MSB bit of pointer for correct full/empty flags
else if (wr_en_i && !full_o) begin
if (wr_ptr[MSB-1:0] == DEPTH-1) begin
wr_ptr[MSB-1:0] <= '0;
wr_ptr[MSB] <= ~wr_ptr[MSB];
end
else begin
wr_ptr <= wr_ptr + 1;
end
// Write the data to memory
mem[wr_ptr[MSB-1:0]] <= wr_data_i;
end
end
always_ff@(posedge clk, negedge rst_n) begin
if (!rst_n) begin
rd_ptr <= '0;
end
else if (rd_en_i && !empty_o) begin
if (rd_ptr[MSB-1:0] == DEPTH-1) begin
rd_ptr[MSB-1:0] <= '0;
rd_ptr[MSB] <= ~rd_ptr[MSB];
end
else begin
rd_ptr <= rd_ptr + 1;
end
end
end
// Read the data out combinationally
assign rd_data_o = mem[rd_ptr[MSB-1:0]];
endmodule